net: korina: Fix MDIO functions
authorThomas Bogendoerfer <tsbogend@alpha.franken.de>
Sun, 18 Apr 2021 22:19:39 +0000 (00:19 +0200)
committerDavid S. Miller <davem@davemloft.net>
Mon, 19 Apr 2021 22:58:14 +0000 (15:58 -0700)
Fixed MDIO functions to work reliable and not just by accident.

Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/Kconfig
drivers/net/ethernet/korina.c

index d46460c5b44dbe0d08c38f9f96af319d5e185324..172cae5dee4a1f7d7565fdca0d2ca102319af993 100644 (file)
@@ -100,6 +100,7 @@ config JME
 config KORINA
        tristate "Korina (IDT RC32434) Ethernet support"
        depends on MIKROTIK_RB532
+       select MII
        help
          If you have a Mikrotik RouterBoard 500 or IDT RC32434
          based system say Y. Otherwise say N.
index 925161959b9ba84004d608cd5adbd8a76b52a930..1b7e1c75ed9e966f9bb6309f6827ebbfc59e1c60 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/types.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
+#include <linux/iopoll.h>
 #include <linux/in.h>
 #include <linux/slab.h>
 #include <linux/string.h>
@@ -137,7 +138,6 @@ struct korina_private {
        struct mii_if_info mii_if;
        struct work_struct restart_task;
        struct net_device *dev;
-       int phy_addr;
 };
 
 extern unsigned int idt_cpu_freq;
@@ -292,32 +292,48 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev)
        return NETDEV_TX_OK;
 }
 
-static int mdio_read(struct net_device *dev, int mii_id, int reg)
+static int korina_mdio_wait(struct korina_private *lp)
+{
+       u32 value;
+
+       return readl_poll_timeout_atomic(&lp->eth_regs->miimind,
+                                        value, value & ETH_MII_IND_BSY,
+                                        1, 1000);
+}
+
+static int korina_mdio_read(struct net_device *dev, int phy, int reg)
 {
        struct korina_private *lp = netdev_priv(dev);
        int ret;
 
-       mii_id = ((lp->rx_irq == 0x2c ? 1 : 0) << 8);
+       ret = korina_mdio_wait(lp);
+       if (ret < 0)
+               return ret;
 
-       writel(0, &lp->eth_regs->miimcfg);
-       writel(0, &lp->eth_regs->miimcmd);
-       writel(mii_id | reg, &lp->eth_regs->miimaddr);
-       writel(ETH_MII_CMD_SCN, &lp->eth_regs->miimcmd);
+       writel(phy << 8 | reg, &lp->eth_regs->miimaddr);
+       writel(1, &lp->eth_regs->miimcmd);
 
-       ret = (int)(readl(&lp->eth_regs->miimrdd));
+       ret = korina_mdio_wait(lp);
+       if (ret < 0)
+               return ret;
+
+       if (readl(&lp->eth_regs->miimind) & ETH_MII_IND_NV)
+               return -EINVAL;
+
+       ret = readl(&lp->eth_regs->miimrdd);
+       writel(0, &lp->eth_regs->miimcmd);
        return ret;
 }
 
-static void mdio_write(struct net_device *dev, int mii_id, int reg, int val)
+static void korina_mdio_write(struct net_device *dev, int phy, int reg, int val)
 {
        struct korina_private *lp = netdev_priv(dev);
 
-       mii_id = ((lp->rx_irq == 0x2c ? 1 : 0) << 8);
+       if (korina_mdio_wait(lp))
+               return;
 
-       writel(0, &lp->eth_regs->miimcfg);
-       writel(1, &lp->eth_regs->miimcmd);
-       writel(mii_id | reg, &lp->eth_regs->miimaddr);
-       writel(ETH_MII_CMD_SCN, &lp->eth_regs->miimcmd);
+       writel(0, &lp->eth_regs->miimcmd);
+       writel(phy << 8 | reg, &lp->eth_regs->miimaddr);
        writel(val, &lp->eth_regs->miimwtd);
 }
 
@@ -643,7 +659,7 @@ static void korina_check_media(struct net_device *dev, unsigned int init_media)
 {
        struct korina_private *lp = netdev_priv(dev);
 
-       mii_check_media(&lp->mii_if, 0, init_media);
+       mii_check_media(&lp->mii_if, 1, init_media);
 
        if (lp->mii_if.full_duplex)
                writel(readl(&lp->eth_regs->ethmac2) | ETH_MAC2_FD,
@@ -869,12 +885,15 @@ static int korina_init(struct net_device *dev)
         * Clock independent setting */
        writel(((idt_cpu_freq) / MII_CLOCK + 1) & ~1,
                        &lp->eth_regs->ethmcp);
+       writel(0, &lp->eth_regs->miimcfg);
 
        /* don't transmit until fifo contains 48b */
        writel(48, &lp->eth_regs->ethfifott);
 
        writel(ETH_MAC1_RE, &lp->eth_regs->ethmac1);
 
+       korina_check_media(dev, 1);
+
        napi_enable(&lp->napi);
        netif_start_queue(dev);
 
@@ -1089,11 +1108,10 @@ static int korina_probe(struct platform_device *pdev)
        dev->watchdog_timeo = TX_TIMEOUT;
        netif_napi_add(dev, &lp->napi, korina_poll, NAPI_POLL_WEIGHT);
 
-       lp->phy_addr = (((lp->rx_irq == 0x2c? 1:0) << 8) | 0x05);
        lp->mii_if.dev = dev;
-       lp->mii_if.mdio_read = mdio_read;
-       lp->mii_if.mdio_write = mdio_write;
-       lp->mii_if.phy_id = lp->phy_addr;
+       lp->mii_if.mdio_read = korina_mdio_read;
+       lp->mii_if.mdio_write = korina_mdio_write;
+       lp->mii_if.phy_id = 1;
        lp->mii_if.phy_id_mask = 0x1f;
        lp->mii_if.reg_num_mask = 0x1f;