Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F151196070
D5261.id13673.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
42 KB
Referenced Files
None
Subscribers
None
D5261.id13673.diff
View Options
Index: head/sys/arm64/cavium/thunder_pcie.c
===================================================================
--- head/sys/arm64/cavium/thunder_pcie.c
+++ head/sys/arm64/cavium/thunder_pcie.c
@@ -1,425 +0,0 @@
-/*-
- * Copyright (c) 2015 The FreeBSD Foundation
- * All rights reserved.
- *
- * This software was developed by Semihalf under
- * the sponsorship of the FreeBSD Foundation.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/* PCIe root complex driver for Cavium Thunder SOC */
-#include "opt_platform.h"
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/malloc.h>
-#include <sys/types.h>
-#include <sys/sysctl.h>
-#include <sys/kernel.h>
-#include <sys/rman.h>
-#include <sys/module.h>
-#include <sys/bus.h>
-#include <sys/endian.h>
-#include <sys/cpuset.h>
-#include <dev/pci/pcivar.h>
-#include <dev/pci/pcireg.h>
-#include <dev/pci/pcib_private.h>
-#include <dev/pci/pci_private.h>
-#include <machine/cpu.h>
-#include <machine/bus.h>
-#include <machine/intr.h>
-
-#include "thunder_pcie_common.h"
-
-#include "pcib_if.h"
-
-/* Assembling ECAM Configuration Address */
-#define PCIE_BUS_SHIFT 20
-#define PCIE_SLOT_SHIFT 15
-#define PCIE_FUNC_SHIFT 12
-#define PCIE_BUS_MASK 0xFF
-#define PCIE_SLOT_MASK 0x1F
-#define PCIE_FUNC_MASK 0x07
-#define PCIE_REG_MASK 0xFFF
-
-#define PCIE_ADDR_OFFSET(bus, slot, func, reg) \
- ((((bus) & PCIE_BUS_MASK) << PCIE_BUS_SHIFT) | \
- (((slot) & PCIE_SLOT_MASK) << PCIE_SLOT_SHIFT) | \
- (((func) & PCIE_FUNC_MASK) << PCIE_FUNC_SHIFT) | \
- ((reg) & PCIE_REG_MASK))
-
-#define THUNDER_ECAM0_CFG_BASE 0x848000000000UL
-#define THUNDER_ECAM1_CFG_BASE 0x849000000000UL
-#define THUNDER_ECAM2_CFG_BASE 0x84a000000000UL
-#define THUNDER_ECAM3_CFG_BASE 0x84b000000000UL
-#define THUNDER_ECAM4_CFG_BASE 0x948000000000UL
-#define THUNDER_ECAM5_CFG_BASE 0x949000000000UL
-#define THUNDER_ECAM6_CFG_BASE 0x94a000000000UL
-#define THUNDER_ECAM7_CFG_BASE 0x94b000000000UL
-
-/*
- * ThunderX supports up to 4 ethernet interfaces, so it's good
- * value to use as default for numbers of VFs, since each eth
- * interface represents separate virtual function.
- */
-static int thunder_pcie_max_vfs = 4;
-SYSCTL_INT(_hw, OID_AUTO, thunder_pcie_max_vfs, CTLFLAG_RWTUN,
- &thunder_pcie_max_vfs, 0, "Max VFs supported by ThunderX internal PCIe");
-
-/* Forward prototypes */
-static int thunder_pcie_identify_pcib(device_t);
-static int thunder_pcie_maxslots(device_t);
-static uint32_t thunder_pcie_read_config(device_t, u_int, u_int, u_int, u_int,
- int);
-static int thunder_pcie_read_ivar(device_t, device_t, int, uintptr_t *);
-static void thunder_pcie_write_config(device_t, u_int, u_int,
- u_int, u_int, uint32_t, int);
-static int thunder_pcie_write_ivar(device_t, device_t, int, uintptr_t);
-
-int
-thunder_pcie_attach(device_t dev)
-{
- int rid;
- struct thunder_pcie_softc *sc;
- int error;
- int tuple;
- uint64_t base, size;
-
- sc = device_get_softc(dev);
- sc->dev = dev;
-
- /* Identify pcib domain */
- if (thunder_pcie_identify_pcib(dev))
- return (ENXIO);
-
- rid = 0;
- sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
- if (sc->res == NULL) {
- device_printf(dev, "could not map memory.\n");
- return (ENXIO);
- }
-
- sc->mem_rman.rm_type = RMAN_ARRAY;
- sc->mem_rman.rm_descr = "PCIe Memory";
-
- /* Initialize rman and allocate memory regions */
- error = rman_init(&sc->mem_rman);
- if (error) {
- device_printf(dev, "rman_init() failed. error = %d\n", error);
- return (error);
- }
-
- for (tuple = 0; tuple < RANGES_TUPLES_MAX; tuple++) {
- base = sc->ranges[tuple].phys_base;
- size = sc->ranges[tuple].size;
- if ((base == 0) || (size == 0))
- continue; /* empty range element */
-
- error = rman_manage_region(&sc->mem_rman, base, base + size - 1);
- if (error) {
- device_printf(dev, "rman_manage_region() failed. error = %d\n", error);
- rman_fini(&sc->mem_rman);
- return (error);
- }
- }
- device_add_child(dev, "pci", -1);
-
- return (bus_generic_attach(dev));
-}
-
-static uint32_t
-thunder_pcie_read_config(device_t dev, u_int bus, u_int slot,
- u_int func, u_int reg, int bytes)
-{
- uint64_t offset;
- uint32_t data;
- struct thunder_pcie_softc *sc;
- bus_space_tag_t t;
- bus_space_handle_t h;
-
- if ((bus > PCI_BUSMAX) || (slot > PCI_SLOTMAX) ||
- (func > PCI_FUNCMAX) || (reg > PCIE_REGMAX))
- return (~0U);
-
- sc = device_get_softc(dev);
-
- offset = PCIE_ADDR_OFFSET(bus, slot, func, reg);
- t = rman_get_bustag(sc->res);
- h = rman_get_bushandle(sc->res);
-
- switch (bytes) {
- case 1:
- data = bus_space_read_1(t, h, offset);
- break;
- case 2:
- data = le16toh(bus_space_read_2(t, h, offset));
- break;
- case 4:
- data = le32toh(bus_space_read_4(t, h, offset));
- break;
- default:
- return (~0U);
- }
-
- return (data);
-}
-
-static void
-thunder_pcie_write_config(device_t dev, u_int bus, u_int slot,
- u_int func, u_int reg, uint32_t val, int bytes)
-{
- uint64_t offset;
- struct thunder_pcie_softc *sc;
- bus_space_tag_t t;
- bus_space_handle_t h;
-
- if ((bus > PCI_BUSMAX) || (slot > PCI_SLOTMAX) ||
- (func > PCI_FUNCMAX) || (reg > PCIE_REGMAX))
- return ;
-
- sc = device_get_softc(dev);
-
- offset = PCIE_ADDR_OFFSET(bus, slot, func, reg);
- t = rman_get_bustag(sc->res);
- h = rman_get_bushandle(sc->res);
-
- switch (bytes) {
- case 1:
- bus_space_write_1(t, h, offset, val);
- break;
- case 2:
- bus_space_write_2(t, h, offset, htole16(val));
- break;
- case 4:
- bus_space_write_4(t, h, offset, htole32(val));
- break;
- default:
- return;
- }
-
-}
-
-static int
-thunder_pcie_maxslots(device_t dev)
-{
-
- /* max slots per bus acc. to standard */
- return (PCI_SLOTMAX);
-}
-
-static int
-thunder_pcie_read_ivar(device_t dev, device_t child, int index,
- uintptr_t *result)
-{
- struct thunder_pcie_softc *sc;
-
- sc = device_get_softc(dev);
-
- if (index == PCIB_IVAR_BUS) {
- /* this pcib is always on bus 0 */
- *result = 0;
- return (0);
- }
- if (index == PCIB_IVAR_DOMAIN) {
- *result = sc->ecam;
- return (0);
- }
-
- return (ENOENT);
-}
-
-static int
-thunder_pcie_write_ivar(device_t dev, device_t child, int index,
- uintptr_t value)
-{
-
- return (ENOENT);
-}
-
-int
-thunder_pcie_release_resource(device_t dev, device_t child, int type, int rid,
- struct resource *res)
-{
-
- if (type != SYS_RES_MEMORY)
- return (bus_generic_release_resource(dev, child,
- type, rid, res));
-
- return (rman_release_resource(res));
-}
-
-struct resource *
-thunder_pcie_alloc_resource(device_t dev, device_t child, int type, int *rid,
- rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
-{
- struct thunder_pcie_softc *sc = device_get_softc(dev);
- struct rman *rm = NULL;
- struct resource *res;
- pci_addr_t map, testval;
-
- switch (type) {
- case SYS_RES_IOPORT:
- goto fail;
- break;
- case SYS_RES_MEMORY:
- rm = &sc->mem_rman;
- break;
- default:
- return (bus_generic_alloc_resource(dev, child,
- type, rid, start, end, count, flags));
- };
-
- if (RMAN_IS_DEFAULT_RANGE(start, end)) {
-
- /* Read BAR manually to get resource address and size */
- pci_read_bar(child, *rid, &map, &testval, NULL);
-
- /* Mask the information bits */
- if (PCI_BAR_MEM(map))
- map &= PCIM_BAR_MEM_BASE;
- else
- map &= PCIM_BAR_IO_BASE;
-
- if (PCI_BAR_MEM(testval))
- testval &= PCIM_BAR_MEM_BASE;
- else
- testval &= PCIM_BAR_IO_BASE;
-
- start = map;
- count = (~testval) + 1;
- /*
- * Internal ThunderX devices supports up to 3 64-bit BARs.
- * If we're allocating anything above, that means upper layer
- * wants us to allocate VF-BAR. In that case reserve bigger
- * slice to make a room for other VFs adjacent to this one.
- */
- if (*rid > PCIR_BAR(5))
- count = count * thunder_pcie_max_vfs;
- end = start + count - 1;
- }
-
- /* Convert input BUS address to required PHYS */
- if (range_addr_is_pci(sc->ranges, start, count) == 0)
- goto fail;
- start = range_addr_pci_to_phys(sc->ranges, start);
- end = start + count - 1;
-
- if (bootverbose) {
- device_printf(dev,
- "rman_reserve_resource: start=%#lx, end=%#lx, count=%#lx\n",
- start, end, count);
- }
-
- res = rman_reserve_resource(rm, start, end, count, flags, child);
- if (res == NULL)
- goto fail;
-
- rman_set_rid(res, *rid);
-
- if ((flags & RF_ACTIVE) != 0)
- if (bus_activate_resource(child, type, *rid, res)) {
- rman_release_resource(res);
- goto fail;
- }
-
- return (res);
-
-fail:
- if (bootverbose) {
- device_printf(dev, "%s FAIL: type=%d, rid=%d, "
- "start=%016lx, end=%016lx, count=%016lx, flags=%x\n",
- __func__, type, *rid, start, end, count, flags);
- }
-
- return (NULL);
-}
-
-static int
-thunder_pcie_identify_pcib(device_t dev)
-{
- struct thunder_pcie_softc *sc;
- rman_res_t start;
-
- sc = device_get_softc(dev);
- start = bus_get_resource_start(dev, SYS_RES_MEMORY, 0);
-
- switch(start) {
- case THUNDER_ECAM0_CFG_BASE:
- sc->ecam = 0;
- break;
- case THUNDER_ECAM1_CFG_BASE:
- sc->ecam = 1;
- break;
- case THUNDER_ECAM2_CFG_BASE:
- sc->ecam = 2;
- break;
- case THUNDER_ECAM3_CFG_BASE:
- sc->ecam = 3;
- break;
- case THUNDER_ECAM4_CFG_BASE:
- sc->ecam = 4;
- break;
- case THUNDER_ECAM5_CFG_BASE:
- sc->ecam = 5;
- break;
- case THUNDER_ECAM6_CFG_BASE:
- sc->ecam = 6;
- break;
- case THUNDER_ECAM7_CFG_BASE:
- sc->ecam = 7;
- break;
- default:
- device_printf(dev,
- "error: incorrect resource address=%#lx.\n", start);
- return (ENXIO);
- }
- return (0);
-}
-
-static device_method_t thunder_pcie_methods[] = {
- DEVMETHOD(pcib_maxslots, thunder_pcie_maxslots),
- DEVMETHOD(pcib_read_config, thunder_pcie_read_config),
- DEVMETHOD(pcib_write_config, thunder_pcie_write_config),
- DEVMETHOD(bus_read_ivar, thunder_pcie_read_ivar),
- DEVMETHOD(bus_write_ivar, thunder_pcie_write_ivar),
- DEVMETHOD(bus_alloc_resource, thunder_pcie_alloc_resource),
- DEVMETHOD(bus_release_resource, thunder_pcie_release_resource),
- DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
- DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
- DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
- DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
-
- DEVMETHOD(pcib_map_msi, arm_map_msi),
- DEVMETHOD(pcib_alloc_msix, arm_alloc_msix),
- DEVMETHOD(pcib_release_msix, arm_release_msix),
- DEVMETHOD(pcib_alloc_msi, arm_alloc_msi),
- DEVMETHOD(pcib_release_msi, arm_release_msi),
-
- DEVMETHOD_END
-};
-
-DEFINE_CLASS_0(pcib, thunder_pcie_driver, thunder_pcie_methods,
- sizeof(struct thunder_pcie_softc));
Index: head/sys/arm64/cavium/thunder_pcie_common.h
===================================================================
--- head/sys/arm64/cavium/thunder_pcie_common.h
+++ head/sys/arm64/cavium/thunder_pcie_common.h
@@ -29,43 +29,15 @@
#ifndef _CAVIUM_THUNDER_PCIE_COMMON_H_
#define _CAVIUM_THUNDER_PCIE_COMMON_H_
-#define RANGES_TUPLES_MAX 6
-#define RANGES_TUPLES_INVALID (RANGES_TUPLES_MAX + 1)
-
DECLARE_CLASS(thunder_pcie_driver);
DECLARE_CLASS(thunder_pem_driver);
MALLOC_DECLARE(M_THUNDER_PCIE);
-struct pcie_range {
- uint64_t pci_base;
- uint64_t phys_base;
- uint64_t size;
- uint64_t flags;
-};
-
-struct thunder_pcie_softc {
- struct pcie_range ranges[RANGES_TUPLES_MAX];
- struct rman mem_rman;
- struct resource *res;
- int ecam;
- device_t dev;
-};
-
uint32_t range_addr_is_pci(struct pcie_range *, uint64_t, uint64_t);
uint32_t range_addr_is_phys(struct pcie_range *, uint64_t, uint64_t);
uint64_t range_addr_pci_to_phys(struct pcie_range *, uint64_t);
-int thunder_common_alloc_msi(device_t, device_t, int, int, int *);
-int thunder_common_alloc_msix(device_t, device_t, int *);
-int thunder_common_map_msi(device_t, device_t, int, uint64_t *, uint32_t *);
-int thunder_common_release_msi(device_t, device_t, int, int *);
-int thunder_common_release_msix(device_t, device_t, int);
-
-struct resource *thunder_pcie_alloc_resource(device_t,
- device_t, int, int *, rman_res_t, rman_res_t, rman_res_t, u_int);
-int thunder_pcie_release_resource(device_t, device_t, int, int,
- struct resource *);
-int thunder_pcie_attach(device_t);
+int thunder_pcie_identify_ecam(device_t, int *);
#endif /* _CAVIUM_THUNDER_PCIE_COMMON_H_ */
Index: head/sys/arm64/cavium/thunder_pcie_common.c
===================================================================
--- head/sys/arm64/cavium/thunder_pcie_common.c
+++ head/sys/arm64/cavium/thunder_pcie_common.c
@@ -32,6 +32,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_platform.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -43,17 +45,31 @@
#include <machine/cpu.h>
#include <machine/intr.h>
+#ifdef FDT
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/ofw/ofw_pci.h>
+#endif
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcib_private.h>
+#include <dev/pci/pci_host_generic.h>
+
#include "thunder_pcie_common.h"
MALLOC_DEFINE(M_THUNDER_PCIE, "Thunder PCIe driver", "Thunder PCIe driver memory");
+#define THUNDER_CFG_BASE_TO_ECAM(x) ((((x) >> 36UL) & 0x3) | (((x) >> 42UL) & 0x4))
+
uint32_t
range_addr_is_pci(struct pcie_range *ranges, uint64_t addr, uint64_t size)
{
struct pcie_range *r;
int tuple;
- for (tuple = 0; tuple < RANGES_TUPLES_MAX; tuple++) {
+ for (tuple = 0; tuple < MAX_RANGES_TUPLES; tuple++) {
r = &ranges[tuple];
if (addr >= r->pci_base &&
addr < (r->pci_base + r->size) &&
@@ -73,7 +89,7 @@
struct pcie_range *r;
int tuple;
- for (tuple = 0; tuple < RANGES_TUPLES_MAX; tuple++) {
+ for (tuple = 0; tuple < MAX_RANGES_TUPLES; tuple++) {
r = &ranges[tuple];
if (addr >= r->phys_base &&
addr < (r->phys_base + r->size) &&
@@ -95,7 +111,7 @@
int tuple;
/* Find physical address corresponding to given bus address */
- for (tuple = 0; tuple < RANGES_TUPLES_MAX; tuple++) {
+ for (tuple = 0; tuple < MAX_RANGES_TUPLES; tuple++) {
r = &ranges[tuple];
if (pci_addr >= r->pci_base &&
pci_addr < (r->pci_base + r->size)) {
@@ -109,3 +125,20 @@
return (0);
}
+int
+thunder_pcie_identify_ecam(device_t dev, int *ecam)
+{
+ rman_res_t start;
+
+ /* Check if we're running on Cavium ThunderX */
+ if (!CPU_MATCH(CPU_IMPL_MASK | CPU_PART_MASK,
+ CPU_IMPL_CAVIUM, CPU_PART_THUNDER, 0, 0))
+ return (EINVAL);
+
+ start = bus_get_resource_start(dev, SYS_RES_MEMORY, 0);
+ *ecam = THUNDER_CFG_BASE_TO_ECAM(start);
+
+ device_printf(dev, "ThunderX quirk, setting ECAM to %d\n", *ecam);
+
+ return (0);
+}
Index: head/sys/arm64/cavium/thunder_pcie_fdt.c
===================================================================
--- head/sys/arm64/cavium/thunder_pcie_fdt.c
+++ head/sys/arm64/cavium/thunder_pcie_fdt.c
@@ -45,53 +45,24 @@
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/pci/pci_host_generic.h>
#include "thunder_pcie_common.h"
-#define OFW_CELL_TO_UINT64(cell) \
- (((uint64_t)(*(cell)) << 32) | (uint64_t)(*((cell) + 1)))
-
-#define SPACE_CODE_SHIFT 24
-#define SPACE_CODE_MASK 0x3
-#define SPACE_CODE_IO_SPACE 0x1
-#define PROPS_CELL_SIZE 1
-#define PCI_ADDR_CELL_SIZE 2
-
-static int thunder_pcie_fdt_probe(device_t);
static int thunder_pcie_fdt_attach(device_t);
-
-static struct resource * thunder_pcie_ofw_bus_alloc_res(device_t, device_t,
- int, int *, rman_res_t, rman_res_t, rman_res_t, u_int);
-static int thunder_pcie_ofw_bus_rel_res(device_t, device_t, int, int,
- struct resource *);
-
-static const struct ofw_bus_devinfo *thunder_pcie_ofw_get_devinfo(device_t,
- device_t);
+static int thunder_pcie_fdt_probe(device_t);
static device_method_t thunder_pcie_fdt_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, thunder_pcie_fdt_probe),
DEVMETHOD(device_attach, thunder_pcie_fdt_attach),
- /* Bus interface */
- DEVMETHOD(bus_alloc_resource, thunder_pcie_ofw_bus_alloc_res),
- DEVMETHOD(bus_release_resource, thunder_pcie_ofw_bus_rel_res),
- DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
-
- /* ofw_bus interface */
- DEVMETHOD(ofw_bus_get_devinfo, thunder_pcie_ofw_get_devinfo),
- DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat),
- DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model),
- DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name),
- DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
- DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
-
/* End */
DEVMETHOD_END
};
DEFINE_CLASS_1(pcib, thunder_pcie_fdt_driver, thunder_pcie_fdt_methods,
- sizeof(struct thunder_pcie_softc), thunder_pcie_driver);
+ sizeof(struct generic_pcie_softc), generic_pcie_driver);
static devclass_t thunder_pcie_fdt_devclass;
@@ -100,17 +71,21 @@
DRIVER_MODULE(thunder_pcib, ofwbus, thunder_pcie_fdt_driver,
thunder_pcie_fdt_devclass, 0, 0);
-static int thunder_pcie_fdt_ranges(device_t);
-static int thunder_pcie_ofw_bus_attach(device_t);
static int
thunder_pcie_fdt_probe(device_t dev)
{
+ /* Check if we're running on Cavium ThunderX */
+ if (!CPU_MATCH(CPU_IMPL_MASK | CPU_PART_MASK,
+ CPU_IMPL_CAVIUM, CPU_PART_THUNDER, 0, 0))
+ return (ENXIO);
+
if (!ofw_bus_status_okay(dev))
return (ENXIO);
- if (ofw_bus_is_compatible(dev, "cavium,thunder-pcie") ||
+ if (ofw_bus_is_compatible(dev, "pci-host-ecam-generic") ||
+ ofw_bus_is_compatible(dev, "cavium,thunder-pcie") ||
ofw_bus_is_compatible(dev, "cavium,pci-host-thunder-ecam")) {
device_set_desc(dev, "Cavium Integrated PCI/PCI-E Controller");
return (BUS_PROBE_DEFAULT);
@@ -122,261 +97,11 @@
static int
thunder_pcie_fdt_attach(device_t dev)
{
- int err;
-
- /* Retrieve 'ranges' property from FDT */
- if (thunder_pcie_fdt_ranges(dev) != 0)
- return (ENXIO);
-
- err = thunder_pcie_ofw_bus_attach(dev);
- if (err != 0)
- return (err);
-
- return (thunder_pcie_attach(dev));
-}
-
-static __inline void
-get_addr_size_cells(phandle_t node, pcell_t *addr_cells, pcell_t *size_cells)
-{
-
- *addr_cells = 2;
- /* Find address cells if present */
- OF_getencprop(node, "#address-cells", addr_cells, sizeof(*addr_cells));
-
- *size_cells = 2;
- /* Find size cells if present */
- OF_getencprop(node, "#size-cells", size_cells, sizeof(*size_cells));
-}
-
-static int
-thunder_pcie_fdt_ranges(device_t dev)
-{
- struct thunder_pcie_softc *sc;
- phandle_t node;
- pcell_t pci_addr_cells, parent_addr_cells, size_cells;
- pcell_t attributes;
- pcell_t *ranges_buf, *cell_ptr;
- int cells_count, tuples_count;
- int tuple;
- int rv;
+ struct generic_pcie_softc *sc;
sc = device_get_softc(dev);
- node = ofw_bus_get_node(dev);
-
- get_addr_size_cells(node, &pci_addr_cells, &size_cells);
-
- /* Find parent address cells if present */
- if (OF_getencprop(OF_parent(node), "#address-cells",
- &parent_addr_cells, sizeof(parent_addr_cells)) < sizeof(parent_addr_cells))
- parent_addr_cells = 2;
-
- /* Check if FDT format matches driver requirements */
- if ((parent_addr_cells != 2) || (pci_addr_cells != 3) ||
- (size_cells != 2)) {
- device_printf(dev,
- "Unexpected number of address or size cells in FDT "
- " %d:%d:%d\n",
- parent_addr_cells, pci_addr_cells, size_cells);
- return (ENXIO);
- }
+ thunder_pcie_identify_ecam(dev, &sc->ecam);
- cells_count = OF_getencprop_alloc(node, "ranges",
- sizeof(pcell_t), (void **)&ranges_buf);
- if (cells_count == -1) {
- device_printf(dev, "Error parsing FDT 'ranges' property\n");
- return (ENXIO);
- }
-
- tuples_count = cells_count /
- (pci_addr_cells + parent_addr_cells + size_cells);
- if (tuples_count > RANGES_TUPLES_MAX) {
- device_printf(dev,
- "Unexpected number of 'ranges' tuples in FDT\n");
- rv = ENXIO;
- goto out;
- }
-
- cell_ptr = ranges_buf;
-
- for (tuple = 0; tuple < tuples_count; tuple++) {
- /*
- * TUPLE FORMAT:
- * attributes - 32-bit attributes field
- * PCI address - bus address combined of two cells in
- * a following format:
- * <ADDR MSB> <ADDR LSB>
- * PA address - physical address combined of two cells in
- * a following format:
- * <ADDR MSB> <ADDR LSB>
- * size - range size combined of two cells in
- * a following format:
- * <ADDR MSB> <ADDR LSB>
- */
- attributes = *cell_ptr;
- attributes = (attributes >> SPACE_CODE_SHIFT) & SPACE_CODE_MASK;
- if (attributes == SPACE_CODE_IO_SPACE) {
- /* Internal PCIe does not support IO space, ignore. */
- sc->ranges[tuple].phys_base = 0;
- sc->ranges[tuple].size = 0;
- cell_ptr +=
- (pci_addr_cells + parent_addr_cells + size_cells);
- continue;
- }
- cell_ptr += PROPS_CELL_SIZE;
- sc->ranges[tuple].pci_base = OFW_CELL_TO_UINT64(cell_ptr);
- cell_ptr += PCI_ADDR_CELL_SIZE;
- sc->ranges[tuple].phys_base = OFW_CELL_TO_UINT64(cell_ptr);
- cell_ptr += parent_addr_cells;
- sc->ranges[tuple].size = OFW_CELL_TO_UINT64(cell_ptr);
- cell_ptr += size_cells;
-
- if (bootverbose) {
- device_printf(dev,
- "\tPCI addr: 0x%jx, CPU addr: 0x%jx, Size: 0x%jx\n",
- sc->ranges[tuple].pci_base,
- sc->ranges[tuple].phys_base,
- sc->ranges[tuple].size);
- }
-
- }
- for (; tuple < RANGES_TUPLES_MAX; tuple++) {
- /* zero-fill remaining tuples to mark empty elements in array */
- sc->ranges[tuple].phys_base = 0;
- sc->ranges[tuple].size = 0;
- }
-
- rv = 0;
-out:
- free(ranges_buf, M_OFWPROP);
- return (rv);
-}
-
-/* OFW bus interface */
-struct thunder_pcie_ofw_devinfo {
- struct ofw_bus_devinfo di_dinfo;
- struct resource_list di_rl;
-};
-
-static const struct ofw_bus_devinfo *
-thunder_pcie_ofw_get_devinfo(device_t bus __unused, device_t child)
-{
- struct thunder_pcie_ofw_devinfo *di;
-
- di = device_get_ivars(child);
- return (&di->di_dinfo);
-}
-
-static struct resource *
-thunder_pcie_ofw_bus_alloc_res(device_t bus, device_t child, int type, int *rid,
- rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
-{
- struct thunder_pcie_softc *sc;
- struct thunder_pcie_ofw_devinfo *di;
- struct resource_list_entry *rle;
- int i;
-
- /* For PCIe devices that do not have FDT nodes, use PCIB method */
- if ((int)ofw_bus_get_node(child) <= 0) {
- return (thunder_pcie_alloc_resource(bus, child, type, rid,
- start, end, count, flags));
- }
-
- sc = device_get_softc(bus);
-
- if (RMAN_IS_DEFAULT_RANGE(start, end)) {
- if ((di = device_get_ivars(child)) == NULL)
- return (NULL);
- if (type == SYS_RES_IOPORT)
- type = SYS_RES_MEMORY;
-
- /* Find defaults for this rid */
- rle = resource_list_find(&di->di_rl, type, *rid);
- if (rle == NULL)
- return (NULL);
-
- start = rle->start;
- end = rle->end;
- count = rle->count;
- }
-
- if (type == SYS_RES_MEMORY) {
- /* Remap through ranges property */
- for (i = 0; i < RANGES_TUPLES_MAX; i++) {
- if (start >= sc->ranges[i].phys_base && end <
- sc->ranges[i].pci_base + sc->ranges[i].size) {
- start -= sc->ranges[i].phys_base;
- start += sc->ranges[i].pci_base;
- end -= sc->ranges[i].phys_base;
- end += sc->ranges[i].pci_base;
- break;
- }
- }
-
- if (i == RANGES_TUPLES_MAX) {
- device_printf(bus, "Could not map resource "
- "%#lx-%#lx\n", start, end);
- return (NULL);
- }
- }
-
- return (bus_generic_alloc_resource(bus, child, type, rid, start, end,
- count, flags));
-}
-
-static int
-thunder_pcie_ofw_bus_rel_res(device_t bus, device_t child, int type, int rid,
- struct resource *res)
-{
-
- /* For PCIe devices that do not have FDT nodes, use PCIB method */
- if ((int)ofw_bus_get_node(child) <= 0) {
- return (thunder_pcie_release_resource(bus,
- child, type, rid, res));
- }
-
- return (bus_generic_release_resource(bus, child, type, rid, res));
+ return (pci_host_generic_attach(dev));
}
-/* Helper functions */
-
-static int
-thunder_pcie_ofw_bus_attach(device_t dev)
-{
- struct thunder_pcie_ofw_devinfo *di;
- device_t child;
- phandle_t parent, node;
- pcell_t addr_cells, size_cells;
-
- parent = ofw_bus_get_node(dev);
- if (parent > 0) {
- get_addr_size_cells(parent, &addr_cells, &size_cells);
- /* Iterate through all bus subordinates */
- for (node = OF_child(parent); node > 0; node = OF_peer(node)) {
- /* Allocate and populate devinfo. */
- di = malloc(sizeof(*di), M_THUNDER_PCIE, M_WAITOK | M_ZERO);
- if (ofw_bus_gen_setup_devinfo(&di->di_dinfo, node) != 0) {
- free(di, M_THUNDER_PCIE);
- continue;
- }
-
- /* Initialize and populate resource list. */
- resource_list_init(&di->di_rl);
- ofw_bus_reg_to_rl(dev, node, addr_cells, size_cells,
- &di->di_rl);
- ofw_bus_intr_to_rl(dev, node, &di->di_rl, NULL);
-
- /* Add newbus device for this FDT node */
- child = device_add_child(dev, NULL, -1);
- if (child == NULL) {
- resource_list_free(&di->di_rl);
- ofw_bus_gen_destroy_devinfo(&di->di_dinfo);
- free(di, M_THUNDER_PCIE);
- continue;
- }
-
- device_set_ivars(child, di);
- }
- }
-
- return (0);
-}
Index: head/sys/arm64/cavium/thunder_pcie_pem.h
===================================================================
--- head/sys/arm64/cavium/thunder_pcie_pem.h
+++ head/sys/arm64/cavium/thunder_pcie_pem.h
@@ -39,7 +39,7 @@
struct resource *reg;
bus_space_tag_t reg_bst;
bus_space_handle_t reg_bsh;
- struct pcie_range ranges[RANGES_TUPLES_MAX];
+ struct pcie_range ranges[MAX_RANGES_TUPLES];
struct rman mem_rman;
struct rman io_rman;
bus_space_handle_t pem_sli_base;
Index: head/sys/arm64/cavium/thunder_pcie_pem.c
===================================================================
--- head/sys/arm64/cavium/thunder_pcie_pem.c
+++ head/sys/arm64/cavium/thunder_pcie_pem.c
@@ -32,6 +32,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_platform.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
@@ -41,8 +43,16 @@
#include <sys/rman.h>
#include <sys/endian.h>
+#ifdef FDT
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/ofw/ofw_pci.h>
+#endif
+
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
+#include <dev/pci/pci_host_generic.h>
#include <machine/bus.h>
#include <machine/resource.h>
Index: head/sys/arm64/cavium/thunder_pcie_pem_fdt.c
===================================================================
--- head/sys/arm64/cavium/thunder_pcie_pem_fdt.c
+++ head/sys/arm64/cavium/thunder_pcie_pem_fdt.c
@@ -28,6 +28,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_platform.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
@@ -44,6 +46,11 @@
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcib_private.h>
+#include <dev/pci/pci_host_generic.h>
+
#include "thunder_pcie_common.h"
#include "thunder_pcie_pem.h"
Index: head/sys/conf/files.arm64
===================================================================
--- head/sys/conf/files.arm64
+++ head/sys/conf/files.arm64
@@ -52,7 +52,6 @@
arm64/arm64/unwind.c optional ddb | kdtrace_hooks | stack
arm64/arm64/vfp.c standard
arm64/arm64/vm_machdep.c standard
-arm64/cavium/thunder_pcie.c optional soc_cavm_thunderx pci
arm64/cavium/thunder_pcie_fdt.c optional soc_cavm_thunderx pci fdt
arm64/cavium/thunder_pcie_pem.c optional soc_cavm_thunderx pci
arm64/cavium/thunder_pcie_pem_fdt.c optional soc_cavm_thunderx pci fdt
Index: head/sys/dev/pci/pci_host_generic.h
===================================================================
--- head/sys/dev/pci/pci_host_generic.h
+++ head/sys/dev/pci/pci_host_generic.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
+ * Copyright (c) 2015 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Semihalf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *
+ * $FreeBSD$
+ *
+ */
+
+#ifndef __PCI_HOST_GENERIC_H_
+#define __PCI_HOST_GENERIC_H_
+
+#define MAX_RANGES_TUPLES 16
+#define MIN_RANGES_TUPLES 2
+
+struct pcie_range {
+ uint64_t pci_base;
+ uint64_t phys_base;
+ uint64_t size;
+ uint64_t flags;
+#define FLAG_IO (1 << 0)
+#define FLAG_MEM (1 << 1)
+};
+
+struct generic_pcie_softc {
+ struct pcie_range ranges[MAX_RANGES_TUPLES];
+ int nranges;
+ struct rman mem_rman;
+ struct rman io_rman;
+ struct resource *res;
+ struct resource *res1;
+ int ecam;
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+ device_t dev;
+ bus_space_handle_t ioh;
+#ifdef FDT
+ struct ofw_bus_iinfo pci_iinfo;
+#endif
+};
+
+extern devclass_t generic_pcie_devclass;
+DECLARE_CLASS(generic_pcie_driver);
+
+int pci_host_generic_attach(device_t);
+
+#endif /* __PCI_HOST_GENERIC_H_ */
Index: head/sys/dev/pci/pci_host_generic.c
===================================================================
--- head/sys/dev/pci/pci_host_generic.c
+++ head/sys/dev/pci/pci_host_generic.c
@@ -33,6 +33,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_platform.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
@@ -51,6 +53,7 @@
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcib_private.h>
+#include <dev/pci/pci_host_generic.h>
#include <machine/cpu.h>
#include <machine/bus.h>
@@ -74,9 +77,6 @@
(((func) & PCIE_FUNC_MASK) << PCIE_FUNC_SHIFT) | \
((reg) & PCIE_REG_MASK))
-#define MAX_RANGES_TUPLES 5
-#define MIN_RANGES_TUPLES 2
-
#define PCI_IO_WINDOW_OFFSET 0x1000
#define SPACE_CODE_SHIFT 24
@@ -85,34 +85,15 @@
#define PROPS_CELL_SIZE 1
#define PCI_ADDR_CELL_SIZE 2
-struct pcie_range {
- uint64_t pci_base;
- uint64_t phys_base;
- uint64_t size;
- uint64_t flags;
-#define FLAG_IO (1 << 0)
-#define FLAG_MEM (1 << 1)
-};
-
-struct generic_pcie_softc {
- struct pcie_range ranges[MAX_RANGES_TUPLES];
- int nranges;
- struct rman mem_rman;
- struct rman io_rman;
- struct resource *res;
- struct resource *res1;
- int ecam;
- bus_space_tag_t bst;
- bus_space_handle_t bsh;
- device_t dev;
- bus_space_handle_t ioh;
- struct ofw_bus_iinfo pci_iinfo;
+/* OFW bus interface */
+struct generic_pcie_ofw_devinfo {
+ struct ofw_bus_devinfo di_dinfo;
+ struct resource_list di_rl;
};
/* Forward prototypes */
static int generic_pcie_probe(device_t dev);
-static int generic_pcie_attach(device_t dev);
static int parse_pci_mem_ranges(struct generic_pcie_softc *sc);
static uint32_t generic_pcie_read_config(device_t dev, u_int bus, u_int slot,
u_int func, u_int reg, int bytes);
@@ -126,8 +107,33 @@
static struct resource *generic_pcie_alloc_resource(device_t dev,
device_t child, int type, int *rid, rman_res_t start, rman_res_t end,
rman_res_t count, u_int flags);
+static struct resource *generic_pcie_alloc_resource_ofw(device_t, device_t,
+ int, int *, rman_res_t, rman_res_t, rman_res_t, u_int);
+static struct resource *generic_pcie_alloc_resource_pcie(device_t dev,
+ device_t child, int type, int *rid, rman_res_t start, rman_res_t end,
+ rman_res_t count, u_int flags);
static int generic_pcie_release_resource(device_t dev, device_t child,
int type, int rid, struct resource *res);
+static int generic_pcie_release_resource_ofw(device_t, device_t, int, int,
+ struct resource *);
+static int generic_pcie_release_resource_pcie(device_t, device_t, int, int,
+ struct resource *);
+static int generic_pcie_ofw_bus_attach(device_t);
+static const struct ofw_bus_devinfo *generic_pcie_ofw_get_devinfo(device_t,
+ device_t);
+
+static __inline void
+get_addr_size_cells(phandle_t node, pcell_t *addr_cells, pcell_t *size_cells)
+{
+
+ *addr_cells = 2;
+ /* Find address cells if present */
+ OF_getencprop(node, "#address-cells", addr_cells, sizeof(*addr_cells));
+
+ *size_cells = 2;
+ /* Find size cells if present */
+ OF_getencprop(node, "#size-cells", size_cells, sizeof(*size_cells));
+}
static int
generic_pcie_probe(device_t dev)
@@ -138,14 +144,14 @@
if (ofw_bus_is_compatible(dev, "pci-host-ecam-generic")) {
device_set_desc(dev, "Generic PCI host controller");
- return (BUS_PROBE_DEFAULT);
+ return (BUS_PROBE_GENERIC);
}
return (ENXIO);
}
-static int
-generic_pcie_attach(device_t dev)
+int
+pci_host_generic_attach(device_t dev)
{
struct generic_pcie_softc *sc;
uint64_t phys_base;
@@ -158,6 +164,17 @@
sc = device_get_softc(dev);
sc->dev = dev;
+ /* Retrieve 'ranges' property from FDT */
+ if (bootverbose)
+ device_printf(dev, "parsing FDT for ECAM%d:\n",
+ sc->ecam);
+ if (parse_pci_mem_ranges(sc))
+ return (ENXIO);
+
+ /* Attach OFW bus */
+ if (generic_pcie_ofw_bus_attach(dev) != 0)
+ return (ENXIO);
+
rid = 0;
sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
if (sc->res == NULL) {
@@ -173,13 +190,6 @@
sc->io_rman.rm_type = RMAN_ARRAY;
sc->io_rman.rm_descr = "PCIe IO window";
- /* Retrieve 'ranges' property from FDT */
- if (bootverbose)
- device_printf(dev, "parsing FDT for ECAM%d:\n",
- sc->ecam);
- if (parse_pci_mem_ranges(sc))
- return (ENXIO);
-
/* Initialize rman and allocate memory regions */
error = rman_init(&sc->mem_rman);
if (error) {
@@ -220,7 +230,6 @@
ofw_bus_setup_iinfo(ofw_bus_get_node(dev), &sc->pci_iinfo,
sizeof(cell_t));
-
device_add_child(dev, "pci", -1);
return (bus_generic_attach(dev));
}
@@ -314,7 +323,8 @@
uint64_t offset;
uint32_t data;
- if (bus > 255 || slot > 31 || func > 7 || reg > 4095)
+ if ((bus > PCI_BUSMAX) || (slot > PCI_SLOTMAX) ||
+ (func > PCI_FUNCMAX) || (reg > PCIE_REGMAX))
return (~0U);
sc = device_get_softc(dev);
@@ -349,7 +359,8 @@
bus_space_tag_t t;
uint64_t offset;
- if (bus > 255 || slot > 31 || func > 7 || reg > 4095)
+ if ((bus > PCI_BUSMAX) || (slot > PCI_SLOTMAX) ||
+ (func > PCI_FUNCMAX) || (reg > PCIE_REGMAX))
return;
sc = device_get_softc(dev);
@@ -434,7 +445,8 @@
return (0);
}
- device_printf(dev, "ERROR: Unknown index.\n");
+ if (bootverbose)
+ device_printf(dev, "ERROR: Unknown index %d.\n", index);
return (ENOENT);
}
@@ -463,7 +475,7 @@
}
static int
-generic_pcie_release_resource(device_t dev, device_t child, int type,
+generic_pcie_release_resource_pcie(device_t dev, device_t child, int type,
int rid, struct resource *res)
{
struct generic_pcie_softc *sc;
@@ -480,10 +492,41 @@
return (bus_generic_release_resource(dev, child, type, rid, res));
}
+static int
+generic_pcie_release_resource(device_t dev, device_t child, int type,
+ int rid, struct resource *res)
+{
+
+ /* For PCIe devices that do not have FDT nodes, use PCIB method */
+ if ((int)ofw_bus_get_node(child) <= 0) {
+ return (generic_pcie_release_resource_pcie(dev,
+ child, type, rid, res));
+ }
+
+ /* For other devices use OFW method */
+ return (generic_pcie_release_resource_ofw(dev,
+ child, type, rid, res));
+}
+
static struct resource *
generic_pcie_alloc_resource(device_t dev, device_t child, int type, int *rid,
rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
{
+
+ /* For PCIe devices that do not have FDT nodes, use PCIB method */
+ if ((int)ofw_bus_get_node(child) <= 0)
+ return (generic_pcie_alloc_resource_pcie(dev, child, type, rid,
+ start, end, count, flags));
+
+ /* For other devices use OFW method */
+ return (generic_pcie_alloc_resource_ofw(dev, child, type, rid,
+ start, end, count, flags));
+}
+
+static struct resource *
+generic_pcie_alloc_resource_pcie(device_t dev, device_t child, int type, int *rid,
+ rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
+{
struct generic_pcie_softc *sc;
struct resource *res;
struct rman *rm;
@@ -516,11 +559,9 @@
return (res);
fail:
- if (bootverbose) {
- device_printf(dev, "%s FAIL: type=%d, rid=%d, "
- "start=%016lx, end=%016lx, count=%016lx, flags=%x\n",
- __func__, type, *rid, start, end, count, flags);
- }
+ device_printf(dev, "%s FAIL: type=%d, rid=%d, "
+ "start=%016lx, end=%016lx, count=%016lx, flags=%x\n",
+ __func__, type, *rid, start, end, count, flags);
return (NULL);
}
@@ -617,7 +658,7 @@
static device_method_t generic_pcie_methods[] = {
DEVMETHOD(device_probe, generic_pcie_probe),
- DEVMETHOD(device_attach, generic_pcie_attach),
+ DEVMETHOD(device_attach, pci_host_generic_attach),
DEVMETHOD(bus_read_ivar, generic_pcie_read_ivar),
DEVMETHOD(bus_write_ivar, generic_pcie_write_ivar),
DEVMETHOD(bus_alloc_resource, generic_pcie_alloc_resource),
@@ -641,18 +682,137 @@
DEVMETHOD(pcib_map_msi, arm_map_msi),
#endif
+ /* ofw_bus interface */
+ DEVMETHOD(ofw_bus_get_devinfo, generic_pcie_ofw_get_devinfo),
+ DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat),
+ DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model),
+ DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name),
+ DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
+ DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
+
DEVMETHOD_END
};
-static driver_t generic_pcie_driver = {
- "pcib",
- generic_pcie_methods,
- sizeof(struct generic_pcie_softc),
-};
+static const struct ofw_bus_devinfo *
+generic_pcie_ofw_get_devinfo(device_t bus __unused, device_t child)
+{
+ struct generic_pcie_ofw_devinfo *di;
+
+ di = device_get_ivars(child);
+ return (&di->di_dinfo);
+}
+
+static struct resource *
+generic_pcie_alloc_resource_ofw(device_t bus, device_t child, int type, int *rid,
+ rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
+{
+ struct generic_pcie_softc *sc;
+ struct generic_pcie_ofw_devinfo *di;
+ struct resource_list_entry *rle;
+ int i;
-static devclass_t generic_pcie_devclass;
+ sc = device_get_softc(bus);
+
+ if ((start == 0UL) && (end == ~0UL)) {
+ if ((di = device_get_ivars(child)) == NULL)
+ return (NULL);
+ if (type == SYS_RES_IOPORT)
+ type = SYS_RES_MEMORY;
+
+ /* Find defaults for this rid */
+ rle = resource_list_find(&di->di_rl, type, *rid);
+ if (rle == NULL)
+ return (NULL);
+
+ start = rle->start;
+ end = rle->end;
+ count = rle->count;
+ }
+
+ if (type == SYS_RES_MEMORY) {
+ /* Remap through ranges property */
+ for (i = 0; i < MAX_RANGES_TUPLES; i++) {
+ if (start >= sc->ranges[i].phys_base && end <
+ sc->ranges[i].pci_base + sc->ranges[i].size) {
+ start -= sc->ranges[i].phys_base;
+ start += sc->ranges[i].pci_base;
+ end -= sc->ranges[i].phys_base;
+ end += sc->ranges[i].pci_base;
+ break;
+ }
+ }
+
+ if (i == MAX_RANGES_TUPLES) {
+ device_printf(bus, "Could not map resource "
+ "%#lx-%#lx\n", start, end);
+ return (NULL);
+ }
+ }
+
+ return (bus_generic_alloc_resource(bus, child, type, rid, start, end,
+ count, flags));
+}
+
+static int
+generic_pcie_release_resource_ofw(device_t bus, device_t child, int type, int rid,
+ struct resource *res)
+{
+
+ return (bus_generic_release_resource(bus, child, type, rid, res));
+}
+
+/* Helper functions */
+
+static int
+generic_pcie_ofw_bus_attach(device_t dev)
+{
+ struct generic_pcie_ofw_devinfo *di;
+ device_t child;
+ phandle_t parent, node;
+ pcell_t addr_cells, size_cells;
+
+ parent = ofw_bus_get_node(dev);
+ if (parent > 0) {
+ get_addr_size_cells(parent, &addr_cells, &size_cells);
+ /* Iterate through all bus subordinates */
+ for (node = OF_child(parent); node > 0; node = OF_peer(node)) {
+
+ /* Allocate and populate devinfo. */
+ di = malloc(sizeof(*di), M_DEVBUF, M_WAITOK | M_ZERO);
+ if (ofw_bus_gen_setup_devinfo(&di->di_dinfo, node) != 0) {
+ free(di, M_DEVBUF);
+ continue;
+ }
+
+ /* Initialize and populate resource list. */
+ resource_list_init(&di->di_rl);
+ ofw_bus_reg_to_rl(dev, node, addr_cells, size_cells,
+ &di->di_rl);
+ ofw_bus_intr_to_rl(dev, node, &di->di_rl, NULL);
+
+ /* Add newbus device for this FDT node */
+ child = device_add_child(dev, NULL, -1);
+ if (child == NULL) {
+ resource_list_free(&di->di_rl);
+ ofw_bus_gen_destroy_devinfo(&di->di_dinfo);
+ free(di, M_DEVBUF);
+ continue;
+ }
+
+ device_set_ivars(child, di);
+ }
+ }
+
+ return (0);
+}
+
+DEFINE_CLASS_0(pcib, generic_pcie_driver,
+ generic_pcie_methods, sizeof(struct generic_pcie_softc));
+
+devclass_t generic_pcie_devclass;
DRIVER_MODULE(pcib, simplebus, generic_pcie_driver,
-generic_pcie_devclass, 0, 0);
+ generic_pcie_devclass, 0, 0);
DRIVER_MODULE(pcib, ofwbus, generic_pcie_driver,
-generic_pcie_devclass, 0, 0);
+ generic_pcie_devclass, 0, 0);
+
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Apr 7, 6:26 PM (5 h, 14 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31045284
Default Alt Text
D5261.id13673.diff (42 KB)
Attached To
Mode
D5261: Make pci_host_generic and thunderx_pci common
Attached
Detach File
Event Timeline
Log In to Comment