summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/freescale
diff options
context:
space:
mode:
authorAndy Duan <fugang.duan@nxp.com>2017-03-14 11:23:10 +0800
committerAnson Huang <Anson.Huang@nxp.com>2017-06-09 22:17:09 +0800
commit87c65f3e62842ea392f83204adacb6781937c6a3 (patch)
treeda0502cb60d0584bc535b11e5fcfcb29d41685ca /drivers/net/ethernet/freescale
parent60313655bdc3d0542e618cea10612bfefdb7c306 (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/Kconfig4
-rw-r--r--drivers/net/ethernet/freescale/fec.h9
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c38
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);
}