/* Needs to happen when coming out of 'standby'/'hibernate' */ static void pcie_war_serdes(pcicore_info_t *pi) { uint32 w = 0; if (pi->pcie_polarity != 0) pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CTRL, pi->pcie_polarity); pcie_mdioread(pi, MDIODATA_DEV_PLL, SERDES_PLL_CTRL, &w); if (w & PLL_CTRL_FREQDET_EN) { w &= ~PLL_CTRL_FREQDET_EN; pcie_mdiowrite(pi, MDIODATA_DEV_PLL, SERDES_PLL_CTRL, w); } }
/* Needs to happen when coming out of 'standby'/'hibernate' */ static void pcie_war_serdes(pcicore_info_t *pi) { uint32 w = 0; /* PR43448: program the correct polarity and disable future polarity inversions */ if (pi->pcie_polarity != 0) pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CTRL, pi->pcie_polarity); /* PR42767 workaround start: modify the SERDESS PLL control register */ pcie_mdioread(pi, MDIODATA_DEV_PLL, SERDES_PLL_CTRL, &w); if (w & PLL_CTRL_FREQDET_EN) { w &= ~PLL_CTRL_FREQDET_EN; pcie_mdiowrite(pi, MDIODATA_DEV_PLL, SERDES_PLL_CTRL, w); } }
/* Needs to happen when coming out of 'standby'/'hibernate' */ static void pcie_war_pci_setup(pcicore_info_t *pi) { si_t *sih = pi->sih; osl_t *osh = pi->osh; sbpcieregs_t *pcieregs = pi->regs.pcieregs; uint32 w; /* PR 29224 enable_9715_fix bit in the TLP workaround register should be set */ if ((sih->buscorerev == 0) || (sih->buscorerev == 1)) { w = pcie_readreg(osh, pcieregs, PCIE_PCIEREGS, PCIE_TLP_WORKAROUNDSREG); w |= 0x8; pcie_writereg(osh, pcieregs, PCIE_PCIEREGS, PCIE_TLP_WORKAROUNDSREG, w); } /* PR 34651 set bit6 to enable pcie-pm power mgmt in DLLP LC Reg, default is off */ if (sih->buscorerev == 1) { w = pcie_readreg(osh, pcieregs, PCIE_PCIEREGS, PCIE_DLLP_LCREG); w |= (0x40); pcie_writereg(osh, pcieregs, PCIE_PCIEREGS, PCIE_DLLP_LCREG, w); } if (sih->buscorerev == 0) { /* PR30841 WAR */ pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_TIMER1, 0x8128); pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CDR, 0x0100); pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CDRBW, 0x1466); } else if (PCIE_ASPM(sih)) { /* PR42766 WAR */ /* Change the L1 threshold for better performance */ w = pcie_readreg(osh, pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG); w &= ~(PCIE_L1THRESHOLDTIME_MASK); w |= (PCIE_L1THRESHOLD_WARVAL << PCIE_L1THRESHOLDTIME_SHIFT); pcie_writereg(osh, pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG, w); pcie_war_serdes(pi); pcie_war_aspm_clkreq(pi); } else if (pi->sih->buscorerev == 7) pcie_war_noplldown(pi); /* Note that the fix is actually in the SROM, that's why this is open-ended */ if (pi->sih->buscorerev >= 6) pcie_misc_config_fixup(pi); }
/* Needs to happen when coming out of 'standby'/'hibernate' */ static void pcie_war_pci_setup(pcicore_info_t *pi) { si_t *sih = pi->sih; osl_t *osh = pi->osh; sbpcieregs_t *pcieregs = pi->regs.pcieregs; uint32 w; if ((sih->buscorerev == 0) || (sih->buscorerev == 1)) { w = pcie_readreg(osh, pcieregs, PCIE_PCIEREGS, PCIE_TLP_WORKAROUNDSREG); w |= 0x8; pcie_writereg(osh, pcieregs, PCIE_PCIEREGS, PCIE_TLP_WORKAROUNDSREG, w); } if (sih->buscorerev == 1) { w = pcie_readreg(osh, pcieregs, PCIE_PCIEREGS, PCIE_DLLP_LCREG); w |= (0x40); pcie_writereg(osh, pcieregs, PCIE_PCIEREGS, PCIE_DLLP_LCREG, w); } if (sih->buscorerev == 0) { pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_TIMER1, 0x8128); pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CDR, 0x0100); pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CDRBW, 0x1466); } else if (PCIE_ASPM(sih)) { /* Change the L1 threshold for better performance */ w = pcie_readreg(osh, pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG); w &= ~(PCIE_L1THRESHOLDTIME_MASK); w |= (PCIE_L1THRESHOLD_WARVAL << PCIE_L1THRESHOLDTIME_SHIFT); pcie_writereg(osh, pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG, w); pcie_war_serdes(pi); pcie_war_aspm_clkreq(pi); } else if (pi->sih->buscorerev == 7) pcie_war_noplldown(pi); /* Note that the fix is actually in the SROM, that's why this is open-ended */ if (pi->sih->buscorerev >= 6) pcie_misc_config_fixup(pi); }
uint32 pcicore_pcieserdesreg(void *pch, uint32 mdioslave, uint32 offset, uint32 mask, uint32 val) { uint32 reg_val = 0; pcicore_info_t *pi = (pcicore_info_t *)pch; if (mask) { pcie_mdiowrite(pi, mdioslave, offset, val); } if (pcie_mdioread(pi, mdioslave, offset, ®_val)) reg_val = 0xFFFFFFFF; return reg_val; }
uint32 pcicore_pcieserdesreg(void *pch, uint32 mdioslave, uint32 offset, uint32 mask, uint32 val) { uint32 reg_val = 0; pcicore_info_t *pi = (pcicore_info_t *)pch; if (mask) { PCI_ERROR(("PCIEMDIOREG: 0x%x writeval 0x%x\n", offset, val)); pcie_mdiowrite(pi, mdioslave, offset, val); } if (pcie_mdioread(pi, mdioslave, offset, ®_val)) reg_val = 0xFFFFFFFF; PCI_ERROR(("PCIEMDIOREG: dev 0x%x offset 0x%x read 0x%x\n", mdioslave, offset, reg_val)); return reg_val; }