^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Broadcom specific AMBA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Bus scanning
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Licensed under the GNU/GPL. See COPYING for details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include "scan.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include "bcma_private.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/bcma/bcma.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/bcma/bcma_regs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/dma-mapping.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) struct bcma_device_id_name {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) u16 id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) static const struct bcma_device_id_name bcma_arm_device_names[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) { BCMA_CORE_4706_MAC_GBIT_COMMON, "BCM4706 GBit MAC Common" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) { BCMA_CORE_ARM_1176, "ARM 1176" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) { BCMA_CORE_ARM_7TDMI, "ARM 7TDMI" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) { BCMA_CORE_ARM_CM3, "ARM CM3" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) static const struct bcma_device_id_name bcma_bcm_device_names[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) { BCMA_CORE_OOB_ROUTER, "OOB Router" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) { BCMA_CORE_4706_CHIPCOMMON, "BCM4706 ChipCommon" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) { BCMA_CORE_4706_SOC_RAM, "BCM4706 SOC RAM" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) { BCMA_CORE_4706_MAC_GBIT, "BCM4706 GBit MAC" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) { BCMA_CORE_NS_PCIEG2, "PCIe Gen 2" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) { BCMA_CORE_NS_DMA, "DMA" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) { BCMA_CORE_NS_SDIO3, "SDIO3" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) { BCMA_CORE_NS_USB20, "USB 2.0" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) { BCMA_CORE_NS_USB30, "USB 3.0" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) { BCMA_CORE_NS_A9JTAG, "ARM Cortex A9 JTAG" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) { BCMA_CORE_NS_DDR23, "Denali DDR2/DDR3 memory controller" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) { BCMA_CORE_NS_ROM, "ROM" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) { BCMA_CORE_NS_NAND, "NAND flash controller" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) { BCMA_CORE_NS_QSPI, "SPI flash controller" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) { BCMA_CORE_NS_CHIPCOMMON_B, "Chipcommon B" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) { BCMA_CORE_ARMCA9, "ARM Cortex A9 core (ihost)" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) { BCMA_CORE_AMEMC, "AMEMC (DDR)" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) { BCMA_CORE_ALTA, "ALTA (I2S)" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) { BCMA_CORE_INVALID, "Invalid" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) { BCMA_CORE_CHIPCOMMON, "ChipCommon" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) { BCMA_CORE_ILINE20, "ILine 20" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) { BCMA_CORE_SRAM, "SRAM" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) { BCMA_CORE_SDRAM, "SDRAM" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) { BCMA_CORE_PCI, "PCI" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) { BCMA_CORE_ETHERNET, "Fast Ethernet" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) { BCMA_CORE_V90, "V90" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) { BCMA_CORE_USB11_HOSTDEV, "USB 1.1 Hostdev" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) { BCMA_CORE_ADSL, "ADSL" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) { BCMA_CORE_ILINE100, "ILine 100" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) { BCMA_CORE_IPSEC, "IPSEC" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) { BCMA_CORE_UTOPIA, "UTOPIA" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) { BCMA_CORE_PCMCIA, "PCMCIA" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) { BCMA_CORE_INTERNAL_MEM, "Internal Memory" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) { BCMA_CORE_MEMC_SDRAM, "MEMC SDRAM" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) { BCMA_CORE_OFDM, "OFDM" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) { BCMA_CORE_EXTIF, "EXTIF" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) { BCMA_CORE_80211, "IEEE 802.11" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) { BCMA_CORE_PHY_A, "PHY A" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) { BCMA_CORE_PHY_B, "PHY B" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) { BCMA_CORE_PHY_G, "PHY G" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) { BCMA_CORE_USB11_HOST, "USB 1.1 Host" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) { BCMA_CORE_USB11_DEV, "USB 1.1 Device" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) { BCMA_CORE_USB20_HOST, "USB 2.0 Host" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) { BCMA_CORE_USB20_DEV, "USB 2.0 Device" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) { BCMA_CORE_SDIO_HOST, "SDIO Host" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) { BCMA_CORE_ROBOSWITCH, "Roboswitch" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) { BCMA_CORE_PARA_ATA, "PATA" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) { BCMA_CORE_SATA_XORDMA, "SATA XOR-DMA" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) { BCMA_CORE_ETHERNET_GBIT, "GBit Ethernet" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) { BCMA_CORE_PCIE, "PCIe" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) { BCMA_CORE_PHY_N, "PHY N" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) { BCMA_CORE_SRAM_CTL, "SRAM Controller" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) { BCMA_CORE_MINI_MACPHY, "Mini MACPHY" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) { BCMA_CORE_PHY_LP, "PHY LP" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) { BCMA_CORE_PMU, "PMU" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) { BCMA_CORE_PHY_SSN, "PHY SSN" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) { BCMA_CORE_SDIO_DEV, "SDIO Device" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) { BCMA_CORE_PHY_HT, "PHY HT" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) { BCMA_CORE_MAC_GBIT, "GBit MAC" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) { BCMA_CORE_DDR12_MEM_CTL, "DDR1/DDR2 Memory Controller" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) { BCMA_CORE_PCIE_RC, "PCIe Root Complex" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) { BCMA_CORE_OCP_OCP_BRIDGE, "OCP to OCP Bridge" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) { BCMA_CORE_SHARED_COMMON, "Common Shared" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) { BCMA_CORE_OCP_AHB_BRIDGE, "OCP to AHB Bridge" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) { BCMA_CORE_SPI_HOST, "SPI Host" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) { BCMA_CORE_I2S, "I2S" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) { BCMA_CORE_SDR_DDR1_MEM_CTL, "SDR/DDR1 Memory Controller" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) { BCMA_CORE_SHIM, "SHIM" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) { BCMA_CORE_PCIE2, "PCIe Gen2" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) { BCMA_CORE_ARM_CR4, "ARM CR4" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) { BCMA_CORE_GCI, "GCI" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) { BCMA_CORE_CMEM, "CNDS DDR2/3 memory controller" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) { BCMA_CORE_ARM_CA7, "ARM CA7" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) { BCMA_CORE_DEFAULT, "Default" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) static const struct bcma_device_id_name bcma_mips_device_names[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) { BCMA_CORE_MIPS, "MIPS" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) { BCMA_CORE_MIPS_3302, "MIPS 3302" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) { BCMA_CORE_MIPS_74K, "MIPS 74K" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) static const char *bcma_device_name(const struct bcma_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) const struct bcma_device_id_name *names;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) int size, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) /* search manufacturer specific names */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) switch (id->manuf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) case BCMA_MANUF_ARM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) names = bcma_arm_device_names;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) size = ARRAY_SIZE(bcma_arm_device_names);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) case BCMA_MANUF_BCM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) names = bcma_bcm_device_names;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) size = ARRAY_SIZE(bcma_bcm_device_names);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) case BCMA_MANUF_MIPS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) names = bcma_mips_device_names;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) size = ARRAY_SIZE(bcma_mips_device_names);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) return "UNKNOWN";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) for (i = 0; i < size; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (names[i].id == id->id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return names[i].name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) return "UNKNOWN";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) static u32 bcma_scan_read32(struct bcma_bus *bus, u8 current_coreidx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) u16 offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) return readl(bus->mmio + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static void bcma_scan_switch_core(struct bcma_bus *bus, u32 addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (bus->hosttype == BCMA_HOSTTYPE_PCI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) pci_write_config_dword(bus->host_pci, BCMA_PCI_BAR0_WIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) static u32 bcma_erom_get_ent(struct bcma_bus *bus, u32 __iomem **eromptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) u32 ent = readl(*eromptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) (*eromptr)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) return ent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static void bcma_erom_push_ent(u32 __iomem **eromptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) (*eromptr)--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) static s32 bcma_erom_get_ci(struct bcma_bus *bus, u32 __iomem **eromptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) u32 ent = bcma_erom_get_ent(bus, eromptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (!(ent & SCAN_ER_VALID))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) if ((ent & SCAN_ER_TAG) != SCAN_ER_TAG_CI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) return ent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) static bool bcma_erom_is_end(struct bcma_bus *bus, u32 __iomem **eromptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) u32 ent = bcma_erom_get_ent(bus, eromptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) bcma_erom_push_ent(eromptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) return (ent == (SCAN_ER_TAG_END | SCAN_ER_VALID));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) static bool bcma_erom_is_bridge(struct bcma_bus *bus, u32 __iomem **eromptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) u32 ent = bcma_erom_get_ent(bus, eromptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) bcma_erom_push_ent(eromptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return (((ent & SCAN_ER_VALID)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) ((ent & SCAN_ER_TAGX) == SCAN_ER_TAG_ADDR) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) ((ent & SCAN_ADDR_TYPE) == SCAN_ADDR_TYPE_BRIDGE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) static void bcma_erom_skip_component(struct bcma_bus *bus, u32 __iomem **eromptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) u32 ent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) ent = bcma_erom_get_ent(bus, eromptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if ((ent & SCAN_ER_VALID) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) ((ent & SCAN_ER_TAG) == SCAN_ER_TAG_CI))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (ent == (SCAN_ER_TAG_END | SCAN_ER_VALID))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) bcma_erom_push_ent(eromptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) static s32 bcma_erom_get_mst_port(struct bcma_bus *bus, u32 __iomem **eromptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) u32 ent = bcma_erom_get_ent(bus, eromptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (!(ent & SCAN_ER_VALID))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if ((ent & SCAN_ER_TAG) != SCAN_ER_TAG_MP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) return ent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) static u32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 __iomem **eromptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) u32 type, u8 port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) u32 addrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) u32 size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) u32 ent = bcma_erom_get_ent(bus, eromptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if ((!(ent & SCAN_ER_VALID)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) ((ent & SCAN_ER_TAGX) != SCAN_ER_TAG_ADDR) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) ((ent & SCAN_ADDR_TYPE) != type) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) (((ent & SCAN_ADDR_PORT) >> SCAN_ADDR_PORT_SHIFT) != port)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) bcma_erom_push_ent(eromptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return (u32)-EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) addrl = ent & SCAN_ADDR_ADDR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) if (ent & SCAN_ADDR_AG32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) bcma_erom_get_ent(bus, eromptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) if ((ent & SCAN_ADDR_SZ) == SCAN_ADDR_SZ_SZD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) size = bcma_erom_get_ent(bus, eromptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) if (size & SCAN_SIZE_SG32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) bcma_erom_get_ent(bus, eromptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) return addrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) static struct bcma_device *bcma_find_core_by_index(struct bcma_bus *bus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) u16 index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) struct bcma_device *core;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) list_for_each_entry(core, &bus->cores, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if (core->core_index == index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) return core;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) static struct bcma_device *bcma_find_core_reverse(struct bcma_bus *bus, u16 coreid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) struct bcma_device *core;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) list_for_each_entry_reverse(core, &bus->cores, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if (core->id.id == coreid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) return core;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) #define IS_ERR_VALUE_U32(x) ((x) >= (u32)-MAX_ERRNO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) struct bcma_device_id *match, int core_num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) struct bcma_device *core)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) u32 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) u8 i, j, k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) s32 cia, cib;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) u8 ports[2], wrappers[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) /* get CIs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) cia = bcma_erom_get_ci(bus, eromptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) if (cia < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) bcma_erom_push_ent(eromptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (bcma_erom_is_end(bus, eromptr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) return -ESPIPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) return -EILSEQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) cib = bcma_erom_get_ci(bus, eromptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) if (cib < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) return -EILSEQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) /* parse CIs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) core->id.class = (cia & SCAN_CIA_CLASS) >> SCAN_CIA_CLASS_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) core->id.id = (cia & SCAN_CIA_ID) >> SCAN_CIA_ID_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) core->id.manuf = (cia & SCAN_CIA_MANUF) >> SCAN_CIA_MANUF_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) ports[0] = (cib & SCAN_CIB_NMP) >> SCAN_CIB_NMP_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) ports[1] = (cib & SCAN_CIB_NSP) >> SCAN_CIB_NSP_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) wrappers[0] = (cib & SCAN_CIB_NMW) >> SCAN_CIB_NMW_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) wrappers[1] = (cib & SCAN_CIB_NSW) >> SCAN_CIB_NSW_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) core->id.rev = (cib & SCAN_CIB_REV) >> SCAN_CIB_REV_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) if (((core->id.manuf == BCMA_MANUF_ARM) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) (core->id.id == 0xFFF)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) (ports[1] == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) bcma_erom_skip_component(bus, eromptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) /* check if component is a core at all */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (wrappers[0] + wrappers[1] == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) /* Some specific cores don't need wrappers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) switch (core->id.id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) case BCMA_CORE_4706_MAC_GBIT_COMMON:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) case BCMA_CORE_NS_CHIPCOMMON_B:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) case BCMA_CORE_PMU:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) case BCMA_CORE_GCI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) /* Not used yet: case BCMA_CORE_OOB_ROUTER: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) bcma_erom_skip_component(bus, eromptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) if (bcma_erom_is_bridge(bus, eromptr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) bcma_erom_skip_component(bus, eromptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (bcma_find_core_by_index(bus, core_num)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) bcma_erom_skip_component(bus, eromptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) if (match && ((match->manuf != BCMA_ANY_MANUF &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) match->manuf != core->id.manuf) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) (match->id != BCMA_ANY_ID && match->id != core->id.id) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) (match->rev != BCMA_ANY_REV && match->rev != core->id.rev) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) (match->class != BCMA_ANY_CLASS && match->class != core->id.class)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) )) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) bcma_erom_skip_component(bus, eromptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) /* get & parse master ports */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) for (i = 0; i < ports[0]; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) s32 mst_port_d = bcma_erom_get_mst_port(bus, eromptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if (mst_port_d < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) return -EILSEQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) /* First Slave Address Descriptor should be port 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * the main register space for the core
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) tmp = bcma_erom_get_addr_desc(bus, eromptr, SCAN_ADDR_TYPE_SLAVE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) if (tmp == 0 || IS_ERR_VALUE_U32(tmp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) /* Try again to see if it is a bridge */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) tmp = bcma_erom_get_addr_desc(bus, eromptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) SCAN_ADDR_TYPE_BRIDGE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (tmp == 0 || IS_ERR_VALUE_U32(tmp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) return -EILSEQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) bcma_info(bus, "Bridge found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) core->addr = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) /* get & parse slave ports */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) k = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) for (i = 0; i < ports[1]; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) for (j = 0; ; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) tmp = bcma_erom_get_addr_desc(bus, eromptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) SCAN_ADDR_TYPE_SLAVE, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) if (IS_ERR_VALUE_U32(tmp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) /* no more entries for port _i_ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) /* pr_debug("erom: slave port %d "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) * "has %d descriptors\n", i, j); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) } else if (k < ARRAY_SIZE(core->addr_s)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) core->addr_s[k] = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) k++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) /* get & parse master wrappers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) for (i = 0; i < wrappers[0]; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) for (j = 0; ; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) tmp = bcma_erom_get_addr_desc(bus, eromptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) SCAN_ADDR_TYPE_MWRAP, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (IS_ERR_VALUE_U32(tmp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) /* no more entries for port _i_ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) /* pr_debug("erom: master wrapper %d "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) * "has %d descriptors\n", i, j); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) if (i == 0 && j == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) core->wrap = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) /* get & parse slave wrappers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) for (i = 0; i < wrappers[1]; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) u8 hack = (ports[1] == 1) ? 0 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) for (j = 0; ; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) tmp = bcma_erom_get_addr_desc(bus, eromptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) SCAN_ADDR_TYPE_SWRAP, i + hack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) if (IS_ERR_VALUE_U32(tmp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) /* no more entries for port _i_ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) /* pr_debug("erom: master wrapper %d "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) * has %d descriptors\n", i, j); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if (wrappers[0] == 0 && !i && !j)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) core->wrap = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) core->io_addr = ioremap(core->addr, BCMA_CORE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) if (!core->io_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) if (core->wrap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) core->io_wrap = ioremap(core->wrap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) BCMA_CORE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) if (!core->io_wrap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) iounmap(core->io_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) void bcma_detect_chip(struct bcma_bus *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) s32 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) struct bcma_chipinfo *chipinfo = &(bus->chipinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) char chip_id[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) bcma_scan_switch_core(bus, BCMA_ADDR_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) tmp = bcma_scan_read32(bus, 0, BCMA_CC_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) chipinfo->id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) chipinfo->rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) chipinfo->pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) snprintf(chip_id, ARRAY_SIZE(chip_id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) (chipinfo->id > 0x9999) ? "%d" : "0x%04X", chipinfo->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) bcma_info(bus, "Found chip with id %s, rev 0x%02X and package 0x%02X\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) chip_id, chipinfo->rev, chipinfo->pkg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) int bcma_bus_scan(struct bcma_bus *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) u32 erombase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) u32 __iomem *eromptr, *eromend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) int err, core_num = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) /* Skip if bus was already scanned (e.g. during early register) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) if (bus->nr_cores)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) eromptr = ioremap(erombase, BCMA_CORE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) if (!eromptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) eromptr = bus->mmio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) bcma_scan_switch_core(bus, erombase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) while (eromptr < eromend) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) struct bcma_device *other_core;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) struct bcma_device *core = kzalloc(sizeof(*core), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) if (!core) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) INIT_LIST_HEAD(&core->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) core->bus = bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) err = bcma_get_next_core(bus, &eromptr, NULL, core_num, core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) kfree(core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) if (err == -ENODEV) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) core_num++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) } else if (err == -ENXIO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) } else if (err == -ESPIPE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) core->core_index = core_num++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) bus->nr_cores++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) other_core = bcma_find_core_reverse(bus, core->id.id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) core->core_unit = (other_core == NULL) ? 0 : other_core->core_unit + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) bcma_prepare_core(bus, core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) bcma_info(bus, "Core %d found: %s (manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) core->core_index, bcma_device_name(&core->id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) core->id.manuf, core->id.id, core->id.rev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) core->id.class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) list_add_tail(&core->list, &bus->cores);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) if (bus->hosttype == BCMA_HOSTTYPE_SOC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) iounmap(eromptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) }