18369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki/* 28369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki * Broadcom specific AMBA 38369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki * Bus scanning 48369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki * 58369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki * Licensed under the GNU/GPL. See COPYING for details. 68369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki */ 78369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki 88369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki#include "scan.h" 98369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki#include "bcma_private.h" 108369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki 118369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki#include <linux/bcma/bcma.h> 128369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki#include <linux/bcma/bcma_regs.h> 138369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki#include <linux/pci.h> 148369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki#include <linux/io.h> 158369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki#include <linux/dma-mapping.h> 168369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki#include <linux/slab.h> 178369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki 188369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłeckistruct bcma_device_id_name { 198369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki u16 id; 208369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki const char *name; 218369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki}; 2282a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintz 2382a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintzstatic const struct bcma_device_id_name bcma_arm_device_names[] = { 24e1ac4b409037b128f9a3eca3b3ab5dbbb71a7e6fRafał Miłecki { BCMA_CORE_4706_MAC_GBIT_COMMON, "BCM4706 GBit MAC Common" }, 2582a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintz { BCMA_CORE_ARM_1176, "ARM 1176" }, 2682a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintz { BCMA_CORE_ARM_7TDMI, "ARM 7TDMI" }, 2782a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintz { BCMA_CORE_ARM_CM3, "ARM CM3" }, 2882a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintz}; 2982a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintz 3082a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintzstatic const struct bcma_device_id_name bcma_bcm_device_names[] = { 318369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_OOB_ROUTER, "OOB Router" }, 32d2bb2b9e9161d221badafae063d0c62b41bf3078Rafał Miłecki { BCMA_CORE_4706_CHIPCOMMON, "BCM4706 ChipCommon" }, 33d2bb2b9e9161d221badafae063d0c62b41bf3078Rafał Miłecki { BCMA_CORE_4706_SOC_RAM, "BCM4706 SOC RAM" }, 34d2bb2b9e9161d221badafae063d0c62b41bf3078Rafał Miłecki { BCMA_CORE_4706_MAC_GBIT, "BCM4706 GBit MAC" }, 35dc6be9f54a4ecb0a09765d1f515ed947d86b7528Rafał Miłecki { BCMA_CORE_NS_PCIEG2, "PCIe Gen 2" }, 36dc6be9f54a4ecb0a09765d1f515ed947d86b7528Rafał Miłecki { BCMA_CORE_NS_DMA, "DMA" }, 37dc6be9f54a4ecb0a09765d1f515ed947d86b7528Rafał Miłecki { BCMA_CORE_NS_SDIO3, "SDIO3" }, 38dc6be9f54a4ecb0a09765d1f515ed947d86b7528Rafał Miłecki { BCMA_CORE_NS_USB20, "USB 2.0" }, 39dc6be9f54a4ecb0a09765d1f515ed947d86b7528Rafał Miłecki { BCMA_CORE_NS_USB30, "USB 3.0" }, 40dc6be9f54a4ecb0a09765d1f515ed947d86b7528Rafał Miłecki { BCMA_CORE_NS_A9JTAG, "ARM Cortex A9 JTAG" }, 41dc6be9f54a4ecb0a09765d1f515ed947d86b7528Rafał Miłecki { BCMA_CORE_NS_DDR23, "Denali DDR2/DDR3 memory controller" }, 42dc6be9f54a4ecb0a09765d1f515ed947d86b7528Rafał Miłecki { BCMA_CORE_NS_ROM, "ROM" }, 43dc6be9f54a4ecb0a09765d1f515ed947d86b7528Rafał Miłecki { BCMA_CORE_NS_NAND, "NAND flash controller" }, 44dc6be9f54a4ecb0a09765d1f515ed947d86b7528Rafał Miłecki { BCMA_CORE_NS_QSPI, "SPI flash controller" }, 45dc6be9f54a4ecb0a09765d1f515ed947d86b7528Rafał Miłecki { BCMA_CORE_NS_CHIPCOMMON_B, "Chipcommon B" }, 46bb4997a1afbff61084b243d62aaaf23ea38a290eHauke Mehrtens { BCMA_CORE_ARMCA9, "ARM Cortex A9 core (ihost)" }, 47d2bb2b9e9161d221badafae063d0c62b41bf3078Rafał Miłecki { BCMA_CORE_AMEMC, "AMEMC (DDR)" }, 48d2bb2b9e9161d221badafae063d0c62b41bf3078Rafał Miłecki { BCMA_CORE_ALTA, "ALTA (I2S)" }, 498369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_INVALID, "Invalid" }, 508369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_CHIPCOMMON, "ChipCommon" }, 518369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_ILINE20, "ILine 20" }, 528369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_SRAM, "SRAM" }, 538369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_SDRAM, "SDRAM" }, 548369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_PCI, "PCI" }, 558369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_ETHERNET, "Fast Ethernet" }, 568369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_V90, "V90" }, 578369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_USB11_HOSTDEV, "USB 1.1 Hostdev" }, 588369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_ADSL, "ADSL" }, 598369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_ILINE100, "ILine 100" }, 608369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_IPSEC, "IPSEC" }, 618369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_UTOPIA, "UTOPIA" }, 628369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_PCMCIA, "PCMCIA" }, 638369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_INTERNAL_MEM, "Internal Memory" }, 648369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_MEMC_SDRAM, "MEMC SDRAM" }, 658369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_OFDM, "OFDM" }, 668369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_EXTIF, "EXTIF" }, 678369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_80211, "IEEE 802.11" }, 688369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_PHY_A, "PHY A" }, 698369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_PHY_B, "PHY B" }, 708369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_PHY_G, "PHY G" }, 718369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_USB11_HOST, "USB 1.1 Host" }, 728369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_USB11_DEV, "USB 1.1 Device" }, 738369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_USB20_HOST, "USB 2.0 Host" }, 748369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_USB20_DEV, "USB 2.0 Device" }, 758369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_SDIO_HOST, "SDIO Host" }, 768369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_ROBOSWITCH, "Roboswitch" }, 778369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_PARA_ATA, "PATA" }, 788369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_SATA_XORDMA, "SATA XOR-DMA" }, 798369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_ETHERNET_GBIT, "GBit Ethernet" }, 808369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_PCIE, "PCIe" }, 818369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_PHY_N, "PHY N" }, 828369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_SRAM_CTL, "SRAM Controller" }, 838369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_MINI_MACPHY, "Mini MACPHY" }, 848369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_PHY_LP, "PHY LP" }, 858369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_PMU, "PMU" }, 868369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_PHY_SSN, "PHY SSN" }, 878369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_SDIO_DEV, "SDIO Device" }, 888369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_PHY_HT, "PHY HT" }, 898369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_MAC_GBIT, "GBit MAC" }, 908369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_DDR12_MEM_CTL, "DDR1/DDR2 Memory Controller" }, 918369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_PCIE_RC, "PCIe Root Complex" }, 928369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_OCP_OCP_BRIDGE, "OCP to OCP Bridge" }, 938369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_SHARED_COMMON, "Common Shared" }, 948369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_OCP_AHB_BRIDGE, "OCP to AHB Bridge" }, 958369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_SPI_HOST, "SPI Host" }, 968369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_I2S, "I2S" }, 978369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_SDR_DDR1_MEM_CTL, "SDR/DDR1 Memory Controller" }, 988369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_SHIM, "SHIM" }, 99d4988d4c733ba0b61cb372edd3d1992d26dd10d3Rafał Miłecki { BCMA_CORE_PCIE2, "PCIe Gen2" }, 100d4988d4c733ba0b61cb372edd3d1992d26dd10d3Rafał Miłecki { BCMA_CORE_ARM_CR4, "ARM CR4" }, 1018369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki { BCMA_CORE_DEFAULT, "Default" }, 1028369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki}; 10382a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintz 10482a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintzstatic const struct bcma_device_id_name bcma_mips_device_names[] = { 10582a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintz { BCMA_CORE_MIPS, "MIPS" }, 10682a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintz { BCMA_CORE_MIPS_3302, "MIPS 3302" }, 10782a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintz { BCMA_CORE_MIPS_74K, "MIPS 74K" }, 10882a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintz}; 10982a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintz 11082a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintzstatic const char *bcma_device_name(const struct bcma_device_id *id) 1118369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki{ 11282a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintz const struct bcma_device_id_name *names; 11382a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintz int size, i; 1148369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki 11582a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintz /* search manufacturer specific names */ 11682a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintz switch (id->manuf) { 11782a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintz case BCMA_MANUF_ARM: 11882a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintz names = bcma_arm_device_names; 11982a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintz size = ARRAY_SIZE(bcma_arm_device_names); 12082a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintz break; 12182a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintz case BCMA_MANUF_BCM: 12282a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintz names = bcma_bcm_device_names; 12382a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintz size = ARRAY_SIZE(bcma_bcm_device_names); 12482a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintz break; 12582a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintz case BCMA_MANUF_MIPS: 12682a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintz names = bcma_mips_device_names; 12782a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintz size = ARRAY_SIZE(bcma_mips_device_names); 12882a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintz break; 12982a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintz default: 13082a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintz return "UNKNOWN"; 1318369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki } 13282a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintz 13382a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintz for (i = 0; i < size; i++) { 13482a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintz if (names[i].id == id->id) 13582a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintz return names[i].name; 13682a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintz } 13782a7c2bb5f57fd9f610f9e6d7c532033bebfa0ccNathan Hintz 1388369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki return "UNKNOWN"; 1398369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki} 1408369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki 1418369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłeckistatic u32 bcma_scan_read32(struct bcma_bus *bus, u8 current_coreidx, 1428369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki u16 offset) 1438369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki{ 1448369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki return readl(bus->mmio + offset); 1458369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki} 1468369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki 1478369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłeckistatic void bcma_scan_switch_core(struct bcma_bus *bus, u32 addr) 1488369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki{ 1498369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki if (bus->hosttype == BCMA_HOSTTYPE_PCI) 1508369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki pci_write_config_dword(bus->host_pci, BCMA_PCI_BAR0_WIN, 1518369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki addr); 1528369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki} 1538369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki 1540b8d6e59a128f4fecce9ea3cddc1872a60a29402Hauke Mehrtensstatic u32 bcma_erom_get_ent(struct bcma_bus *bus, u32 __iomem **eromptr) 1558369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki{ 1568369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki u32 ent = readl(*eromptr); 1578369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki (*eromptr)++; 1588369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki return ent; 1598369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki} 1608369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki 1610b8d6e59a128f4fecce9ea3cddc1872a60a29402Hauke Mehrtensstatic void bcma_erom_push_ent(u32 __iomem **eromptr) 1628369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki{ 1638369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki (*eromptr)--; 1648369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki} 1658369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki 1660b8d6e59a128f4fecce9ea3cddc1872a60a29402Hauke Mehrtensstatic s32 bcma_erom_get_ci(struct bcma_bus *bus, u32 __iomem **eromptr) 1678369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki{ 1688369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki u32 ent = bcma_erom_get_ent(bus, eromptr); 1698369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki if (!(ent & SCAN_ER_VALID)) 1708369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki return -ENOENT; 1718369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki if ((ent & SCAN_ER_TAG) != SCAN_ER_TAG_CI) 1728369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki return -ENOENT; 1738369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki return ent; 1748369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki} 1758369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki 1760b8d6e59a128f4fecce9ea3cddc1872a60a29402Hauke Mehrtensstatic bool bcma_erom_is_end(struct bcma_bus *bus, u32 __iomem **eromptr) 1778369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki{ 1788369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki u32 ent = bcma_erom_get_ent(bus, eromptr); 1798369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki bcma_erom_push_ent(eromptr); 1808369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki return (ent == (SCAN_ER_TAG_END | SCAN_ER_VALID)); 1818369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki} 1828369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki 1830b8d6e59a128f4fecce9ea3cddc1872a60a29402Hauke Mehrtensstatic bool bcma_erom_is_bridge(struct bcma_bus *bus, u32 __iomem **eromptr) 1848369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki{ 1858369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki u32 ent = bcma_erom_get_ent(bus, eromptr); 1868369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki bcma_erom_push_ent(eromptr); 1878369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki return (((ent & SCAN_ER_VALID)) && 1888369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki ((ent & SCAN_ER_TAGX) == SCAN_ER_TAG_ADDR) && 1898369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki ((ent & SCAN_ADDR_TYPE) == SCAN_ADDR_TYPE_BRIDGE)); 1908369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki} 1918369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki 1920b8d6e59a128f4fecce9ea3cddc1872a60a29402Hauke Mehrtensstatic void bcma_erom_skip_component(struct bcma_bus *bus, u32 __iomem **eromptr) 1938369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki{ 1948369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki u32 ent; 1958369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki while (1) { 1968369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki ent = bcma_erom_get_ent(bus, eromptr); 1978369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki if ((ent & SCAN_ER_VALID) && 1988369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki ((ent & SCAN_ER_TAG) == SCAN_ER_TAG_CI)) 1998369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki break; 2008369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki if (ent == (SCAN_ER_TAG_END | SCAN_ER_VALID)) 2018369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki break; 2028369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki } 2038369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki bcma_erom_push_ent(eromptr); 2048369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki} 2058369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki 2060b8d6e59a128f4fecce9ea3cddc1872a60a29402Hauke Mehrtensstatic s32 bcma_erom_get_mst_port(struct bcma_bus *bus, u32 __iomem **eromptr) 2078369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki{ 2088369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki u32 ent = bcma_erom_get_ent(bus, eromptr); 2098369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki if (!(ent & SCAN_ER_VALID)) 2108369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki return -ENOENT; 2118369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki if ((ent & SCAN_ER_TAG) != SCAN_ER_TAG_MP) 2128369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki return -ENOENT; 2138369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki return ent; 2148369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki} 2158369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki 216fd4edf197544bae1c77d84bad354aa7ce1d08ce1Hauke Mehrtensstatic u32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 __iomem **eromptr, 2178369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki u32 type, u8 port) 2188369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki{ 2198369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki u32 addrl, addrh, sizel, sizeh = 0; 2208369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki u32 size; 2218369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki 2228369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki u32 ent = bcma_erom_get_ent(bus, eromptr); 2238369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki if ((!(ent & SCAN_ER_VALID)) || 2248369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki ((ent & SCAN_ER_TAGX) != SCAN_ER_TAG_ADDR) || 2258369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki ((ent & SCAN_ADDR_TYPE) != type) || 2268369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki (((ent & SCAN_ADDR_PORT) >> SCAN_ADDR_PORT_SHIFT) != port)) { 2278369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki bcma_erom_push_ent(eromptr); 228fd4edf197544bae1c77d84bad354aa7ce1d08ce1Hauke Mehrtens return (u32)-EINVAL; 2298369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki } 2308369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki 2318369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki addrl = ent & SCAN_ADDR_ADDR; 2328369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki if (ent & SCAN_ADDR_AG32) 2338369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki addrh = bcma_erom_get_ent(bus, eromptr); 2348369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki else 2358369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki addrh = 0; 2368369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki 2378369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki if ((ent & SCAN_ADDR_SZ) == SCAN_ADDR_SZ_SZD) { 2388369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki size = bcma_erom_get_ent(bus, eromptr); 2398369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki sizel = size & SCAN_SIZE_SZ; 2408369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki if (size & SCAN_SIZE_SG32) 2418369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki sizeh = bcma_erom_get_ent(bus, eromptr); 2428369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki } else 2438369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki sizel = SCAN_ADDR_SZ_BASE << 2448369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki ((ent & SCAN_ADDR_SZ) >> SCAN_ADDR_SZ_SHIFT); 2458369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki 2468369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki return addrl; 2478369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki} 2488369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki 249517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtensstatic struct bcma_device *bcma_find_core_by_index(struct bcma_bus *bus, 250517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens u16 index) 251517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens{ 252517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens struct bcma_device *core; 253517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens 254517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens list_for_each_entry(core, &bus->cores, list) { 255517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens if (core->core_index == index) 256517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens return core; 257517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens } 258517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens return NULL; 259517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens} 260517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens 2615f2d6171e1e70584b9819771443485750453fd16Hauke Mehrtensstatic struct bcma_device *bcma_find_core_reverse(struct bcma_bus *bus, u16 coreid) 2625f2d6171e1e70584b9819771443485750453fd16Hauke Mehrtens{ 2635f2d6171e1e70584b9819771443485750453fd16Hauke Mehrtens struct bcma_device *core; 2645f2d6171e1e70584b9819771443485750453fd16Hauke Mehrtens 2655f2d6171e1e70584b9819771443485750453fd16Hauke Mehrtens list_for_each_entry_reverse(core, &bus->cores, list) { 2665f2d6171e1e70584b9819771443485750453fd16Hauke Mehrtens if (core->id.id == coreid) 2675f2d6171e1e70584b9819771443485750453fd16Hauke Mehrtens return core; 2685f2d6171e1e70584b9819771443485750453fd16Hauke Mehrtens } 2695f2d6171e1e70584b9819771443485750453fd16Hauke Mehrtens return NULL; 2705f2d6171e1e70584b9819771443485750453fd16Hauke Mehrtens} 2715f2d6171e1e70584b9819771443485750453fd16Hauke Mehrtens 272aaa2ced15ad8dca8048666c9f70736424d696a6bHauke Mehrtens#define IS_ERR_VALUE_U32(x) ((x) >= (u32)-MAX_ERRNO) 273aaa2ced15ad8dca8048666c9f70736424d696a6bHauke Mehrtens 274982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtensstatic int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr, 275517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens struct bcma_device_id *match, int core_num, 276982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens struct bcma_device *core) 277982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens{ 278fd4edf197544bae1c77d84bad354aa7ce1d08ce1Hauke Mehrtens u32 tmp; 27923a2f39c8f4035eade7f226eb7ada30c78d9eee3Hauke Mehrtens u8 i, j, k; 280982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens s32 cia, cib; 281982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens u8 ports[2], wrappers[2]; 282982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens 283982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens /* get CIs */ 284982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens cia = bcma_erom_get_ci(bus, eromptr); 285982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens if (cia < 0) { 286982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens bcma_erom_push_ent(eromptr); 287982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens if (bcma_erom_is_end(bus, eromptr)) 288982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens return -ESPIPE; 289982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens return -EILSEQ; 290982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens } 291982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens cib = bcma_erom_get_ci(bus, eromptr); 292982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens if (cib < 0) 293982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens return -EILSEQ; 294982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens 295982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens /* parse CIs */ 296982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens core->id.class = (cia & SCAN_CIA_CLASS) >> SCAN_CIA_CLASS_SHIFT; 297982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens core->id.id = (cia & SCAN_CIA_ID) >> SCAN_CIA_ID_SHIFT; 298982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens core->id.manuf = (cia & SCAN_CIA_MANUF) >> SCAN_CIA_MANUF_SHIFT; 299982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens ports[0] = (cib & SCAN_CIB_NMP) >> SCAN_CIB_NMP_SHIFT; 300982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens ports[1] = (cib & SCAN_CIB_NSP) >> SCAN_CIB_NSP_SHIFT; 301982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens wrappers[0] = (cib & SCAN_CIB_NMW) >> SCAN_CIB_NMW_SHIFT; 302982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens wrappers[1] = (cib & SCAN_CIB_NSW) >> SCAN_CIB_NSW_SHIFT; 303982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens core->id.rev = (cib & SCAN_CIB_REV) >> SCAN_CIB_REV_SHIFT; 304982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens 305982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens if (((core->id.manuf == BCMA_MANUF_ARM) && 306982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens (core->id.id == 0xFFF)) || 307982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens (ports[1] == 0)) { 308982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens bcma_erom_skip_component(bus, eromptr); 309982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens return -ENXIO; 310982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens } 311982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens 312982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens /* check if component is a core at all */ 313982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens if (wrappers[0] + wrappers[1] == 0) { 314e1ac4b409037b128f9a3eca3b3ab5dbbb71a7e6fRafał Miłecki /* Some specific cores don't need wrappers */ 315e1ac4b409037b128f9a3eca3b3ab5dbbb71a7e6fRafał Miłecki switch (core->id.id) { 316e1ac4b409037b128f9a3eca3b3ab5dbbb71a7e6fRafał Miłecki case BCMA_CORE_4706_MAC_GBIT_COMMON: 3171716bcf3f76fe71e98d4851a3eb73ea3d93d4773Hauke Mehrtens case BCMA_CORE_NS_CHIPCOMMON_B: 318e1ac4b409037b128f9a3eca3b3ab5dbbb71a7e6fRafał Miłecki /* Not used yet: case BCMA_CORE_OOB_ROUTER: */ 319e1ac4b409037b128f9a3eca3b3ab5dbbb71a7e6fRafał Miłecki break; 320e1ac4b409037b128f9a3eca3b3ab5dbbb71a7e6fRafał Miłecki default: 321e1ac4b409037b128f9a3eca3b3ab5dbbb71a7e6fRafał Miłecki bcma_erom_skip_component(bus, eromptr); 322e1ac4b409037b128f9a3eca3b3ab5dbbb71a7e6fRafał Miłecki return -ENXIO; 323e1ac4b409037b128f9a3eca3b3ab5dbbb71a7e6fRafał Miłecki } 324982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens } 325982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens 326982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens if (bcma_erom_is_bridge(bus, eromptr)) { 327982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens bcma_erom_skip_component(bus, eromptr); 328982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens return -ENXIO; 329982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens } 330982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens 331517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens if (bcma_find_core_by_index(bus, core_num)) { 332517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens bcma_erom_skip_component(bus, eromptr); 333517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens return -ENODEV; 334517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens } 335517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens 336517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens if (match && ((match->manuf != BCMA_ANY_MANUF && 337517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens match->manuf != core->id.manuf) || 338517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens (match->id != BCMA_ANY_ID && match->id != core->id.id) || 339517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens (match->rev != BCMA_ANY_REV && match->rev != core->id.rev) || 340517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens (match->class != BCMA_ANY_CLASS && match->class != core->id.class) 341517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens )) { 342517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens bcma_erom_skip_component(bus, eromptr); 343517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens return -ENODEV; 344517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens } 345517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens 346982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens /* get & parse master ports */ 347982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens for (i = 0; i < ports[0]; i++) { 3484e0d8cc1006b889909a87f824943bad9a56358e8Dan Carpenter s32 mst_port_d = bcma_erom_get_mst_port(bus, eromptr); 349982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens if (mst_port_d < 0) 350982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens return -EILSEQ; 351982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens } 352982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens 353e167d9fbb881c030f93563fd364c8a0b8c5cd6d3Hauke Mehrtens /* First Slave Address Descriptor should be port 0: 354e167d9fbb881c030f93563fd364c8a0b8c5cd6d3Hauke Mehrtens * the main register space for the core 355e167d9fbb881c030f93563fd364c8a0b8c5cd6d3Hauke Mehrtens */ 356e167d9fbb881c030f93563fd364c8a0b8c5cd6d3Hauke Mehrtens tmp = bcma_erom_get_addr_desc(bus, eromptr, SCAN_ADDR_TYPE_SLAVE, 0); 357aaa2ced15ad8dca8048666c9f70736424d696a6bHauke Mehrtens if (tmp == 0 || IS_ERR_VALUE_U32(tmp)) { 358e167d9fbb881c030f93563fd364c8a0b8c5cd6d3Hauke Mehrtens /* Try again to see if it is a bridge */ 359e167d9fbb881c030f93563fd364c8a0b8c5cd6d3Hauke Mehrtens tmp = bcma_erom_get_addr_desc(bus, eromptr, 360e167d9fbb881c030f93563fd364c8a0b8c5cd6d3Hauke Mehrtens SCAN_ADDR_TYPE_BRIDGE, 0); 361aaa2ced15ad8dca8048666c9f70736424d696a6bHauke Mehrtens if (tmp == 0 || IS_ERR_VALUE_U32(tmp)) { 362e167d9fbb881c030f93563fd364c8a0b8c5cd6d3Hauke Mehrtens return -EILSEQ; 363e167d9fbb881c030f93563fd364c8a0b8c5cd6d3Hauke Mehrtens } else { 3643d9d8af330a891f141db420115238f01e4c6ece7Rafał Miłecki bcma_info(bus, "Bridge found\n"); 365e167d9fbb881c030f93563fd364c8a0b8c5cd6d3Hauke Mehrtens return -ENXIO; 366e167d9fbb881c030f93563fd364c8a0b8c5cd6d3Hauke Mehrtens } 367e167d9fbb881c030f93563fd364c8a0b8c5cd6d3Hauke Mehrtens } 368e167d9fbb881c030f93563fd364c8a0b8c5cd6d3Hauke Mehrtens core->addr = tmp; 369e167d9fbb881c030f93563fd364c8a0b8c5cd6d3Hauke Mehrtens 370982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens /* get & parse slave ports */ 37123a2f39c8f4035eade7f226eb7ada30c78d9eee3Hauke Mehrtens k = 0; 372982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens for (i = 0; i < ports[1]; i++) { 373982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens for (j = 0; ; j++) { 374982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens tmp = bcma_erom_get_addr_desc(bus, eromptr, 375982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens SCAN_ADDR_TYPE_SLAVE, i); 376aaa2ced15ad8dca8048666c9f70736424d696a6bHauke Mehrtens if (IS_ERR_VALUE_U32(tmp)) { 377982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens /* no more entries for port _i_ */ 378982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens /* pr_debug("erom: slave port %d " 379982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens * "has %d descriptors\n", i, j); */ 380982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens break; 38123a2f39c8f4035eade7f226eb7ada30c78d9eee3Hauke Mehrtens } else if (k < ARRAY_SIZE(core->addr_s)) { 38223a2f39c8f4035eade7f226eb7ada30c78d9eee3Hauke Mehrtens core->addr_s[k] = tmp; 38323a2f39c8f4035eade7f226eb7ada30c78d9eee3Hauke Mehrtens k++; 384982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens } 385982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens } 386982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens } 387982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens 388982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens /* get & parse master wrappers */ 389982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens for (i = 0; i < wrappers[0]; i++) { 390982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens for (j = 0; ; j++) { 391982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens tmp = bcma_erom_get_addr_desc(bus, eromptr, 392982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens SCAN_ADDR_TYPE_MWRAP, i); 393aaa2ced15ad8dca8048666c9f70736424d696a6bHauke Mehrtens if (IS_ERR_VALUE_U32(tmp)) { 394982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens /* no more entries for port _i_ */ 395982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens /* pr_debug("erom: master wrapper %d " 396982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens * "has %d descriptors\n", i, j); */ 397982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens break; 398982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens } else { 399982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens if (i == 0 && j == 0) 400982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens core->wrap = tmp; 401982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens } 402982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens } 403982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens } 404982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens 405982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens /* get & parse slave wrappers */ 406982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens for (i = 0; i < wrappers[1]; i++) { 407982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens u8 hack = (ports[1] == 1) ? 0 : 1; 408982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens for (j = 0; ; j++) { 409982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens tmp = bcma_erom_get_addr_desc(bus, eromptr, 410982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens SCAN_ADDR_TYPE_SWRAP, i + hack); 411aaa2ced15ad8dca8048666c9f70736424d696a6bHauke Mehrtens if (IS_ERR_VALUE_U32(tmp)) { 412982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens /* no more entries for port _i_ */ 413982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens /* pr_debug("erom: master wrapper %d " 414982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens * has %d descriptors\n", i, j); */ 415982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens break; 416982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens } else { 417982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens if (wrappers[0] == 0 && !i && !j) 418982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens core->wrap = tmp; 419982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens } 420982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens } 421982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens } 422ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens if (bus->hosttype == BCMA_HOSTTYPE_SOC) { 423ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens core->io_addr = ioremap_nocache(core->addr, BCMA_CORE_SIZE); 424ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens if (!core->io_addr) 425ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens return -ENOMEM; 426ecf47e9bb796558423fa87b43a8fe55f086ca56eHauke Mehrtens if (core->wrap) { 427ecf47e9bb796558423fa87b43a8fe55f086ca56eHauke Mehrtens core->io_wrap = ioremap_nocache(core->wrap, 428ecf47e9bb796558423fa87b43a8fe55f086ca56eHauke Mehrtens BCMA_CORE_SIZE); 429ecf47e9bb796558423fa87b43a8fe55f086ca56eHauke Mehrtens if (!core->io_wrap) { 430ecf47e9bb796558423fa87b43a8fe55f086ca56eHauke Mehrtens iounmap(core->io_addr); 431ecf47e9bb796558423fa87b43a8fe55f086ca56eHauke Mehrtens return -ENOMEM; 432ecf47e9bb796558423fa87b43a8fe55f086ca56eHauke Mehrtens } 433ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens } 434ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens } 435982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens return 0; 436982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens} 437982eee67dd703a37edc3532b85e3a4122b5eb90bHauke Mehrtens 438517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtensvoid bcma_init_bus(struct bcma_bus *bus) 4398369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki{ 4408369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki s32 tmp; 441f0d4724b2a663089d21e19933ca591d842b63230Hauke Mehrtens struct bcma_chipinfo *chipinfo = &(bus->chipinfo); 442fbf019909173c683d85f7f63b0a33746bf5e4a02Rafał Miłecki char chip_id[8]; 4438369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki 4448369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki INIT_LIST_HEAD(&bus->cores); 4458369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki bus->nr_cores = 0; 4468369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki 4478369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki bcma_scan_switch_core(bus, BCMA_ADDR_BASE); 4488369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki 4498369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki tmp = bcma_scan_read32(bus, 0, BCMA_CC_ID); 450f0d4724b2a663089d21e19933ca591d842b63230Hauke Mehrtens chipinfo->id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT; 451f0d4724b2a663089d21e19933ca591d842b63230Hauke Mehrtens chipinfo->rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT; 452f0d4724b2a663089d21e19933ca591d842b63230Hauke Mehrtens chipinfo->pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT; 453fbf019909173c683d85f7f63b0a33746bf5e4a02Rafał Miłecki 454fbf019909173c683d85f7f63b0a33746bf5e4a02Rafał Miłecki snprintf(chip_id, ARRAY_SIZE(chip_id), 455fbf019909173c683d85f7f63b0a33746bf5e4a02Rafał Miłecki (chipinfo->id > 0x9999) ? "%d" : "0x%04X", chipinfo->id); 456fbf019909173c683d85f7f63b0a33746bf5e4a02Rafał Miłecki bcma_info(bus, "Found chip with id %s, rev 0x%02X and package 0x%02X\n", 457fbf019909173c683d85f7f63b0a33746bf5e4a02Rafał Miłecki chip_id, chipinfo->rev, chipinfo->pkg); 45867a5c29e1623edda5ff3f0355af533e72a245ad9Hauke Mehrtens} 45967a5c29e1623edda5ff3f0355af533e72a245ad9Hauke Mehrtens 46067a5c29e1623edda5ff3f0355af533e72a245ad9Hauke Mehrtensint bcma_bus_scan(struct bcma_bus *bus) 46167a5c29e1623edda5ff3f0355af533e72a245ad9Hauke Mehrtens{ 46267a5c29e1623edda5ff3f0355af533e72a245ad9Hauke Mehrtens u32 erombase; 46367a5c29e1623edda5ff3f0355af533e72a245ad9Hauke Mehrtens u32 __iomem *eromptr, *eromend; 46467a5c29e1623edda5ff3f0355af533e72a245ad9Hauke Mehrtens 465517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens int err, core_num = 0; 46667a5c29e1623edda5ff3f0355af533e72a245ad9Hauke Mehrtens 4678369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM); 468ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens if (bus->hosttype == BCMA_HOSTTYPE_SOC) { 469ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens eromptr = ioremap_nocache(erombase, BCMA_CORE_SIZE); 470ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens if (!eromptr) 471ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens return -ENOMEM; 472ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens } else { 473ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens eromptr = bus->mmio; 474ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens } 475ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens 4768369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32); 4778369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki 4788369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki bcma_scan_switch_core(bus, erombase); 4798369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki 4808369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki while (eromptr < eromend) { 4815f2d6171e1e70584b9819771443485750453fd16Hauke Mehrtens struct bcma_device *other_core; 4828369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki struct bcma_device *core = kzalloc(sizeof(*core), GFP_KERNEL); 4839dbf5f55f8d35ff9aedc75267f4e4042aaf89755Hauke Mehrtens if (!core) { 4849dbf5f55f8d35ff9aedc75267f4e4042aaf89755Hauke Mehrtens err = -ENOMEM; 4859dbf5f55f8d35ff9aedc75267f4e4042aaf89755Hauke Mehrtens goto out; 4869dbf5f55f8d35ff9aedc75267f4e4042aaf89755Hauke Mehrtens } 4878369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki INIT_LIST_HEAD(&core->list); 4888369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki core->bus = bus; 4898369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki 490517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens err = bcma_get_next_core(bus, &eromptr, NULL, core_num, core); 491f9721ed2707661af75a414d09cdcd71f99a13f62Jesper Juhl if (err < 0) { 492f9721ed2707661af75a414d09cdcd71f99a13f62Jesper Juhl kfree(core); 493f9721ed2707661af75a414d09cdcd71f99a13f62Jesper Juhl if (err == -ENODEV) { 494f9721ed2707661af75a414d09cdcd71f99a13f62Jesper Juhl core_num++; 495f9721ed2707661af75a414d09cdcd71f99a13f62Jesper Juhl continue; 496f9721ed2707661af75a414d09cdcd71f99a13f62Jesper Juhl } else if (err == -ENXIO) { 497f9721ed2707661af75a414d09cdcd71f99a13f62Jesper Juhl continue; 498f9721ed2707661af75a414d09cdcd71f99a13f62Jesper Juhl } else if (err == -ESPIPE) { 499f9721ed2707661af75a414d09cdcd71f99a13f62Jesper Juhl break; 500f9721ed2707661af75a414d09cdcd71f99a13f62Jesper Juhl } 5019dbf5f55f8d35ff9aedc75267f4e4042aaf89755Hauke Mehrtens goto out; 502f9721ed2707661af75a414d09cdcd71f99a13f62Jesper Juhl } 5038369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki 504517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens core->core_index = core_num++; 505517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens bus->nr_cores++; 5065f2d6171e1e70584b9819771443485750453fd16Hauke Mehrtens other_core = bcma_find_core_reverse(bus, core->id.id); 5075f2d6171e1e70584b9819771443485750453fd16Hauke Mehrtens core->core_unit = (other_core == NULL) ? 0 : other_core->core_unit + 1; 508517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens 5093d9d8af330a891f141db420115238f01e4c6ece7Rafał Miłecki bcma_info(bus, "Core %d found: %s (manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n", 5103d9d8af330a891f141db420115238f01e4c6ece7Rafał Miłecki core->core_index, bcma_device_name(&core->id), 5113d9d8af330a891f141db420115238f01e4c6ece7Rafał Miłecki core->id.manuf, core->id.id, core->id.rev, 5123d9d8af330a891f141db420115238f01e4c6ece7Rafał Miłecki core->id.class); 5138369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki 514c334e25c9f3a95f2bd6b79fedc5170f17245b1c7Rafał Miłecki list_add_tail(&core->list, &bus->cores); 5158369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki } 5168369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki 5179dbf5f55f8d35ff9aedc75267f4e4042aaf89755Hauke Mehrtens err = 0; 5189dbf5f55f8d35ff9aedc75267f4e4042aaf89755Hauke Mehrtensout: 519ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens if (bus->hosttype == BCMA_HOSTTYPE_SOC) 520ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens iounmap(eromptr); 521ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens 5229dbf5f55f8d35ff9aedc75267f4e4042aaf89755Hauke Mehrtens return err; 5238369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki} 524517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens 525517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtensint __init bcma_bus_scan_early(struct bcma_bus *bus, 526517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens struct bcma_device_id *match, 527517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens struct bcma_device *core) 528517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens{ 529517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens u32 erombase; 530517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens u32 __iomem *eromptr, *eromend; 531517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens 532ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens int err = -ENODEV; 533ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens int core_num = 0; 534517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens 535517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM); 536ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens if (bus->hosttype == BCMA_HOSTTYPE_SOC) { 537ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens eromptr = ioremap_nocache(erombase, BCMA_CORE_SIZE); 538ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens if (!eromptr) 539ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens return -ENOMEM; 540ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens } else { 541ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens eromptr = bus->mmio; 542ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens } 543ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens 544517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32); 545517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens 546517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens bcma_scan_switch_core(bus, erombase); 547517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens 548517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens while (eromptr < eromend) { 549517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens memset(core, 0, sizeof(*core)); 550517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens INIT_LIST_HEAD(&core->list); 551517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens core->bus = bus; 552517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens 553517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens err = bcma_get_next_core(bus, &eromptr, match, core_num, core); 554517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens if (err == -ENODEV) { 555517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens core_num++; 556517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens continue; 557517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens } else if (err == -ENXIO) 558517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens continue; 559517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens else if (err == -ESPIPE) 560517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens break; 561517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens else if (err < 0) 5629dbf5f55f8d35ff9aedc75267f4e4042aaf89755Hauke Mehrtens goto out; 563517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens 564517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens core->core_index = core_num++; 565517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens bus->nr_cores++; 5663d9d8af330a891f141db420115238f01e4c6ece7Rafał Miłecki bcma_info(bus, "Core %d found: %s (manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n", 5673d9d8af330a891f141db420115238f01e4c6ece7Rafał Miłecki core->core_index, bcma_device_name(&core->id), 5683d9d8af330a891f141db420115238f01e4c6ece7Rafał Miłecki core->id.manuf, core->id.id, core->id.rev, 5693d9d8af330a891f141db420115238f01e4c6ece7Rafał Miłecki core->id.class); 570517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens 571c334e25c9f3a95f2bd6b79fedc5170f17245b1c7Rafał Miłecki list_add_tail(&core->list, &bus->cores); 572ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens err = 0; 573ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens break; 574517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens } 575517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens 5769dbf5f55f8d35ff9aedc75267f4e4042aaf89755Hauke Mehrtensout: 577ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens if (bus->hosttype == BCMA_HOSTTYPE_SOC) 578ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens iounmap(eromptr); 579ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens 580ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens return err; 581517f43e5a922d51ac960424de4f72676fe6a7390Hauke Mehrtens} 582