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