]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - drivers/net/mvgbe.c
arm: mx6: add support for i.MX6ULL
[karo-tx-uboot.git] / drivers / net / mvgbe.c
index 1dcb700161289e954d8273dc48b97ad0b2dca905..ab5aa68fc8cf7ce41d51d2222e0c225a83dc7fa0 100644 (file)
@@ -9,23 +9,7 @@
  * based on - Driver for MV64360X ethernet ports
  * Copyright (C) 2002 rabeeh@galileo.co.il
  *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
+ * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <common.h>
 #include <asm/arch/cpu.h>
 
 #if defined(CONFIG_KIRKWOOD)
-#include <asm/arch/kirkwood.h>
+#include <asm/arch/soc.h>
 #elif defined(CONFIG_ORION5X)
 #include <asm/arch/orion5x.h>
+#elif defined(CONFIG_DOVE)
+#include <asm/arch/dove.h>
 #endif
 
 #include "mvgbe.h"
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#ifndef CONFIG_MVGBE_PORTS
+# define CONFIG_MVGBE_PORTS {0, 0}
+#endif
+
 #define MV_PHY_ADR_REQUEST 0xee
 #define MVGBE_SMI_REG (((struct mvgbe_registers *)MVGBE0_BASE)->smi)
 
+#if defined(CONFIG_PHYLIB) || defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
 /*
  * smi_reg_read - miiphy_read callback function.
  *
@@ -75,12 +66,12 @@ static int smi_reg_read(const char *devname, u8 phy_adr, u8 reg_ofs, u16 * data)
        /* check parameters */
        if (phy_adr > PHYADR_MASK) {
                printf("Err..(%s) Invalid PHY address %d\n",
-                       __FUNCTION__, phy_adr);
+                       __func__, phy_adr);
                return -EFAULT;
        }
        if (reg_ofs > PHYREG_MASK) {
                printf("Err..(%s) Invalid register offset %d\n",
-                       __FUNCTION__, reg_ofs);
+                       __func__, reg_ofs);
                return -EFAULT;
        }
 
@@ -90,7 +81,7 @@ static int smi_reg_read(const char *devname, u8 phy_adr, u8 reg_ofs, u16 * data)
                /* read smi register */
                smi_reg = MVGBE_REG_RD(MVGBE_SMI_REG);
                if (timeout-- == 0) {
-                       printf("Err..(%s) SMI busy timeout\n", __FUNCTION__);
+                       printf("Err..(%s) SMI busy timeout\n", __func__);
                        return -EFAULT;
                }
        } while (smi_reg & MVGBE_PHY_SMI_BUSY_MASK);
@@ -111,7 +102,7 @@ static int smi_reg_read(const char *devname, u8 phy_adr, u8 reg_ofs, u16 * data)
                smi_reg = MVGBE_REG_RD(MVGBE_SMI_REG);
                if (timeout-- == 0) {
                        printf("Err..(%s) SMI read ready timeout\n",
-                               __FUNCTION__);
+                               __func__);
                        return -EFAULT;
                }
        } while (!(smi_reg & MVGBE_PHY_SMI_READ_VALID_MASK));
@@ -122,8 +113,8 @@ static int smi_reg_read(const char *devname, u8 phy_adr, u8 reg_ofs, u16 * data)
 
        *data = (u16) (MVGBE_REG_RD(MVGBE_SMI_REG) & MVGBE_PHY_SMI_DATA_MASK);
 
-       debug("%s:(adr %d, off %d) value= %04x\n", __FUNCTION__, phy_adr,
-               reg_ofs, *data);
+       debug("%s:(adr %d, off %d) value= %04x\n", __func__, phy_adr, reg_ofs,
+             *data);
 
        return 0;
 }
@@ -151,11 +142,11 @@ static int smi_reg_write(const char *devname, u8 phy_adr, u8 reg_ofs, u16 data)
 
        /* check parameters */
        if (phy_adr > PHYADR_MASK) {
-               printf("Err..(%s) Invalid phy address\n", __FUNCTION__);
+               printf("Err..(%s) Invalid phy address\n", __func__);
                return -EINVAL;
        }
        if (reg_ofs > PHYREG_MASK) {
-               printf("Err..(%s) Invalid register offset\n", __FUNCTION__);
+               printf("Err..(%s) Invalid register offset\n", __func__);
                return -EINVAL;
        }
 
@@ -165,7 +156,7 @@ static int smi_reg_write(const char *devname, u8 phy_adr, u8 reg_ofs, u16 data)
                /* read smi register */
                smi_reg = MVGBE_REG_RD(MVGBE_SMI_REG);
                if (timeout-- == 0) {
-                       printf("Err..(%s) SMI busy timeout\n", __FUNCTION__);
+                       printf("Err..(%s) SMI busy timeout\n", __func__);
                        return -ETIME;
                }
        } while (smi_reg & MVGBE_PHY_SMI_BUSY_MASK);
@@ -181,6 +172,26 @@ static int smi_reg_write(const char *devname, u8 phy_adr, u8 reg_ofs, u16 data)
 
        return 0;
 }
+#endif
+
+#if defined(CONFIG_PHYLIB)
+int mvgbe_phy_read(struct mii_dev *bus, int phy_addr, int dev_addr,
+                  int reg_addr)
+{
+       u16 data;
+       int ret;
+       ret = smi_reg_read(bus->name, phy_addr, reg_addr, &data);
+       if (ret)
+               return ret;
+       return data;
+}
+
+int mvgbe_phy_write(struct mii_dev *bus, int phy_addr, int dev_addr,
+                   int reg_addr, u16 data)
+{
+       return smi_reg_write(bus->name, phy_addr, reg_addr, data);
+}
+#endif
 
 /* Stop and checks all queues */
 static void stop_queue(u32 * qreg)
@@ -413,8 +424,9 @@ static int mvgbe_init(struct eth_device *dev)
 {
        struct mvgbe_device *dmvgbe = to_mvgbe(dev);
        struct mvgbe_registers *regs = dmvgbe->regs;
-#if (defined (CONFIG_MII) || defined (CONFIG_CMD_MII)) \
-        && defined (CONFIG_SYS_FAULT_ECHO_LINK_DOWN)
+#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) &&  \
+       !defined(CONFIG_PHYLIB) &&                       \
+       defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN)
        int i;
 #endif
        /* setup RX rings */
@@ -465,8 +477,9 @@ static int mvgbe_init(struct eth_device *dev)
        /* Enable port Rx. */
        MVGBE_REG_WR(regs->rqc, (1 << RXUQ));
 
-#if (defined (CONFIG_MII) || defined (CONFIG_CMD_MII)) \
-        && defined (CONFIG_SYS_FAULT_ECHO_LINK_DOWN)
+#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && \
+       !defined(CONFIG_PHYLIB) && \
+       defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN)
        /* Wait up to 5s for the link status */
        for (i = 0; i < 5; i++) {
                u16 phyadr;
@@ -523,8 +536,7 @@ static int mvgbe_write_hwaddr(struct eth_device *dev)
        return 0;
 }
 
-static int mvgbe_send(struct eth_device *dev, void *dataptr,
-                     int datasize)
+static int mvgbe_send(struct eth_device *dev, void *dataptr, int datasize)
 {
        struct mvgbe_device *dmvgbe = to_mvgbe(dev);
        struct mvgbe_registers *regs = dmvgbe->regs;
@@ -571,7 +583,7 @@ static int mvgbe_send(struct eth_device *dev, void *dataptr,
                if ((cmd_sts & (MVGBE_ERROR_SUMMARY | MVGBE_TX_LAST_FRAME)) ==
                                (MVGBE_ERROR_SUMMARY | MVGBE_TX_LAST_FRAME) &&
                                cmd_sts & (MVGBE_UR_ERROR | MVGBE_RL_ERROR)) {
-                       printf("Err..(%s) in xmit packet\n", __FUNCTION__);
+                       printf("Err..(%s) in xmit packet\n", __func__);
                        return -1;
                }
                cmd_sts = readl(&p_txdesc->cmd_sts);
@@ -592,14 +604,14 @@ static int mvgbe_recv(struct eth_device *dev)
                if (timeout < MVGBE_PHY_SMI_TIMEOUT)
                        timeout++;
                else {
-                       debug("%s time out...\n", __FUNCTION__);
+                       debug("%s time out...\n", __func__);
                        return -1;
                }
        } while (readl(&p_rxdesc_curr->cmd_sts) & MVGBE_BUFFER_OWNED_BY_DMA);
 
        if (p_rxdesc_curr->byte_cnt != 0) {
                debug("%s: Received %d byte Packet @ 0x%x (cmd_sts= %08x)\n",
-                       __FUNCTION__, (u32) p_rxdesc_curr->byte_cnt,
+                       __func__, (u32) p_rxdesc_curr->byte_cnt,
                        (u32) p_rxdesc_curr->buf_ptr,
                        (u32) p_rxdesc_curr->cmd_sts);
        }
@@ -616,21 +628,24 @@ static int mvgbe_recv(struct eth_device *dev)
                != (MVGBE_RX_FIRST_DESC | MVGBE_RX_LAST_DESC)) {
 
                printf("Err..(%s) Dropping packet spread on"
-                       " multiple descriptors\n", __FUNCTION__);
+                       " multiple descriptors\n", __func__);
 
        } else if (cmd_sts & MVGBE_ERROR_SUMMARY) {
 
                printf("Err..(%s) Dropping packet with errors\n",
-                       __FUNCTION__);
+                       __func__);
 
        } else {
                /* !!! call higher layer processing */
                debug("%s: Sending Received packet to"
-                       " upper layer (NetReceive)\n", __FUNCTION__);
+                     " upper layer (net_process_received_packet)\n",
+                     __func__);
 
                /* let the upper layer handle the packet */
-               NetReceive((p_rxdesc_curr->buf_ptr + RX_BUF_OFFSET),
-                       (int)(p_rxdesc_curr->byte_cnt - RX_BUF_OFFSET));
+               net_process_received_packet((p_rxdesc_curr->buf_ptr +
+                                            RX_BUF_OFFSET),
+                                           (int)(p_rxdesc_curr->byte_cnt -
+                                                 RX_BUF_OFFSET));
        }
        /*
         * free these descriptors and point next in the ring
@@ -646,6 +661,45 @@ static int mvgbe_recv(struct eth_device *dev)
        return 0;
 }
 
+#if defined(CONFIG_PHYLIB)
+int mvgbe_phylib_init(struct eth_device *dev, int phyid)
+{
+       struct mii_dev *bus;
+       struct phy_device *phydev;
+       int ret;
+
+       bus = mdio_alloc();
+       if (!bus) {
+               printf("mdio_alloc failed\n");
+               return -ENOMEM;
+       }
+       bus->read = mvgbe_phy_read;
+       bus->write = mvgbe_phy_write;
+       sprintf(bus->name, dev->name);
+
+       ret = mdio_register(bus);
+       if (ret) {
+               printf("mdio_register failed\n");
+               free(bus);
+               return -ENOMEM;
+       }
+
+       /* Set phy address of the port */
+       mvgbe_phy_write(bus, MV_PHY_ADR_REQUEST, 0, MV_PHY_ADR_REQUEST, phyid);
+
+       phydev = phy_connect(bus, phyid, dev, PHY_INTERFACE_MODE_RGMII);
+       if (!phydev) {
+               printf("phy_connect failed\n");
+               return -ENODEV;
+       }
+
+       phy_config(phydev);
+       phy_startup(phydev);
+
+       return 0;
+}
+#endif
+
 int mvgbe_initialize(bd_t *bis)
 {
        struct mvgbe_device *dmvgbe;
@@ -696,13 +750,13 @@ error2:
                        free(dmvgbe);
 error1:
                        printf("Err.. %s Failed to allocate memory\n",
-                               __FUNCTION__);
+                               __func__);
                        return -1;
                }
 
                dev = &dmvgbe->dev;
 
-               /* must be less than NAMESIZE (16) */
+               /* must be less than sizeof(dev->name) */
                sprintf(dev->name, "egiga%d", devnum);
 
                switch (devnum) {
@@ -716,7 +770,7 @@ error1:
 #endif
                default:        /* this should never happen */
                        printf("Err..(%s) Invalid device number %d\n",
-                               __FUNCTION__, devnum);
+                               __func__, devnum);
                        return -1;
                }
 
@@ -728,7 +782,9 @@ error1:
 
                eth_register(dev);
 
-#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+#if defined(CONFIG_PHYLIB)
+               mvgbe_phylib_init(dev, PHY_BASE_ADR + devnum);
+#elif defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
                miiphy_register(dev->name, smi_reg_read, smi_reg_write);
                /* Set phy address of the port */
                miiphy_write(dev->name, MV_PHY_ADR_REQUEST,