2 * Copyright (c) 2010 Broadcom Corporation
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.
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.
17 #include <linux/delay.h>
18 #include <linux/string.h>
19 #include <linux/pci.h>
28 #include <pcie_core.h>
34 sbpcieregs_t
*pcieregs
;
35 struct sbpciregs
*pciregs
;
36 } regs
; /* Memory mapped register to the core */
38 si_t
*sih
; /* System interconnect handle */
40 struct osl_info
*osh
; /* OSL handle */
41 u8 pciecap_lcreg_offset
; /* PCIE capability LCreg offset in the config space */
44 u8 pcie_war_aspm_ovr
; /* Override ASPM/Clkreq settings */
46 u8 pmecap_offset
; /* PM Capability offset in the config space */
47 bool pmecap
; /* Capable of generating PME */
51 #define PCI_ERROR(args)
52 #define PCIE_PUB(sih) \
53 (((sih)->bustype == PCI_BUS) && ((sih)->buscoretype == PCIE_CORE_ID))
55 /* routines to access mdio slave device registers */
56 static bool pcie_mdiosetblock(pcicore_info_t
*pi
, uint blk
);
57 static int pcie_mdioop(pcicore_info_t
*pi
, uint physmedia
, uint regaddr
,
58 bool write
, uint
*val
);
59 static int pcie_mdiowrite(pcicore_info_t
*pi
, uint physmedia
, uint readdr
,
61 static int pcie_mdioread(pcicore_info_t
*pi
, uint physmedia
, uint readdr
,
64 static void pcie_extendL1timer(pcicore_info_t
*pi
, bool extend
);
65 static void pcie_clkreq_upd(pcicore_info_t
*pi
, uint state
);
67 static void pcie_war_aspm_clkreq(pcicore_info_t
*pi
);
68 static void pcie_war_serdes(pcicore_info_t
*pi
);
69 static void pcie_war_noplldown(pcicore_info_t
*pi
);
70 static void pcie_war_polarity(pcicore_info_t
*pi
);
71 static void pcie_war_pci_setup(pcicore_info_t
*pi
);
73 static bool pcicore_pmecap(pcicore_info_t
*pi
);
75 #define PCIE_ASPM(sih) ((PCIE_PUB(sih)) && (((sih)->buscorerev >= 3) && ((sih)->buscorerev <= 5)))
78 /* delay needed between the mdio control/ mdiodata register data access */
79 #define PR28829_DELAY() udelay(10)
81 /* Initialize the PCI core. It's caller's responsibility to make sure that this is done
84 void *pcicore_init(si_t
*sih
, struct osl_info
*osh
, void *regs
)
88 ASSERT(sih
->bustype
== PCI_BUS
);
90 /* alloc pcicore_info_t */
91 pi
= kzalloc(sizeof(pcicore_info_t
), GFP_ATOMIC
);
93 PCI_ERROR(("pci_attach: malloc failed!\n"));
101 if (sih
->buscoretype
== PCIE_CORE_ID
) {
103 pi
->regs
.pcieregs
= (sbpcieregs_t
*) regs
;
105 pcicore_find_pci_capability(pi
->dev
, PCI_CAP_PCIECAP_ID
,
108 pi
->pciecap_lcreg_offset
= cap_ptr
+ PCIE_CAP_LINKCTRL_OFFSET
;
110 pi
->regs
.pciregs
= (struct sbpciregs
*) regs
;
115 void pcicore_deinit(void *pch
)
117 pcicore_info_t
*pi
= (pcicore_info_t
*) pch
;
124 /* return cap_offset if requested capability exists in the PCI config space */
125 /* Note that it's caller's responsibility to make sure it's a pci bus */
127 pcicore_find_pci_capability(void *dev
, u8 req_cap_id
,
128 unsigned char *buf
, u32
*buflen
)
135 /* check for Header type 0 */
136 pci_read_config_byte(dev
, PCI_CFG_HDR
, &byte_val
);
137 if ((byte_val
& 0x7f) != PCI_HEADER_NORMAL
)
140 /* check if the capability pointer field exists */
141 pci_read_config_byte(dev
, PCI_CFG_STAT
, &byte_val
);
142 if (!(byte_val
& PCI_CAPPTR_PRESENT
))
145 pci_read_config_byte(dev
, PCI_CFG_CAPPTR
, &cap_ptr
);
146 /* check if the capability pointer is 0x00 */
150 /* loop thr'u the capability list and see if the pcie capabilty exists */
152 pci_read_config_byte(dev
, cap_ptr
, &cap_id
);
154 while (cap_id
!= req_cap_id
) {
155 pci_read_config_byte(dev
, cap_ptr
+ 1, &cap_ptr
);
158 pci_read_config_byte(dev
, cap_ptr
, &cap_id
);
160 if (cap_id
!= req_cap_id
) {
163 /* found the caller requested capability */
164 if ((buf
!= NULL
) && (buflen
!= NULL
)) {
171 /* copy the cpability data excluding cap ID and next ptr */
172 cap_data
= cap_ptr
+ 2;
173 if ((bufsize
+ cap_data
) > SZPCR
)
174 bufsize
= SZPCR
- cap_data
;
177 pci_read_config_byte(dev
, cap_data
, buf
);
186 /* ***** Register Access API */
188 pcie_readreg(struct osl_info
*osh
, sbpcieregs_t
*pcieregs
, uint addrtype
,
191 uint retval
= 0xFFFFFFFF;
193 ASSERT(pcieregs
!= NULL
);
196 case PCIE_CONFIGREGS
:
197 W_REG((&pcieregs
->configaddr
), offset
);
198 (void)R_REG((&pcieregs
->configaddr
));
199 retval
= R_REG(&(pcieregs
->configdata
));
202 W_REG(&(pcieregs
->pcieindaddr
), offset
);
203 (void)R_REG((&pcieregs
->pcieindaddr
));
204 retval
= R_REG(&(pcieregs
->pcieinddata
));
215 pcie_writereg(struct osl_info
*osh
, sbpcieregs_t
*pcieregs
, uint addrtype
,
216 uint offset
, uint val
)
218 ASSERT(pcieregs
!= NULL
);
221 case PCIE_CONFIGREGS
:
222 W_REG((&pcieregs
->configaddr
), offset
);
223 W_REG((&pcieregs
->configdata
), val
);
226 W_REG((&pcieregs
->pcieindaddr
), offset
);
227 W_REG((&pcieregs
->pcieinddata
), val
);
236 static bool pcie_mdiosetblock(pcicore_info_t
*pi
, uint blk
)
238 sbpcieregs_t
*pcieregs
= pi
->regs
.pcieregs
;
239 uint mdiodata
, i
= 0;
240 uint pcie_serdes_spinwait
= 200;
243 MDIODATA_START
| MDIODATA_WRITE
| (MDIODATA_DEV_ADDR
<<
244 MDIODATA_DEVADDR_SHF
) |
245 (MDIODATA_BLK_ADDR
<< MDIODATA_REGADDR_SHF
) | MDIODATA_TA
| (blk
<<
247 W_REG(&pcieregs
->mdiodata
, mdiodata
);
250 /* retry till the transaction is complete */
251 while (i
< pcie_serdes_spinwait
) {
252 if (R_REG(&(pcieregs
->mdiocontrol
)) &
253 MDIOCTL_ACCESS_DONE
) {
260 if (i
>= pcie_serdes_spinwait
) {
261 PCI_ERROR(("pcie_mdiosetblock: timed out\n"));
269 pcie_mdioop(pcicore_info_t
*pi
, uint physmedia
, uint regaddr
, bool write
,
272 sbpcieregs_t
*pcieregs
= pi
->regs
.pcieregs
;
275 uint pcie_serdes_spinwait
= 10;
277 /* enable mdio access to SERDES */
278 W_REG((&pcieregs
->mdiocontrol
),
279 MDIOCTL_PREAM_EN
| MDIOCTL_DIVISOR_VAL
);
281 if (pi
->sih
->buscorerev
>= 10) {
282 /* new serdes is slower in rw, using two layers of reg address mapping */
283 if (!pcie_mdiosetblock(pi
, physmedia
))
285 mdiodata
= (MDIODATA_DEV_ADDR
<< MDIODATA_DEVADDR_SHF
) |
286 (regaddr
<< MDIODATA_REGADDR_SHF
);
287 pcie_serdes_spinwait
*= 20;
289 mdiodata
= (physmedia
<< MDIODATA_DEVADDR_SHF_OLD
) |
290 (regaddr
<< MDIODATA_REGADDR_SHF_OLD
);
294 mdiodata
|= (MDIODATA_START
| MDIODATA_READ
| MDIODATA_TA
);
297 (MDIODATA_START
| MDIODATA_WRITE
| MDIODATA_TA
| *val
);
299 W_REG(&pcieregs
->mdiodata
, mdiodata
);
303 /* retry till the transaction is complete */
304 while (i
< pcie_serdes_spinwait
) {
305 if (R_REG(&(pcieregs
->mdiocontrol
)) &
306 MDIOCTL_ACCESS_DONE
) {
310 (R_REG(&(pcieregs
->mdiodata
)) &
313 /* Disable mdio access to SERDES */
314 W_REG((&pcieregs
->mdiocontrol
), 0);
321 PCI_ERROR(("pcie_mdioop: timed out op: %d\n", write
));
322 /* Disable mdio access to SERDES */
323 W_REG((&pcieregs
->mdiocontrol
), 0);
327 /* use the mdio interface to read from mdio slaves */
329 pcie_mdioread(pcicore_info_t
*pi
, uint physmedia
, uint regaddr
, uint
*regval
)
331 return pcie_mdioop(pi
, physmedia
, regaddr
, false, regval
);
334 /* use the mdio interface to write to mdio slaves */
336 pcie_mdiowrite(pcicore_info_t
*pi
, uint physmedia
, uint regaddr
, uint val
)
338 return pcie_mdioop(pi
, physmedia
, regaddr
, true, &val
);
341 /* ***** Support functions ***** */
342 u8
pcie_clkreq(void *pch
, u32 mask
, u32 val
)
344 pcicore_info_t
*pi
= (pcicore_info_t
*) pch
;
348 offset
= pi
->pciecap_lcreg_offset
;
352 pci_read_config_dword(pi
->dev
, offset
, ®_val
);
356 reg_val
|= PCIE_CLKREQ_ENAB
;
358 reg_val
&= ~PCIE_CLKREQ_ENAB
;
359 pci_write_config_dword(pi
->dev
, offset
, reg_val
);
360 pci_read_config_dword(pi
->dev
, offset
, ®_val
);
362 if (reg_val
& PCIE_CLKREQ_ENAB
)
368 static void pcie_extendL1timer(pcicore_info_t
*pi
, bool extend
)
372 struct osl_info
*osh
= pi
->osh
;
373 sbpcieregs_t
*pcieregs
= pi
->regs
.pcieregs
;
375 if (!PCIE_PUB(sih
) || sih
->buscorerev
< 7)
378 w
= pcie_readreg(osh
, pcieregs
, PCIE_PCIEREGS
, PCIE_DLLP_PMTHRESHREG
);
380 w
|= PCIE_ASPMTIMER_EXTEND
;
382 w
&= ~PCIE_ASPMTIMER_EXTEND
;
383 pcie_writereg(osh
, pcieregs
, PCIE_PCIEREGS
, PCIE_DLLP_PMTHRESHREG
, w
);
384 w
= pcie_readreg(osh
, pcieregs
, PCIE_PCIEREGS
, PCIE_DLLP_PMTHRESHREG
);
387 /* centralized clkreq control policy */
388 static void pcie_clkreq_upd(pcicore_info_t
*pi
, uint state
)
391 ASSERT(PCIE_PUB(sih
));
396 pcie_clkreq((void *)pi
, 1, 0);
399 if (sih
->buscorerev
== 6) { /* turn on serdes PLL down */
400 si_corereg(sih
, SI_CC_IDX
,
401 offsetof(chipcregs_t
, chipcontrol_addr
), ~0,
403 si_corereg(sih
, SI_CC_IDX
,
404 offsetof(chipcregs_t
, chipcontrol_data
),
406 } else if (pi
->pcie_pr42767
) {
407 pcie_clkreq((void *)pi
, 1, 1);
411 if (sih
->buscorerev
== 6) { /* turn off serdes PLL down */
412 si_corereg(sih
, SI_CC_IDX
,
413 offsetof(chipcregs_t
, chipcontrol_addr
), ~0,
415 si_corereg(sih
, SI_CC_IDX
,
416 offsetof(chipcregs_t
, chipcontrol_data
),
418 } else if (PCIE_ASPM(sih
)) { /* disable clkreq */
419 pcie_clkreq((void *)pi
, 1, 0);
428 /* ***** PCI core WARs ***** */
429 /* Done only once at attach time */
430 static void pcie_war_polarity(pcicore_info_t
*pi
)
434 if (pi
->pcie_polarity
!= 0)
437 w
= pcie_readreg(pi
->osh
, pi
->regs
.pcieregs
, PCIE_PCIEREGS
,
440 /* Detect the current polarity at attach and force that polarity and
441 * disable changing the polarity
443 if ((w
& PCIE_PLP_POLARITYINV_STAT
) == 0)
444 pi
->pcie_polarity
= (SERDES_RX_CTRL_FORCE
);
447 (SERDES_RX_CTRL_FORCE
| SERDES_RX_CTRL_POLARITY
);
450 /* enable ASPM and CLKREQ if srom doesn't have it */
451 /* Needs to happen when update to shadow SROM is needed
452 * : Coming out of 'standby'/'hibernate'
453 * : If pcie_war_aspm_ovr state changed
455 static void pcie_war_aspm_clkreq(pcicore_info_t
*pi
)
457 sbpcieregs_t
*pcieregs
= pi
->regs
.pcieregs
;
465 /* bypass this on QT or VSIM */
466 if (!ISSIM_ENAB(sih
)) {
468 reg16
= &pcieregs
->sprom
[SRSH_ASPM_OFFSET
];
469 val16
= R_REG(reg16
);
471 val16
&= ~SRSH_ASPM_ENB
;
472 if (pi
->pcie_war_aspm_ovr
== PCIE_ASPM_ENAB
)
473 val16
|= SRSH_ASPM_ENB
;
474 else if (pi
->pcie_war_aspm_ovr
== PCIE_ASPM_L1_ENAB
)
475 val16
|= SRSH_ASPM_L1_ENB
;
476 else if (pi
->pcie_war_aspm_ovr
== PCIE_ASPM_L0s_ENAB
)
477 val16
|= SRSH_ASPM_L0s_ENB
;
481 pci_read_config_dword(pi
->dev
, pi
->pciecap_lcreg_offset
,
483 w
&= ~PCIE_ASPM_ENAB
;
484 w
|= pi
->pcie_war_aspm_ovr
;
485 pci_write_config_dword(pi
->dev
,
486 pi
->pciecap_lcreg_offset
, w
);
489 reg16
= &pcieregs
->sprom
[SRSH_CLKREQ_OFFSET_REV5
];
490 val16
= R_REG(reg16
);
492 if (pi
->pcie_war_aspm_ovr
!= PCIE_ASPM_DISAB
) {
493 val16
|= SRSH_CLKREQ_ENB
;
494 pi
->pcie_pr42767
= true;
496 val16
&= ~SRSH_CLKREQ_ENB
;
501 /* Apply the polarity determined at the start */
502 /* Needs to happen when coming out of 'standby'/'hibernate' */
503 static void pcie_war_serdes(pcicore_info_t
*pi
)
507 if (pi
->pcie_polarity
!= 0)
508 pcie_mdiowrite(pi
, MDIODATA_DEV_RX
, SERDES_RX_CTRL
,
511 pcie_mdioread(pi
, MDIODATA_DEV_PLL
, SERDES_PLL_CTRL
, &w
);
512 if (w
& PLL_CTRL_FREQDET_EN
) {
513 w
&= ~PLL_CTRL_FREQDET_EN
;
514 pcie_mdiowrite(pi
, MDIODATA_DEV_PLL
, SERDES_PLL_CTRL
, w
);
518 /* Fix MISC config to allow coming out of L2/L3-Ready state w/o PRST */
519 /* Needs to happen when coming out of 'standby'/'hibernate' */
520 static void pcie_misc_config_fixup(pcicore_info_t
*pi
)
522 sbpcieregs_t
*pcieregs
= pi
->regs
.pcieregs
;
525 reg16
= &pcieregs
->sprom
[SRSH_PCIE_MISC_CONFIG
];
526 val16
= R_REG(reg16
);
528 if ((val16
& SRSH_L23READY_EXIT_NOPERST
) == 0) {
529 val16
|= SRSH_L23READY_EXIT_NOPERST
;
534 /* quick hack for testing */
535 /* Needs to happen when coming out of 'standby'/'hibernate' */
536 static void pcie_war_noplldown(pcicore_info_t
*pi
)
538 sbpcieregs_t
*pcieregs
= pi
->regs
.pcieregs
;
541 ASSERT(pi
->sih
->buscorerev
== 7);
543 /* turn off serdes PLL down */
544 si_corereg(pi
->sih
, SI_CC_IDX
, offsetof(chipcregs_t
, chipcontrol
),
545 CHIPCTRL_4321_PLL_DOWN
, CHIPCTRL_4321_PLL_DOWN
);
547 /* clear srom shadow backdoor */
548 reg16
= &pcieregs
->sprom
[SRSH_BD_OFFSET
];
552 /* Needs to happen when coming out of 'standby'/'hibernate' */
553 static void pcie_war_pci_setup(pcicore_info_t
*pi
)
556 struct osl_info
*osh
= pi
->osh
;
557 sbpcieregs_t
*pcieregs
= pi
->regs
.pcieregs
;
560 if ((sih
->buscorerev
== 0) || (sih
->buscorerev
== 1)) {
561 w
= pcie_readreg(osh
, pcieregs
, PCIE_PCIEREGS
,
562 PCIE_TLP_WORKAROUNDSREG
);
564 pcie_writereg(osh
, pcieregs
, PCIE_PCIEREGS
,
565 PCIE_TLP_WORKAROUNDSREG
, w
);
568 if (sih
->buscorerev
== 1) {
569 w
= pcie_readreg(osh
, pcieregs
, PCIE_PCIEREGS
, PCIE_DLLP_LCREG
);
571 pcie_writereg(osh
, pcieregs
, PCIE_PCIEREGS
, PCIE_DLLP_LCREG
, w
);
574 if (sih
->buscorerev
== 0) {
575 pcie_mdiowrite(pi
, MDIODATA_DEV_RX
, SERDES_RX_TIMER1
, 0x8128);
576 pcie_mdiowrite(pi
, MDIODATA_DEV_RX
, SERDES_RX_CDR
, 0x0100);
577 pcie_mdiowrite(pi
, MDIODATA_DEV_RX
, SERDES_RX_CDRBW
, 0x1466);
578 } else if (PCIE_ASPM(sih
)) {
579 /* Change the L1 threshold for better performance */
580 w
= pcie_readreg(osh
, pcieregs
, PCIE_PCIEREGS
,
581 PCIE_DLLP_PMTHRESHREG
);
582 w
&= ~(PCIE_L1THRESHOLDTIME_MASK
);
583 w
|= (PCIE_L1THRESHOLD_WARVAL
<< PCIE_L1THRESHOLDTIME_SHIFT
);
584 pcie_writereg(osh
, pcieregs
, PCIE_PCIEREGS
,
585 PCIE_DLLP_PMTHRESHREG
, w
);
589 pcie_war_aspm_clkreq(pi
);
590 } else if (pi
->sih
->buscorerev
== 7)
591 pcie_war_noplldown(pi
);
593 /* Note that the fix is actually in the SROM, that's why this is open-ended */
594 if (pi
->sih
->buscorerev
>= 6)
595 pcie_misc_config_fixup(pi
);
598 void pcie_war_ovr_aspm_update(void *pch
, u8 aspm
)
600 pcicore_info_t
*pi
= (pcicore_info_t
*) pch
;
602 if (!PCIE_ASPM(pi
->sih
))
606 if (aspm
> PCIE_ASPM_ENAB
)
609 pi
->pcie_war_aspm_ovr
= aspm
;
611 /* Update the current state */
612 pcie_war_aspm_clkreq(pi
);
615 /* ***** Functions called during driver state changes ***** */
616 void pcicore_attach(void *pch
, char *pvars
, int state
)
618 pcicore_info_t
*pi
= (pcicore_info_t
*) pch
;
621 /* Determine if this board needs override */
622 if (PCIE_ASPM(sih
)) {
623 if ((u32
) getintvar(pvars
, "boardflags2") & BFL2_PCIEWAR_OVR
) {
624 pi
->pcie_war_aspm_ovr
= PCIE_ASPM_DISAB
;
626 pi
->pcie_war_aspm_ovr
= PCIE_ASPM_ENAB
;
630 /* These need to happen in this order only */
631 pcie_war_polarity(pi
);
635 pcie_war_aspm_clkreq(pi
);
637 pcie_clkreq_upd(pi
, state
);
641 void pcicore_hwup(void *pch
)
643 pcicore_info_t
*pi
= (pcicore_info_t
*) pch
;
645 if (!pi
|| !PCIE_PUB(pi
->sih
))
648 pcie_war_pci_setup(pi
);
651 void pcicore_up(void *pch
, int state
)
653 pcicore_info_t
*pi
= (pcicore_info_t
*) pch
;
655 if (!pi
|| !PCIE_PUB(pi
->sih
))
658 /* Restore L1 timer for better performance */
659 pcie_extendL1timer(pi
, true);
661 pcie_clkreq_upd(pi
, state
);
664 /* When the device is going to enter D3 state (or the system is going to enter S3/S4 states */
665 void pcicore_sleep(void *pch
)
667 pcicore_info_t
*pi
= (pcicore_info_t
*) pch
;
670 if (!pi
|| !PCIE_ASPM(pi
->sih
))
673 pci_read_config_dword(pi
->dev
, pi
->pciecap_lcreg_offset
, &w
);
674 w
&= ~PCIE_CAP_LCREG_ASPML1
;
675 pci_write_config_dword(pi
->dev
, pi
->pciecap_lcreg_offset
, w
);
677 pi
->pcie_pr42767
= false;
680 void pcicore_down(void *pch
, int state
)
682 pcicore_info_t
*pi
= (pcicore_info_t
*) pch
;
684 if (!pi
|| !PCIE_PUB(pi
->sih
))
687 pcie_clkreq_upd(pi
, state
);
689 /* Reduce L1 timer for better power savings */
690 pcie_extendL1timer(pi
, false);
693 /* ***** Wake-on-wireless-LAN (WOWL) support functions ***** */
694 /* Just uses PCI config accesses to find out, when needed before sb_attach is done */
695 bool pcicore_pmecap_fast(void *pch
)
697 pcicore_info_t
*pi
= (pcicore_info_t
*) pch
;
702 pcicore_find_pci_capability(pi
->dev
, PCI_CAP_POWERMGMTCAP_ID
, NULL
,
708 pci_read_config_dword(pi
->dev
, cap_ptr
, &pmecap
);
710 return (pmecap
& PME_CAP_PM_STATES
) != 0;
713 /* return true if PM capability exists in the pci config space
714 * Uses and caches the information using core handle
716 static bool pcicore_pmecap(pcicore_info_t
*pi
)
721 if (!pi
->pmecap_offset
) {
723 pcicore_find_pci_capability(pi
->dev
,
724 PCI_CAP_POWERMGMTCAP_ID
, NULL
,
729 pi
->pmecap_offset
= cap_ptr
;
731 pci_read_config_dword(pi
->dev
, pi
->pmecap_offset
,
734 /* At least one state can generate PME */
735 pi
->pmecap
= (pmecap
& PME_CAP_PM_STATES
) != 0;
741 /* Enable PME generation */
742 void pcicore_pmeen(void *pch
)
744 pcicore_info_t
*pi
= (pcicore_info_t
*) pch
;
747 /* if not pmecapable return */
748 if (!pcicore_pmecap(pi
))
751 pci_read_config_dword(pi
->dev
, pi
->pmecap_offset
+ PME_CSR_OFFSET
,
753 w
|= (PME_CSR_PME_EN
);
754 pci_write_config_dword(pi
->dev
,
755 pi
->pmecap_offset
+ PME_CSR_OFFSET
, w
);
759 * Return true if PME status set
761 bool pcicore_pmestat(void *pch
)
763 pcicore_info_t
*pi
= (pcicore_info_t
*) pch
;
766 if (!pcicore_pmecap(pi
))
769 pci_read_config_dword(pi
->dev
, pi
->pmecap_offset
+ PME_CSR_OFFSET
,
772 return (w
& PME_CSR_PME_STAT
) == PME_CSR_PME_STAT
;
775 /* Disable PME generation, clear the PME status bit if set
777 void pcicore_pmeclr(void *pch
)
779 pcicore_info_t
*pi
= (pcicore_info_t
*) pch
;
782 if (!pcicore_pmecap(pi
))
785 pci_read_config_dword(pi
->dev
, pi
->pmecap_offset
+ PME_CSR_OFFSET
,
788 PCI_ERROR(("pcicore_pci_pmeclr PMECSR : 0x%x\n", w
));
790 /* PMESTAT is cleared by writing 1 to it */
791 w
&= ~(PME_CSR_PME_EN
);
793 pci_write_config_dword(pi
->dev
,
794 pi
->pmecap_offset
+ PME_CSR_OFFSET
, w
);
797 u32
pcie_lcreg(void *pch
, u32 mask
, u32 val
)
799 pcicore_info_t
*pi
= (pcicore_info_t
*) pch
;
803 offset
= pi
->pciecap_lcreg_offset
;
809 pci_write_config_dword(pi
->dev
, offset
, val
);
811 pci_read_config_dword(pi
->dev
, offset
, &tmpval
);
816 pcicore_pciereg(void *pch
, u32 offset
, u32 mask
, u32 val
, uint type
)
819 pcicore_info_t
*pi
= (pcicore_info_t
*) pch
;
820 sbpcieregs_t
*pcieregs
= pi
->regs
.pcieregs
;
821 struct osl_info
*osh
= pi
->osh
;
824 PCI_ERROR(("PCIEREG: 0x%x writeval 0x%x\n", offset
, val
));
825 pcie_writereg(osh
, pcieregs
, type
, offset
, val
);
828 /* Should not read register 0x154 */
829 if (pi
->sih
->buscorerev
<= 5 && offset
== PCIE_DLLP_PCIE11
830 && type
== PCIE_PCIEREGS
)
833 reg_val
= pcie_readreg(osh
, pcieregs
, type
, offset
);
834 PCI_ERROR(("PCIEREG: 0x%x readval is 0x%x\n", offset
, reg_val
));
840 pcicore_pcieserdesreg(void *pch
, u32 mdioslave
, u32 offset
, u32 mask
,
844 pcicore_info_t
*pi
= (pcicore_info_t
*) pch
;
847 PCI_ERROR(("PCIEMDIOREG: 0x%x writeval 0x%x\n", offset
, val
));
848 pcie_mdiowrite(pi
, mdioslave
, offset
, val
);
851 if (pcie_mdioread(pi
, mdioslave
, offset
, ®_val
))
852 reg_val
= 0xFFFFFFFF;
853 PCI_ERROR(("PCIEMDIOREG: dev 0x%x offset 0x%x read 0x%x\n", mdioslave
,