Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ac1f74a7 authored by Alexandre TORGUE's avatar Alexandre TORGUE Committed by David S. Miller
Browse files

net: ethernet: stmmac: update MDIO support for GMAC4



On new GMAC4 IP, MAC_MDIO_address register has been updated, and bitmaps
changed. This patch takes into account those changes.

Signed-off-by: default avatarAlexandre TORGUE <alexandre.torgue@st.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 65226ef8
Loading
Loading
Loading
Loading
+98 −4
Original line number Diff line number Diff line
@@ -37,6 +37,18 @@
#define MII_BUSY 0x00000001
#define MII_WRITE 0x00000002

/* GMAC4 defines */
#define MII_GMAC4_GOC_SHIFT		2
#define MII_GMAC4_WRITE			(1 << MII_GMAC4_GOC_SHIFT)
#define MII_GMAC4_READ			(3 << MII_GMAC4_GOC_SHIFT)

#define MII_PHY_ADDR_GMAC4_SHIFT	21
#define MII_PHY_ADDR_GMAC4_MASK		GENMASK(25, 21)
#define MII_PHY_REG_GMAC4_SHIFT		16
#define MII_PHY_REG_GMAC4_MASK		GENMASK(20, 16)
#define MII_CSR_CLK_GMAC4_SHIFT		8
#define MII_CSR_CLK_GMAC4_MASK		GENMASK(11, 8)

static int stmmac_mdio_busy_wait(void __iomem *ioaddr, unsigned int mii_addr)
{
	unsigned long curr;
@@ -123,6 +135,80 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
	return stmmac_mdio_busy_wait(priv->ioaddr, mii_address);
}

/**
 * stmmac_mdio_read_gmac4
 * @bus: points to the mii_bus structure
 * @phyaddr: MII addr reg bits 25-21
 * @phyreg: MII addr reg bits 20-16
 * Description: it reads data from the MII register of GMAC4 from within
 * the phy device.
 */
static int stmmac_mdio_read_gmac4(struct mii_bus *bus, int phyaddr, int phyreg)
{
	struct net_device *ndev = bus->priv;
	struct stmmac_priv *priv = netdev_priv(ndev);
	unsigned int mii_address = priv->hw->mii.addr;
	unsigned int mii_data = priv->hw->mii.data;
	int data;
	u32 value = (((phyaddr << MII_PHY_ADDR_GMAC4_SHIFT) &
		     (MII_PHY_ADDR_GMAC4_MASK)) |
		     ((phyreg << MII_PHY_REG_GMAC4_SHIFT) &
		     (MII_PHY_REG_GMAC4_MASK))) | MII_GMAC4_READ;

	value |= MII_BUSY | ((priv->clk_csr & MII_CSR_CLK_GMAC4_MASK)
		 << MII_CSR_CLK_GMAC4_SHIFT);

	if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
		return -EBUSY;

	writel(value, priv->ioaddr + mii_address);

	if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
		return -EBUSY;

	/* Read the data from the MII data register */
	data = (int)readl(priv->ioaddr + mii_data);

	return data;
}

/**
 * stmmac_mdio_write_gmac4
 * @bus: points to the mii_bus structure
 * @phyaddr: MII addr reg bits 25-21
 * @phyreg: MII addr reg bits 20-16
 * @phydata: phy data
 * Description: it writes the data into the MII register of GMAC4 from within
 * the device.
 */
static int stmmac_mdio_write_gmac4(struct mii_bus *bus, int phyaddr, int phyreg,
				   u16 phydata)
{
	struct net_device *ndev = bus->priv;
	struct stmmac_priv *priv = netdev_priv(ndev);
	unsigned int mii_address = priv->hw->mii.addr;
	unsigned int mii_data = priv->hw->mii.data;

	u32 value = (((phyaddr << MII_PHY_ADDR_GMAC4_SHIFT) &
		     (MII_PHY_ADDR_GMAC4_MASK)) |
		     ((phyreg << MII_PHY_REG_GMAC4_SHIFT) &
		     (MII_PHY_REG_GMAC4_MASK))) | MII_GMAC4_WRITE;

	value |= MII_BUSY | ((priv->clk_csr & MII_CSR_CLK_GMAC4_MASK)
		 << MII_CSR_CLK_GMAC4_SHIFT);

	/* Wait until any existing MII operation is complete */
	if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
		return -EBUSY;

	/* Set the MII address register to write */
	writel(phydata, priv->ioaddr + mii_data);
	writel(value, priv->ioaddr + mii_address);

	/* Wait until any existing MII operation is complete */
	return stmmac_mdio_busy_wait(priv->ioaddr, mii_address);
}

/**
 * stmmac_mdio_reset
 * @bus: points to the mii_bus structure
@@ -180,8 +266,10 @@ int stmmac_mdio_reset(struct mii_bus *bus)

	/* This is a workaround for problems with the STE101P PHY.
	 * It doesn't complete its reset until at least one clock cycle
	 * on MDC, so perform a dummy mdio read.
	 * on MDC, so perform a dummy mdio read. To be upadted for GMAC4
	 * if needed.
	 */
	if (!priv->plat->has_gmac4)
		writel(0, priv->ioaddr + mii_address);
#endif
	return 0;
@@ -217,8 +305,14 @@ int stmmac_mdio_register(struct net_device *ndev)
#endif

	new_bus->name = "stmmac";
	if (priv->plat->has_gmac4) {
		new_bus->read = &stmmac_mdio_read_gmac4;
		new_bus->write = &stmmac_mdio_write_gmac4;
	} else {
		new_bus->read = &stmmac_mdio_read;
		new_bus->write = &stmmac_mdio_write;
	}

	new_bus->reset = &stmmac_mdio_reset;
	snprintf(new_bus->id, MII_BUS_ID_SIZE, "%s-%x",
		 new_bus->name, priv->plat->bus_id);