uint32 pcie_ltr_reg(void *pch, uint32 reg, uint32 mask, uint32 val) { pcicore_info_t *pi = (pcicore_info_t *)pch; uint32 reg_val; uint32 offset; if (PCIE_GEN1(pi->sih)) return 0; if (reg == PCIE_CAP_LTR0_REG) offset = pi->pciecap_ltr0_reg_offset; else if (reg == PCIE_CAP_LTR1_REG) offset = pi->pciecap_ltr1_reg_offset; else if (reg == PCIE_CAP_LTR2_REG) offset = pi->pciecap_ltr2_reg_offset; else { PCI_ERROR(("pcie_ltr_reg: unsupported LTR register offset %d\n", reg)); return 0; } if (!offset) return 0; if (mask) { /* set operation */ reg_val = val; pcie_writereg(pi->sih, pi->regs.pcieregs, PCIE_CONFIGREGS, offset, reg_val); } else { /* get operation */ reg_val = pcie_readreg(pi->sih, pi->regs.pcieregs, PCIE_CONFIGREGS, offset); } return reg_val; }
void pcie_set_L1substate(void *pch, uint32 substate) { pcicore_info_t *pi = (pcicore_info_t *)pch; si_t *sih = pi->sih; sbpcieregs_t *pcieregs = pi->regs.pcieregs; uint32 data; ASSERT(PCIE_GEN2(sih)); ASSERT(substate <= 3); if (substate != 0) { /* turn on ASPM L1 */ data = pcie_readreg(sih, pcieregs, PCIE_CONFIGREGS, pi->pciecap_lcreg_offset); pcie_writereg(sih, pcieregs, PCIE_CONFIGREGS, pi->pciecap_lcreg_offset, data | 2); /* enable LTR */ pcie_ltrenable(pch, 1, 1); } /* PML1_sub_control1 can only be accessed by OSL_PCI_xxxx_CONFIG */ data = OSL_PCI_READ_CONFIG(pi->osh, PCIECFGREG_PML1_SUB_CTRL1, sizeof(uint32)) & 0xfffffff0; /* JIRA:SWWLAN-28455 */ if (substate & 1) data |= PCI_PM_L1_2_ENA_MASK | ASPM_L1_2_ENA_MASK; if (substate & 2) data |= PCI_PM_L1_1_ENA_MASK | ASPM_L1_1_ENA_MASK; OSL_PCI_WRITE_CONFIG(pi->osh, PCIECFGREG_PML1_SUB_CTRL1, sizeof(uint32), data); }
/* 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); }
/* mode : 0 -- reset, 1 -- tx, 2 -- rx */ void pcie_set_error_injection(void *pch, uint32 mode) { /* through reg_phy_ctl_7 - 0x181c */ pcicore_info_t *pi = (pcicore_info_t *)pch; si_t *sih = pi->sih; sbpcieregs_t *pcieregs = pi->regs.pcieregs; if (!PCIE_GEN1(sih) && !PCIE_GEN2(sih)) return; if (mode == 0) pcie_writereg(pch, pcieregs, PCIE_CONFIGREGS, 0x181c, 0); else if (mode == 1) pcie_writereg(pch, pcieregs, PCIE_CONFIGREGS, 0x181c, 0x14031); else pcie_writereg(pch, pcieregs, PCIE_CONFIGREGS, 0x181c, 0x2c031); }
/* 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); }
static void pcie_extendL1timer(struct pcicore_info *pi, bool extend) { u32 w; struct si_pub *sih = pi->sih; if (ai_get_buscoretype(sih) != PCIE_CORE_ID || ai_get_buscorerev(sih) < 7) return; w = pcie_readreg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG); if (extend) w |= PCIE_ASPMTIMER_EXTEND; else w &= ~PCIE_ASPMTIMER_EXTEND; pcie_writereg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG, w); w = pcie_readreg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG); }
void pcie_set_L1_entry_time(void *pch, uint32 val) { /* L1 entry time is located in bits [22:16] of register 0x1004 (pdl_control_1) */ pcicore_info_t *pi = (pcicore_info_t *)pch; si_t *sih = pi->sih; sbpcieregs_t *pcieregs = pi->regs.pcieregs; uint32 data; if (!PCIE_GEN1(sih) && !PCIE_GEN2(sih)) return; if (val > 0x7F) return; data = pcie_readreg(sih, pcieregs, PCIE_CONFIGREGS, 0x1004); pcie_writereg(pch, pcieregs, PCIE_CONFIGREGS, 0x1004, (data & ~0x7F0000) | (val << 16)); }
static void pcie_extendL1timer(pcicore_info_t *pi, bool extend) { uint32 w; si_t *sih = pi->sih; sbpcieregs_t *pcieregs = pi->regs.pcieregs; if (!PCIE_GEN1(sih)) return; w = pcie_readreg(sih, pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG); if (extend && sih->buscorerev >= 7) w |= PCIE_ASPMTIMER_EXTEND; else w &= ~PCIE_ASPMTIMER_EXTEND; pcie_writereg(sih, pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG, w); w = pcie_readreg(sih, pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG); }
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); }
uint32 pcicore_pciereg(void *pch, uint32 offset, uint32 mask, uint32 val, uint type) { uint32 reg_val = 0; pcicore_info_t *pi = (pcicore_info_t *)pch; sbpcieregs_t *pcieregs = pi->regs.pcieregs; if (mask) { PCI_ERROR(("PCIEREG: 0x%x writeval 0x%x\n", offset, val)); pcie_writereg(pi->sih, pcieregs, type, offset, val); } /* Should not read register 0x154 */ if (PCIE_GEN1(pi->sih) && pi->sih->buscorerev <= 5 && offset == PCIE_DLLP_PCIE11 && type == PCIE_PCIEREGS) return reg_val; reg_val = pcie_readreg(pi->sih, pcieregs, type, offset); PCI_ERROR(("PCIEREG: 0x%x readval is 0x%x\n", offset, reg_val)); return reg_val; }
uint32 pcicore_pciereg(void *pch, uint32 offset, uint32 mask, uint32 val, uint type) { uint32 reg_val = 0; pcicore_info_t *pi = (pcicore_info_t *)pch; sbpcieregs_t *pcieregs = pi->regs.pcieregs; osl_t *osh = pi->osh; if (mask) { PCI_ERROR(("PCIEREG: 0x%x writeval 0x%x\n", offset, val)); pcie_writereg(osh, pcieregs, type, offset, val); } /* Should not read register 0x154 */ /* PR42815: PCIE: Accesses to dlinkPCIE1_1 register (0x154 address) broken */ if (pi->sih->buscorerev <= 5 && offset == PCIE_DLLP_PCIE11 && type == PCIE_PCIEREGS) return reg_val; reg_val = pcie_readreg(osh, pcieregs, type, offset); PCI_ERROR(("PCIEREG: 0x%x readval is 0x%x\n", offset, reg_val)); return reg_val; }