drivers: net: fsl_enetc: add write_hwaddr() for LS1028A
authorMichael Walle <michael@walle.cc>
Fri, 20 Dec 2019 13:16:48 +0000 (14:16 +0100)
committerPriyanka Jain <priyanka.jain@nxp.com>
Fri, 24 Jan 2020 08:58:26 +0000 (14:28 +0530)
The LS1028A SoC is special in the handling of the MAC addresses. We need
to write to the IERB version of the PSIPMAR0/1 register. This value will
be sampled into the corresponding port PSIPMAR0/1 register if the PCI
memory access is enabled.

Signed-off-by: Michael Walle <michael@walle.cc>
Signed-off-by: Alex Marginean <alexandru.marginean@nxp.com>
Reviewed-by: Priyanka Jain <priyanka.jain@nxp.com>
drivers/net/fsl_enetc.c

index 7c0ed9f606565d934a979fd81844e2e0c7df288b..2ffab1bb148e93fc8fb34b61e6bad79cd3371d3b 100644 (file)
@@ -330,12 +330,50 @@ static int enetc_remove(struct udevice *dev)
        return 0;
 }
 
+/*
+ * 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 LS1028A_IERB_BASE              0x1f0800000ULL
+#define LS1028A_IERB_PSIPMAR0(pf, vf)  (LS1028A_IERB_BASE + 0x8000 \
+                                        + (pf) * 0x100 + (vf) * 8)
+#define LS1028A_IERB_PSIPMAR1(pf, vf)  (LS1028A_IERB_PSIPMAR0(pf, vf) + 4)
+
+static int enetc_ls1028a_write_hwaddr(struct udevice *dev)
+{
+       struct pci_child_platdata *ppdata = dev_get_parent_platdata(dev);
+       const int devfn_to_pf[] = {0, 1, 2, -1, -1, -1, 3};
+       struct eth_pdata *plat = dev_get_platdata(dev);
+       int devfn = PCI_FUNC(ppdata->devfn);
+       u8 *addr = plat->enetaddr;
+       u32 lower, upper;
+       int pf;
+
+       if (devfn >= ARRAY_SIZE(devfn_to_pf))
+               return 0;
+
+       pf = devfn_to_pf[devfn];
+       if (pf < 0)
+               return 0;
+
+       lower = *(const u16 *)(addr + 4);
+       upper = *(const u32 *)addr;
+
+       out_le32(LS1028A_IERB_PSIPMAR0(pf, 0), upper);
+       out_le32(LS1028A_IERB_PSIPMAR1(pf, 0), lower);
+
+       return 0;
+}
+
 static int enetc_write_hwaddr(struct udevice *dev)
 {
        struct eth_pdata *plat = dev_get_platdata(dev);
        struct enetc_priv *priv = dev_get_priv(dev);
        u8 *addr = plat->enetaddr;
 
+       if (IS_ENABLED(CONFIG_ARCH_LS1028A))
+               return enetc_ls1028a_write_hwaddr(dev);
+
        u16 lower = *(const u16 *)(addr + 4);
        u32 upper = *(const u32 *)addr;