drivers: net: fsl_enetc: Pass on primary MAC address to Linux
authorAlex Marginean <alexandru.marginean@nxp.com>
Tue, 10 Dec 2019 14:55:39 +0000 (16:55 +0200)
committerPriyanka Jain <priyanka.jain@nxp.com>
Fri, 24 Jan 2020 08:58:26 +0000 (14:28 +0530)
Passes on the primary address used by u-boot to Linux. The code does a DT
fix-up for ENETC PFs and sets the primary MAC address in IERB. The address
in IERB is restored on ENETC PCI functions at FLR.

Signed-off-by: Alex Marginean <alexandru.marginean@nxp.com>
Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Priyanka Jain <priyanka.jain@nxp.com>
board/freescale/ls1028a/ls1028a.c
drivers/net/fsl_enetc.c
drivers/net/fsl_enetc.h

index 1151e775314db1a8420a1d977c12f69dd32e3959..c080a6b22e8a0463b736521e7d9165c247eca6de 100644 (file)
@@ -25,6 +25,7 @@
 #include <fdtdec.h>
 #include <miiphy.h>
 #include "../common/qixis.h"
+#include "../drivers/net/fsl_enetc.h"
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -162,6 +163,10 @@ int ft_board_setup(void *blob, bd_t *bd)
 
        fdt_fixup_icid(blob);
 
+#ifdef CONFIG_FSL_ENETC
+       fdt_fixup_enetc_mac(blob);
+#endif
+
        return 0;
 }
 #endif
index 02c1ee70d987985e4b455cdc38276b8205958c3c..f8fe7d4d8d75a83c02a6b8c3ad05bec6335263cf 100644 (file)
 
 #include "fsl_enetc.h"
 
+#define ENETC_DRIVER_NAME      "enetc_eth"
+
+/*
+ * sets the MAC address in IERB registers, this setting is persistent and
+ * carried over to Linux.
+ */
+static void enetc_set_ierb_primary_mac(struct udevice *dev, int devfn,
+                                      const u8 *enetaddr)
+{
+#ifdef CONFIG_ARCH_LS1028A
+/*
+ * LS1028A is the only part with IERB at this time and there are plans to change
+ * its structure, keep this LS1028A specific for now
+ */
+#define IERB_BASE              0x1f0800000ULL
+#define IERB_PFMAC(pf, vf, n)  (IERB_BASE + 0x8000 + (pf) * 0x100 + (vf) * 8 \
+                                + (n) * 4)
+
+static int ierb_fn_to_pf[] = {0, 1, 2, -1, -1, -1, 3};
+
+       u16 lower = *(const u16 *)(enetaddr + 4);
+       u32 upper = *(const u32 *)enetaddr;
+
+       if (ierb_fn_to_pf[devfn] < 0)
+               return;
+
+       out_le32(IERB_PFMAC(ierb_fn_to_pf[devfn], 0, 0), upper);
+       out_le32(IERB_PFMAC(ierb_fn_to_pf[devfn], 0, 1), (u32)lower);
+#endif
+}
+
+/* sets up primary MAC addresses in DT/IERB */
+void fdt_fixup_enetc_mac(void *blob)
+{
+       struct pci_child_platdata *ppdata;
+       struct eth_pdata *pdata;
+       struct udevice *dev;
+       struct uclass *uc;
+       char path[256];
+       int offset;
+       int devfn;
+
+       uclass_get(UCLASS_ETH, &uc);
+       uclass_foreach_dev(dev, uc) {
+               if (!dev->driver || !dev->driver->name ||
+                   strcmp(dev->driver->name, ENETC_DRIVER_NAME))
+                       continue;
+
+               pdata = dev_get_platdata(dev);
+               ppdata = dev_get_parent_platdata(dev);
+               devfn = PCI_FUNC(ppdata->devfn);
+
+               enetc_set_ierb_primary_mac(dev, devfn, pdata->enetaddr);
+
+               snprintf(path, 256, "/soc/pcie@1f0000000/ethernet@%x,%x",
+                        PCI_DEV(ppdata->devfn), PCI_FUNC(ppdata->devfn));
+               offset = fdt_path_offset(blob, path);
+               if (offset < 0)
+                       continue;
+               fdt_setprop(blob, offset, "mac-address", pdata->enetaddr, 6);
+       }
+}
+
 /*
  * Bind the device:
  * - set a more explicit name on the interface
@@ -551,7 +614,7 @@ static const struct eth_ops enetc_ops = {
 };
 
 U_BOOT_DRIVER(eth_enetc) = {
-       .name   = "enetc_eth",
+       .name   = ENETC_DRIVER_NAME,
        .id     = UCLASS_ETH,
        .bind   = enetc_bind,
        .probe  = enetc_probe,
index 9a36cdad80714fb073f32d958d5f0ff92a4332d9..48c3005cb3aa5123aff7af3f61036427acc6a173 100644 (file)
@@ -227,4 +227,7 @@ int enetc_mdio_read_priv(struct enetc_mdio_priv *priv, int addr, int devad,
 int enetc_mdio_write_priv(struct enetc_mdio_priv *priv, int addr, int devad,
                          int reg, u16 val);
 
+/* sets up primary MAC addresses in DT/IERB */
+void fdt_fixup_enetc_mac(void *blob);
+
 #endif /* _ENETC_H */