void pcicore_up(void *pch, int state) { pcicore_info_t *pi = (pcicore_info_t *)pch; bool is_x19_x28 = FALSE; if (!pi || !PCIE(pi->sih)) return; pcie_power_save_upd(pi, TRUE); /* Restore L1 timer for better performance */ pcie_extendL1timer(pi, TRUE); pcie_clkreq_upd(pi, state); is_x19_x28 = ((pi->sih->boardvendor == VENDOR_APPLE) && ((pi->sih->boardtype == BCM94331X19) || (pi->sih->boardtype == BCM94331PCIEBT3Ax_SSID))); if (pi->sih->buscorerev == 18 || (pi->sih->buscorerev == 19 && !is_x19_x28)) pi->pcie_reqsize = PCIE_CAP_DEVCTRL_MRRS_128B; pcie_devcontrol_mrrs(pi, PCIE_CAP_DEVCTRL_MRRS_MASK, pi->pcie_reqsize); }
void pcicore_hwup(void *pch) { pcicore_info_t *pi = (pcicore_info_t *)pch; if (!pi || !PCIE(pi->sih)) return; pcie_power_save_upd(pi, TRUE); if (pi->sih->boardtype == CB2_4321_BOARD || pi->sih->boardtype == CB2_4321_AG_BOARD) pcicore_fixlatencytimer(pch, 0x20); pcie_war_pci_setup(pi); /* Alter default TX drive strength setting */ if (pi->sih->boardvendor == VENDOR_APPLE) { if (pi->sih->boardtype == 0x8d) /* change the TX drive strength to max */ pcicore_pcieserdesreg(pch, MDIO_DEV_TXCTRL0, 0x18, 0xff, 0x7f); else if (BCM4331_CHIP_ID == CHIPID(pi->sih->chip)) /* change the drive strength for X19b & X28 to 700mv */ pcicore_pcieserdesreg(pch, MDIO_DEV_TXCTRL0, 0x18, 0xff, 0x70); } }
void pcicore_down(void *pch, int state) { pcicore_info_t *pi = (pcicore_info_t *)pch; if (!pi || !PCIE(pi->sih)) return; pcie_clkreq_upd(pi, state); /* Reduce L1 timer for better power savings */ pcie_extendL1timer(pi, FALSE); }
void pcicore_up(void *pch, int state) { pcicore_info_t *pi = (pcicore_info_t *)pch; if (!pi || !PCIE(pi->sih)) return; /* Restore L1 timer for better performance */ pcie_extendL1timer(pi, TRUE); pcie_clkreq_upd(pi, state); }
void pcicore_hwup(void *pch) { pcicore_info_t *pi = (pcicore_info_t *)pch; if (!pi || !PCIE(pi->sih)) return; if (pi->sih->boardtype == CB2_4321_BOARD || pi->sih->boardtype == CB2_4321_AG_BOARD) pcicore_fixlatencytimer(pch, 0x20); pcie_war_pci_setup(pi); }
static void pcie_extendL1timer(pcicore_info_t *pi, bool extend) { uint32 w; si_t *sih = pi->sih; osl_t *osh = pi->osh; sbpcieregs_t *pcieregs = pi->regs.pcieregs; if (!PCIE(sih)) return; w = pcie_readreg(osh, pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG); if (extend && sih->buscorerev >= 7) w |= PCIE_ASPMTIMER_EXTEND; else w &= ~PCIE_ASPMTIMER_EXTEND; pcie_writereg(osh, pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG, w); w = pcie_readreg(osh, pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG); }
/* centralized clkreq control policy */ static void pcie_clkreq_upd(pcicore_info_t *pi, uint state) { si_t *sih = pi->sih; ASSERT(PCIE(sih)); switch (state) { case SI_DOATTACH: /* XXX PR42780 WAR: Disable clk req when coming up */ if (PCIE_ASPM(sih)) pcie_clkreq((void *)pi, 1, 0); break; case SI_PCIDOWN: if (sih->buscorerev == 6) { /* turn on serdes PLL down */ si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol_addr), ~0, 0); si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol_data), ~0x40, 0); } else if (pi->pcie_pr42767) { /* When the driver going down, enable clkreq if PR42767 has been applied. * Also, adjust the state as system could hibernate, so Serdes PLL WAR is * a must before doing this */ pcie_clkreq((void *)pi, 1, 1); } break; case SI_PCIUP: if (sih->buscorerev == 6) { /* turn off serdes PLL down */ si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol_addr), ~0, 0); si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol_data), ~0x40, 0x40); } else if (PCIE_ASPM(sih)) { /* disable clkreq */ pcie_clkreq((void *)pi, 1, 0); } break; default: ASSERT(0); break; } }
static void pcie_extendL1timer(pcicore_info_t *pi, bool extend) { uint32 w; si_t *sih = pi->sih; osl_t *osh = pi->osh; sbpcieregs_t *pcieregs = pi->regs.pcieregs; if (!PCIE(sih) || !(sih->buscorerev == 7 || sih->buscorerev == 8)) return; /* to workaround throughput degradation due to tx underflow */ w = pcie_readreg(osh, pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG); if (extend) w |= PCIE_ASPMTIMER_EXTEND; else w &= ~PCIE_ASPMTIMER_EXTEND; pcie_writereg(osh, pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG, w); w = pcie_readreg(osh, pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG); }
/* centralized clkreq control policy */ static void pcie_clkreq_upd(pcicore_info_t *pi, uint state) { si_t *sih = pi->sih; ASSERT(PCIE(sih)); if (!PCIE_GEN1(sih)) return; switch (state) { case SI_DOATTACH: if (PCIEGEN1_ASPM(sih)) pcie_clkreq((void *)pi, 1, 0); break; case SI_PCIDOWN: if (sih->buscorerev == 6) { /* turn on serdes PLL down */ si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol_addr), ~0, 0); si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol_data), ~0x40, 0); } else if (pi->pcie_pr42767) { pcie_clkreq((void *)pi, 1, 1); } break; case SI_PCIUP: if (sih->buscorerev == 6) { /* turn off serdes PLL down */ si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol_addr), ~0, 0); si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol_data), ~0x40, 0x40); } else if (PCIEGEN1_ASPM(sih)) { /* disable clkreq */ pcie_clkreq((void *)pi, 1, 0); } break; default: ASSERT(0); break; } }
/* When the device is going to enter D3 state (or the system is going to enter S3/S4 states */ void pcicore_sleep(void *pch) { pcicore_info_t *pi = (pcicore_info_t *)pch; uint32 w; if (!pi || !PCIE(pi->sih)) return; pcie_power_save_upd(pi, FALSE); if (!PCIE_ASPM(pi->sih)) return; w = OSL_PCI_READ_CONFIG(pi->osh, pi->pciecap_lcreg_offset, sizeof(uint32)); w &= ~PCIE_CAP_LCREG_ASPML1; OSL_PCI_WRITE_CONFIG(pi->osh, pi->pciecap_lcreg_offset, sizeof(uint32), w); pi->pcie_pr42767 = FALSE; }