diff options
author | Andy Duan <fugang.duan@nxp.com> | 2017-03-14 11:23:10 +0800 |
---|---|---|
committer | Anson Huang <Anson.Huang@nxp.com> | 2017-06-09 22:17:09 +0800 |
commit | 87c65f3e62842ea392f83204adacb6781937c6a3 (patch) | |
tree | da0502cb60d0584bc535b11e5fcfcb29d41685ca /drivers/net/ethernet/freescale | |
parent | 60313655bdc3d0542e618cea10612bfefdb7c306 (diff) |
MLK-14438-01 net: fec: add FEC support for NXP i.MX8x chips
Add FEC support for NXP i.MX8x chips.
Signed-off-by: Fugang Duan <fugang.duan@nxp.com>
Diffstat (limited to 'drivers/net/ethernet/freescale')
-rw-r--r-- | drivers/net/ethernet/freescale/Kconfig | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/fec.h | 9 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/fec_main.c | 38 |
3 files changed, 34 insertions, 17 deletions
diff --git a/drivers/net/ethernet/freescale/Kconfig b/drivers/net/ethernet/freescale/Kconfig index d1ca45fbb164..2204c57fcc7d 100644 --- a/drivers/net/ethernet/freescale/Kconfig +++ b/drivers/net/ethernet/freescale/Kconfig @@ -22,8 +22,8 @@ if NET_VENDOR_FREESCALE config FEC tristate "FEC ethernet controller (of ColdFire and some i.MX CPUs)" depends on (M523x || M527x || M5272 || M528x || M520x || M532x || \ - ARCH_MXC || SOC_IMX28) - default ARCH_MXC || SOC_IMX28 if ARM + ARM || ARM64) + default y select PHYLIB select PTP_1588_CLOCK ---help--- diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index 2982850cfdc9..8048af973c35 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -20,7 +20,8 @@ #include <linux/timecounter.h> #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ - defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM) + defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM) || \ + defined(CONFIG_ARM64) /* * Just figures, Motorola would have to change the offsets for * registers in the same peripheral device on different models @@ -195,7 +196,7 @@ * Evidently, ARM SoCs have the FEC block generated in a * little endian mode so adjust endianness accordingly. */ -#if defined(CONFIG_ARM) +#if defined(CONFIG_ARM) || defined(CONFIG_ARM64) #define fec32_to_cpu le32_to_cpu #define fec16_to_cpu le16_to_cpu #define cpu_to_fec32 cpu_to_le32 @@ -293,7 +294,7 @@ struct bufdesc_ex { /* This device has up to three irqs on some platforms */ -#define FEC_IRQ_NUM 3 +#define FEC_IRQ_NUM 4 /* Maximum number of queues supported * ENET with AVB IP can support up to 3 independent tx queues and rx queues. @@ -456,7 +457,7 @@ struct bufdesc_ex { * interrupt signal don't connect to GPC. So use pm qos to avoid cpu enter * to wait mode. */ -#define FEC_QUIRK_BUG_WAITMODE (1 << 15) +#define FEC_QUIRK_BUG_WAITMODE (1 << 15) struct bufdesc_prop { int qid; diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index b06f4ab65690..e262819e24df 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -19,12 +19,13 @@ * Copyright (c) 2004-2006 Macq Electronique SA. * * Copyright (C) 2010-2014 Freescale Semiconductor, Inc. + * + * Copyright 2017 NXP */ #include <linux/module.h> #include <linux/kernel.h> #include <linux/string.h> -#include <linux/pm_runtime.h> #include <linux/ptrace.h> #include <linux/errno.h> #include <linux/ioport.h> @@ -47,6 +48,7 @@ #include <linux/io.h> #include <linux/irq.h> #include <linux/clk.h> +#include <linux/clk/clk-conf.h> #include <linux/platform_device.h> #include <linux/mdio.h> #include <linux/phy.h> @@ -62,11 +64,11 @@ #include <linux/pm_runtime.h> #include <linux/busfreq-imx.h> #include <linux/prefetch.h> -#include <soc/imx/cpuidle.h> #include <linux/mfd/syscon.h> #include <linux/regmap.h> #include <asm/cacheflush.h> +#include <soc/imx/cpuidle.h> #include "fec.h" @@ -125,10 +127,12 @@ static struct platform_device_id fec_devtype[] = { FEC_QUIRK_HAS_VLAN | FEC_QUIRK_BUG_CAPTURE | FEC_QUIRK_HAS_RACC | FEC_QUIRK_HAS_COALESCE, }, { - .name = "imx6ul-fec", + .name = "imx8qm-fec", .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT | FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM | - FEC_QUIRK_HAS_VLAN, + FEC_QUIRK_HAS_VLAN | FEC_QUIRK_HAS_AVB | + FEC_QUIRK_ERR007885 | FEC_QUIRK_BUG_CAPTURE | + FEC_QUIRK_HAS_RACC | FEC_QUIRK_HAS_COALESCE, }, { /* sentinel */ } @@ -143,6 +147,7 @@ enum imx_fec_type { MVF600_FEC, IMX6SX_FEC, IMX6UL_FEC, + IMX8QM_FEC, }; static const struct of_device_id fec_dt_ids[] = { @@ -153,6 +158,7 @@ static const struct of_device_id fec_dt_ids[] = { { .compatible = "fsl,mvf600-fec", .data = &fec_devtype[MVF600_FEC], }, { .compatible = "fsl,imx6sx-fec", .data = &fec_devtype[IMX6SX_FEC], }, { .compatible = "fsl,imx6ul-fec", .data = &fec_devtype[IMX6UL_FEC], }, + { .compatible = "fsl,imx8qm-fec", .data = &fec_devtype[IMX8QM_FEC], }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, fec_dt_ids); @@ -199,7 +205,8 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address"); * account when setting it. */ #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ - defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM) + defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM) || \ + defined(CONFIG_ARM64) #define OPT_FRAME_SIZE (PKT_MAXBUF_SIZE << 16) #else #define OPT_FRAME_SIZE 0 @@ -245,14 +252,14 @@ static struct bufdesc *fec_enet_get_nextdesc(struct bufdesc *bdp, struct bufdesc_prop *bd) { return (bdp >= bd->last) ? bd->base - : (struct bufdesc *)(((unsigned)bdp) + bd->dsize); + : (struct bufdesc *)(((void *)bdp) + bd->dsize); } static struct bufdesc *fec_enet_get_prevdesc(struct bufdesc *bdp, struct bufdesc_prop *bd) { return (bdp <= bd->base) ? bd->last - : (struct bufdesc *)(((unsigned)bdp) - bd->dsize); + : (struct bufdesc *)(((void *)bdp) - bd->dsize); } static int fec_enet_get_bd_index(struct bufdesc *bdp, @@ -2154,7 +2161,8 @@ static int fec_enet_get_regs_len(struct net_device *ndev) /* List of registers that can be safety be read to dump them with ethtool */ #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ - defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM) + defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM) || \ + defined(CONFIG_ARM64) static u32 fec_enet_register_offset[] = { FEC_IEVENT, FEC_IMASK, FEC_R_DES_ACTIVE_0, FEC_X_DES_ACTIVE_0, FEC_ECNTRL, FEC_MII_DATA, FEC_MII_SPEED, FEC_MIB_CTRLSTAT, FEC_R_CNTRL, @@ -2712,7 +2720,7 @@ static void fec_enet_free_queue(struct net_device *ndev) for (i = 0; i < fep->num_tx_queues; i++) if (fep->tx_queue[i] && fep->tx_queue[i]->tso_hdrs) { txq = fep->tx_queue[i]; - dma_free_coherent(NULL, + dma_free_coherent(&fep->pdev->dev, txq->bd.ring_size * TSO_HEADER_SIZE, txq->tso_hdrs, txq->tso_hdrs_dma); @@ -2746,7 +2754,7 @@ static int fec_enet_alloc_queue(struct net_device *ndev) txq->tx_wake_threshold = (txq->bd.ring_size - txq->tx_stop_threshold) / 2; - txq->tso_hdrs = dma_alloc_coherent(NULL, + txq->tso_hdrs = dma_alloc_coherent(&fep->pdev->dev, txq->bd.ring_size * TSO_HEADER_SIZE, &txq->tso_hdrs_dma, GFP_KERNEL); @@ -3225,7 +3233,7 @@ static int fec_enet_init(struct net_device *ndev) unsigned dsize_log2 = __fls(dsize); WARN_ON(dsize != (1 << dsize_log2)); -#if defined(CONFIG_ARM) +#if defined(CONFIG_ARM) || defined(CONFIG_ARM64) fep->rx_align = 0xf; fep->tx_align = 0xf; #else @@ -3447,6 +3455,8 @@ fec_probe(struct platform_device *pdev) int num_tx_qs; int num_rx_qs; + of_dma_configure(&pdev->dev, np); + fec_enet_get_queue_num(pdev, &num_tx_qs, &num_rx_qs); /* Init network device */ @@ -3523,7 +3533,9 @@ fec_probe(struct platform_device *pdev) fep->phy_interface = ret; } +#if !defined(CONFIG_ARM64) request_bus_freq(BUS_FREQ_HIGH); +#endif fep->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); if (IS_ERR(fep->clk_ipg)) { @@ -3791,7 +3803,9 @@ static int __maybe_unused fec_runtime_suspend(struct device *dev) struct fec_enet_private *fep = netdev_priv(ndev); clk_disable_unprepare(fep->clk_ipg); +#if !defined(CONFIG_ARM64) release_bus_freq(BUS_FREQ_HIGH); +#endif return 0; } @@ -3801,7 +3815,9 @@ static int __maybe_unused fec_runtime_resume(struct device *dev) struct net_device *ndev = dev_get_drvdata(dev); struct fec_enet_private *fep = netdev_priv(ndev); +#if !defined(CONFIG_ARM64) request_bus_freq(BUS_FREQ_HIGH); +#endif return clk_prepare_enable(fep->clk_ipg); } |