diff options
Diffstat (limited to 'drivers/bcma/scan.c')
| -rw-r--r-- | drivers/bcma/scan.c | 196 |
1 files changed, 143 insertions, 53 deletions
diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c index 3a2f672db9a..37768401d11 100644 --- a/drivers/bcma/scan.c +++ b/drivers/bcma/scan.c @@ -19,15 +19,39 @@ struct bcma_device_id_name { u16 id; const char *name; }; -struct bcma_device_id_name bcma_device_names[] = { + +static const struct bcma_device_id_name bcma_arm_device_names[] = { + { BCMA_CORE_4706_MAC_GBIT_COMMON, "BCM4706 GBit MAC Common" }, + { BCMA_CORE_ARM_1176, "ARM 1176" }, + { BCMA_CORE_ARM_7TDMI, "ARM 7TDMI" }, + { BCMA_CORE_ARM_CM3, "ARM CM3" }, +}; + +static const struct bcma_device_id_name bcma_bcm_device_names[] = { { BCMA_CORE_OOB_ROUTER, "OOB Router" }, + { BCMA_CORE_4706_CHIPCOMMON, "BCM4706 ChipCommon" }, + { BCMA_CORE_4706_SOC_RAM, "BCM4706 SOC RAM" }, + { BCMA_CORE_4706_MAC_GBIT, "BCM4706 GBit MAC" }, + { BCMA_CORE_PCIEG2, "PCIe Gen 2" }, + { BCMA_CORE_DMA, "DMA" }, + { BCMA_CORE_SDIO3, "SDIO3" }, + { BCMA_CORE_USB20, "USB 2.0" }, + { BCMA_CORE_USB30, "USB 3.0" }, + { BCMA_CORE_A9JTAG, "ARM Cortex A9 JTAG" }, + { BCMA_CORE_DDR23, "Denali DDR2/DDR3 memory controller" }, + { BCMA_CORE_ROM, "ROM" }, + { BCMA_CORE_NAND, "NAND flash controller" }, + { BCMA_CORE_QSPI, "SPI flash controller" }, + { BCMA_CORE_CHIPCOMMON_B, "Chipcommon B" }, + { BCMA_CORE_ARMCA9, "ARM Cortex A9 core (ihost)" }, + { BCMA_CORE_AMEMC, "AMEMC (DDR)" }, + { BCMA_CORE_ALTA, "ALTA (I2S)" }, { BCMA_CORE_INVALID, "Invalid" }, { BCMA_CORE_CHIPCOMMON, "ChipCommon" }, { BCMA_CORE_ILINE20, "ILine 20" }, { BCMA_CORE_SRAM, "SRAM" }, { BCMA_CORE_SDRAM, "SDRAM" }, { BCMA_CORE_PCI, "PCI" }, - { BCMA_CORE_MIPS, "MIPS" }, { BCMA_CORE_ETHERNET, "Fast Ethernet" }, { BCMA_CORE_V90, "V90" }, { BCMA_CORE_USB11_HOSTDEV, "USB 1.1 Hostdev" }, @@ -44,7 +68,6 @@ struct bcma_device_id_name bcma_device_names[] = { { BCMA_CORE_PHY_A, "PHY A" }, { BCMA_CORE_PHY_B, "PHY B" }, { BCMA_CORE_PHY_G, "PHY G" }, - { BCMA_CORE_MIPS_3302, "MIPS 3302" }, { BCMA_CORE_USB11_HOST, "USB 1.1 Host" }, { BCMA_CORE_USB11_DEV, "USB 1.1 Device" }, { BCMA_CORE_USB20_HOST, "USB 2.0 Host" }, @@ -58,15 +81,11 @@ struct bcma_device_id_name bcma_device_names[] = { { BCMA_CORE_PHY_N, "PHY N" }, { BCMA_CORE_SRAM_CTL, "SRAM Controller" }, { BCMA_CORE_MINI_MACPHY, "Mini MACPHY" }, - { BCMA_CORE_ARM_1176, "ARM 1176" }, - { BCMA_CORE_ARM_7TDMI, "ARM 7TDMI" }, { BCMA_CORE_PHY_LP, "PHY LP" }, { BCMA_CORE_PMU, "PMU" }, { BCMA_CORE_PHY_SSN, "PHY SSN" }, { BCMA_CORE_SDIO_DEV, "SDIO Device" }, - { BCMA_CORE_ARM_CM3, "ARM CM3" }, { BCMA_CORE_PHY_HT, "PHY HT" }, - { BCMA_CORE_MIPS_74K, "MIPS 74K" }, { BCMA_CORE_MAC_GBIT, "GBit MAC" }, { BCMA_CORE_DDR12_MEM_CTL, "DDR1/DDR2 Memory Controller" }, { BCMA_CORE_PCIE_RC, "PCIe Root Complex" }, @@ -77,18 +96,45 @@ struct bcma_device_id_name bcma_device_names[] = { { BCMA_CORE_I2S, "I2S" }, { BCMA_CORE_SDR_DDR1_MEM_CTL, "SDR/DDR1 Memory Controller" }, { BCMA_CORE_SHIM, "SHIM" }, + { BCMA_CORE_PCIE2, "PCIe Gen2" }, + { BCMA_CORE_ARM_CR4, "ARM CR4" }, { BCMA_CORE_DEFAULT, "Default" }, }; -const char *bcma_device_name(struct bcma_device_id *id) + +static const struct bcma_device_id_name bcma_mips_device_names[] = { + { BCMA_CORE_MIPS, "MIPS" }, + { BCMA_CORE_MIPS_3302, "MIPS 3302" }, + { BCMA_CORE_MIPS_74K, "MIPS 74K" }, +}; + +static const char *bcma_device_name(const struct bcma_device_id *id) { - int i; + const struct bcma_device_id_name *names; + int size, i; + + /* search manufacturer specific names */ + switch (id->manuf) { + case BCMA_MANUF_ARM: + names = bcma_arm_device_names; + size = ARRAY_SIZE(bcma_arm_device_names); + break; + case BCMA_MANUF_BCM: + names = bcma_bcm_device_names; + size = ARRAY_SIZE(bcma_bcm_device_names); + break; + case BCMA_MANUF_MIPS: + names = bcma_mips_device_names; + size = ARRAY_SIZE(bcma_mips_device_names); + break; + default: + return "UNKNOWN"; + } - if (id->manuf == BCMA_MANUF_BCM) { - for (i = 0; i < ARRAY_SIZE(bcma_device_names); i++) { - if (bcma_device_names[i].id == id->id) - return bcma_device_names[i].name; - } + for (i = 0; i < size; i++) { + if (names[i].id == id->id) + return names[i].name; } + return "UNKNOWN"; } @@ -105,19 +151,19 @@ static void bcma_scan_switch_core(struct bcma_bus *bus, u32 addr) addr); } -static u32 bcma_erom_get_ent(struct bcma_bus *bus, u32 **eromptr) +static u32 bcma_erom_get_ent(struct bcma_bus *bus, u32 __iomem **eromptr) { u32 ent = readl(*eromptr); (*eromptr)++; return ent; } -static void bcma_erom_push_ent(u32 **eromptr) +static void bcma_erom_push_ent(u32 __iomem **eromptr) { (*eromptr)--; } -static s32 bcma_erom_get_ci(struct bcma_bus *bus, u32 **eromptr) +static s32 bcma_erom_get_ci(struct bcma_bus *bus, u32 __iomem **eromptr) { u32 ent = bcma_erom_get_ent(bus, eromptr); if (!(ent & SCAN_ER_VALID)) @@ -127,14 +173,14 @@ static s32 bcma_erom_get_ci(struct bcma_bus *bus, u32 **eromptr) return ent; } -static bool bcma_erom_is_end(struct bcma_bus *bus, u32 **eromptr) +static bool bcma_erom_is_end(struct bcma_bus *bus, u32 __iomem **eromptr) { u32 ent = bcma_erom_get_ent(bus, eromptr); bcma_erom_push_ent(eromptr); return (ent == (SCAN_ER_TAG_END | SCAN_ER_VALID)); } -static bool bcma_erom_is_bridge(struct bcma_bus *bus, u32 **eromptr) +static bool bcma_erom_is_bridge(struct bcma_bus *bus, u32 __iomem **eromptr) { u32 ent = bcma_erom_get_ent(bus, eromptr); bcma_erom_push_ent(eromptr); @@ -143,7 +189,7 @@ static bool bcma_erom_is_bridge(struct bcma_bus *bus, u32 **eromptr) ((ent & SCAN_ADDR_TYPE) == SCAN_ADDR_TYPE_BRIDGE)); } -static void bcma_erom_skip_component(struct bcma_bus *bus, u32 **eromptr) +static void bcma_erom_skip_component(struct bcma_bus *bus, u32 __iomem **eromptr) { u32 ent; while (1) { @@ -157,7 +203,7 @@ static void bcma_erom_skip_component(struct bcma_bus *bus, u32 **eromptr) bcma_erom_push_ent(eromptr); } -static s32 bcma_erom_get_mst_port(struct bcma_bus *bus, u32 **eromptr) +static s32 bcma_erom_get_mst_port(struct bcma_bus *bus, u32 __iomem **eromptr) { u32 ent = bcma_erom_get_ent(bus, eromptr); if (!(ent & SCAN_ER_VALID)) @@ -167,7 +213,7 @@ static s32 bcma_erom_get_mst_port(struct bcma_bus *bus, u32 **eromptr) return ent; } -static s32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 **eromptr, +static u32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 __iomem **eromptr, u32 type, u8 port) { u32 addrl, addrh, sizel, sizeh = 0; @@ -179,7 +225,7 @@ static s32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 **eromptr, ((ent & SCAN_ADDR_TYPE) != type) || (((ent & SCAN_ADDR_PORT) >> SCAN_ADDR_PORT_SHIFT) != port)) { bcma_erom_push_ent(eromptr); - return -EINVAL; + return (u32)-EINVAL; } addrl = ent & SCAN_ADDR_ADDR; @@ -212,11 +258,24 @@ static struct bcma_device *bcma_find_core_by_index(struct bcma_bus *bus, return NULL; } +static struct bcma_device *bcma_find_core_reverse(struct bcma_bus *bus, u16 coreid) +{ + struct bcma_device *core; + + list_for_each_entry_reverse(core, &bus->cores, list) { + if (core->id.id == coreid) + return core; + } + return NULL; +} + +#define IS_ERR_VALUE_U32(x) ((x) >= (u32)-MAX_ERRNO) + static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr, struct bcma_device_id *match, int core_num, struct bcma_device *core) { - s32 tmp; + u32 tmp; u8 i, j; s32 cia, cib; u8 ports[2], wrappers[2]; @@ -252,11 +311,15 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr, /* check if component is a core at all */ if (wrappers[0] + wrappers[1] == 0) { - /* we could save addrl of the router - if (cid == BCMA_CORE_OOB_ROUTER) - */ - bcma_erom_skip_component(bus, eromptr); - return -ENXIO; + /* Some specific cores don't need wrappers */ + switch (core->id.id) { + case BCMA_CORE_4706_MAC_GBIT_COMMON: + /* Not used yet: case BCMA_CORE_OOB_ROUTER: */ + break; + default: + bcma_erom_skip_component(bus, eromptr); + return -ENXIO; + } } if (bcma_erom_is_bridge(bus, eromptr)) { @@ -286,19 +349,36 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr, return -EILSEQ; } + /* First Slave Address Descriptor should be port 0: + * the main register space for the core + */ + tmp = bcma_erom_get_addr_desc(bus, eromptr, SCAN_ADDR_TYPE_SLAVE, 0); + if (tmp == 0 || IS_ERR_VALUE_U32(tmp)) { + /* Try again to see if it is a bridge */ + tmp = bcma_erom_get_addr_desc(bus, eromptr, + SCAN_ADDR_TYPE_BRIDGE, 0); + if (tmp == 0 || IS_ERR_VALUE_U32(tmp)) { + return -EILSEQ; + } else { + bcma_info(bus, "Bridge found\n"); + return -ENXIO; + } + } + core->addr = tmp; + /* get & parse slave ports */ for (i = 0; i < ports[1]; i++) { for (j = 0; ; j++) { tmp = bcma_erom_get_addr_desc(bus, eromptr, SCAN_ADDR_TYPE_SLAVE, i); - if (tmp < 0) { + if (IS_ERR_VALUE_U32(tmp)) { /* no more entries for port _i_ */ /* pr_debug("erom: slave port %d " * "has %d descriptors\n", i, j); */ break; } else { if (i == 0 && j == 0) - core->addr = tmp; + core->addr1 = tmp; } } } @@ -308,7 +388,7 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr, for (j = 0; ; j++) { tmp = bcma_erom_get_addr_desc(bus, eromptr, SCAN_ADDR_TYPE_MWRAP, i); - if (tmp < 0) { + if (IS_ERR_VALUE_U32(tmp)) { /* no more entries for port _i_ */ /* pr_debug("erom: master wrapper %d " * "has %d descriptors\n", i, j); */ @@ -326,7 +406,7 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr, for (j = 0; ; j++) { tmp = bcma_erom_get_addr_desc(bus, eromptr, SCAN_ADDR_TYPE_SWRAP, i + hack); - if (tmp < 0) { + if (IS_ERR_VALUE_U32(tmp)) { /* no more entries for port _i_ */ /* pr_debug("erom: master wrapper %d " * has %d descriptors\n", i, j); */ @@ -353,6 +433,7 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr, void bcma_init_bus(struct bcma_bus *bus) { s32 tmp; + struct bcma_chipinfo *chipinfo = &(bus->chipinfo); if (bus->init_done) return; @@ -363,9 +444,12 @@ void bcma_init_bus(struct bcma_bus *bus) bcma_scan_switch_core(bus, BCMA_ADDR_BASE); tmp = bcma_scan_read32(bus, 0, BCMA_CC_ID); - 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; + chipinfo->id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT; + chipinfo->rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT; + chipinfo->pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT; + bcma_info(bus, "Found chip with id 0x%04X, rev 0x%02X and package 0x%02X\n", + chipinfo->id, chipinfo->rev, chipinfo->pkg); + bus->init_done = true; } @@ -392,9 +476,12 @@ int bcma_bus_scan(struct bcma_bus *bus) bcma_scan_switch_core(bus, erombase); while (eromptr < eromend) { + struct bcma_device *other_core; struct bcma_device *core = kzalloc(sizeof(*core), GFP_KERNEL); - if (!core) - return -ENOMEM; + if (!core) { + err = -ENOMEM; + goto out; + } INIT_LIST_HEAD(&core->list); core->bus = bus; @@ -409,25 +496,28 @@ int bcma_bus_scan(struct bcma_bus *bus) } else if (err == -ESPIPE) { break; } - return err; + goto out; } core->core_index = core_num++; bus->nr_cores++; + other_core = bcma_find_core_reverse(bus, core->id.id); + core->core_unit = (other_core == NULL) ? 0 : other_core->core_unit + 1; - pr_info("Core %d found: %s " - "(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n", - core->core_index, bcma_device_name(&core->id), - core->id.manuf, core->id.id, core->id.rev, - core->id.class); + bcma_info(bus, "Core %d found: %s (manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n", + core->core_index, bcma_device_name(&core->id), + core->id.manuf, core->id.id, core->id.rev, + core->id.class); - list_add(&core->list, &bus->cores); + list_add_tail(&core->list, &bus->cores); } + err = 0; +out: if (bus->hosttype == BCMA_HOSTTYPE_SOC) iounmap(eromptr); - return 0; + return err; } int __init bcma_bus_scan_early(struct bcma_bus *bus, @@ -467,21 +557,21 @@ int __init bcma_bus_scan_early(struct bcma_bus *bus, else if (err == -ESPIPE) break; else if (err < 0) - return err; + goto out; core->core_index = core_num++; bus->nr_cores++; - pr_info("Core %d found: %s " - "(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n", - core->core_index, bcma_device_name(&core->id), - core->id.manuf, core->id.id, core->id.rev, - core->id.class); + bcma_info(bus, "Core %d found: %s (manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n", + core->core_index, bcma_device_name(&core->id), + core->id.manuf, core->id.id, core->id.rev, + core->id.class); - list_add(&core->list, &bus->cores); + list_add_tail(&core->list, &bus->cores); err = 0; break; } +out: if (bus->hosttype == BCMA_HOSTTYPE_SOC) iounmap(eromptr); |
