This patch adds support for using bcma on an embedded bus. An embedded system like the bcm4716 could register this bus and it searches for the bcma cores then. Signed-off-by: Hauke Mehrtens <hauke@xxxxxxxxxx> --- drivers/bcma/Kconfig | 5 ++ drivers/bcma/Makefile | 1 + drivers/bcma/host_embedded.c | 93 ++++++++++++++++++++++++++++++++++++ drivers/bcma/main.c | 1 + drivers/bcma/scan.c | 29 ++++++++++- include/linux/bcma/bcma.h | 3 + include/linux/bcma/bcma_embedded.h | 8 +++ 7 files changed, 138 insertions(+), 2 deletions(-) create mode 100644 drivers/bcma/host_embedded.c create mode 100644 include/linux/bcma/bcma_embedded.h diff --git a/drivers/bcma/Kconfig b/drivers/bcma/Kconfig index 83e9adf..0390e32 100644 --- a/drivers/bcma/Kconfig +++ b/drivers/bcma/Kconfig @@ -27,6 +27,11 @@ config BCMA_HOST_PCI bool "Support for BCMA on PCI-host bus" depends on BCMA_HOST_PCI_POSSIBLE +config BCMA_HOST_EMBEDDED + bool + depends on BCMA && MIPS + default n + config BCMA_DEBUG bool "BCMA debugging" depends on BCMA diff --git a/drivers/bcma/Makefile b/drivers/bcma/Makefile index 0d56245..e509b1b 100644 --- a/drivers/bcma/Makefile +++ b/drivers/bcma/Makefile @@ -2,6 +2,7 @@ bcma-y += main.o scan.o core.o bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o bcma-y += driver_pci.o bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o +bcma-$(CONFIG_BCMA_HOST_EMBEDDED) += host_embedded.o obj-$(CONFIG_BCMA) += bcma.o ccflags-$(CONFIG_BCMA_DEBUG) := -DDEBUG diff --git a/drivers/bcma/host_embedded.c b/drivers/bcma/host_embedded.c new file mode 100644 index 0000000..6942440 --- /dev/null +++ b/drivers/bcma/host_embedded.c @@ -0,0 +1,93 @@ +/* + * Broadcom specific AMBA + * PCI Host + * + * Licensed under the GNU/GPL. See COPYING for details. + */ + +#include "bcma_private.h" +#include "scan.h" +#include <linux/bcma/bcma.h> + +static u8 bcma_host_bcma_read8(struct bcma_device *core, u16 offset) +{ + offset += core->core_index * BCMA_CORE_SIZE; + return readb(core->bus->mmio + offset); +} + +static u16 bcma_host_bcma_read16(struct bcma_device *core, u16 offset) +{ + offset += core->core_index * BCMA_CORE_SIZE; + return readw(core->bus->mmio + offset); +} + +static u32 bcma_host_bcma_read32(struct bcma_device *core, u16 offset) +{ + offset += core->core_index * BCMA_CORE_SIZE; + return readl(core->bus->mmio + offset); +} + +static void bcma_host_bcma_write8(struct bcma_device *core, u16 offset, + u8 value) +{ + offset += core->core_index * BCMA_CORE_SIZE; + writeb(value, core->bus->mmio + offset); +} + +static void bcma_host_bcma_write16(struct bcma_device *core, u16 offset, + u16 value) +{ + offset += core->core_index * BCMA_CORE_SIZE; + writew(value, core->bus->mmio + offset); +} + +static void bcma_host_bcma_write32(struct bcma_device *core, u16 offset, + u32 value) +{ + offset += core->core_index * BCMA_CORE_SIZE; + writel(value, core->bus->mmio + offset); +} + +static u32 bcma_host_bcma_aread32(struct bcma_device *core, u16 offset) +{ + offset += core->core_index * BCMA_CORE_SIZE; + return readl(core->bus->host_embedded + offset); +} + +static void bcma_host_bcma_awrite32(struct bcma_device *core, u16 offset, + u32 value) +{ + offset += core->core_index * BCMA_CORE_SIZE; + writel(value, core->bus->host_embedded + offset); +} + +const struct bcma_host_ops bcma_host_bcma_ops = { + .read8 = bcma_host_bcma_read8, + .read16 = bcma_host_bcma_read16, + .read32 = bcma_host_bcma_read32, + .write8 = bcma_host_bcma_write8, + .write16 = bcma_host_bcma_write16, + .write32 = bcma_host_bcma_write32, + .aread32 = bcma_host_bcma_aread32, + .awrite32 = bcma_host_bcma_awrite32, +}; + +int bcma_host_bcma_register(struct bcma_bus *bus) +{ + u32 __iomem *mmio; + + /* iomap only first core. We have to read some register on this core + * to get the number of cores. This is sone in bcma_scan() + */ + mmio = ioremap(BCMA_ADDR_BASE, BCMA_CORE_SIZE * 1); + if (!mmio) + return -ENOMEM; + bus->mmio = mmio; + + /* Host specific */ + bus->hosttype = BCMA_HOSTTYPE_EMBEDDED; + bus->ops = &bcma_host_bcma_ops; + + /* Register */ + return bcma_bus_register(bus); +} diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index 1afa107..c5bcb5f 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c @@ -119,6 +119,7 @@ static int bcma_register_cores(struct bcma_bus *bus) break; case BCMA_HOSTTYPE_NONE: case BCMA_HOSTTYPE_SDIO: + case BCMA_HOSTTYPE_EMBEDDED: break; } diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c index 70b39f7..9229615 100644 --- a/drivers/bcma/scan.c +++ b/drivers/bcma/scan.c @@ -203,7 +203,7 @@ static s32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 **eromptr, int bcma_bus_scan(struct bcma_bus *bus) { u32 erombase; - u32 __iomem *eromptr, *eromend; + u32 __iomem *eromptr, *eromend, *mmio; s32 cia, cib; u8 ports[2], wrappers[2]; @@ -219,9 +219,34 @@ int bcma_bus_scan(struct bcma_bus *bus) bus->chipinfo.id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT; bus->chipinfo.rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT; bus->chipinfo.pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT; + bus->nr_cores = (tmp & BCMA_CC_ID_NRCORES) >> BCMA_CC_ID_NRCORES_SHIFT; + + /* If we are an embedded device we now know the number of avaliable + * core and ioremap the correct space. + */ + if (bus->hosttype == BCMA_HOSTTYPE_EMBEDDED) { + iounmap(bus->mmio); + mmio = ioremap(BCMA_ADDR_BASE, BCMA_CORE_SIZE * bus->nr_cores); + if (!mmio) + return -ENOMEM; + bus->mmio = mmio; + + mmio = ioremap(BCMA_WRAP_BASE, BCMA_CORE_SIZE * bus->nr_cores); + if (!mmio) + return -ENOMEM; + bus->host_embedded = mmio; + } + /* reset it to 0 as we use it for counting */ + bus->nr_cores = 0; erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM); - eromptr = bus->mmio; + if (bus->hosttype == BCMA_HOSTTYPE_EMBEDDED) { + eromptr = ioremap(erombase, BCMA_CORE_SIZE); + if (!eromptr) + return -ENOMEM; + } else + eromptr = bus->mmio; + eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32); bcma_scan_switch_core(bus, erombase); diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h index 8b6feca..192c4ae 100644 --- a/include/linux/bcma/bcma.h +++ b/include/linux/bcma/bcma.h @@ -16,6 +16,7 @@ enum bcma_hosttype { BCMA_HOSTTYPE_NONE, BCMA_HOSTTYPE_PCI, BCMA_HOSTTYPE_SDIO, + BCMA_HOSTTYPE_EMBEDDED, }; struct bcma_chipinfo { @@ -185,6 +186,8 @@ struct bcma_bus { struct pci_dev *host_pci; /* Pointer to the SDIO device (only for BCMA_HOSTTYPE_SDIO) */ struct sdio_func *host_sdio; + /* Pointer to the embedded iomem (only for BCMA_HOSTTYPE_EMBEDDED) */ + void __iomem *host_embedded; }; struct bcma_chipinfo chipinfo; diff --git a/include/linux/bcma/bcma_embedded.h b/include/linux/bcma/bcma_embedded.h new file mode 100644 index 0000000..0faf46d --- /dev/null +++ b/include/linux/bcma/bcma_embedded.h @@ -0,0 +1,8 @@ +#ifndef LINUX_BCMA_EMBEDDED_H_ +#define LINUX_BCMA_EMBEDDED_H_ + +#include <linux/bcma/bcma.h> + +extern int bcma_host_bcma_register(struct bcma_bus *bus); + +#endif /* LINUX_BCMA_EMBEDDED_H_ */ -- 1.7.4.1