drivers: net: fsl_enetc: add write_hwaddr() for LS1028A
[oweals/u-boot.git] / drivers / net / fsl_enetc.c
index f8fe7d4d8d75a83c02a6b8c3ad05bec6335263cf..2ffab1bb148e93fc8fb34b61e6bad79cd3371d3b 100644 (file)
@@ -330,14 +330,57 @@ static int enetc_remove(struct udevice *dev)
        return 0;
 }
 
-/* ENETC Port MAC address registers, accepts big-endian format */
-static void enetc_set_primary_mac_addr(struct enetc_priv *priv, const u8 *addr)
+/*
+ * 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;
 
        enetc_write_port(priv, ENETC_PSIPMAR0, upper);
        enetc_write_port(priv, ENETC_PSIPMAR1, lower);
+
+       return 0;
 }
 
 /* Configure port parameters (# of rings, frame size, enable port) */
@@ -468,7 +511,6 @@ static void enetc_setup_rx_bdr(struct udevice *dev)
  */
 static int enetc_start(struct udevice *dev)
 {
-       struct eth_pdata *plat = dev_get_platdata(dev);
        struct enetc_priv *priv = dev_get_priv(dev);
 
        /* reset and enable the PCI device */
@@ -476,12 +518,6 @@ static int enetc_start(struct udevice *dev)
        dm_pci_clrset_config16(dev, PCI_COMMAND, 0,
                               PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
 
-       if (!is_valid_ethaddr(plat->enetaddr)) {
-               enetc_dbg(dev, "invalid MAC address, generate random ...\n");
-               net_random_ethaddr(plat->enetaddr);
-       }
-       enetc_set_primary_mac_addr(priv, plat->enetaddr);
-
        enetc_enable_si_port(priv);
 
        /* setup Tx/Rx buffer descriptors */
@@ -611,6 +647,7 @@ static const struct eth_ops enetc_ops = {
        .send   = enetc_send,
        .recv   = enetc_recv,
        .stop   = enetc_stop,
+       .write_hwaddr = enetc_write_hwaddr,
 };
 
 U_BOOT_DRIVER(eth_enetc) = {