static int iproc_mdio_read(struct mii_bus *bus, int phy_id, int reg) { struct iproc_mdio_priv *priv = bus->priv; u32 cmd; int rc; rc = iproc_mdio_wait_for_idle(priv->base); if (rc) return rc; iproc_mdio_config_clk(priv->base); /* Prepare the read operation */ cmd = (MII_DATA_TA_VAL << MII_DATA_TA_SHIFT) | (reg << MII_DATA_RA_SHIFT) | (phy_id << MII_DATA_PA_SHIFT) | BIT(MII_DATA_SB_SHIFT) | (MII_DATA_OP_READ << MII_DATA_OP_SHIFT); writel(cmd, priv->base + MII_DATA_OFFSET); rc = iproc_mdio_wait_for_idle(priv->base); if (rc) return rc; cmd = readl(priv->base + MII_DATA_OFFSET) & MII_DATA_MASK; return cmd; }
/* start_miim_ops- Program and start MDIO transaction over mdio bus. * @base: Base address * @phyid: phyid of the selected bus. * @reg: register offset to be read/written. * @val :0 if read op else value to be written in @reg; * @op: Operation that need to be carried out. * MDIO_CTRL_READ_OP: Read transaction. * MDIO_CTRL_WRITE_OP: Write transaction. * * Return value: Successful Read operation returns read reg values and write * operation returns 0. Failure operation returns negative error code. */ static int start_miim_ops(void __iomem *base, u16 phyid, u32 reg, u16 val, u32 op) { u32 param; int ret; writel(0, base + MDIO_CTRL_OFFSET); ret = iproc_mdio_wait_for_idle(base, 0); if (ret) goto err; param = readl(base + MDIO_PARAM_OFFSET); param |= phyid << MDIO_PARAM_PHY_ID; param |= val << MDIO_PARAM_PHY_DATA; if (reg & MII_ADDR_C45) param |= BIT(MDIO_PARAM_C45_SEL); writel(param, base + MDIO_PARAM_OFFSET); writel(reg, base + MDIO_ADDR_OFFSET); writel(op, base + MDIO_CTRL_OFFSET); ret = iproc_mdio_wait_for_idle(base, 1); if (ret) goto err; if (op == MDIO_CTRL_READ_OP) ret = readl(base + MDIO_READ_OFFSET) & MDIO_READ_DATA_MASK; err: return ret; }
static int iproc_mdio_write(struct mii_bus *bus, int phy_id, int reg, u16 val) { struct iproc_mdio_priv *priv = bus->priv; u32 cmd; int rc; rc = iproc_mdio_wait_for_idle(priv->base); if (rc) return rc; iproc_mdio_config_clk(priv->base); /* Prepare the write operation */ cmd = (MII_DATA_TA_VAL << MII_DATA_TA_SHIFT) | (reg << MII_DATA_RA_SHIFT) | (phy_id << MII_DATA_PA_SHIFT) | BIT(MII_DATA_SB_SHIFT) | (MII_DATA_OP_WRITE << MII_DATA_OP_SHIFT) | ((u32)(val) & MII_DATA_MASK); writel(cmd, priv->base + MII_DATA_OFFSET); rc = iproc_mdio_wait_for_idle(priv->base); if (rc) return rc; return 0; }