2 * Code to operate on PCI/E core, in NIC mode
4 * Copyright (C) 2011, 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 323253 2012-03-23 17:21:10Z $
31 #include <pcie_core.h>
37 sbpcieregs_t
*pcieregs
;
39 } regs
; /* Memory mapped register to the core */
41 si_t
*sih
; /* System interconnect handle */
42 osl_t
*osh
; /* OSL handle */
43 uint8 pciecap_lcreg_offset
; /* PCIE capability LCreg offset in the config space */
44 uint8 pciecap_devctrl_offset
; /* PCIE DevControl reg offset in the config space */
47 uint8 pcie_war_aspm_ovr
; /* Override ASPM/Clkreq settings */
48 uint8 pmecap_offset
; /* PM Capability offset in the config space */
49 bool pmecap
; /* Capable of generating PME */
54 uint8 pcie_configspace
[PCI_CONFIG_SPACE_SIZE
];
59 #define PCI_ERROR(args) printf args
61 #define PCI_ERROR(args)
62 #endif /* BCMDBG_ERR */
64 /* routines to access mdio slave device registers */
65 static bool pcie_mdiosetblock(pcicore_info_t
*pi
, uint blk
);
66 static int pcie_mdioop(pcicore_info_t
*pi
, uint physmedia
, uint regaddr
, bool write
, uint
*val
);
67 static int pciegen1_mdioop(pcicore_info_t
*pi
, uint physmedia
, uint regaddr
, bool write
,
69 static int pciegen2_mdioop(pcicore_info_t
*pi
, uint physmedia
, uint regaddr
, bool write
,
70 uint
*val
, bool slave_bypass
);
71 static int pcie_mdiowrite(pcicore_info_t
*pi
, uint physmedia
, uint readdr
, uint val
);
72 static int pcie_mdioread(pcicore_info_t
*pi
, uint physmedia
, uint readdr
, uint
*ret_val
);
74 static void pcie_extendL1timer(pcicore_info_t
*pi
, bool extend
);
75 static void pcie_clkreq_upd(pcicore_info_t
*pi
, uint state
);
77 static void pcie_war_aspm_clkreq(pcicore_info_t
*pi
);
78 static void pcie_war_serdes(pcicore_info_t
*pi
);
79 static void pcie_war_noplldown(pcicore_info_t
*pi
);
80 static void pcie_war_polarity(pcicore_info_t
*pi
);
81 static void pcie_war_pci_setup(pcicore_info_t
*pi
);
82 static void pcie_power_save_upd(pcicore_info_t
*pi
, bool up
);
84 static bool pcicore_pmecap(pcicore_info_t
*pi
);
85 static void pcicore_fixlatencytimer(pcicore_info_t
* pch
, uint8 timer_val
);
87 #define PCIE_GEN1(sih) ((BUSTYPE((sih)->bustype) == PCI_BUS) && \
88 ((sih)->buscoretype == PCIE_CORE_ID))
89 #define PCIE_GEN2(sih) ((BUSTYPE((sih)->bustype) == PCI_BUS) && \
90 ((sih)->buscoretype == PCIE2_CORE_ID))
91 #define PCIE(sih) (PCIE_GEN1(sih) || PCIE_GEN2(sih))
93 #define PCIEGEN1_ASPM(sih) ((PCIE_GEN1(sih)) && \
94 (((sih)->buscorerev >= 3) && ((sih)->buscorerev <= 5)))
96 #define DWORD_ALIGN(x) (x & ~(0x03))
97 #define BYTE_POS(x) (x & 0x3)
98 #define WORD_POS(x) (x & 0x1)
100 #define BYTE_SHIFT(x) (8 * BYTE_POS(x))
101 #define WORD_SHIFT(x) (16 * WORD_POS(x))
103 #define BYTE_VAL(a, x) ((a >> BYTE_SHIFT(x)) & 0xFF)
104 #define WORD_VAL(a, x) ((a >> WORD_SHIFT(x)) & 0xFFFF)
106 #define read_pci_cfg_byte(a) \
107 (BYTE_VAL(OSL_PCI_READ_CONFIG(osh, DWORD_ALIGN(a), 4), a) & 0xff)
109 #define read_pci_cfg_word(a) \
110 (WORD_VAL(OSL_PCI_READ_CONFIG(osh, DWORD_ALIGN(a), 4), a) & 0xffff)
112 #define write_pci_cfg_byte(a, val) do { \
114 tmpval = (OSL_PCI_READ_CONFIG(osh, DWORD_ALIGN(a), 4) & ~0xFF << BYTE_POS(a)) | \
115 val << BYTE_POS(a); \
116 OSL_PCI_WRITE_CONFIG(osh, DWORD_ALIGN(a), 4, tmpval); \
119 #define write_pci_cfg_word(a, val) do { \
121 tmpval = (OSL_PCI_READ_CONFIG(osh, DWORD_ALIGN(a), 4) & ~0xFFFF << WORD_POS(a)) | \
122 val << WORD_POS(a); \
123 OSL_PCI_WRITE_CONFIG(osh, DWORD_ALIGN(a), 4, tmpval); \
126 /* delay needed between the mdio control/ mdiodata register data access */
127 #define PR28829_DELAY() OSL_DELAY(10)
129 /* Initialize the PCI core. It's caller's responsibility to make sure that this is done
133 pcicore_init(si_t
*sih
, osl_t
*osh
, void *regs
)
138 ASSERT(sih
->bustype
== PCI_BUS
);
140 /* alloc pcicore_info_t */
141 if ((pi
= MALLOC(osh
, sizeof(pcicore_info_t
))) == NULL
) {
142 PCI_ERROR(("pci_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh
)));
146 bzero(pi
, sizeof(pcicore_info_t
));
151 if (sih
->buscoretype
== PCIE2_CORE_ID
) {
152 pi
->regs
.pcieregs
= (sbpcieregs_t
*)regs
;
153 cap_ptr
= pcicore_find_pci_capability(pi
->osh
, PCI_CAP_PCIECAP_ID
, NULL
, NULL
);
155 pi
->pciecap_devctrl_offset
= cap_ptr
+ PCIE_CAP_DEVCTRL_OFFSET
;
156 pi
->pciecap_lcreg_offset
= cap_ptr
+ PCIE_CAP_LINKCTRL_OFFSET
;
157 } else if (sih
->buscoretype
== PCIE_CORE_ID
) {
158 pi
->regs
.pcieregs
= (sbpcieregs_t
*)regs
;
159 cap_ptr
= pcicore_find_pci_capability(pi
->osh
, PCI_CAP_PCIECAP_ID
, NULL
, NULL
);
161 pi
->pciecap_lcreg_offset
= cap_ptr
+ PCIE_CAP_LINKCTRL_OFFSET
;
162 pi
->pciecap_devctrl_offset
= cap_ptr
+ PCIE_CAP_DEVCTRL_OFFSET
;
163 pi
->pcie_power_save
= TRUE
; /* Enable pcie_power_save by default */
165 pi
->regs
.pciregs
= (sbpciregs_t
*)regs
;
171 pcicore_deinit(void *pch
)
173 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
178 MFREE(pi
->osh
, pi
, sizeof(pcicore_info_t
));
181 /* return cap_offset if requested capability exists in the PCI config space */
182 /* Note that it's caller's responsibility to make sure it's a pci bus */
184 pcicore_find_pci_capability(osl_t
*osh
, uint8 req_cap_id
, uchar
*buf
, uint32
*buflen
)
191 /* check for Header type 0 */
192 byte_val
= read_pci_cfg_byte(PCI_CFG_HDR
);
193 if ((byte_val
& 0x7f) != PCI_HEADER_NORMAL
)
196 /* check if the capability pointer field exists */
197 byte_val
= read_pci_cfg_byte(PCI_CFG_STAT
);
198 if (!(byte_val
& PCI_CAPPTR_PRESENT
))
201 cap_ptr
= read_pci_cfg_byte(PCI_CFG_CAPPTR
);
202 /* check if the capability pointer is 0x00 */
206 /* loop thr'u the capability list and see if the pcie capabilty exists */
208 cap_id
= read_pci_cfg_byte(cap_ptr
);
210 while (cap_id
!= req_cap_id
) {
211 cap_ptr
= read_pci_cfg_byte((cap_ptr
+1));
212 if (cap_ptr
== 0x00) break;
213 cap_id
= read_pci_cfg_byte(cap_ptr
);
215 if (cap_id
!= req_cap_id
) {
218 /* found the caller requested capability */
219 if ((buf
!= NULL
) && (buflen
!= NULL
)) {
223 if (!bufsize
) goto end
;
225 /* copy the cpability data excluding cap ID and next ptr */
226 cap_data
= cap_ptr
+ 2;
227 if ((bufsize
+ cap_data
) > SZPCR
)
228 bufsize
= SZPCR
- cap_data
;
231 *buf
= read_pci_cfg_byte(cap_data
);
240 /* ***** Register Access API */
242 pcie_readreg(si_t
*sih
, sbpcieregs_t
*pcieregs
, uint addrtype
, uint offset
)
244 uint retval
= 0xFFFFFFFF;
245 osl_t
*osh
= si_osh(sih
);
247 ASSERT(pcieregs
!= NULL
);
250 if ((BUSTYPE(sih
->bustype
) == SI_BUS
) || PCIE_GEN1(sih
)) {
252 case PCIE_CONFIGREGS
:
253 W_REG(osh
, (&pcieregs
->configaddr
), offset
);
254 (void)R_REG(osh
, (&pcieregs
->configaddr
));
255 retval
= R_REG(osh
, &(pcieregs
->configdata
));
258 W_REG(osh
, &(pcieregs
->u
.pcie1
.pcieindaddr
), offset
);
259 (void)R_REG(osh
, (&pcieregs
->u
.pcie1
.pcieindaddr
));
260 retval
= R_REG(osh
, &(pcieregs
->u
.pcie1
.pcieinddata
));
267 else if (PCIE_GEN2(sih
)) {
268 W_REG(osh
, (&pcieregs
->configaddr
), offset
);
269 (void)R_REG(osh
, (&pcieregs
->configaddr
));
270 retval
= R_REG(osh
, &(pcieregs
->configdata
));
277 pcie_writereg(si_t
*sih
, sbpcieregs_t
*pcieregs
, uint addrtype
, uint offset
, uint val
)
279 osl_t
*osh
= si_osh(sih
);
281 ASSERT(pcieregs
!= NULL
);
284 if ((BUSTYPE(sih
->bustype
) == SI_BUS
) || PCIE_GEN1(sih
)) {
286 case PCIE_CONFIGREGS
:
287 W_REG(osh
, (&pcieregs
->configaddr
), offset
);
288 W_REG(osh
, (&pcieregs
->configdata
), val
);
291 W_REG(osh
, (&pcieregs
->u
.pcie1
.pcieindaddr
), offset
);
292 W_REG(osh
, (&pcieregs
->u
.pcie1
.pcieinddata
), val
);
299 else if (PCIE_GEN2(sih
)) {
300 W_REG(osh
, (&pcieregs
->configaddr
), offset
);
301 W_REG(osh
, (&pcieregs
->configdata
), val
);
307 pcie_mdiosetblock(pcicore_info_t
*pi
, uint blk
)
309 sbpcieregs_t
*pcieregs
= pi
->regs
.pcieregs
;
310 uint mdiodata
, i
= 0;
311 uint pcie_serdes_spinwait
= 200;
313 mdiodata
= MDIODATA_START
| MDIODATA_WRITE
| (MDIODATA_DEV_ADDR
<< MDIODATA_DEVADDR_SHF
) |
314 (MDIODATA_BLK_ADDR
<< MDIODATA_REGADDR_SHF
) | MDIODATA_TA
| (blk
<< 4);
315 W_REG(pi
->osh
, &pcieregs
->u
.pcie1
.mdiodata
, mdiodata
);
318 /* retry till the transaction is complete */
319 while (i
< pcie_serdes_spinwait
) {
320 if (R_REG(pi
->osh
, &(pcieregs
->u
.pcie1
.mdiocontrol
)) & MDIOCTL_ACCESS_DONE
) {
327 if (i
>= pcie_serdes_spinwait
) {
328 PCI_ERROR(("pcie_mdiosetblock: timed out\n"));
336 pcie_mdioop(pcicore_info_t
*pi
, uint physmedia
, uint regaddr
, bool write
, uint
*val
)
338 if (PCIE_GEN1(pi
->sih
))
339 return (pciegen1_mdioop(pi
, physmedia
, regaddr
, write
, val
));
340 else if (PCIE_GEN1(pi
->sih
))
341 return (pciegen2_mdioop(pi
, physmedia
, regaddr
, write
, val
, 0));
347 pciegen2_mdioop(pcicore_info_t
*pi
, uint physmedia
, uint regaddr
, bool write
, uint
*val
,
350 sbpcieregs_t
*pcieregs
= pi
->regs
.pcieregs
;
351 uint pcie_serdes_spinwait
= 200, i
= 0, mdio_ctrl
;
354 if (!PCIE_GEN2(pi
->sih
))
357 /* enable mdio access to SERDES */
358 mdio_ctrl
= MDIOCTL2_DIVISOR_VAL
;
359 mdio_ctrl
|= (regaddr
<< MDIOCTL2_REGADDR_SHF
);
360 mdio_ctrl
|= (physmedia
<< MDIOCTL2_DEVADDR_SHF
);
363 mdio_ctrl
|= MDIOCTL2_SLAVE_BYPASS
;
366 mdio_ctrl
|= MDIOCTL2_READ
;
368 W_REG(pi
->osh
, (&pcieregs
->u
.pcie2
.mdiocontrol
), mdio_ctrl
);
370 reg32
= (uint32
*)&(pcieregs
->u
.pcie2
.mdiowrdata
);
371 W_REG(pi
->osh
, reg32
, *val
);
374 reg32
= (uint32
*)&(pcieregs
->u
.pcie2
.mdiorddata
);
376 /* retry till the transaction is complete */
377 while (i
< pcie_serdes_spinwait
) {
378 if (R_REG(pi
->osh
, reg32
) & MDIODATA2_DONE
) {
380 *val
= (R_REG(pi
->osh
, reg32
) & MDIODATA2_MASK
);
390 pciegen1_mdioop(pcicore_info_t
*pi
, uint physmedia
, uint regaddr
, bool write
, uint
*val
)
392 sbpcieregs_t
*pcieregs
= pi
->regs
.pcieregs
;
395 uint pcie_serdes_spinwait
= 10;
397 if (!PCIE_GEN1(pi
->sih
))
400 /* enable mdio access to SERDES */
401 W_REG(pi
->osh
, (&pcieregs
->u
.pcie1
.mdiocontrol
), MDIOCTL_PREAM_EN
| MDIOCTL_DIVISOR_VAL
);
403 if (pi
->sih
->buscorerev
>= 10) {
404 /* new serdes is slower in rw, using two layers of reg address mapping */
405 if (!pcie_mdiosetblock(pi
, physmedia
))
407 mdiodata
= (MDIODATA_DEV_ADDR
<< MDIODATA_DEVADDR_SHF
) |
408 (regaddr
<< MDIODATA_REGADDR_SHF
);
409 pcie_serdes_spinwait
*= 20;
411 mdiodata
= (physmedia
<< MDIODATA_DEVADDR_SHF_OLD
) |
412 (regaddr
<< MDIODATA_REGADDR_SHF_OLD
);
416 mdiodata
|= (MDIODATA_START
| MDIODATA_READ
| MDIODATA_TA
);
418 mdiodata
|= (MDIODATA_START
| MDIODATA_WRITE
| MDIODATA_TA
| *val
);
420 W_REG(pi
->osh
, &pcieregs
->u
.pcie1
.mdiodata
, mdiodata
);
424 /* retry till the transaction is complete */
425 while (i
< pcie_serdes_spinwait
) {
426 if (R_REG(pi
->osh
, &(pcieregs
->u
.pcie1
.mdiocontrol
)) & MDIOCTL_ACCESS_DONE
) {
429 *val
= (R_REG(pi
->osh
, &(pcieregs
->u
.pcie1
.mdiodata
)) &
432 /* Disable mdio access to SERDES */
433 W_REG(pi
->osh
, (&pcieregs
->u
.pcie1
.mdiocontrol
), 0);
440 PCI_ERROR(("pcie_mdioop: timed out op: %d\n", write
));
441 /* Disable mdio access to SERDES */
442 W_REG(pi
->osh
, (&pcieregs
->u
.pcie1
.mdiocontrol
), 0);
446 /* use the mdio interface to read from mdio slaves */
448 pcie_mdioread(pcicore_info_t
*pi
, uint physmedia
, uint regaddr
, uint
*regval
)
450 return pcie_mdioop(pi
, physmedia
, regaddr
, FALSE
, regval
);
453 /* use the mdio interface to write to mdio slaves */
455 pcie_mdiowrite(pcicore_info_t
*pi
, uint physmedia
, uint regaddr
, uint val
)
457 return pcie_mdioop(pi
, physmedia
, regaddr
, TRUE
, &val
);
460 /* ***** Support functions ***** */
462 pcie_devcontrol_mrrs(void *pch
, uint32 mask
, uint32 val
)
464 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
468 offset
= pi
->pciecap_devctrl_offset
;
472 reg_val
= OSL_PCI_READ_CONFIG(pi
->osh
, offset
, sizeof(uint32
));
475 if (val
> PCIE_CAP_DEVCTRL_MRRS_128B
) {
476 if (PCIE_GEN1(pi
->sih
) && (pi
->sih
->buscorerev
< 18)) {
477 PCI_ERROR(("%s pcie corerev %d doesn't support >128B MRRS",
478 __FUNCTION__
, pi
->sih
->buscorerev
));
479 val
= PCIE_CAP_DEVCTRL_MRRS_128B
;
483 reg_val
&= ~PCIE_CAP_DEVCTRL_MRRS_MASK
;
484 reg_val
|= (val
<< PCIE_CAP_DEVCTRL_MRRS_SHIFT
) & PCIE_CAP_DEVCTRL_MRRS_MASK
;
486 OSL_PCI_WRITE_CONFIG(pi
->osh
, offset
, sizeof(uint32
), reg_val
);
487 reg_val
= OSL_PCI_READ_CONFIG(pi
->osh
, offset
, sizeof(uint32
));
493 pcie_devcontrol_mps(void *pch
, uint32 mask
, uint32 val
)
495 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
499 offset
= pi
->pciecap_devctrl_offset
;
503 reg_val
= OSL_PCI_READ_CONFIG(pi
->osh
, offset
, sizeof(uint32
));
506 reg_val
&= ~PCIE_CAP_DEVCTRL_MPS_MASK
;
507 reg_val
|= (val
<< PCIE_CAP_DEVCTRL_MPS_SHIFT
) & PCIE_CAP_DEVCTRL_MPS_MASK
;
509 OSL_PCI_WRITE_CONFIG(pi
->osh
, offset
, sizeof(uint32
), reg_val
);
510 reg_val
= OSL_PCI_READ_CONFIG(pi
->osh
, offset
, sizeof(uint32
));
516 pcie_clkreq(void *pch
, uint32 mask
, uint32 val
)
518 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
522 offset
= pi
->pciecap_lcreg_offset
;
526 reg_val
= OSL_PCI_READ_CONFIG(pi
->osh
, offset
, sizeof(uint32
));
530 reg_val
|= PCIE_CLKREQ_ENAB
;
532 reg_val
&= ~PCIE_CLKREQ_ENAB
;
533 OSL_PCI_WRITE_CONFIG(pi
->osh
, offset
, sizeof(uint32
), reg_val
);
534 reg_val
= OSL_PCI_READ_CONFIG(pi
->osh
, offset
, sizeof(uint32
));
536 if (reg_val
& PCIE_CLKREQ_ENAB
)
543 pcie_extendL1timer(pcicore_info_t
*pi
, bool extend
)
547 sbpcieregs_t
*pcieregs
= pi
->regs
.pcieregs
;
552 w
= pcie_readreg(sih
, pcieregs
, PCIE_PCIEREGS
, PCIE_DLLP_PMTHRESHREG
);
554 if (extend
&& sih
->buscorerev
>= 7)
555 w
|= PCIE_ASPMTIMER_EXTEND
;
557 w
&= ~PCIE_ASPMTIMER_EXTEND
;
558 pcie_writereg(sih
, pcieregs
, PCIE_PCIEREGS
, PCIE_DLLP_PMTHRESHREG
, w
);
559 w
= pcie_readreg(sih
, pcieregs
, PCIE_PCIEREGS
, PCIE_DLLP_PMTHRESHREG
);
562 /* centralized clkreq control policy */
564 pcie_clkreq_upd(pcicore_info_t
*pi
, uint state
)
574 if (PCIEGEN1_ASPM(sih
))
575 pcie_clkreq((void *)pi
, 1, 0);
578 if (sih
->buscorerev
== 6) { /* turn on serdes PLL down */
579 si_corereg(sih
, SI_CC_IDX
, OFFSETOF(chipcregs_t
, chipcontrol_addr
),
581 si_corereg(sih
, SI_CC_IDX
, OFFSETOF(chipcregs_t
, chipcontrol_data
),
583 } else if (pi
->pcie_pr42767
) {
584 pcie_clkreq((void *)pi
, 1, 1);
588 if (sih
->buscorerev
== 6) { /* turn off serdes PLL down */
589 si_corereg(sih
, SI_CC_IDX
, OFFSETOF(chipcregs_t
, chipcontrol_addr
),
591 si_corereg(sih
, SI_CC_IDX
, OFFSETOF(chipcregs_t
, chipcontrol_data
),
593 } else if (PCIEGEN1_ASPM(sih
)) { /* disable clkreq */
594 pcie_clkreq((void *)pi
, 1, 0);
603 /* ***** PCI core WARs ***** */
604 /* Done only once at attach time */
606 pcie_war_polarity(pcicore_info_t
*pi
)
610 if (pi
->pcie_polarity
!= 0)
613 w
= pcie_readreg(pi
->sih
, pi
->regs
.pcieregs
, PCIE_PCIEREGS
, PCIE_PLP_STATUSREG
);
615 /* Detect the current polarity at attach and force that polarity and
616 * disable changing the polarity
618 if ((w
& PCIE_PLP_POLARITYINV_STAT
) == 0)
619 pi
->pcie_polarity
= (SERDES_RX_CTRL_FORCE
);
621 pi
->pcie_polarity
= (SERDES_RX_CTRL_FORCE
| SERDES_RX_CTRL_POLARITY
);
624 /* enable ASPM and CLKREQ if srom doesn't have it */
625 /* Needs to happen when update to shadow SROM is needed
626 * : Coming out of 'standby'/'hibernate'
627 * : If pcie_war_aspm_ovr state changed
630 pcie_war_aspm_clkreq(pcicore_info_t
*pi
)
632 sbpcieregs_t
*pcieregs
= pi
->regs
.pcieregs
;
634 uint16 val16
, *reg16
;
637 if (!PCIEGEN1_ASPM(sih
))
640 /* bypass this on QT or VSIM */
641 if (!ISSIM_ENAB(sih
)) {
643 reg16
= &pcieregs
->sprom
[SRSH_ASPM_OFFSET
];
644 val16
= R_REG(pi
->osh
, reg16
);
646 val16
&= ~SRSH_ASPM_ENB
;
647 if (pi
->pcie_war_aspm_ovr
== PCIE_ASPM_ENAB
)
648 val16
|= SRSH_ASPM_ENB
;
649 else if (pi
->pcie_war_aspm_ovr
== PCIE_ASPM_L1_ENAB
)
650 val16
|= SRSH_ASPM_L1_ENB
;
651 else if (pi
->pcie_war_aspm_ovr
== PCIE_ASPM_L0s_ENAB
)
652 val16
|= SRSH_ASPM_L0s_ENB
;
654 W_REG(pi
->osh
, reg16
, val16
);
656 w
= OSL_PCI_READ_CONFIG(pi
->osh
, pi
->pciecap_lcreg_offset
, sizeof(uint32
));
657 w
&= ~PCIE_ASPM_ENAB
;
658 w
|= pi
->pcie_war_aspm_ovr
;
659 OSL_PCI_WRITE_CONFIG(pi
->osh
, pi
->pciecap_lcreg_offset
, sizeof(uint32
), w
);
662 reg16
= &pcieregs
->sprom
[SRSH_CLKREQ_OFFSET_REV5
];
663 val16
= R_REG(pi
->osh
, reg16
);
665 if (pi
->pcie_war_aspm_ovr
!= PCIE_ASPM_DISAB
) {
666 val16
|= SRSH_CLKREQ_ENB
;
667 pi
->pcie_pr42767
= TRUE
;
669 val16
&= ~SRSH_CLKREQ_ENB
;
671 W_REG(pi
->osh
, reg16
, val16
);
675 pcie_war_pmebits(pcicore_info_t
*pi
)
677 sbpcieregs_t
*pcieregs
= pi
->regs
.pcieregs
;
678 uint16 val16
, *reg16
;
680 if (pi
->sih
->buscorerev
!= 18 && pi
->sih
->buscorerev
!= 19)
683 reg16
= &pcieregs
->sprom
[SRSH_CLKREQ_OFFSET_REV8
];
684 val16
= R_REG(pi
->osh
, reg16
);
685 if (val16
!= pi
->pmebits
) {
686 PCI_ERROR(("pcie_war_pmebits: pmebits mismatch 0x%x (was 0x%x)\n",
687 val16
, pi
->pmebits
));
688 pi
->pmebits
= 0x1f30;
689 W_REG(pi
->osh
, reg16
, pi
->pmebits
);
690 val16
= R_REG(pi
->osh
, reg16
);
691 PCI_ERROR(("pcie_war_pmebits: update pmebits to 0x%x\n", val16
));
695 /* Apply the polarity determined at the start */
696 /* Needs to happen when coming out of 'standby'/'hibernate' */
698 pcie_war_serdes(pcicore_info_t
*pi
)
702 if (pi
->pcie_polarity
!= 0)
703 pcie_mdiowrite(pi
, MDIODATA_DEV_RX
, SERDES_RX_CTRL
, pi
->pcie_polarity
);
705 pcie_mdioread(pi
, MDIODATA_DEV_PLL
, SERDES_PLL_CTRL
, &w
);
706 if (w
& PLL_CTRL_FREQDET_EN
) {
707 w
&= ~PLL_CTRL_FREQDET_EN
;
708 pcie_mdiowrite(pi
, MDIODATA_DEV_PLL
, SERDES_PLL_CTRL
, w
);
712 /* Fix MISC config to allow coming out of L2/L3-Ready state w/o PRST */
713 /* Needs to happen when coming out of 'standby'/'hibernate' */
715 BCMINITFN(pcie_misc_config_fixup
)(pcicore_info_t
*pi
)
717 sbpcieregs_t
*pcieregs
= pi
->regs
.pcieregs
;
718 uint16 val16
, *reg16
;
720 reg16
= &pcieregs
->sprom
[SRSH_PCIE_MISC_CONFIG
];
721 val16
= R_REG(pi
->osh
, reg16
);
723 if ((val16
& SRSH_L23READY_EXIT_NOPERST
) == 0) {
724 val16
|= SRSH_L23READY_EXIT_NOPERST
;
725 W_REG(pi
->osh
, reg16
, val16
);
729 /* quick hack for testing */
730 /* Needs to happen when coming out of 'standby'/'hibernate' */
732 pcie_war_noplldown(pcicore_info_t
*pi
)
734 sbpcieregs_t
*pcieregs
= pi
->regs
.pcieregs
;
737 ASSERT(pi
->sih
->buscorerev
== 7);
739 /* turn off serdes PLL down */
740 si_corereg(pi
->sih
, SI_CC_IDX
, OFFSETOF(chipcregs_t
, chipcontrol
),
741 CHIPCTRL_4321_PLL_DOWN
, CHIPCTRL_4321_PLL_DOWN
);
743 /* clear srom shadow backdoor */
744 reg16
= &pcieregs
->sprom
[SRSH_BD_OFFSET
];
745 W_REG(pi
->osh
, reg16
, 0);
748 /* Needs to happen when coming out of 'standby'/'hibernate' */
750 pcie_war_pci_setup(pcicore_info_t
*pi
)
753 sbpcieregs_t
*pcieregs
= pi
->regs
.pcieregs
;
756 if ((sih
->buscorerev
== 0) || (sih
->buscorerev
== 1)) {
757 w
= pcie_readreg(sih
, pcieregs
, PCIE_PCIEREGS
, PCIE_TLP_WORKAROUNDSREG
);
759 pcie_writereg(sih
, pcieregs
, PCIE_PCIEREGS
, PCIE_TLP_WORKAROUNDSREG
, w
);
762 if (sih
->buscorerev
== 1) {
763 w
= pcie_readreg(sih
, pcieregs
, PCIE_PCIEREGS
, PCIE_DLLP_LCREG
);
765 pcie_writereg(sih
, pcieregs
, PCIE_PCIEREGS
, PCIE_DLLP_LCREG
, w
);
768 if (sih
->buscorerev
== 0) {
769 pcie_mdiowrite(pi
, MDIODATA_DEV_RX
, SERDES_RX_TIMER1
, 0x8128);
770 pcie_mdiowrite(pi
, MDIODATA_DEV_RX
, SERDES_RX_CDR
, 0x0100);
771 pcie_mdiowrite(pi
, MDIODATA_DEV_RX
, SERDES_RX_CDRBW
, 0x1466);
772 } else if (PCIEGEN1_ASPM(sih
)) {
773 /* Change the L1 threshold for better performance */
774 w
= pcie_readreg(sih
, pcieregs
, PCIE_PCIEREGS
, PCIE_DLLP_PMTHRESHREG
);
775 w
&= ~(PCIE_L1THRESHOLDTIME_MASK
);
776 w
|= (PCIE_L1THRESHOLD_WARVAL
<< PCIE_L1THRESHOLDTIME_SHIFT
);
777 pcie_writereg(sih
, pcieregs
, PCIE_PCIEREGS
, PCIE_DLLP_PMTHRESHREG
, w
);
781 pcie_war_aspm_clkreq(pi
);
782 } else if (pi
->sih
->buscorerev
== 7)
783 pcie_war_noplldown(pi
);
785 /* Note that the fix is actually in the SROM, that's why this is open-ended */
786 if (pi
->sih
->buscorerev
>= 6)
787 pcie_misc_config_fixup(pi
);
791 pcie_war_ovr_aspm_update(void *pch
, uint8 aspm
)
793 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
795 if (!PCIE_GEN1(pi
->sih
))
798 if (!PCIEGEN1_ASPM(pi
->sih
))
802 if (aspm
> PCIE_ASPM_ENAB
)
805 pi
->pcie_war_aspm_ovr
= aspm
;
807 /* Update the current state */
808 pcie_war_aspm_clkreq(pi
);
813 pcie_power_save_enable(void *pch
, bool enable
)
815 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
821 pi
->pcie_power_save
= enable
;
825 pcie_power_save_upd(pcicore_info_t
*pi
, bool up
)
829 if (!pi
->pcie_power_save
)
833 if ((sih
->buscorerev
>= 15) && (sih
->buscorerev
<= 20)) {
835 pcicore_pcieserdesreg(pi
, MDIO_DEV_BLK1
, BLK1_PWR_MGMT1
, 1, 0x7F64);
838 pcicore_pcieserdesreg(pi
, MDIO_DEV_BLK1
, BLK1_PWR_MGMT3
, 1, 0x74);
840 pcicore_pcieserdesreg(pi
, MDIO_DEV_BLK1
, BLK1_PWR_MGMT3
, 1, 0x7C);
842 } else if ((sih
->buscorerev
>= 21) && (sih
->buscorerev
<= 22)) {
844 pcicore_pcieserdesreg(pi
, MDIO_DEV_BLK1
, BLK1_PWR_MGMT1
, 1, 0x7E65);
847 pcicore_pcieserdesreg(pi
, MDIO_DEV_BLK1
, BLK1_PWR_MGMT3
, 1, 0x175);
849 pcicore_pcieserdesreg(pi
, MDIO_DEV_BLK1
, BLK1_PWR_MGMT3
, 1, 0x17D);
854 pcie_set_request_size(void *pch
, uint16 size
)
856 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
865 pi
->pcie_reqsize
= PCIE_CAP_DEVCTRL_MRRS_128B
;
866 else if (size
== 256)
867 pi
->pcie_reqsize
= PCIE_CAP_DEVCTRL_MRRS_256B
;
868 else if (size
== 512)
869 pi
->pcie_reqsize
= PCIE_CAP_DEVCTRL_MRRS_512B
;
870 else if (size
== 1024)
871 pi
->pcie_reqsize
= PCIE_CAP_DEVCTRL_MRRS_1024B
;
875 if (PCIE_GEN1(sih
)) {
876 if (pi
->sih
->buscorerev
== 18 || pi
->sih
->buscorerev
== 19)
877 pcie_devcontrol_mrrs(pi
, PCIE_CAP_DEVCTRL_MRRS_MASK
,
878 (uint32
)pi
->pcie_reqsize
);
880 else if (PCIE_GEN2(sih
)) {
881 pcie_devcontrol_mrrs(pi
, PCIE_CAP_DEVCTRL_MRRS_MASK
, (uint32
)pi
->pcie_reqsize
);
888 pcie_get_request_size(void *pch
)
890 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
895 if (pi
->pcie_reqsize
== PCIE_CAP_DEVCTRL_MRRS_128B
)
897 else if (pi
->pcie_reqsize
== PCIE_CAP_DEVCTRL_MRRS_256B
)
899 else if (pi
->pcie_reqsize
== PCIE_CAP_DEVCTRL_MRRS_512B
)
905 pcie_set_maxpayload_size(void *pch
, uint16 size
)
907 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
913 pi
->pcie_mps
= PCIE_CAP_DEVCTRL_MPS_128B
;
914 else if (size
== 256)
915 pi
->pcie_mps
= PCIE_CAP_DEVCTRL_MPS_256B
;
916 else if (size
== 512)
917 pi
->pcie_mps
= PCIE_CAP_DEVCTRL_MPS_512B
;
918 else if (size
== 1024)
919 pi
->pcie_mps
= PCIE_CAP_DEVCTRL_MPS_1024B
;
923 pcie_devcontrol_mps(pi
, PCIE_CAP_DEVCTRL_MPS_MASK
, (uint32
)pi
->pcie_mps
);
927 pcie_get_maxpayload_size(void *pch
)
929 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
934 if (pi
->pcie_mps
== PCIE_CAP_DEVCTRL_MPS_128B
)
936 else if (pi
->pcie_mps
== PCIE_CAP_DEVCTRL_MPS_256B
)
938 else if (pi
->pcie_mps
== PCIE_CAP_DEVCTRL_MPS_512B
)
940 else if (pi
->pcie_mps
== PCIE_CAP_DEVCTRL_MPS_1024B
)
946 pcie_disable_TL_clk_gating(void *pch
)
948 /* disable TL clk gating is located in bit 4 of PCIEControl (Offset 0x000) */
949 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
952 if (!PCIE_GEN1(sih
) && !PCIE_GEN2(sih
))
955 si_corereg(sih
, sih
->buscoreidx
, 0, 0x10, 0x10);
959 pcie_set_L1_entry_time(void *pch
, uint32 val
)
961 /* L1 entry time is located in bits [22:16] of register 0x1004 (pdl_control_1) */
962 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
964 sbpcieregs_t
*pcieregs
= pi
->regs
.pcieregs
;
967 if (!PCIE_GEN1(sih
) && !PCIE_GEN2(sih
))
973 data
= pcie_readreg(sih
, pcieregs
, PCIE_CONFIGREGS
, 0x1004);
974 pcie_writereg(pch
, pcieregs
, PCIE_CONFIGREGS
, 0x1004, (data
& ~0x7F0000) | (val
<< 16));
977 /* mode : 0 -- reset, 1 -- tx, 2 -- rx */
979 pcie_set_error_injection(void *pch
, uint32 mode
)
981 /* through reg_phy_ctl_7 - 0x181c */
982 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
984 sbpcieregs_t
*pcieregs
= pi
->regs
.pcieregs
;
986 if (!PCIE_GEN1(sih
) && !PCIE_GEN2(sih
))
990 pcie_writereg(pch
, pcieregs
, PCIE_CONFIGREGS
, 0x181c, 0);
992 pcie_writereg(pch
, pcieregs
, PCIE_CONFIGREGS
, 0x181c, 0x14031);
994 pcie_writereg(pch
, pcieregs
, PCIE_CONFIGREGS
, 0x181c, 0x2c031);
997 /* ***** Functions called during driver state changes ***** */
999 BCMATTACHFN(pcicore_attach
)(void *pch
, char *pvars
, int state
)
1001 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
1002 si_t
*sih
= pi
->sih
;
1004 if (!PCIE_GEN1(sih
)) {
1005 if ((BCM4360_CHIP_ID
== CHIPID(sih
->chip
)) ||
1006 (BCM43460_CHIP_ID
== CHIPID(sih
->chip
)) ||
1007 (BCM4352_CHIP_ID
== CHIPID(sih
->chip
)))
1008 pi
->pcie_reqsize
= PCIE_CAP_DEVCTRL_MRRS_1024B
;
1012 if (PCIEGEN1_ASPM(sih
)) {
1013 if (((sih
->boardvendor
== VENDOR_APPLE
) &&
1014 ((uint8
)getintvar(pvars
, "sromrev") == 4) &&
1015 ((uint8
)getintvar(pvars
, "boardrev") <= 0x71)) ||
1016 ((uint32
)getintvar(pvars
, "boardflags2") & BFL2_PCIEWAR_OVR
)) {
1017 pi
->pcie_war_aspm_ovr
= PCIE_ASPM_DISAB
;
1019 pi
->pcie_war_aspm_ovr
= PCIE_ASPM_ENAB
;
1023 pi
->pcie_reqsize
= PCIE_CAP_DEVCTRL_MRRS_128B
;
1024 if (BCM4331_CHIP_ID
== CHIPID(sih
->chip
))
1025 pi
->pcie_reqsize
= PCIE_CAP_DEVCTRL_MRRS_512B
;
1027 bzero(pi
->pcie_configspace
, PCI_CONFIG_SPACE_SIZE
);
1029 /* These need to happen in this order only */
1030 pcie_war_polarity(pi
);
1032 pcie_war_serdes(pi
);
1034 pcie_war_aspm_clkreq(pi
);
1036 pcie_clkreq_upd(pi
, state
);
1038 /* Alter default TX drive strength setting */
1039 if (sih
->boardvendor
== VENDOR_APPLE
) {
1040 if (sih
->boardtype
== 0x8d)
1041 /* change the TX drive strength to max */
1042 pcicore_pcieserdesreg(pch
, MDIO_DEV_TXCTRL0
, 0x18, 0xff, 0x7f);
1043 else if (PCIE_DRIVE_STRENGTH_OVERRIDE(sih
))
1044 /* change the drive strength to 700mv */
1045 pcicore_pcieserdesreg(pch
, MDIO_DEV_TXCTRL0
, 0x18, 0xff, 0x70);
1050 pcicore_hwup(void *pch
)
1052 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
1054 if (!pi
|| !PCIE_GEN1(pi
->sih
))
1057 pcie_power_save_upd(pi
, TRUE
);
1059 if (pi
->sih
->boardtype
== CB2_4321_BOARD
|| pi
->sih
->boardtype
== CB2_4321_AG_BOARD
)
1060 pcicore_fixlatencytimer(pch
, 0x20);
1062 pcie_war_pci_setup(pi
);
1064 /* Alter default TX drive strength setting */
1065 if (pi
->sih
->boardvendor
== VENDOR_APPLE
) {
1066 if (pi
->sih
->boardtype
== 0x8d)
1067 /* change the TX drive strength to max */
1068 pcicore_pcieserdesreg(pch
, MDIO_DEV_TXCTRL0
, 0x18, 0xff, 0x7f);
1069 else if (BCM4331_CHIP_ID
== CHIPID(pi
->sih
->chip
))
1070 /* change the drive strength for X19b & X28 to 700mv */
1071 pcicore_pcieserdesreg(pch
, MDIO_DEV_TXCTRL0
, 0x18, 0xff, 0x70);
1076 pcicore_up(void *pch
, int state
)
1078 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
1083 if (PCIE_GEN2(pi
->sih
)) {
1084 pcie_devcontrol_mrrs(pi
, PCIE_CAP_DEVCTRL_MRRS_MASK
, pi
->pcie_reqsize
);
1088 pcie_power_save_upd(pi
, TRUE
);
1090 /* Restore L1 timer for better performance */
1091 pcie_extendL1timer(pi
, TRUE
);
1093 pcie_clkreq_upd(pi
, state
);
1095 if (pi
->sih
->buscorerev
== 18 ||
1096 (pi
->sih
->buscorerev
== 19 && !PCIE_MRRS_OVERRIDE(sih
)))
1097 pi
->pcie_reqsize
= PCIE_CAP_DEVCTRL_MRRS_128B
;
1099 pcie_devcontrol_mrrs(pi
, PCIE_CAP_DEVCTRL_MRRS_MASK
, pi
->pcie_reqsize
);
1102 /* When the device is going to enter D3 state (or the system is going to enter S3/S4 states */
1104 pcicore_sleep(void *pch
)
1106 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
1109 if (!pi
|| !PCIE_GEN1(pi
->sih
))
1112 pcie_power_save_upd(pi
, FALSE
);
1115 if (!PCIEGEN1_ASPM(pi
->sih
))
1119 w
= OSL_PCI_READ_CONFIG(pi
->osh
, pi
->pciecap_lcreg_offset
, sizeof(uint32
));
1120 w
&= ~PCIE_CAP_LCREG_ASPML1
;
1121 OSL_PCI_WRITE_CONFIG(pi
->osh
, pi
->pciecap_lcreg_offset
, sizeof(uint32
), w
);
1124 pi
->pcie_pr42767
= FALSE
;
1128 pcicore_down(void *pch
, int state
)
1130 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
1132 if (!pi
|| !PCIE_GEN1(pi
->sih
))
1135 pcie_clkreq_upd(pi
, state
);
1137 /* Reduce L1 timer for better power savings */
1138 pcie_extendL1timer(pi
, FALSE
);
1140 pcie_power_save_upd(pi
, FALSE
);
1143 /* ***** Wake-on-wireless-LAN (WOWL) support functions ***** */
1144 /* Just uses PCI config accesses to find out, when needed before sb_attach is done */
1146 pcicore_pmecap_fast(osl_t
*osh
)
1151 cap_ptr
= pcicore_find_pci_capability(osh
, PCI_CAP_POWERMGMTCAP_ID
, NULL
, NULL
);
1156 pmecap
= OSL_PCI_READ_CONFIG(osh
, cap_ptr
, sizeof(uint32
));
1158 return ((pmecap
& PME_CAP_PM_STATES
) != 0);
1161 /* return TRUE if PM capability exists in the pci config space
1162 * Uses and caches the information using core handle
1165 pcicore_pmecap(pcicore_info_t
*pi
)
1169 sbpcieregs_t
*pcieregs
= pi
->regs
.pcieregs
;
1172 if (!pi
->pmecap_offset
) {
1173 cap_ptr
= pcicore_find_pci_capability(pi
->osh
, PCI_CAP_POWERMGMTCAP_ID
, NULL
, NULL
);
1177 pi
->pmecap_offset
= cap_ptr
;
1179 reg16
= &pcieregs
->sprom
[SRSH_CLKREQ_OFFSET_REV8
];
1180 pi
->pmebits
= R_REG(pi
->osh
, reg16
);
1182 pmecap
= OSL_PCI_READ_CONFIG(pi
->osh
, pi
->pmecap_offset
, sizeof(uint32
));
1184 /* At least one state can generate PME */
1185 pi
->pmecap
= (pmecap
& PME_CAP_PM_STATES
) != 0;
1188 return (pi
->pmecap
);
1191 /* Enable PME generation */
1193 pcicore_pmeen(void *pch
)
1195 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
1198 /* if not pmecapable return */
1199 if (!pcicore_pmecap(pi
))
1202 pcie_war_pmebits(pi
);
1204 w
= OSL_PCI_READ_CONFIG(pi
->osh
, pi
->pmecap_offset
+ PME_CSR_OFFSET
, sizeof(uint32
));
1205 w
|= (PME_CSR_PME_EN
);
1206 OSL_PCI_WRITE_CONFIG(pi
->osh
, pi
->pmecap_offset
+ PME_CSR_OFFSET
, sizeof(uint32
), w
);
1210 * Return TRUE if PME status set
1213 pcicore_pmestat(void *pch
)
1215 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
1218 if (!pcicore_pmecap(pi
))
1221 w
= OSL_PCI_READ_CONFIG(pi
->osh
, pi
->pmecap_offset
+ PME_CSR_OFFSET
, sizeof(uint32
));
1223 return (w
& PME_CSR_PME_STAT
) == PME_CSR_PME_STAT
;
1227 pcicore_pmestatclr(void *pch
)
1229 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
1232 if (!pcicore_pmecap(pi
))
1235 pcie_war_pmebits(pi
);
1236 w
= OSL_PCI_READ_CONFIG(pi
->osh
, pi
->pmecap_offset
+ PME_CSR_OFFSET
, sizeof(uint32
));
1238 PCI_ERROR(("pcicore_pmestatclr PMECSR : 0x%x\n", w
));
1240 /* Writing a 1 to PMESTAT will clear it */
1241 if ((w
& PME_CSR_PME_STAT
) == PME_CSR_PME_STAT
) {
1242 OSL_PCI_WRITE_CONFIG(pi
->osh
, pi
->pmecap_offset
+ PME_CSR_OFFSET
, sizeof(uint32
),
1247 /* Disable PME generation, clear the PME status bit if set
1250 pcicore_pmeclr(void *pch
)
1252 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
1255 if (!pcicore_pmecap(pi
))
1258 pcie_war_pmebits(pi
);
1260 w
= OSL_PCI_READ_CONFIG(pi
->osh
, pi
->pmecap_offset
+ PME_CSR_OFFSET
, sizeof(uint32
));
1262 PCI_ERROR(("pcicore_pci_pmeclr PMECSR : 0x%x\n", w
));
1264 /* PMESTAT is cleared by writing 1 to it */
1265 w
&= ~(PME_CSR_PME_EN
);
1267 OSL_PCI_WRITE_CONFIG(pi
->osh
, pi
->pmecap_offset
+ PME_CSR_OFFSET
, sizeof(uint32
), w
);
1271 pcicore_fixlatencytimer(pcicore_info_t
* pch
, uint8 timer_val
)
1273 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
1278 lattim
= read_pci_cfg_byte(PCI_CFG_LATTIM
);
1281 PCI_ERROR(("%s: Modifying PCI_CFG_LATTIM from 0x%x to 0x%x\n",
1282 __FUNCTION__
, lattim
, timer_val
));
1283 write_pci_cfg_byte(PCI_CFG_LATTIM
, timer_val
);
1288 pcie_lcreg(void *pch
, uint32 mask
, uint32 val
)
1290 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
1293 offset
= pi
->pciecap_lcreg_offset
;
1299 OSL_PCI_WRITE_CONFIG(pi
->osh
, offset
, sizeof(uint32
), val
);
1301 return OSL_PCI_READ_CONFIG(pi
->osh
, offset
, sizeof(uint32
));
1306 pcicore_dump(void *pch
, struct bcmstrbuf
*b
)
1308 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
1310 bcm_bprintf(b
, "FORCEHT %d pcie_polarity 0x%x pcie_aspm_ovr 0x%x\n",
1311 pi
->sih
->pci_pr32414
, pi
->pcie_polarity
, pi
->pcie_war_aspm_ovr
);
1316 pcicore_pciereg(void *pch
, uint32 offset
, uint32 mask
, uint32 val
, uint type
)
1319 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
1320 sbpcieregs_t
*pcieregs
= pi
->regs
.pcieregs
;
1323 PCI_ERROR(("PCIEREG: 0x%x writeval 0x%x\n", offset
, val
));
1324 pcie_writereg(pi
->sih
, pcieregs
, type
, offset
, val
);
1327 /* Should not read register 0x154 */
1328 if (PCIE_GEN1(pi
->sih
) &&
1329 pi
->sih
->buscorerev
<= 5 && offset
== PCIE_DLLP_PCIE11
&& type
== PCIE_PCIEREGS
)
1332 reg_val
= pcie_readreg(pi
->sih
, pcieregs
, type
, offset
);
1333 PCI_ERROR(("PCIEREG: 0x%x readval is 0x%x\n", offset
, reg_val
));
1339 pcicore_pcieserdesreg(void *pch
, uint32 mdioslave
, uint32 offset
, uint32 mask
, uint32 val
)
1342 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
1345 pcie_mdiowrite(pi
, mdioslave
, offset
, val
);
1348 if (pcie_mdioread(pi
, mdioslave
, offset
, ®_val
))
1349 reg_val
= 0xFFFFFFFF;
1355 pcie_get_ssid(void* pch
)
1358 OSL_PCI_READ_CONFIG(((pcicore_info_t
*)pch
)->osh
, PCI_CFG_SVID
, sizeof(uint32
));
1359 return (uint16
)(ssid
>> 16);
1363 pcie_get_bar0(void* pch
)
1365 return OSL_PCI_READ_CONFIG(((pcicore_info_t
*)pch
)->osh
, PCI_CFG_BAR0
, sizeof(uint32
));
1369 pcie_configspace_cache(void* pch
)
1371 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
1373 uint32
*tmp
= (uint32
*)pi
->pcie_configspace
;
1375 while (offset
< PCI_CONFIG_SPACE_SIZE
) {
1376 *tmp
++ = OSL_PCI_READ_CONFIG(pi
->osh
, offset
, sizeof(uint32
));
1383 pcie_configspace_restore(void* pch
)
1385 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
1387 uint32
*tmp
= (uint32
*)pi
->pcie_configspace
;
1389 /* if config space was not buffered, than abort restore */
1393 while (offset
< PCI_CONFIG_SPACE_SIZE
) {
1394 OSL_PCI_WRITE_CONFIG(pi
->osh
, offset
, sizeof(uint32
), *tmp
);
1402 pcie_configspace_get(void* pch
, uint8
*buf
, uint size
)
1404 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
1405 memcpy(buf
, pi
->pcie_configspace
, size
);
1410 pcie_get_link_speed(void* pch
)
1412 pcicore_info_t
*pi
= (pcicore_info_t
*)pch
;
1413 sbpcieregs_t
*pcieregs
= pi
->regs
.pcieregs
;
1416 data
= pcie_readreg(pi
->sih
, pcieregs
, PCIE_CONFIGREGS
, 0xBC);
1417 return (data
>> 16) & 0xf;