Merge branch 'for-linus' of git://git.kernel.dk/linux-block
[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 side: PCI core and host control registers */
131 struct sbpciregs {
132         u32 control;            /* PCI control */
133         u32 PAD[3];
134         u32 arbcontrol;         /* PCI arbiter control */
135         u32 clkrun;             /* Clkrun Control (>=rev11) */
136         u32 PAD[2];
137         u32 intstatus;          /* Interrupt status */
138         u32 intmask;            /* Interrupt mask */
139         u32 sbtopcimailbox;     /* Sonics to PCI mailbox */
140         u32 PAD[9];
141         u32 bcastaddr;          /* Sonics broadcast address */
142         u32 bcastdata;          /* Sonics broadcast data */
143         u32 PAD[2];
144         u32 gpioin;             /* ro: gpio input (>=rev2) */
145         u32 gpioout;            /* rw: gpio output (>=rev2) */
146         u32 gpioouten;          /* rw: gpio output enable (>= rev2) */
147         u32 gpiocontrol;        /* rw: gpio control (>= rev2) */
148         u32 PAD[36];
149         u32 sbtopci0;           /* Sonics to PCI translation 0 */
150         u32 sbtopci1;           /* Sonics to PCI translation 1 */
151         u32 sbtopci2;           /* Sonics to PCI translation 2 */
152         u32 PAD[189];
153         u32 pcicfg[4][64];      /* 0x400 - 0x7FF, PCI Cfg Space (>=rev8) */
154         u16 sprom[36];          /* SPROM shadow Area */
155         u32 PAD[46];
156 };
157
158 /* SB side: PCIE core and host control registers */
159 struct sbpcieregs {
160         u32 control;            /* host mode only */
161         u32 PAD[2];
162         u32 biststatus;         /* bist Status: 0x00C */
163         u32 gpiosel;            /* PCIE gpio sel: 0x010 */
164         u32 gpioouten;          /* PCIE gpio outen: 0x14 */
165         u32 PAD[2];
166         u32 intstatus;          /* Interrupt status: 0x20 */
167         u32 intmask;            /* Interrupt mask: 0x24 */
168         u32 sbtopcimailbox;     /* sb to pcie mailbox: 0x028 */
169         u32 PAD[53];
170         u32 sbtopcie0;          /* sb to pcie translation 0: 0x100 */
171         u32 sbtopcie1;          /* sb to pcie translation 1: 0x104 */
172         u32 sbtopcie2;          /* sb to pcie translation 2: 0x108 */
173         u32 PAD[5];
174
175         /* pcie core supports in direct access to config space */
176         u32 configaddr; /* pcie config space access: Address field: 0x120 */
177         u32 configdata; /* pcie config space access: Data field: 0x124 */
178
179         /* mdio access to serdes */
180         u32 mdiocontrol;        /* controls the mdio access: 0x128 */
181         u32 mdiodata;           /* Data to the mdio access: 0x12c */
182
183         /* pcie protocol phy/dllp/tlp register indirect access mechanism */
184         u32 pcieindaddr;        /* indirect access to
185                                  * the internal register: 0x130
186                                  */
187         u32 pcieinddata;        /* Data to/from the internal regsiter: 0x134 */
188
189         u32 clkreqenctrl;       /* >= rev 6, Clkreq rdma control : 0x138 */
190         u32 PAD[177];
191         u32 pciecfg[4][64];     /* 0x400 - 0x7FF, PCIE Cfg Space */
192         u16 sprom[64];          /* SPROM shadow Area */
193 };
194
195 struct pcicore_info {
196         union {
197                 struct sbpcieregs *pcieregs;
198                 struct sbpciregs *pciregs;
199         } regs;                 /* Memory mapped register to the core */
200
201         struct si_pub *sih;     /* System interconnect handle */
202         struct pci_dev *dev;
203         u8 pciecap_lcreg_offset;/* PCIE capability LCreg offset
204                                  * in the config space
205                                  */
206         bool pcie_pr42767;
207         u8 pcie_polarity;
208         u8 pcie_war_aspm_ovr;   /* Override ASPM/Clkreq settings */
209
210         u8 pmecap_offset;       /* PM Capability offset in the config space */
211         bool pmecap;            /* Capable of generating PME */
212 };
213
214 /* debug/trace */
215 #define PCI_ERROR(args)
216 #define PCIE_PUB(sih)                                                   \
217         (((sih)->bustype == PCI_BUS) &&                                 \
218          ((sih)->buscoretype == PCIE_CORE_ID))
219
220 /* routines to access mdio slave device registers */
221 static bool pcie_mdiosetblock(struct pcicore_info *pi, uint blk);
222 static int pcie_mdioop(struct pcicore_info *pi, uint physmedia, uint regaddr,
223                        bool write, uint *val);
224 static int pcie_mdiowrite(struct pcicore_info *pi, uint physmedia, uint readdr,
225                           uint val);
226 static int pcie_mdioread(struct pcicore_info *pi, uint physmedia, uint readdr,
227                          uint *ret_val);
228
229 static void pcie_extendL1timer(struct pcicore_info *pi, bool extend);
230 static void pcie_clkreq_upd(struct pcicore_info *pi, uint state);
231
232 static void pcie_war_aspm_clkreq(struct pcicore_info *pi);
233 static void pcie_war_serdes(struct pcicore_info *pi);
234 static void pcie_war_noplldown(struct pcicore_info *pi);
235 static void pcie_war_polarity(struct pcicore_info *pi);
236 static void pcie_war_pci_setup(struct pcicore_info *pi);
237
238 #define PCIE_ASPM(sih)                                                  \
239         ((PCIE_PUB(sih)) &&                                             \
240          (((sih)->buscorerev >= 3) &&                                   \
241           ((sih)->buscorerev <= 5)))
242
243
244 /* delay needed between the mdio control/ mdiodata register data access */
245 #define PR28829_DELAY() udelay(10)
246
247 /* Initialize the PCI core.
248  * It's caller's responsibility to make sure that this is done only once
249  */
250 void *pcicore_init(struct si_pub *sih, void *pdev, void *regs)
251 {
252         struct pcicore_info *pi;
253
254         /* alloc struct pcicore_info */
255         pi = kzalloc(sizeof(struct pcicore_info), GFP_ATOMIC);
256         if (pi == NULL) {
257                 PCI_ERROR(("pci_attach: malloc failed!\n"));
258                 return NULL;
259         }
260
261         pi->sih = sih;
262         pi->dev = pdev;
263
264         if (sih->buscoretype == PCIE_CORE_ID) {
265                 u8 cap_ptr;
266                 pi->regs.pcieregs = regs;
267                 cap_ptr = pcicore_find_pci_capability(pi->dev, PCI_CAP_ID_EXP,
268                                                       NULL, NULL);
269                 pi->pciecap_lcreg_offset = cap_ptr + PCIE_CAP_LINKCTRL_OFFSET;
270         } else
271                 pi->regs.pciregs = regs;
272
273         return pi;
274 }
275
276 void pcicore_deinit(void *pch)
277 {
278         kfree(pch);
279 }
280
281 /* return cap_offset if requested capability exists in the PCI config space */
282 /* Note that it's caller's responsibility to make sure it's a pci bus */
283 u8
284 pcicore_find_pci_capability(void *dev, u8 req_cap_id,
285                             unsigned char *buf, u32 *buflen)
286 {
287         u8 cap_id;
288         u8 cap_ptr = 0;
289         u32 bufsize;
290         u8 byte_val;
291
292         /* check for Header type 0 */
293         pci_read_config_byte(dev, PCI_HEADER_TYPE, &byte_val);
294         if ((byte_val & 0x7f) != PCI_HEADER_TYPE_NORMAL)
295                 goto end;
296
297         /* check if the capability pointer field exists */
298         pci_read_config_byte(dev, PCI_STATUS, &byte_val);
299         if (!(byte_val & PCI_STATUS_CAP_LIST))
300                 goto end;
301
302         pci_read_config_byte(dev, PCI_CAPABILITY_LIST, &cap_ptr);
303         /* check if the capability pointer is 0x00 */
304         if (cap_ptr == 0x00)
305                 goto end;
306
307         /* loop thru the capability list
308          * and see if the pcie capability exists
309          */
310
311         pci_read_config_byte(dev, cap_ptr, &cap_id);
312
313         while (cap_id != req_cap_id) {
314                 pci_read_config_byte(dev, cap_ptr + 1, &cap_ptr);
315                 if (cap_ptr == 0x00)
316                         break;
317                 pci_read_config_byte(dev, cap_ptr, &cap_id);
318         }
319         if (cap_id != req_cap_id)
320                 goto end;
321
322         /* found the caller requested capability */
323         if (buf != NULL && buflen != NULL) {
324                 u8 cap_data;
325
326                 bufsize = *buflen;
327                 if (!bufsize)
328                         goto end;
329                 *buflen = 0;
330                 /* copy the capability data excluding cap ID and next ptr */
331                 cap_data = cap_ptr + 2;
332                 if ((bufsize + cap_data) > PCI_SZPCR)
333                         bufsize = PCI_SZPCR - cap_data;
334                 *buflen = bufsize;
335                 while (bufsize--) {
336                         pci_read_config_byte(dev, cap_data, buf);
337                         cap_data++;
338                         buf++;
339                 }
340         }
341 end:
342         return cap_ptr;
343 }
344
345 /* ***** Register Access API */
346 static uint
347 pcie_readreg(struct sbpcieregs *pcieregs, uint addrtype, uint offset)
348 {
349         uint retval = 0xFFFFFFFF;
350
351         switch (addrtype) {
352         case PCIE_CONFIGREGS:
353                 W_REG(&pcieregs->configaddr, offset);
354                 (void)R_REG((&pcieregs->configaddr));
355                 retval = R_REG(&pcieregs->configdata);
356                 break;
357         case PCIE_PCIEREGS:
358                 W_REG(&pcieregs->pcieindaddr, offset);
359                 (void)R_REG(&pcieregs->pcieindaddr);
360                 retval = R_REG(&pcieregs->pcieinddata);
361                 break;
362         }
363
364         return retval;
365 }
366
367 static uint
368 pcie_writereg(struct sbpcieregs *pcieregs, uint addrtype, uint offset, uint val)
369 {
370         switch (addrtype) {
371         case PCIE_CONFIGREGS:
372                 W_REG((&pcieregs->configaddr), offset);
373                 W_REG((&pcieregs->configdata), val);
374                 break;
375         case PCIE_PCIEREGS:
376                 W_REG((&pcieregs->pcieindaddr), offset);
377                 W_REG((&pcieregs->pcieinddata), val);
378                 break;
379         default:
380                 break;
381         }
382         return 0;
383 }
384
385 static bool pcie_mdiosetblock(struct pcicore_info *pi, uint blk)
386 {
387         struct sbpcieregs *pcieregs = pi->regs.pcieregs;
388         uint mdiodata, i = 0;
389         uint pcie_serdes_spinwait = 200;
390
391         mdiodata = (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA |
392                     (MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) |
393                     (MDIODATA_BLK_ADDR << MDIODATA_REGADDR_SHF) |
394                     (blk << 4));
395         W_REG(&pcieregs->mdiodata, mdiodata);
396
397         PR28829_DELAY();
398         /* retry till the transaction is complete */
399         while (i < pcie_serdes_spinwait) {
400                 if (R_REG(&pcieregs->mdiocontrol) & MDIOCTL_ACCESS_DONE)
401                         break;
402                 udelay(1000);
403                 i++;
404         }
405
406         if (i >= pcie_serdes_spinwait) {
407                 PCI_ERROR(("pcie_mdiosetblock: timed out\n"));
408                 return false;
409         }
410
411         return true;
412 }
413
414 static int
415 pcie_mdioop(struct pcicore_info *pi, uint physmedia, uint regaddr, bool write,
416             uint *val)
417 {
418         struct sbpcieregs *pcieregs = pi->regs.pcieregs;
419         uint mdiodata;
420         uint i = 0;
421         uint pcie_serdes_spinwait = 10;
422
423         /* enable mdio access to SERDES */
424         W_REG(&pcieregs->mdiocontrol, MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL);
425
426         if (pi->sih->buscorerev >= 10) {
427                 /* new serdes is slower in rw,
428                  * using two layers of reg address mapping
429                  */
430                 if (!pcie_mdiosetblock(pi, physmedia))
431                         return 1;
432                 mdiodata = ((MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) |
433                             (regaddr << MDIODATA_REGADDR_SHF));
434                 pcie_serdes_spinwait *= 20;
435         } else {
436                 mdiodata = ((physmedia << MDIODATA_DEVADDR_SHF_OLD) |
437                             (regaddr << MDIODATA_REGADDR_SHF_OLD));
438         }
439
440         if (!write)
441                 mdiodata |= (MDIODATA_START | MDIODATA_READ | MDIODATA_TA);
442         else
443                 mdiodata |= (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA |
444                              *val);
445
446         W_REG(&pcieregs->mdiodata, mdiodata);
447
448         PR28829_DELAY();
449
450         /* retry till the transaction is complete */
451         while (i < pcie_serdes_spinwait) {
452                 if (R_REG(&pcieregs->mdiocontrol) & MDIOCTL_ACCESS_DONE) {
453                         if (!write) {
454                                 PR28829_DELAY();
455                                 *val = (R_REG(&pcieregs->mdiodata) &
456                                         MDIODATA_MASK);
457                         }
458                         /* Disable mdio access to SERDES */
459                         W_REG(&pcieregs->mdiocontrol, 0);
460                         return 0;
461                 }
462                 udelay(1000);
463                 i++;
464         }
465
466         PCI_ERROR(("pcie_mdioop: timed out op: %d\n", write));
467         /* Disable mdio access to SERDES */
468         W_REG(&pcieregs->mdiocontrol, 0);
469         return 1;
470 }
471
472 /* use the mdio interface to read from mdio slaves */
473 static int
474 pcie_mdioread(struct pcicore_info *pi, uint physmedia, uint regaddr,
475               uint *regval)
476 {
477         return pcie_mdioop(pi, physmedia, regaddr, false, regval);
478 }
479
480 /* use the mdio interface to write to mdio slaves */
481 static int
482 pcie_mdiowrite(struct pcicore_info *pi, uint physmedia, uint regaddr, uint val)
483 {
484         return pcie_mdioop(pi, physmedia, regaddr, true, &val);
485 }
486
487 /* ***** Support functions ***** */
488 static u8 pcie_clkreq(void *pch, u32 mask, u32 val)
489 {
490         struct pcicore_info *pi = pch;
491         u32 reg_val;
492         u8 offset;
493
494         offset = pi->pciecap_lcreg_offset;
495         if (!offset)
496                 return 0;
497
498         pci_read_config_dword(pi->dev, offset, &reg_val);
499         /* set operation */
500         if (mask) {
501                 if (val)
502                         reg_val |= PCIE_CLKREQ_ENAB;
503                 else
504                         reg_val &= ~PCIE_CLKREQ_ENAB;
505                 pci_write_config_dword(pi->dev, offset, reg_val);
506                 pci_read_config_dword(pi->dev, offset, &reg_val);
507         }
508         if (reg_val & PCIE_CLKREQ_ENAB)
509                 return 1;
510         else
511                 return 0;
512 }
513
514 static void pcie_extendL1timer(struct pcicore_info *pi, bool extend)
515 {
516         u32 w;
517         struct si_pub *sih = pi->sih;
518         struct sbpcieregs *pcieregs = pi->regs.pcieregs;
519
520         if (!PCIE_PUB(sih) || sih->buscorerev < 7)
521                 return;
522
523         w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG);
524         if (extend)
525                 w |= PCIE_ASPMTIMER_EXTEND;
526         else
527                 w &= ~PCIE_ASPMTIMER_EXTEND;
528         pcie_writereg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG, w);
529         w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG);
530 }
531
532 /* centralized clkreq control policy */
533 static void pcie_clkreq_upd(struct pcicore_info *pi, uint state)
534 {
535         struct si_pub *sih = pi->sih;
536
537         switch (state) {
538         case SI_DOATTACH:
539                 if (PCIE_ASPM(sih))
540                         pcie_clkreq((void *)pi, 1, 0);
541                 break;
542         case SI_PCIDOWN:
543                 if (sih->buscorerev == 6) {     /* turn on serdes PLL down */
544                         ai_corereg(sih, SI_CC_IDX,
545                                    offsetof(chipcregs_t, chipcontrol_addr),
546                                    ~0, 0);
547                         ai_corereg(sih, SI_CC_IDX,
548                                    offsetof(chipcregs_t, chipcontrol_data),
549                                    ~0x40, 0);
550                 } else if (pi->pcie_pr42767) {
551                         pcie_clkreq((void *)pi, 1, 1);
552                 }
553                 break;
554         case SI_PCIUP:
555                 if (sih->buscorerev == 6) {     /* turn off serdes PLL down */
556                         ai_corereg(sih, SI_CC_IDX,
557                                    offsetof(chipcregs_t, chipcontrol_addr),
558                                    ~0, 0);
559                         ai_corereg(sih, SI_CC_IDX,
560                                    offsetof(chipcregs_t, chipcontrol_data),
561                                    ~0x40, 0x40);
562                 } else if (PCIE_ASPM(sih)) {    /* disable clkreq */
563                         pcie_clkreq((void *)pi, 1, 0);
564                 }
565                 break;
566         }
567 }
568
569 /* ***** PCI core WARs ***** */
570 /* Done only once at attach time */
571 static void pcie_war_polarity(struct pcicore_info *pi)
572 {
573         u32 w;
574
575         if (pi->pcie_polarity != 0)
576                 return;
577
578         w = pcie_readreg(pi->regs.pcieregs, PCIE_PCIEREGS, PCIE_PLP_STATUSREG);
579
580         /* Detect the current polarity at attach and force that polarity and
581          * disable changing the polarity
582          */
583         if ((w & PCIE_PLP_POLARITYINV_STAT) == 0)
584                 pi->pcie_polarity = SERDES_RX_CTRL_FORCE;
585         else
586                 pi->pcie_polarity = (SERDES_RX_CTRL_FORCE |
587                                      SERDES_RX_CTRL_POLARITY);
588 }
589
590 /* enable ASPM and CLKREQ if srom doesn't have it */
591 /* Needs to happen when update to shadow SROM is needed
592  *   : Coming out of 'standby'/'hibernate'
593  *   : If pcie_war_aspm_ovr state changed
594  */
595 static void pcie_war_aspm_clkreq(struct pcicore_info *pi)
596 {
597         struct sbpcieregs *pcieregs = pi->regs.pcieregs;
598         struct si_pub *sih = pi->sih;
599         u16 val16, *reg16;
600         u32 w;
601
602         if (!PCIE_ASPM(sih))
603                 return;
604
605         /* bypass this on QT or VSIM */
606         reg16 = &pcieregs->sprom[SRSH_ASPM_OFFSET];
607         val16 = R_REG(reg16);
608
609         val16 &= ~SRSH_ASPM_ENB;
610         if (pi->pcie_war_aspm_ovr == PCIE_ASPM_ENAB)
611                 val16 |= SRSH_ASPM_ENB;
612         else if (pi->pcie_war_aspm_ovr == PCIE_ASPM_L1_ENAB)
613                 val16 |= SRSH_ASPM_L1_ENB;
614         else if (pi->pcie_war_aspm_ovr == PCIE_ASPM_L0s_ENAB)
615                 val16 |= SRSH_ASPM_L0s_ENB;
616
617         W_REG(reg16, val16);
618
619         pci_read_config_dword(pi->dev, pi->pciecap_lcreg_offset, &w);
620         w &= ~PCIE_ASPM_ENAB;
621         w |= pi->pcie_war_aspm_ovr;
622         pci_write_config_dword(pi->dev, pi->pciecap_lcreg_offset, w);
623
624         reg16 = &pcieregs->sprom[SRSH_CLKREQ_OFFSET_REV5];
625         val16 = R_REG(reg16);
626
627         if (pi->pcie_war_aspm_ovr != PCIE_ASPM_DISAB) {
628                 val16 |= SRSH_CLKREQ_ENB;
629                 pi->pcie_pr42767 = true;
630         } else
631                 val16 &= ~SRSH_CLKREQ_ENB;
632
633         W_REG(reg16, val16);
634 }
635
636 /* Apply the polarity determined at the start */
637 /* Needs to happen when coming out of 'standby'/'hibernate' */
638 static void pcie_war_serdes(struct pcicore_info *pi)
639 {
640         u32 w = 0;
641
642         if (pi->pcie_polarity != 0)
643                 pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CTRL,
644                                pi->pcie_polarity);
645
646         pcie_mdioread(pi, MDIODATA_DEV_PLL, SERDES_PLL_CTRL, &w);
647         if (w & PLL_CTRL_FREQDET_EN) {
648                 w &= ~PLL_CTRL_FREQDET_EN;
649                 pcie_mdiowrite(pi, MDIODATA_DEV_PLL, SERDES_PLL_CTRL, w);
650         }
651 }
652
653 /* Fix MISC config to allow coming out of L2/L3-Ready state w/o PRST */
654 /* Needs to happen when coming out of 'standby'/'hibernate' */
655 static void pcie_misc_config_fixup(struct pcicore_info *pi)
656 {
657         struct sbpcieregs *pcieregs = pi->regs.pcieregs;
658         u16 val16, *reg16;
659
660         reg16 = &pcieregs->sprom[SRSH_PCIE_MISC_CONFIG];
661         val16 = R_REG(reg16);
662
663         if ((val16 & SRSH_L23READY_EXIT_NOPERST) == 0) {
664                 val16 |= SRSH_L23READY_EXIT_NOPERST;
665                 W_REG(reg16, val16);
666         }
667 }
668
669 /* quick hack for testing */
670 /* Needs to happen when coming out of 'standby'/'hibernate' */
671 static void pcie_war_noplldown(struct pcicore_info *pi)
672 {
673         struct sbpcieregs *pcieregs = pi->regs.pcieregs;
674         u16 *reg16;
675
676         /* turn off serdes PLL down */
677         ai_corereg(pi->sih, SI_CC_IDX, offsetof(chipcregs_t, chipcontrol),
678                    CHIPCTRL_4321_PLL_DOWN, CHIPCTRL_4321_PLL_DOWN);
679
680         /* clear srom shadow backdoor */
681         reg16 = &pcieregs->sprom[SRSH_BD_OFFSET];
682         W_REG(reg16, 0);
683 }
684
685 /* Needs to happen when coming out of 'standby'/'hibernate' */
686 static void pcie_war_pci_setup(struct pcicore_info *pi)
687 {
688         struct si_pub *sih = pi->sih;
689         struct sbpcieregs *pcieregs = pi->regs.pcieregs;
690         u32 w;
691
692         if (sih->buscorerev == 0 || sih->buscorerev == 1) {
693                 w = pcie_readreg(pcieregs, PCIE_PCIEREGS,
694                                  PCIE_TLP_WORKAROUNDSREG);
695                 w |= 0x8;
696                 pcie_writereg(pcieregs, PCIE_PCIEREGS,
697                               PCIE_TLP_WORKAROUNDSREG, w);
698         }
699
700         if (sih->buscorerev == 1) {
701                 w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_LCREG);
702                 w |= 0x40;
703                 pcie_writereg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_LCREG, w);
704         }
705
706         if (sih->buscorerev == 0) {
707                 pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_TIMER1, 0x8128);
708                 pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CDR, 0x0100);
709                 pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CDRBW, 0x1466);
710         } else if (PCIE_ASPM(sih)) {
711                 /* Change the L1 threshold for better performance */
712                 w = pcie_readreg(pcieregs, PCIE_PCIEREGS,
713                                  PCIE_DLLP_PMTHRESHREG);
714                 w &= ~PCIE_L1THRESHOLDTIME_MASK;
715                 w |= PCIE_L1THRESHOLD_WARVAL << PCIE_L1THRESHOLDTIME_SHIFT;
716                 pcie_writereg(pcieregs, PCIE_PCIEREGS,
717                               PCIE_DLLP_PMTHRESHREG, w);
718
719                 pcie_war_serdes(pi);
720
721                 pcie_war_aspm_clkreq(pi);
722         } else if (pi->sih->buscorerev == 7)
723                 pcie_war_noplldown(pi);
724
725         /* Note that the fix is actually in the SROM,
726          * that's why this is open-ended
727          */
728         if (pi->sih->buscorerev >= 6)
729                 pcie_misc_config_fixup(pi);
730 }
731
732 /* ***** Functions called during driver state changes ***** */
733 void pcicore_attach(void *pch, char *pvars, int state)
734 {
735         struct pcicore_info *pi = pch;
736         struct si_pub *sih = pi->sih;
737
738         /* Determine if this board needs override */
739         if (PCIE_ASPM(sih)) {
740                 if ((u32)getintvar(pvars, "boardflags2") & BFL2_PCIEWAR_OVR)
741                         pi->pcie_war_aspm_ovr = PCIE_ASPM_DISAB;
742                 else
743                         pi->pcie_war_aspm_ovr = PCIE_ASPM_ENAB;
744         }
745
746         /* These need to happen in this order only */
747         pcie_war_polarity(pi);
748
749         pcie_war_serdes(pi);
750
751         pcie_war_aspm_clkreq(pi);
752
753         pcie_clkreq_upd(pi, state);
754
755 }
756
757 void pcicore_hwup(void *pch)
758 {
759         struct pcicore_info *pi = pch;
760
761         if (!pi || !PCIE_PUB(pi->sih))
762                 return;
763
764         pcie_war_pci_setup(pi);
765 }
766
767 void pcicore_up(void *pch, int state)
768 {
769         struct pcicore_info *pi = pch;
770
771         if (!pi || !PCIE_PUB(pi->sih))
772                 return;
773
774         /* Restore L1 timer for better performance */
775         pcie_extendL1timer(pi, true);
776
777         pcie_clkreq_upd(pi, state);
778 }
779
780 /* When the device is going to enter D3 state
781  * (or the system is going to enter S3/S4 states)
782  */
783 void pcicore_sleep(void *pch)
784 {
785         struct pcicore_info *pi = pch;
786         u32 w;
787
788         if (!pi || !PCIE_ASPM(pi->sih))
789                 return;
790
791         pci_read_config_dword(pi->dev, pi->pciecap_lcreg_offset, &w);
792         w &= ~PCIE_CAP_LCREG_ASPML1;
793         pci_write_config_dword(pi->dev, pi->pciecap_lcreg_offset, w);
794
795         pi->pcie_pr42767 = false;
796 }
797
798 void pcicore_down(void *pch, int state)
799 {
800         struct pcicore_info *pi = pch;
801
802         if (!pi || !PCIE_PUB(pi->sih))
803                 return;
804
805         pcie_clkreq_upd(pi, state);
806
807         /* Reduce L1 timer for better power savings */
808         pcie_extendL1timer(pi, false);
809 }
810
811 /* precondition: current core is sii->buscoretype */
812 void pcicore_fixcfg(void *pch, void *regs)
813 {
814         struct pcicore_info *pi = pch;
815         struct si_info *sii = SI_INFO(pi->sih);
816         struct sbpciregs *pciregs = regs;
817         struct sbpcieregs *pcieregs = regs;
818         u16 val16, *reg16 = NULL;
819         uint pciidx;
820
821         /* check 'pi' is correct and fix it if not */
822         if (sii->pub.buscoretype == PCIE_CORE_ID)
823                 reg16 = &pcieregs->sprom[SRSH_PI_OFFSET];
824         else if (sii->pub.buscoretype == PCI_CORE_ID)
825                 reg16 = &pciregs->sprom[SRSH_PI_OFFSET];
826         pciidx = ai_coreidx(&sii->pub);
827         val16 = R_REG(reg16);
828         if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != (u16)pciidx) {
829                 val16 = (u16)(pciidx << SRSH_PI_SHIFT) |
830                         (val16 & ~SRSH_PI_MASK);
831                 W_REG(reg16, val16);
832         }
833 }
834
835 /* precondition: current core is pci core */
836 void pcicore_pci_setup(void *pch, void *regs)
837 {
838         struct pcicore_info *pi = pch;
839         struct sbpciregs *pciregs = regs;
840         u32 w;
841
842         OR_REG(&pciregs->sbtopci2, SBTOPCI_PREF | SBTOPCI_BURST);
843
844         if (SI_INFO(pi->sih)->pub.buscorerev >= 11) {
845                 OR_REG(&pciregs->sbtopci2, SBTOPCI_RC_READMULTI);
846                 w = R_REG(&pciregs->clkrun);
847                 W_REG(&pciregs->clkrun, w | PCI_CLKRUN_DSBL);
848                 w = R_REG(&pciregs->clkrun);
849         }
850 }