BCM WL 6.30.102.9 (r366174)
[tomato.git] / release / src-rt / shared / nicpci.c
blobc1d72ed5db38c1a3309a3af568b16ce30ee9b2c1
1 /*
2 * Code to operate on PCI/E core, in NIC mode
3 * Implements pci_api.h
4 * Copyright (C) 2011, Broadcom Corporation. All Rights Reserved.
5 *
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.
9 *
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 $
21 #include <bcm_cfg.h>
22 #include <typedefs.h>
23 #include <bcmdefs.h>
24 #include <osl.h>
25 #include <bcmutils.h>
26 #include <siutils.h>
27 #include <hndsoc.h>
28 #include <bcmdevs.h>
29 #include <sbchipc.h>
30 #include <pci_core.h>
31 #include <pcie_core.h>
32 #include <nicpci.h>
33 #include <pcicfg.h>
35 typedef struct {
36 union {
37 sbpcieregs_t *pcieregs;
38 sbpciregs_t *pciregs;
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 */
45 bool pcie_pr42767;
46 uint8 pcie_polarity;
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 */
50 bool pcie_power_save;
51 uint16 pmebits;
52 uint16 pcie_reqsize;
53 uint16 pcie_mps;
54 uint8 pcie_configspace[PCI_CONFIG_SPACE_SIZE];
55 } pcicore_info_t;
57 /* debug/trace */
58 #ifdef BCMDBG_ERR
59 #define PCI_ERROR(args) printf args
60 #else
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,
68 uint *val);
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 { \
113 uint32 tmpval; \
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); \
117 } while (0)
119 #define write_pci_cfg_word(a, val) do { \
120 uint32 tmpval; \
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); \
124 } while (0)
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
130 * only once
132 void *
133 pcicore_init(si_t *sih, osl_t *osh, void *regs)
135 pcicore_info_t *pi;
136 uint8 cap_ptr;
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)));
143 return (NULL);
146 bzero(pi, sizeof(pcicore_info_t));
148 pi->sih = sih;
149 pi->osh = osh;
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);
154 ASSERT(cap_ptr);
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);
160 ASSERT(cap_ptr);
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 */
164 } else
165 pi->regs.pciregs = (sbpciregs_t*)regs;
167 return pi;
170 void
171 pcicore_deinit(void *pch)
173 pcicore_info_t *pi = (pcicore_info_t *)pch;
176 if (pi == NULL)
177 return;
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 */
183 uint8
184 pcicore_find_pci_capability(osl_t *osh, uint8 req_cap_id, uchar *buf, uint32 *buflen)
186 uint8 cap_id;
187 uint8 cap_ptr = 0;
188 uint32 bufsize;
189 uint8 byte_val;
191 /* check for Header type 0 */
192 byte_val = read_pci_cfg_byte(PCI_CFG_HDR);
193 if ((byte_val & 0x7f) != PCI_HEADER_NORMAL)
194 goto end;
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))
199 goto end;
201 cap_ptr = read_pci_cfg_byte(PCI_CFG_CAPPTR);
202 /* check if the capability pointer is 0x00 */
203 if (cap_ptr == 0x00)
204 goto end;
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) {
216 goto end;
218 /* found the caller requested capability */
219 if ((buf != NULL) && (buflen != NULL)) {
220 uint8 cap_data;
222 bufsize = *buflen;
223 if (!bufsize) goto end;
224 *buflen = 0;
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;
229 *buflen = bufsize;
230 while (bufsize--) {
231 *buf = read_pci_cfg_byte(cap_data);
232 cap_data++;
233 buf++;
236 end:
237 return cap_ptr;
240 /* ***** Register Access API */
241 uint
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);
248 BCM_REFERENCE(osh);
250 if ((BUSTYPE(sih->bustype) == SI_BUS) || PCIE_GEN1(sih)) {
251 switch (addrtype) {
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));
256 break;
257 case PCIE_PCIEREGS:
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));
261 break;
262 default:
263 ASSERT(0);
264 break;
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));
273 return retval;
276 uint
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);
282 BCM_REFERENCE(osh);
284 if ((BUSTYPE(sih->bustype) == SI_BUS) || PCIE_GEN1(sih)) {
285 switch (addrtype) {
286 case PCIE_CONFIGREGS:
287 W_REG(osh, (&pcieregs->configaddr), offset);
288 W_REG(osh, (&pcieregs->configdata), val);
289 break;
290 case PCIE_PCIEREGS:
291 W_REG(osh, (&pcieregs->u.pcie1.pcieindaddr), offset);
292 W_REG(osh, (&pcieregs->u.pcie1.pcieinddata), val);
293 break;
294 default:
295 ASSERT(0);
296 break;
299 else if (PCIE_GEN2(sih)) {
300 W_REG(osh, (&pcieregs->configaddr), offset);
301 W_REG(osh, (&pcieregs->configdata), val);
303 return 0;
306 static bool
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);
317 PR28829_DELAY();
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) {
321 break;
323 OSL_DELAY(1000);
324 i++;
327 if (i >= pcie_serdes_spinwait) {
328 PCI_ERROR(("pcie_mdiosetblock: timed out\n"));
329 return FALSE;
332 return TRUE;
335 static int
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));
342 else
343 return 0xFFFFFFFF;
346 static int
347 pciegen2_mdioop(pcicore_info_t *pi, uint physmedia, uint regaddr, bool write, uint *val,
348 bool slave_bypass)
350 sbpcieregs_t *pcieregs = pi->regs.pcieregs;
351 uint pcie_serdes_spinwait = 200, i = 0, mdio_ctrl;
352 uint32 *reg32;
354 if (!PCIE_GEN2(pi->sih))
355 ASSERT(0);
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);
362 if (slave_bypass)
363 mdio_ctrl |= MDIOCTL2_SLAVE_BYPASS;
365 if (!write)
366 mdio_ctrl |= MDIOCTL2_READ;
368 W_REG(pi->osh, (&pcieregs->u.pcie2.mdiocontrol), mdio_ctrl);
369 if (write) {
370 reg32 = (uint32 *)&(pcieregs->u.pcie2.mdiowrdata);
371 W_REG(pi->osh, reg32, *val);
373 else
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) {
379 if (!write)
380 *val = (R_REG(pi->osh, reg32) & MDIODATA2_MASK);
381 return 0;
383 OSL_DELAY(1000);
384 i++;
386 return 0;
389 static int
390 pciegen1_mdioop(pcicore_info_t *pi, uint physmedia, uint regaddr, bool write, uint *val)
392 sbpcieregs_t *pcieregs = pi->regs.pcieregs;
393 uint mdiodata;
394 uint i = 0;
395 uint pcie_serdes_spinwait = 10;
397 if (!PCIE_GEN1(pi->sih))
398 ASSERT(0);
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))
406 return 1;
407 mdiodata = (MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) |
408 (regaddr << MDIODATA_REGADDR_SHF);
409 pcie_serdes_spinwait *= 20;
410 } else {
411 mdiodata = (physmedia << MDIODATA_DEVADDR_SHF_OLD) |
412 (regaddr << MDIODATA_REGADDR_SHF_OLD);
415 if (!write)
416 mdiodata |= (MDIODATA_START | MDIODATA_READ | MDIODATA_TA);
417 else
418 mdiodata |= (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA | *val);
420 W_REG(pi->osh, &pcieregs->u.pcie1.mdiodata, mdiodata);
422 PR28829_DELAY();
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) {
427 if (!write) {
428 PR28829_DELAY();
429 *val = (R_REG(pi->osh, &(pcieregs->u.pcie1.mdiodata)) &
430 MDIODATA_MASK);
432 /* Disable mdio access to SERDES */
433 W_REG(pi->osh, (&pcieregs->u.pcie1.mdiocontrol), 0);
434 return 0;
436 OSL_DELAY(1000);
437 i++;
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);
443 return 1;
446 /* use the mdio interface to read from mdio slaves */
447 static int
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 */
454 static int
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 ***** */
461 static uint32
462 pcie_devcontrol_mrrs(void *pch, uint32 mask, uint32 val)
464 pcicore_info_t *pi = (pcicore_info_t *)pch;
465 uint32 reg_val;
466 uint8 offset;
468 offset = pi->pciecap_devctrl_offset;
469 if (!offset)
470 return 0;
472 reg_val = OSL_PCI_READ_CONFIG(pi->osh, offset, sizeof(uint32));
473 /* set operation */
474 if (mask) {
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));
489 return reg_val;
492 static uint32
493 pcie_devcontrol_mps(void *pch, uint32 mask, uint32 val)
495 pcicore_info_t *pi = (pcicore_info_t *)pch;
496 uint32 reg_val;
497 uint8 offset;
499 offset = pi->pciecap_devctrl_offset;
500 if (!offset)
501 return 0;
503 reg_val = OSL_PCI_READ_CONFIG(pi->osh, offset, sizeof(uint32));
504 /* set operation */
505 if (mask) {
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));
512 return reg_val;
515 uint8
516 pcie_clkreq(void *pch, uint32 mask, uint32 val)
518 pcicore_info_t *pi = (pcicore_info_t *)pch;
519 uint32 reg_val;
520 uint8 offset;
522 offset = pi->pciecap_lcreg_offset;
523 if (!offset)
524 return 0;
526 reg_val = OSL_PCI_READ_CONFIG(pi->osh, offset, sizeof(uint32));
527 /* set operation */
528 if (mask) {
529 if (val)
530 reg_val |= PCIE_CLKREQ_ENAB;
531 else
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)
537 return 1;
538 else
539 return 0;
542 static void
543 pcie_extendL1timer(pcicore_info_t *pi, bool extend)
545 uint32 w;
546 si_t *sih = pi->sih;
547 sbpcieregs_t *pcieregs = pi->regs.pcieregs;
549 if (!PCIE_GEN1(sih))
550 return;
552 w = pcie_readreg(sih, pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG);
554 if (extend && sih->buscorerev >= 7)
555 w |= PCIE_ASPMTIMER_EXTEND;
556 else
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 */
563 static void
564 pcie_clkreq_upd(pcicore_info_t *pi, uint state)
566 si_t *sih = pi->sih;
567 ASSERT(PCIE(sih));
569 if (!PCIE_GEN1(sih))
570 return;
572 switch (state) {
573 case SI_DOATTACH:
574 if (PCIEGEN1_ASPM(sih))
575 pcie_clkreq((void *)pi, 1, 0);
576 break;
577 case SI_PCIDOWN:
578 if (sih->buscorerev == 6) { /* turn on serdes PLL down */
579 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol_addr),
580 ~0, 0);
581 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol_data),
582 ~0x40, 0);
583 } else if (pi->pcie_pr42767) {
584 pcie_clkreq((void *)pi, 1, 1);
586 break;
587 case SI_PCIUP:
588 if (sih->buscorerev == 6) { /* turn off serdes PLL down */
589 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol_addr),
590 ~0, 0);
591 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol_data),
592 ~0x40, 0x40);
593 } else if (PCIEGEN1_ASPM(sih)) { /* disable clkreq */
594 pcie_clkreq((void *)pi, 1, 0);
596 break;
597 default:
598 ASSERT(0);
599 break;
603 /* ***** PCI core WARs ***** */
604 /* Done only once at attach time */
605 static void
606 pcie_war_polarity(pcicore_info_t *pi)
608 uint32 w;
610 if (pi->pcie_polarity != 0)
611 return;
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);
620 else
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
629 static void
630 pcie_war_aspm_clkreq(pcicore_info_t *pi)
632 sbpcieregs_t *pcieregs = pi->regs.pcieregs;
633 si_t *sih = pi->sih;
634 uint16 val16, *reg16;
635 uint32 w;
637 if (!PCIEGEN1_ASPM(sih))
638 return;
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;
668 } else
669 val16 &= ~SRSH_CLKREQ_ENB;
671 W_REG(pi->osh, reg16, val16);
674 static void
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)
681 return;
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' */
697 static void
698 pcie_war_serdes(pcicore_info_t *pi)
700 uint32 w = 0;
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' */
714 static void
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' */
731 static void
732 pcie_war_noplldown(pcicore_info_t *pi)
734 sbpcieregs_t *pcieregs = pi->regs.pcieregs;
735 uint16 *reg16;
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' */
749 static void
750 pcie_war_pci_setup(pcicore_info_t *pi)
752 si_t *sih = pi->sih;
753 sbpcieregs_t *pcieregs = pi->regs.pcieregs;
754 uint32 w;
756 if ((sih->buscorerev == 0) || (sih->buscorerev == 1)) {
757 w = pcie_readreg(sih, pcieregs, PCIE_PCIEREGS, PCIE_TLP_WORKAROUNDSREG);
758 w |= 0x8;
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);
764 w |= (0x40);
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);
779 pcie_war_serdes(pi);
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);
790 void
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))
796 return;
798 if (!PCIEGEN1_ASPM(pi->sih))
799 return;
801 /* Validate */
802 if (aspm > PCIE_ASPM_ENAB)
803 return;
805 pi->pcie_war_aspm_ovr = aspm;
807 /* Update the current state */
808 pcie_war_aspm_clkreq(pi);
812 void
813 pcie_power_save_enable(void *pch, bool enable)
815 pcicore_info_t *pi = (pcicore_info_t *)pch;
818 if (!pi)
819 return;
821 pi->pcie_power_save = enable;
824 static void
825 pcie_power_save_upd(pcicore_info_t *pi, bool up)
827 si_t *sih = pi->sih;
829 if (!pi->pcie_power_save)
830 return;
833 if ((sih->buscorerev >= 15) && (sih->buscorerev <= 20)) {
835 pcicore_pcieserdesreg(pi, MDIO_DEV_BLK1, BLK1_PWR_MGMT1, 1, 0x7F64);
837 if (up)
838 pcicore_pcieserdesreg(pi, MDIO_DEV_BLK1, BLK1_PWR_MGMT3, 1, 0x74);
839 else
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);
846 if (up)
847 pcicore_pcieserdesreg(pi, MDIO_DEV_BLK1, BLK1_PWR_MGMT3, 1, 0x175);
848 else
849 pcicore_pcieserdesreg(pi, MDIO_DEV_BLK1, BLK1_PWR_MGMT3, 1, 0x17D);
853 void
854 pcie_set_request_size(void *pch, uint16 size)
856 pcicore_info_t *pi = (pcicore_info_t *)pch;
857 si_t *sih;
859 if (!pi)
860 return;
862 sih = pi->sih;
864 if (size == 128)
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;
872 else
873 return;
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);
883 else
884 ASSERT(0);
887 uint16
888 pcie_get_request_size(void *pch)
890 pcicore_info_t *pi = (pcicore_info_t *)pch;
892 if (!pi)
893 return (0);
895 if (pi->pcie_reqsize == PCIE_CAP_DEVCTRL_MRRS_128B)
896 return (128);
897 else if (pi->pcie_reqsize == PCIE_CAP_DEVCTRL_MRRS_256B)
898 return (256);
899 else if (pi->pcie_reqsize == PCIE_CAP_DEVCTRL_MRRS_512B)
900 return (512);
901 return (0);
904 void
905 pcie_set_maxpayload_size(void *pch, uint16 size)
907 pcicore_info_t *pi = (pcicore_info_t *)pch;
909 if (!pi)
910 return;
912 if (size == 128)
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;
920 else
921 return;
923 pcie_devcontrol_mps(pi, PCIE_CAP_DEVCTRL_MPS_MASK, (uint32)pi->pcie_mps);
926 uint16
927 pcie_get_maxpayload_size(void *pch)
929 pcicore_info_t *pi = (pcicore_info_t *)pch;
931 if (!pi)
932 return (0);
934 if (pi->pcie_mps == PCIE_CAP_DEVCTRL_MPS_128B)
935 return (128);
936 else if (pi->pcie_mps == PCIE_CAP_DEVCTRL_MPS_256B)
937 return (256);
938 else if (pi->pcie_mps == PCIE_CAP_DEVCTRL_MPS_512B)
939 return (512);
940 else if (pi->pcie_mps == PCIE_CAP_DEVCTRL_MPS_1024B)
941 return (1024);
942 return (0);
945 void
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;
950 si_t *sih = pi->sih;
952 if (!PCIE_GEN1(sih) && !PCIE_GEN2(sih))
953 return;
955 si_corereg(sih, sih->buscoreidx, 0, 0x10, 0x10);
958 void
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;
963 si_t *sih = pi->sih;
964 sbpcieregs_t *pcieregs = pi->regs.pcieregs;
965 uint32 data;
967 if (!PCIE_GEN1(sih) && !PCIE_GEN2(sih))
968 return;
970 if (val > 0x7F)
971 return;
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 */
978 void
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;
983 si_t *sih = pi->sih;
984 sbpcieregs_t *pcieregs = pi->regs.pcieregs;
986 if (!PCIE_GEN1(sih) && !PCIE_GEN2(sih))
987 return;
989 if (mode == 0)
990 pcie_writereg(pch, pcieregs, PCIE_CONFIGREGS, 0x181c, 0);
991 else if (mode == 1)
992 pcie_writereg(pch, pcieregs, PCIE_CONFIGREGS, 0x181c, 0x14031);
993 else
994 pcie_writereg(pch, pcieregs, PCIE_CONFIGREGS, 0x181c, 0x2c031);
997 /* ***** Functions called during driver state changes ***** */
998 void
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;
1009 return;
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;
1018 } else {
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);
1049 void
1050 pcicore_hwup(void *pch)
1052 pcicore_info_t *pi = (pcicore_info_t *)pch;
1054 if (!pi || !PCIE_GEN1(pi->sih))
1055 return;
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);
1075 void
1076 pcicore_up(void *pch, int state)
1078 pcicore_info_t *pi = (pcicore_info_t *)pch;
1080 if (!pi)
1081 return;
1083 if (PCIE_GEN2(pi->sih)) {
1084 pcie_devcontrol_mrrs(pi, PCIE_CAP_DEVCTRL_MRRS_MASK, pi->pcie_reqsize);
1085 return;
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 */
1103 void
1104 pcicore_sleep(void *pch)
1106 pcicore_info_t *pi = (pcicore_info_t *)pch;
1107 uint32 w;
1109 if (!pi || !PCIE_GEN1(pi->sih))
1110 return;
1112 pcie_power_save_upd(pi, FALSE);
1115 if (!PCIEGEN1_ASPM(pi->sih))
1116 return;
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;
1127 void
1128 pcicore_down(void *pch, int state)
1130 pcicore_info_t *pi = (pcicore_info_t *)pch;
1132 if (!pi || !PCIE_GEN1(pi->sih))
1133 return;
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 */
1145 bool
1146 pcicore_pmecap_fast(osl_t *osh)
1148 uint8 cap_ptr;
1149 uint32 pmecap;
1151 cap_ptr = pcicore_find_pci_capability(osh, PCI_CAP_POWERMGMTCAP_ID, NULL, NULL);
1153 if (!cap_ptr)
1154 return FALSE;
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
1164 static bool
1165 pcicore_pmecap(pcicore_info_t *pi)
1167 uint8 cap_ptr;
1168 uint32 pmecap;
1169 sbpcieregs_t *pcieregs = pi->regs.pcieregs;
1170 uint16*reg16;
1172 if (!pi->pmecap_offset) {
1173 cap_ptr = pcicore_find_pci_capability(pi->osh, PCI_CAP_POWERMGMTCAP_ID, NULL, NULL);
1174 if (!cap_ptr)
1175 return FALSE;
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 */
1192 void
1193 pcicore_pmeen(void *pch)
1195 pcicore_info_t *pi = (pcicore_info_t *)pch;
1196 uint32 w;
1198 /* if not pmecapable return */
1199 if (!pcicore_pmecap(pi))
1200 return;
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
1212 bool
1213 pcicore_pmestat(void *pch)
1215 pcicore_info_t *pi = (pcicore_info_t *)pch;
1216 uint32 w;
1218 if (!pcicore_pmecap(pi))
1219 return FALSE;
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;
1226 void
1227 pcicore_pmestatclr(void *pch)
1229 pcicore_info_t *pi = (pcicore_info_t *)pch;
1230 uint32 w;
1232 if (!pcicore_pmecap(pi))
1233 return;
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
1249 void
1250 pcicore_pmeclr(void *pch)
1252 pcicore_info_t *pi = (pcicore_info_t *)pch;
1253 uint32 w;
1255 if (!pcicore_pmecap(pi))
1256 return;
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);
1270 static void
1271 pcicore_fixlatencytimer(pcicore_info_t* pch, uint8 timer_val)
1273 pcicore_info_t *pi = (pcicore_info_t *)pch;
1274 osl_t *osh;
1275 uint8 lattim;
1277 osh = pi->osh;
1278 lattim = read_pci_cfg_byte(PCI_CFG_LATTIM);
1280 if (!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);
1287 uint32
1288 pcie_lcreg(void *pch, uint32 mask, uint32 val)
1290 pcicore_info_t *pi = (pcicore_info_t *)pch;
1291 uint8 offset;
1293 offset = pi->pciecap_lcreg_offset;
1294 if (!offset)
1295 return 0;
1297 /* set operation */
1298 if (mask)
1299 OSL_PCI_WRITE_CONFIG(pi->osh, offset, sizeof(uint32), val);
1301 return OSL_PCI_READ_CONFIG(pi->osh, offset, sizeof(uint32));
1304 #ifdef BCMDBG
1305 void
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);
1313 #endif /* BCMDBG */
1315 uint32
1316 pcicore_pciereg(void *pch, uint32 offset, uint32 mask, uint32 val, uint type)
1318 uint32 reg_val = 0;
1319 pcicore_info_t *pi = (pcicore_info_t *)pch;
1320 sbpcieregs_t *pcieregs = pi->regs.pcieregs;
1322 if (mask) {
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)
1330 return reg_val;
1332 reg_val = pcie_readreg(pi->sih, pcieregs, type, offset);
1333 PCI_ERROR(("PCIEREG: 0x%x readval is 0x%x\n", offset, reg_val));
1335 return reg_val;
1338 uint32
1339 pcicore_pcieserdesreg(void *pch, uint32 mdioslave, uint32 offset, uint32 mask, uint32 val)
1341 uint32 reg_val = 0;
1342 pcicore_info_t *pi = (pcicore_info_t *)pch;
1344 if (mask) {
1345 pcie_mdiowrite(pi, mdioslave, offset, val);
1348 if (pcie_mdioread(pi, mdioslave, offset, &reg_val))
1349 reg_val = 0xFFFFFFFF;
1351 return reg_val;
1354 uint16
1355 pcie_get_ssid(void* pch)
1357 uint32 ssid =
1358 OSL_PCI_READ_CONFIG(((pcicore_info_t *)pch)->osh, PCI_CFG_SVID, sizeof(uint32));
1359 return (uint16)(ssid >> 16);
1362 uint32
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;
1372 uint offset = 0;
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));
1377 offset += 4;
1379 return 0;
1383 pcie_configspace_restore(void* pch)
1385 pcicore_info_t *pi = (pcicore_info_t *)pch;
1386 uint offset = 0;
1387 uint32 *tmp = (uint32 *)pi->pcie_configspace;
1389 /* if config space was not buffered, than abort restore */
1390 if (*tmp == 0)
1391 return -1;
1393 while (offset < PCI_CONFIG_SPACE_SIZE) {
1394 OSL_PCI_WRITE_CONFIG(pi->osh, offset, sizeof(uint32), *tmp);
1395 tmp++;
1396 offset += 4;
1398 return 0;
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);
1406 return 0;
1409 uint32
1410 pcie_get_link_speed(void* pch)
1412 pcicore_info_t *pi = (pcicore_info_t *)pch;
1413 sbpcieregs_t *pcieregs = pi->regs.pcieregs;
1414 uint32 data;
1416 data = pcie_readreg(pi->sih, pcieregs, PCIE_CONFIGREGS, 0xBC);
1417 return (data >> 16) & 0xf;