__be32 mdio_addr; /* MDIO address */
} __packed;
+#define MDIO_STAT_ENC BIT(6)
#define MDIO_STAT_CLKDIV(x) (((x>>1) & 0xff) << 8)
#define MDIO_STAT_BSY (1 << 0)
#define MDIO_STAT_RD_ER (1 << 1)
static int xgmac_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 value)
{
struct tgec_mdio_controller __iomem *regs = bus->priv;
- uint16_t dev_addr = regnum >> 16;
+ uint16_t dev_addr;
+ u32 mdio_ctl, mdio_stat;
int ret;
- /* Set the port and dev addr */
- out_be32(®s->mdio_ctl,
- MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr));
+ mdio_stat = in_be32(®s->mdio_stat);
+ if (regnum & MII_ADDR_C45) {
+ /* Clause 45 (ie 10G) */
+ dev_addr = (regnum >> 16) & 0x1f;
+ mdio_stat |= MDIO_STAT_ENC;
+ } else {
+ /* Clause 22 (ie 1G) */
+ dev_addr = regnum & 0x1f;
+ mdio_stat &= ~MDIO_STAT_ENC;
+ }
- /* Set the register address */
- out_be32(®s->mdio_addr, regnum & 0xffff);
+ out_be32(®s->mdio_stat, mdio_stat);
ret = xgmac_wait_until_free(&bus->dev, regs);
if (ret)
return ret;
+ /* Set the port and dev addr */
+ mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr);
+ out_be32(®s->mdio_ctl, mdio_ctl);
+
+ /* Set the register address */
+ if (regnum & MII_ADDR_C45) {
+ out_be32(®s->mdio_addr, regnum & 0xffff);
+
+ ret = xgmac_wait_until_free(&bus->dev, regs);
+ if (ret)
+ return ret;
+ }
+
/* Write the value to the register */
out_be32(®s->mdio_data, MDIO_DATA(value));
static int xgmac_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
{
struct tgec_mdio_controller __iomem *regs = bus->priv;
- uint16_t dev_addr = regnum >> 16;
+ uint16_t dev_addr;
+ uint32_t mdio_stat;
uint32_t mdio_ctl;
uint16_t value;
int ret;
+ mdio_stat = in_be32(®s->mdio_stat);
+ if (regnum & MII_ADDR_C45) {
+ dev_addr = (regnum >> 16) & 0x1f;
+ mdio_stat |= MDIO_STAT_ENC;
+ } else {
+ dev_addr = regnum & 0x1f;
+ mdio_stat = ~MDIO_STAT_ENC;
+ }
+
+ out_be32(®s->mdio_stat, mdio_stat);
+
+ ret = xgmac_wait_until_free(&bus->dev, regs);
+ if (ret)
+ return ret;
+
/* Set the Port and Device Addrs */
mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr);
out_be32(®s->mdio_ctl, mdio_ctl);
/* Set the register address */
- out_be32(®s->mdio_addr, regnum & 0xffff);
+ if (regnum & MII_ADDR_C45) {
+ out_be32(®s->mdio_addr, regnum & 0xffff);
- ret = xgmac_wait_until_free(&bus->dev, regs);
- if (ret)
- return ret;
+ ret = xgmac_wait_until_free(&bus->dev, regs);
+ if (ret)
+ return ret;
+ }
/* Initiate the read */
out_be32(®s->mdio_ctl, mdio_ctl | MDIO_CTL_READ);
{
.compatible = "fsl,fman-xmdio",
},
+ {
+ .compatible = "fsl,fman-memac-mdio",
+ },
{},
};
MODULE_DEVICE_TABLE(of, xgmac_mdio_match);