net: keystone_net: register MDIO bus
authorKhoronzhuk, Ivan <ivan.khoronzhuk@ti.com>
Fri, 17 Oct 2014 17:44:34 +0000 (20:44 +0300)
committerTom Rini <trini@ti.com>
Thu, 23 Oct 2014 15:27:28 +0000 (11:27 -0400)
Currently MDIO framework is not used to configure Ethernet PHY.
As result some of already implemented functions are duplicated.
So register MDIO bus in order to use it. On that stage it's just
registered, it'll be used as we start to use PHY framework.

Use mdio bus read/write/reset functions in the driver.

Acked-by: Vitaly Andrianov <vitalya@ti.com>
Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@ti.com>
drivers/net/keystone_net.c

index 3f9650c6ea3ca7939474c46af81ac1343e2a9a34..265530ad621f3a26f2ff467644c44a1d31096a8d 100644 (file)
@@ -17,6 +17,7 @@
 #include <asm/ti-common/keystone_serdes.h>
 
 unsigned int emac_open;
+static struct mii_dev *mdio_bus;
 static unsigned int sys_has_mdio = 1;
 
 #ifdef KEYSTONE2_EMAC_GIG_ENABLE
@@ -42,10 +43,6 @@ static void keystone2_net_serdes_setup(void);
 
 static int gen_get_link_speed(int phy_addr);
 
-/* EMAC Addresses */
-static volatile struct mdio_regs       *adap_mdio =
-       (struct mdio_regs *)EMAC_MDIO_BASE_ADDR;
-
 int keystone2_eth_read_mac_addr(struct eth_device *dev)
 {
        struct eth_priv_t *eth_priv;
@@ -70,64 +67,67 @@ int keystone2_eth_read_mac_addr(struct eth_device *dev)
        return 0;
 }
 
-static void keystone2_mdio_reset(void)
+/* MDIO */
+
+static int keystone2_mdio_reset(struct mii_dev *bus)
 {
-       u_int32_t       clkdiv;
+       u_int32_t clkdiv;
+       struct mdio_regs *adap_mdio = bus->priv;
 
        clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1;
 
-       writel((clkdiv & 0xffff) |
-              MDIO_CONTROL_ENABLE |
-              MDIO_CONTROL_FAULT |
-              MDIO_CONTROL_FAULT_ENABLE,
+       writel((clkdiv & 0xffff) | MDIO_CONTROL_ENABLE |
+              MDIO_CONTROL_FAULT | MDIO_CONTROL_FAULT_ENABLE,
               &adap_mdio->control);
 
        while (readl(&adap_mdio->control) & MDIO_CONTROL_IDLE)
                ;
+
+       return 0;
 }
 
-/* Read a PHY register via MDIO inteface. Returns 1 on success, 0 otherwise */
-int keystone2_eth_phy_read(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t *data)
+/**
+ * keystone2_mdio_read - read a PHY register via MDIO interface.
+ * Blocks until operation is complete.
+ */
+static int keystone2_mdio_read(struct mii_dev *bus,
+                              int addr, int devad, int reg)
 {
-       int     tmp;
+       int tmp;
+       struct mdio_regs *adap_mdio = bus->priv;
 
        while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO)
                ;
 
-       writel(MDIO_USERACCESS0_GO |
-              MDIO_USERACCESS0_WRITE_READ |
-              ((reg_num & 0x1f) << 21) |
-              ((phy_addr & 0x1f) << 16),
+       writel(MDIO_USERACCESS0_GO | MDIO_USERACCESS0_WRITE_READ |
+              ((reg & 0x1f) << 21) | ((addr & 0x1f) << 16),
               &adap_mdio->useraccess0);
 
        /* Wait for command to complete */
        while ((tmp = readl(&adap_mdio->useraccess0)) & MDIO_USERACCESS0_GO)
                ;
 
-       if (tmp & MDIO_USERACCESS0_ACK) {
-               *data = tmp & 0xffff;
-               return 0;
-       }
+       if (tmp & MDIO_USERACCESS0_ACK)
+               return tmp & 0xffff;
 
-       *data = -1;
        return -1;
 }
 
-/*
- * Write to a PHY register via MDIO inteface.
+/**
+ * keystone2_mdio_write - write to a PHY register via MDIO interface.
  * Blocks until operation is complete.
  */
-int keystone2_eth_phy_write(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t data)
+static int keystone2_mdio_write(struct mii_dev *bus,
+                               int addr, int devad, int reg, u16 val)
 {
+       struct mdio_regs *adap_mdio = bus->priv;
+
        while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO)
                ;
 
-       writel(MDIO_USERACCESS0_GO |
-              MDIO_USERACCESS0_WRITE_WRITE |
-              ((reg_num & 0x1f) << 21) |
-              ((phy_addr & 0x1f) << 16) |
-              (data & 0xffff),
-              &adap_mdio->useraccess0);
+       writel(MDIO_USERACCESS0_GO | MDIO_USERACCESS0_WRITE_WRITE |
+              ((reg & 0x1f) << 21) | ((addr & 0x1f) << 16) |
+              (val & 0xffff), &adap_mdio->useraccess0);
 
        /* Wait for command to complete */
        while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO)
@@ -139,12 +139,12 @@ int keystone2_eth_phy_write(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t data)
 /* PHY functions for a generic PHY */
 static int gen_get_link_speed(int phy_addr)
 {
-       u_int16_t       tmp;
+       u_int16_t tmp;
 
-       if ((!keystone2_eth_phy_read(phy_addr, MII_STATUS_REG, &tmp)) &&
-           (tmp & 0x04)) {
+       tmp = mdio_bus->read(mdio_bus, phy_addr,
+                            MDIO_DEVAD_NONE, MII_STATUS_REG);
+       if (tmp & 0x04)
                return 0;
-       }
 
        return -1;
 }
@@ -156,8 +156,10 @@ static void  __attribute__((unused))
        struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv;
 
        if (sys_has_mdio) {
-               if (keystone2_eth_phy_read(eth_priv->phy_addr, 0, &data) ||
-                   !(data & (1 << 6))) /* speed selection MSB */
+               data = keystone2_mdio_read(mdio_bus, eth_priv->phy_addr,
+                                          MDIO_DEVAD_NONE, 0);
+               /* speed selection MSB */
+               if (!(data & (1 << 6)))
                        return;
        }
 
@@ -435,7 +437,7 @@ static int keystone2_eth_open(struct eth_device *dev, bd_t *bis)
        hw_config_streaming_switch();
 
        if (sys_has_mdio) {
-               keystone2_mdio_reset();
+               keystone2_mdio_reset(mdio_bus);
 
                link = keystone_get_link_status(dev);
                if (link == 0) {
@@ -518,6 +520,7 @@ static int keystone2_eth_rcv_packet(struct eth_device *dev)
  */
 int keystone2_emac_initialize(struct eth_priv_t *eth_priv)
 {
+       int res;
        struct eth_device *dev;
 
        dev = malloc(sizeof(struct eth_device));
@@ -539,6 +542,20 @@ int keystone2_emac_initialize(struct eth_priv_t *eth_priv)
 
        eth_register(dev);
 
+       /* Register MDIO bus if it's not registered yet */
+       if (!mdio_bus) {
+               mdio_bus        = mdio_alloc();
+               mdio_bus->read  = keystone2_mdio_read;
+               mdio_bus->write = keystone2_mdio_write;
+               mdio_bus->reset = keystone2_mdio_reset;
+               mdio_bus->priv  = (void *)EMAC_MDIO_BASE_ADDR;
+               sprintf(mdio_bus->name, "ethernet-mdio");
+
+               res = mdio_register(mdio_bus);
+               if (res)
+                       return res;
+       }
+
        return 0;
 }