a2cab5c312eb2be9a29bdde49836b5f25e71d6b6
[pandora-kernel.git] / drivers / staging / 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 *pcieregs;
210                 struct sbpciregs *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 *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
252         pi->sih = sih;
253         pi->dev = pdev;
254
255         if (sih->buscoretype == PCIE_CORE_ID) {
256                 u8 cap_ptr;
257                 pi->regs.pcieregs = regs;
258                 cap_ptr = pcicore_find_pci_capability(pi->dev, PCI_CAP_ID_EXP,
259                                                       NULL, NULL);
260                 pi->pciecap_lcreg_offset = cap_ptr + PCIE_CAP_LINKCTRL_OFFSET;
261         } else
262                 pi->regs.pciregs = regs;
263
264         return pi;
265 }
266
267 void pcicore_deinit(struct pcicore_info *pch)
268 {
269         kfree(pch);
270 }
271
272 /* return cap_offset if requested capability exists in the PCI config space */
273 /* Note that it's caller's responsibility to make sure it's a pci bus */
274 u8
275 pcicore_find_pci_capability(struct pci_dev *dev, u8 req_cap_id,
276                             unsigned char *buf, u32 *buflen)
277 {
278         u8 cap_id;
279         u8 cap_ptr = 0;
280         u32 bufsize;
281         u8 byte_val;
282
283         /* check for Header type 0 */
284         pci_read_config_byte(dev, PCI_HEADER_TYPE, &byte_val);
285         if ((byte_val & 0x7f) != PCI_HEADER_TYPE_NORMAL)
286                 goto end;
287
288         /* check if the capability pointer field exists */
289         pci_read_config_byte(dev, PCI_STATUS, &byte_val);
290         if (!(byte_val & PCI_STATUS_CAP_LIST))
291                 goto end;
292
293         pci_read_config_byte(dev, PCI_CAPABILITY_LIST, &cap_ptr);
294         /* check if the capability pointer is 0x00 */
295         if (cap_ptr == 0x00)
296                 goto end;
297
298         /* loop thru the capability list
299          * and see if the pcie capability exists
300          */
301
302         pci_read_config_byte(dev, cap_ptr, &cap_id);
303
304         while (cap_id != req_cap_id) {
305                 pci_read_config_byte(dev, cap_ptr + 1, &cap_ptr);
306                 if (cap_ptr == 0x00)
307                         break;
308                 pci_read_config_byte(dev, cap_ptr, &cap_id);
309         }
310         if (cap_id != req_cap_id)
311                 goto end;
312
313         /* found the caller requested capability */
314         if (buf != NULL && buflen != NULL) {
315                 u8 cap_data;
316
317                 bufsize = *buflen;
318                 if (!bufsize)
319                         goto end;
320                 *buflen = 0;
321                 /* copy the capability data excluding cap ID and next ptr */
322                 cap_data = cap_ptr + 2;
323                 if ((bufsize + cap_data) > PCI_SZPCR)
324                         bufsize = PCI_SZPCR - cap_data;
325                 *buflen = bufsize;
326                 while (bufsize--) {
327                         pci_read_config_byte(dev, cap_data, buf);
328                         cap_data++;
329                         buf++;
330                 }
331         }
332 end:
333         return cap_ptr;
334 }
335
336 /* ***** Register Access API */
337 static uint
338 pcie_readreg(struct sbpcieregs *pcieregs, uint addrtype, uint offset)
339 {
340         uint retval = 0xFFFFFFFF;
341
342         switch (addrtype) {
343         case PCIE_CONFIGREGS:
344                 W_REG(&pcieregs->configaddr, offset);
345                 (void)R_REG((&pcieregs->configaddr));
346                 retval = R_REG(&pcieregs->configdata);
347                 break;
348         case PCIE_PCIEREGS:
349                 W_REG(&pcieregs->pcieindaddr, offset);
350                 (void)R_REG(&pcieregs->pcieindaddr);
351                 retval = R_REG(&pcieregs->pcieinddata);
352                 break;
353         }
354
355         return retval;
356 }
357
358 static uint
359 pcie_writereg(struct sbpcieregs *pcieregs, uint addrtype, uint offset, uint val)
360 {
361         switch (addrtype) {
362         case PCIE_CONFIGREGS:
363                 W_REG((&pcieregs->configaddr), offset);
364                 W_REG((&pcieregs->configdata), val);
365                 break;
366         case PCIE_PCIEREGS:
367                 W_REG((&pcieregs->pcieindaddr), offset);
368                 W_REG((&pcieregs->pcieinddata), val);
369                 break;
370         default:
371                 break;
372         }
373         return 0;
374 }
375
376 static bool pcie_mdiosetblock(struct pcicore_info *pi, uint blk)
377 {
378         struct sbpcieregs *pcieregs = pi->regs.pcieregs;
379         uint mdiodata, i = 0;
380         uint pcie_serdes_spinwait = 200;
381
382         mdiodata = (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA |
383                     (MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) |
384                     (MDIODATA_BLK_ADDR << MDIODATA_REGADDR_SHF) |
385                     (blk << 4));
386         W_REG(&pcieregs->mdiodata, mdiodata);
387
388         pr28829_delay();
389         /* retry till the transaction is complete */
390         while (i < pcie_serdes_spinwait) {
391                 if (R_REG(&pcieregs->mdiocontrol) & MDIOCTL_ACCESS_DONE)
392                         break;
393
394                 udelay(1000);
395                 i++;
396         }
397
398         if (i >= pcie_serdes_spinwait) {
399                 return false;
400         }
401
402         return true;
403 }
404
405 static int
406 pcie_mdioop(struct pcicore_info *pi, uint physmedia, uint regaddr, bool write,
407             uint *val)
408 {
409         struct sbpcieregs *pcieregs = pi->regs.pcieregs;
410         uint mdiodata;
411         uint i = 0;
412         uint pcie_serdes_spinwait = 10;
413
414         /* enable mdio access to SERDES */
415         W_REG(&pcieregs->mdiocontrol, MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL);
416
417         if (pi->sih->buscorerev >= 10) {
418                 /* new serdes is slower in rw,
419                  * using two layers of reg address mapping
420                  */
421                 if (!pcie_mdiosetblock(pi, physmedia))
422                         return 1;
423                 mdiodata = ((MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) |
424                             (regaddr << MDIODATA_REGADDR_SHF));
425                 pcie_serdes_spinwait *= 20;
426         } else {
427                 mdiodata = ((physmedia << MDIODATA_DEVADDR_SHF_OLD) |
428                             (regaddr << MDIODATA_REGADDR_SHF_OLD));
429         }
430
431         if (!write)
432                 mdiodata |= (MDIODATA_START | MDIODATA_READ | MDIODATA_TA);
433         else
434                 mdiodata |= (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA |
435                              *val);
436
437         W_REG(&pcieregs->mdiodata, mdiodata);
438
439         pr28829_delay();
440
441         /* retry till the transaction is complete */
442         while (i < pcie_serdes_spinwait) {
443                 if (R_REG(&pcieregs->mdiocontrol) & MDIOCTL_ACCESS_DONE) {
444                         if (!write) {
445                                 pr28829_delay();
446                                 *val = (R_REG(&pcieregs->mdiodata) &
447                                         MDIODATA_MASK);
448                         }
449                         /* Disable mdio access to SERDES */
450                         W_REG(&pcieregs->mdiocontrol, 0);
451                         return 0;
452                 }
453                 udelay(1000);
454                 i++;
455         }
456
457         /* Timed out. Disable mdio access to SERDES. */
458         W_REG(&pcieregs->mdiocontrol, 0);
459         return 1;
460 }
461
462 /* use the mdio interface to read from mdio slaves */
463 static int
464 pcie_mdioread(struct pcicore_info *pi, uint physmedia, uint regaddr,
465               uint *regval)
466 {
467         return pcie_mdioop(pi, physmedia, regaddr, false, regval);
468 }
469
470 /* use the mdio interface to write to mdio slaves */
471 static int
472 pcie_mdiowrite(struct pcicore_info *pi, uint physmedia, uint regaddr, uint val)
473 {
474         return pcie_mdioop(pi, physmedia, regaddr, true, &val);
475 }
476
477 /* ***** Support functions ***** */
478 static u8 pcie_clkreq(struct pcicore_info *pi, u32 mask, u32 val)
479 {
480         u32 reg_val;
481         u8 offset;
482
483         offset = pi->pciecap_lcreg_offset;
484         if (!offset)
485                 return 0;
486
487         pci_read_config_dword(pi->dev, offset, &reg_val);
488         /* set operation */
489         if (mask) {
490                 if (val)
491                         reg_val |= PCIE_CLKREQ_ENAB;
492                 else
493                         reg_val &= ~PCIE_CLKREQ_ENAB;
494                 pci_write_config_dword(pi->dev, offset, reg_val);
495                 pci_read_config_dword(pi->dev, offset, &reg_val);
496         }
497         if (reg_val & PCIE_CLKREQ_ENAB)
498                 return 1;
499         else
500                 return 0;
501 }
502
503 static void pcie_extendL1timer(struct pcicore_info *pi, bool extend)
504 {
505         u32 w;
506         struct si_pub *sih = pi->sih;
507         struct sbpcieregs *pcieregs = pi->regs.pcieregs;
508
509         if (sih->buscoretype != PCIE_CORE_ID || sih->buscorerev < 7)
510                 return;
511
512         w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG);
513         if (extend)
514                 w |= PCIE_ASPMTIMER_EXTEND;
515         else
516                 w &= ~PCIE_ASPMTIMER_EXTEND;
517         pcie_writereg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG, w);
518         w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG);
519 }
520
521 /* centralized clkreq control policy */
522 static void pcie_clkreq_upd(struct pcicore_info *pi, uint state)
523 {
524         struct si_pub *sih = pi->sih;
525
526         switch (state) {
527         case SI_DOATTACH:
528                 if (PCIE_ASPM(sih))
529                         pcie_clkreq(pi, 1, 0);
530                 break;
531         case SI_PCIDOWN:
532                 if (sih->buscorerev == 6) {     /* turn on serdes PLL down */
533                         ai_corereg(sih, SI_CC_IDX,
534                                    offsetof(struct chipcregs, chipcontrol_addr),
535                                    ~0, 0);
536                         ai_corereg(sih, SI_CC_IDX,
537                                    offsetof(struct chipcregs, chipcontrol_data),
538                                    ~0x40, 0);
539                 } else if (pi->pcie_pr42767) {
540                         pcie_clkreq(pi, 1, 1);
541                 }
542                 break;
543         case SI_PCIUP:
544                 if (sih->buscorerev == 6) {     /* turn off serdes PLL down */
545                         ai_corereg(sih, SI_CC_IDX,
546                                    offsetof(struct chipcregs, chipcontrol_addr),
547                                    ~0, 0);
548                         ai_corereg(sih, SI_CC_IDX,
549                                    offsetof(struct chipcregs, chipcontrol_data),
550                                    ~0x40, 0x40);
551                 } else if (PCIE_ASPM(sih)) {    /* disable clkreq */
552                         pcie_clkreq(pi, 1, 0);
553                 }
554                 break;
555         }
556 }
557
558 /* ***** PCI core WARs ***** */
559 /* Done only once at attach time */
560 static void pcie_war_polarity(struct pcicore_info *pi)
561 {
562         u32 w;
563
564         if (pi->pcie_polarity != 0)
565                 return;
566
567         w = pcie_readreg(pi->regs.pcieregs, PCIE_PCIEREGS, PCIE_PLP_STATUSREG);
568
569         /* Detect the current polarity at attach and force that polarity and
570          * disable changing the polarity
571          */
572         if ((w & PCIE_PLP_POLARITYINV_STAT) == 0)
573                 pi->pcie_polarity = SERDES_RX_CTRL_FORCE;
574         else
575                 pi->pcie_polarity = (SERDES_RX_CTRL_FORCE |
576                                      SERDES_RX_CTRL_POLARITY);
577 }
578
579 /* enable ASPM and CLKREQ if srom doesn't have it */
580 /* Needs to happen when update to shadow SROM is needed
581  *   : Coming out of 'standby'/'hibernate'
582  *   : If pcie_war_aspm_ovr state changed
583  */
584 static void pcie_war_aspm_clkreq(struct pcicore_info *pi)
585 {
586         struct sbpcieregs *pcieregs = pi->regs.pcieregs;
587         struct si_pub *sih = pi->sih;
588         u16 val16, *reg16;
589         u32 w;
590
591         if (!PCIE_ASPM(sih))
592                 return;
593
594         /* bypass this on QT or VSIM */
595         reg16 = &pcieregs->sprom[SRSH_ASPM_OFFSET];
596         val16 = R_REG(reg16);
597
598         val16 &= ~SRSH_ASPM_ENB;
599         if (pi->pcie_war_aspm_ovr == PCIE_ASPM_ENAB)
600                 val16 |= SRSH_ASPM_ENB;
601         else if (pi->pcie_war_aspm_ovr == PCIE_ASPM_L1_ENAB)
602                 val16 |= SRSH_ASPM_L1_ENB;
603         else if (pi->pcie_war_aspm_ovr == PCIE_ASPM_L0s_ENAB)
604                 val16 |= SRSH_ASPM_L0s_ENB;
605
606         W_REG(reg16, val16);
607
608         pci_read_config_dword(pi->dev, pi->pciecap_lcreg_offset, &w);
609         w &= ~PCIE_ASPM_ENAB;
610         w |= pi->pcie_war_aspm_ovr;
611         pci_write_config_dword(pi->dev, pi->pciecap_lcreg_offset, w);
612
613         reg16 = &pcieregs->sprom[SRSH_CLKREQ_OFFSET_REV5];
614         val16 = R_REG(reg16);
615
616         if (pi->pcie_war_aspm_ovr != PCIE_ASPM_DISAB) {
617                 val16 |= SRSH_CLKREQ_ENB;
618                 pi->pcie_pr42767 = true;
619         } else
620                 val16 &= ~SRSH_CLKREQ_ENB;
621
622         W_REG(reg16, val16);
623 }
624
625 /* Apply the polarity determined at the start */
626 /* Needs to happen when coming out of 'standby'/'hibernate' */
627 static void pcie_war_serdes(struct pcicore_info *pi)
628 {
629         u32 w = 0;
630
631         if (pi->pcie_polarity != 0)
632                 pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CTRL,
633                                pi->pcie_polarity);
634
635         pcie_mdioread(pi, MDIODATA_DEV_PLL, SERDES_PLL_CTRL, &w);
636         if (w & PLL_CTRL_FREQDET_EN) {
637                 w &= ~PLL_CTRL_FREQDET_EN;
638                 pcie_mdiowrite(pi, MDIODATA_DEV_PLL, SERDES_PLL_CTRL, w);
639         }
640 }
641
642 /* Fix MISC config to allow coming out of L2/L3-Ready state w/o PRST */
643 /* Needs to happen when coming out of 'standby'/'hibernate' */
644 static void pcie_misc_config_fixup(struct pcicore_info *pi)
645 {
646         struct sbpcieregs *pcieregs = pi->regs.pcieregs;
647         u16 val16, *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 *pcieregs = pi->regs.pcieregs;
663         u16 *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 *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, char *pvars, int state)
723 {
724         struct si_pub *sih = pi->sih;
725
726         /* Determine if this board needs override */
727         if (PCIE_ASPM(sih)) {
728                 if ((u32)getintvar(pvars, "boardflags2") & BFL2_PCIEWAR_OVR)
729                         pi->pcie_war_aspm_ovr = PCIE_ASPM_DISAB;
730                 else
731                         pi->pcie_war_aspm_ovr = PCIE_ASPM_ENAB;
732         }
733
734         /* These need to happen in this order only */
735         pcie_war_polarity(pi);
736
737         pcie_war_serdes(pi);
738
739         pcie_war_aspm_clkreq(pi);
740
741         pcie_clkreq_upd(pi, state);
742
743 }
744
745 void pcicore_hwup(struct pcicore_info *pi)
746 {
747         if (!pi || pi->sih->buscoretype != PCIE_CORE_ID)
748                 return;
749
750         pcie_war_pci_setup(pi);
751 }
752
753 void pcicore_up(struct pcicore_info *pi, int state)
754 {
755         if (!pi || pi->sih->buscoretype != PCIE_CORE_ID)
756                 return;
757
758         /* Restore L1 timer for better performance */
759         pcie_extendL1timer(pi, true);
760
761         pcie_clkreq_upd(pi, state);
762 }
763
764 /* When the device is going to enter D3 state
765  * (or the system is going to enter S3/S4 states)
766  */
767 void pcicore_sleep(struct pcicore_info *pi)
768 {
769         u32 w;
770
771         if (!pi || !PCIE_ASPM(pi->sih))
772                 return;
773
774         pci_read_config_dword(pi->dev, pi->pciecap_lcreg_offset, &w);
775         w &= ~PCIE_CAP_LCREG_ASPML1;
776         pci_write_config_dword(pi->dev, pi->pciecap_lcreg_offset, w);
777
778         pi->pcie_pr42767 = false;
779 }
780
781 void pcicore_down(struct pcicore_info *pi, int state)
782 {
783         if (!pi || pi->sih->buscoretype != PCIE_CORE_ID)
784                 return;
785
786         pcie_clkreq_upd(pi, state);
787
788         /* Reduce L1 timer for better power savings */
789         pcie_extendL1timer(pi, false);
790 }
791
792 /* precondition: current core is sii->buscoretype */
793 static void pcicore_fixcfg(struct pcicore_info *pi, u16 *reg16)
794 {
795         struct si_info *sii = (struct si_info *)(pi->sih);
796         u16 val16;
797         uint pciidx;
798
799         pciidx = ai_coreidx(&sii->pub);
800         val16 = R_REG(reg16);
801         if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != (u16)pciidx) {
802                 val16 = (u16)(pciidx << SRSH_PI_SHIFT) |
803                         (val16 & ~SRSH_PI_MASK);
804                 W_REG(reg16, val16);
805         }
806 }
807
808 void pcicore_fixcfg_pci(struct pcicore_info *pi, struct sbpciregs *pciregs)
809 {
810         pcicore_fixcfg(pi, &pciregs->sprom[SRSH_PI_OFFSET]);
811 }
812
813 void pcicore_fixcfg_pcie(struct pcicore_info *pi, struct sbpcieregs *pcieregs)
814 {
815         pcicore_fixcfg(pi, &pcieregs->sprom[SRSH_PI_OFFSET]);
816 }
817
818 /* precondition: current core is pci core */
819 void pcicore_pci_setup(struct pcicore_info *pi, struct sbpciregs *pciregs)
820 {
821         u32 w;
822
823         OR_REG(&pciregs->sbtopci2, SBTOPCI_PREF | SBTOPCI_BURST);
824
825         if (((struct si_info *)(pi->sih))->pub.buscorerev >= 11) {
826                 OR_REG(&pciregs->sbtopci2, SBTOPCI_RC_READMULTI);
827                 w = R_REG(&pciregs->clkrun);
828                 W_REG(&pciregs->clkrun, w | PCI_CLKRUN_DSBL);
829                 w = R_REG(&pciregs->clkrun);
830         }
831 }