|
@@ -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,9 +266,11 @@ 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.
|
|
|
*/
|
|
|
- writel(0, priv->ioaddr + mii_address);
|
|
|
+ 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";
|
|
|
- new_bus->read = &stmmac_mdio_read;
|
|
|
- new_bus->write = &stmmac_mdio_write;
|
|
|
+ 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);
|