LCOV - code coverage report
Current view: top level - drivers/ssb - pci.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 617 0.0 %
Date: 2022-04-01 14:35:51 Functions: 0 25 0.0 %
Branches: 0 244 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Sonics Silicon Backplane PCI-Hostbus related functions.
       3                 :            :  *
       4                 :            :  * Copyright (C) 2005-2006 Michael Buesch <m@bues.ch>
       5                 :            :  * Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
       6                 :            :  * Copyright (C) 2005 Stefano Brivio <st3@riseup.net>
       7                 :            :  * Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
       8                 :            :  * Copyright (C) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
       9                 :            :  *
      10                 :            :  * Derived from the Broadcom 4400 device driver.
      11                 :            :  * Copyright (C) 2002 David S. Miller (davem@redhat.com)
      12                 :            :  * Fixed by Pekka Pietikainen (pp@ee.oulu.fi)
      13                 :            :  * Copyright (C) 2006 Broadcom Corporation.
      14                 :            :  *
      15                 :            :  * Licensed under the GNU/GPL. See COPYING for details.
      16                 :            :  */
      17                 :            : 
      18                 :            : #include "ssb_private.h"
      19                 :            : 
      20                 :            : #include <linux/ssb/ssb.h>
      21                 :            : #include <linux/ssb/ssb_regs.h>
      22                 :            : #include <linux/slab.h>
      23                 :            : #include <linux/pci.h>
      24                 :            : #include <linux/delay.h>
      25                 :            : 
      26                 :            : #define DPRINT(fmt, ...) do { printk(KERN_INFO "[%s] "fmt"\n", \
      27                 :            :                 __FUNCTION__, ##__VA_ARGS__); } while (0)
      28                 :            : 
      29                 :            : /* Define the following to 1 to enable a printk on each coreswitch. */
      30                 :            : #define SSB_VERBOSE_PCICORESWITCH_DEBUG         0
      31                 :            : 
      32                 :            : 
      33                 :            : /* Lowlevel coreswitching */
      34                 :          0 : int ssb_pci_switch_coreidx(struct ssb_bus *bus, u8 coreidx)
      35                 :            : {
      36                 :          0 :         int err;
      37                 :          0 :         int attempts = 0;
      38                 :          0 :         u32 cur_core;
      39                 :            : 
      40                 :          0 :         while (1) {
      41                 :          0 :                 err = pci_write_config_dword(bus->host_pci, SSB_BAR0_WIN,
      42                 :          0 :                                              (coreidx * SSB_CORE_SIZE)
      43                 :            :                                              + SSB_ENUM_BASE);
      44         [ #  # ]:          0 :                 if (err)
      45                 :          0 :                         goto error;
      46                 :          0 :                 err = pci_read_config_dword(bus->host_pci, SSB_BAR0_WIN,
      47                 :            :                                             &cur_core);
      48         [ #  # ]:          0 :                 if (err)
      49                 :          0 :                         goto error;
      50                 :          0 :                 cur_core = (cur_core - SSB_ENUM_BASE)
      51                 :          0 :                            / SSB_CORE_SIZE;
      52         [ #  # ]:          0 :                 if (cur_core == coreidx)
      53                 :            :                         break;
      54                 :            : 
      55         [ #  # ]:          0 :                 if (attempts++ > SSB_BAR0_MAX_RETRIES)
      56                 :          0 :                         goto error;
      57                 :          0 :                 udelay(10);
      58                 :            :         }
      59                 :            :         return 0;
      60                 :          0 : error:
      61                 :          0 :         pr_err("Failed to switch to core %u\n", coreidx);
      62                 :          0 :         return -ENODEV;
      63                 :            : }
      64                 :            : 
      65                 :          0 : int ssb_pci_switch_core(struct ssb_bus *bus,
      66                 :            :                         struct ssb_device *dev)
      67                 :            : {
      68                 :          0 :         int err;
      69                 :          0 :         unsigned long flags;
      70                 :            : 
      71                 :            : #if SSB_VERBOSE_PCICORESWITCH_DEBUG
      72                 :            :         pr_info("Switching to %s core, index %d\n",
      73                 :            :                 ssb_core_name(dev->id.coreid), dev->core_index);
      74                 :            : #endif
      75                 :            : 
      76                 :          0 :         spin_lock_irqsave(&bus->bar_lock, flags);
      77                 :          0 :         err = ssb_pci_switch_coreidx(bus, dev->core_index);
      78         [ #  # ]:          0 :         if (!err)
      79                 :          0 :                 bus->mapped_device = dev;
      80                 :          0 :         spin_unlock_irqrestore(&bus->bar_lock, flags);
      81                 :            : 
      82                 :          0 :         return err;
      83                 :            : }
      84                 :            : 
      85                 :            : /* Enable/disable the on board crystal oscillator and/or PLL. */
      86                 :          0 : int ssb_pci_xtal(struct ssb_bus *bus, u32 what, int turn_on)
      87                 :            : {
      88                 :          0 :         int err;
      89                 :          0 :         u32 in, out, outenable;
      90                 :          0 :         u16 pci_status;
      91                 :            : 
      92         [ #  # ]:          0 :         if (bus->bustype != SSB_BUSTYPE_PCI)
      93                 :            :                 return 0;
      94                 :            : 
      95                 :          0 :         err = pci_read_config_dword(bus->host_pci, SSB_GPIO_IN, &in);
      96         [ #  # ]:          0 :         if (err)
      97                 :          0 :                 goto err_pci;
      98                 :          0 :         err = pci_read_config_dword(bus->host_pci, SSB_GPIO_OUT, &out);
      99         [ #  # ]:          0 :         if (err)
     100                 :          0 :                 goto err_pci;
     101                 :          0 :         err = pci_read_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE, &outenable);
     102         [ #  # ]:          0 :         if (err)
     103                 :          0 :                 goto err_pci;
     104                 :            : 
     105                 :          0 :         outenable |= what;
     106                 :            : 
     107         [ #  # ]:          0 :         if (turn_on) {
     108                 :            :                 /* Avoid glitching the clock if GPRS is already using it.
     109                 :            :                  * We can't actually read the state of the PLLPD so we infer it
     110                 :            :                  * by the value of XTAL_PU which *is* readable via gpioin.
     111                 :            :                  */
     112         [ #  # ]:          0 :                 if (!(in & SSB_GPIO_XTAL)) {
     113         [ #  # ]:          0 :                         if (what & SSB_GPIO_XTAL) {
     114                 :            :                                 /* Turn the crystal on */
     115                 :          0 :                                 out |= SSB_GPIO_XTAL;
     116         [ #  # ]:          0 :                                 if (what & SSB_GPIO_PLL)
     117                 :          0 :                                         out |= SSB_GPIO_PLL;
     118                 :          0 :                                 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out);
     119         [ #  # ]:          0 :                                 if (err)
     120                 :          0 :                                         goto err_pci;
     121                 :          0 :                                 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE,
     122                 :            :                                                              outenable);
     123         [ #  # ]:          0 :                                 if (err)
     124                 :          0 :                                         goto err_pci;
     125                 :          0 :                                 msleep(1);
     126                 :            :                         }
     127         [ #  # ]:          0 :                         if (what & SSB_GPIO_PLL) {
     128                 :            :                                 /* Turn the PLL on */
     129                 :          0 :                                 out &= ~SSB_GPIO_PLL;
     130                 :          0 :                                 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out);
     131         [ #  # ]:          0 :                                 if (err)
     132                 :          0 :                                         goto err_pci;
     133                 :          0 :                                 msleep(5);
     134                 :            :                         }
     135                 :            :                 }
     136                 :            : 
     137                 :          0 :                 err = pci_read_config_word(bus->host_pci, PCI_STATUS, &pci_status);
     138         [ #  # ]:          0 :                 if (err)
     139                 :          0 :                         goto err_pci;
     140                 :          0 :                 pci_status &= ~PCI_STATUS_SIG_TARGET_ABORT;
     141                 :          0 :                 err = pci_write_config_word(bus->host_pci, PCI_STATUS, pci_status);
     142         [ #  # ]:          0 :                 if (err)
     143                 :          0 :                         goto err_pci;
     144                 :            :         } else {
     145         [ #  # ]:          0 :                 if (what & SSB_GPIO_XTAL) {
     146                 :            :                         /* Turn the crystal off */
     147                 :          0 :                         out &= ~SSB_GPIO_XTAL;
     148                 :            :                 }
     149         [ #  # ]:          0 :                 if (what & SSB_GPIO_PLL) {
     150                 :            :                         /* Turn the PLL off */
     151                 :          0 :                         out |= SSB_GPIO_PLL;
     152                 :            :                 }
     153                 :          0 :                 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out);
     154         [ #  # ]:          0 :                 if (err)
     155                 :          0 :                         goto err_pci;
     156                 :          0 :                 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE, outenable);
     157         [ #  # ]:          0 :                 if (err)
     158                 :          0 :                         goto err_pci;
     159                 :            :         }
     160                 :            : 
     161                 :          0 : out:
     162                 :            :         return err;
     163                 :            : 
     164                 :          0 : err_pci:
     165                 :          0 :         pr_err("Error: ssb_pci_xtal() could not access PCI config space!\n");
     166                 :          0 :         err = -EBUSY;
     167                 :          0 :         goto out;
     168                 :            : }
     169                 :            : 
     170                 :            : /* Get the word-offset for a SSB_SPROM_XXX define. */
     171                 :            : #define SPOFF(offset)   ((offset) / sizeof(u16))
     172                 :            : /* Helper to extract some _offset, which is one of the SSB_SPROM_XXX defines. */
     173                 :            : #define SPEX16(_outvar, _offset, _mask, _shift) \
     174                 :            :         out->_outvar = ((in[SPOFF(_offset)] & (_mask)) >> (_shift))
     175                 :            : #define SPEX32(_outvar, _offset, _mask, _shift) \
     176                 :            :         out->_outvar = ((((u32)in[SPOFF((_offset)+2)] << 16 | \
     177                 :            :                            in[SPOFF(_offset)]) & (_mask)) >> (_shift))
     178                 :            : #define SPEX(_outvar, _offset, _mask, _shift) \
     179                 :            :         SPEX16(_outvar, _offset, _mask, _shift)
     180                 :            : 
     181                 :            : #define SPEX_ARRAY8(_field, _offset, _mask, _shift)     \
     182                 :            :         do {    \
     183                 :            :                 SPEX(_field[0], _offset +  0, _mask, _shift);   \
     184                 :            :                 SPEX(_field[1], _offset +  2, _mask, _shift);   \
     185                 :            :                 SPEX(_field[2], _offset +  4, _mask, _shift);   \
     186                 :            :                 SPEX(_field[3], _offset +  6, _mask, _shift);   \
     187                 :            :                 SPEX(_field[4], _offset +  8, _mask, _shift);   \
     188                 :            :                 SPEX(_field[5], _offset + 10, _mask, _shift);   \
     189                 :            :                 SPEX(_field[6], _offset + 12, _mask, _shift);   \
     190                 :            :                 SPEX(_field[7], _offset + 14, _mask, _shift);   \
     191                 :            :         } while (0)
     192                 :            : 
     193                 :            : 
     194                 :          0 : static inline u8 ssb_crc8(u8 crc, u8 data)
     195                 :            : {
     196                 :            :         /* Polynomial:   x^8 + x^7 + x^6 + x^4 + x^2 + 1   */
     197                 :          0 :         static const u8 t[] = {
     198                 :            :                 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
     199                 :            :                 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
     200                 :            :                 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
     201                 :            :                 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
     202                 :            :                 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
     203                 :            :                 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
     204                 :            :                 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
     205                 :            :                 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
     206                 :            :                 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
     207                 :            :                 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
     208                 :            :                 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
     209                 :            :                 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
     210                 :            :                 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
     211                 :            :                 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
     212                 :            :                 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
     213                 :            :                 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
     214                 :            :                 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
     215                 :            :                 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
     216                 :            :                 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
     217                 :            :                 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
     218                 :            :                 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
     219                 :            :                 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
     220                 :            :                 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
     221                 :            :                 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
     222                 :            :                 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
     223                 :            :                 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
     224                 :            :                 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
     225                 :            :                 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
     226                 :            :                 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
     227                 :            :                 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
     228                 :            :                 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
     229                 :            :                 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F,
     230                 :            :         };
     231                 :          0 :         return t[crc ^ data];
     232                 :            : }
     233                 :            : 
     234                 :          0 : static void sprom_get_mac(char *mac, const u16 *in)
     235                 :            : {
     236                 :          0 :         int i;
     237   [ #  #  #  #  :          0 :         for (i = 0; i < 3; i++) {
          #  #  #  #  #  
                      # ]
     238                 :          0 :                 *mac++ = in[i] >> 8;
     239                 :          0 :                 *mac++ = in[i];
     240                 :            :         }
     241                 :            : }
     242                 :            : 
     243                 :          0 : static u8 ssb_sprom_crc(const u16 *sprom, u16 size)
     244                 :            : {
     245                 :          0 :         int word;
     246                 :          0 :         u8 crc = 0xFF;
     247                 :            : 
     248         [ #  # ]:          0 :         for (word = 0; word < size - 1; word++) {
     249                 :          0 :                 crc = ssb_crc8(crc, sprom[word] & 0x00FF);
     250                 :          0 :                 crc = ssb_crc8(crc, (sprom[word] & 0xFF00) >> 8);
     251                 :            :         }
     252                 :          0 :         crc = ssb_crc8(crc, sprom[size - 1] & 0x00FF);
     253                 :          0 :         crc ^= 0xFF;
     254                 :            : 
     255                 :          0 :         return crc;
     256                 :            : }
     257                 :            : 
     258                 :          0 : static int sprom_check_crc(const u16 *sprom, size_t size)
     259                 :            : {
     260                 :          0 :         u8 crc;
     261                 :          0 :         u8 expected_crc;
     262                 :          0 :         u16 tmp;
     263                 :            : 
     264                 :          0 :         crc = ssb_sprom_crc(sprom, size);
     265                 :          0 :         tmp = sprom[size - 1] & SSB_SPROM_REVISION_CRC;
     266                 :          0 :         expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT;
     267                 :          0 :         DPRINT("CRC: %x expected: %x", crc, expected_crc);
     268         [ #  # ]:          0 :         if (crc != expected_crc)
     269                 :          0 :                 return -EPROTO;
     270                 :            : 
     271                 :            :         return 0;
     272                 :            : }
     273                 :            : 
     274                 :          0 : static int sprom_do_read(struct ssb_bus *bus, u16 *sprom)
     275                 :            : {
     276                 :          0 :         int i;
     277                 :            : 
     278         [ #  # ]:          0 :         for (i = 0; i < bus->sprom_size; i++)
     279                 :          0 :                 sprom[i] = ioread16(bus->mmio + bus->sprom_offset + (i * 2));
     280                 :            : 
     281                 :          0 :         return 0;
     282                 :            : }
     283                 :            : 
     284                 :          0 : static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom)
     285                 :            : {
     286                 :          0 :         struct pci_dev *pdev = bus->host_pci;
     287                 :          0 :         int i, err;
     288                 :          0 :         u32 spromctl;
     289                 :          0 :         u16 size = bus->sprom_size;
     290                 :            : 
     291                 :          0 :         pr_notice("Writing SPROM. Do NOT turn off the power! Please stand by...\n");
     292                 :          0 :         err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
     293         [ #  # ]:          0 :         if (err)
     294                 :          0 :                 goto err_ctlreg;
     295                 :          0 :         spromctl |= SSB_SPROMCTL_WE;
     296                 :          0 :         err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
     297         [ #  # ]:          0 :         if (err)
     298                 :          0 :                 goto err_ctlreg;
     299                 :          0 :         pr_notice("[ 0%%");
     300                 :          0 :         msleep(500);
     301         [ #  # ]:          0 :         for (i = 0; i < size; i++) {
     302         [ #  # ]:          0 :                 if (i == size / 4)
     303                 :          0 :                         pr_cont("25%%");
     304         [ #  # ]:          0 :                 else if (i == size / 2)
     305                 :          0 :                         pr_cont("50%%");
     306         [ #  # ]:          0 :                 else if (i == (size * 3) / 4)
     307                 :          0 :                         pr_cont("75%%");
     308         [ #  # ]:          0 :                 else if (i % 2)
     309                 :          0 :                         pr_cont(".");
     310                 :          0 :                 writew(sprom[i], bus->mmio + bus->sprom_offset + (i * 2));
     311                 :          0 :                 msleep(20);
     312                 :            :         }
     313                 :          0 :         err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
     314         [ #  # ]:          0 :         if (err)
     315                 :          0 :                 goto err_ctlreg;
     316                 :          0 :         spromctl &= ~SSB_SPROMCTL_WE;
     317                 :          0 :         err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
     318         [ #  # ]:          0 :         if (err)
     319                 :          0 :                 goto err_ctlreg;
     320                 :          0 :         msleep(500);
     321                 :          0 :         pr_cont("100%% ]\n");
     322                 :          0 :         pr_notice("SPROM written\n");
     323                 :            : 
     324                 :          0 :         return 0;
     325                 :          0 : err_ctlreg:
     326                 :          0 :         pr_err("Could not access SPROM control register.\n");
     327                 :          0 :         return err;
     328                 :            : }
     329                 :            : 
     330                 :          0 : static s8 sprom_extract_antgain(u8 sprom_revision, const u16 *in, u16 offset,
     331                 :            :                                 u16 mask, u16 shift)
     332                 :            : {
     333                 :          0 :         u16 v;
     334                 :          0 :         u8 gain;
     335                 :            : 
     336                 :          0 :         v = in[SPOFF(offset)];
     337                 :          0 :         gain = (v & mask) >> shift;
     338                 :          0 :         if (gain == 0xFF)
     339                 :          0 :                 gain = 2; /* If unset use 2dBm */
     340   [ #  #  #  #  :          0 :         if (sprom_revision == 1) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
     341                 :            :                 /* Convert to Q5.2 */
     342                 :          0 :                 gain <<= 2;
     343                 :            :         } else {
     344                 :            :                 /* Q5.2 Fractional part is stored in 0xC0 */
     345                 :          0 :                 gain = ((gain & 0xC0) >> 6) | ((gain & 0x3F) << 2);
     346                 :            :         }
     347                 :            : 
     348                 :          0 :         return (s8)gain;
     349                 :            : }
     350                 :            : 
     351                 :          0 : static void sprom_extract_r23(struct ssb_sprom *out, const u16 *in)
     352                 :            : {
     353                 :          0 :         SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0);
     354                 :          0 :         SPEX(opo, SSB_SPROM2_OPO, SSB_SPROM2_OPO_VALUE, 0);
     355                 :          0 :         SPEX(pa1lob0, SSB_SPROM2_PA1LOB0, 0xFFFF, 0);
     356                 :          0 :         SPEX(pa1lob1, SSB_SPROM2_PA1LOB1, 0xFFFF, 0);
     357                 :          0 :         SPEX(pa1lob2, SSB_SPROM2_PA1LOB2, 0xFFFF, 0);
     358                 :          0 :         SPEX(pa1hib0, SSB_SPROM2_PA1HIB0, 0xFFFF, 0);
     359                 :          0 :         SPEX(pa1hib1, SSB_SPROM2_PA1HIB1, 0xFFFF, 0);
     360                 :          0 :         SPEX(pa1hib2, SSB_SPROM2_PA1HIB2, 0xFFFF, 0);
     361                 :          0 :         SPEX(maxpwr_ah, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_HI, 0);
     362                 :          0 :         SPEX(maxpwr_al, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_LO,
     363                 :            :              SSB_SPROM2_MAXP_A_LO_SHIFT);
     364                 :          0 : }
     365                 :            : 
     366                 :          0 : static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
     367                 :            : {
     368                 :          0 :         u16 loc[3];
     369                 :            : 
     370         [ #  # ]:          0 :         if (out->revision == 3)                      /* rev 3 moved MAC */
     371                 :            :                 loc[0] = SSB_SPROM3_IL0MAC;
     372                 :            :         else {
     373                 :          0 :                 loc[0] = SSB_SPROM1_IL0MAC;
     374                 :          0 :                 loc[1] = SSB_SPROM1_ET0MAC;
     375                 :          0 :                 loc[2] = SSB_SPROM1_ET1MAC;
     376                 :            :         }
     377                 :          0 :         sprom_get_mac(out->il0mac, &in[SPOFF(loc[0])]);
     378         [ #  # ]:          0 :         if (out->revision < 3) {  /* only rev 1-2 have et0, et1 */
     379                 :          0 :                 sprom_get_mac(out->et0mac, &in[SPOFF(loc[1])]);
     380                 :          0 :                 sprom_get_mac(out->et1mac, &in[SPOFF(loc[2])]);
     381                 :            :         }
     382                 :          0 :         SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0);
     383                 :          0 :         SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A,
     384                 :            :              SSB_SPROM1_ETHPHY_ET1A_SHIFT);
     385                 :          0 :         SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14);
     386                 :          0 :         SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15);
     387                 :          0 :         SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0);
     388                 :          0 :         SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0);
     389         [ #  # ]:          0 :         if (out->revision == 1)
     390                 :          0 :                 SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
     391                 :            :                      SSB_SPROM1_BINF_CCODE_SHIFT);
     392                 :          0 :         SPEX(ant_available_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA,
     393                 :            :              SSB_SPROM1_BINF_ANTA_SHIFT);
     394                 :          0 :         SPEX(ant_available_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG,
     395                 :            :              SSB_SPROM1_BINF_ANTBG_SHIFT);
     396                 :          0 :         SPEX(pa0b0, SSB_SPROM1_PA0B0, 0xFFFF, 0);
     397                 :          0 :         SPEX(pa0b1, SSB_SPROM1_PA0B1, 0xFFFF, 0);
     398                 :          0 :         SPEX(pa0b2, SSB_SPROM1_PA0B2, 0xFFFF, 0);
     399                 :          0 :         SPEX(pa1b0, SSB_SPROM1_PA1B0, 0xFFFF, 0);
     400                 :          0 :         SPEX(pa1b1, SSB_SPROM1_PA1B1, 0xFFFF, 0);
     401                 :          0 :         SPEX(pa1b2, SSB_SPROM1_PA1B2, 0xFFFF, 0);
     402                 :          0 :         SPEX(gpio0, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P0, 0);
     403                 :          0 :         SPEX(gpio1, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P1,
     404                 :            :              SSB_SPROM1_GPIOA_P1_SHIFT);
     405                 :          0 :         SPEX(gpio2, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P2, 0);
     406                 :          0 :         SPEX(gpio3, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P3,
     407                 :            :              SSB_SPROM1_GPIOB_P3_SHIFT);
     408                 :          0 :         SPEX(maxpwr_a, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_A,
     409                 :            :              SSB_SPROM1_MAXPWR_A_SHIFT);
     410                 :          0 :         SPEX(maxpwr_bg, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_BG, 0);
     411                 :          0 :         SPEX(itssi_a, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_A,
     412                 :            :              SSB_SPROM1_ITSSI_A_SHIFT);
     413                 :          0 :         SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0);
     414                 :          0 :         SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0);
     415                 :            : 
     416                 :          0 :         SPEX(alpha2[0], SSB_SPROM1_CCODE, 0xff00, 8);
     417                 :          0 :         SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0);
     418                 :            : 
     419                 :            :         /* Extract the antenna gain values. */
     420         [ #  # ]:          0 :         out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in,
     421                 :            :                                                      SSB_SPROM1_AGAIN,
     422                 :            :                                                      SSB_SPROM1_AGAIN_BG,
     423                 :            :                                                      SSB_SPROM1_AGAIN_BG_SHIFT);
     424         [ #  # ]:          0 :         out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in,
     425                 :            :                                                      SSB_SPROM1_AGAIN,
     426                 :            :                                                      SSB_SPROM1_AGAIN_A,
     427                 :            :                                                      SSB_SPROM1_AGAIN_A_SHIFT);
     428         [ #  # ]:          0 :         if (out->revision >= 2)
     429                 :          0 :                 sprom_extract_r23(out, in);
     430                 :          0 : }
     431                 :            : 
     432                 :            : /* Revs 4 5 and 8 have partially shared layout */
     433                 :          0 : static void sprom_extract_r458(struct ssb_sprom *out, const u16 *in)
     434                 :            : {
     435                 :          0 :         SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01,
     436                 :            :              SSB_SPROM4_TXPID2G0, SSB_SPROM4_TXPID2G0_SHIFT);
     437                 :          0 :         SPEX(txpid2g[1], SSB_SPROM4_TXPID2G01,
     438                 :            :              SSB_SPROM4_TXPID2G1, SSB_SPROM4_TXPID2G1_SHIFT);
     439                 :          0 :         SPEX(txpid2g[2], SSB_SPROM4_TXPID2G23,
     440                 :            :              SSB_SPROM4_TXPID2G2, SSB_SPROM4_TXPID2G2_SHIFT);
     441                 :          0 :         SPEX(txpid2g[3], SSB_SPROM4_TXPID2G23,
     442                 :            :              SSB_SPROM4_TXPID2G3, SSB_SPROM4_TXPID2G3_SHIFT);
     443                 :            : 
     444                 :          0 :         SPEX(txpid5gl[0], SSB_SPROM4_TXPID5GL01,
     445                 :            :              SSB_SPROM4_TXPID5GL0, SSB_SPROM4_TXPID5GL0_SHIFT);
     446                 :          0 :         SPEX(txpid5gl[1], SSB_SPROM4_TXPID5GL01,
     447                 :            :              SSB_SPROM4_TXPID5GL1, SSB_SPROM4_TXPID5GL1_SHIFT);
     448                 :          0 :         SPEX(txpid5gl[2], SSB_SPROM4_TXPID5GL23,
     449                 :            :              SSB_SPROM4_TXPID5GL2, SSB_SPROM4_TXPID5GL2_SHIFT);
     450                 :          0 :         SPEX(txpid5gl[3], SSB_SPROM4_TXPID5GL23,
     451                 :            :              SSB_SPROM4_TXPID5GL3, SSB_SPROM4_TXPID5GL3_SHIFT);
     452                 :            : 
     453                 :          0 :         SPEX(txpid5g[0], SSB_SPROM4_TXPID5G01,
     454                 :            :              SSB_SPROM4_TXPID5G0, SSB_SPROM4_TXPID5G0_SHIFT);
     455                 :          0 :         SPEX(txpid5g[1], SSB_SPROM4_TXPID5G01,
     456                 :            :              SSB_SPROM4_TXPID5G1, SSB_SPROM4_TXPID5G1_SHIFT);
     457                 :          0 :         SPEX(txpid5g[2], SSB_SPROM4_TXPID5G23,
     458                 :            :              SSB_SPROM4_TXPID5G2, SSB_SPROM4_TXPID5G2_SHIFT);
     459                 :          0 :         SPEX(txpid5g[3], SSB_SPROM4_TXPID5G23,
     460                 :            :              SSB_SPROM4_TXPID5G3, SSB_SPROM4_TXPID5G3_SHIFT);
     461                 :            : 
     462                 :          0 :         SPEX(txpid5gh[0], SSB_SPROM4_TXPID5GH01,
     463                 :            :              SSB_SPROM4_TXPID5GH0, SSB_SPROM4_TXPID5GH0_SHIFT);
     464                 :          0 :         SPEX(txpid5gh[1], SSB_SPROM4_TXPID5GH01,
     465                 :            :              SSB_SPROM4_TXPID5GH1, SSB_SPROM4_TXPID5GH1_SHIFT);
     466                 :          0 :         SPEX(txpid5gh[2], SSB_SPROM4_TXPID5GH23,
     467                 :            :              SSB_SPROM4_TXPID5GH2, SSB_SPROM4_TXPID5GH2_SHIFT);
     468                 :          0 :         SPEX(txpid5gh[3], SSB_SPROM4_TXPID5GH23,
     469                 :            :              SSB_SPROM4_TXPID5GH3, SSB_SPROM4_TXPID5GH3_SHIFT);
     470                 :          0 : }
     471                 :            : 
     472                 :          0 : static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in)
     473                 :            : {
     474                 :          0 :         static const u16 pwr_info_offset[] = {
     475                 :            :                 SSB_SPROM4_PWR_INFO_CORE0, SSB_SPROM4_PWR_INFO_CORE1,
     476                 :            :                 SSB_SPROM4_PWR_INFO_CORE2, SSB_SPROM4_PWR_INFO_CORE3
     477                 :            :         };
     478                 :          0 :         u16 il0mac_offset;
     479                 :          0 :         int i;
     480                 :            : 
     481                 :          0 :         BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) !=
     482                 :            :                      ARRAY_SIZE(out->core_pwr_info));
     483                 :            : 
     484         [ #  # ]:          0 :         if (out->revision == 4)
     485                 :            :                 il0mac_offset = SSB_SPROM4_IL0MAC;
     486                 :            :         else
     487                 :          0 :                 il0mac_offset = SSB_SPROM5_IL0MAC;
     488                 :            : 
     489                 :          0 :         sprom_get_mac(out->il0mac, &in[SPOFF(il0mac_offset)]);
     490                 :            : 
     491                 :          0 :         SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0);
     492                 :          0 :         SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A,
     493                 :            :              SSB_SPROM4_ETHPHY_ET1A_SHIFT);
     494                 :          0 :         SPEX(board_rev, SSB_SPROM4_BOARDREV, 0xFFFF, 0);
     495                 :          0 :         SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0);
     496         [ #  # ]:          0 :         if (out->revision == 4) {
     497                 :          0 :                 SPEX(alpha2[0], SSB_SPROM4_CCODE, 0xff00, 8);
     498                 :          0 :                 SPEX(alpha2[1], SSB_SPROM4_CCODE, 0x00ff, 0);
     499                 :          0 :                 SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0);
     500                 :          0 :                 SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0);
     501                 :          0 :                 SPEX(boardflags2_lo, SSB_SPROM4_BFL2LO, 0xFFFF, 0);
     502                 :          0 :                 SPEX(boardflags2_hi, SSB_SPROM4_BFL2HI, 0xFFFF, 0);
     503                 :            :         } else {
     504                 :          0 :                 SPEX(alpha2[0], SSB_SPROM5_CCODE, 0xff00, 8);
     505                 :          0 :                 SPEX(alpha2[1], SSB_SPROM5_CCODE, 0x00ff, 0);
     506                 :          0 :                 SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0);
     507                 :          0 :                 SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0);
     508                 :          0 :                 SPEX(boardflags2_lo, SSB_SPROM5_BFL2LO, 0xFFFF, 0);
     509                 :          0 :                 SPEX(boardflags2_hi, SSB_SPROM5_BFL2HI, 0xFFFF, 0);
     510                 :            :         }
     511                 :          0 :         SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A,
     512                 :            :              SSB_SPROM4_ANTAVAIL_A_SHIFT);
     513                 :          0 :         SPEX(ant_available_bg, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_BG,
     514                 :            :              SSB_SPROM4_ANTAVAIL_BG_SHIFT);
     515                 :          0 :         SPEX(maxpwr_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_MAXP_BG_MASK, 0);
     516                 :          0 :         SPEX(itssi_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_ITSSI_BG,
     517                 :            :              SSB_SPROM4_ITSSI_BG_SHIFT);
     518                 :          0 :         SPEX(maxpwr_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_MAXP_A_MASK, 0);
     519                 :          0 :         SPEX(itssi_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_ITSSI_A,
     520                 :            :              SSB_SPROM4_ITSSI_A_SHIFT);
     521         [ #  # ]:          0 :         if (out->revision == 4) {
     522                 :          0 :                 SPEX(gpio0, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P0, 0);
     523                 :          0 :                 SPEX(gpio1, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P1,
     524                 :            :                      SSB_SPROM4_GPIOA_P1_SHIFT);
     525                 :          0 :                 SPEX(gpio2, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P2, 0);
     526                 :          0 :                 SPEX(gpio3, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P3,
     527                 :            :                      SSB_SPROM4_GPIOB_P3_SHIFT);
     528                 :            :         } else {
     529                 :          0 :                 SPEX(gpio0, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P0, 0);
     530                 :          0 :                 SPEX(gpio1, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P1,
     531                 :            :                      SSB_SPROM5_GPIOA_P1_SHIFT);
     532                 :          0 :                 SPEX(gpio2, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P2, 0);
     533                 :          0 :                 SPEX(gpio3, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P3,
     534                 :            :                      SSB_SPROM5_GPIOB_P3_SHIFT);
     535                 :            :         }
     536                 :            : 
     537                 :            :         /* Extract the antenna gain values. */
     538         [ #  # ]:          0 :         out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in,
     539                 :            :                                                      SSB_SPROM4_AGAIN01,
     540                 :            :                                                      SSB_SPROM4_AGAIN0,
     541                 :            :                                                      SSB_SPROM4_AGAIN0_SHIFT);
     542         [ #  # ]:          0 :         out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in,
     543                 :            :                                                      SSB_SPROM4_AGAIN01,
     544                 :            :                                                      SSB_SPROM4_AGAIN1,
     545                 :            :                                                      SSB_SPROM4_AGAIN1_SHIFT);
     546         [ #  # ]:          0 :         out->antenna_gain.a2 = sprom_extract_antgain(out->revision, in,
     547                 :            :                                                      SSB_SPROM4_AGAIN23,
     548                 :            :                                                      SSB_SPROM4_AGAIN2,
     549                 :            :                                                      SSB_SPROM4_AGAIN2_SHIFT);
     550         [ #  # ]:          0 :         out->antenna_gain.a3 = sprom_extract_antgain(out->revision, in,
     551                 :            :                                                      SSB_SPROM4_AGAIN23,
     552                 :            :                                                      SSB_SPROM4_AGAIN3,
     553                 :            :                                                      SSB_SPROM4_AGAIN3_SHIFT);
     554                 :            : 
     555                 :            :         /* Extract cores power info info */
     556         [ #  # ]:          0 :         for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
     557                 :          0 :                 u16 o = pwr_info_offset[i];
     558                 :            : 
     559                 :          0 :                 SPEX(core_pwr_info[i].itssi_2g, o + SSB_SPROM4_2G_MAXP_ITSSI,
     560                 :            :                         SSB_SPROM4_2G_ITSSI, SSB_SPROM4_2G_ITSSI_SHIFT);
     561                 :          0 :                 SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SPROM4_2G_MAXP_ITSSI,
     562                 :            :                         SSB_SPROM4_2G_MAXP, 0);
     563                 :            : 
     564                 :          0 :                 SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SPROM4_2G_PA_0, ~0, 0);
     565                 :          0 :                 SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SPROM4_2G_PA_1, ~0, 0);
     566                 :          0 :                 SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SPROM4_2G_PA_2, ~0, 0);
     567                 :          0 :                 SPEX(core_pwr_info[i].pa_2g[3], o + SSB_SPROM4_2G_PA_3, ~0, 0);
     568                 :            : 
     569                 :          0 :                 SPEX(core_pwr_info[i].itssi_5g, o + SSB_SPROM4_5G_MAXP_ITSSI,
     570                 :            :                         SSB_SPROM4_5G_ITSSI, SSB_SPROM4_5G_ITSSI_SHIFT);
     571                 :          0 :                 SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SPROM4_5G_MAXP_ITSSI,
     572                 :            :                         SSB_SPROM4_5G_MAXP, 0);
     573                 :          0 :                 SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM4_5GHL_MAXP,
     574                 :            :                         SSB_SPROM4_5GH_MAXP, 0);
     575                 :          0 :                 SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM4_5GHL_MAXP,
     576                 :            :                         SSB_SPROM4_5GL_MAXP, SSB_SPROM4_5GL_MAXP_SHIFT);
     577                 :            : 
     578                 :          0 :                 SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SPROM4_5GL_PA_0, ~0, 0);
     579                 :          0 :                 SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SPROM4_5GL_PA_1, ~0, 0);
     580                 :          0 :                 SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SPROM4_5GL_PA_2, ~0, 0);
     581                 :          0 :                 SPEX(core_pwr_info[i].pa_5gl[3], o + SSB_SPROM4_5GL_PA_3, ~0, 0);
     582                 :          0 :                 SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SPROM4_5G_PA_0, ~0, 0);
     583                 :          0 :                 SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SPROM4_5G_PA_1, ~0, 0);
     584                 :          0 :                 SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SPROM4_5G_PA_2, ~0, 0);
     585                 :          0 :                 SPEX(core_pwr_info[i].pa_5g[3], o + SSB_SPROM4_5G_PA_3, ~0, 0);
     586                 :          0 :                 SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SPROM4_5GH_PA_0, ~0, 0);
     587                 :          0 :                 SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SPROM4_5GH_PA_1, ~0, 0);
     588                 :          0 :                 SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SPROM4_5GH_PA_2, ~0, 0);
     589                 :          0 :                 SPEX(core_pwr_info[i].pa_5gh[3], o + SSB_SPROM4_5GH_PA_3, ~0, 0);
     590                 :            :         }
     591                 :            : 
     592                 :          0 :         sprom_extract_r458(out, in);
     593                 :            : 
     594                 :            :         /* TODO - get remaining rev 4 stuff needed */
     595                 :          0 : }
     596                 :            : 
     597                 :          0 : static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
     598                 :            : {
     599                 :          0 :         int i;
     600                 :          0 :         u16 o;
     601                 :          0 :         static const u16 pwr_info_offset[] = {
     602                 :            :                 SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1,
     603                 :            :                 SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3
     604                 :            :         };
     605                 :          0 :         BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) !=
     606                 :            :                         ARRAY_SIZE(out->core_pwr_info));
     607                 :            : 
     608                 :            :         /* extract the MAC address */
     609                 :          0 :         sprom_get_mac(out->il0mac, &in[SPOFF(SSB_SPROM8_IL0MAC)]);
     610                 :            : 
     611                 :          0 :         SPEX(board_rev, SSB_SPROM8_BOARDREV, 0xFFFF, 0);
     612                 :          0 :         SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0);
     613                 :          0 :         SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8);
     614                 :          0 :         SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0);
     615                 :          0 :         SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0);
     616                 :          0 :         SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0);
     617                 :          0 :         SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, 0xFFFF, 0);
     618                 :          0 :         SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, 0xFFFF, 0);
     619                 :          0 :         SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A,
     620                 :            :              SSB_SPROM8_ANTAVAIL_A_SHIFT);
     621                 :          0 :         SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG,
     622                 :            :              SSB_SPROM8_ANTAVAIL_BG_SHIFT);
     623                 :          0 :         SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0);
     624                 :          0 :         SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG,
     625                 :            :              SSB_SPROM8_ITSSI_BG_SHIFT);
     626                 :          0 :         SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0);
     627                 :          0 :         SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A,
     628                 :            :              SSB_SPROM8_ITSSI_A_SHIFT);
     629                 :          0 :         SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0);
     630                 :          0 :         SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK,
     631                 :            :              SSB_SPROM8_MAXP_AL_SHIFT);
     632                 :          0 :         SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0);
     633                 :          0 :         SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1,
     634                 :            :              SSB_SPROM8_GPIOA_P1_SHIFT);
     635                 :          0 :         SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0);
     636                 :          0 :         SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3,
     637                 :            :              SSB_SPROM8_GPIOB_P3_SHIFT);
     638                 :          0 :         SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0);
     639                 :          0 :         SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G,
     640                 :            :              SSB_SPROM8_TRI5G_SHIFT);
     641                 :          0 :         SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0);
     642                 :          0 :         SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH,
     643                 :            :              SSB_SPROM8_TRI5GH_SHIFT);
     644                 :          0 :         SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G, 0);
     645                 :          0 :         SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G,
     646                 :            :              SSB_SPROM8_RXPO5G_SHIFT);
     647                 :          0 :         SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0);
     648                 :          0 :         SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G,
     649                 :            :              SSB_SPROM8_RSSISMC2G_SHIFT);
     650                 :          0 :         SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G,
     651                 :            :              SSB_SPROM8_RSSISAV2G_SHIFT);
     652                 :          0 :         SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G,
     653                 :            :              SSB_SPROM8_BXA2G_SHIFT);
     654                 :          0 :         SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0);
     655                 :          0 :         SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G,
     656                 :            :              SSB_SPROM8_RSSISMC5G_SHIFT);
     657                 :          0 :         SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G,
     658                 :            :              SSB_SPROM8_RSSISAV5G_SHIFT);
     659                 :          0 :         SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G,
     660                 :            :              SSB_SPROM8_BXA5G_SHIFT);
     661                 :          0 :         SPEX(pa0b0, SSB_SPROM8_PA0B0, 0xFFFF, 0);
     662                 :          0 :         SPEX(pa0b1, SSB_SPROM8_PA0B1, 0xFFFF, 0);
     663                 :          0 :         SPEX(pa0b2, SSB_SPROM8_PA0B2, 0xFFFF, 0);
     664                 :          0 :         SPEX(pa1b0, SSB_SPROM8_PA1B0, 0xFFFF, 0);
     665                 :          0 :         SPEX(pa1b1, SSB_SPROM8_PA1B1, 0xFFFF, 0);
     666                 :          0 :         SPEX(pa1b2, SSB_SPROM8_PA1B2, 0xFFFF, 0);
     667                 :          0 :         SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, 0xFFFF, 0);
     668                 :          0 :         SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, 0xFFFF, 0);
     669                 :          0 :         SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, 0xFFFF, 0);
     670                 :          0 :         SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, 0xFFFF, 0);
     671                 :          0 :         SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, 0xFFFF, 0);
     672                 :          0 :         SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, 0xFFFF, 0);
     673                 :          0 :         SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, 0xFFFF, 0);
     674                 :          0 :         SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, 0xFFFFFFFF, 0);
     675                 :          0 :         SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, 0xFFFFFFFF, 0);
     676                 :          0 :         SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, 0xFFFFFFFF, 0);
     677                 :          0 :         SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0);
     678                 :            : 
     679                 :            :         /* Extract the antenna gain values. */
     680         [ #  # ]:          0 :         out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in,
     681                 :            :                                                      SSB_SPROM8_AGAIN01,
     682                 :            :                                                      SSB_SPROM8_AGAIN0,
     683                 :            :                                                      SSB_SPROM8_AGAIN0_SHIFT);
     684         [ #  # ]:          0 :         out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in,
     685                 :            :                                                      SSB_SPROM8_AGAIN01,
     686                 :            :                                                      SSB_SPROM8_AGAIN1,
     687                 :            :                                                      SSB_SPROM8_AGAIN1_SHIFT);
     688         [ #  # ]:          0 :         out->antenna_gain.a2 = sprom_extract_antgain(out->revision, in,
     689                 :            :                                                      SSB_SPROM8_AGAIN23,
     690                 :            :                                                      SSB_SPROM8_AGAIN2,
     691                 :            :                                                      SSB_SPROM8_AGAIN2_SHIFT);
     692         [ #  # ]:          0 :         out->antenna_gain.a3 = sprom_extract_antgain(out->revision, in,
     693                 :            :                                                      SSB_SPROM8_AGAIN23,
     694                 :            :                                                      SSB_SPROM8_AGAIN3,
     695                 :            :                                                      SSB_SPROM8_AGAIN3_SHIFT);
     696                 :            : 
     697                 :            :         /* Extract cores power info info */
     698         [ #  # ]:          0 :         for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
     699                 :          0 :                 o = pwr_info_offset[i];
     700                 :          0 :                 SPEX(core_pwr_info[i].itssi_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
     701                 :            :                         SSB_SPROM8_2G_ITSSI, SSB_SPROM8_2G_ITSSI_SHIFT);
     702                 :          0 :                 SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
     703                 :            :                         SSB_SPROM8_2G_MAXP, 0);
     704                 :            : 
     705                 :          0 :                 SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SROM8_2G_PA_0, ~0, 0);
     706                 :          0 :                 SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SROM8_2G_PA_1, ~0, 0);
     707                 :          0 :                 SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SROM8_2G_PA_2, ~0, 0);
     708                 :            : 
     709                 :          0 :                 SPEX(core_pwr_info[i].itssi_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
     710                 :            :                         SSB_SPROM8_5G_ITSSI, SSB_SPROM8_5G_ITSSI_SHIFT);
     711                 :          0 :                 SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
     712                 :            :                         SSB_SPROM8_5G_MAXP, 0);
     713                 :          0 :                 SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM8_5GHL_MAXP,
     714                 :            :                         SSB_SPROM8_5GH_MAXP, 0);
     715                 :          0 :                 SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM8_5GHL_MAXP,
     716                 :            :                         SSB_SPROM8_5GL_MAXP, SSB_SPROM8_5GL_MAXP_SHIFT);
     717                 :            : 
     718                 :          0 :                 SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SROM8_5GL_PA_0, ~0, 0);
     719                 :          0 :                 SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SROM8_5GL_PA_1, ~0, 0);
     720                 :          0 :                 SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SROM8_5GL_PA_2, ~0, 0);
     721                 :          0 :                 SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SROM8_5G_PA_0, ~0, 0);
     722                 :          0 :                 SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SROM8_5G_PA_1, ~0, 0);
     723                 :          0 :                 SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SROM8_5G_PA_2, ~0, 0);
     724                 :          0 :                 SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SROM8_5GH_PA_0, ~0, 0);
     725                 :          0 :                 SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SROM8_5GH_PA_1, ~0, 0);
     726                 :          0 :                 SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SROM8_5GH_PA_2, ~0, 0);
     727                 :            :         }
     728                 :            : 
     729                 :            :         /* Extract FEM info */
     730                 :          0 :         SPEX(fem.ghz2.tssipos, SSB_SPROM8_FEM2G,
     731                 :            :                 SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT);
     732                 :          0 :         SPEX(fem.ghz2.extpa_gain, SSB_SPROM8_FEM2G,
     733                 :            :                 SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
     734                 :          0 :         SPEX(fem.ghz2.pdet_range, SSB_SPROM8_FEM2G,
     735                 :            :                 SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT);
     736                 :          0 :         SPEX(fem.ghz2.tr_iso, SSB_SPROM8_FEM2G,
     737                 :            :                 SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT);
     738                 :          0 :         SPEX(fem.ghz2.antswlut, SSB_SPROM8_FEM2G,
     739                 :            :                 SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT);
     740                 :            : 
     741                 :          0 :         SPEX(fem.ghz5.tssipos, SSB_SPROM8_FEM5G,
     742                 :            :                 SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT);
     743                 :          0 :         SPEX(fem.ghz5.extpa_gain, SSB_SPROM8_FEM5G,
     744                 :            :                 SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
     745                 :          0 :         SPEX(fem.ghz5.pdet_range, SSB_SPROM8_FEM5G,
     746                 :            :                 SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT);
     747                 :          0 :         SPEX(fem.ghz5.tr_iso, SSB_SPROM8_FEM5G,
     748                 :            :                 SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT);
     749                 :          0 :         SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G,
     750                 :            :                 SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT);
     751                 :            : 
     752                 :          0 :         SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON,
     753                 :            :              SSB_SPROM8_LEDDC_ON_SHIFT);
     754                 :          0 :         SPEX(leddc_off_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_OFF,
     755                 :            :              SSB_SPROM8_LEDDC_OFF_SHIFT);
     756                 :            : 
     757                 :          0 :         SPEX(txchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_TXCHAIN,
     758                 :            :              SSB_SPROM8_TXRXC_TXCHAIN_SHIFT);
     759                 :          0 :         SPEX(rxchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_RXCHAIN,
     760                 :            :              SSB_SPROM8_TXRXC_RXCHAIN_SHIFT);
     761                 :          0 :         SPEX(antswitch, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_SWITCH,
     762                 :            :              SSB_SPROM8_TXRXC_SWITCH_SHIFT);
     763                 :            : 
     764                 :          0 :         SPEX(opo, SSB_SPROM8_OFDM2GPO, 0x00ff, 0);
     765                 :            : 
     766                 :          0 :         SPEX_ARRAY8(mcs2gpo, SSB_SPROM8_2G_MCSPO, ~0, 0);
     767                 :          0 :         SPEX_ARRAY8(mcs5gpo, SSB_SPROM8_5G_MCSPO, ~0, 0);
     768                 :          0 :         SPEX_ARRAY8(mcs5glpo, SSB_SPROM8_5GL_MCSPO, ~0, 0);
     769                 :          0 :         SPEX_ARRAY8(mcs5ghpo, SSB_SPROM8_5GH_MCSPO, ~0, 0);
     770                 :            : 
     771                 :          0 :         SPEX(rawtempsense, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_RAWTEMP,
     772                 :            :              SSB_SPROM8_RAWTS_RAWTEMP_SHIFT);
     773                 :          0 :         SPEX(measpower, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_MEASPOWER,
     774                 :            :              SSB_SPROM8_RAWTS_MEASPOWER_SHIFT);
     775                 :          0 :         SPEX(tempsense_slope, SSB_SPROM8_OPT_CORRX,
     776                 :            :              SSB_SPROM8_OPT_CORRX_TEMP_SLOPE,
     777                 :            :              SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT);
     778                 :          0 :         SPEX(tempcorrx, SSB_SPROM8_OPT_CORRX, SSB_SPROM8_OPT_CORRX_TEMPCORRX,
     779                 :            :              SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT);
     780                 :          0 :         SPEX(tempsense_option, SSB_SPROM8_OPT_CORRX,
     781                 :            :              SSB_SPROM8_OPT_CORRX_TEMP_OPTION,
     782                 :            :              SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT);
     783                 :          0 :         SPEX(freqoffset_corr, SSB_SPROM8_HWIQ_IQSWP,
     784                 :            :              SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR,
     785                 :            :              SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT);
     786                 :          0 :         SPEX(iqcal_swp_dis, SSB_SPROM8_HWIQ_IQSWP,
     787                 :            :              SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP,
     788                 :            :              SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT);
     789                 :          0 :         SPEX(hw_iqcal_en, SSB_SPROM8_HWIQ_IQSWP, SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL,
     790                 :            :              SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT);
     791                 :            : 
     792                 :          0 :         SPEX(bw40po, SSB_SPROM8_BW40PO, ~0, 0);
     793                 :          0 :         SPEX(cddpo, SSB_SPROM8_CDDPO, ~0, 0);
     794                 :          0 :         SPEX(stbcpo, SSB_SPROM8_STBCPO, ~0, 0);
     795                 :          0 :         SPEX(bwduppo, SSB_SPROM8_BWDUPPO, ~0, 0);
     796                 :            : 
     797                 :          0 :         SPEX(tempthresh, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_TRESH,
     798                 :            :              SSB_SPROM8_THERMAL_TRESH_SHIFT);
     799                 :          0 :         SPEX(tempoffset, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_OFFSET,
     800                 :            :              SSB_SPROM8_THERMAL_OFFSET_SHIFT);
     801                 :          0 :         SPEX(phycal_tempdelta, SSB_SPROM8_TEMPDELTA,
     802                 :            :              SSB_SPROM8_TEMPDELTA_PHYCAL,
     803                 :            :              SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT);
     804                 :          0 :         SPEX(temps_period, SSB_SPROM8_TEMPDELTA, SSB_SPROM8_TEMPDELTA_PERIOD,
     805                 :            :              SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT);
     806                 :          0 :         SPEX(temps_hysteresis, SSB_SPROM8_TEMPDELTA,
     807                 :            :              SSB_SPROM8_TEMPDELTA_HYSTERESIS,
     808                 :            :              SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT);
     809                 :          0 :         sprom_extract_r458(out, in);
     810                 :            : 
     811                 :            :         /* TODO - get remaining rev 8 stuff needed */
     812                 :          0 : }
     813                 :            : 
     814                 :          0 : static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
     815                 :            :                          const u16 *in, u16 size)
     816                 :            : {
     817                 :          0 :         memset(out, 0, sizeof(*out));
     818                 :            : 
     819                 :          0 :         out->revision = in[size - 1] & 0x00FF;
     820                 :          0 :         pr_debug("SPROM revision %d detected\n", out->revision);
     821                 :          0 :         memset(out->et0mac, 0xFF, 6);                /* preset et0 and et1 mac */
     822                 :          0 :         memset(out->et1mac, 0xFF, 6);
     823                 :            : 
     824         [ #  # ]:          0 :         if ((bus->chip_id & 0xFF00) == 0x4400) {
     825                 :            :                 /* Workaround: The BCM44XX chip has a stupid revision
     826                 :            :                  * number stored in the SPROM.
     827                 :            :                  * Always extract r1. */
     828                 :          0 :                 out->revision = 1;
     829                 :          0 :                 pr_debug("SPROM treated as revision %d\n", out->revision);
     830                 :            :         }
     831                 :            : 
     832   [ #  #  #  # ]:          0 :         switch (out->revision) {
     833                 :          0 :         case 1:
     834                 :            :         case 2:
     835                 :            :         case 3:
     836                 :          0 :                 sprom_extract_r123(out, in);
     837                 :          0 :                 break;
     838                 :          0 :         case 4:
     839                 :            :         case 5:
     840                 :          0 :                 sprom_extract_r45(out, in);
     841                 :          0 :                 break;
     842                 :          0 :         case 8:
     843                 :          0 :                 sprom_extract_r8(out, in);
     844                 :          0 :                 break;
     845                 :          0 :         default:
     846                 :          0 :                 pr_warn("Unsupported SPROM revision %d detected. Will extract v1\n",
     847                 :            :                         out->revision);
     848                 :          0 :                 out->revision = 1;
     849                 :          0 :                 sprom_extract_r123(out, in);
     850                 :            :         }
     851                 :            : 
     852         [ #  # ]:          0 :         if (out->boardflags_lo == 0xFFFF)
     853                 :          0 :                 out->boardflags_lo = 0;  /* per specs */
     854         [ #  # ]:          0 :         if (out->boardflags_hi == 0xFFFF)
     855                 :          0 :                 out->boardflags_hi = 0;  /* per specs */
     856                 :            : 
     857                 :          0 :         return 0;
     858                 :            : }
     859                 :            : 
     860                 :          0 : static int ssb_pci_sprom_get(struct ssb_bus *bus,
     861                 :            :                              struct ssb_sprom *sprom)
     862                 :            : {
     863                 :          0 :         int err;
     864                 :          0 :         u16 *buf;
     865                 :            : 
     866         [ #  # ]:          0 :         if (!ssb_is_sprom_available(bus)) {
     867                 :          0 :                 pr_err("No SPROM available!\n");
     868                 :          0 :                 return -ENODEV;
     869                 :            :         }
     870         [ #  # ]:          0 :         if (bus->chipco.dev) {       /* can be unavailable! */
     871                 :            :                 /*
     872                 :            :                  * get SPROM offset: SSB_SPROM_BASE1 except for
     873                 :            :                  * chipcommon rev >= 31 or chip ID is 0x4312 and
     874                 :            :                  * chipcommon status & 3 == 2
     875                 :            :                  */
     876         [ #  # ]:          0 :                 if (bus->chipco.dev->id.revision >= 31)
     877                 :          0 :                         bus->sprom_offset = SSB_SPROM_BASE31;
     878         [ #  # ]:          0 :                 else if (bus->chip_id == 0x4312 &&
     879         [ #  # ]:          0 :                          (bus->chipco.status & 0x03) == 2)
     880                 :          0 :                         bus->sprom_offset = SSB_SPROM_BASE31;
     881                 :            :                 else
     882                 :          0 :                         bus->sprom_offset = SSB_SPROM_BASE1;
     883                 :            :         } else {
     884                 :          0 :                 bus->sprom_offset = SSB_SPROM_BASE1;
     885                 :            :         }
     886                 :          0 :         pr_debug("SPROM offset is 0x%x\n", bus->sprom_offset);
     887                 :            : 
     888                 :          0 :         buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
     889         [ #  # ]:          0 :         if (!buf)
     890                 :            :                 return -ENOMEM;
     891                 :          0 :         bus->sprom_size = SSB_SPROMSIZE_WORDS_R123;
     892                 :          0 :         sprom_do_read(bus, buf);
     893                 :          0 :         err = sprom_check_crc(buf, bus->sprom_size);
     894         [ #  # ]:          0 :         if (err) {
     895                 :            :                 /* try for a 440 byte SPROM - revision 4 and higher */
     896                 :          0 :                 kfree(buf);
     897                 :          0 :                 buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
     898                 :            :                               GFP_KERNEL);
     899         [ #  # ]:          0 :                 if (!buf)
     900                 :            :                         return -ENOMEM;
     901                 :          0 :                 bus->sprom_size = SSB_SPROMSIZE_WORDS_R4;
     902                 :          0 :                 sprom_do_read(bus, buf);
     903                 :          0 :                 err = sprom_check_crc(buf, bus->sprom_size);
     904         [ #  # ]:          0 :                 if (err) {
     905                 :            :                         /* All CRC attempts failed.
     906                 :            :                          * Maybe there is no SPROM on the device?
     907                 :            :                          * Now we ask the arch code if there is some sprom
     908                 :            :                          * available for this device in some other storage */
     909                 :          0 :                         err = ssb_fill_sprom_with_fallback(bus, sprom);
     910         [ #  # ]:          0 :                         if (err) {
     911                 :          0 :                                 pr_warn("WARNING: Using fallback SPROM failed (err %d)\n",
     912                 :            :                                         err);
     913                 :          0 :                                 goto out_free;
     914                 :            :                         } else {
     915                 :          0 :                                 pr_debug("Using SPROM revision %d provided by platform\n",
     916                 :            :                                          sprom->revision);
     917                 :          0 :                                 err = 0;
     918                 :          0 :                                 goto out_free;
     919                 :            :                         }
     920                 :            :                         pr_warn("WARNING: Invalid SPROM CRC (corrupt SPROM)\n");
     921                 :            :                 }
     922                 :            :         }
     923                 :          0 :         err = sprom_extract(bus, sprom, buf, bus->sprom_size);
     924                 :            : 
     925                 :          0 : out_free:
     926                 :          0 :         kfree(buf);
     927                 :          0 :         return err;
     928                 :            : }
     929                 :            : 
     930                 :          0 : static void ssb_pci_get_boardinfo(struct ssb_bus *bus,
     931                 :            :                                   struct ssb_boardinfo *bi)
     932                 :            : {
     933                 :          0 :         bi->vendor = bus->host_pci->subsystem_vendor;
     934                 :          0 :         bi->type = bus->host_pci->subsystem_device;
     935                 :          0 : }
     936                 :            : 
     937                 :          0 : int ssb_pci_get_invariants(struct ssb_bus *bus,
     938                 :            :                            struct ssb_init_invariants *iv)
     939                 :            : {
     940                 :          0 :         int err;
     941                 :          0 :         DPRINT("ssb_pci_sprom_get");
     942                 :            : 
     943                 :          0 :         err = ssb_pci_sprom_get(bus, &iv->sprom);
     944         [ #  # ]:          0 :         if (err)
     945                 :          0 :                 goto out;
     946                 :          0 :         DPRINT("ssb_pci_get_boardinfo");
     947                 :          0 :         ssb_pci_get_boardinfo(bus, &iv->boardinfo);
     948                 :            : 
     949                 :          0 : out:
     950                 :          0 :         return err;
     951                 :            : }
     952                 :            : 
     953                 :            : static int ssb_pci_assert_buspower(struct ssb_bus *bus)
     954                 :            : {
     955                 :            :         if (likely(bus->powered_up))
     956                 :            :                 return 0;
     957                 :            : 
     958                 :            :         pr_err("FATAL ERROR: Bus powered down while accessing PCI MMIO space\n");
     959                 :            :         if (bus->power_warn_count <= 10) {
     960                 :            :                 bus->power_warn_count++;
     961                 :            :                 dump_stack();
     962                 :            :         }
     963                 :            : 
     964                 :            :         return -ENODEV;
     965                 :            : }
     966                 :            : 
     967                 :          0 : static u8 ssb_pci_read8(struct ssb_device *dev, u16 offset)
     968                 :            : {
     969                 :          0 :         struct ssb_bus *bus = dev->bus;
     970                 :            : 
     971         [ #  # ]:          0 :         if (unlikely(ssb_pci_assert_buspower(bus)))
     972                 :            :                 return 0xFF;
     973         [ #  # ]:          0 :         if (unlikely(bus->mapped_device != dev)) {
     974         [ #  # ]:          0 :                 if (unlikely(ssb_pci_switch_core(bus, dev)))
     975                 :            :                         return 0xFF;
     976                 :            :         }
     977                 :          0 :         return ioread8(bus->mmio + offset);
     978                 :            : }
     979                 :            : 
     980                 :          0 : static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)
     981                 :            : {
     982                 :          0 :         struct ssb_bus *bus = dev->bus;
     983                 :            : 
     984         [ #  # ]:          0 :         if (unlikely(ssb_pci_assert_buspower(bus)))
     985                 :            :                 return 0xFFFF;
     986         [ #  # ]:          0 :         if (unlikely(bus->mapped_device != dev)) {
     987         [ #  # ]:          0 :                 if (unlikely(ssb_pci_switch_core(bus, dev)))
     988                 :            :                         return 0xFFFF;
     989                 :            :         }
     990                 :          0 :         return ioread16(bus->mmio + offset);
     991                 :            : }
     992                 :            : 
     993                 :          0 : static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
     994                 :            : {
     995                 :          0 :         struct ssb_bus *bus = dev->bus;
     996                 :            : 
     997         [ #  # ]:          0 :         if (unlikely(ssb_pci_assert_buspower(bus)))
     998                 :            :                 return 0xFFFFFFFF;
     999         [ #  # ]:          0 :         if (unlikely(bus->mapped_device != dev)) {
    1000         [ #  # ]:          0 :                 if (unlikely(ssb_pci_switch_core(bus, dev)))
    1001                 :            :                         return 0xFFFFFFFF;
    1002                 :            :         }
    1003                 :          0 :         return ioread32(bus->mmio + offset);
    1004                 :            : }
    1005                 :            : 
    1006                 :            : #ifdef CONFIG_SSB_BLOCKIO
    1007                 :          0 : static void ssb_pci_block_read(struct ssb_device *dev, void *buffer,
    1008                 :            :                                size_t count, u16 offset, u8 reg_width)
    1009                 :            : {
    1010                 :          0 :         struct ssb_bus *bus = dev->bus;
    1011                 :          0 :         void __iomem *addr = bus->mmio + offset;
    1012                 :            : 
    1013         [ #  # ]:          0 :         if (unlikely(ssb_pci_assert_buspower(bus)))
    1014                 :          0 :                 goto error;
    1015         [ #  # ]:          0 :         if (unlikely(bus->mapped_device != dev)) {
    1016         [ #  # ]:          0 :                 if (unlikely(ssb_pci_switch_core(bus, dev)))
    1017                 :          0 :                         goto error;
    1018                 :            :         }
    1019   [ #  #  #  # ]:          0 :         switch (reg_width) {
    1020                 :          0 :         case sizeof(u8):
    1021                 :          0 :                 ioread8_rep(addr, buffer, count);
    1022                 :          0 :                 break;
    1023                 :          0 :         case sizeof(u16):
    1024         [ #  # ]:          0 :                 WARN_ON(count & 1);
    1025                 :          0 :                 ioread16_rep(addr, buffer, count >> 1);
    1026                 :          0 :                 break;
    1027                 :          0 :         case sizeof(u32):
    1028         [ #  # ]:          0 :                 WARN_ON(count & 3);
    1029                 :          0 :                 ioread32_rep(addr, buffer, count >> 2);
    1030                 :          0 :                 break;
    1031                 :            :         default:
    1032                 :          0 :                 WARN_ON(1);
    1033                 :            :         }
    1034                 :            : 
    1035                 :            :         return;
    1036                 :          0 : error:
    1037                 :          0 :         memset(buffer, 0xFF, count);
    1038                 :            : }
    1039                 :            : #endif /* CONFIG_SSB_BLOCKIO */
    1040                 :            : 
    1041                 :          0 : static void ssb_pci_write8(struct ssb_device *dev, u16 offset, u8 value)
    1042                 :            : {
    1043                 :          0 :         struct ssb_bus *bus = dev->bus;
    1044                 :            : 
    1045         [ #  # ]:          0 :         if (unlikely(ssb_pci_assert_buspower(bus)))
    1046                 :            :                 return;
    1047         [ #  # ]:          0 :         if (unlikely(bus->mapped_device != dev)) {
    1048         [ #  # ]:          0 :                 if (unlikely(ssb_pci_switch_core(bus, dev)))
    1049                 :            :                         return;
    1050                 :            :         }
    1051                 :          0 :         iowrite8(value, bus->mmio + offset);
    1052                 :            : }
    1053                 :            : 
    1054                 :          0 : static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)
    1055                 :            : {
    1056                 :          0 :         struct ssb_bus *bus = dev->bus;
    1057                 :            : 
    1058         [ #  # ]:          0 :         if (unlikely(ssb_pci_assert_buspower(bus)))
    1059                 :            :                 return;
    1060         [ #  # ]:          0 :         if (unlikely(bus->mapped_device != dev)) {
    1061         [ #  # ]:          0 :                 if (unlikely(ssb_pci_switch_core(bus, dev)))
    1062                 :            :                         return;
    1063                 :            :         }
    1064                 :          0 :         iowrite16(value, bus->mmio + offset);
    1065                 :            : }
    1066                 :            : 
    1067                 :          0 : static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
    1068                 :            : {
    1069                 :          0 :         struct ssb_bus *bus = dev->bus;
    1070                 :            : 
    1071         [ #  # ]:          0 :         if (unlikely(ssb_pci_assert_buspower(bus)))
    1072                 :            :                 return;
    1073         [ #  # ]:          0 :         if (unlikely(bus->mapped_device != dev)) {
    1074         [ #  # ]:          0 :                 if (unlikely(ssb_pci_switch_core(bus, dev)))
    1075                 :            :                         return;
    1076                 :            :         }
    1077                 :          0 :         iowrite32(value, bus->mmio + offset);
    1078                 :            : }
    1079                 :            : 
    1080                 :            : #ifdef CONFIG_SSB_BLOCKIO
    1081                 :          0 : static void ssb_pci_block_write(struct ssb_device *dev, const void *buffer,
    1082                 :            :                                 size_t count, u16 offset, u8 reg_width)
    1083                 :            : {
    1084                 :          0 :         struct ssb_bus *bus = dev->bus;
    1085                 :          0 :         void __iomem *addr = bus->mmio + offset;
    1086                 :            : 
    1087         [ #  # ]:          0 :         if (unlikely(ssb_pci_assert_buspower(bus)))
    1088                 :            :                 return;
    1089         [ #  # ]:          0 :         if (unlikely(bus->mapped_device != dev)) {
    1090         [ #  # ]:          0 :                 if (unlikely(ssb_pci_switch_core(bus, dev)))
    1091                 :            :                         return;
    1092                 :            :         }
    1093   [ #  #  #  # ]:          0 :         switch (reg_width) {
    1094                 :          0 :         case sizeof(u8):
    1095                 :          0 :                 iowrite8_rep(addr, buffer, count);
    1096                 :          0 :                 break;
    1097                 :          0 :         case sizeof(u16):
    1098         [ #  # ]:          0 :                 WARN_ON(count & 1);
    1099                 :          0 :                 iowrite16_rep(addr, buffer, count >> 1);
    1100                 :          0 :                 break;
    1101                 :          0 :         case sizeof(u32):
    1102         [ #  # ]:          0 :                 WARN_ON(count & 3);
    1103                 :          0 :                 iowrite32_rep(addr, buffer, count >> 2);
    1104                 :          0 :                 break;
    1105                 :            :         default:
    1106                 :          0 :                 WARN_ON(1);
    1107                 :            :         }
    1108                 :            : }
    1109                 :            : #endif /* CONFIG_SSB_BLOCKIO */
    1110                 :            : 
    1111                 :            : /* Not "static", as it's used in main.c */
    1112                 :            : const struct ssb_bus_ops ssb_pci_ops = {
    1113                 :            :         .read8          = ssb_pci_read8,
    1114                 :            :         .read16         = ssb_pci_read16,
    1115                 :            :         .read32         = ssb_pci_read32,
    1116                 :            :         .write8         = ssb_pci_write8,
    1117                 :            :         .write16        = ssb_pci_write16,
    1118                 :            :         .write32        = ssb_pci_write32,
    1119                 :            : #ifdef CONFIG_SSB_BLOCKIO
    1120                 :            :         .block_read     = ssb_pci_block_read,
    1121                 :            :         .block_write    = ssb_pci_block_write,
    1122                 :            : #endif
    1123                 :            : };
    1124                 :            : 
    1125                 :          0 : static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,
    1126                 :            :                                        struct device_attribute *attr,
    1127                 :            :                                        char *buf)
    1128                 :            : {
    1129                 :          0 :         struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
    1130                 :          0 :         struct ssb_bus *bus;
    1131                 :            : 
    1132                 :          0 :         bus = ssb_pci_dev_to_bus(pdev);
    1133         [ #  # ]:          0 :         if (!bus)
    1134                 :            :                 return -ENODEV;
    1135                 :            : 
    1136                 :          0 :         return ssb_attr_sprom_show(bus, buf, sprom_do_read);
    1137                 :            : }
    1138                 :            : 
    1139                 :          0 : static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,
    1140                 :            :                                         struct device_attribute *attr,
    1141                 :            :                                         const char *buf, size_t count)
    1142                 :            : {
    1143                 :          0 :         struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
    1144                 :          0 :         struct ssb_bus *bus;
    1145                 :            : 
    1146                 :          0 :         bus = ssb_pci_dev_to_bus(pdev);
    1147         [ #  # ]:          0 :         if (!bus)
    1148                 :            :                 return -ENODEV;
    1149                 :            : 
    1150                 :          0 :         return ssb_attr_sprom_store(bus, buf, count,
    1151                 :            :                                     sprom_check_crc, sprom_do_write);
    1152                 :            : }
    1153                 :            : 
    1154                 :            : static DEVICE_ATTR(ssb_sprom, 0600,
    1155                 :            :                    ssb_pci_attr_sprom_show,
    1156                 :            :                    ssb_pci_attr_sprom_store);
    1157                 :            : 
    1158                 :          0 : void ssb_pci_exit(struct ssb_bus *bus)
    1159                 :            : {
    1160                 :          0 :         struct pci_dev *pdev;
    1161                 :            : 
    1162         [ #  # ]:          0 :         if (bus->bustype != SSB_BUSTYPE_PCI)
    1163                 :            :                 return;
    1164                 :            : 
    1165                 :          0 :         pdev = bus->host_pci;
    1166                 :          0 :         device_remove_file(&pdev->dev, &dev_attr_ssb_sprom);
    1167                 :            : }
    1168                 :            : 
    1169                 :          0 : int ssb_pci_init(struct ssb_bus *bus)
    1170                 :            : {
    1171                 :          0 :         struct pci_dev *pdev;
    1172                 :          0 :         int err;
    1173                 :            : 
    1174         [ #  # ]:          0 :         if (bus->bustype != SSB_BUSTYPE_PCI)
    1175                 :            :                 return 0;
    1176                 :            : 
    1177                 :          0 :         pdev = bus->host_pci;
    1178                 :          0 :         mutex_init(&bus->sprom_mutex);
    1179                 :          0 :         err = device_create_file(&pdev->dev, &dev_attr_ssb_sprom);
    1180         [ #  # ]:          0 :         if (err)
    1181                 :          0 :                 goto out;
    1182                 :            : 
    1183                 :          0 : out:
    1184                 :            :         return err;
    1185                 :            : }

Generated by: LCOV version 1.14