diff options
author | Fugang Duan <fugang.duan@nxp.com> | 2017-07-12 14:49:45 +0800 |
---|---|---|
committer | Leonard Crestez <leonard.crestez@nxp.com> | 2018-08-24 12:41:33 +0300 |
commit | 2aa81fdffca8731d67695006385cf5b1b68e2deb (patch) | |
tree | 22733ba03c857af880e25bcd96be3a92c65a42b2 /drivers/net/ethernet/freescale | |
parent | 36eae80ee9b77db9a5aefbfdfefb0dd4c5579411 (diff) |
MLK-16022 net: fec: get mac address from fuse
i.MX8QM/QXP MAC address only can be program by SCU, and A core
read fuse enet MAC address by sc APIs interface. i.MX8mScale is
inherited from i.MX7D, can directly read fuse in A-core.
Add i.MX8QM/QXP/MQ ENET MAC address check from fuse.
Signed-off-by: Fugang Duan <fugang.duan@nxp.com>
Diffstat (limited to 'drivers/net/ethernet/freescale')
-rw-r--r-- | drivers/net/ethernet/freescale/fec.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/fec_fixup.c | 114 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/fec_main.c | 10 |
3 files changed, 123 insertions, 2 deletions
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index 1d7b3cc115e4..e5756bd24599 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -615,6 +615,7 @@ int fec_ptp_get(struct net_device *ndev, struct ifreq *ifr); uint fec_ptp_check_pps_event(struct fec_enet_private *fep); void fec_enet_register_fixup(struct net_device *ndev); int of_fec_enet_parse_fixup(struct device_node *np); +void fec_enet_get_mac_from_fuse(struct device_node *np, unsigned char *mac); /****************************************************************************/ #endif /* FEC_H */ diff --git a/drivers/net/ethernet/freescale/fec_fixup.c b/drivers/net/ethernet/freescale/fec_fixup.c index 5a8497c22acd..da9e03d150e7 100644 --- a/drivers/net/ethernet/freescale/fec_fixup.c +++ b/drivers/net/ethernet/freescale/fec_fixup.c @@ -14,10 +14,22 @@ #include <linux/netdevice.h> #include <linux/phy.h> +#include <linux/of.h> +#include <linux/of_address.h> +#ifdef CONFIG_ARCH_MXC_ARM64 +#include <soc/imx8/sc/sci.h> +#endif #include "fec.h" #define PHY_ID_AR8031 0x004dd074 +#define IMX8QM_FUSE_MAC0_WORD0 452 +#define IMX8QM_FUSE_MAC0_WORD1 453 +#define IMX8QM_FUSE_MAC1_WORD0 454 +#define IMX8QM_FUSE_MAC1_WORD1 455 +#define IMX8M_OCOTP_MAC_ADDR0_OFF 0x640 +#define IMX8M_OCOTP_MAC_ADDR1_OFF 0x650 + static int ar8031_phy_fixup(struct phy_device *dev) { u16 val; @@ -72,3 +84,105 @@ int of_fec_enet_parse_fixup(struct device_node *np) return fixups; } + +static void imx8mq_get_mac_from_fuse(int dev_id, unsigned char *mac) +{ + struct device_node *ocotp_np; + void __iomem *base; + u32 value; + + ocotp_np = of_find_compatible_node(NULL, NULL, "fsl,imx7d-ocotp"); + if (!ocotp_np) { + pr_warn("failed to find ocotp node\n"); + return; + } + + base = of_iomap(ocotp_np, 0); + if (!base) { + pr_warn("failed to map ocotp\n"); + goto put_ocotp_node; + } + + value = readl_relaxed(base + IMX8M_OCOTP_MAC_ADDR1_OFF); + mac[0] = (value >> 8); + mac[1] = value; + + value = readl_relaxed(base + IMX8M_OCOTP_MAC_ADDR0_OFF); + mac[2] = value >> 24; + mac[3] = value >> 16; + mac[4] = value >> 8; + mac[5] = value; + +put_ocotp_node: + of_node_put(ocotp_np); +} + +#ifdef CONFIG_ARCH_MXC_ARM64 +static void imx8qm_get_mac_from_fuse(int dev_id, unsigned char *mac) +{ + uint32_t mu_id; + sc_ipc_t ipc_handle; + sc_err_t sc_err = SC_ERR_NONE; + uint32_t val1 = 0, val2 = 0; + uint32_t word1, word2; + + sc_err = sc_ipc_getMuID(&mu_id); + if (sc_err != SC_ERR_NONE) { + pr_err("FEC MAC fuse: Get MU ID failed\n"); + return; + } + + sc_err = sc_ipc_open(&ipc_handle, mu_id); + if (sc_err != SC_ERR_NONE) { + pr_err("FEC MAC fuse: Open MU channel failed\n"); + return; + } + + if (dev_id == 0) { + word1 = IMX8QM_FUSE_MAC0_WORD0; + word2 = IMX8QM_FUSE_MAC0_WORD1; + } else { + word1 = IMX8QM_FUSE_MAC1_WORD0; + word2 = IMX8QM_FUSE_MAC1_WORD1; + } + + sc_err = sc_misc_otp_fuse_read(ipc_handle, word1, &val1); + if (sc_err != SC_ERR_NONE) { + pr_err("FEC MAC fuse %d read error: %d\n", word1, sc_err); + return; + } + + sc_err = sc_misc_otp_fuse_read(ipc_handle, word2, &val2); + if (sc_err != SC_ERR_NONE) { + pr_err("FEC MAC fuse %d read error: %d\n", word2, sc_err); + return; + } + + mac[0] = val1; + mac[1] = val1 >> 8; + mac[2] = val1 >> 16; + mac[3] = val1 >> 24; + mac[4] = val2; + mac[5] = val2 >> 8; +} +#else +static void imx8qm_get_mac_from_fuse(int dev_id, unsigned char *mac) {} +#endif + +void fec_enet_get_mac_from_fuse(struct device_node *np, unsigned char *mac) +{ + int idx; + + if (!np) + return; + + idx = of_alias_get_id(np, "ethernet"); + if (idx < 0) + idx = 0; + + if (of_machine_is_compatible("fsl,imx8qm") || + of_machine_is_compatible("fsl,imx8qxp")) + imx8qm_get_mac_from_fuse(idx, mac); + else if (of_machine_is_compatible("fsl,imx8mq")) + imx8mq_get_mac_from_fuse(idx, mac); +} diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 94839678bac1..3230ff613b1c 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -1685,7 +1685,7 @@ static void fec_get_mac(struct net_device *ndev) { struct fec_enet_private *fep = netdev_priv(ndev); struct fec_platform_data *pdata = dev_get_platdata(&fep->pdev->dev); - unsigned char *iap, tmpaddr[ETH_ALEN]; + unsigned char *iap, tmpaddr[ETH_ALEN] = {0}; /* * try to get mac address in following order: @@ -1715,8 +1715,14 @@ static void fec_get_mac(struct net_device *ndev) if (FEC_FLASHMAC) iap = (unsigned char *)FEC_FLASHMAC; #else - if (pdata) + if (pdata) { iap = (unsigned char *)&pdata->mac; + } else { + struct device_node *np = fep->pdev->dev.of_node; + + fec_enet_get_mac_from_fuse(np, tmpaddr); + iap = &tmpaddr[0]; + } #endif } |