Merge branch '2022-03-18-Kconfig-migrations' into next
[platform/kernel/u-boot.git] / drivers / net / fec_mxc.c
index 992180d..e8ebef0 100644 (file)
@@ -18,6 +18,7 @@
 #include <net.h>
 #include <netdev.h>
 #include <asm/cache.h>
+#include <asm/global_data.h>
 #include <linux/delay.h>
 #include <power/regulator.h>
 
@@ -53,10 +54,6 @@ DECLARE_GLOBAL_DATA_PTR;
 #error "CONFIG_MII has to be defined!"
 #endif
 
-#ifndef CONFIG_FEC_XCV_TYPE
-#define CONFIG_FEC_XCV_TYPE MII100
-#endif
-
 /*
  * The i.MX28 operates with packets in big endian. We need to swap them before
  * sending and after receiving.
@@ -145,7 +142,7 @@ static int fec_get_clk_rate(void *udev, int idx)
            CONFIG_IS_ENABLED(CLK_CCF)) {
                dev = udev;
                if (!dev) {
-                       ret = uclass_get_device(UCLASS_ETH, idx, &dev);
+                       ret = uclass_get_device_by_seq(UCLASS_ETH, idx, &dev);
                        if (ret < 0) {
                                debug("Can't get FEC udev: %d\n", ret);
                                return ret;
@@ -330,7 +327,7 @@ static int fec_tx_task_disable(struct fec_priv *fec)
  * @param[in] fec all we know about the device yet
  * @param[in] count receive buffer count to be allocated
  * @param[in] dsize desired size of each receive buffer
- * @return 0 on success
+ * Return: 0 on success
  *
  * Init all RX descriptors to default values.
  */
@@ -407,20 +404,11 @@ static int fec_get_hwaddr(int dev_id, unsigned char *mac)
        return !is_valid_ethaddr(mac);
 }
 
-#ifdef CONFIG_DM_ETH
 static int fecmxc_set_hwaddr(struct udevice *dev)
-#else
-static int fec_set_hwaddr(struct eth_device *dev)
-#endif
 {
-#ifdef CONFIG_DM_ETH
        struct fec_priv *fec = dev_get_priv(dev);
-       struct eth_pdata *pdata = dev_get_platdata(dev);
+       struct eth_pdata *pdata = dev_get_plat(dev);
        uchar *mac = pdata->enetaddr;
-#else
-       uchar *mac = dev->enetaddr;
-       struct fec_priv *fec = (struct fec_priv *)dev->priv;
-#endif
 
        writel(0, &fec->eth->iaddr1);
        writel(0, &fec->eth->iaddr2);
@@ -457,6 +445,9 @@ static void fec_reg_setup(struct fec_priv *fec)
        else if (fec->xcv_type == RMII)
                rcntrl |= FEC_RCNTRL_RMII;
 
+       if (fec->promisc)
+               rcntrl |= 0x8;
+
        writel(rcntrl, &fec->eth->r_cntrl);
 }
 
@@ -464,17 +455,9 @@ static void fec_reg_setup(struct fec_priv *fec)
  * Start the FEC engine
  * @param[in] dev Our device to handle
  */
-#ifdef CONFIG_DM_ETH
 static int fec_open(struct udevice *dev)
-#else
-static int fec_open(struct eth_device *edev)
-#endif
 {
-#ifdef CONFIG_DM_ETH
        struct fec_priv *fec = dev_get_priv(dev);
-#else
-       struct fec_priv *fec = (struct fec_priv *)edev->priv;
-#endif
        int speed;
        ulong addr, size;
        int i;
@@ -517,7 +500,7 @@ static int fec_open(struct eth_device *edev)
               &fec->eth->ecntrl);
 #endif
 
-#if defined(CONFIG_MX25) || defined(CONFIG_MX53) || defined(CONFIG_MX6SL)
+#if defined(CONFIG_MX53) || defined(CONFIG_MX6SL)
        udelay(100);
 
        /* setup the MII gasket for RMII mode */
@@ -585,27 +568,15 @@ static int fec_open(struct eth_device *edev)
        return 0;
 }
 
-#ifdef CONFIG_DM_ETH
 static int fecmxc_init(struct udevice *dev)
-#else
-static int fec_init(struct eth_device *dev, bd_t *bd)
-#endif
 {
-#ifdef CONFIG_DM_ETH
        struct fec_priv *fec = dev_get_priv(dev);
-#else
-       struct fec_priv *fec = (struct fec_priv *)dev->priv;
-#endif
        u8 *mib_ptr = (uint8_t *)&fec->eth->rmon_t_drop;
        u8 *i;
        ulong addr;
 
        /* Initialize MAC address */
-#ifdef CONFIG_DM_ETH
        fecmxc_set_hwaddr(dev);
-#else
-       fec_set_hwaddr(dev);
-#endif
 
        /* Setup transmit descriptors, there are two in total. */
        fec_tbd_init(fec);
@@ -627,7 +598,7 @@ static int fec_init(struct eth_device *dev, bd_t *bd)
        writel(0x00000000, &fec->eth->gaddr2);
 
        /* Do not access reserved register */
-       if (!is_mx6ul() && !is_mx6ull() && !is_imx8() && !is_imx8m()) {
+       if (!is_mx6ul() && !is_mx6ull() && !is_imx8() && !is_imx8m() && !is_imx8ulp()) {
                /* clear MIB RAM */
                for (i = mib_ptr; i <= mib_ptr + 0xfc; i += 4)
                        writel(0, i);
@@ -657,17 +628,9 @@ static int fec_init(struct eth_device *dev, bd_t *bd)
  * Halt the FEC engine
  * @param[in] dev Our device to handle
  */
-#ifdef CONFIG_DM_ETH
 static void fecmxc_halt(struct udevice *dev)
-#else
-static void fec_halt(struct eth_device *dev)
-#endif
 {
-#ifdef CONFIG_DM_ETH
        struct fec_priv *fec = dev_get_priv(dev);
-#else
-       struct fec_priv *fec = (struct fec_priv *)dev->priv;
-#endif
        int counter = 0xffff;
 
        /* issue graceful stop command to the FEC transmitter if necessary */
@@ -699,13 +662,9 @@ static void fec_halt(struct eth_device *dev)
  * @param[in] dev Our ethernet device to handle
  * @param[in] packet Pointer to the data to be transmitted
  * @param[in] length Data count in bytes
- * @return 0 on success
+ * Return: 0 on success
  */
-#ifdef CONFIG_DM_ETH
 static int fecmxc_send(struct udevice *dev, void *packet, int length)
-#else
-static int fec_send(struct eth_device *dev, void *packet, int length)
-#endif
 {
        unsigned int status;
        u32 size;
@@ -717,11 +676,7 @@ static int fec_send(struct eth_device *dev, void *packet, int length)
         * This routine transmits one frame.  This routine only accepts
         * 6-byte Ethernet addresses.
         */
-#ifdef CONFIG_DM_ETH
        struct fec_priv *fec = dev_get_priv(dev);
-#else
-       struct fec_priv *fec = (struct fec_priv *)dev->priv;
-#endif
 
        /*
         * Check for valid length of data.
@@ -850,19 +805,11 @@ out:
 /**
  * Pull one frame from the card
  * @param[in] dev Our ethernet device to handle
- * @return Length of packet read
+ * Return: Length of packet read
  */
-#ifdef CONFIG_DM_ETH
 static int fecmxc_recv(struct udevice *dev, int flags, uchar **packetp)
-#else
-static int fec_recv(struct eth_device *dev)
-#endif
 {
-#ifdef CONFIG_DM_ETH
        struct fec_priv *fec = dev_get_priv(dev);
-#else
-       struct fec_priv *fec = (struct fec_priv *)dev->priv;
-#endif
        struct fec_bd *rbd = &fec->rbd_base[fec->rbd_index];
        unsigned long ievent;
        int frame_length, len = 0;
@@ -870,28 +817,19 @@ static int fec_recv(struct eth_device *dev)
        ulong addr, size, end;
        int i;
 
-#ifdef CONFIG_DM_ETH
        *packetp = memalign(ARCH_DMA_MINALIGN, FEC_MAX_PKT_SIZE);
        if (*packetp == 0) {
                printf("%s: error allocating packetp\n", __func__);
                return -ENOMEM;
        }
-#else
-       ALLOC_CACHE_ALIGN_BUFFER(uchar, buff, FEC_MAX_PKT_SIZE);
-#endif
 
        /* Check if any critical events have happened */
        ievent = readl(&fec->eth->ievent);
        writel(ievent, &fec->eth->ievent);
        debug("fec_recv: ievent 0x%lx\n", ievent);
        if (ievent & FEC_IEVENT_BABR) {
-#ifdef CONFIG_DM_ETH
                fecmxc_halt(dev);
                fecmxc_init(dev);
-#else
-               fec_halt(dev);
-               fec_init(dev, fec->bd);
-#endif
                printf("some error: 0x%08lx\n", ievent);
                return 0;
        }
@@ -903,18 +841,10 @@ static int fec_recv(struct eth_device *dev)
        if (ievent & FEC_IEVENT_GRA) {
                /* Graceful stop complete */
                if (readl(&fec->eth->x_cntrl) & 0x00000001) {
-#ifdef CONFIG_DM_ETH
                        fecmxc_halt(dev);
-#else
-                       fec_halt(dev);
-#endif
                        writel(~0x00000001 & readl(&fec->eth->x_cntrl),
                               &fec->eth->x_cntrl);
-#ifdef CONFIG_DM_ETH
                        fecmxc_init(dev);
-#else
-                       fec_init(dev, fec->bd);
-#endif
                }
        }
 
@@ -955,12 +885,7 @@ static int fec_recv(struct eth_device *dev)
                        swap_packet((uint32_t *)addr, frame_length);
 #endif
 
-#ifdef CONFIG_DM_ETH
                        memcpy(*packetp, (char *)addr, frame_length);
-#else
-                       memcpy(buff, (char *)addr, frame_length);
-                       net_process_received_packet(buff, frame_length);
-#endif
                        len = frame_length;
                } else {
                        if (bd_status & FEC_RBD_ERR)
@@ -1100,181 +1025,22 @@ struct mii_dev *fec_get_miibus(ulong base_addr, int dev_id)
        return bus;
 }
 
-#ifndef CONFIG_DM_ETH
-#ifdef CONFIG_PHYLIB
-int fec_probe(bd_t *bd, int dev_id, uint32_t base_addr,
-               struct mii_dev *bus, struct phy_device *phydev)
-#else
-static int fec_probe(bd_t *bd, int dev_id, uint32_t base_addr,
-               struct mii_dev *bus, int phy_id)
-#endif
+static int fecmxc_read_rom_hwaddr(struct udevice *dev)
 {
-       struct eth_device *edev;
-       struct fec_priv *fec;
-       unsigned char ethaddr[6];
-       char mac[16];
-       uint32_t start;
-       int ret = 0;
-
-       /* create and fill edev struct */
-       edev = (struct eth_device *)malloc(sizeof(struct eth_device));
-       if (!edev) {
-               puts("fec_mxc: not enough malloc memory for eth_device\n");
-               ret = -ENOMEM;
-               goto err1;
-       }
-
-       fec = (struct fec_priv *)malloc(sizeof(struct fec_priv));
-       if (!fec) {
-               puts("fec_mxc: not enough malloc memory for fec_priv\n");
-               ret = -ENOMEM;
-               goto err2;
-       }
-
-       memset(edev, 0, sizeof(*edev));
-       memset(fec, 0, sizeof(*fec));
-
-       ret = fec_alloc_descs(fec);
-       if (ret)
-               goto err3;
-
-       edev->priv = fec;
-       edev->init = fec_init;
-       edev->send = fec_send;
-       edev->recv = fec_recv;
-       edev->halt = fec_halt;
-       edev->write_hwaddr = fec_set_hwaddr;
-
-       fec->eth = (struct ethernet_regs *)(ulong)base_addr;
-       fec->bd = bd;
-
-       fec->xcv_type = CONFIG_FEC_XCV_TYPE;
-
-       /* Reset chip. */
-       writel(readl(&fec->eth->ecntrl) | FEC_ECNTRL_RESET, &fec->eth->ecntrl);
-       start = get_timer(0);
-       while (readl(&fec->eth->ecntrl) & FEC_ECNTRL_RESET) {
-               if (get_timer(start) > (CONFIG_SYS_HZ * 5)) {
-                       printf("FEC MXC: Timeout resetting chip\n");
-                       goto err4;
-               }
-               udelay(10);
-       }
+       struct fec_priv *priv = dev_get_priv(dev);
+       struct eth_pdata *pdata = dev_get_plat(dev);
 
-       fec_reg_setup(fec);
-       fec_set_dev_name(edev->name, dev_id);
-       fec->dev_id = (dev_id == -1) ? 0 : dev_id;
-       fec->bus = bus;
-       fec_mii_setspeed(bus->priv);
-#ifdef CONFIG_PHYLIB
-       fec->phydev = phydev;
-       phy_connect_dev(phydev, edev);
-       /* Configure phy */
-       phy_config(phydev);
-#else
-       fec->phy_id = phy_id;
-#endif
-       eth_register(edev);
-       /* only support one eth device, the index number pointed by dev_id */
-       edev->index = fec->dev_id;
-
-       if (fec_get_hwaddr(fec->dev_id, ethaddr) == 0) {
-               debug("got MAC%d address from fuse: %pM\n", fec->dev_id, ethaddr);
-               memcpy(edev->enetaddr, ethaddr, 6);
-               if (fec->dev_id)
-                       sprintf(mac, "eth%daddr", fec->dev_id);
-               else
-                       strcpy(mac, "ethaddr");
-               if (!env_get(mac))
-                       eth_env_set_enetaddr(mac, ethaddr);
-       }
-       return ret;
-err4:
-       fec_free_descs(fec);
-err3:
-       free(fec);
-err2:
-       free(edev);
-err1:
-       return ret;
+       return fec_get_hwaddr(priv->dev_id, pdata->enetaddr);
 }
 
-int fecmxc_initialize_multi(bd_t *bd, int dev_id, int phy_id, uint32_t addr)
+static int fecmxc_set_promisc(struct udevice *dev, bool enable)
 {
-       uint32_t base_mii;
-       struct mii_dev *bus = NULL;
-#ifdef CONFIG_PHYLIB
-       struct phy_device *phydev = NULL;
-#endif
-       int ret;
-
-       if (CONFIG_IS_ENABLED(IMX_MODULE_FUSE)) {
-               if (enet_fused((ulong)addr)) {
-                       printf("SoC fuse indicates Ethernet@0x%x is unavailable.\n", addr);
-                       return -ENODEV;
-               }
-       }
-
-#ifdef CONFIG_FEC_MXC_MDIO_BASE
-       /*
-        * The i.MX28 has two ethernet interfaces, but they are not equal.
-        * Only the first one can access the MDIO bus.
-        */
-       base_mii = CONFIG_FEC_MXC_MDIO_BASE;
-#else
-       base_mii = addr;
-#endif
-       debug("eth_init: fec_probe(bd, %i, %i) @ %08x\n", dev_id, phy_id, addr);
-       bus = fec_get_miibus(base_mii, dev_id);
-       if (!bus)
-               return -ENOMEM;
-#ifdef CONFIG_PHYLIB
-       phydev = phy_find_by_mask(bus, 1 << phy_id, PHY_INTERFACE_MODE_RGMII);
-       if (!phydev) {
-               mdio_unregister(bus);
-               free(bus);
-               return -ENOMEM;
-       }
-       ret = fec_probe(bd, dev_id, addr, bus, phydev);
-#else
-       ret = fec_probe(bd, dev_id, addr, bus, phy_id);
-#endif
-       if (ret) {
-#ifdef CONFIG_PHYLIB
-               free(phydev);
-#endif
-               mdio_unregister(bus);
-               free(bus);
-       }
-       return ret;
-}
+       struct fec_priv *priv = dev_get_priv(dev);
 
-#ifdef CONFIG_FEC_MXC_PHYADDR
-int fecmxc_initialize(bd_t *bd)
-{
-       return fecmxc_initialize_multi(bd, -1, CONFIG_FEC_MXC_PHYADDR,
-                       IMX_FEC_BASE);
-}
-#endif
+       priv->promisc = enable;
 
-#ifndef CONFIG_PHYLIB
-int fecmxc_register_mii_postcall(struct eth_device *dev, int (*cb)(int))
-{
-       struct fec_priv *fec = (struct fec_priv *)dev->priv;
-       fec->mii_postcall = cb;
        return 0;
 }
-#endif
-
-#else
-
-static int fecmxc_read_rom_hwaddr(struct udevice *dev)
-{
-       struct fec_priv *priv = dev_get_priv(dev);
-       struct eth_pdata *pdata = dev_get_platdata(dev);
-
-       return fec_get_hwaddr(priv->dev_id, pdata->enetaddr);
-}
 
 static int fecmxc_free_pkt(struct udevice *dev, uchar *packet, int length)
 {
@@ -1292,21 +1058,29 @@ static const struct eth_ops fecmxc_ops = {
        .stop                   = fecmxc_halt,
        .write_hwaddr           = fecmxc_set_hwaddr,
        .read_rom_hwaddr        = fecmxc_read_rom_hwaddr,
+       .set_promisc            = fecmxc_set_promisc,
 };
 
 static int device_get_phy_addr(struct fec_priv *priv, struct udevice *dev)
 {
        struct ofnode_phandle_args phandle_args;
-       int reg;
+       int reg, ret;
 
-       if (dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0,
-                                      &phandle_args)) {
-               debug("Failed to find phy-handle");
-               return -ENODEV;
+       ret = dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0,
+                                        &phandle_args);
+       if (ret) {
+               priv->phy_of_node = ofnode_find_subnode(dev_ofnode(dev),
+                                                       "fixed-link");
+               if (ofnode_valid(priv->phy_of_node))
+                       return 0;
+               debug("Failed to find phy-handle (err = %d)\n", ret);
+               return ret;
        }
 
-       priv->phy_of_node = phandle_args.node;
+       if (!ofnode_is_available(phandle_args.node))
+               return -ENOENT;
 
+       priv->phy_of_node = phandle_args.node;
        reg = ofnode_read_u32_default(phandle_args.node, "reg", 0);
 
        return reg;
@@ -1350,7 +1124,8 @@ static void fec_gpio_reset(struct fec_priv *priv)
 
 static int fecmxc_probe(struct udevice *dev)
 {
-       struct eth_pdata *pdata = dev_get_platdata(dev);
+       bool dm_mii_bus = true;
+       struct eth_pdata *pdata = dev_get_plat(dev);
        struct fec_priv *priv = dev_get_priv(dev);
        struct mii_dev *bus = NULL;
        uint32_t start;
@@ -1442,7 +1217,7 @@ static int fecmxc_probe(struct udevice *dev)
        start = get_timer(0);
        while (readl(&priv->eth->ecntrl) & FEC_ECNTRL_RESET) {
                if (get_timer(start) > (CONFIG_SYS_HZ * 5)) {
-                       printf("FEC MXC: Timeout reseting chip\n");
+                       printf("FEC MXC: Timeout resetting chip\n");
                        goto err_timeout;
                }
                udelay(10);
@@ -1450,17 +1225,19 @@ static int fecmxc_probe(struct udevice *dev)
 
        fec_reg_setup(priv);
 
-       priv->dev_id = dev->seq;
+       priv->dev_id = dev_seq(dev);
 
 #ifdef CONFIG_DM_ETH_PHY
        bus = eth_phy_get_mdio_bus(dev);
 #endif
 
        if (!bus) {
+               dm_mii_bus = false;
 #ifdef CONFIG_FEC_MXC_MDIO_BASE
-               bus = fec_get_miibus((ulong)CONFIG_FEC_MXC_MDIO_BASE, dev->seq);
+               bus = fec_get_miibus((ulong)CONFIG_FEC_MXC_MDIO_BASE,
+                                    dev_seq(dev));
 #else
-               bus = fec_get_miibus((ulong)priv->eth, dev->seq);
+               bus = fec_get_miibus((ulong)priv->eth, dev_seq(dev));
 #endif
        }
        if (!bus) {
@@ -1488,9 +1265,9 @@ static int fecmxc_probe(struct udevice *dev)
                priv->xcv_type = RGMII;
                break;
        default:
-               priv->xcv_type = CONFIG_FEC_XCV_TYPE;
-               printf("Unsupported interface type %d defaulting to %d\n",
-                      priv->interface, priv->xcv_type);
+               priv->xcv_type = MII100;
+               printf("Unsupported interface type %d defaulting to MII100\n",
+                      priv->interface);
                break;
        }
 
@@ -1501,8 +1278,10 @@ static int fecmxc_probe(struct udevice *dev)
        return 0;
 
 err_phy:
-       mdio_unregister(bus);
-       free(bus);
+       if (!dm_mii_bus) {
+               mdio_unregister(bus);
+               free(bus);
+       }
 err_mii:
 err_timeout:
        fec_free_descs(priv);
@@ -1526,14 +1305,14 @@ static int fecmxc_remove(struct udevice *dev)
        return 0;
 }
 
-static int fecmxc_ofdata_to_platdata(struct udevice *dev)
+static int fecmxc_of_to_plat(struct udevice *dev)
 {
        int ret = 0;
-       struct eth_pdata *pdata = dev_get_platdata(dev);
+       struct eth_pdata *pdata = dev_get_plat(dev);
        struct fec_priv *priv = dev_get_priv(dev);
        const char *phy_mode;
 
-       pdata->iobase = (phys_addr_t)devfdt_get_addr(dev);
+       pdata->iobase = dev_read_addr(dev);
        priv->eth = (struct ethernet_regs *)pdata->iobase;
 
        pdata->phy_interface = -1;
@@ -1592,11 +1371,10 @@ U_BOOT_DRIVER(fecmxc_gem) = {
        .name   = "fecmxc",
        .id     = UCLASS_ETH,
        .of_match = fecmxc_ids,
-       .ofdata_to_platdata = fecmxc_ofdata_to_platdata,
+       .of_to_plat = fecmxc_of_to_plat,
        .probe  = fecmxc_probe,
        .remove = fecmxc_remove,
        .ops    = &fecmxc_ops,
-       .priv_auto_alloc_size = sizeof(struct fec_priv),
-       .platdata_auto_alloc_size = sizeof(struct eth_pdata),
+       .priv_auto      = sizeof(struct fec_priv),
+       .plat_auto      = sizeof(struct eth_pdata),
 };
-#endif