aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/fsl_enetc.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/drivers/net/fsl_enetc.c b/drivers/net/fsl_enetc.c
index 7c0ed9f6065..2ffab1bb148 100644
--- a/drivers/net/fsl_enetc.c
+++ b/drivers/net/fsl_enetc.c
@@ -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;