summaryrefslogtreecommitdiffstats
path: root/sys/arm
diff options
context:
space:
mode:
authorraj <raj@FreeBSD.org>2009-01-09 10:20:51 +0000
committerraj <raj@FreeBSD.org>2009-01-09 10:20:51 +0000
commit761fc046203f800a47f1af4d3acf0d2d07af1669 (patch)
tree28ab282455b120754c984fa2352bdf734c59d825 /sys/arm
parenta2e0aa00719a79a8fb007b086ea855dec3bcd0f4 (diff)
downloadFreeBSD-src-761fc046203f800a47f1af4d3acf0d2d07af1669.zip
FreeBSD-src-761fc046203f800a47f1af4d3acf0d2d07af1669.tar.gz
Improve Marvell SOCs PCI/PCIE driver.
- Provide dedicated rmans for MEM and IO resources. - Convert PCI IRQ routing info into a table (from callback approach), provide config data for alternative DB- boards. - Fix a wrong boundary check error in pcib_mbus_init_bar() Obtained from: Semihalf
Diffstat (limited to 'sys/arm')
-rw-r--r--sys/arm/mv/mv_pci.c86
-rw-r--r--sys/arm/mv/mvvar.h10
-rw-r--r--sys/arm/mv/orion/db88f5xxx.c51
-rw-r--r--sys/arm/mv/orion/orion.c4
4 files changed, 110 insertions, 41 deletions
diff --git a/sys/arm/mv/mv_pci.c b/sys/arm/mv/mv_pci.c
index b878b0a..0c893bfd 100644
--- a/sys/arm/mv/mv_pci.c
+++ b/sys/arm/mv/mv_pci.c
@@ -95,10 +95,12 @@ __FBSDID("$FreeBSD$");
struct pcib_mbus_softc {
device_t sc_dev;
+ struct rman sc_iomem_rman;
bus_addr_t sc_iomem_base;
bus_addr_t sc_iomem_size;
bus_addr_t sc_iomem_alloc; /* Next allocation. */
+ struct rman sc_ioport_rman;
bus_addr_t sc_ioport_base;
bus_addr_t sc_ioport_size;
bus_addr_t sc_ioport_alloc; /* Next allocation. */
@@ -521,12 +523,39 @@ pcib_mbus_attach(device_t self)
sc->sc_ioport_size = sc->sc_info->op_io_size;
sc->sc_ioport_alloc = sc->sc_info->op_io_base;
+ sc->sc_iomem_rman.rm_type = RMAN_ARRAY;
+ err = rman_init(&sc->sc_iomem_rman);
+ if (err)
+ return (err);
+
+ sc->sc_ioport_rman.rm_type = RMAN_ARRAY;
+ err = rman_init(&sc->sc_ioport_rman);
+ if (err) {
+ rman_fini(&sc->sc_iomem_rman);
+ return (err);
+ }
+
+ err = rman_manage_region(&sc->sc_iomem_rman, sc->sc_iomem_base,
+ sc->sc_iomem_base + sc->sc_iomem_size - 1);
+ if (err)
+ goto error;
+
+ err = rman_manage_region(&sc->sc_ioport_rman, sc->sc_ioport_base,
+ sc->sc_ioport_base + sc->sc_ioport_size - 1);
+ if (err)
+ goto error;
+
err = pcib_mbus_init(sc, sc->sc_busnr, pcib_mbus_maxslots(sc->sc_dev));
if (err)
- return(err);
+ goto error;
device_add_child(self, "pci", -1);
return (bus_generic_attach(self));
+
+error:
+ rman_fini(&sc->sc_iomem_rman);
+ rman_fini(&sc->sc_ioport_rman);
+ return (err);
}
static int
@@ -570,7 +599,7 @@ pcib_mbus_init_bar(struct pcib_mbus_softc *sc, int bus, int slot, int func,
return (width);
addr = (*allocp + mask) & ~mask;
- if ((*allocp = addr + size) >= limit)
+ if ((*allocp = addr + size) > limit)
return (-1);
if (bootverbose)
@@ -634,8 +663,10 @@ static int
pcib_mbus_init_resources(struct pcib_mbus_softc *sc, int bus, int slot,
int func, int hdrtype)
{
+ const struct obio_pci_irq_map *map = sc->sc_info->op_pci_irq_map;
int maxbar = (hdrtype & PCIM_HDRTYPE) ? 0 : 6;
- int bar = 0, irq, pin, i;
+ int bar = 0, irq = -1;
+ int pin, i;
/* Program the base address registers */
while (bar < maxbar) {
@@ -652,8 +683,14 @@ pcib_mbus_init_resources(struct pcib_mbus_softc *sc, int bus, int slot,
pin = pcib_mbus_read_config(sc->sc_dev, bus, slot, func,
PCIR_INTPIN, 1);
- if (sc->sc_info->op_get_irq != NULL)
- irq = sc->sc_info->op_get_irq(bus, slot, func, pin);
+ if (map != NULL)
+ while (map->opim_irq >= 0) {
+ if ((map->opim_slot == slot || map->opim_slot < 0) &&
+ (map->opim_pin == pin || map->opim_pin < 0))
+ irq = map->opim_irq;
+
+ map++;
+ }
else
irq = sc->sc_info->op_irq;
@@ -728,9 +765,37 @@ static struct resource *
pcib_mbus_alloc_resource(device_t dev, device_t child, int type, int *rid,
u_long start, u_long end, u_long count, u_int flags)
{
+ struct pcib_mbus_softc *sc = device_get_softc(dev);
+ struct rman *rm = NULL;
+ struct resource *res;
- return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
- type, rid, start, end, count, flags));
+ switch (type) {
+ case SYS_RES_IOPORT:
+ rm = &sc->sc_ioport_rman;
+ break;
+ case SYS_RES_MEMORY:
+ rm = &sc->sc_iomem_rman;
+ break;
+ default:
+ return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
+ type, rid, start, end, count, flags));
+ };
+
+ res = rman_reserve_resource(rm, start, end, count, flags, child);
+ if (res == NULL)
+ return (NULL);
+
+ rman_set_rid(res, *rid);
+ rman_set_bustag(res, obio_tag);
+ rman_set_bushandle(res, start);
+
+ if (flags & RF_ACTIVE)
+ if (bus_activate_resource(child, type, *rid, res)) {
+ rman_release_resource(res);
+ return (NULL);
+ }
+
+ return (res);
}
static int
@@ -738,8 +803,11 @@ pcib_mbus_release_resource(device_t dev, device_t child, int type, int rid,
struct resource *res)
{
- return (BUS_RELEASE_RESOURCE(device_get_parent(dev), child,
- type, rid, res));
+ if (type != SYS_RES_IOPORT && type != SYS_RES_MEMORY)
+ return (BUS_RELEASE_RESOURCE(device_get_parent(dev), child,
+ type, rid, res));
+
+ return (rman_release_resource(res));
}
static int
diff --git a/sys/arm/mv/mvvar.h b/sys/arm/mv/mvvar.h
index a92e631..061f363 100644
--- a/sys/arm/mv/mvvar.h
+++ b/sys/arm/mv/mvvar.h
@@ -63,7 +63,11 @@ struct obio_device {
struct resource_list od_resources;
};
-typedef int (*obio_get_irq_t)(u_int bus, u_int slot, u_int func, u_int pin);
+struct obio_pci_irq_map {
+ int opim_slot;
+ int opim_pin;
+ int opim_irq;
+};
struct obio_pci {
int op_type;
@@ -82,8 +86,8 @@ struct obio_pci {
int op_mem_win_target;
int op_mem_win_attr;
- obio_get_irq_t op_get_irq; /* IRQ Mapping callback */
- int op_irq; /* used if callback is NULL */
+ const struct obio_pci_irq_map *op_pci_irq_map;
+ int op_irq; /* used if IRQ map table is NULL */
};
struct gpio_config {
diff --git a/sys/arm/mv/orion/db88f5xxx.c b/sys/arm/mv/orion/db88f5xxx.c
index 8db1b75..5a5f283 100644
--- a/sys/arm/mv/orion/db88f5xxx.c
+++ b/sys/arm/mv/orion/db88f5xxx.c
@@ -123,35 +123,32 @@ static const struct pmap_devmap pmap_devmap[] = {
{ 0, 0, 0, 0, 0, }
};
-int platform_pci_get_irq(u_int bus, u_int slot, u_int func, u_int pin)
-{
- int irq;
-
- switch (slot) {
- case 7:
- irq = GPIO2IRQ(12); /* GPIO 0 for DB-88F5182 */
- break; /* GPIO 12 for DB-88F5281 */
- case 8:
- case 9:
- irq = GPIO2IRQ(13); /* GPIO 1 for DB-88F5182 */
- break; /* GPIO 13 for DB-88F5281 */
- default:
- irq = -1;
- break;
- };
+/*
+ * The pci_irq_map table consists of 3 columns:
+ * - PCI slot number (less than zero means ANY).
+ * - PCI IRQ pin (less than zero means ANY).
+ * - PCI IRQ (less than zero marks end of table).
+ *
+ * IRQ number from the first matching entry is used to configure PCI device
+ */
- /*
- * XXX This isn't the right place to setup GPIO, but it makes sure
- * that PCI works on 5XXX targets where U-Boot doesn't set up the GPIO
- * correctly to handle PCI IRQs (e.g., on 5182). This code will go
- * away once we set up GPIO in a generic way in a proper place (TBD).
- */
- if (irq >= 0)
- mv_gpio_configure(IRQ2GPIO(irq), MV_GPIO_POLAR_LOW |
- MV_GPIO_LEVEL, ~0u);
+/* PCI IRQ Map for DB-88F5281 */
+const struct obio_pci_irq_map pci_irq_map[] = {
+ { 7, -1, GPIO2IRQ(12) },
+ { 8, -1, GPIO2IRQ(13) },
+ { 9, -1, GPIO2IRQ(13) },
+ { -1, -1, -1 }
+};
- return (irq);
-}
+#if 0
+/* PCI IRQ Map for DB-88F5182 */
+const struct obio_pci_irq_map pci_irq_map[] = {
+ { 7, -1, GPIO2IRQ(0) },
+ { 8, -1, GPIO2IRQ(1) },
+ { 9, -1, GPIO2IRQ(1) },
+ { -1, -1, -1 }
+};
+#endif
/*
* mv_gpio_config row structure:
diff --git a/sys/arm/mv/orion/orion.c b/sys/arm/mv/orion/orion.c
index 5d3dc91..e1852c1 100644
--- a/sys/arm/mv/orion/orion.c
+++ b/sys/arm/mv/orion/orion.c
@@ -41,7 +41,7 @@ __FBSDID("$FreeBSD$");
#include <arm/mv/mvreg.h>
#include <arm/mv/mvvar.h>
-extern int platform_pci_get_irq(u_int bus, u_int slot, u_int func, u_int pin);
+extern const struct obio_pci_irq_map pci_irq_map[];
struct obio_device obio_devices[] = {
{ "ic", MV_IC_BASE, MV_IC_SIZE,
@@ -106,7 +106,7 @@ const struct obio_pci mv_pci_info[] = {
MV_PCI_BASE, MV_PCI_SIZE,
MV_PCI_IO_BASE, MV_PCI_IO_SIZE, 3, 0x51,
MV_PCI_MEM_BASE, MV_PCI_MEM_SIZE, 3, 0x59,
- platform_pci_get_irq, -1
+ pci_irq_map, -1
},
{ 0, 0, 0 }
OpenPOWER on IntegriCloud