|
@@ -32,6 +32,7 @@ struct tgec_mdio_controller {
|
|
__be32 mdio_addr; /* MDIO address */
|
|
__be32 mdio_addr; /* MDIO address */
|
|
} __packed;
|
|
} __packed;
|
|
|
|
|
|
|
|
+#define MDIO_STAT_ENC BIT(6)
|
|
#define MDIO_STAT_CLKDIV(x) (((x>>1) & 0xff) << 8)
|
|
#define MDIO_STAT_CLKDIV(x) (((x>>1) & 0xff) << 8)
|
|
#define MDIO_STAT_BSY (1 << 0)
|
|
#define MDIO_STAT_BSY (1 << 0)
|
|
#define MDIO_STAT_RD_ER (1 << 1)
|
|
#define MDIO_STAT_RD_ER (1 << 1)
|
|
@@ -91,20 +92,40 @@ static int xgmac_wait_until_done(struct device *dev,
|
|
static int xgmac_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 value)
|
|
static int xgmac_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 value)
|
|
{
|
|
{
|
|
struct tgec_mdio_controller __iomem *regs = bus->priv;
|
|
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;
|
|
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);
|
|
ret = xgmac_wait_until_free(&bus->dev, regs);
|
|
if (ret)
|
|
if (ret)
|
|
return 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 */
|
|
/* Write the value to the register */
|
|
out_be32(®s->mdio_data, MDIO_DATA(value));
|
|
out_be32(®s->mdio_data, MDIO_DATA(value));
|
|
|
|
|
|
@@ -123,21 +144,39 @@ static int xgmac_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 val
|
|
static int xgmac_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
|
|
static int xgmac_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
|
|
{
|
|
{
|
|
struct tgec_mdio_controller __iomem *regs = bus->priv;
|
|
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;
|
|
uint32_t mdio_ctl;
|
|
uint16_t value;
|
|
uint16_t value;
|
|
int ret;
|
|
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 */
|
|
/* Set the Port and Device Addrs */
|
|
mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr);
|
|
mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr);
|
|
out_be32(®s->mdio_ctl, mdio_ctl);
|
|
out_be32(®s->mdio_ctl, mdio_ctl);
|
|
|
|
|
|
/* Set the register address */
|
|
/* 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 */
|
|
/* Initiate the read */
|
|
out_be32(®s->mdio_ctl, mdio_ctl | MDIO_CTL_READ);
|
|
out_be32(®s->mdio_ctl, mdio_ctl | MDIO_CTL_READ);
|
|
@@ -224,6 +263,9 @@ static struct of_device_id xgmac_mdio_match[] = {
|
|
{
|
|
{
|
|
.compatible = "fsl,fman-xmdio",
|
|
.compatible = "fsl,fman-xmdio",
|
|
},
|
|
},
|
|
|
|
+ {
|
|
|
|
+ .compatible = "fsl,fman-memac-mdio",
|
|
|
|
+ },
|
|
{},
|
|
{},
|
|
};
|
|
};
|
|
MODULE_DEVICE_TABLE(of, xgmac_mdio_match);
|
|
MODULE_DEVICE_TABLE(of, xgmac_mdio_match);
|