161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch/* 261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch * Sonics Silicon Backplane PCI-Hostbus related functions. 361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch * 4eb032b9837a958e21ca000358a5bde5e17192ddbMichael Buesch * Copyright (C) 2005-2006 Michael Buesch <m@bues.ch> 561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch * Copyright (C) 2005 Martin Langer <martin-langer@gmx.de> 661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch * Copyright (C) 2005 Stefano Brivio <st3@riseup.net> 761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch * Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org> 861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch * Copyright (C) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch> 961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch * 1061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch * Derived from the Broadcom 4400 device driver. 1161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch * Copyright (C) 2002 David S. Miller (davem@redhat.com) 1261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch * Fixed by Pekka Pietikainen (pp@ee.oulu.fi) 1361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch * Copyright (C) 2006 Broadcom Corporation. 1461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch * 1561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch * Licensed under the GNU/GPL. See COPYING for details. 1661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch */ 1761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 1861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch#include <linux/ssb/ssb.h> 1961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch#include <linux/ssb/ssb_regs.h> 205a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 2161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch#include <linux/pci.h> 2261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch#include <linux/delay.h> 2361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 2461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch#include "ssb_private.h" 2561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 2661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 2761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch/* Define the following to 1 to enable a printk on each coreswitch. */ 2861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch#define SSB_VERBOSE_PCICORESWITCH_DEBUG 0 2961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 3061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 3161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch/* Lowlevel coreswitching */ 3261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschint ssb_pci_switch_coreidx(struct ssb_bus *bus, u8 coreidx) 3361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 3461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch int err; 3561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch int attempts = 0; 3661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch u32 cur_core; 3761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 3861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch while (1) { 3961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch err = pci_write_config_dword(bus->host_pci, SSB_BAR0_WIN, 4061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch (coreidx * SSB_CORE_SIZE) 4161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch + SSB_ENUM_BASE); 4261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (err) 4361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch goto error; 4461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch err = pci_read_config_dword(bus->host_pci, SSB_BAR0_WIN, 4561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch &cur_core); 4661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (err) 4761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch goto error; 4861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch cur_core = (cur_core - SSB_ENUM_BASE) 4961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch / SSB_CORE_SIZE; 5061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (cur_core == coreidx) 5161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch break; 5261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 5361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (attempts++ > SSB_BAR0_MAX_RETRIES) 5461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch goto error; 5561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch udelay(10); 5661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch } 5761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return 0; 5861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buescherror: 5961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch ssb_printk(KERN_ERR PFX "Failed to switch to core %u\n", coreidx); 6061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return -ENODEV; 6161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 6261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 6361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschint ssb_pci_switch_core(struct ssb_bus *bus, 6461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch struct ssb_device *dev) 6561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 6661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch int err; 6761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch unsigned long flags; 6861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 6961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch#if SSB_VERBOSE_PCICORESWITCH_DEBUG 7061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch ssb_printk(KERN_INFO PFX 7161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch "Switching to %s core, index %d\n", 7261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch ssb_core_name(dev->id.coreid), 7361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch dev->core_index); 7461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch#endif 7561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 7661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch spin_lock_irqsave(&bus->bar_lock, flags); 7761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch err = ssb_pci_switch_coreidx(bus, dev->core_index); 7861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (!err) 7961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch bus->mapped_device = dev; 8061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch spin_unlock_irqrestore(&bus->bar_lock, flags); 8161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 8261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return err; 8361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 8461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 8561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch/* Enable/disable the on board crystal oscillator and/or PLL. */ 8661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschint ssb_pci_xtal(struct ssb_bus *bus, u32 what, int turn_on) 8761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 8861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch int err; 8961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch u32 in, out, outenable; 9061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch u16 pci_status; 9161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 9261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (bus->bustype != SSB_BUSTYPE_PCI) 9361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return 0; 9461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 9561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch err = pci_read_config_dword(bus->host_pci, SSB_GPIO_IN, &in); 9661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (err) 9761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch goto err_pci; 9861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch err = pci_read_config_dword(bus->host_pci, SSB_GPIO_OUT, &out); 9961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (err) 10061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch goto err_pci; 10161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch err = pci_read_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE, &outenable); 10261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (err) 10361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch goto err_pci; 10461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 10561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch outenable |= what; 10661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 10761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (turn_on) { 10861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch /* Avoid glitching the clock if GPRS is already using it. 10961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch * We can't actually read the state of the PLLPD so we infer it 11061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch * by the value of XTAL_PU which *is* readable via gpioin. 11161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch */ 11261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (!(in & SSB_GPIO_XTAL)) { 11361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (what & SSB_GPIO_XTAL) { 11461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch /* Turn the crystal on */ 11561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch out |= SSB_GPIO_XTAL; 11661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (what & SSB_GPIO_PLL) 11761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch out |= SSB_GPIO_PLL; 11861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out); 11961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (err) 12061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch goto err_pci; 12161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE, 12261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch outenable); 12361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (err) 12461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch goto err_pci; 12561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch msleep(1); 12661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch } 12761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (what & SSB_GPIO_PLL) { 12861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch /* Turn the PLL on */ 12961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch out &= ~SSB_GPIO_PLL; 13061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out); 13161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (err) 13261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch goto err_pci; 13361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch msleep(5); 13461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch } 13561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch } 13661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 13761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch err = pci_read_config_word(bus->host_pci, PCI_STATUS, &pci_status); 13861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (err) 13961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch goto err_pci; 14061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch pci_status &= ~PCI_STATUS_SIG_TARGET_ABORT; 14161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch err = pci_write_config_word(bus->host_pci, PCI_STATUS, pci_status); 14261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (err) 14361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch goto err_pci; 14461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch } else { 14561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (what & SSB_GPIO_XTAL) { 14661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch /* Turn the crystal off */ 14761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch out &= ~SSB_GPIO_XTAL; 14861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch } 14961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (what & SSB_GPIO_PLL) { 15061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch /* Turn the PLL off */ 15161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch out |= SSB_GPIO_PLL; 15261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch } 15361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out); 15461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (err) 15561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch goto err_pci; 15661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE, outenable); 15761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (err) 15861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch goto err_pci; 15961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch } 16061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 16161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschout: 16261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return err; 16361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 16461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buescherr_pci: 16561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch printk(KERN_ERR PFX "Error: ssb_pci_xtal() could not access PCI config space!\n"); 16661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch err = -EBUSY; 16761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch goto out; 16861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 16961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 17061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch/* Get the word-offset for a SSB_SPROM_XXX define. */ 1710a182fd88f8180b342f753f04c7d5507b5891c96Rafał Miłecki#define SPOFF(offset) ((offset) / sizeof(u16)) 17261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch/* Helper to extract some _offset, which is one of the SSB_SPROM_XXX defines. */ 173f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik#define SPEX16(_outvar, _offset, _mask, _shift) \ 17461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch out->_outvar = ((in[SPOFF(_offset)] & (_mask)) >> (_shift)) 175f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik#define SPEX32(_outvar, _offset, _mask, _shift) \ 176f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik out->_outvar = ((((u32)in[SPOFF((_offset)+2)] << 16 | \ 177f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik in[SPOFF(_offset)]) & (_mask)) >> (_shift)) 178f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik#define SPEX(_outvar, _offset, _mask, _shift) \ 179f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SPEX16(_outvar, _offset, _mask, _shift) 180f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik 18161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 18261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschstatic inline u8 ssb_crc8(u8 crc, u8 data) 18361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 18461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch /* Polynomial: x^8 + x^7 + x^6 + x^4 + x^2 + 1 */ 18561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch static const u8 t[] = { 18661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B, 18761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21, 18861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF, 18961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5, 19061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14, 19161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E, 19261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80, 19361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA, 19461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95, 19561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF, 19661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01, 19761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B, 19861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA, 19961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0, 20061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E, 20161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34, 20261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0, 20361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A, 20461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54, 20561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E, 20661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF, 20761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5, 20861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B, 20961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61, 21061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E, 21161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74, 21261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA, 21361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0, 21461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41, 21561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B, 21661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5, 21761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F, 21861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch }; 21961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return t[crc ^ data]; 22061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 22161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 222c272ef4403c271799a7f09a4ab7a236c86643843Larry Fingerstatic u8 ssb_sprom_crc(const u16 *sprom, u16 size) 22361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 22461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch int word; 22561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch u8 crc = 0xFF; 22661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 227c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger for (word = 0; word < size - 1; word++) { 22861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch crc = ssb_crc8(crc, sprom[word] & 0x00FF); 22961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch crc = ssb_crc8(crc, (sprom[word] & 0xFF00) >> 8); 23061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch } 231c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger crc = ssb_crc8(crc, sprom[size - 1] & 0x00FF); 23261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch crc ^= 0xFF; 23361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 23461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return crc; 23561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 23661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 237e7ec2e3230633a858af1b0b359f6c4670dbeb997Michael Bueschstatic int sprom_check_crc(const u16 *sprom, size_t size) 23861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 23961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch u8 crc; 24061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch u8 expected_crc; 24161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch u16 tmp; 24261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 243c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger crc = ssb_sprom_crc(sprom, size); 244c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger tmp = sprom[size - 1] & SSB_SPROM_REVISION_CRC; 24561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT; 24661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (crc != expected_crc) 24761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return -EPROTO; 24861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 24961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return 0; 25061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 25161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 252e7ec2e3230633a858af1b0b359f6c4670dbeb997Michael Bueschstatic int sprom_do_read(struct ssb_bus *bus, u16 *sprom) 25361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 25461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch int i; 25561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 256c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger for (i = 0; i < bus->sprom_size; i++) 257ea2db495f92ad2cf3301623e60cb95b4062bc484Rafał Miłecki sprom[i] = ioread16(bus->mmio + bus->sprom_offset + (i * 2)); 258e7ec2e3230633a858af1b0b359f6c4670dbeb997Michael Buesch 259e7ec2e3230633a858af1b0b359f6c4670dbeb997Michael Buesch return 0; 26061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 26161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 26261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschstatic int sprom_do_write(struct ssb_bus *bus, const u16 *sprom) 26361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 26461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch struct pci_dev *pdev = bus->host_pci; 26561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch int i, err; 26661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch u32 spromctl; 267c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger u16 size = bus->sprom_size; 26861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 26961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch ssb_printk(KERN_NOTICE PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n"); 27061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl); 27161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (err) 27261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch goto err_ctlreg; 27361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch spromctl |= SSB_SPROMCTL_WE; 27461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl); 27561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (err) 27661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch goto err_ctlreg; 27761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch ssb_printk(KERN_NOTICE PFX "[ 0%%"); 27861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch msleep(500); 279c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger for (i = 0; i < size; i++) { 280c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger if (i == size / 4) 28161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch ssb_printk("25%%"); 282c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger else if (i == size / 2) 28361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch ssb_printk("50%%"); 284c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger else if (i == (size * 3) / 4) 28561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch ssb_printk("75%%"); 28661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch else if (i % 2) 28761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch ssb_printk("."); 288ea2db495f92ad2cf3301623e60cb95b4062bc484Rafał Miłecki writew(sprom[i], bus->mmio + bus->sprom_offset + (i * 2)); 28961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch mmiowb(); 29061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch msleep(20); 29161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch } 29261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl); 29361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (err) 29461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch goto err_ctlreg; 29561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch spromctl &= ~SSB_SPROMCTL_WE; 29661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl); 29761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (err) 29861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch goto err_ctlreg; 29961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch msleep(500); 30061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch ssb_printk("100%% ]\n"); 30161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch ssb_printk(KERN_NOTICE PFX "SPROM written.\n"); 30261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 30361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return 0; 30461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buescherr_ctlreg: 30561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch ssb_printk(KERN_ERR PFX "Could not access SPROM control register.\n"); 30661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return err; 30761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 30861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 309e861b98d5e1be769ca6483b6df97149b956ea834Michael Bueschstatic s8 r123_extract_antgain(u8 sprom_revision, const u16 *in, 310e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch u16 mask, u16 shift) 311e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch{ 312e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch u16 v; 313e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch u8 gain; 314e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch 315e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch v = in[SPOFF(SSB_SPROM1_AGAIN)]; 316e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch gain = (v & mask) >> shift; 317e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch if (gain == 0xFF) 318e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch gain = 2; /* If unset use 2dBm */ 319e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch if (sprom_revision == 1) { 320e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch /* Convert to Q5.2 */ 321e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch gain <<= 2; 322e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch } else { 323e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch /* Q5.2 Fractional part is stored in 0xC0 */ 324e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch gain = ((gain & 0xC0) >> 6) | ((gain & 0x3F) << 2); 325e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch } 326e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch 327e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch return (s8)gain; 328e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch} 329e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch 330c272ef4403c271799a7f09a4ab7a236c86643843Larry Fingerstatic void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) 33161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 33261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch int i; 33361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch u16 v; 334c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger u16 loc[3]; 33561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 33631ce12fb3ebf88b054deb99ad729e84888bf6125Larry Finger if (out->revision == 3) /* rev 3 moved MAC */ 337c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger loc[0] = SSB_SPROM3_IL0MAC; 33831ce12fb3ebf88b054deb99ad729e84888bf6125Larry Finger else { 339c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger loc[0] = SSB_SPROM1_IL0MAC; 340c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger loc[1] = SSB_SPROM1_ET0MAC; 341c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger loc[2] = SSB_SPROM1_ET1MAC; 342c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger } 343c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger for (i = 0; i < 3; i++) { 344c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger v = in[SPOFF(loc[0]) + i]; 345c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v); 346c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger } 34731ce12fb3ebf88b054deb99ad729e84888bf6125Larry Finger if (out->revision < 3) { /* only rev 1-2 have et0, et1 */ 34831ce12fb3ebf88b054deb99ad729e84888bf6125Larry Finger for (i = 0; i < 3; i++) { 34931ce12fb3ebf88b054deb99ad729e84888bf6125Larry Finger v = in[SPOFF(loc[1]) + i]; 35031ce12fb3ebf88b054deb99ad729e84888bf6125Larry Finger *(((__be16 *)out->et0mac) + i) = cpu_to_be16(v); 35131ce12fb3ebf88b054deb99ad729e84888bf6125Larry Finger } 35231ce12fb3ebf88b054deb99ad729e84888bf6125Larry Finger for (i = 0; i < 3; i++) { 35331ce12fb3ebf88b054deb99ad729e84888bf6125Larry Finger v = in[SPOFF(loc[2]) + i]; 35431ce12fb3ebf88b054deb99ad729e84888bf6125Larry Finger *(((__be16 *)out->et1mac) + i) = cpu_to_be16(v); 35531ce12fb3ebf88b054deb99ad729e84888bf6125Larry Finger } 35661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch } 357c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0); 358c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A, 359c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger SSB_SPROM1_ETHPHY_ET1A_SHIFT); 360e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14); 361e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15); 362e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0); 363c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE, 364c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger SSB_SPROM1_BINF_CCODE_SHIFT); 365e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch SPEX(ant_available_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA, 366e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch SSB_SPROM1_BINF_ANTA_SHIFT); 367e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch SPEX(ant_available_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG, 368e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch SSB_SPROM1_BINF_ANTBG_SHIFT); 369c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger SPEX(pa0b0, SSB_SPROM1_PA0B0, 0xFFFF, 0); 370c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger SPEX(pa0b1, SSB_SPROM1_PA0B1, 0xFFFF, 0); 371c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger SPEX(pa0b2, SSB_SPROM1_PA0B2, 0xFFFF, 0); 372c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger SPEX(pa1b0, SSB_SPROM1_PA1B0, 0xFFFF, 0); 373c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger SPEX(pa1b1, SSB_SPROM1_PA1B1, 0xFFFF, 0); 374c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger SPEX(pa1b2, SSB_SPROM1_PA1B2, 0xFFFF, 0); 375c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger SPEX(gpio0, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P0, 0); 376c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger SPEX(gpio1, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P1, 377c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger SSB_SPROM1_GPIOA_P1_SHIFT); 378c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger SPEX(gpio2, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P2, 0); 379c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger SPEX(gpio3, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P3, 380c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger SSB_SPROM1_GPIOB_P3_SHIFT); 381c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger SPEX(maxpwr_a, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_A, 382c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger SSB_SPROM1_MAXPWR_A_SHIFT); 383c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger SPEX(maxpwr_bg, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_BG, 0); 384c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger SPEX(itssi_a, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_A, 385c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger SSB_SPROM1_ITSSI_A_SHIFT); 386c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0); 387c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0); 388af4b7450788426a113057ce2d85c25b4f4e440d1Michael Buesch if (out->revision >= 2) 389af4b7450788426a113057ce2d85c25b4f4e440d1Michael Buesch SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0); 390e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch 391e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch /* Extract the antenna gain values. */ 392f8f8a660ba501ad14617ccd0d91a1ed8ce54d6d0Hauke Mehrtens out->antenna_gain.a0 = r123_extract_antgain(out->revision, in, 393f8f8a660ba501ad14617ccd0d91a1ed8ce54d6d0Hauke Mehrtens SSB_SPROM1_AGAIN_BG, 394f8f8a660ba501ad14617ccd0d91a1ed8ce54d6d0Hauke Mehrtens SSB_SPROM1_AGAIN_BG_SHIFT); 395f8f8a660ba501ad14617ccd0d91a1ed8ce54d6d0Hauke Mehrtens out->antenna_gain.a1 = r123_extract_antgain(out->revision, in, 396f8f8a660ba501ad14617ccd0d91a1ed8ce54d6d0Hauke Mehrtens SSB_SPROM1_AGAIN_A, 397f8f8a660ba501ad14617ccd0d91a1ed8ce54d6d0Hauke Mehrtens SSB_SPROM1_AGAIN_A_SHIFT); 39861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 39961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 400172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki/* Revs 4 5 and 8 have partially shared layout */ 401172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłeckistatic void sprom_extract_r458(struct ssb_sprom *out, const u16 *in) 402172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki{ 403172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01, 404172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki SSB_SPROM4_TXPID2G0, SSB_SPROM4_TXPID2G0_SHIFT); 405172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki SPEX(txpid2g[1], SSB_SPROM4_TXPID2G01, 406172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki SSB_SPROM4_TXPID2G1, SSB_SPROM4_TXPID2G1_SHIFT); 407172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki SPEX(txpid2g[2], SSB_SPROM4_TXPID2G23, 408172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki SSB_SPROM4_TXPID2G2, SSB_SPROM4_TXPID2G2_SHIFT); 409172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki SPEX(txpid2g[3], SSB_SPROM4_TXPID2G23, 410172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki SSB_SPROM4_TXPID2G3, SSB_SPROM4_TXPID2G3_SHIFT); 411172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki 412172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki SPEX(txpid5gl[0], SSB_SPROM4_TXPID5GL01, 413172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki SSB_SPROM4_TXPID5GL0, SSB_SPROM4_TXPID5GL0_SHIFT); 414172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki SPEX(txpid5gl[1], SSB_SPROM4_TXPID5GL01, 415172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki SSB_SPROM4_TXPID5GL1, SSB_SPROM4_TXPID5GL1_SHIFT); 416172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki SPEX(txpid5gl[2], SSB_SPROM4_TXPID5GL23, 417172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki SSB_SPROM4_TXPID5GL2, SSB_SPROM4_TXPID5GL2_SHIFT); 418172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki SPEX(txpid5gl[3], SSB_SPROM4_TXPID5GL23, 419172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki SSB_SPROM4_TXPID5GL3, SSB_SPROM4_TXPID5GL3_SHIFT); 420172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki 421172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki SPEX(txpid5g[0], SSB_SPROM4_TXPID5G01, 422172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki SSB_SPROM4_TXPID5G0, SSB_SPROM4_TXPID5G0_SHIFT); 423172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki SPEX(txpid5g[1], SSB_SPROM4_TXPID5G01, 424172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki SSB_SPROM4_TXPID5G1, SSB_SPROM4_TXPID5G1_SHIFT); 425172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki SPEX(txpid5g[2], SSB_SPROM4_TXPID5G23, 426172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki SSB_SPROM4_TXPID5G2, SSB_SPROM4_TXPID5G2_SHIFT); 427172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki SPEX(txpid5g[3], SSB_SPROM4_TXPID5G23, 428172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki SSB_SPROM4_TXPID5G3, SSB_SPROM4_TXPID5G3_SHIFT); 429172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki 430172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki SPEX(txpid5gh[0], SSB_SPROM4_TXPID5GH01, 431172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki SSB_SPROM4_TXPID5GH0, SSB_SPROM4_TXPID5GH0_SHIFT); 432172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki SPEX(txpid5gh[1], SSB_SPROM4_TXPID5GH01, 433172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki SSB_SPROM4_TXPID5GH1, SSB_SPROM4_TXPID5GH1_SHIFT); 434172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki SPEX(txpid5gh[2], SSB_SPROM4_TXPID5GH23, 435172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki SSB_SPROM4_TXPID5GH2, SSB_SPROM4_TXPID5GH2_SHIFT); 436172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki SPEX(txpid5gh[3], SSB_SPROM4_TXPID5GH23, 437172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki SSB_SPROM4_TXPID5GH3, SSB_SPROM4_TXPID5GH3_SHIFT); 438172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki} 439172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki 440095f695cbb07281682462da0618fffabb499d0beLarry Fingerstatic void sprom_extract_r45(struct ssb_sprom *out, const u16 *in) 44161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 442c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger int i; 443c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger u16 v; 444095f695cbb07281682462da0618fffabb499d0beLarry Finger u16 il0mac_offset; 445c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger 446095f695cbb07281682462da0618fffabb499d0beLarry Finger if (out->revision == 4) 447095f695cbb07281682462da0618fffabb499d0beLarry Finger il0mac_offset = SSB_SPROM4_IL0MAC; 448095f695cbb07281682462da0618fffabb499d0beLarry Finger else 449095f695cbb07281682462da0618fffabb499d0beLarry Finger il0mac_offset = SSB_SPROM5_IL0MAC; 45031ce12fb3ebf88b054deb99ad729e84888bf6125Larry Finger /* extract the MAC address */ 451c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger for (i = 0; i < 3; i++) { 452095f695cbb07281682462da0618fffabb499d0beLarry Finger v = in[SPOFF(il0mac_offset) + i]; 453c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v); 454c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger } 455c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0); 456c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A, 457c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger SSB_SPROM4_ETHPHY_ET1A_SHIFT); 458095f695cbb07281682462da0618fffabb499d0beLarry Finger if (out->revision == 4) { 459095f695cbb07281682462da0618fffabb499d0beLarry Finger SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0); 460095f695cbb07281682462da0618fffabb499d0beLarry Finger SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0); 461095f695cbb07281682462da0618fffabb499d0beLarry Finger SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0); 4626d1d4ea4a82f8c17a3ff7c2f677bc3d41ea7484bRafał Miłecki SPEX(boardflags2_lo, SSB_SPROM4_BFL2LO, 0xFFFF, 0); 4636d1d4ea4a82f8c17a3ff7c2f677bc3d41ea7484bRafał Miłecki SPEX(boardflags2_hi, SSB_SPROM4_BFL2HI, 0xFFFF, 0); 464095f695cbb07281682462da0618fffabb499d0beLarry Finger } else { 465095f695cbb07281682462da0618fffabb499d0beLarry Finger SPEX(country_code, SSB_SPROM5_CCODE, 0xFFFF, 0); 466095f695cbb07281682462da0618fffabb499d0beLarry Finger SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0); 467095f695cbb07281682462da0618fffabb499d0beLarry Finger SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0); 4686d1d4ea4a82f8c17a3ff7c2f677bc3d41ea7484bRafał Miłecki SPEX(boardflags2_lo, SSB_SPROM5_BFL2LO, 0xFFFF, 0); 4696d1d4ea4a82f8c17a3ff7c2f677bc3d41ea7484bRafał Miłecki SPEX(boardflags2_hi, SSB_SPROM5_BFL2HI, 0xFFFF, 0); 470095f695cbb07281682462da0618fffabb499d0beLarry Finger } 471e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A, 472e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch SSB_SPROM4_ANTAVAIL_A_SHIFT); 473e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch SPEX(ant_available_bg, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_BG, 474e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch SSB_SPROM4_ANTAVAIL_BG_SHIFT); 475d3c319f9c8d9ee2c042c60b8a1bbd909dcc42782Larry Finger SPEX(maxpwr_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_MAXP_BG_MASK, 0); 476d3c319f9c8d9ee2c042c60b8a1bbd909dcc42782Larry Finger SPEX(itssi_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_ITSSI_BG, 477d3c319f9c8d9ee2c042c60b8a1bbd909dcc42782Larry Finger SSB_SPROM4_ITSSI_BG_SHIFT); 478d3c319f9c8d9ee2c042c60b8a1bbd909dcc42782Larry Finger SPEX(maxpwr_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_MAXP_A_MASK, 0); 479d3c319f9c8d9ee2c042c60b8a1bbd909dcc42782Larry Finger SPEX(itssi_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_ITSSI_A, 480d3c319f9c8d9ee2c042c60b8a1bbd909dcc42782Larry Finger SSB_SPROM4_ITSSI_A_SHIFT); 481095f695cbb07281682462da0618fffabb499d0beLarry Finger if (out->revision == 4) { 482095f695cbb07281682462da0618fffabb499d0beLarry Finger SPEX(gpio0, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P0, 0); 483095f695cbb07281682462da0618fffabb499d0beLarry Finger SPEX(gpio1, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P1, 484095f695cbb07281682462da0618fffabb499d0beLarry Finger SSB_SPROM4_GPIOA_P1_SHIFT); 485095f695cbb07281682462da0618fffabb499d0beLarry Finger SPEX(gpio2, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P2, 0); 486095f695cbb07281682462da0618fffabb499d0beLarry Finger SPEX(gpio3, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P3, 487095f695cbb07281682462da0618fffabb499d0beLarry Finger SSB_SPROM4_GPIOB_P3_SHIFT); 488095f695cbb07281682462da0618fffabb499d0beLarry Finger } else { 489095f695cbb07281682462da0618fffabb499d0beLarry Finger SPEX(gpio0, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P0, 0); 490095f695cbb07281682462da0618fffabb499d0beLarry Finger SPEX(gpio1, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P1, 491095f695cbb07281682462da0618fffabb499d0beLarry Finger SSB_SPROM5_GPIOA_P1_SHIFT); 492095f695cbb07281682462da0618fffabb499d0beLarry Finger SPEX(gpio2, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P2, 0); 493095f695cbb07281682462da0618fffabb499d0beLarry Finger SPEX(gpio3, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P3, 494095f695cbb07281682462da0618fffabb499d0beLarry Finger SSB_SPROM5_GPIOB_P3_SHIFT); 495095f695cbb07281682462da0618fffabb499d0beLarry Finger } 496e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch 497e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch /* Extract the antenna gain values. */ 498f8f8a660ba501ad14617ccd0d91a1ed8ce54d6d0Hauke Mehrtens SPEX(antenna_gain.a0, SSB_SPROM4_AGAIN01, 499e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch SSB_SPROM4_AGAIN0, SSB_SPROM4_AGAIN0_SHIFT); 500f8f8a660ba501ad14617ccd0d91a1ed8ce54d6d0Hauke Mehrtens SPEX(antenna_gain.a1, SSB_SPROM4_AGAIN01, 501e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch SSB_SPROM4_AGAIN1, SSB_SPROM4_AGAIN1_SHIFT); 502f8f8a660ba501ad14617ccd0d91a1ed8ce54d6d0Hauke Mehrtens SPEX(antenna_gain.a2, SSB_SPROM4_AGAIN23, 503e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch SSB_SPROM4_AGAIN2, SSB_SPROM4_AGAIN2_SHIFT); 504f8f8a660ba501ad14617ccd0d91a1ed8ce54d6d0Hauke Mehrtens SPEX(antenna_gain.a3, SSB_SPROM4_AGAIN23, 505e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch SSB_SPROM4_AGAIN3, SSB_SPROM4_AGAIN3_SHIFT); 506e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch 507172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki sprom_extract_r458(out, in); 508172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki 509c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger /* TODO - get remaining rev 4 stuff needed */ 51061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 51161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 5126b1c7c67603efdf0b39f6056989b0f8194cdc1f3Michael Bueschstatic void sprom_extract_r8(struct ssb_sprom *out, const u16 *in) 5136b1c7c67603efdf0b39f6056989b0f8194cdc1f3Michael Buesch{ 5146b1c7c67603efdf0b39f6056989b0f8194cdc1f3Michael Buesch int i; 515b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki u16 v, o; 516b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki u16 pwr_info_offset[] = { 517b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1, 518b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3 519b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki }; 520b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) != 521b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki ARRAY_SIZE(out->core_pwr_info)); 5226b1c7c67603efdf0b39f6056989b0f8194cdc1f3Michael Buesch 5236b1c7c67603efdf0b39f6056989b0f8194cdc1f3Michael Buesch /* extract the MAC address */ 5246b1c7c67603efdf0b39f6056989b0f8194cdc1f3Michael Buesch for (i = 0; i < 3; i++) { 525f0ea6ce14ae2a72a353ddf8ab370c09ba403d897Gábor Stefanik v = in[SPOFF(SSB_SPROM8_IL0MAC) + i]; 5266b1c7c67603efdf0b39f6056989b0f8194cdc1f3Michael Buesch *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v); 5276b1c7c67603efdf0b39f6056989b0f8194cdc1f3Michael Buesch } 5286b1c7c67603efdf0b39f6056989b0f8194cdc1f3Michael Buesch SPEX(country_code, SSB_SPROM8_CCODE, 0xFFFF, 0); 5296b1c7c67603efdf0b39f6056989b0f8194cdc1f3Michael Buesch SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0); 5306b1c7c67603efdf0b39f6056989b0f8194cdc1f3Michael Buesch SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0); 531f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, 0xFFFF, 0); 532f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, 0xFFFF, 0); 5336b1c7c67603efdf0b39f6056989b0f8194cdc1f3Michael Buesch SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A, 5346b1c7c67603efdf0b39f6056989b0f8194cdc1f3Michael Buesch SSB_SPROM8_ANTAVAIL_A_SHIFT); 5356b1c7c67603efdf0b39f6056989b0f8194cdc1f3Michael Buesch SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG, 5366b1c7c67603efdf0b39f6056989b0f8194cdc1f3Michael Buesch SSB_SPROM8_ANTAVAIL_BG_SHIFT); 5376b1c7c67603efdf0b39f6056989b0f8194cdc1f3Michael Buesch SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0); 5386b1c7c67603efdf0b39f6056989b0f8194cdc1f3Michael Buesch SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG, 5396b1c7c67603efdf0b39f6056989b0f8194cdc1f3Michael Buesch SSB_SPROM8_ITSSI_BG_SHIFT); 5406b1c7c67603efdf0b39f6056989b0f8194cdc1f3Michael Buesch SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0); 5416b1c7c67603efdf0b39f6056989b0f8194cdc1f3Michael Buesch SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A, 5426b1c7c67603efdf0b39f6056989b0f8194cdc1f3Michael Buesch SSB_SPROM8_ITSSI_A_SHIFT); 543f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0); 544f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK, 545f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SSB_SPROM8_MAXP_AL_SHIFT); 5466b1c7c67603efdf0b39f6056989b0f8194cdc1f3Michael Buesch SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0); 5476b1c7c67603efdf0b39f6056989b0f8194cdc1f3Michael Buesch SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1, 5486b1c7c67603efdf0b39f6056989b0f8194cdc1f3Michael Buesch SSB_SPROM8_GPIOA_P1_SHIFT); 5496b1c7c67603efdf0b39f6056989b0f8194cdc1f3Michael Buesch SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0); 5506b1c7c67603efdf0b39f6056989b0f8194cdc1f3Michael Buesch SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3, 5516b1c7c67603efdf0b39f6056989b0f8194cdc1f3Michael Buesch SSB_SPROM8_GPIOB_P3_SHIFT); 552f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0); 553f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G, 554f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SSB_SPROM8_TRI5G_SHIFT); 555f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0); 556f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH, 557f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SSB_SPROM8_TRI5GH_SHIFT); 558f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G, 0); 559f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G, 560f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SSB_SPROM8_RXPO5G_SHIFT); 561f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0); 562f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G, 563f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SSB_SPROM8_RSSISMC2G_SHIFT); 564f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G, 565f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SSB_SPROM8_RSSISAV2G_SHIFT); 566f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G, 567f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SSB_SPROM8_BXA2G_SHIFT); 568f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0); 569f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G, 570f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SSB_SPROM8_RSSISMC5G_SHIFT); 571f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G, 572f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SSB_SPROM8_RSSISAV5G_SHIFT); 573f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G, 574f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SSB_SPROM8_BXA5G_SHIFT); 575f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SPEX(pa0b0, SSB_SPROM8_PA0B0, 0xFFFF, 0); 576f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SPEX(pa0b1, SSB_SPROM8_PA0B1, 0xFFFF, 0); 577f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SPEX(pa0b2, SSB_SPROM8_PA0B2, 0xFFFF, 0); 578f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SPEX(pa1b0, SSB_SPROM8_PA1B0, 0xFFFF, 0); 579f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SPEX(pa1b1, SSB_SPROM8_PA1B1, 0xFFFF, 0); 580f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SPEX(pa1b2, SSB_SPROM8_PA1B2, 0xFFFF, 0); 581f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, 0xFFFF, 0); 582f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, 0xFFFF, 0); 583f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, 0xFFFF, 0); 584f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, 0xFFFF, 0); 585f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, 0xFFFF, 0); 586f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, 0xFFFF, 0); 587f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, 0xFFFF, 0); 588f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, 0xFFFFFFFF, 0); 589f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, 0xFFFFFFFF, 0); 590f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, 0xFFFFFFFF, 0); 591f679056b2fdd4e9b7c8eb42ba447cd9646236305Gábor Stefanik SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0); 5926b1c7c67603efdf0b39f6056989b0f8194cdc1f3Michael Buesch 5936b1c7c67603efdf0b39f6056989b0f8194cdc1f3Michael Buesch /* Extract the antenna gain values. */ 594f8f8a660ba501ad14617ccd0d91a1ed8ce54d6d0Hauke Mehrtens SPEX(antenna_gain.a0, SSB_SPROM8_AGAIN01, 5956b1c7c67603efdf0b39f6056989b0f8194cdc1f3Michael Buesch SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT); 596f8f8a660ba501ad14617ccd0d91a1ed8ce54d6d0Hauke Mehrtens SPEX(antenna_gain.a1, SSB_SPROM8_AGAIN01, 5976b1c7c67603efdf0b39f6056989b0f8194cdc1f3Michael Buesch SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT); 598f8f8a660ba501ad14617ccd0d91a1ed8ce54d6d0Hauke Mehrtens SPEX(antenna_gain.a2, SSB_SPROM8_AGAIN23, 5996b1c7c67603efdf0b39f6056989b0f8194cdc1f3Michael Buesch SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT); 600f8f8a660ba501ad14617ccd0d91a1ed8ce54d6d0Hauke Mehrtens SPEX(antenna_gain.a3, SSB_SPROM8_AGAIN23, 6016b1c7c67603efdf0b39f6056989b0f8194cdc1f3Michael Buesch SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT); 6026b1c7c67603efdf0b39f6056989b0f8194cdc1f3Michael Buesch 603b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki /* Extract cores power info info */ 604b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) { 605b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki o = pwr_info_offset[i]; 606b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki SPEX(core_pwr_info[i].itssi_2g, o + SSB_SROM8_2G_MAXP_ITSSI, 607b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki SSB_SPROM8_2G_ITSSI, SSB_SPROM8_2G_ITSSI_SHIFT); 608b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SROM8_2G_MAXP_ITSSI, 609b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki SSB_SPROM8_2G_MAXP, 0); 610b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki 611b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SROM8_2G_PA_0, ~0, 0); 612b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SROM8_2G_PA_1, ~0, 0); 613b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SROM8_2G_PA_2, ~0, 0); 614b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki 615b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki SPEX(core_pwr_info[i].itssi_5g, o + SSB_SROM8_5G_MAXP_ITSSI, 616b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki SSB_SPROM8_5G_ITSSI, SSB_SPROM8_5G_ITSSI_SHIFT); 617b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SROM8_5G_MAXP_ITSSI, 618b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki SSB_SPROM8_5G_MAXP, 0); 619b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM8_5GHL_MAXP, 620b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki SSB_SPROM8_5GH_MAXP, 0); 621b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM8_5GHL_MAXP, 622b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki SSB_SPROM8_5GL_MAXP, SSB_SPROM8_5GL_MAXP_SHIFT); 623b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki 624b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SROM8_5GL_PA_0, ~0, 0); 625b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SROM8_5GL_PA_1, ~0, 0); 626b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SROM8_5GL_PA_2, ~0, 0); 627b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SROM8_5G_PA_0, ~0, 0); 628b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SROM8_5G_PA_1, ~0, 0); 629b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SROM8_5G_PA_2, ~0, 0); 630b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SROM8_5GH_PA_0, ~0, 0); 631b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SROM8_5GH_PA_1, ~0, 0); 632b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SROM8_5GH_PA_2, ~0, 0); 633b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki } 634b0f70292053a0f68f406564a721a7a3f2d66b44fRafał Miłecki 6358a5ac6ecd56756ee72588627aa23ab6cf9b790dbRafał Miłecki /* Extract FEM info */ 6368a5ac6ecd56756ee72588627aa23ab6cf9b790dbRafał Miłecki SPEX(fem.ghz2.tssipos, SSB_SPROM8_FEM2G, 6378a5ac6ecd56756ee72588627aa23ab6cf9b790dbRafał Miłecki SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT); 6388a5ac6ecd56756ee72588627aa23ab6cf9b790dbRafał Miłecki SPEX(fem.ghz2.extpa_gain, SSB_SPROM8_FEM2G, 6398a5ac6ecd56756ee72588627aa23ab6cf9b790dbRafał Miłecki SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT); 6408a5ac6ecd56756ee72588627aa23ab6cf9b790dbRafał Miłecki SPEX(fem.ghz2.pdet_range, SSB_SPROM8_FEM2G, 6418a5ac6ecd56756ee72588627aa23ab6cf9b790dbRafał Miłecki SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT); 6428a5ac6ecd56756ee72588627aa23ab6cf9b790dbRafał Miłecki SPEX(fem.ghz2.tr_iso, SSB_SPROM8_FEM2G, 6438a5ac6ecd56756ee72588627aa23ab6cf9b790dbRafał Miłecki SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT); 6448a5ac6ecd56756ee72588627aa23ab6cf9b790dbRafał Miłecki SPEX(fem.ghz2.antswlut, SSB_SPROM8_FEM2G, 6458a5ac6ecd56756ee72588627aa23ab6cf9b790dbRafał Miłecki SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT); 6468a5ac6ecd56756ee72588627aa23ab6cf9b790dbRafał Miłecki 6478a5ac6ecd56756ee72588627aa23ab6cf9b790dbRafał Miłecki SPEX(fem.ghz5.tssipos, SSB_SPROM8_FEM5G, 6488a5ac6ecd56756ee72588627aa23ab6cf9b790dbRafał Miłecki SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT); 6498a5ac6ecd56756ee72588627aa23ab6cf9b790dbRafał Miłecki SPEX(fem.ghz5.extpa_gain, SSB_SPROM8_FEM5G, 6508a5ac6ecd56756ee72588627aa23ab6cf9b790dbRafał Miłecki SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT); 6518a5ac6ecd56756ee72588627aa23ab6cf9b790dbRafał Miłecki SPEX(fem.ghz5.pdet_range, SSB_SPROM8_FEM5G, 6528a5ac6ecd56756ee72588627aa23ab6cf9b790dbRafał Miłecki SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT); 6538a5ac6ecd56756ee72588627aa23ab6cf9b790dbRafał Miłecki SPEX(fem.ghz5.tr_iso, SSB_SPROM8_FEM5G, 6548a5ac6ecd56756ee72588627aa23ab6cf9b790dbRafał Miłecki SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT); 6558a5ac6ecd56756ee72588627aa23ab6cf9b790dbRafał Miłecki SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G, 6568a5ac6ecd56756ee72588627aa23ab6cf9b790dbRafał Miłecki SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT); 6578a5ac6ecd56756ee72588627aa23ab6cf9b790dbRafał Miłecki 658172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki sprom_extract_r458(out, in); 659172c69a47675dc1ca9c7243c031d8d77701bccc0Rafał Miłecki 6606b1c7c67603efdf0b39f6056989b0f8194cdc1f3Michael Buesch /* TODO - get remaining rev 8 stuff needed */ 6616b1c7c67603efdf0b39f6056989b0f8194cdc1f3Michael Buesch} 6626b1c7c67603efdf0b39f6056989b0f8194cdc1f3Michael Buesch 663c272ef4403c271799a7f09a4ab7a236c86643843Larry Fingerstatic int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out, 664c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger const u16 *in, u16 size) 66561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 66661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch memset(out, 0, sizeof(*out)); 66761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 668c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger out->revision = in[size - 1] & 0x00FF; 669e861b98d5e1be769ca6483b6df97149b956ea834Michael Buesch ssb_dprintk(KERN_DEBUG PFX "SPROM revision %d detected.\n", out->revision); 67031ce12fb3ebf88b054deb99ad729e84888bf6125Larry Finger memset(out->et0mac, 0xFF, 6); /* preset et0 and et1 mac */ 67131ce12fb3ebf88b054deb99ad729e84888bf6125Larry Finger memset(out->et1mac, 0xFF, 6); 67254435f9ec837cf0bb0ea02a2bb6362a6aaef5250Rafał Miłecki 67361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if ((bus->chip_id & 0xFF00) == 0x4400) { 67461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch /* Workaround: The BCM44XX chip has a stupid revision 67561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch * number stored in the SPROM. 67661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch * Always extract r1. */ 677c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger out->revision = 1; 67854435f9ec837cf0bb0ea02a2bb6362a6aaef5250Rafał Miłecki ssb_dprintk(KERN_DEBUG PFX "SPROM treated as revision %d\n", out->revision); 67954435f9ec837cf0bb0ea02a2bb6362a6aaef5250Rafał Miłecki } 68054435f9ec837cf0bb0ea02a2bb6362a6aaef5250Rafał Miłecki 68154435f9ec837cf0bb0ea02a2bb6362a6aaef5250Rafał Miłecki switch (out->revision) { 68254435f9ec837cf0bb0ea02a2bb6362a6aaef5250Rafał Miłecki case 1: 68354435f9ec837cf0bb0ea02a2bb6362a6aaef5250Rafał Miłecki case 2: 68454435f9ec837cf0bb0ea02a2bb6362a6aaef5250Rafał Miłecki case 3: 68554435f9ec837cf0bb0ea02a2bb6362a6aaef5250Rafał Miłecki sprom_extract_r123(out, in); 68654435f9ec837cf0bb0ea02a2bb6362a6aaef5250Rafał Miłecki break; 68754435f9ec837cf0bb0ea02a2bb6362a6aaef5250Rafał Miłecki case 4: 68854435f9ec837cf0bb0ea02a2bb6362a6aaef5250Rafał Miłecki case 5: 689095f695cbb07281682462da0618fffabb499d0beLarry Finger sprom_extract_r45(out, in); 69054435f9ec837cf0bb0ea02a2bb6362a6aaef5250Rafał Miłecki break; 69154435f9ec837cf0bb0ea02a2bb6362a6aaef5250Rafał Miłecki case 8: 69254435f9ec837cf0bb0ea02a2bb6362a6aaef5250Rafał Miłecki sprom_extract_r8(out, in); 69354435f9ec837cf0bb0ea02a2bb6362a6aaef5250Rafał Miłecki break; 69454435f9ec837cf0bb0ea02a2bb6362a6aaef5250Rafał Miłecki default: 69554435f9ec837cf0bb0ea02a2bb6362a6aaef5250Rafał Miłecki ssb_printk(KERN_WARNING PFX "Unsupported SPROM" 69698605c2ed4963c44aa72799e697ae4bc7085ffcdRafał Miłecki " revision %d detected. Will extract" 69754435f9ec837cf0bb0ea02a2bb6362a6aaef5250Rafał Miłecki " v1\n", out->revision); 69854435f9ec837cf0bb0ea02a2bb6362a6aaef5250Rafał Miłecki out->revision = 1; 69954435f9ec837cf0bb0ea02a2bb6362a6aaef5250Rafał Miłecki sprom_extract_r123(out, in); 70061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch } 70161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 7024503183aa32e6886400d82282292934fa64a81b0Larry Finger if (out->boardflags_lo == 0xFFFF) 7034503183aa32e6886400d82282292934fa64a81b0Larry Finger out->boardflags_lo = 0; /* per specs */ 7044503183aa32e6886400d82282292934fa64a81b0Larry Finger if (out->boardflags_hi == 0xFFFF) 7054503183aa32e6886400d82282292934fa64a81b0Larry Finger out->boardflags_hi = 0; /* per specs */ 7064503183aa32e6886400d82282292934fa64a81b0Larry Finger 70761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return 0; 70861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 70961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 71061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschstatic int ssb_pci_sprom_get(struct ssb_bus *bus, 71161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch struct ssb_sprom *sprom) 71261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 713ca4a0831917d6541b45f03542257fcb20dc9cf4aRafał Miłecki int err; 71461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch u16 *buf; 71561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 716d53cdbb94a52a920d5420ed64d986c3523a56743John W. Linville if (!ssb_is_sprom_available(bus)) { 717d53cdbb94a52a920d5420ed64d986c3523a56743John W. Linville ssb_printk(KERN_ERR PFX "No SPROM available!\n"); 718d53cdbb94a52a920d5420ed64d986c3523a56743John W. Linville return -ENODEV; 719d53cdbb94a52a920d5420ed64d986c3523a56743John W. Linville } 72025985edcedea6396277003854657b5f3cb31a628Lucas De Marchi if (bus->chipco.dev) { /* can be unavailable! */ 7219d1ac34ec3a67713308ae0883c3359c557f14d17Larry Finger /* 7229d1ac34ec3a67713308ae0883c3359c557f14d17Larry Finger * get SPROM offset: SSB_SPROM_BASE1 except for 7239d1ac34ec3a67713308ae0883c3359c557f14d17Larry Finger * chipcommon rev >= 31 or chip ID is 0x4312 and 7249d1ac34ec3a67713308ae0883c3359c557f14d17Larry Finger * chipcommon status & 3 == 2 7259d1ac34ec3a67713308ae0883c3359c557f14d17Larry Finger */ 7269d1ac34ec3a67713308ae0883c3359c557f14d17Larry Finger if (bus->chipco.dev->id.revision >= 31) 7279d1ac34ec3a67713308ae0883c3359c557f14d17Larry Finger bus->sprom_offset = SSB_SPROM_BASE31; 7289d1ac34ec3a67713308ae0883c3359c557f14d17Larry Finger else if (bus->chip_id == 0x4312 && 7299d1ac34ec3a67713308ae0883c3359c557f14d17Larry Finger (bus->chipco.status & 0x03) == 2) 7309d1ac34ec3a67713308ae0883c3359c557f14d17Larry Finger bus->sprom_offset = SSB_SPROM_BASE31; 7319d1ac34ec3a67713308ae0883c3359c557f14d17Larry Finger else 7329d1ac34ec3a67713308ae0883c3359c557f14d17Larry Finger bus->sprom_offset = SSB_SPROM_BASE1; 733da1fdb02d9200ff28b6f3a380d21930335fe5429Christoph Fritz } else { 734da1fdb02d9200ff28b6f3a380d21930335fe5429Christoph Fritz bus->sprom_offset = SSB_SPROM_BASE1; 735da1fdb02d9200ff28b6f3a380d21930335fe5429Christoph Fritz } 7369d1ac34ec3a67713308ae0883c3359c557f14d17Larry Finger ssb_dprintk(KERN_INFO PFX "SPROM offset is 0x%x\n", bus->sprom_offset); 737ea2db495f92ad2cf3301623e60cb95b4062bc484Rafał Miłecki 738c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL); 73961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (!buf) 740ca4a0831917d6541b45f03542257fcb20dc9cf4aRafał Miłecki return -ENOMEM; 741c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger bus->sprom_size = SSB_SPROMSIZE_WORDS_R123; 74261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch sprom_do_read(bus, buf); 743c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger err = sprom_check_crc(buf, bus->sprom_size); 74461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (err) { 7452afc49015db927fea7bc6ca33c0a60bf5d7c2c5fLarry.Finger@lwfinger.net /* try for a 440 byte SPROM - revision 4 and higher */ 7462afc49015db927fea7bc6ca33c0a60bf5d7c2c5fLarry.Finger@lwfinger.net kfree(buf); 7472afc49015db927fea7bc6ca33c0a60bf5d7c2c5fLarry.Finger@lwfinger.net buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16), 7482afc49015db927fea7bc6ca33c0a60bf5d7c2c5fLarry.Finger@lwfinger.net GFP_KERNEL); 7492afc49015db927fea7bc6ca33c0a60bf5d7c2c5fLarry.Finger@lwfinger.net if (!buf) 750ca4a0831917d6541b45f03542257fcb20dc9cf4aRafał Miłecki return -ENOMEM; 7512afc49015db927fea7bc6ca33c0a60bf5d7c2c5fLarry.Finger@lwfinger.net bus->sprom_size = SSB_SPROMSIZE_WORDS_R4; 7522afc49015db927fea7bc6ca33c0a60bf5d7c2c5fLarry.Finger@lwfinger.net sprom_do_read(bus, buf); 7532afc49015db927fea7bc6ca33c0a60bf5d7c2c5fLarry.Finger@lwfinger.net err = sprom_check_crc(buf, bus->sprom_size); 754e79c1ba84c68de9161d541bd2bcc8ea65c89955cMichael Buesch if (err) { 755e79c1ba84c68de9161d541bd2bcc8ea65c89955cMichael Buesch /* All CRC attempts failed. 756e79c1ba84c68de9161d541bd2bcc8ea65c89955cMichael Buesch * Maybe there is no SPROM on the device? 757b3ae52b6b0335eba547221aad2cb3c50902e3d2dHauke Mehrtens * Now we ask the arch code if there is some sprom 758b3ae52b6b0335eba547221aad2cb3c50902e3d2dHauke Mehrtens * available for this device in some other storage */ 759b3ae52b6b0335eba547221aad2cb3c50902e3d2dHauke Mehrtens err = ssb_fill_sprom_with_fallback(bus, sprom); 760b3ae52b6b0335eba547221aad2cb3c50902e3d2dHauke Mehrtens if (err) { 761b3ae52b6b0335eba547221aad2cb3c50902e3d2dHauke Mehrtens ssb_printk(KERN_WARNING PFX "WARNING: Using" 762b3ae52b6b0335eba547221aad2cb3c50902e3d2dHauke Mehrtens " fallback SPROM failed (err %d)\n", 763b3ae52b6b0335eba547221aad2cb3c50902e3d2dHauke Mehrtens err); 764b3ae52b6b0335eba547221aad2cb3c50902e3d2dHauke Mehrtens } else { 765b3ae52b6b0335eba547221aad2cb3c50902e3d2dHauke Mehrtens ssb_dprintk(KERN_DEBUG PFX "Using SPROM" 766b3ae52b6b0335eba547221aad2cb3c50902e3d2dHauke Mehrtens " revision %d provided by" 767b3ae52b6b0335eba547221aad2cb3c50902e3d2dHauke Mehrtens " platform.\n", sprom->revision); 768e79c1ba84c68de9161d541bd2bcc8ea65c89955cMichael Buesch err = 0; 769e79c1ba84c68de9161d541bd2bcc8ea65c89955cMichael Buesch goto out_free; 770e79c1ba84c68de9161d541bd2bcc8ea65c89955cMichael Buesch } 771c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger ssb_printk(KERN_WARNING PFX "WARNING: Invalid" 772c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger " SPROM CRC (corrupt SPROM)\n"); 773e79c1ba84c68de9161d541bd2bcc8ea65c89955cMichael Buesch } 77461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch } 775c272ef4403c271799a7f09a4ab7a236c86643843Larry Finger err = sprom_extract(bus, sprom, buf, bus->sprom_size); 77661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 777e79c1ba84c68de9161d541bd2bcc8ea65c89955cMichael Bueschout_free: 77861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch kfree(buf); 77961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return err; 78061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 78161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 78261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschstatic void ssb_pci_get_boardinfo(struct ssb_bus *bus, 78361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch struct ssb_boardinfo *bi) 78461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 785115f9450babbf2ed530db04e16a99df28cec85ddSergei Shtylyov bi->vendor = bus->host_pci->subsystem_vendor; 786115f9450babbf2ed530db04e16a99df28cec85ddSergei Shtylyov bi->type = bus->host_pci->subsystem_device; 7872fa2319027dd498edde332afe9a27f1b34b34d7fSergei Shtylyov bi->rev = bus->host_pci->revision; 78861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 78961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 79061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschint ssb_pci_get_invariants(struct ssb_bus *bus, 79161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch struct ssb_init_invariants *iv) 79261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 79361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch int err; 79461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 79561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch err = ssb_pci_sprom_get(bus, &iv->sprom); 79661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (err) 79761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch goto out; 79861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch ssb_pci_get_boardinfo(bus, &iv->boardinfo); 79961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 80061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschout: 80161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return err; 80261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 80361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 80461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch#ifdef CONFIG_SSB_DEBUG 80561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschstatic int ssb_pci_assert_buspower(struct ssb_bus *bus) 80661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 80761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (likely(bus->powered_up)) 80861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return 0; 80961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 81061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch printk(KERN_ERR PFX "FATAL ERROR: Bus powered down " 81161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch "while accessing PCI MMIO space\n"); 81261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (bus->power_warn_count <= 10) { 81361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch bus->power_warn_count++; 81461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch dump_stack(); 81561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch } 81661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 81761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return -ENODEV; 81861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 81961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch#else /* DEBUG */ 82061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschstatic inline int ssb_pci_assert_buspower(struct ssb_bus *bus) 82161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 82261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return 0; 82361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 82461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch#endif /* DEBUG */ 82561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 826ffc7689ddae5cbe12bde437ae0f2b386d568b5cdMichael Bueschstatic u8 ssb_pci_read8(struct ssb_device *dev, u16 offset) 827ffc7689ddae5cbe12bde437ae0f2b386d568b5cdMichael Buesch{ 828ffc7689ddae5cbe12bde437ae0f2b386d568b5cdMichael Buesch struct ssb_bus *bus = dev->bus; 829ffc7689ddae5cbe12bde437ae0f2b386d568b5cdMichael Buesch 830ffc7689ddae5cbe12bde437ae0f2b386d568b5cdMichael Buesch if (unlikely(ssb_pci_assert_buspower(bus))) 831ffc7689ddae5cbe12bde437ae0f2b386d568b5cdMichael Buesch return 0xFF; 832ffc7689ddae5cbe12bde437ae0f2b386d568b5cdMichael Buesch if (unlikely(bus->mapped_device != dev)) { 833ffc7689ddae5cbe12bde437ae0f2b386d568b5cdMichael Buesch if (unlikely(ssb_pci_switch_core(bus, dev))) 834ffc7689ddae5cbe12bde437ae0f2b386d568b5cdMichael Buesch return 0xFF; 835ffc7689ddae5cbe12bde437ae0f2b386d568b5cdMichael Buesch } 836ffc7689ddae5cbe12bde437ae0f2b386d568b5cdMichael Buesch return ioread8(bus->mmio + offset); 837ffc7689ddae5cbe12bde437ae0f2b386d568b5cdMichael Buesch} 838ffc7689ddae5cbe12bde437ae0f2b386d568b5cdMichael Buesch 83961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschstatic u16 ssb_pci_read16(struct ssb_device *dev, u16 offset) 84061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 84161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch struct ssb_bus *bus = dev->bus; 84261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 84361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (unlikely(ssb_pci_assert_buspower(bus))) 84461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return 0xFFFF; 84561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (unlikely(bus->mapped_device != dev)) { 84661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (unlikely(ssb_pci_switch_core(bus, dev))) 84761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return 0xFFFF; 84861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch } 8494b402c65a3a17257af45875159395278e4a2f0cdMichael Buesch return ioread16(bus->mmio + offset); 85061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 85161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 85261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschstatic u32 ssb_pci_read32(struct ssb_device *dev, u16 offset) 85361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 85461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch struct ssb_bus *bus = dev->bus; 85561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 85661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (unlikely(ssb_pci_assert_buspower(bus))) 85761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return 0xFFFFFFFF; 85861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (unlikely(bus->mapped_device != dev)) { 85961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (unlikely(ssb_pci_switch_core(bus, dev))) 86061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return 0xFFFFFFFF; 86161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch } 8624b402c65a3a17257af45875159395278e4a2f0cdMichael Buesch return ioread32(bus->mmio + offset); 86361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 86461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 865d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch#ifdef CONFIG_SSB_BLOCKIO 866d625a29ba649a4df6027520ffc378f23c0e6883eMichael Bueschstatic void ssb_pci_block_read(struct ssb_device *dev, void *buffer, 867d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch size_t count, u16 offset, u8 reg_width) 868d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch{ 869d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch struct ssb_bus *bus = dev->bus; 870d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch void __iomem *addr = bus->mmio + offset; 871d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch 872d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch if (unlikely(ssb_pci_assert_buspower(bus))) 873d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch goto error; 874d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch if (unlikely(bus->mapped_device != dev)) { 875d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch if (unlikely(ssb_pci_switch_core(bus, dev))) 876d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch goto error; 877d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch } 878d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch switch (reg_width) { 879d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch case sizeof(u8): 880d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch ioread8_rep(addr, buffer, count); 881d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch break; 882d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch case sizeof(u16): 883d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch SSB_WARN_ON(count & 1); 884d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch ioread16_rep(addr, buffer, count >> 1); 885d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch break; 886d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch case sizeof(u32): 887d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch SSB_WARN_ON(count & 3); 888d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch ioread32_rep(addr, buffer, count >> 2); 889d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch break; 890d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch default: 891d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch SSB_WARN_ON(1); 892d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch } 893d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch 894d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch return; 895d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buescherror: 896d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch memset(buffer, 0xFF, count); 897d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch} 898d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch#endif /* CONFIG_SSB_BLOCKIO */ 899d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch 900ffc7689ddae5cbe12bde437ae0f2b386d568b5cdMichael Bueschstatic void ssb_pci_write8(struct ssb_device *dev, u16 offset, u8 value) 901ffc7689ddae5cbe12bde437ae0f2b386d568b5cdMichael Buesch{ 902ffc7689ddae5cbe12bde437ae0f2b386d568b5cdMichael Buesch struct ssb_bus *bus = dev->bus; 903ffc7689ddae5cbe12bde437ae0f2b386d568b5cdMichael Buesch 904ffc7689ddae5cbe12bde437ae0f2b386d568b5cdMichael Buesch if (unlikely(ssb_pci_assert_buspower(bus))) 905ffc7689ddae5cbe12bde437ae0f2b386d568b5cdMichael Buesch return; 906ffc7689ddae5cbe12bde437ae0f2b386d568b5cdMichael Buesch if (unlikely(bus->mapped_device != dev)) { 907ffc7689ddae5cbe12bde437ae0f2b386d568b5cdMichael Buesch if (unlikely(ssb_pci_switch_core(bus, dev))) 908ffc7689ddae5cbe12bde437ae0f2b386d568b5cdMichael Buesch return; 909ffc7689ddae5cbe12bde437ae0f2b386d568b5cdMichael Buesch } 910ffc7689ddae5cbe12bde437ae0f2b386d568b5cdMichael Buesch iowrite8(value, bus->mmio + offset); 911ffc7689ddae5cbe12bde437ae0f2b386d568b5cdMichael Buesch} 912ffc7689ddae5cbe12bde437ae0f2b386d568b5cdMichael Buesch 91361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschstatic void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value) 91461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 91561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch struct ssb_bus *bus = dev->bus; 91661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 91761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (unlikely(ssb_pci_assert_buspower(bus))) 91861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return; 91961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (unlikely(bus->mapped_device != dev)) { 92061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (unlikely(ssb_pci_switch_core(bus, dev))) 92161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return; 92261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch } 9234b402c65a3a17257af45875159395278e4a2f0cdMichael Buesch iowrite16(value, bus->mmio + offset); 92461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 92561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 92661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschstatic void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value) 92761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 92861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch struct ssb_bus *bus = dev->bus; 92961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 93061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (unlikely(ssb_pci_assert_buspower(bus))) 93161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return; 93261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (unlikely(bus->mapped_device != dev)) { 93361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (unlikely(ssb_pci_switch_core(bus, dev))) 93461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return; 93561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch } 9364b402c65a3a17257af45875159395278e4a2f0cdMichael Buesch iowrite32(value, bus->mmio + offset); 93761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 93861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 939d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch#ifdef CONFIG_SSB_BLOCKIO 940d625a29ba649a4df6027520ffc378f23c0e6883eMichael Bueschstatic void ssb_pci_block_write(struct ssb_device *dev, const void *buffer, 941d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch size_t count, u16 offset, u8 reg_width) 942d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch{ 943d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch struct ssb_bus *bus = dev->bus; 944d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch void __iomem *addr = bus->mmio + offset; 945d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch 946d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch if (unlikely(ssb_pci_assert_buspower(bus))) 947d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch return; 948d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch if (unlikely(bus->mapped_device != dev)) { 949d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch if (unlikely(ssb_pci_switch_core(bus, dev))) 950d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch return; 951d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch } 952d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch switch (reg_width) { 953d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch case sizeof(u8): 954d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch iowrite8_rep(addr, buffer, count); 955d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch break; 956d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch case sizeof(u16): 957d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch SSB_WARN_ON(count & 1); 958d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch iowrite16_rep(addr, buffer, count >> 1); 959d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch break; 960d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch case sizeof(u32): 961d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch SSB_WARN_ON(count & 3); 962d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch iowrite32_rep(addr, buffer, count >> 2); 963d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch break; 964d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch default: 965d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch SSB_WARN_ON(1); 966d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch } 967d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch} 968d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch#endif /* CONFIG_SSB_BLOCKIO */ 969d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch 97061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch/* Not "static", as it's used in main.c */ 97161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschconst struct ssb_bus_ops ssb_pci_ops = { 972ffc7689ddae5cbe12bde437ae0f2b386d568b5cdMichael Buesch .read8 = ssb_pci_read8, 97361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch .read16 = ssb_pci_read16, 97461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch .read32 = ssb_pci_read32, 975ffc7689ddae5cbe12bde437ae0f2b386d568b5cdMichael Buesch .write8 = ssb_pci_write8, 97661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch .write16 = ssb_pci_write16, 97761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch .write32 = ssb_pci_write32, 978d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch#ifdef CONFIG_SSB_BLOCKIO 979d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch .block_read = ssb_pci_block_read, 980d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch .block_write = ssb_pci_block_write, 981d625a29ba649a4df6027520ffc378f23c0e6883eMichael Buesch#endif 98261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch}; 98361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 98461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschstatic ssize_t ssb_pci_attr_sprom_show(struct device *pcidev, 98561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch struct device_attribute *attr, 98661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch char *buf) 98761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 98861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev); 98961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch struct ssb_bus *bus; 99061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 99161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch bus = ssb_pci_dev_to_bus(pdev); 99261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (!bus) 993e7ec2e3230633a858af1b0b359f6c4670dbeb997Michael Buesch return -ENODEV; 99461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 995e7ec2e3230633a858af1b0b359f6c4670dbeb997Michael Buesch return ssb_attr_sprom_show(bus, buf, sprom_do_read); 99661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 99761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 99861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschstatic ssize_t ssb_pci_attr_sprom_store(struct device *pcidev, 99961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch struct device_attribute *attr, 100061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch const char *buf, size_t count) 100161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 100261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev); 100361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch struct ssb_bus *bus; 100461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 100561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch bus = ssb_pci_dev_to_bus(pdev); 100661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (!bus) 1007e7ec2e3230633a858af1b0b359f6c4670dbeb997Michael Buesch return -ENODEV; 100861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 1009e7ec2e3230633a858af1b0b359f6c4670dbeb997Michael Buesch return ssb_attr_sprom_store(bus, buf, count, 1010e7ec2e3230633a858af1b0b359f6c4670dbeb997Michael Buesch sprom_check_crc, sprom_do_write); 101161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 101261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 101361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschstatic DEVICE_ATTR(ssb_sprom, 0600, 101461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch ssb_pci_attr_sprom_show, 101561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch ssb_pci_attr_sprom_store); 101661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 101761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschvoid ssb_pci_exit(struct ssb_bus *bus) 101861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 101961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch struct pci_dev *pdev; 102061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 102161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (bus->bustype != SSB_BUSTYPE_PCI) 102261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return; 102361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 102461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch pdev = bus->host_pci; 102561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch device_remove_file(&pdev->dev, &dev_attr_ssb_sprom); 102661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 102761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 102861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschint ssb_pci_init(struct ssb_bus *bus) 102961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 103061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch struct pci_dev *pdev; 103161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch int err; 103261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 103361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (bus->bustype != SSB_BUSTYPE_PCI) 103461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return 0; 103561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 103661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch pdev = bus->host_pci; 1037e7ec2e3230633a858af1b0b359f6c4670dbeb997Michael Buesch mutex_init(&bus->sprom_mutex); 103861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch err = device_create_file(&pdev->dev, &dev_attr_ssb_sprom); 103961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (err) 104061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch goto out; 104161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 104261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschout: 104361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return err; 104461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 1045