int mvl88e6064_readmii(int p, int r) { union cvmx_smix_cmd smi_cmd; union cvmx_smix_wr_dat smi_wr; union cvmx_smix_rd_dat smi_rd; /* Write out address register */ smi_wr.u64 = 0; smi_wr.s.dat = 0x9800 | (p << 5) | r; cvmx_write_csr(CVMX_SMIX_WR_DAT(0), smi_wr.u64); smi_cmd.u64 = 0; smi_cmd.s.phy_op = 0; smi_cmd.s.phy_adr = 0x10; smi_cmd.s.reg_adr = 0; cvmx_write_csr(CVMX_SMIX_CMD(0), smi_cmd.u64); do { smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(0)); } while (smi_wr.s.pending); retry: /* Check BUSY bit not set anymore */ smi_cmd.u64 = 0; smi_cmd.s.phy_op = 1; smi_cmd.s.phy_adr = 0x10; smi_cmd.s.reg_adr = 0; cvmx_write_csr(CVMX_SMIX_CMD(0), smi_cmd.u64); do { smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(0)); } while (smi_rd.s.pending); if ((smi_rd.s.val) && (smi_rd.s.dat & 0x8000)) goto retry; /* Read the register value from DATA register */ smi_cmd.u64 = 0; smi_cmd.s.phy_op = 1; smi_cmd.s.phy_adr = 0x10; smi_cmd.s.reg_adr = 1; cvmx_write_csr(CVMX_SMIX_CMD(0), smi_cmd.u64); do { smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(0)); } while (smi_rd.s.pending); if (smi_rd.s.val) return smi_rd.s.dat; return 0xffff; }
void mvl88e6064_writemii(int p, int r, int v) { union cvmx_smix_cmd smi_cmd; union cvmx_smix_wr_dat smi_wr; union cvmx_smix_rd_dat smi_rd; /* Write out data register first */ smi_wr.u64 = 0; smi_wr.s.dat = v & 0xffff; cvmx_write_csr(CVMX_SMIX_WR_DAT(0), smi_wr.u64); smi_cmd.u64 = 0; smi_cmd.s.phy_op = 0; smi_cmd.s.phy_adr = 0x10; smi_cmd.s.reg_adr = 1; cvmx_write_csr(CVMX_SMIX_CMD(0), smi_cmd.u64); do { smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(0)); } while (smi_wr.s.pending); /* Write out command/address register */ smi_wr.u64 = 0; smi_wr.s.dat = 0x9400 | (p << 5) | r; cvmx_write_csr(CVMX_SMIX_WR_DAT(0), smi_wr.u64); smi_cmd.u64 = 0; smi_cmd.s.phy_op = 0; smi_cmd.s.phy_adr = 0x10; smi_cmd.s.reg_adr = 0; cvmx_write_csr(CVMX_SMIX_CMD(0), smi_cmd.u64); do { smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(0)); } while (smi_wr.s.pending); retry: /* Check BUSY bit not set anymore */ smi_cmd.u64 = 0; smi_cmd.s.phy_op = 1; smi_cmd.s.phy_adr = 0x10; smi_cmd.s.reg_adr = 0; cvmx_write_csr(CVMX_SMIX_CMD(0), smi_cmd.u64); do { smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(0)); } while (smi_rd.s.pending); if (smi_rd.s.dat & 0x8000) goto retry; }
static int octeon_mdiobus_write(struct mii_bus *bus, int phy_id, int regnum, u16 val) { struct octeon_mdiobus *p = bus->priv; union cvmx_smix_cmd smi_cmd; union cvmx_smix_wr_dat smi_wr; int timeout = 1000; smi_wr.u64 = 0; smi_wr.s.dat = val; cvmx_write_csr(CVMX_SMIX_WR_DAT(p->unit), smi_wr.u64); smi_cmd.u64 = 0; smi_cmd.s.phy_op = 0; /* MDIO_CLAUSE_22_WRITE */ smi_cmd.s.phy_adr = phy_id; smi_cmd.s.reg_adr = regnum; cvmx_write_csr(CVMX_SMIX_CMD(p->unit), smi_cmd.u64); do { /* * Wait 1000 clocks so we don't saturate the RSL bus * doing reads. */ cvmx_wait(1000); smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(p->unit)); } while (smi_wr.s.pending && --timeout); if (timeout <= 0) return -EIO; return 0; }
static int octeon_mdiobus_read(struct mii_bus *bus, int phy_id, int regnum) { struct octeon_mdiobus *p = bus->priv; union cvmx_smix_cmd smi_cmd; union cvmx_smix_rd_dat smi_rd; int timeout = 1000; smi_cmd.u64 = 0; smi_cmd.s.phy_op = 1; /* MDIO_CLAUSE_22_READ */ smi_cmd.s.phy_adr = phy_id; smi_cmd.s.reg_adr = regnum; cvmx_write_csr(CVMX_SMIX_CMD(p->unit), smi_cmd.u64); do { /* * Wait 1000 clocks so we don't saturate the RSL bus * doing reads. */ cvmx_wait(1000); smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(p->unit)); } while (smi_rd.s.pending && --timeout); if (smi_rd.s.val) return smi_rd.s.dat; else return -EIO; }
static void cvm_oct_mdio_write(struct net_device *dev, int phy_id, int location, int val) { union cvmx_smix_cmd smi_cmd; union cvmx_smix_wr_dat smi_wr; smi_wr.u64 = 0; smi_wr.s.dat = val; cvmx_write_csr(CVMX_SMIX_WR_DAT(0), smi_wr.u64); smi_cmd.u64 = 0; smi_cmd.s.phy_op = 0; smi_cmd.s.phy_adr = phy_id; smi_cmd.s.reg_adr = location; cvmx_write_csr(CVMX_SMIX_CMD(0), smi_cmd.u64); do { if (!in_interrupt()) yield(); smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(0)); } while (smi_wr.s.pending); }
static int cvm_oct_mdio_read(struct net_device *dev, int phy_id, int location) { union cvmx_smix_cmd smi_cmd; union cvmx_smix_rd_dat smi_rd; smi_cmd.u64 = 0; smi_cmd.s.phy_op = 1; smi_cmd.s.phy_adr = phy_id; smi_cmd.s.reg_adr = location; cvmx_write_csr(CVMX_SMIX_CMD(0), smi_cmd.u64); do { if (!in_interrupt()) yield(); smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(0)); } while (smi_rd.s.pending); if (smi_rd.s.val) return smi_rd.s.dat; else return 0; }
/** * Perform an MII write. Called by the generic MII routines * * @dev: Device to perform write for * @phy_id: The MII phy id * @location: Register location to write * @val: Value to write */ static void cvm_oct_mdio_write(struct net_device *dev, int phy_id, int location, int val) { union cvmx_smix_cmd smi_cmd; union cvmx_smix_wr_dat smi_wr; #ifdef CONFIG_SG590 if (phy_id == 16) { mvl88e6064_writemii(0, location, val); return; } else if (phy_id >= 32) { /* * On the 590, we map all of the switch registers * above address 32. */ mvl88e6064_writemii((phy_id % 32), location, val); return; } #endif smi_wr.u64 = 0; smi_wr.s.dat = val; cvmx_write_csr(CVMX_SMIX_WR_DAT(0), smi_wr.u64); smi_cmd.u64 = 0; smi_cmd.s.phy_op = 0; smi_cmd.s.phy_adr = phy_id; smi_cmd.s.reg_adr = location; cvmx_write_csr(CVMX_SMIX_CMD(0), smi_cmd.u64); do { if (!in_interrupt()) yield(); smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(0)); } while (smi_wr.s.pending); }
/** * Perform an MII read. Called by the generic MII routines * * @dev: Device to perform read for * @phy_id: The MII phy id * @location: Register location to read * Returns Result from the read or zero on failure */ static int cvm_oct_mdio_read(struct net_device *dev, int phy_id, int location) { union cvmx_smix_cmd smi_cmd; union cvmx_smix_rd_dat smi_rd; #ifdef CONFIG_SG590 if (phy_id == 16) { smi_rd.s.dat = mvl88e6064_readmii(0x1a, location); return smi_rd.s.dat; } else if (phy_id >= 32) { /* * On the SG590, we map all of the switch registers * above address 32. */ smi_rd.s.dat = mvl88e6064_readmii((phy_id % 32), location); return smi_rd.s.dat; } #endif smi_cmd.u64 = 0; smi_cmd.s.phy_op = 1; smi_cmd.s.phy_adr = phy_id; smi_cmd.s.reg_adr = location; cvmx_write_csr(CVMX_SMIX_CMD(0), smi_cmd.u64); do { if (!in_interrupt()) yield(); smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(0)); } while (smi_rd.s.pending); if (smi_rd.s.val) return smi_rd.s.dat; else return 0; }