summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/brcm80211/brcmsmac/nicpci.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-05-24 18:54:29 (GMT)
committerLinus Torvalds <torvalds@linux-foundation.org>2012-05-24 18:54:29 (GMT)
commit28f3d717618156c0dcd2f497d791b578a7931d87 (patch)
tree37b11581b51929b5473541e53bd242b3e1a9f666 /drivers/net/wireless/brcm80211/brcmsmac/nicpci.c
parent654443e20dfc0617231f28a07c96a979ee1a0239 (diff)
parent1ca7ee30630e1022dbcf1b51be20580815ffab73 (diff)
downloadlinux-28f3d717618156c0dcd2f497d791b578a7931d87.tar.xz
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull more networking updates from David Miller: "Ok, everything from here on out will be bug fixes." 1) One final sync of wireless and bluetooth stuff from John Linville. These changes have all been in his tree for more than a week, and therefore have had the necessary -next exposure. John was just away on a trip and didn't have a change to send the pull request until a day or two ago. 2) Put back some defines in user exposed header file areas that were removed during the tokenring purge. From Stephen Hemminger and Paul Gortmaker. 3) A bug fix for UDP hash table allocation got lost in the pile due to one of those "you got it.. no I've got it.." situations. :-) From Tim Bird. 4) SKB coalescing in TCP needs to have stricter checks, otherwise we'll try to coalesce overlapping frags and crash. Fix from Eric Dumazet. 5) RCU routing table lookups can race with free_fib_info(), causing crashes when we deref the device pointers in the route. Fix by releasing the net device in the RCU callback. From Yanmin Zhang. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (293 commits) tcp: take care of overlaps in tcp_try_coalesce() ipv4: fix the rcu race between free_fib_info and ip_route_output_slow mm: add a low limit to alloc_large_system_hash ipx: restore token ring define to include/linux/ipx.h if: restore token ring ARP type to header xen: do not disable netfront in dom0 phy/micrel: Fix ID of KSZ9021 mISDN: Add X-Tensions USB ISDN TA XC-525 gianfar:don't add FCB length to hard_header_len Bluetooth: Report proper error number in disconnection Bluetooth: Create flags for bt_sk() Bluetooth: report the right security level in getsockopt Bluetooth: Lock the L2CAP channel when sending Bluetooth: Restore locking semantics when looking up L2CAP channels Bluetooth: Fix a redundant and problematic incoming MTU check Bluetooth: Add support for Foxconn/Hon Hai AR5BBU22 0489:E03C Bluetooth: Fix EIR data generation for mgmt_device_found Bluetooth: Fix Inquiry with RSSI event mask Bluetooth: improve readability of l2cap_seq_list code Bluetooth: Fix skb length calculation ...
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmsmac/nicpci.c')
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/nicpci.c826
1 files changed, 0 insertions, 826 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/nicpci.c b/drivers/net/wireless/brcm80211/brcmsmac/nicpci.c
deleted file mode 100644
index 7fad6dc..0000000
--- a/drivers/net/wireless/brcm80211/brcmsmac/nicpci.c
+++ /dev/null
@@ -1,826 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-
-#include <defs.h>
-#include <soc.h>
-#include <chipcommon.h>
-#include "aiutils.h"
-#include "pub.h"
-#include "nicpci.h"
-
-/* SPROM offsets */
-#define SRSH_ASPM_OFFSET 4 /* word 4 */
-#define SRSH_ASPM_ENB 0x18 /* bit 3, 4 */
-#define SRSH_ASPM_L1_ENB 0x10 /* bit 4 */
-#define SRSH_ASPM_L0s_ENB 0x8 /* bit 3 */
-
-#define SRSH_PCIE_MISC_CONFIG 5 /* word 5 */
-#define SRSH_L23READY_EXIT_NOPERST 0x8000 /* bit 15 */
-#define SRSH_CLKREQ_OFFSET_REV5 20 /* word 20 for srom rev <= 5 */
-#define SRSH_CLKREQ_ENB 0x0800 /* bit 11 */
-#define SRSH_BD_OFFSET 6 /* word 6 */
-
-/* chipcontrol */
-#define CHIPCTRL_4321_PLL_DOWN 0x800000/* serdes PLL down override */
-
-/* MDIO control */
-#define MDIOCTL_DIVISOR_MASK 0x7f /* clock to be used on MDIO */
-#define MDIOCTL_DIVISOR_VAL 0x2
-#define MDIOCTL_PREAM_EN 0x80 /* Enable preamble sequnce */
-#define MDIOCTL_ACCESS_DONE 0x100 /* Transaction complete */
-
-/* MDIO Data */
-#define MDIODATA_MASK 0x0000ffff /* data 2 bytes */
-#define MDIODATA_TA 0x00020000 /* Turnaround */
-
-#define MDIODATA_REGADDR_SHF 18 /* Regaddr shift */
-#define MDIODATA_REGADDR_MASK 0x007c0000 /* Regaddr Mask */
-#define MDIODATA_DEVADDR_SHF 23 /* Physmedia devaddr shift */
-#define MDIODATA_DEVADDR_MASK 0x0f800000
- /* Physmedia devaddr Mask */
-
-/* MDIO Data for older revisions < 10 */
-#define MDIODATA_REGADDR_SHF_OLD 18 /* Regaddr shift */
-#define MDIODATA_REGADDR_MASK_OLD 0x003c0000
- /* Regaddr Mask */
-#define MDIODATA_DEVADDR_SHF_OLD 22 /* Physmedia devaddr shift */
-#define MDIODATA_DEVADDR_MASK_OLD 0x0fc00000
- /* Physmedia devaddr Mask */
-
-/* Transactions flags */
-#define MDIODATA_WRITE 0x10000000
-#define MDIODATA_READ 0x20000000
-#define MDIODATA_START 0x40000000
-
-#define MDIODATA_DEV_ADDR 0x0 /* dev address for serdes */
-#define MDIODATA_BLK_ADDR 0x1F /* blk address for serdes */
-
-/* serdes regs (rev < 10) */
-#define MDIODATA_DEV_PLL 0x1d /* SERDES PLL Dev */
-#define MDIODATA_DEV_TX 0x1e /* SERDES TX Dev */
-#define MDIODATA_DEV_RX 0x1f /* SERDES RX Dev */
-
-/* SERDES RX registers */
-#define SERDES_RX_CTRL 1 /* Rx cntrl */
-#define SERDES_RX_TIMER1 2 /* Rx Timer1 */
-#define SERDES_RX_CDR 6 /* CDR */
-#define SERDES_RX_CDRBW 7 /* CDR BW */
-/* SERDES RX control register */
-#define SERDES_RX_CTRL_FORCE 0x80 /* rxpolarity_force */
-#define SERDES_RX_CTRL_POLARITY 0x40 /* rxpolarity_value */
-
-/* SERDES PLL registers */
-#define SERDES_PLL_CTRL 1 /* PLL control reg */
-#define PLL_CTRL_FREQDET_EN 0x4000 /* bit 14 is FREQDET on */
-
-/* Linkcontrol reg offset in PCIE Cap */
-#define PCIE_CAP_LINKCTRL_OFFSET 16 /* offset in pcie cap */
-#define PCIE_CAP_LCREG_ASPML0s 0x01 /* ASPM L0s in linkctrl */
-#define PCIE_CAP_LCREG_ASPML1 0x02 /* ASPM L1 in linkctrl */
-#define PCIE_CLKREQ_ENAB 0x100 /* CLKREQ Enab in linkctrl */
-
-#define PCIE_ASPM_ENAB 3 /* ASPM L0s & L1 in linkctrl */
-#define PCIE_ASPM_L1_ENAB 2 /* ASPM L0s & L1 in linkctrl */
-#define PCIE_ASPM_L0s_ENAB 1 /* ASPM L0s & L1 in linkctrl */
-#define PCIE_ASPM_DISAB 0 /* ASPM L0s & L1 in linkctrl */
-
-/* Power management threshold */
-#define PCIE_L1THRESHOLDTIME_MASK 0xFF00 /* bits 8 - 15 */
-#define PCIE_L1THRESHOLDTIME_SHIFT 8 /* PCIE_L1THRESHOLDTIME_SHIFT */
-#define PCIE_L1THRESHOLD_WARVAL 0x72 /* WAR value */
-#define PCIE_ASPMTIMER_EXTEND 0x01000000
- /* > rev7:
- * enable extend ASPM timer
- */
-
-/* different register spaces to access thru pcie indirect access */
-#define PCIE_CONFIGREGS 1 /* Access to config space */
-#define PCIE_PCIEREGS 2 /* Access to pcie registers */
-
-/* PCIE protocol PHY diagnostic registers */
-#define PCIE_PLP_STATUSREG 0x204 /* Status */
-
-/* Status reg PCIE_PLP_STATUSREG */
-#define PCIE_PLP_POLARITYINV_STAT 0x10
-
-/* PCIE protocol DLLP diagnostic registers */
-#define PCIE_DLLP_LCREG 0x100 /* Link Control */
-#define PCIE_DLLP_PMTHRESHREG 0x128 /* Power Management Threshold */
-
-/* PCIE protocol TLP diagnostic registers */
-#define PCIE_TLP_WORKAROUNDSREG 0x004 /* TLP Workarounds */
-
-/* Sonics to PCI translation types */
-#define SBTOPCI_PREF 0x4 /* prefetch enable */
-#define SBTOPCI_BURST 0x8 /* burst enable */
-#define SBTOPCI_RC_READMULTI 0x20 /* memory read multiple */
-
-#define PCI_CLKRUN_DSBL 0x8000 /* Bit 15 forceClkrun */
-
-/* PCI core index in SROM shadow area */
-#define SRSH_PI_OFFSET 0 /* first word */
-#define SRSH_PI_MASK 0xf000 /* bit 15:12 */
-#define SRSH_PI_SHIFT 12 /* bit 15:12 */
-
-#define PCIREGOFFS(field) offsetof(struct sbpciregs, field)
-#define PCIEREGOFFS(field) offsetof(struct sbpcieregs, field)
-
-/* Sonics side: PCI core and host control registers */
-struct sbpciregs {
- u32 control; /* PCI control */
- u32 PAD[3];
- u32 arbcontrol; /* PCI arbiter control */
- u32 clkrun; /* Clkrun Control (>=rev11) */
- u32 PAD[2];
- u32 intstatus; /* Interrupt status */
- u32 intmask; /* Interrupt mask */
- u32 sbtopcimailbox; /* Sonics to PCI mailbox */
- u32 PAD[9];
- u32 bcastaddr; /* Sonics broadcast address */
- u32 bcastdata; /* Sonics broadcast data */
- u32 PAD[2];
- u32 gpioin; /* ro: gpio input (>=rev2) */
- u32 gpioout; /* rw: gpio output (>=rev2) */
- u32 gpioouten; /* rw: gpio output enable (>= rev2) */
- u32 gpiocontrol; /* rw: gpio control (>= rev2) */
- u32 PAD[36];
- u32 sbtopci0; /* Sonics to PCI translation 0 */
- u32 sbtopci1; /* Sonics to PCI translation 1 */
- u32 sbtopci2; /* Sonics to PCI translation 2 */
- u32 PAD[189];
- u32 pcicfg[4][64]; /* 0x400 - 0x7FF, PCI Cfg Space (>=rev8) */
- u16 sprom[36]; /* SPROM shadow Area */
- u32 PAD[46];
-};
-
-/* SB side: PCIE core and host control registers */
-struct sbpcieregs {
- u32 control; /* host mode only */
- u32 PAD[2];
- u32 biststatus; /* bist Status: 0x00C */
- u32 gpiosel; /* PCIE gpio sel: 0x010 */
- u32 gpioouten; /* PCIE gpio outen: 0x14 */
- u32 PAD[2];
- u32 intstatus; /* Interrupt status: 0x20 */
- u32 intmask; /* Interrupt mask: 0x24 */
- u32 sbtopcimailbox; /* sb to pcie mailbox: 0x028 */
- u32 PAD[53];
- u32 sbtopcie0; /* sb to pcie translation 0: 0x100 */
- u32 sbtopcie1; /* sb to pcie translation 1: 0x104 */
- u32 sbtopcie2; /* sb to pcie translation 2: 0x108 */
- u32 PAD[5];
-
- /* pcie core supports in direct access to config space */
- u32 configaddr; /* pcie config space access: Address field: 0x120 */
- u32 configdata; /* pcie config space access: Data field: 0x124 */
-
- /* mdio access to serdes */
- u32 mdiocontrol; /* controls the mdio access: 0x128 */
- u32 mdiodata; /* Data to the mdio access: 0x12c */
-
- /* pcie protocol phy/dllp/tlp register indirect access mechanism */
- u32 pcieindaddr; /* indirect access to
- * the internal register: 0x130
- */
- u32 pcieinddata; /* Data to/from the internal regsiter: 0x134 */
-
- u32 clkreqenctrl; /* >= rev 6, Clkreq rdma control : 0x138 */
- u32 PAD[177];
- u32 pciecfg[4][64]; /* 0x400 - 0x7FF, PCIE Cfg Space */
- u16 sprom[64]; /* SPROM shadow Area */
-};
-
-struct pcicore_info {
- struct bcma_device *core;
- struct si_pub *sih; /* System interconnect handle */
- struct pci_dev *dev;
- u8 pciecap_lcreg_offset;/* PCIE capability LCreg offset
- * in the config space
- */
- bool pcie_pr42767;
- u8 pcie_polarity;
- u8 pcie_war_aspm_ovr; /* Override ASPM/Clkreq settings */
-
- u8 pmecap_offset; /* PM Capability offset in the config space */
- bool pmecap; /* Capable of generating PME */
-};
-
-#define PCIE_ASPM(sih) \
- ((ai_get_buscoretype(sih) == PCIE_CORE_ID) && \
- ((ai_get_buscorerev(sih) >= 3) && \
- (ai_get_buscorerev(sih) <= 5)))
-
-
-/* delay needed between the mdio control/ mdiodata register data access */
-static void pr28829_delay(void)
-{
- udelay(10);
-}
-
-/* Initialize the PCI core.
- * It's caller's responsibility to make sure that this is done only once
- */
-struct pcicore_info *pcicore_init(struct si_pub *sih, struct bcma_device *core)
-{
- struct pcicore_info *pi;
-
- /* alloc struct pcicore_info */
- pi = kzalloc(sizeof(struct pcicore_info), GFP_ATOMIC);
- if (pi == NULL)
- return NULL;
-
- pi->sih = sih;
- pi->dev = core->bus->host_pci;
- pi->core = core;
-
- if (core->id.id == PCIE_CORE_ID) {
- u8 cap_ptr;
- cap_ptr = pcicore_find_pci_capability(pi->dev, PCI_CAP_ID_EXP,
- NULL, NULL);
- pi->pciecap_lcreg_offset = cap_ptr + PCIE_CAP_LINKCTRL_OFFSET;
- }
- return pi;
-}
-
-void pcicore_deinit(struct pcicore_info *pch)
-{
- kfree(pch);
-}
-
-/* return cap_offset if requested capability exists in the PCI config space */
-/* Note that it's caller's responsibility to make sure it's a pci bus */
-u8
-pcicore_find_pci_capability(struct pci_dev *dev, u8 req_cap_id,
- unsigned char *buf, u32 *buflen)
-{
- u8 cap_id;
- u8 cap_ptr = 0;
- u32 bufsize;
- u8 byte_val;
-
- /* check for Header type 0 */
- pci_read_config_byte(dev, PCI_HEADER_TYPE, &byte_val);
- if ((byte_val & 0x7f) != PCI_HEADER_TYPE_NORMAL)
- goto end;
-
- /* check if the capability pointer field exists */
- pci_read_config_byte(dev, PCI_STATUS, &byte_val);
- if (!(byte_val & PCI_STATUS_CAP_LIST))
- goto end;
-
- pci_read_config_byte(dev, PCI_CAPABILITY_LIST, &cap_ptr);
- /* check if the capability pointer is 0x00 */
- if (cap_ptr == 0x00)
- goto end;
-
- /* loop thru the capability list
- * and see if the pcie capability exists
- */
-
- pci_read_config_byte(dev, cap_ptr, &cap_id);
-
- while (cap_id != req_cap_id) {
- pci_read_config_byte(dev, cap_ptr + 1, &cap_ptr);
- if (cap_ptr == 0x00)
- break;
- pci_read_config_byte(dev, cap_ptr, &cap_id);
- }
- if (cap_id != req_cap_id)
- goto end;
-
- /* found the caller requested capability */
- if (buf != NULL && buflen != NULL) {
- u8 cap_data;
-
- bufsize = *buflen;
- if (!bufsize)
- goto end;
- *buflen = 0;
- /* copy the capability data excluding cap ID and next ptr */
- cap_data = cap_ptr + 2;
- if ((bufsize + cap_data) > PCI_SZPCR)
- bufsize = PCI_SZPCR - cap_data;
- *buflen = bufsize;
- while (bufsize--) {
- pci_read_config_byte(dev, cap_data, buf);
- cap_data++;
- buf++;
- }
- }
-end:
- return cap_ptr;
-}
-
-/* ***** Register Access API */
-static uint
-pcie_readreg(struct bcma_device *core, uint addrtype, uint offset)
-{
- uint retval = 0xFFFFFFFF;
-
- switch (addrtype) {
- case PCIE_CONFIGREGS:
- bcma_write32(core, PCIEREGOFFS(configaddr), offset);
- (void)bcma_read32(core, PCIEREGOFFS(configaddr));
- retval = bcma_read32(core, PCIEREGOFFS(configdata));
- break;
- case PCIE_PCIEREGS:
- bcma_write32(core, PCIEREGOFFS(pcieindaddr), offset);
- (void)bcma_read32(core, PCIEREGOFFS(pcieindaddr));
- retval = bcma_read32(core, PCIEREGOFFS(pcieinddata));
- break;
- }
-
- return retval;
-}
-
-static uint pcie_writereg(struct bcma_device *core, uint addrtype,
- uint offset, uint val)
-{
- switch (addrtype) {
- case PCIE_CONFIGREGS:
- bcma_write32(core, PCIEREGOFFS(configaddr), offset);
- bcma_write32(core, PCIEREGOFFS(configdata), val);
- break;
- case PCIE_PCIEREGS:
- bcma_write32(core, PCIEREGOFFS(pcieindaddr), offset);
- bcma_write32(core, PCIEREGOFFS(pcieinddata), val);
- break;
- default:
- break;
- }
- return 0;
-}
-
-static bool pcie_mdiosetblock(struct pcicore_info *pi, uint blk)
-{
- uint mdiodata, i = 0;
- uint pcie_serdes_spinwait = 200;
-
- mdiodata = (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA |
- (MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) |
- (MDIODATA_BLK_ADDR << MDIODATA_REGADDR_SHF) |
- (blk << 4));
- bcma_write32(pi->core, PCIEREGOFFS(mdiodata), mdiodata);
-
- pr28829_delay();
- /* retry till the transaction is complete */
- while (i < pcie_serdes_spinwait) {
- if (bcma_read32(pi->core, PCIEREGOFFS(mdiocontrol)) &
- MDIOCTL_ACCESS_DONE)
- break;
-
- udelay(1000);
- i++;
- }
-
- if (i >= pcie_serdes_spinwait)
- return false;
-
- return true;
-}
-
-static int
-pcie_mdioop(struct pcicore_info *pi, uint physmedia, uint regaddr, bool write,
- uint *val)
-{
- uint mdiodata;
- uint i = 0;
- uint pcie_serdes_spinwait = 10;
-
- /* enable mdio access to SERDES */
- bcma_write32(pi->core, PCIEREGOFFS(mdiocontrol),
- MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL);
-
- if (ai_get_buscorerev(pi->sih) >= 10) {
- /* new serdes is slower in rw,
- * using two layers of reg address mapping
- */
- if (!pcie_mdiosetblock(pi, physmedia))
- return 1;
- mdiodata = ((MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) |
- (regaddr << MDIODATA_REGADDR_SHF));
- pcie_serdes_spinwait *= 20;
- } else {
- mdiodata = ((physmedia << MDIODATA_DEVADDR_SHF_OLD) |
- (regaddr << MDIODATA_REGADDR_SHF_OLD));
- }
-
- if (!write)
- mdiodata |= (MDIODATA_START | MDIODATA_READ | MDIODATA_TA);
- else
- mdiodata |= (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA |
- *val);
-
- bcma_write32(pi->core, PCIEREGOFFS(mdiodata), mdiodata);
-
- pr28829_delay();
-
- /* retry till the transaction is complete */
- while (i < pcie_serdes_spinwait) {
- if (bcma_read32(pi->core, PCIEREGOFFS(mdiocontrol)) &
- MDIOCTL_ACCESS_DONE) {
- if (!write) {
- pr28829_delay();
- *val = (bcma_read32(pi->core,
- PCIEREGOFFS(mdiodata)) &
- MDIODATA_MASK);
- }
- /* Disable mdio access to SERDES */
- bcma_write32(pi->core, PCIEREGOFFS(mdiocontrol), 0);
- return 0;
- }
- udelay(1000);
- i++;
- }
-
- /* Timed out. Disable mdio access to SERDES. */
- bcma_write32(pi->core, PCIEREGOFFS(mdiocontrol), 0);
- return 1;
-}
-
-/* use the mdio interface to read from mdio slaves */
-static int
-pcie_mdioread(struct pcicore_info *pi, uint physmedia, uint regaddr,
- uint *regval)
-{
- return pcie_mdioop(pi, physmedia, regaddr, false, regval);
-}
-
-/* use the mdio interface to write to mdio slaves */
-static int
-pcie_mdiowrite(struct pcicore_info *pi, uint physmedia, uint regaddr, uint val)
-{
- return pcie_mdioop(pi, physmedia, regaddr, true, &val);
-}
-
-/* ***** Support functions ***** */
-static u8 pcie_clkreq(struct pcicore_info *pi, u32 mask, u32 val)
-{
- u32 reg_val;
- u8 offset;
-
- offset = pi->pciecap_lcreg_offset;
- if (!offset)
- return 0;
-
- pci_read_config_dword(pi->dev, offset, &reg_val);
- /* set operation */
- if (mask) {
- if (val)
- reg_val |= PCIE_CLKREQ_ENAB;
- else
- reg_val &= ~PCIE_CLKREQ_ENAB;
- pci_write_config_dword(pi->dev, offset, reg_val);
- pci_read_config_dword(pi->dev, offset, &reg_val);
- }
- if (reg_val & PCIE_CLKREQ_ENAB)
- return 1;
- else
- return 0;
-}
-
-static void pcie_extendL1timer(struct pcicore_info *pi, bool extend)
-{
- u32 w;
- struct si_pub *sih = pi->sih;
-
- if (ai_get_buscoretype(sih) != PCIE_CORE_ID ||
- ai_get_buscorerev(sih) < 7)
- return;
-
- w = pcie_readreg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG);
- if (extend)
- w |= PCIE_ASPMTIMER_EXTEND;
- else
- w &= ~PCIE_ASPMTIMER_EXTEND;
- pcie_writereg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG, w);
- w = pcie_readreg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG);
-}
-
-/* centralized clkreq control policy */
-static void pcie_clkreq_upd(struct pcicore_info *pi, uint state)
-{
- struct si_pub *sih = pi->sih;
-
- switch (state) {
- case SI_DOATTACH:
- if (PCIE_ASPM(sih))
- pcie_clkreq(pi, 1, 0);
- break;
- case SI_PCIDOWN:
- /* turn on serdes PLL down */
- if (ai_get_buscorerev(sih) == 6) {
- ai_cc_reg(sih,
- offsetof(struct chipcregs, chipcontrol_addr),
- ~0, 0);
- ai_cc_reg(sih,
- offsetof(struct chipcregs, chipcontrol_data),
- ~0x40, 0);
- } else if (pi->pcie_pr42767) {
- pcie_clkreq(pi, 1, 1);
- }
- break;
- case SI_PCIUP:
- /* turn off serdes PLL down */
- if (ai_get_buscorerev(sih) == 6) {
- ai_cc_reg(sih,
- offsetof(struct chipcregs, chipcontrol_addr),
- ~0, 0);
- ai_cc_reg(sih,
- offsetof(struct chipcregs, chipcontrol_data),
- ~0x40, 0x40);
- } else if (PCIE_ASPM(sih)) { /* disable clkreq */
- pcie_clkreq(pi, 1, 0);
- }
- break;
- }
-}
-
-/* ***** PCI core WARs ***** */
-/* Done only once at attach time */
-static void pcie_war_polarity(struct pcicore_info *pi)
-{
- u32 w;
-
- if (pi->pcie_polarity != 0)
- return;
-
- w = pcie_readreg(pi->core, PCIE_PCIEREGS, PCIE_PLP_STATUSREG);
-
- /* Detect the current polarity at attach and force that polarity and
- * disable changing the polarity
- */
- if ((w & PCIE_PLP_POLARITYINV_STAT) == 0)
- pi->pcie_polarity = SERDES_RX_CTRL_FORCE;
- else
- pi->pcie_polarity = (SERDES_RX_CTRL_FORCE |
- SERDES_RX_CTRL_POLARITY);
-}
-
-/* enable ASPM and CLKREQ if srom doesn't have it */
-/* Needs to happen when update to shadow SROM is needed
- * : Coming out of 'standby'/'hibernate'
- * : If pcie_war_aspm_ovr state changed
- */
-static void pcie_war_aspm_clkreq(struct pcicore_info *pi)
-{
- struct si_pub *sih = pi->sih;
- u16 val16;
- u32 w;
-
- if (!PCIE_ASPM(sih))
- return;
-
- /* bypass this on QT or VSIM */
- val16 = bcma_read16(pi->core, PCIEREGOFFS(sprom[SRSH_ASPM_OFFSET]));
-
- val16 &= ~SRSH_ASPM_ENB;
- if (pi->pcie_war_aspm_ovr == PCIE_ASPM_ENAB)
- val16 |= SRSH_ASPM_ENB;
- else if (pi->pcie_war_aspm_ovr == PCIE_ASPM_L1_ENAB)
- val16 |= SRSH_ASPM_L1_ENB;
- else if (pi->pcie_war_aspm_ovr == PCIE_ASPM_L0s_ENAB)
- val16 |= SRSH_ASPM_L0s_ENB;
-
- bcma_write16(pi->core, PCIEREGOFFS(sprom[SRSH_ASPM_OFFSET]), val16);
-
- pci_read_config_dword(pi->dev, pi->pciecap_lcreg_offset, &w);
- w &= ~PCIE_ASPM_ENAB;
- w |= pi->pcie_war_aspm_ovr;
- pci_write_config_dword(pi->dev, pi->pciecap_lcreg_offset, w);
-
- val16 = bcma_read16(pi->core,
- PCIEREGOFFS(sprom[SRSH_CLKREQ_OFFSET_REV5]));
-
- if (pi->pcie_war_aspm_ovr != PCIE_ASPM_DISAB) {
- val16 |= SRSH_CLKREQ_ENB;
- pi->pcie_pr42767 = true;
- } else
- val16 &= ~SRSH_CLKREQ_ENB;
-
- bcma_write16(pi->core, PCIEREGOFFS(sprom[SRSH_CLKREQ_OFFSET_REV5]),
- val16);
-}
-
-/* Apply the polarity determined at the start */
-/* Needs to happen when coming out of 'standby'/'hibernate' */
-static void pcie_war_serdes(struct pcicore_info *pi)
-{
- u32 w = 0;
-
- if (pi->pcie_polarity != 0)
- pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CTRL,
- pi->pcie_polarity);
-
- pcie_mdioread(pi, MDIODATA_DEV_PLL, SERDES_PLL_CTRL, &w);
- if (w & PLL_CTRL_FREQDET_EN) {
- w &= ~PLL_CTRL_FREQDET_EN;
- pcie_mdiowrite(pi, MDIODATA_DEV_PLL, SERDES_PLL_CTRL, w);
- }
-}
-
-/* Fix MISC config to allow coming out of L2/L3-Ready state w/o PRST */
-/* Needs to happen when coming out of 'standby'/'hibernate' */
-static void pcie_misc_config_fixup(struct pcicore_info *pi)
-{
- u16 val16;
-
- val16 = bcma_read16(pi->core,
- PCIEREGOFFS(sprom[SRSH_PCIE_MISC_CONFIG]));
-
- if ((val16 & SRSH_L23READY_EXIT_NOPERST) == 0) {
- val16 |= SRSH_L23READY_EXIT_NOPERST;
- bcma_write16(pi->core,
- PCIEREGOFFS(sprom[SRSH_PCIE_MISC_CONFIG]), val16);
- }
-}
-
-/* quick hack for testing */
-/* Needs to happen when coming out of 'standby'/'hibernate' */
-static void pcie_war_noplldown(struct pcicore_info *pi)
-{
- /* turn off serdes PLL down */
- ai_cc_reg(pi->sih, offsetof(struct chipcregs, chipcontrol),
- CHIPCTRL_4321_PLL_DOWN, CHIPCTRL_4321_PLL_DOWN);
-
- /* clear srom shadow backdoor */
- bcma_write16(pi->core, PCIEREGOFFS(sprom[SRSH_BD_OFFSET]), 0);
-}
-
-/* Needs to happen when coming out of 'standby'/'hibernate' */
-static void pcie_war_pci_setup(struct pcicore_info *pi)
-{
- struct si_pub *sih = pi->sih;
- u32 w;
-
- if (ai_get_buscorerev(sih) == 0 || ai_get_buscorerev(sih) == 1) {
- w = pcie_readreg(pi->core, PCIE_PCIEREGS,
- PCIE_TLP_WORKAROUNDSREG);
- w |= 0x8;
- pcie_writereg(pi->core, PCIE_PCIEREGS,
- PCIE_TLP_WORKAROUNDSREG, w);
- }
-
- if (ai_get_buscorerev(sih) == 1) {
- w = pcie_readreg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_LCREG);
- w |= 0x40;
- pcie_writereg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_LCREG, w);
- }
-
- if (ai_get_buscorerev(sih) == 0) {
- pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_TIMER1, 0x8128);
- pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CDR, 0x0100);
- pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CDRBW, 0x1466);
- } else if (PCIE_ASPM(sih)) {
- /* Change the L1 threshold for better performance */
- w = pcie_readreg(pi->core, PCIE_PCIEREGS,
- PCIE_DLLP_PMTHRESHREG);
- w &= ~PCIE_L1THRESHOLDTIME_MASK;
- w |= PCIE_L1THRESHOLD_WARVAL << PCIE_L1THRESHOLDTIME_SHIFT;
- pcie_writereg(pi->core, PCIE_PCIEREGS,
- PCIE_DLLP_PMTHRESHREG, w);
-
- pcie_war_serdes(pi);
-
- pcie_war_aspm_clkreq(pi);
- } else if (ai_get_buscorerev(pi->sih) == 7)
- pcie_war_noplldown(pi);
-
- /* Note that the fix is actually in the SROM,
- * that's why this is open-ended
- */
- if (ai_get_buscorerev(pi->sih) >= 6)
- pcie_misc_config_fixup(pi);
-}
-
-/* ***** Functions called during driver state changes ***** */
-void pcicore_attach(struct pcicore_info *pi, int state)
-{
- struct si_pub *sih = pi->sih;
- u32 bfl2 = (u32)getintvar(sih, BRCMS_SROM_BOARDFLAGS2);
-
- /* Determine if this board needs override */
- if (PCIE_ASPM(sih)) {
- if (bfl2 & BFL2_PCIEWAR_OVR)
- pi->pcie_war_aspm_ovr = PCIE_ASPM_DISAB;
- else
- pi->pcie_war_aspm_ovr = PCIE_ASPM_ENAB;
- }
-
- /* These need to happen in this order only */
- pcie_war_polarity(pi);
-
- pcie_war_serdes(pi);
-
- pcie_war_aspm_clkreq(pi);
-
- pcie_clkreq_upd(pi, state);
-
-}
-
-void pcicore_hwup(struct pcicore_info *pi)
-{
- if (!pi || ai_get_buscoretype(pi->sih) != PCIE_CORE_ID)
- return;
-
- pcie_war_pci_setup(pi);
-}
-
-void pcicore_up(struct pcicore_info *pi, int state)
-{
- if (!pi || ai_get_buscoretype(pi->sih) != PCIE_CORE_ID)
- return;
-
- /* Restore L1 timer for better performance */
- pcie_extendL1timer(pi, true);
-
- pcie_clkreq_upd(pi, state);
-}
-
-/* When the device is going to enter D3 state
- * (or the system is going to enter S3/S4 states)
- */
-void pcicore_sleep(struct pcicore_info *pi)
-{
- u32 w;
-
- if (!pi || !PCIE_ASPM(pi->sih))
- return;
-
- pci_read_config_dword(pi->dev, pi->pciecap_lcreg_offset, &w);
- w &= ~PCIE_CAP_LCREG_ASPML1;
- pci_write_config_dword(pi->dev, pi->pciecap_lcreg_offset, w);
-
- pi->pcie_pr42767 = false;
-}
-
-void pcicore_down(struct pcicore_info *pi, int state)
-{
- if (!pi || ai_get_buscoretype(pi->sih) != PCIE_CORE_ID)
- return;
-
- pcie_clkreq_upd(pi, state);
-
- /* Reduce L1 timer for better power savings */
- pcie_extendL1timer(pi, false);
-}
-
-void pcicore_fixcfg(struct pcicore_info *pi)
-{
- struct bcma_device *core = pi->core;
- u16 val16;
- uint regoff;
-
- switch (pi->core->id.id) {
- case BCMA_CORE_PCI:
- regoff = PCIREGOFFS(sprom[SRSH_PI_OFFSET]);
- break;
-
- case BCMA_CORE_PCIE:
- regoff = PCIEREGOFFS(sprom[SRSH_PI_OFFSET]);
- break;
-
- default:
- return;
- }
-
- val16 = bcma_read16(pi->core, regoff);
- if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) !=
- (u16)core->core_index) {
- val16 = ((u16)core->core_index << SRSH_PI_SHIFT) |
- (val16 & ~SRSH_PI_MASK);
- bcma_write16(pi->core, regoff, val16);
- }
-}
-
-/* precondition: current core is pci core */
-void
-pcicore_pci_setup(struct pcicore_info *pi)
-{
- bcma_set32(pi->core, PCIREGOFFS(sbtopci2),
- SBTOPCI_PREF | SBTOPCI_BURST);
-
- if (pi->core->id.rev >= 11) {
- bcma_set32(pi->core, PCIREGOFFS(sbtopci2),
- SBTOPCI_RC_READMULTI);
- bcma_set32(pi->core, PCIREGOFFS(clkrun), PCI_CLKRUN_DSBL);
- (void)bcma_read32(pi->core, PCIREGOFFS(clkrun));
- }
-}