net: wireless: add brcm80211 drivers
[pandora-kernel.git] / drivers / net / wireless / brcm80211 / brcmsmac / nicpci.c
1 /*
2  * Copyright (c) 2010 Broadcom Corporation
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 #include <linux/slab.h>
18 #include <linux/delay.h>
19 #include <linux/pci.h>
20
21 #include <defs.h>
22 #include <soc.h>
23 #include <chipcommon.h>
24 #include "aiutils.h"
25 #include "pub.h"
26 #include "nicpci.h"
27
28 /* SPROM offsets */
29 #define SRSH_ASPM_OFFSET                4       /* word 4 */
30 #define SRSH_ASPM_ENB                   0x18    /* bit 3, 4 */
31 #define SRSH_ASPM_L1_ENB                0x10    /* bit 4 */
32 #define SRSH_ASPM_L0s_ENB               0x8     /* bit 3 */
33
34 #define SRSH_PCIE_MISC_CONFIG           5       /* word 5 */
35 #define SRSH_L23READY_EXIT_NOPERST      0x8000  /* bit 15 */
36 #define SRSH_CLKREQ_OFFSET_REV5         20      /* word 20 for srom rev <= 5 */
37 #define SRSH_CLKREQ_ENB                 0x0800  /* bit 11 */
38 #define SRSH_BD_OFFSET                  6       /* word 6 */
39
40 /* chipcontrol */
41 #define CHIPCTRL_4321_PLL_DOWN          0x800000/* serdes PLL down override */
42
43 /* MDIO control */
44 #define MDIOCTL_DIVISOR_MASK            0x7f    /* clock to be used on MDIO */
45 #define MDIOCTL_DIVISOR_VAL             0x2
46 #define MDIOCTL_PREAM_EN                0x80    /* Enable preamble sequnce */
47 #define MDIOCTL_ACCESS_DONE             0x100   /* Transaction complete */
48
49 /* MDIO Data */
50 #define MDIODATA_MASK                   0x0000ffff      /* data 2 bytes */
51 #define MDIODATA_TA                     0x00020000      /* Turnaround */
52
53 #define MDIODATA_REGADDR_SHF            18              /* Regaddr shift */
54 #define MDIODATA_REGADDR_MASK           0x007c0000      /* Regaddr Mask */
55 #define MDIODATA_DEVADDR_SHF            23      /* Physmedia devaddr shift */
56 #define MDIODATA_DEVADDR_MASK           0x0f800000
57                                                 /* Physmedia devaddr Mask */
58
59 /* MDIO Data for older revisions < 10 */
60 #define MDIODATA_REGADDR_SHF_OLD        18      /* Regaddr shift */
61 #define MDIODATA_REGADDR_MASK_OLD       0x003c0000
62                                                 /* Regaddr Mask */
63 #define MDIODATA_DEVADDR_SHF_OLD        22      /* Physmedia devaddr shift  */
64 #define MDIODATA_DEVADDR_MASK_OLD       0x0fc00000
65                                                 /* Physmedia devaddr Mask */
66
67 /* Transactions flags */
68 #define MDIODATA_WRITE                  0x10000000
69 #define MDIODATA_READ                   0x20000000
70 #define MDIODATA_START                  0x40000000
71
72 #define MDIODATA_DEV_ADDR               0x0     /* dev address for serdes */
73 #define MDIODATA_BLK_ADDR               0x1F    /* blk address for serdes */
74
75 /* serdes regs (rev < 10) */
76 #define MDIODATA_DEV_PLL                0x1d    /* SERDES PLL Dev */
77 #define MDIODATA_DEV_TX                 0x1e    /* SERDES TX Dev */
78 #define MDIODATA_DEV_RX                 0x1f    /* SERDES RX Dev */
79
80 /* SERDES RX registers */
81 #define SERDES_RX_CTRL                  1       /* Rx cntrl */
82 #define SERDES_RX_TIMER1                2       /* Rx Timer1 */
83 #define SERDES_RX_CDR                   6       /* CDR */
84 #define SERDES_RX_CDRBW                 7       /* CDR BW */
85 /* SERDES RX control register */
86 #define SERDES_RX_CTRL_FORCE            0x80    /* rxpolarity_force */
87 #define SERDES_RX_CTRL_POLARITY         0x40    /* rxpolarity_value */
88
89 /* SERDES PLL registers */
90 #define SERDES_PLL_CTRL                 1       /* PLL control reg */
91 #define PLL_CTRL_FREQDET_EN             0x4000  /* bit 14 is FREQDET on */
92
93 /* Linkcontrol reg offset in PCIE Cap */
94 #define PCIE_CAP_LINKCTRL_OFFSET        16      /* offset in pcie cap */
95 #define PCIE_CAP_LCREG_ASPML0s          0x01    /* ASPM L0s in linkctrl */
96 #define PCIE_CAP_LCREG_ASPML1           0x02    /* ASPM L1 in linkctrl */
97 #define PCIE_CLKREQ_ENAB                0x100   /* CLKREQ Enab in linkctrl */
98
99 #define PCIE_ASPM_ENAB                  3       /* ASPM L0s & L1 in linkctrl */
100 #define PCIE_ASPM_L1_ENAB               2       /* ASPM L0s & L1 in linkctrl */
101 #define PCIE_ASPM_L0s_ENAB              1       /* ASPM L0s & L1 in linkctrl */
102 #define PCIE_ASPM_DISAB                 0       /* ASPM L0s & L1 in linkctrl */
103
104 /* Power management threshold */
105 #define PCIE_L1THRESHOLDTIME_MASK       0xFF00  /* bits 8 - 15 */
106 #define PCIE_L1THRESHOLDTIME_SHIFT      8       /* PCIE_L1THRESHOLDTIME_SHIFT */
107 #define PCIE_L1THRESHOLD_WARVAL         0x72    /* WAR value */
108 #define PCIE_ASPMTIMER_EXTEND           0x01000000
109                                                 /* > rev7:
110                                                  * enable extend ASPM timer
111                                                  */
112
113 /* different register spaces to access thru pcie indirect access */
114 #define PCIE_CONFIGREGS         1       /* Access to config space */
115 #define PCIE_PCIEREGS           2       /* Access to pcie registers */
116
117 /* PCIE protocol PHY diagnostic registers */
118 #define PCIE_PLP_STATUSREG              0x204   /* Status */
119
120 /* Status reg PCIE_PLP_STATUSREG */
121 #define PCIE_PLP_POLARITYINV_STAT       0x10
122
123 /* PCIE protocol DLLP diagnostic registers */
124 #define PCIE_DLLP_LCREG                 0x100   /* Link Control */
125 #define PCIE_DLLP_PMTHRESHREG           0x128   /* Power Management Threshold */
126
127 /* PCIE protocol TLP diagnostic registers */
128 #define PCIE_TLP_WORKAROUNDSREG         0x004   /* TLP Workarounds */
129
130 /* Sonics to PCI translation types */
131 #define SBTOPCI_PREF    0x4             /* prefetch enable */
132 #define SBTOPCI_BURST   0x8             /* burst enable */
133 #define SBTOPCI_RC_READMULTI    0x20    /* memory read multiple */
134
135 #define PCI_CLKRUN_DSBL 0x8000  /* Bit 15 forceClkrun */
136
137 /* PCI core index in SROM shadow area */
138 #define SRSH_PI_OFFSET  0       /* first word */
139 #define SRSH_PI_MASK    0xf000  /* bit 15:12 */
140 #define SRSH_PI_SHIFT   12      /* bit 15:12 */
141
142 /* Sonics side: PCI core and host control registers */
143 struct sbpciregs {
144         u32 control;            /* PCI control */
145         u32 PAD[3];
146         u32 arbcontrol;         /* PCI arbiter control */
147         u32 clkrun;             /* Clkrun Control (>=rev11) */
148         u32 PAD[2];
149         u32 intstatus;          /* Interrupt status */
150         u32 intmask;            /* Interrupt mask */
151         u32 sbtopcimailbox;     /* Sonics to PCI mailbox */
152         u32 PAD[9];
153         u32 bcastaddr;          /* Sonics broadcast address */
154         u32 bcastdata;          /* Sonics broadcast data */
155         u32 PAD[2];
156         u32 gpioin;             /* ro: gpio input (>=rev2) */
157         u32 gpioout;            /* rw: gpio output (>=rev2) */
158         u32 gpioouten;          /* rw: gpio output enable (>= rev2) */
159         u32 gpiocontrol;        /* rw: gpio control (>= rev2) */
160         u32 PAD[36];
161         u32 sbtopci0;           /* Sonics to PCI translation 0 */
162         u32 sbtopci1;           /* Sonics to PCI translation 1 */
163         u32 sbtopci2;           /* Sonics to PCI translation 2 */
164         u32 PAD[189];
165         u32 pcicfg[4][64];      /* 0x400 - 0x7FF, PCI Cfg Space (>=rev8) */
166         u16 sprom[36];          /* SPROM shadow Area */
167         u32 PAD[46];
168 };
169
170 /* SB side: PCIE core and host control registers */
171 struct sbpcieregs {
172         u32 control;            /* host mode only */
173         u32 PAD[2];
174         u32 biststatus;         /* bist Status: 0x00C */
175         u32 gpiosel;            /* PCIE gpio sel: 0x010 */
176         u32 gpioouten;          /* PCIE gpio outen: 0x14 */
177         u32 PAD[2];
178         u32 intstatus;          /* Interrupt status: 0x20 */
179         u32 intmask;            /* Interrupt mask: 0x24 */
180         u32 sbtopcimailbox;     /* sb to pcie mailbox: 0x028 */
181         u32 PAD[53];
182         u32 sbtopcie0;          /* sb to pcie translation 0: 0x100 */
183         u32 sbtopcie1;          /* sb to pcie translation 1: 0x104 */
184         u32 sbtopcie2;          /* sb to pcie translation 2: 0x108 */
185         u32 PAD[5];
186
187         /* pcie core supports in direct access to config space */
188         u32 configaddr; /* pcie config space access: Address field: 0x120 */
189         u32 configdata; /* pcie config space access: Data field: 0x124 */
190
191         /* mdio access to serdes */
192         u32 mdiocontrol;        /* controls the mdio access: 0x128 */
193         u32 mdiodata;           /* Data to the mdio access: 0x12c */
194
195         /* pcie protocol phy/dllp/tlp register indirect access mechanism */
196         u32 pcieindaddr;        /* indirect access to
197                                  * the internal register: 0x130
198                                  */
199         u32 pcieinddata;        /* Data to/from the internal regsiter: 0x134 */
200
201         u32 clkreqenctrl;       /* >= rev 6, Clkreq rdma control : 0x138 */
202         u32 PAD[177];
203         u32 pciecfg[4][64];     /* 0x400 - 0x7FF, PCIE Cfg Space */
204         u16 sprom[64];          /* SPROM shadow Area */
205 };
206
207 struct pcicore_info {
208         union {
209                 struct sbpcieregs __iomem *pcieregs;
210                 struct sbpciregs __iomem *pciregs;
211         } regs;                 /* Memory mapped register to the core */
212
213         struct si_pub *sih;     /* System interconnect handle */
214         struct pci_dev *dev;
215         u8 pciecap_lcreg_offset;/* PCIE capability LCreg offset
216                                  * in the config space
217                                  */
218         bool pcie_pr42767;
219         u8 pcie_polarity;
220         u8 pcie_war_aspm_ovr;   /* Override ASPM/Clkreq settings */
221
222         u8 pmecap_offset;       /* PM Capability offset in the config space */
223         bool pmecap;            /* Capable of generating PME */
224 };
225
226 #define PCIE_ASPM(sih)                                                  \
227         (((sih)->buscoretype == PCIE_CORE_ID) &&                        \
228          (((sih)->buscorerev >= 3) &&                                   \
229           ((sih)->buscorerev <= 5)))
230
231
232 /* delay needed between the mdio control/ mdiodata register data access */
233 static void pr28829_delay(void)
234 {
235         udelay(10);
236 }
237
238 /* Initialize the PCI core.
239  * It's caller's responsibility to make sure that this is done only once
240  */
241 struct pcicore_info *pcicore_init(struct si_pub *sih, struct pci_dev *pdev,
242                                   void __iomem *regs)
243 {
244         struct pcicore_info *pi;
245
246         /* alloc struct pcicore_info */
247         pi = kzalloc(sizeof(struct pcicore_info), GFP_ATOMIC);
248         if (pi == NULL)
249                 return NULL;
250
251         pi->sih = sih;
252         pi->dev = pdev;
253
254         if (sih->buscoretype == PCIE_CORE_ID) {
255                 u8 cap_ptr;
256                 pi->regs.pcieregs = regs;
257                 cap_ptr = pcicore_find_pci_capability(pi->dev, PCI_CAP_ID_EXP,
258                                                       NULL, NULL);
259                 pi->pciecap_lcreg_offset = cap_ptr + PCIE_CAP_LINKCTRL_OFFSET;
260         } else
261                 pi->regs.pciregs = regs;
262
263         return pi;
264 }
265
266 void pcicore_deinit(struct pcicore_info *pch)
267 {
268         kfree(pch);
269 }
270
271 /* return cap_offset if requested capability exists in the PCI config space */
272 /* Note that it's caller's responsibility to make sure it's a pci bus */
273 u8
274 pcicore_find_pci_capability(struct pci_dev *dev, u8 req_cap_id,
275                             unsigned char *buf, u32 *buflen)
276 {
277         u8 cap_id;
278         u8 cap_ptr = 0;
279         u32 bufsize;
280         u8 byte_val;
281
282         /* check for Header type 0 */
283         pci_read_config_byte(dev, PCI_HEADER_TYPE, &byte_val);
284         if ((byte_val & 0x7f) != PCI_HEADER_TYPE_NORMAL)
285                 goto end;
286
287         /* check if the capability pointer field exists */
288         pci_read_config_byte(dev, PCI_STATUS, &byte_val);
289         if (!(byte_val & PCI_STATUS_CAP_LIST))
290                 goto end;
291
292         pci_read_config_byte(dev, PCI_CAPABILITY_LIST, &cap_ptr);
293         /* check if the capability pointer is 0x00 */
294         if (cap_ptr == 0x00)
295                 goto end;
296
297         /* loop thru the capability list
298          * and see if the pcie capability exists
299          */
300
301         pci_read_config_byte(dev, cap_ptr, &cap_id);
302
303         while (cap_id != req_cap_id) {
304                 pci_read_config_byte(dev, cap_ptr + 1, &cap_ptr);
305                 if (cap_ptr == 0x00)
306                         break;
307                 pci_read_config_byte(dev, cap_ptr, &cap_id);
308         }
309         if (cap_id != req_cap_id)
310                 goto end;
311
312         /* found the caller requested capability */
313         if (buf != NULL && buflen != NULL) {
314                 u8 cap_data;
315
316                 bufsize = *buflen;
317                 if (!bufsize)
318                         goto end;
319                 *buflen = 0;
320                 /* copy the capability data excluding cap ID and next ptr */
321                 cap_data = cap_ptr + 2;
322                 if ((bufsize + cap_data) > PCI_SZPCR)
323                         bufsize = PCI_SZPCR - cap_data;
324                 *buflen = bufsize;
325                 while (bufsize--) {
326                         pci_read_config_byte(dev, cap_data, buf);
327                         cap_data++;
328                         buf++;
329                 }
330         }
331 end:
332         return cap_ptr;
333 }
334
335 /* ***** Register Access API */
336 static uint
337 pcie_readreg(struct sbpcieregs __iomem *pcieregs, uint addrtype, uint offset)
338 {
339         uint retval = 0xFFFFFFFF;
340
341         switch (addrtype) {
342         case PCIE_CONFIGREGS:
343                 W_REG(&pcieregs->configaddr, offset);
344                 (void)R_REG((&pcieregs->configaddr));
345                 retval = R_REG(&pcieregs->configdata);
346                 break;
347         case PCIE_PCIEREGS:
348                 W_REG(&pcieregs->pcieindaddr, offset);
349                 (void)R_REG(&pcieregs->pcieindaddr);
350                 retval = R_REG(&pcieregs->pcieinddata);
351                 break;
352         }
353
354         return retval;
355 }
356
357 static uint pcie_writereg(struct sbpcieregs __iomem *pcieregs, uint addrtype,
358                           uint offset, uint val)
359 {
360         switch (addrtype) {
361         case PCIE_CONFIGREGS:
362                 W_REG((&pcieregs->configaddr), offset);
363                 W_REG((&pcieregs->configdata), val);
364                 break;
365         case PCIE_PCIEREGS:
366                 W_REG((&pcieregs->pcieindaddr), offset);
367                 W_REG((&pcieregs->pcieinddata), val);
368                 break;
369         default:
370                 break;
371         }
372         return 0;
373 }
374
375 static bool pcie_mdiosetblock(struct pcicore_info *pi, uint blk)
376 {
377         struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs;
378         uint mdiodata, i = 0;
379         uint pcie_serdes_spinwait = 200;
380
381         mdiodata = (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA |
382                     (MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) |
383                     (MDIODATA_BLK_ADDR << MDIODATA_REGADDR_SHF) |
384                     (blk << 4));
385         W_REG(&pcieregs->mdiodata, mdiodata);
386
387         pr28829_delay();
388         /* retry till the transaction is complete */
389         while (i < pcie_serdes_spinwait) {
390                 if (R_REG(&pcieregs->mdiocontrol) & MDIOCTL_ACCESS_DONE)
391                         break;
392
393                 udelay(1000);
394                 i++;
395         }
396
397         if (i >= pcie_serdes_spinwait)
398                 return false;
399
400         return true;
401 }
402
403 static int
404 pcie_mdioop(struct pcicore_info *pi, uint physmedia, uint regaddr, bool write,
405             uint *val)
406 {
407         struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs;
408         uint mdiodata;
409         uint i = 0;
410         uint pcie_serdes_spinwait = 10;
411
412         /* enable mdio access to SERDES */
413         W_REG(&pcieregs->mdiocontrol, MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL);
414
415         if (pi->sih->buscorerev >= 10) {
416                 /* new serdes is slower in rw,
417                  * using two layers of reg address mapping
418                  */
419                 if (!pcie_mdiosetblock(pi, physmedia))
420                         return 1;
421                 mdiodata = ((MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) |
422                             (regaddr << MDIODATA_REGADDR_SHF));
423                 pcie_serdes_spinwait *= 20;
424         } else {
425                 mdiodata = ((physmedia << MDIODATA_DEVADDR_SHF_OLD) |
426                             (regaddr << MDIODATA_REGADDR_SHF_OLD));
427         }
428
429         if (!write)
430                 mdiodata |= (MDIODATA_START | MDIODATA_READ | MDIODATA_TA);
431         else
432                 mdiodata |= (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA |
433                              *val);
434
435         W_REG(&pcieregs->mdiodata, mdiodata);
436
437         pr28829_delay();
438
439         /* retry till the transaction is complete */
440         while (i < pcie_serdes_spinwait) {
441                 if (R_REG(&pcieregs->mdiocontrol) & MDIOCTL_ACCESS_DONE) {
442                         if (!write) {
443                                 pr28829_delay();
444                                 *val = (R_REG(&pcieregs->mdiodata) &
445                                         MDIODATA_MASK);
446                         }
447                         /* Disable mdio access to SERDES */
448                         W_REG(&pcieregs->mdiocontrol, 0);
449                         return 0;
450                 }
451                 udelay(1000);
452                 i++;
453         }
454
455         /* Timed out. Disable mdio access to SERDES. */
456         W_REG(&pcieregs->mdiocontrol, 0);
457         return 1;
458 }
459
460 /* use the mdio interface to read from mdio slaves */
461 static int
462 pcie_mdioread(struct pcicore_info *pi, uint physmedia, uint regaddr,
463               uint *regval)
464 {
465         return pcie_mdioop(pi, physmedia, regaddr, false, regval);
466 }
467
468 /* use the mdio interface to write to mdio slaves */
469 static int
470 pcie_mdiowrite(struct pcicore_info *pi, uint physmedia, uint regaddr, uint val)
471 {
472         return pcie_mdioop(pi, physmedia, regaddr, true, &val);
473 }
474
475 /* ***** Support functions ***** */
476 static u8 pcie_clkreq(struct pcicore_info *pi, u32 mask, u32 val)
477 {
478         u32 reg_val;
479         u8 offset;
480
481         offset = pi->pciecap_lcreg_offset;
482         if (!offset)
483                 return 0;
484
485         pci_read_config_dword(pi->dev, offset, &reg_val);
486         /* set operation */
487         if (mask) {
488                 if (val)
489                         reg_val |= PCIE_CLKREQ_ENAB;
490                 else
491                         reg_val &= ~PCIE_CLKREQ_ENAB;
492                 pci_write_config_dword(pi->dev, offset, reg_val);
493                 pci_read_config_dword(pi->dev, offset, &reg_val);
494         }
495         if (reg_val & PCIE_CLKREQ_ENAB)
496                 return 1;
497         else
498                 return 0;
499 }
500
501 static void pcie_extendL1timer(struct pcicore_info *pi, bool extend)
502 {
503         u32 w;
504         struct si_pub *sih = pi->sih;
505         struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs;
506
507         if (sih->buscoretype != PCIE_CORE_ID || sih->buscorerev < 7)
508                 return;
509
510         w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG);
511         if (extend)
512                 w |= PCIE_ASPMTIMER_EXTEND;
513         else
514                 w &= ~PCIE_ASPMTIMER_EXTEND;
515         pcie_writereg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG, w);
516         w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG);
517 }
518
519 /* centralized clkreq control policy */
520 static void pcie_clkreq_upd(struct pcicore_info *pi, uint state)
521 {
522         struct si_pub *sih = pi->sih;
523
524         switch (state) {
525         case SI_DOATTACH:
526                 if (PCIE_ASPM(sih))
527                         pcie_clkreq(pi, 1, 0);
528                 break;
529         case SI_PCIDOWN:
530                 if (sih->buscorerev == 6) {     /* turn on serdes PLL down */
531                         ai_corereg(sih, SI_CC_IDX,
532                                    offsetof(struct chipcregs, chipcontrol_addr),
533                                    ~0, 0);
534                         ai_corereg(sih, SI_CC_IDX,
535                                    offsetof(struct chipcregs, chipcontrol_data),
536                                    ~0x40, 0);
537                 } else if (pi->pcie_pr42767) {
538                         pcie_clkreq(pi, 1, 1);
539                 }
540                 break;
541         case SI_PCIUP:
542                 if (sih->buscorerev == 6) {     /* turn off serdes PLL down */
543                         ai_corereg(sih, SI_CC_IDX,
544                                    offsetof(struct chipcregs, chipcontrol_addr),
545                                    ~0, 0);
546                         ai_corereg(sih, SI_CC_IDX,
547                                    offsetof(struct chipcregs, chipcontrol_data),
548                                    ~0x40, 0x40);
549                 } else if (PCIE_ASPM(sih)) {    /* disable clkreq */
550                         pcie_clkreq(pi, 1, 0);
551                 }
552                 break;
553         }
554 }
555
556 /* ***** PCI core WARs ***** */
557 /* Done only once at attach time */
558 static void pcie_war_polarity(struct pcicore_info *pi)
559 {
560         u32 w;
561
562         if (pi->pcie_polarity != 0)
563                 return;
564
565         w = pcie_readreg(pi->regs.pcieregs, PCIE_PCIEREGS, PCIE_PLP_STATUSREG);
566
567         /* Detect the current polarity at attach and force that polarity and
568          * disable changing the polarity
569          */
570         if ((w & PCIE_PLP_POLARITYINV_STAT) == 0)
571                 pi->pcie_polarity = SERDES_RX_CTRL_FORCE;
572         else
573                 pi->pcie_polarity = (SERDES_RX_CTRL_FORCE |
574                                      SERDES_RX_CTRL_POLARITY);
575 }
576
577 /* enable ASPM and CLKREQ if srom doesn't have it */
578 /* Needs to happen when update to shadow SROM is needed
579  *   : Coming out of 'standby'/'hibernate'
580  *   : If pcie_war_aspm_ovr state changed
581  */
582 static void pcie_war_aspm_clkreq(struct pcicore_info *pi)
583 {
584         struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs;
585         struct si_pub *sih = pi->sih;
586         u16 val16;
587         u16 __iomem *reg16;
588         u32 w;
589
590         if (!PCIE_ASPM(sih))
591                 return;
592
593         /* bypass this on QT or VSIM */
594         reg16 = &pcieregs->sprom[SRSH_ASPM_OFFSET];
595         val16 = R_REG(reg16);
596
597         val16 &= ~SRSH_ASPM_ENB;
598         if (pi->pcie_war_aspm_ovr == PCIE_ASPM_ENAB)
599                 val16 |= SRSH_ASPM_ENB;
600         else if (pi->pcie_war_aspm_ovr == PCIE_ASPM_L1_ENAB)
601                 val16 |= SRSH_ASPM_L1_ENB;
602         else if (pi->pcie_war_aspm_ovr == PCIE_ASPM_L0s_ENAB)
603                 val16 |= SRSH_ASPM_L0s_ENB;
604
605         W_REG(reg16, val16);
606
607         pci_read_config_dword(pi->dev, pi->pciecap_lcreg_offset, &w);
608         w &= ~PCIE_ASPM_ENAB;
609         w |= pi->pcie_war_aspm_ovr;
610         pci_write_config_dword(pi->dev, pi->pciecap_lcreg_offset, w);
611
612         reg16 = &pcieregs->sprom[SRSH_CLKREQ_OFFSET_REV5];
613         val16 = R_REG(reg16);
614
615         if (pi->pcie_war_aspm_ovr != PCIE_ASPM_DISAB) {
616                 val16 |= SRSH_CLKREQ_ENB;
617                 pi->pcie_pr42767 = true;
618         } else
619                 val16 &= ~SRSH_CLKREQ_ENB;
620
621         W_REG(reg16, val16);
622 }
623
624 /* Apply the polarity determined at the start */
625 /* Needs to happen when coming out of 'standby'/'hibernate' */
626 static void pcie_war_serdes(struct pcicore_info *pi)
627 {
628         u32 w = 0;
629
630         if (pi->pcie_polarity != 0)
631                 pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CTRL,
632                                pi->pcie_polarity);
633
634         pcie_mdioread(pi, MDIODATA_DEV_PLL, SERDES_PLL_CTRL, &w);
635         if (w & PLL_CTRL_FREQDET_EN) {
636                 w &= ~PLL_CTRL_FREQDET_EN;
637                 pcie_mdiowrite(pi, MDIODATA_DEV_PLL, SERDES_PLL_CTRL, w);
638         }
639 }
640
641 /* Fix MISC config to allow coming out of L2/L3-Ready state w/o PRST */
642 /* Needs to happen when coming out of 'standby'/'hibernate' */
643 static void pcie_misc_config_fixup(struct pcicore_info *pi)
644 {
645         struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs;
646         u16 val16;
647         u16 __iomem *reg16;
648
649         reg16 = &pcieregs->sprom[SRSH_PCIE_MISC_CONFIG];
650         val16 = R_REG(reg16);
651
652         if ((val16 & SRSH_L23READY_EXIT_NOPERST) == 0) {
653                 val16 |= SRSH_L23READY_EXIT_NOPERST;
654                 W_REG(reg16, val16);
655         }
656 }
657
658 /* quick hack for testing */
659 /* Needs to happen when coming out of 'standby'/'hibernate' */
660 static void pcie_war_noplldown(struct pcicore_info *pi)
661 {
662         struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs;
663         u16 __iomem *reg16;
664
665         /* turn off serdes PLL down */
666         ai_corereg(pi->sih, SI_CC_IDX, offsetof(struct chipcregs, chipcontrol),
667                    CHIPCTRL_4321_PLL_DOWN, CHIPCTRL_4321_PLL_DOWN);
668
669         /* clear srom shadow backdoor */
670         reg16 = &pcieregs->sprom[SRSH_BD_OFFSET];
671         W_REG(reg16, 0);
672 }
673
674 /* Needs to happen when coming out of 'standby'/'hibernate' */
675 static void pcie_war_pci_setup(struct pcicore_info *pi)
676 {
677         struct si_pub *sih = pi->sih;
678         struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs;
679         u32 w;
680
681         if (sih->buscorerev == 0 || sih->buscorerev == 1) {
682                 w = pcie_readreg(pcieregs, PCIE_PCIEREGS,
683                                  PCIE_TLP_WORKAROUNDSREG);
684                 w |= 0x8;
685                 pcie_writereg(pcieregs, PCIE_PCIEREGS,
686                               PCIE_TLP_WORKAROUNDSREG, w);
687         }
688
689         if (sih->buscorerev == 1) {
690                 w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_LCREG);
691                 w |= 0x40;
692                 pcie_writereg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_LCREG, w);
693         }
694
695         if (sih->buscorerev == 0) {
696                 pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_TIMER1, 0x8128);
697                 pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CDR, 0x0100);
698                 pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CDRBW, 0x1466);
699         } else if (PCIE_ASPM(sih)) {
700                 /* Change the L1 threshold for better performance */
701                 w = pcie_readreg(pcieregs, PCIE_PCIEREGS,
702                                  PCIE_DLLP_PMTHRESHREG);
703                 w &= ~PCIE_L1THRESHOLDTIME_MASK;
704                 w |= PCIE_L1THRESHOLD_WARVAL << PCIE_L1THRESHOLDTIME_SHIFT;
705                 pcie_writereg(pcieregs, PCIE_PCIEREGS,
706                               PCIE_DLLP_PMTHRESHREG, w);
707
708                 pcie_war_serdes(pi);
709
710                 pcie_war_aspm_clkreq(pi);
711         } else if (pi->sih->buscorerev == 7)
712                 pcie_war_noplldown(pi);
713
714         /* Note that the fix is actually in the SROM,
715          * that's why this is open-ended
716          */
717         if (pi->sih->buscorerev >= 6)
718                 pcie_misc_config_fixup(pi);
719 }
720
721 /* ***** Functions called during driver state changes ***** */
722 void pcicore_attach(struct pcicore_info *pi, int state)
723 {
724         struct si_pub *sih = pi->sih;
725         u32 bfl2 = (u32)getintvar(sih, BRCMS_SROM_BOARDFLAGS2);
726
727         /* Determine if this board needs override */
728         if (PCIE_ASPM(sih)) {
729                 if (bfl2 & BFL2_PCIEWAR_OVR)
730                         pi->pcie_war_aspm_ovr = PCIE_ASPM_DISAB;
731                 else
732                         pi->pcie_war_aspm_ovr = PCIE_ASPM_ENAB;
733         }
734
735         /* These need to happen in this order only */
736         pcie_war_polarity(pi);
737
738         pcie_war_serdes(pi);
739
740         pcie_war_aspm_clkreq(pi);
741
742         pcie_clkreq_upd(pi, state);
743
744 }
745
746 void pcicore_hwup(struct pcicore_info *pi)
747 {
748         if (!pi || pi->sih->buscoretype != PCIE_CORE_ID)
749                 return;
750
751         pcie_war_pci_setup(pi);
752 }
753
754 void pcicore_up(struct pcicore_info *pi, int state)
755 {
756         if (!pi || pi->sih->buscoretype != PCIE_CORE_ID)
757                 return;
758
759         /* Restore L1 timer for better performance */
760         pcie_extendL1timer(pi, true);
761
762         pcie_clkreq_upd(pi, state);
763 }
764
765 /* When the device is going to enter D3 state
766  * (or the system is going to enter S3/S4 states)
767  */
768 void pcicore_sleep(struct pcicore_info *pi)
769 {
770         u32 w;
771
772         if (!pi || !PCIE_ASPM(pi->sih))
773                 return;
774
775         pci_read_config_dword(pi->dev, pi->pciecap_lcreg_offset, &w);
776         w &= ~PCIE_CAP_LCREG_ASPML1;
777         pci_write_config_dword(pi->dev, pi->pciecap_lcreg_offset, w);
778
779         pi->pcie_pr42767 = false;
780 }
781
782 void pcicore_down(struct pcicore_info *pi, int state)
783 {
784         if (!pi || pi->sih->buscoretype != PCIE_CORE_ID)
785                 return;
786
787         pcie_clkreq_upd(pi, state);
788
789         /* Reduce L1 timer for better power savings */
790         pcie_extendL1timer(pi, false);
791 }
792
793 /* precondition: current core is sii->buscoretype */
794 static void pcicore_fixcfg(struct pcicore_info *pi, u16 __iomem *reg16)
795 {
796         struct si_info *sii = (struct si_info *)(pi->sih);
797         u16 val16;
798         uint pciidx;
799
800         pciidx = ai_coreidx(&sii->pub);
801         val16 = R_REG(reg16);
802         if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != (u16)pciidx) {
803                 val16 = (u16)(pciidx << SRSH_PI_SHIFT) |
804                         (val16 & ~SRSH_PI_MASK);
805                 W_REG(reg16, val16);
806         }
807 }
808
809 void
810 pcicore_fixcfg_pci(struct pcicore_info *pi, struct sbpciregs __iomem *pciregs)
811 {
812         pcicore_fixcfg(pi, &pciregs->sprom[SRSH_PI_OFFSET]);
813 }
814
815 void pcicore_fixcfg_pcie(struct pcicore_info *pi,
816                          struct sbpcieregs __iomem *pcieregs)
817 {
818         pcicore_fixcfg(pi, &pcieregs->sprom[SRSH_PI_OFFSET]);
819 }
820
821 /* precondition: current core is pci core */
822 void
823 pcicore_pci_setup(struct pcicore_info *pi, struct sbpciregs __iomem *pciregs)
824 {
825         u32 w;
826
827         OR_REG(&pciregs->sbtopci2, SBTOPCI_PREF | SBTOPCI_BURST);
828
829         if (((struct si_info *)(pi->sih))->pub.buscorerev >= 11) {
830                 OR_REG(&pciregs->sbtopci2, SBTOPCI_RC_READMULTI);
831                 w = R_REG(&pciregs->clkrun);
832                 W_REG(&pciregs->clkrun, w | PCI_CLKRUN_DSBL);
833                 w = R_REG(&pciregs->clkrun);
834         }
835 }