1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17#include <linux/delay.h>
18#include <linux/string.h>
19#include <linux/pci.h>
20#include <bcmdefs.h>
21#include <osl.h>
22#include <bcmutils.h>
23#include <siutils.h>
24#include <hndsoc.h>
25#include <bcmdevs.h>
26#include <sbchipc.h>
27#include <pci_core.h>
28#include <pcie_core.h>
29#include <nicpci.h>
30#include <pcicfg.h>
31
32typedef struct {
33 union {
34 sbpcieregs_t *pcieregs;
35 struct sbpciregs *pciregs;
36 } regs;
37
38 si_t *sih;
39 struct osl_info *osh;
40 u8 pciecap_lcreg_offset;
41 bool pcie_pr42767;
42 u8 pcie_polarity;
43 u8 pcie_war_aspm_ovr;
44
45 u8 pmecap_offset;
46 bool pmecap;
47} pcicore_info_t;
48
49
50#define PCI_ERROR(args)
51#define PCIE_PUB(sih) \
52 (((sih)->bustype == PCI_BUS) && ((sih)->buscoretype == PCIE_CORE_ID))
53
54
55static bool pcie_mdiosetblock(pcicore_info_t *pi, uint blk);
56static int pcie_mdioop(pcicore_info_t *pi, uint physmedia, uint regaddr,
57 bool write, uint *val);
58static int pcie_mdiowrite(pcicore_info_t *pi, uint physmedia, uint readdr,
59 uint val);
60static int pcie_mdioread(pcicore_info_t *pi, uint physmedia, uint readdr,
61 uint *ret_val);
62
63static void pcie_extendL1timer(pcicore_info_t *pi, bool extend);
64static void pcie_clkreq_upd(pcicore_info_t *pi, uint state);
65
66static void pcie_war_aspm_clkreq(pcicore_info_t *pi);
67static void pcie_war_serdes(pcicore_info_t *pi);
68static void pcie_war_noplldown(pcicore_info_t *pi);
69static void pcie_war_polarity(pcicore_info_t *pi);
70static void pcie_war_pci_setup(pcicore_info_t *pi);
71
72static bool pcicore_pmecap(pcicore_info_t *pi);
73
74#define PCIE_ASPM(sih) ((PCIE_PUB(sih)) && (((sih)->buscorerev >= 3) && ((sih)->buscorerev <= 5)))
75
76
77
78#define PR28829_DELAY() udelay(10)
79
80
81
82
83void *pcicore_init(si_t *sih, struct osl_info *osh, void *regs)
84{
85 pcicore_info_t *pi;
86
87 ASSERT(sih->bustype == PCI_BUS);
88
89
90 pi = kzalloc(sizeof(pcicore_info_t), GFP_ATOMIC);
91 if (pi == NULL) {
92 PCI_ERROR(("pci_attach: malloc failed!\n"));
93 return NULL;
94 }
95
96 pi->sih = sih;
97 pi->osh = osh;
98
99 if (sih->buscoretype == PCIE_CORE_ID) {
100 u8 cap_ptr;
101 pi->regs.pcieregs = (sbpcieregs_t *) regs;
102 cap_ptr =
103 pcicore_find_pci_capability(pi->osh, PCI_CAP_PCIECAP_ID,
104 NULL, NULL);
105 ASSERT(cap_ptr);
106 pi->pciecap_lcreg_offset = cap_ptr + PCIE_CAP_LINKCTRL_OFFSET;
107 } else
108 pi->regs.pciregs = (struct sbpciregs *) regs;
109
110 return pi;
111}
112
113void pcicore_deinit(void *pch)
114{
115 pcicore_info_t *pi = (pcicore_info_t *) pch;
116
117 if (pi == NULL)
118 return;
119 kfree(pi);
120}
121
122
123
124u8
125pcicore_find_pci_capability(struct osl_info *osh, u8 req_cap_id,
126 unsigned char *buf, u32 *buflen)
127{
128 u8 cap_id;
129 u8 cap_ptr = 0;
130 u32 bufsize;
131 u8 byte_val;
132
133
134 pci_read_config_byte(osh->pdev, PCI_CFG_HDR, &byte_val);
135 if ((byte_val & 0x7f) != PCI_HEADER_NORMAL)
136 goto end;
137
138
139 pci_read_config_byte(osh->pdev, PCI_CFG_STAT, &byte_val);
140 if (!(byte_val & PCI_CAPPTR_PRESENT))
141 goto end;
142
143 pci_read_config_byte(osh->pdev, PCI_CFG_CAPPTR, &cap_ptr);
144
145 if (cap_ptr == 0x00)
146 goto end;
147
148
149
150 pci_read_config_byte(osh->pdev, cap_ptr, &cap_id);
151
152 while (cap_id != req_cap_id) {
153 pci_read_config_byte(osh->pdev, cap_ptr + 1, &cap_ptr);
154 if (cap_ptr == 0x00)
155 break;
156 pci_read_config_byte(osh->pdev, cap_ptr, &cap_id);
157 }
158 if (cap_id != req_cap_id) {
159 goto end;
160 }
161
162 if ((buf != NULL) && (buflen != NULL)) {
163 u8 cap_data;
164
165 bufsize = *buflen;
166 if (!bufsize)
167 goto end;
168 *buflen = 0;
169
170 cap_data = cap_ptr + 2;
171 if ((bufsize + cap_data) > SZPCR)
172 bufsize = SZPCR - cap_data;
173 *buflen = bufsize;
174 while (bufsize--) {
175 pci_read_config_byte(osh->pdev, cap_data, buf);
176 cap_data++;
177 buf++;
178 }
179 }
180 end:
181 return cap_ptr;
182}
183
184
185uint
186pcie_readreg(struct osl_info *osh, sbpcieregs_t *pcieregs, uint addrtype,
187 uint offset)
188{
189 uint retval = 0xFFFFFFFF;
190
191 ASSERT(pcieregs != NULL);
192
193 switch (addrtype) {
194 case PCIE_CONFIGREGS:
195 W_REG(osh, (&pcieregs->configaddr), offset);
196 (void)R_REG(osh, (&pcieregs->configaddr));
197 retval = R_REG(osh, &(pcieregs->configdata));
198 break;
199 case PCIE_PCIEREGS:
200 W_REG(osh, &(pcieregs->pcieindaddr), offset);
201 (void)R_REG(osh, (&pcieregs->pcieindaddr));
202 retval = R_REG(osh, &(pcieregs->pcieinddata));
203 break;
204 default:
205 ASSERT(0);
206 break;
207 }
208
209 return retval;
210}
211
212uint
213pcie_writereg(struct osl_info *osh, sbpcieregs_t *pcieregs, uint addrtype,
214 uint offset, uint val)
215{
216 ASSERT(pcieregs != NULL);
217
218 switch (addrtype) {
219 case PCIE_CONFIGREGS:
220 W_REG(osh, (&pcieregs->configaddr), offset);
221 W_REG(osh, (&pcieregs->configdata), val);
222 break;
223 case PCIE_PCIEREGS:
224 W_REG(osh, (&pcieregs->pcieindaddr), offset);
225 W_REG(osh, (&pcieregs->pcieinddata), val);
226 break;
227 default:
228 ASSERT(0);
229 break;
230 }
231 return 0;
232}
233
234static bool pcie_mdiosetblock(pcicore_info_t *pi, uint blk)
235{
236 sbpcieregs_t *pcieregs = pi->regs.pcieregs;
237 uint mdiodata, i = 0;
238 uint pcie_serdes_spinwait = 200;
239
240 mdiodata =
241 MDIODATA_START | MDIODATA_WRITE | (MDIODATA_DEV_ADDR <<
242 MDIODATA_DEVADDR_SHF) |
243 (MDIODATA_BLK_ADDR << MDIODATA_REGADDR_SHF) | MDIODATA_TA | (blk <<
244 4);
245 W_REG(pi->osh, &pcieregs->mdiodata, mdiodata);
246
247 PR28829_DELAY();
248
249 while (i < pcie_serdes_spinwait) {
250 if (R_REG(pi->osh, &(pcieregs->mdiocontrol)) &
251 MDIOCTL_ACCESS_DONE) {
252 break;
253 }
254 udelay(1000);
255 i++;
256 }
257
258 if (i >= pcie_serdes_spinwait) {
259 PCI_ERROR(("pcie_mdiosetblock: timed out\n"));
260 return false;
261 }
262
263 return true;
264}
265
266static int
267pcie_mdioop(pcicore_info_t *pi, uint physmedia, uint regaddr, bool write,
268 uint *val)
269{
270 sbpcieregs_t *pcieregs = pi->regs.pcieregs;
271 uint mdiodata;
272 uint i = 0;
273 uint pcie_serdes_spinwait = 10;
274
275
276 W_REG(pi->osh, (&pcieregs->mdiocontrol),
277 MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL);
278
279 if (pi->sih->buscorerev >= 10) {
280
281 if (!pcie_mdiosetblock(pi, physmedia))
282 return 1;
283 mdiodata = (MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) |
284 (regaddr << MDIODATA_REGADDR_SHF);
285 pcie_serdes_spinwait *= 20;
286 } else {
287 mdiodata = (physmedia << MDIODATA_DEVADDR_SHF_OLD) |
288 (regaddr << MDIODATA_REGADDR_SHF_OLD);
289 }
290
291 if (!write)
292 mdiodata |= (MDIODATA_START | MDIODATA_READ | MDIODATA_TA);
293 else
294 mdiodata |=
295 (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA | *val);
296
297 W_REG(pi->osh, &pcieregs->mdiodata, mdiodata);
298
299 PR28829_DELAY();
300
301
302 while (i < pcie_serdes_spinwait) {
303 if (R_REG(pi->osh, &(pcieregs->mdiocontrol)) &
304 MDIOCTL_ACCESS_DONE) {
305 if (!write) {
306 PR28829_DELAY();
307 *val =
308 (R_REG(pi->osh, &(pcieregs->mdiodata)) &
309 MDIODATA_MASK);
310 }
311
312 W_REG(pi->osh, (&pcieregs->mdiocontrol), 0);
313 return 0;
314 }
315 udelay(1000);
316 i++;
317 }
318
319 PCI_ERROR(("pcie_mdioop: timed out op: %d\n", write));
320
321 W_REG(pi->osh, (&pcieregs->mdiocontrol), 0);
322 return 1;
323}
324
325
326static int
327pcie_mdioread(pcicore_info_t *pi, uint physmedia, uint regaddr, uint *regval)
328{
329 return pcie_mdioop(pi, physmedia, regaddr, false, regval);
330}
331
332
333static int
334pcie_mdiowrite(pcicore_info_t *pi, uint physmedia, uint regaddr, uint val)
335{
336 return pcie_mdioop(pi, physmedia, regaddr, true, &val);
337}
338
339
340u8 pcie_clkreq(void *pch, u32 mask, u32 val)
341{
342 pcicore_info_t *pi = (pcicore_info_t *) pch;
343 u32 reg_val;
344 u8 offset;
345
346 offset = pi->pciecap_lcreg_offset;
347 if (!offset)
348 return 0;
349
350 pci_read_config_dword(pi->osh->pdev, offset, ®_val);
351
352 if (mask) {
353 if (val)
354 reg_val |= PCIE_CLKREQ_ENAB;
355 else
356 reg_val &= ~PCIE_CLKREQ_ENAB;
357 pci_write_config_dword(pi->osh->pdev, offset, reg_val);
358 pci_read_config_dword(pi->osh->pdev, offset, ®_val);
359 }
360 if (reg_val & PCIE_CLKREQ_ENAB)
361 return 1;
362 else
363 return 0;
364}
365
366static void pcie_extendL1timer(pcicore_info_t *pi, bool extend)
367{
368 u32 w;
369 si_t *sih = pi->sih;
370 struct osl_info *osh = pi->osh;
371 sbpcieregs_t *pcieregs = pi->regs.pcieregs;
372
373 if (!PCIE_PUB(sih) || sih->buscorerev < 7)
374 return;
375
376 w = pcie_readreg(osh, pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG);
377 if (extend)
378 w |= PCIE_ASPMTIMER_EXTEND;
379 else
380 w &= ~PCIE_ASPMTIMER_EXTEND;
381 pcie_writereg(osh, pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG, w);
382 w = pcie_readreg(osh, pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG);
383}
384
385
386static void pcie_clkreq_upd(pcicore_info_t *pi, uint state)
387{
388 si_t *sih = pi->sih;
389 ASSERT(PCIE_PUB(sih));
390
391 switch (state) {
392 case SI_DOATTACH:
393 if (PCIE_ASPM(sih))
394 pcie_clkreq((void *)pi, 1, 0);
395 break;
396 case SI_PCIDOWN:
397 if (sih->buscorerev == 6) {
398 si_corereg(sih, SI_CC_IDX,
399 offsetof(chipcregs_t, chipcontrol_addr), ~0,
400 0);
401 si_corereg(sih, SI_CC_IDX,
402 offsetof(chipcregs_t, chipcontrol_data),
403 ~0x40, 0);
404 } else if (pi->pcie_pr42767) {
405 pcie_clkreq((void *)pi, 1, 1);
406 }
407 break;
408 case SI_PCIUP:
409 if (sih->buscorerev == 6) {
410 si_corereg(sih, SI_CC_IDX,
411 offsetof(chipcregs_t, chipcontrol_addr), ~0,
412 0);
413 si_corereg(sih, SI_CC_IDX,
414 offsetof(chipcregs_t, chipcontrol_data),
415 ~0x40, 0x40);
416 } else if (PCIE_ASPM(sih)) {
417 pcie_clkreq((void *)pi, 1, 0);
418 }
419 break;
420 default:
421 ASSERT(0);
422 break;
423 }
424}
425
426
427
428static void pcie_war_polarity(pcicore_info_t *pi)
429{
430 u32 w;
431
432 if (pi->pcie_polarity != 0)
433 return;
434
435 w = pcie_readreg(pi->osh, pi->regs.pcieregs, PCIE_PCIEREGS,
436 PCIE_PLP_STATUSREG);
437
438
439
440
441 if ((w & PCIE_PLP_POLARITYINV_STAT) == 0)
442 pi->pcie_polarity = (SERDES_RX_CTRL_FORCE);
443 else
444 pi->pcie_polarity =
445 (SERDES_RX_CTRL_FORCE | SERDES_RX_CTRL_POLARITY);
446}
447
448
449
450
451
452
453static void pcie_war_aspm_clkreq(pcicore_info_t *pi)
454{
455 sbpcieregs_t *pcieregs = pi->regs.pcieregs;
456 si_t *sih = pi->sih;
457 u16 val16, *reg16;
458 u32 w;
459
460 if (!PCIE_ASPM(sih))
461 return;
462
463
464 if (!ISSIM_ENAB(sih)) {
465
466 reg16 = &pcieregs->sprom[SRSH_ASPM_OFFSET];
467 val16 = R_REG(pi->osh, reg16);
468
469 val16 &= ~SRSH_ASPM_ENB;
470 if (pi->pcie_war_aspm_ovr == PCIE_ASPM_ENAB)
471 val16 |= SRSH_ASPM_ENB;
472 else if (pi->pcie_war_aspm_ovr == PCIE_ASPM_L1_ENAB)
473 val16 |= SRSH_ASPM_L1_ENB;
474 else if (pi->pcie_war_aspm_ovr == PCIE_ASPM_L0s_ENAB)
475 val16 |= SRSH_ASPM_L0s_ENB;
476
477 W_REG(pi->osh, reg16, val16);
478
479 pci_read_config_dword(pi->osh->pdev, pi->pciecap_lcreg_offset,
480 &w);
481 w &= ~PCIE_ASPM_ENAB;
482 w |= pi->pcie_war_aspm_ovr;
483 pci_write_config_dword(pi->osh->pdev,
484 pi->pciecap_lcreg_offset, w);
485 }
486
487 reg16 = &pcieregs->sprom[SRSH_CLKREQ_OFFSET_REV5];
488 val16 = R_REG(pi->osh, reg16);
489
490 if (pi->pcie_war_aspm_ovr != PCIE_ASPM_DISAB) {
491 val16 |= SRSH_CLKREQ_ENB;
492 pi->pcie_pr42767 = true;
493 } else
494 val16 &= ~SRSH_CLKREQ_ENB;
495
496 W_REG(pi->osh, reg16, val16);
497}
498
499
500
501static void pcie_war_serdes(pcicore_info_t *pi)
502{
503 u32 w = 0;
504
505 if (pi->pcie_polarity != 0)
506 pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CTRL,
507 pi->pcie_polarity);
508
509 pcie_mdioread(pi, MDIODATA_DEV_PLL, SERDES_PLL_CTRL, &w);
510 if (w & PLL_CTRL_FREQDET_EN) {
511 w &= ~PLL_CTRL_FREQDET_EN;
512 pcie_mdiowrite(pi, MDIODATA_DEV_PLL, SERDES_PLL_CTRL, w);
513 }
514}
515
516
517
518static void pcie_misc_config_fixup(pcicore_info_t *pi)
519{
520 sbpcieregs_t *pcieregs = pi->regs.pcieregs;
521 u16 val16, *reg16;
522
523 reg16 = &pcieregs->sprom[SRSH_PCIE_MISC_CONFIG];
524 val16 = R_REG(pi->osh, reg16);
525
526 if ((val16 & SRSH_L23READY_EXIT_NOPERST) == 0) {
527 val16 |= SRSH_L23READY_EXIT_NOPERST;
528 W_REG(pi->osh, reg16, val16);
529 }
530}
531
532
533
534static void pcie_war_noplldown(pcicore_info_t *pi)
535{
536 sbpcieregs_t *pcieregs = pi->regs.pcieregs;
537 u16 *reg16;
538
539 ASSERT(pi->sih->buscorerev == 7);
540
541
542 si_corereg(pi->sih, SI_CC_IDX, offsetof(chipcregs_t, chipcontrol),
543 CHIPCTRL_4321_PLL_DOWN, CHIPCTRL_4321_PLL_DOWN);
544
545
546 reg16 = &pcieregs->sprom[SRSH_BD_OFFSET];
547 W_REG(pi->osh, reg16, 0);
548}
549
550
551static void pcie_war_pci_setup(pcicore_info_t *pi)
552{
553 si_t *sih = pi->sih;
554 struct osl_info *osh = pi->osh;
555 sbpcieregs_t *pcieregs = pi->regs.pcieregs;
556 u32 w;
557
558 if ((sih->buscorerev == 0) || (sih->buscorerev == 1)) {
559 w = pcie_readreg(osh, pcieregs, PCIE_PCIEREGS,
560 PCIE_TLP_WORKAROUNDSREG);
561 w |= 0x8;
562 pcie_writereg(osh, pcieregs, PCIE_PCIEREGS,
563 PCIE_TLP_WORKAROUNDSREG, w);
564 }
565
566 if (sih->buscorerev == 1) {
567 w = pcie_readreg(osh, pcieregs, PCIE_PCIEREGS, PCIE_DLLP_LCREG);
568 w |= (0x40);
569 pcie_writereg(osh, pcieregs, PCIE_PCIEREGS, PCIE_DLLP_LCREG, w);
570 }
571
572 if (sih->buscorerev == 0) {
573 pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_TIMER1, 0x8128);
574 pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CDR, 0x0100);
575 pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CDRBW, 0x1466);
576 } else if (PCIE_ASPM(sih)) {
577
578 w = pcie_readreg(osh, pcieregs, PCIE_PCIEREGS,
579 PCIE_DLLP_PMTHRESHREG);
580 w &= ~(PCIE_L1THRESHOLDTIME_MASK);
581 w |= (PCIE_L1THRESHOLD_WARVAL << PCIE_L1THRESHOLDTIME_SHIFT);
582 pcie_writereg(osh, pcieregs, PCIE_PCIEREGS,
583 PCIE_DLLP_PMTHRESHREG, w);
584
585 pcie_war_serdes(pi);
586
587 pcie_war_aspm_clkreq(pi);
588 } else if (pi->sih->buscorerev == 7)
589 pcie_war_noplldown(pi);
590
591
592 if (pi->sih->buscorerev >= 6)
593 pcie_misc_config_fixup(pi);
594}
595
596void pcie_war_ovr_aspm_update(void *pch, u8 aspm)
597{
598 pcicore_info_t *pi = (pcicore_info_t *) pch;
599
600 if (!PCIE_ASPM(pi->sih))
601 return;
602
603
604 if (aspm > PCIE_ASPM_ENAB)
605 return;
606
607 pi->pcie_war_aspm_ovr = aspm;
608
609
610 pcie_war_aspm_clkreq(pi);
611}
612
613
614void pcicore_attach(void *pch, char *pvars, int state)
615{
616 pcicore_info_t *pi = (pcicore_info_t *) pch;
617 si_t *sih = pi->sih;
618
619
620 if (PCIE_ASPM(sih)) {
621 if ((u32) getintvar(pvars, "boardflags2") & BFL2_PCIEWAR_OVR) {
622 pi->pcie_war_aspm_ovr = PCIE_ASPM_DISAB;
623 } else {
624 pi->pcie_war_aspm_ovr = PCIE_ASPM_ENAB;
625 }
626 }
627
628
629 pcie_war_polarity(pi);
630
631 pcie_war_serdes(pi);
632
633 pcie_war_aspm_clkreq(pi);
634
635 pcie_clkreq_upd(pi, state);
636
637}
638
639void pcicore_hwup(void *pch)
640{
641 pcicore_info_t *pi = (pcicore_info_t *) pch;
642
643 if (!pi || !PCIE_PUB(pi->sih))
644 return;
645
646 pcie_war_pci_setup(pi);
647}
648
649void pcicore_up(void *pch, int state)
650{
651 pcicore_info_t *pi = (pcicore_info_t *) pch;
652
653 if (!pi || !PCIE_PUB(pi->sih))
654 return;
655
656
657 pcie_extendL1timer(pi, true);
658
659 pcie_clkreq_upd(pi, state);
660}
661
662
663void pcicore_sleep(void *pch)
664{
665 pcicore_info_t *pi = (pcicore_info_t *) pch;
666 u32 w;
667
668 if (!pi || !PCIE_ASPM(pi->sih))
669 return;
670
671 pci_read_config_dword(pi->osh->pdev, pi->pciecap_lcreg_offset, &w);
672 w &= ~PCIE_CAP_LCREG_ASPML1;
673 pci_write_config_dword(pi->osh->pdev, pi->pciecap_lcreg_offset, w);
674
675 pi->pcie_pr42767 = false;
676}
677
678void pcicore_down(void *pch, int state)
679{
680 pcicore_info_t *pi = (pcicore_info_t *) pch;
681
682 if (!pi || !PCIE_PUB(pi->sih))
683 return;
684
685 pcie_clkreq_upd(pi, state);
686
687
688 pcie_extendL1timer(pi, false);
689}
690
691
692
693bool pcicore_pmecap_fast(struct osl_info *osh)
694{
695 u8 cap_ptr;
696 u32 pmecap;
697
698 cap_ptr =
699 pcicore_find_pci_capability(osh, PCI_CAP_POWERMGMTCAP_ID, NULL,
700 NULL);
701
702 if (!cap_ptr)
703 return false;
704
705 pci_read_config_dword(osh->pdev, cap_ptr, &pmecap);
706
707 return (pmecap & PME_CAP_PM_STATES) != 0;
708}
709
710
711
712
713static bool pcicore_pmecap(pcicore_info_t *pi)
714{
715 u8 cap_ptr;
716 u32 pmecap;
717
718 if (!pi->pmecap_offset) {
719 cap_ptr =
720 pcicore_find_pci_capability(pi->osh,
721 PCI_CAP_POWERMGMTCAP_ID, NULL,
722 NULL);
723 if (!cap_ptr)
724 return false;
725
726 pi->pmecap_offset = cap_ptr;
727
728 pci_read_config_dword(pi->osh->pdev, pi->pmecap_offset,
729 &pmecap);
730
731
732 pi->pmecap = (pmecap & PME_CAP_PM_STATES) != 0;
733 }
734
735 return pi->pmecap;
736}
737
738
739void pcicore_pmeen(void *pch)
740{
741 pcicore_info_t *pi = (pcicore_info_t *) pch;
742 u32 w;
743
744
745 if (!pcicore_pmecap(pi))
746 return;
747
748 pci_read_config_dword(pi->osh->pdev, pi->pmecap_offset + PME_CSR_OFFSET,
749 &w);
750 w |= (PME_CSR_PME_EN);
751 pci_write_config_dword(pi->osh->pdev,
752 pi->pmecap_offset + PME_CSR_OFFSET, w);
753}
754
755
756
757
758bool pcicore_pmestat(void *pch)
759{
760 pcicore_info_t *pi = (pcicore_info_t *) pch;
761 u32 w;
762
763 if (!pcicore_pmecap(pi))
764 return false;
765
766 pci_read_config_dword(pi->osh->pdev, pi->pmecap_offset + PME_CSR_OFFSET,
767 &w);
768
769 return (w & PME_CSR_PME_STAT) == PME_CSR_PME_STAT;
770}
771
772
773
774void pcicore_pmeclr(void *pch)
775{
776 pcicore_info_t *pi = (pcicore_info_t *) pch;
777 u32 w;
778
779 if (!pcicore_pmecap(pi))
780 return;
781
782 pci_read_config_dword(pi->osh->pdev, pi->pmecap_offset + PME_CSR_OFFSET,
783 &w);
784
785 PCI_ERROR(("pcicore_pci_pmeclr PMECSR : 0x%x\n", w));
786
787
788 w &= ~(PME_CSR_PME_EN);
789
790 pci_write_config_dword(pi->osh->pdev,
791 pi->pmecap_offset + PME_CSR_OFFSET, w);
792}
793
794u32 pcie_lcreg(void *pch, u32 mask, u32 val)
795{
796 pcicore_info_t *pi = (pcicore_info_t *) pch;
797 u8 offset;
798 u32 tmpval;
799
800 offset = pi->pciecap_lcreg_offset;
801 if (!offset)
802 return 0;
803
804
805 if (mask)
806 pci_write_config_dword(pi->osh->pdev, offset, val);
807
808 pci_read_config_dword(pi->osh->pdev, offset, &tmpval);
809 return tmpval;
810}
811
812u32
813pcicore_pciereg(void *pch, u32 offset, u32 mask, u32 val, uint type)
814{
815 u32 reg_val = 0;
816 pcicore_info_t *pi = (pcicore_info_t *) pch;
817 sbpcieregs_t *pcieregs = pi->regs.pcieregs;
818 struct osl_info *osh = pi->osh;
819
820 if (mask) {
821 PCI_ERROR(("PCIEREG: 0x%x writeval 0x%x\n", offset, val));
822 pcie_writereg(osh, pcieregs, type, offset, val);
823 }
824
825
826 if (pi->sih->buscorerev <= 5 && offset == PCIE_DLLP_PCIE11
827 && type == PCIE_PCIEREGS)
828 return reg_val;
829
830 reg_val = pcie_readreg(osh, pcieregs, type, offset);
831 PCI_ERROR(("PCIEREG: 0x%x readval is 0x%x\n", offset, reg_val));
832
833 return reg_val;
834}
835
836u32
837pcicore_pcieserdesreg(void *pch, u32 mdioslave, u32 offset, u32 mask,
838 u32 val)
839{
840 u32 reg_val = 0;
841 pcicore_info_t *pi = (pcicore_info_t *) pch;
842
843 if (mask) {
844 PCI_ERROR(("PCIEMDIOREG: 0x%x writeval 0x%x\n", offset, val));
845 pcie_mdiowrite(pi, mdioslave, offset, val);
846 }
847
848 if (pcie_mdioread(pi, mdioslave, offset, ®_val))
849 reg_val = 0xFFFFFFFF;
850 PCI_ERROR(("PCIEMDIOREG: dev 0x%x offset 0x%x read 0x%x\n", mdioslave,
851 offset, reg_val));
852
853 return reg_val;
854}
855