2 * Code to operate on PCI/E core, in NIC mode
4 * Copyright (C) 2010, Broadcom Corporation. All Rights Reserved.
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 * $Id: nicpci.c,v 1.33.10.24 2011-02-03 01:11:15 Exp $
30 #include <pcie_core.h>
36 sbpcieregs_t
*pcieregs
;
38 } regs
; /* Memory mapped register to the core */
40 si_t
*sih
; /* System interconnect handle */
41 osl_t
*osh
; /* OSL handle */
42 uint8 pciecap_lcreg_offset
; /* PCIE capability LCreg offset in the config space */
43 uint8 pciecap_devctrl_offset
; /* PCIE DevControl reg offset in the config space */
46 uint8 pcie_war_aspm_ovr
; /* Override ASPM/Clkreq settings */
47 uint8 pmecap_offset
; /* PM Capability offset in the config space */
48 bool pmecap
; /* Capable of generating PME */
56 #define PCI_ERROR(args) printf args
58 #define PCI_ERROR(args)
59 #endif /* BCMDBG_ERR */
61 /* routines to access mdio slave device registers */
62 static bool pcie_mdiosetblock(pcicore_info_t
*pi
, uint blk
);
63 static int pcie_mdioop(pcicore_info_t
*pi
, uint physmedia
, uint regaddr
, bool write
, uint
*val
);
64 static int pcie_mdiowrite(pcicore_info_t
*pi
, uint physmedia
, uint readdr
, uint val
);
65 static int pcie_mdioread(pcicore_info_t
*pi
, uint physmedia
, uint readdr
, uint
*ret_val
);
67 static void pcie_extendL1timer(pcicore_info_t
*pi
, bool extend
);
68 static void pcie_clkreq_upd(pcicore_info_t
*pi
, uint state
);
70 static void pcie_war_aspm_clkreq(pcicore_info_t
*pi
);
71 static void pcie_war_serdes(pcicore_info_t
*pi
);
72 static void pcie_war_noplldown(pcicore_info_t
*pi
);
73 static void pcie_war_polarity(pcicore_info_t
*pi
);
74 static void pcie_war_pci_setup(pcicore_info_t
*pi
);
75 static void pcie_power_save_upd(pcicore_info_t
*pi
, bool up
);
77 static bool pcicore_pmecap(pcicore_info_t
*pi
);
78 static void pcicore_fixlatencytimer(pcicore_info_t
* pch
, uint8 timer_val
);
80 #define PCIE(sih) ((BUSTYPE((sih)->bustype) == PCI_BUS) && ((sih)->buscoretype == PCIE_CORE_ID))
81 #define PCIE_ASPM(sih) ((PCIE(sih)) && (((sih)->buscorerev >= 3) && ((sih)->buscorerev <= 5)))
83 #define DWORD_ALIGN(x) (x & ~(0x03))
84 #define BYTE_POS(x) (x & 0x3)
85 #define WORD_POS(x) (x & 0x1)
87 #define BYTE_SHIFT(x) (8 * BYTE_POS(x))
88 #define WORD_SHIFT(x) (16 * WORD_POS(x))
90 #define BYTE_VAL(a, x) ((a >> BYTE_SHIFT(x)) & 0xFF)
91 #define WORD_VAL(a, x) ((a >> WORD_SHIFT(x)) & 0xFFFF)
93 #define read_pci_cfg_byte(a) \
94 (BYTE_VAL(OSL_PCI_READ_CONFIG(osh, DWORD_ALIGN(a), 4), a) & 0xff)
96 #define read_pci_cfg_word(a) \
97 (WORD_VAL(OSL_PCI_READ_CONFIG(osh, DWORD_ALIGN(a), 4), a) & 0xffff)
99 #define write_pci_cfg_byte(a, val) do { \
101 tmpval = (OSL_PCI_READ_CONFIG(osh, DWORD_ALIGN(a), 4) & ~0xFF << BYTE_POS(a)) | \
102 val << BYTE_POS(a); \
103 OSL_PCI_WRITE_CONFIG(osh, DWORD_ALIGN(a), 4, tmpval); \
106 #define write_pci_cfg_word(a, val) do { \
108 tmpval = (OSL_PCI_READ_CONFIG(osh, DWORD_ALIGN(a), 4) & ~0xFFFF << WORD_POS(a)) | \
109 val << WORD_POS(a); \
110 OSL_PCI_WRITE_CONFIG(osh, DWORD_ALIGN(a), 4, tmpval); \
113 /* delay needed between the mdio control/ mdiodata register data access */
114 #define PR28829_DELAY() OSL_DELAY(10)
116 /* Initialize the PCI core. It's caller's responsibility to make sure that this is done
120 pcicore_init(si_t
*sih
, osl_t
*osh
, void *regs
)
124 ASSERT(sih
->bustype
== PCI_BUS
);
126 /* alloc pcicore_info_t */
127 if ((pi
= MALLOC(osh
, sizeof(pcicore_info_t
))) == NULL
) {
128 PCI_ERROR(("pci_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh
)));
132 bzero(pi
, sizeof(pcicore_info_t
));
137 if (sih
->buscoretype
== PCIE_CORE_ID
) {
139 pi
->regs
.pcieregs
= (sbpcieregs_t
*)regs
;
140 cap_ptr
= pcicore_find_pci_capability(pi
->osh
, PCI_CAP_PCIECAP_ID
, NULL
, NULL
);
142 pi
->pciecap_lcreg_offset
= cap_ptr
+ PCIE_CAP_LINKCTRL_OFFSET
;
143 pi
->pciecap_devctrl_offset
= cap_ptr
+ PCIE_CAP_DEVCTRL_OFFSET
;
144 pi
->pcie_power_save
= TRUE
; /* Enable pcie_power_save by default */
146 pi
->regs
.pciregs
= (sbpciregs_t
*)regs
;
152 pcicore_deinit(void *pch
)
154 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
159 MFREE(pi
->osh
, pi
, sizeof(pcicore_info_t
));
162 /* return cap_offset if requested capability exists in the PCI config space */
163 /* Note that it's caller's responsibility to make sure it's a pci bus */
165 pcicore_find_pci_capability(osl_t
*osh
, uint8 req_cap_id
, uchar
*buf
, uint32
*buflen
)
172 /* check for Header type 0 */
173 byte_val
= read_pci_cfg_byte(PCI_CFG_HDR
);
174 if ((byte_val
& 0x7f) != PCI_HEADER_NORMAL
)
177 /* check if the capability pointer field exists */
178 byte_val
= read_pci_cfg_byte(PCI_CFG_STAT
);
179 if (!(byte_val
& PCI_CAPPTR_PRESENT
))
182 cap_ptr
= read_pci_cfg_byte(PCI_CFG_CAPPTR
);
183 /* check if the capability pointer is 0x00 */
187 /* loop thr'u the capability list and see if the pcie capabilty exists */
189 cap_id
= read_pci_cfg_byte(cap_ptr
);
191 while (cap_id
!= req_cap_id
) {
192 cap_ptr
= read_pci_cfg_byte((cap_ptr
+1));
193 if (cap_ptr
== 0x00) break;
194 cap_id
= read_pci_cfg_byte(cap_ptr
);
196 if (cap_id
!= req_cap_id
) {
199 /* found the caller requested capability */
200 if ((buf
!= NULL
) && (buflen
!= NULL
)) {
204 if (!bufsize
) goto end
;
206 /* copy the cpability data excluding cap ID and next ptr */
207 cap_data
= cap_ptr
+ 2;
208 if ((bufsize
+ cap_data
) > SZPCR
)
209 bufsize
= SZPCR
- cap_data
;
212 *buf
= read_pci_cfg_byte(cap_data
);
221 /* ***** Register Access API */
223 pcie_readreg(osl_t
*osh
, sbpcieregs_t
*pcieregs
, uint addrtype
, uint offset
)
225 uint retval
= 0xFFFFFFFF;
227 ASSERT(pcieregs
!= NULL
);
230 case PCIE_CONFIGREGS
:
231 W_REG(osh
, (&pcieregs
->configaddr
), offset
);
232 (void)R_REG(osh
, (&pcieregs
->configaddr
));
233 retval
= R_REG(osh
, &(pcieregs
->configdata
));
236 W_REG(osh
, &(pcieregs
->pcieindaddr
), offset
);
237 (void)R_REG(osh
, (&pcieregs
->pcieindaddr
));
238 retval
= R_REG(osh
, &(pcieregs
->pcieinddata
));
249 pcie_writereg(osl_t
*osh
, sbpcieregs_t
*pcieregs
, uint addrtype
, uint offset
, uint val
)
251 ASSERT(pcieregs
!= NULL
);
254 case PCIE_CONFIGREGS
:
255 W_REG(osh
, (&pcieregs
->configaddr
), offset
);
256 W_REG(osh
, (&pcieregs
->configdata
), val
);
259 W_REG(osh
, (&pcieregs
->pcieindaddr
), offset
);
260 W_REG(osh
, (&pcieregs
->pcieinddata
), val
);
270 pcie_mdiosetblock(pcicore_info_t
*pi
, uint blk
)
272 sbpcieregs_t
*pcieregs
= pi
->regs
.pcieregs
;
273 uint mdiodata
, i
= 0;
274 uint pcie_serdes_spinwait
= 200;
276 mdiodata
= MDIODATA_START
| MDIODATA_WRITE
| (MDIODATA_DEV_ADDR
<< MDIODATA_DEVADDR_SHF
) |
277 (MDIODATA_BLK_ADDR
<< MDIODATA_REGADDR_SHF
) | MDIODATA_TA
| (blk
<< 4);
278 W_REG(pi
->osh
, &pcieregs
->mdiodata
, mdiodata
);
281 /* retry till the transaction is complete */
282 while (i
< pcie_serdes_spinwait
) {
283 if (R_REG(pi
->osh
, &(pcieregs
->mdiocontrol
)) & MDIOCTL_ACCESS_DONE
) {
290 if (i
>= pcie_serdes_spinwait
) {
291 PCI_ERROR(("pcie_mdiosetblock: timed out\n"));
299 pcie_mdioop(pcicore_info_t
*pi
, uint physmedia
, uint regaddr
, bool write
, uint
*val
)
301 sbpcieregs_t
*pcieregs
= pi
->regs
.pcieregs
;
304 uint pcie_serdes_spinwait
= 10;
306 /* enable mdio access to SERDES */
307 W_REG(pi
->osh
, (&pcieregs
->mdiocontrol
), MDIOCTL_PREAM_EN
| MDIOCTL_DIVISOR_VAL
);
309 if (pi
->sih
->buscorerev
>= 10) {
310 /* new serdes is slower in rw, using two layers of reg address mapping */
311 if (!pcie_mdiosetblock(pi
, physmedia
))
313 mdiodata
= (MDIODATA_DEV_ADDR
<< MDIODATA_DEVADDR_SHF
) |
314 (regaddr
<< MDIODATA_REGADDR_SHF
);
315 pcie_serdes_spinwait
*= 20;
317 mdiodata
= (physmedia
<< MDIODATA_DEVADDR_SHF_OLD
) |
318 (regaddr
<< MDIODATA_REGADDR_SHF_OLD
);
322 mdiodata
|= (MDIODATA_START
| MDIODATA_READ
| MDIODATA_TA
);
324 mdiodata
|= (MDIODATA_START
| MDIODATA_WRITE
| MDIODATA_TA
| *val
);
326 W_REG(pi
->osh
, &pcieregs
->mdiodata
, mdiodata
);
330 /* retry till the transaction is complete */
331 while (i
< pcie_serdes_spinwait
) {
332 if (R_REG(pi
->osh
, &(pcieregs
->mdiocontrol
)) & MDIOCTL_ACCESS_DONE
) {
335 *val
= (R_REG(pi
->osh
, &(pcieregs
->mdiodata
)) & MDIODATA_MASK
);
337 /* Disable mdio access to SERDES */
338 W_REG(pi
->osh
, (&pcieregs
->mdiocontrol
), 0);
345 PCI_ERROR(("pcie_mdioop: timed out op: %d\n", write
));
346 /* Disable mdio access to SERDES */
347 W_REG(pi
->osh
, (&pcieregs
->mdiocontrol
), 0);
351 /* use the mdio interface to read from mdio slaves */
353 pcie_mdioread(pcicore_info_t
*pi
, uint physmedia
, uint regaddr
, uint
*regval
)
355 return pcie_mdioop(pi
, physmedia
, regaddr
, FALSE
, regval
);
358 /* use the mdio interface to write to mdio slaves */
360 pcie_mdiowrite(pcicore_info_t
*pi
, uint physmedia
, uint regaddr
, uint val
)
362 return pcie_mdioop(pi
, physmedia
, regaddr
, TRUE
, &val
);
365 /* ***** Support functions ***** */
367 pcie_devcontrol_mrrs(void *pch
, uint32 mask
, uint32 val
)
369 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
373 offset
= pi
->pciecap_devctrl_offset
;
377 reg_val
= OSL_PCI_READ_CONFIG(pi
->osh
, offset
, sizeof(uint32
));
380 if (val
> PCIE_CAP_DEVCTRL_MRRS_128B
) {
381 if (pi
->sih
->buscorerev
< 18) {
382 PCI_ERROR(("%s pcie corerev %d doesn't support >128B MRRS",
383 __FUNCTION__
, pi
->sih
->buscorerev
));
384 val
= PCIE_CAP_DEVCTRL_MRRS_128B
;
388 reg_val
&= ~PCIE_CAP_DEVCTRL_MRRS_MASK
;
389 reg_val
|= (val
<< PCIE_CAP_DEVCTRL_MRRS_SHIFT
) & PCIE_CAP_DEVCTRL_MRRS_MASK
;
391 OSL_PCI_WRITE_CONFIG(pi
->osh
, offset
, sizeof(uint32
), reg_val
);
392 reg_val
= OSL_PCI_READ_CONFIG(pi
->osh
, offset
, sizeof(uint32
));
398 pcie_clkreq(void *pch
, uint32 mask
, uint32 val
)
400 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
404 offset
= pi
->pciecap_lcreg_offset
;
408 reg_val
= OSL_PCI_READ_CONFIG(pi
->osh
, offset
, sizeof(uint32
));
412 reg_val
|= PCIE_CLKREQ_ENAB
;
414 reg_val
&= ~PCIE_CLKREQ_ENAB
;
415 OSL_PCI_WRITE_CONFIG(pi
->osh
, offset
, sizeof(uint32
), reg_val
);
416 reg_val
= OSL_PCI_READ_CONFIG(pi
->osh
, offset
, sizeof(uint32
));
418 if (reg_val
& PCIE_CLKREQ_ENAB
)
425 pcie_extendL1timer(pcicore_info_t
*pi
, bool extend
)
429 osl_t
*osh
= pi
->osh
;
430 sbpcieregs_t
*pcieregs
= pi
->regs
.pcieregs
;
435 w
= pcie_readreg(osh
, pcieregs
, PCIE_PCIEREGS
, PCIE_DLLP_PMTHRESHREG
);
437 if (extend
&& sih
->buscorerev
>= 7)
438 w
|= PCIE_ASPMTIMER_EXTEND
;
440 w
&= ~PCIE_ASPMTIMER_EXTEND
;
441 pcie_writereg(osh
, pcieregs
, PCIE_PCIEREGS
, PCIE_DLLP_PMTHRESHREG
, w
);
442 w
= pcie_readreg(osh
, pcieregs
, PCIE_PCIEREGS
, PCIE_DLLP_PMTHRESHREG
);
445 /* centralized clkreq control policy */
447 pcie_clkreq_upd(pcicore_info_t
*pi
, uint state
)
455 pcie_clkreq((void *)pi
, 1, 0);
458 if (sih
->buscorerev
== 6) { /* turn on serdes PLL down */
459 si_corereg(sih
, SI_CC_IDX
, OFFSETOF(chipcregs_t
, chipcontrol_addr
),
461 si_corereg(sih
, SI_CC_IDX
, OFFSETOF(chipcregs_t
, chipcontrol_data
),
463 } else if (pi
->pcie_pr42767
) {
464 pcie_clkreq((void *)pi
, 1, 1);
468 if (sih
->buscorerev
== 6) { /* turn off serdes PLL down */
469 si_corereg(sih
, SI_CC_IDX
, OFFSETOF(chipcregs_t
, chipcontrol_addr
),
471 si_corereg(sih
, SI_CC_IDX
, OFFSETOF(chipcregs_t
, chipcontrol_data
),
473 } else if (PCIE_ASPM(sih
)) { /* disable clkreq */
474 pcie_clkreq((void *)pi
, 1, 0);
483 /* ***** PCI core WARs ***** */
484 /* Done only once at attach time */
486 pcie_war_polarity(pcicore_info_t
*pi
)
490 if (pi
->pcie_polarity
!= 0)
493 w
= pcie_readreg(pi
->osh
, pi
->regs
.pcieregs
, PCIE_PCIEREGS
, PCIE_PLP_STATUSREG
);
495 /* Detect the current polarity at attach and force that polarity and
496 * disable changing the polarity
498 if ((w
& PCIE_PLP_POLARITYINV_STAT
) == 0)
499 pi
->pcie_polarity
= (SERDES_RX_CTRL_FORCE
);
501 pi
->pcie_polarity
= (SERDES_RX_CTRL_FORCE
| SERDES_RX_CTRL_POLARITY
);
504 /* enable ASPM and CLKREQ if srom doesn't have it */
505 /* Needs to happen when update to shadow SROM is needed
506 * : Coming out of 'standby'/'hibernate'
507 * : If pcie_war_aspm_ovr state changed
510 pcie_war_aspm_clkreq(pcicore_info_t
*pi
)
512 sbpcieregs_t
*pcieregs
= pi
->regs
.pcieregs
;
514 uint16 val16
, *reg16
;
520 /* bypass this on QT or VSIM */
521 if (!ISSIM_ENAB(sih
)) {
523 reg16
= &pcieregs
->sprom
[SRSH_ASPM_OFFSET
];
524 val16
= R_REG(pi
->osh
, reg16
);
526 val16
&= ~SRSH_ASPM_ENB
;
527 if (pi
->pcie_war_aspm_ovr
== PCIE_ASPM_ENAB
)
528 val16
|= SRSH_ASPM_ENB
;
529 else if (pi
->pcie_war_aspm_ovr
== PCIE_ASPM_L1_ENAB
)
530 val16
|= SRSH_ASPM_L1_ENB
;
531 else if (pi
->pcie_war_aspm_ovr
== PCIE_ASPM_L0s_ENAB
)
532 val16
|= SRSH_ASPM_L0s_ENB
;
534 W_REG(pi
->osh
, reg16
, val16
);
536 w
= OSL_PCI_READ_CONFIG(pi
->osh
, pi
->pciecap_lcreg_offset
, sizeof(uint32
));
537 w
&= ~PCIE_ASPM_ENAB
;
538 w
|= pi
->pcie_war_aspm_ovr
;
539 OSL_PCI_WRITE_CONFIG(pi
->osh
, pi
->pciecap_lcreg_offset
, sizeof(uint32
), w
);
542 reg16
= &pcieregs
->sprom
[SRSH_CLKREQ_OFFSET_REV5
];
543 val16
= R_REG(pi
->osh
, reg16
);
545 if (pi
->pcie_war_aspm_ovr
!= PCIE_ASPM_DISAB
) {
546 val16
|= SRSH_CLKREQ_ENB
;
547 pi
->pcie_pr42767
= TRUE
;
549 val16
&= ~SRSH_CLKREQ_ENB
;
551 W_REG(pi
->osh
, reg16
, val16
);
555 pcie_war_pmebits(pcicore_info_t
*pi
)
557 sbpcieregs_t
*pcieregs
= pi
->regs
.pcieregs
;
558 uint16 val16
, *reg16
;
560 if (pi
->sih
->buscorerev
!= 18 && pi
->sih
->buscorerev
!= 19)
563 reg16
= &pcieregs
->sprom
[SRSH_CLKREQ_OFFSET_REV8
];
564 val16
= R_REG(pi
->osh
, reg16
);
565 if (val16
!= pi
->pmebits
) {
566 PCI_ERROR(("pcie_war_pmebits: pmebits mismatch 0x%x (was 0x%x)\n",
567 val16
, pi
->pmebits
));
568 pi
->pmebits
= 0x1f30;
569 W_REG(pi
->osh
, reg16
, pi
->pmebits
);
570 val16
= R_REG(pi
->osh
, reg16
);
571 PCI_ERROR(("pcie_war_pmebits: update pmebits to 0x%x\n", val16
));
575 /* Apply the polarity determined at the start */
576 /* Needs to happen when coming out of 'standby'/'hibernate' */
578 pcie_war_serdes(pcicore_info_t
*pi
)
582 if (pi
->pcie_polarity
!= 0)
583 pcie_mdiowrite(pi
, MDIODATA_DEV_RX
, SERDES_RX_CTRL
, pi
->pcie_polarity
);
585 pcie_mdioread(pi
, MDIODATA_DEV_PLL
, SERDES_PLL_CTRL
, &w
);
586 if (w
& PLL_CTRL_FREQDET_EN
) {
587 w
&= ~PLL_CTRL_FREQDET_EN
;
588 pcie_mdiowrite(pi
, MDIODATA_DEV_PLL
, SERDES_PLL_CTRL
, w
);
592 /* Fix MISC config to allow coming out of L2/L3-Ready state w/o PRST */
593 /* Needs to happen when coming out of 'standby'/'hibernate' */
595 BCMINITFN(pcie_misc_config_fixup
)(pcicore_info_t
*pi
)
597 sbpcieregs_t
*pcieregs
= pi
->regs
.pcieregs
;
598 uint16 val16
, *reg16
;
600 reg16
= &pcieregs
->sprom
[SRSH_PCIE_MISC_CONFIG
];
601 val16
= R_REG(pi
->osh
, reg16
);
603 if ((val16
& SRSH_L23READY_EXIT_NOPERST
) == 0) {
604 val16
|= SRSH_L23READY_EXIT_NOPERST
;
605 W_REG(pi
->osh
, reg16
, val16
);
609 /* quick hack for testing */
610 /* Needs to happen when coming out of 'standby'/'hibernate' */
612 pcie_war_noplldown(pcicore_info_t
*pi
)
614 sbpcieregs_t
*pcieregs
= pi
->regs
.pcieregs
;
617 ASSERT(pi
->sih
->buscorerev
== 7);
619 /* turn off serdes PLL down */
620 si_corereg(pi
->sih
, SI_CC_IDX
, OFFSETOF(chipcregs_t
, chipcontrol
),
621 CHIPCTRL_4321_PLL_DOWN
, CHIPCTRL_4321_PLL_DOWN
);
623 /* clear srom shadow backdoor */
624 reg16
= &pcieregs
->sprom
[SRSH_BD_OFFSET
];
625 W_REG(pi
->osh
, reg16
, 0);
628 /* Needs to happen when coming out of 'standby'/'hibernate' */
630 pcie_war_pci_setup(pcicore_info_t
*pi
)
633 osl_t
*osh
= pi
->osh
;
634 sbpcieregs_t
*pcieregs
= pi
->regs
.pcieregs
;
637 if ((sih
->buscorerev
== 0) || (sih
->buscorerev
== 1)) {
638 w
= pcie_readreg(osh
, pcieregs
, PCIE_PCIEREGS
, PCIE_TLP_WORKAROUNDSREG
);
640 pcie_writereg(osh
, pcieregs
, PCIE_PCIEREGS
, PCIE_TLP_WORKAROUNDSREG
, w
);
643 if (sih
->buscorerev
== 1) {
644 w
= pcie_readreg(osh
, pcieregs
, PCIE_PCIEREGS
, PCIE_DLLP_LCREG
);
646 pcie_writereg(osh
, pcieregs
, PCIE_PCIEREGS
, PCIE_DLLP_LCREG
, w
);
649 if (sih
->buscorerev
== 0) {
650 pcie_mdiowrite(pi
, MDIODATA_DEV_RX
, SERDES_RX_TIMER1
, 0x8128);
651 pcie_mdiowrite(pi
, MDIODATA_DEV_RX
, SERDES_RX_CDR
, 0x0100);
652 pcie_mdiowrite(pi
, MDIODATA_DEV_RX
, SERDES_RX_CDRBW
, 0x1466);
653 } else if (PCIE_ASPM(sih
)) {
654 /* Change the L1 threshold for better performance */
655 w
= pcie_readreg(osh
, pcieregs
, PCIE_PCIEREGS
, PCIE_DLLP_PMTHRESHREG
);
656 w
&= ~(PCIE_L1THRESHOLDTIME_MASK
);
657 w
|= (PCIE_L1THRESHOLD_WARVAL
<< PCIE_L1THRESHOLDTIME_SHIFT
);
658 pcie_writereg(osh
, pcieregs
, PCIE_PCIEREGS
, PCIE_DLLP_PMTHRESHREG
, w
);
662 pcie_war_aspm_clkreq(pi
);
663 } else if (pi
->sih
->buscorerev
== 7)
664 pcie_war_noplldown(pi
);
666 /* Note that the fix is actually in the SROM, that's why this is open-ended */
667 if (pi
->sih
->buscorerev
>= 6)
668 pcie_misc_config_fixup(pi
);
672 pcie_war_ovr_aspm_update(void *pch
, uint8 aspm
)
674 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
676 if (!PCIE_ASPM(pi
->sih
))
680 if (aspm
> PCIE_ASPM_ENAB
)
683 pi
->pcie_war_aspm_ovr
= aspm
;
685 /* Update the current state */
686 pcie_war_aspm_clkreq(pi
);
691 pcie_power_save_enable(void *pch
, bool enable
)
693 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
699 pi
->pcie_power_save
= enable
;
703 pcie_power_save_upd(pcicore_info_t
*pi
, bool up
)
707 if (!pi
->pcie_power_save
)
711 if ((sih
->buscorerev
>= 15) && (sih
->buscorerev
<= 20)) {
713 pcicore_pcieserdesreg(pi
, MDIO_DEV_BLK1
, BLK1_PWR_MGMT1
, 1, 0x7F64);
716 pcicore_pcieserdesreg(pi
, MDIO_DEV_BLK1
, BLK1_PWR_MGMT3
, 1, 0x74);
718 pcicore_pcieserdesreg(pi
, MDIO_DEV_BLK1
, BLK1_PWR_MGMT3
, 1, 0x7C);
723 pcie_set_request_size(void *pch
, uint16 size
)
725 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
730 pi
->pcie_reqsize
= PCIE_CAP_DEVCTRL_MRRS_128B
;
731 else if (size
== 256)
732 pi
->pcie_reqsize
= PCIE_CAP_DEVCTRL_MRRS_256B
;
733 else if (size
== 512)
734 pi
->pcie_reqsize
= PCIE_CAP_DEVCTRL_MRRS_512B
;
738 if (pi
->sih
->buscorerev
== 18 || pi
->sih
->buscorerev
== 19)
739 pcie_devcontrol_mrrs(pi
, PCIE_CAP_DEVCTRL_MRRS_MASK
, (uint32
)pi
->pcie_reqsize
);
743 pcie_get_request_size(void *pch
)
745 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
750 if (pi
->pcie_reqsize
== PCIE_CAP_DEVCTRL_MRRS_128B
)
752 else if (pi
->pcie_reqsize
== PCIE_CAP_DEVCTRL_MRRS_256B
)
754 else if (pi
->pcie_reqsize
== PCIE_CAP_DEVCTRL_MRRS_512B
)
759 /* ***** Functions called during driver state changes ***** */
761 BCMATTACHFN(pcicore_attach
)(void *pch
, char *pvars
, int state
)
763 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
766 if (PCIE_ASPM(sih
)) {
767 if (((sih
->boardvendor
== VENDOR_APPLE
) &&
768 ((uint8
)getintvar(pvars
, "sromrev") == 4) &&
769 ((uint8
)getintvar(pvars
, "boardrev") <= 0x71)) ||
770 ((uint32
)getintvar(pvars
, "boardflags2") & BFL2_PCIEWAR_OVR
)) {
771 pi
->pcie_war_aspm_ovr
= PCIE_ASPM_DISAB
;
773 pi
->pcie_war_aspm_ovr
= PCIE_ASPM_ENAB
;
777 pi
->pcie_reqsize
= PCIE_CAP_DEVCTRL_MRRS_128B
;
778 if (BCM4331_CHIP_ID
== CHIPID(sih
->chip
))
779 pi
->pcie_reqsize
= PCIE_CAP_DEVCTRL_MRRS_512B
;
781 /* These need to happen in this order only */
782 pcie_war_polarity(pi
);
786 pcie_war_aspm_clkreq(pi
);
788 pcie_clkreq_upd(pi
, state
);
790 /* Alter default TX drive strength setting */
791 if (sih
->boardvendor
== VENDOR_APPLE
) {
792 if (sih
->boardtype
== 0x8d)
793 /* change the TX drive strength to max */
794 pcicore_pcieserdesreg(pch
, MDIO_DEV_TXCTRL0
, 0x18, 0xff, 0x7f);
795 else if (BCM4331_CHIP_ID
== CHIPID(sih
->chip
))
796 /* change the drive strength for X19b & X28 to 700mv */
797 pcicore_pcieserdesreg(pch
, MDIO_DEV_TXCTRL0
, 0x18, 0xff, 0x70);
802 pcicore_hwup(void *pch
)
804 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
806 if (!pi
|| !PCIE(pi
->sih
))
809 pcie_power_save_upd(pi
, TRUE
);
811 if (pi
->sih
->boardtype
== CB2_4321_BOARD
|| pi
->sih
->boardtype
== CB2_4321_AG_BOARD
)
812 pcicore_fixlatencytimer(pch
, 0x20);
814 pcie_war_pci_setup(pi
);
816 /* Alter default TX drive strength setting */
817 if (pi
->sih
->boardvendor
== VENDOR_APPLE
) {
818 if (pi
->sih
->boardtype
== 0x8d)
819 /* change the TX drive strength to max */
820 pcicore_pcieserdesreg(pch
, MDIO_DEV_TXCTRL0
, 0x18, 0xff, 0x7f);
821 else if (BCM4331_CHIP_ID
== CHIPID(pi
->sih
->chip
))
822 /* change the drive strength for X19b & X28 to 700mv */
823 pcicore_pcieserdesreg(pch
, MDIO_DEV_TXCTRL0
, 0x18, 0xff, 0x70);
828 pcicore_up(void *pch
, int state
)
830 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
831 bool is_x19_x28
= FALSE
;
833 if (!pi
|| !PCIE(pi
->sih
))
836 pcie_power_save_upd(pi
, TRUE
);
838 /* Restore L1 timer for better performance */
839 pcie_extendL1timer(pi
, TRUE
);
841 pcie_clkreq_upd(pi
, state
);
843 is_x19_x28
= ((pi
->sih
->boardvendor
== VENDOR_APPLE
) &&
844 ((pi
->sih
->boardtype
== BCM94331X19
) ||
845 (pi
->sih
->boardtype
== BCM94331PCIEBT3Ax_SSID
)));
847 if (pi
->sih
->buscorerev
== 18 ||
848 (pi
->sih
->buscorerev
== 19 && !is_x19_x28
))
849 pi
->pcie_reqsize
= PCIE_CAP_DEVCTRL_MRRS_128B
;
851 pcie_devcontrol_mrrs(pi
, PCIE_CAP_DEVCTRL_MRRS_MASK
, pi
->pcie_reqsize
);
854 /* When the device is going to enter D3 state (or the system is going to enter S3/S4 states */
856 pcicore_sleep(void *pch
)
858 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
861 if (!pi
|| !PCIE(pi
->sih
))
864 pcie_power_save_upd(pi
, FALSE
);
867 if (!PCIE_ASPM(pi
->sih
))
871 w
= OSL_PCI_READ_CONFIG(pi
->osh
, pi
->pciecap_lcreg_offset
, sizeof(uint32
));
872 w
&= ~PCIE_CAP_LCREG_ASPML1
;
873 OSL_PCI_WRITE_CONFIG(pi
->osh
, pi
->pciecap_lcreg_offset
, sizeof(uint32
), w
);
876 pi
->pcie_pr42767
= FALSE
;
880 pcicore_down(void *pch
, int state
)
882 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
884 if (!pi
|| !PCIE(pi
->sih
))
887 pcie_clkreq_upd(pi
, state
);
889 /* Reduce L1 timer for better power savings */
890 pcie_extendL1timer(pi
, FALSE
);
892 pcie_power_save_upd(pi
, FALSE
);
895 /* ***** Wake-on-wireless-LAN (WOWL) support functions ***** */
896 /* Just uses PCI config accesses to find out, when needed before sb_attach is done */
898 pcicore_pmecap_fast(osl_t
*osh
)
903 cap_ptr
= pcicore_find_pci_capability(osh
, PCI_CAP_POWERMGMTCAP_ID
, NULL
, NULL
);
908 pmecap
= OSL_PCI_READ_CONFIG(osh
, cap_ptr
, sizeof(uint32
));
910 return ((pmecap
& PME_CAP_PM_STATES
) != 0);
913 /* return TRUE if PM capability exists in the pci config space
914 * Uses and caches the information using core handle
917 pcicore_pmecap(pcicore_info_t
*pi
)
921 sbpcieregs_t
*pcieregs
= pi
->regs
.pcieregs
;
924 if (!pi
->pmecap_offset
) {
925 cap_ptr
= pcicore_find_pci_capability(pi
->osh
, PCI_CAP_POWERMGMTCAP_ID
, NULL
, NULL
);
929 pi
->pmecap_offset
= cap_ptr
;
931 reg16
= &pcieregs
->sprom
[SRSH_CLKREQ_OFFSET_REV8
];
932 pi
->pmebits
= R_REG(pi
->osh
, reg16
);
934 pmecap
= OSL_PCI_READ_CONFIG(pi
->osh
, pi
->pmecap_offset
, sizeof(uint32
));
936 /* At least one state can generate PME */
937 pi
->pmecap
= (pmecap
& PME_CAP_PM_STATES
) != 0;
943 /* Enable PME generation */
945 pcicore_pmeen(void *pch
)
947 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
950 /* if not pmecapable return */
951 if (!pcicore_pmecap(pi
))
954 pcie_war_pmebits(pi
);
955 w
= OSL_PCI_READ_CONFIG(pi
->osh
, pi
->pmecap_offset
+ PME_CSR_OFFSET
, sizeof(uint32
));
956 w
|= (PME_CSR_PME_EN
);
957 OSL_PCI_WRITE_CONFIG(pi
->osh
, pi
->pmecap_offset
+ PME_CSR_OFFSET
, sizeof(uint32
), w
);
961 * Return TRUE if PME status set
964 pcicore_pmestat(void *pch
)
966 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
969 if (!pcicore_pmecap(pi
))
972 w
= OSL_PCI_READ_CONFIG(pi
->osh
, pi
->pmecap_offset
+ PME_CSR_OFFSET
, sizeof(uint32
));
974 return (w
& PME_CSR_PME_STAT
) == PME_CSR_PME_STAT
;
977 /* Disable PME generation, clear the PME status bit if set
980 pcicore_pmeclr(void *pch
)
982 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
985 if (!pcicore_pmecap(pi
))
988 pcie_war_pmebits(pi
);
989 w
= OSL_PCI_READ_CONFIG(pi
->osh
, pi
->pmecap_offset
+ PME_CSR_OFFSET
, sizeof(uint32
));
991 PCI_ERROR(("pcicore_pci_pmeclr PMECSR : 0x%x\n", w
));
993 /* PMESTAT is cleared by writing 1 to it */
994 w
&= ~(PME_CSR_PME_EN
);
996 OSL_PCI_WRITE_CONFIG(pi
->osh
, pi
->pmecap_offset
+ PME_CSR_OFFSET
, sizeof(uint32
), w
);
1000 pcicore_fixlatencytimer(pcicore_info_t
* pch
, uint8 timer_val
)
1002 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
1007 lattim
= read_pci_cfg_byte(PCI_CFG_LATTIM
);
1010 PCI_ERROR(("%s: Modifying PCI_CFG_LATTIM from 0x%x to 0x%x\n",
1011 __FUNCTION__
, lattim
, timer_val
));
1012 write_pci_cfg_byte(PCI_CFG_LATTIM
, timer_val
);
1017 pcie_lcreg(void *pch
, uint32 mask
, uint32 val
)
1019 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
1022 offset
= pi
->pciecap_lcreg_offset
;
1028 OSL_PCI_WRITE_CONFIG(pi
->osh
, offset
, sizeof(uint32
), val
);
1030 return OSL_PCI_READ_CONFIG(pi
->osh
, offset
, sizeof(uint32
));
1035 pcicore_dump(void *pch
, struct bcmstrbuf
*b
)
1037 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
1039 bcm_bprintf(b
, "FORCEHT %d pcie_polarity 0x%x pcie_aspm_ovr 0x%x\n",
1040 pi
->sih
->pci_pr32414
, pi
->pcie_polarity
, pi
->pcie_war_aspm_ovr
);
1045 pcicore_pciereg(void *pch
, uint32 offset
, uint32 mask
, uint32 val
, uint type
)
1048 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
1049 sbpcieregs_t
*pcieregs
= pi
->regs
.pcieregs
;
1050 osl_t
*osh
= pi
->osh
;
1053 PCI_ERROR(("PCIEREG: 0x%x writeval 0x%x\n", offset
, val
));
1054 pcie_writereg(osh
, pcieregs
, type
, offset
, val
);
1057 /* Should not read register 0x154 */
1058 if (pi
->sih
->buscorerev
<= 5 && offset
== PCIE_DLLP_PCIE11
&& type
== PCIE_PCIEREGS
)
1061 reg_val
= pcie_readreg(osh
, pcieregs
, type
, offset
);
1062 PCI_ERROR(("PCIEREG: 0x%x readval is 0x%x\n", offset
, reg_val
));
1068 pcicore_pcieserdesreg(void *pch
, uint32 mdioslave
, uint32 offset
, uint32 mask
, uint32 val
)
1071 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
1074 pcie_mdiowrite(pi
, mdioslave
, offset
, val
);
1077 if (pcie_mdioread(pi
, mdioslave
, offset
, ®_val
))
1078 reg_val
= 0xFFFFFFFF;
1084 #if defined(BCMDBG_DUMP)
1086 /* size that can take bitfielddump */
1087 #define BITFIELD_DUMP_SIZE 2048
1089 /* Dump PCIE PLP/DLLP/TLP diagnostic registers */
1091 pcicore_dump_pcieregs(void *pch
, struct bcmstrbuf
*b
)
1093 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
1094 sbpcieregs_t
*pcieregs
= pi
->regs
.pcieregs
;
1095 si_t
*sih
= pi
->sih
;
1097 char *bitfield_dump_buf
;
1099 if (!(bitfield_dump_buf
= MALLOC(pi
->osh
, BITFIELD_DUMP_SIZE
))) {
1100 printf("bitfield dump allocation failed\n");
1104 bcm_bprintf(b
, "PLPRegs \t");
1105 bcmdumpfields(si_pcie_readreg
, (void *)(uintptr
)pi
->sih
, PCIE_PCIEREGS
,
1106 (struct fielddesc
*)(uintptr
)pcie_plp_regdesc
,
1107 bitfield_dump_buf
, BITFIELD_DUMP_SIZE
);
1108 bcm_bprintf(b
, "%s", bitfield_dump_buf
);
1109 bzero(bitfield_dump_buf
, BITFIELD_DUMP_SIZE
);
1110 bcm_bprintf(b
, "\n");
1111 bcm_bprintf(b
, "DLLPRegs \t");
1112 bcmdumpfields(si_pcie_readreg
, (void *)(uintptr
)pi
->sih
, PCIE_PCIEREGS
,
1113 (struct fielddesc
*)(uintptr
)pcie_dllp_regdesc
,
1114 bitfield_dump_buf
, BITFIELD_DUMP_SIZE
);
1115 bcm_bprintf(b
, "%s", bitfield_dump_buf
);
1116 bzero(bitfield_dump_buf
, BITFIELD_DUMP_SIZE
);
1117 bcm_bprintf(b
, "\n");
1118 bcm_bprintf(b
, "TLPRegs \t");
1119 bcmdumpfields(si_pcie_readreg
, (void *)(uintptr
)pi
->sih
, PCIE_PCIEREGS
,
1120 (struct fielddesc
*)(uintptr
)pcie_tlp_regdesc
,
1121 bitfield_dump_buf
, BITFIELD_DUMP_SIZE
);
1122 bcm_bprintf(b
, "%s", bitfield_dump_buf
);
1123 bzero(bitfield_dump_buf
, BITFIELD_DUMP_SIZE
);
1124 bcm_bprintf(b
, "\n");
1126 /* enable mdio access to SERDES */
1127 W_REG(pi
->osh
, (&pcieregs
->mdiocontrol
), MDIOCTL_PREAM_EN
| MDIOCTL_DIVISOR_VAL
);
1129 bcm_bprintf(b
, "SERDES regs \n");
1130 if (sih
->buscorerev
>= 10) {
1131 pcie_mdioread(pi
, MDIO_DEV_IEEE0
, 0x2, ®_val
);
1132 bcm_bprintf(b
, "block IEEE0, offset 2: 0x%x\n", reg_val
);
1133 pcie_mdioread(pi
, MDIO_DEV_IEEE0
, 0x3, ®_val
);
1134 bcm_bprintf(b
, "block IEEE0, offset 2: 0x%x\n", reg_val
);
1135 pcie_mdioread(pi
, MDIO_DEV_IEEE1
, 0x08, ®_val
);
1136 bcm_bprintf(b
, "block IEEE1, lanestatus: 0x%x\n", reg_val
);
1137 pcie_mdioread(pi
, MDIO_DEV_IEEE1
, 0x0a, ®_val
);
1138 bcm_bprintf(b
, "block IEEE1, lanestatus2: 0x%x\n", reg_val
);
1139 pcie_mdioread(pi
, MDIO_DEV_BLK4
, 0x16, ®_val
);
1140 bcm_bprintf(b
, "MDIO_DEV_BLK4, lanetest0: 0x%x\n", reg_val
);
1141 pcie_mdioread(pi
, MDIO_DEV_TXPLL
, 0x11, ®_val
);
1142 bcm_bprintf(b
, "MDIO_DEV_TXPLL, pllcontrol: 0x%x\n", reg_val
);
1143 pcie_mdioread(pi
, MDIO_DEV_TXPLL
, 0x12, ®_val
);
1144 bcm_bprintf(b
, "MDIO_DEV_TXPLL, plltimer1: 0x%x\n", reg_val
);
1145 pcie_mdioread(pi
, MDIO_DEV_TXPLL
, 0x13, ®_val
);
1146 bcm_bprintf(b
, "MDIO_DEV_TXPLL, plltimer2: 0x%x\n", reg_val
);
1147 pcie_mdioread(pi
, MDIO_DEV_TXPLL
, 0x14, ®_val
);
1148 bcm_bprintf(b
, "MDIO_DEV_TXPLL, plltimer3: 0x%x\n", reg_val
);
1149 pcie_mdioread(pi
, MDIO_DEV_TXPLL
, 0x17, ®_val
);
1150 bcm_bprintf(b
, "MDIO_DEV_TXPLL, freqdetcounter: 0x%x\n", reg_val
);
1152 pcie_mdioread(pi
, MDIODATA_DEV_RX
, SERDES_RX_TIMER1
, ®_val
);
1153 bcm_bprintf(b
, "rxtimer1 0x%x ", reg_val
);
1154 pcie_mdioread(pi
, MDIODATA_DEV_RX
, SERDES_RX_CDR
, ®_val
);
1155 bcm_bprintf(b
, "rxCDR 0x%x ", reg_val
);
1156 pcie_mdioread(pi
, MDIODATA_DEV_RX
, SERDES_RX_CDRBW
, ®_val
);
1157 bcm_bprintf(b
, "rxCDRBW 0x%x\n", reg_val
);
1160 /* disable mdio access to SERDES */
1161 W_REG(pi
->osh
, (&pcieregs
->mdiocontrol
), 0);
1163 MFREE(pi
->osh
, bitfield_dump_buf
, BITFIELD_DUMP_SIZE
);