static bool pcie_mdiosetblock(struct pcicore_info *pi, uint blk) { uint mdiodata, i = 0; uint pcie_serdes_spinwait = 200; mdiodata = (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA | (MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) | (MDIODATA_BLK_ADDR << MDIODATA_REGADDR_SHF) | (blk << 4)); bcma_write32(pi->core, PCIEREGOFFS(mdiodata), mdiodata); pr28829_delay(); /* retry till the transaction is complete */ while (i < pcie_serdes_spinwait) { if (bcma_read32(pi->core, PCIEREGOFFS(mdiocontrol)) & MDIOCTL_ACCESS_DONE) break; udelay(1000); i++; } if (i >= pcie_serdes_spinwait) return false; return true; }
static uint pcie_writereg(struct bcma_device *core, uint addrtype, uint offset, uint val) { switch (addrtype) { case PCIE_CONFIGREGS: bcma_write32(core, PCIEREGOFFS(configaddr), offset); bcma_write32(core, PCIEREGOFFS(configdata), val); break; case PCIE_PCIEREGS: bcma_write32(core, PCIEREGOFFS(pcieindaddr), offset); bcma_write32(core, PCIEREGOFFS(pcieinddata), val); break; default: break; } return 0; }
static int pcie_mdioop(struct pcicore_info *pi, uint physmedia, uint regaddr, bool write, uint *val) { uint mdiodata; uint i = 0; uint pcie_serdes_spinwait = 10; /* enable mdio access to SERDES */ bcma_write32(pi->core, PCIEREGOFFS(mdiocontrol), MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL); if (ai_get_buscorerev(pi->sih) >= 10) { /* new serdes is slower in rw, * using two layers of reg address mapping */ if (!pcie_mdiosetblock(pi, physmedia)) return 1; mdiodata = ((MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) | (regaddr << MDIODATA_REGADDR_SHF)); pcie_serdes_spinwait *= 20; } else { mdiodata = ((physmedia << MDIODATA_DEVADDR_SHF_OLD) | (regaddr << MDIODATA_REGADDR_SHF_OLD)); } if (!write) mdiodata |= (MDIODATA_START | MDIODATA_READ | MDIODATA_TA); else mdiodata |= (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA | *val); bcma_write32(pi->core, PCIEREGOFFS(mdiodata), mdiodata); pr28829_delay(); /* retry till the transaction is complete */ while (i < pcie_serdes_spinwait) { if (bcma_read32(pi->core, PCIEREGOFFS(mdiocontrol)) & MDIOCTL_ACCESS_DONE) { if (!write) { pr28829_delay(); *val = (bcma_read32(pi->core, PCIEREGOFFS(mdiodata)) & MDIODATA_MASK); } /* Disable mdio access to SERDES */ bcma_write32(pi->core, PCIEREGOFFS(mdiocontrol), 0); return 0; } udelay(1000); i++; } /* Timed out. Disable mdio access to SERDES. */ bcma_write32(pi->core, PCIEREGOFFS(mdiocontrol), 0); return 1; }
static int pcie_mdioop(struct pcicore_info *pi, uint physmedia, uint regaddr, bool write, uint *val) { uint mdiodata; uint i = 0; uint pcie_serdes_spinwait = 10; bcma_write32(pi->core, PCIEREGOFFS(mdiocontrol), MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL); if (ai_get_buscorerev(pi->sih) >= 10) { if (!pcie_mdiosetblock(pi, physmedia)) return 1; mdiodata = ((MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) | (regaddr << MDIODATA_REGADDR_SHF)); pcie_serdes_spinwait *= 20; } else { mdiodata = ((physmedia << MDIODATA_DEVADDR_SHF_OLD) | (regaddr << MDIODATA_REGADDR_SHF_OLD)); } if (!write) mdiodata |= (MDIODATA_START | MDIODATA_READ | MDIODATA_TA); else mdiodata |= (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA | *val); bcma_write32(pi->core, PCIEREGOFFS(mdiodata), mdiodata); pr28829_delay(); while (i < pcie_serdes_spinwait) { if (bcma_read32(pi->core, PCIEREGOFFS(mdiocontrol)) & MDIOCTL_ACCESS_DONE) { if (!write) { pr28829_delay(); *val = (bcma_read32(pi->core, PCIEREGOFFS(mdiodata)) & MDIODATA_MASK); } bcma_write32(pi->core, PCIEREGOFFS(mdiocontrol), 0); return 0; } udelay(1000); i++; } bcma_write32(pi->core, PCIEREGOFFS(mdiocontrol), 0); return 1; }
/* ***** Register Access API */ static uint pcie_readreg(struct bcma_device *core, uint addrtype, uint offset) { uint retval = 0xFFFFFFFF; switch (addrtype) { case PCIE_CONFIGREGS: bcma_write32(core, PCIEREGOFFS(configaddr), offset); (void)bcma_read32(core, PCIEREGOFFS(configaddr)); retval = bcma_read32(core, PCIEREGOFFS(configdata)); break; case PCIE_PCIEREGS: bcma_write32(core, PCIEREGOFFS(pcieindaddr), offset); (void)bcma_read32(core, PCIEREGOFFS(pcieindaddr)); retval = bcma_read32(core, PCIEREGOFFS(pcieinddata)); break; } return retval; }