LCOV - code coverage report
Current view: top level - drivers/bcma - scan.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 205 0.0 %
Date: 2022-03-28 16:04:14 Functions: 0 4 0.0 %
Branches: 0 158 0.0 %

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

Generated by: LCOV version 1.14