diff options
Diffstat (limited to 'drivers/net/ethernet/freescale/enetc')
-rw-r--r-- | drivers/net/ethernet/freescale/enetc/Kconfig | 9 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/enetc/Makefile | 19 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/enetc/enetc.c | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/enetc/enetc_mdio.c | 97 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/enetc/enetc_mdio.h | 12 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/enetc/enetc_pci_mdio.c | 101 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/enetc/enetc_pf.c | 5 |
7 files changed, 180 insertions, 65 deletions
diff --git a/drivers/net/ethernet/freescale/enetc/Kconfig b/drivers/net/ethernet/freescale/enetc/Kconfig index 04a59db03f2b..c219587bd334 100644 --- a/drivers/net/ethernet/freescale/enetc/Kconfig +++ b/drivers/net/ethernet/freescale/enetc/Kconfig @@ -20,6 +20,15 @@ config FSL_ENETC_VF If compiled as module (M), the module name is fsl-enetc-vf. +config FSL_ENETC_MDIO + tristate "ENETC MDIO driver" + depends on PCI && (ARCH_LAYERSCAPE || COMPILE_TEST) + help + This driver supports NXP ENETC Central MDIO controller as a PCIe + physical function (PF) device. + + If compiled as module (M), the module name is fsl-enetc-mdio. + config FSL_ENETC_PTP_CLOCK tristate "ENETC PTP clock driver" depends on PTP_1588_CLOCK_QORIQ && (FSL_ENETC || FSL_ENETC_VF) diff --git a/drivers/net/ethernet/freescale/enetc/Makefile b/drivers/net/ethernet/freescale/enetc/Makefile index 7139e414dccf..d200c27c3bf6 100644 --- a/drivers/net/ethernet/freescale/enetc/Makefile +++ b/drivers/net/ethernet/freescale/enetc/Makefile @@ -1,19 +1,16 @@ # SPDX-License-Identifier: GPL-2.0 + +common-objs := enetc.o enetc_cbdr.o enetc_ethtool.o + obj-$(CONFIG_FSL_ENETC) += fsl-enetc.o -fsl-enetc-$(CONFIG_FSL_ENETC) += enetc.o enetc_cbdr.o enetc_ethtool.o \ - enetc_mdio.o +fsl-enetc-y := enetc_pf.o enetc_mdio.o $(common-objs) fsl-enetc-$(CONFIG_PCI_IOV) += enetc_msg.o -fsl-enetc-objs := enetc_pf.o $(fsl-enetc-y) obj-$(CONFIG_FSL_ENETC_VF) += fsl-enetc-vf.o +fsl-enetc-vf-y := enetc_vf.o $(common-objs) -ifeq ($(CONFIG_FSL_ENETC)$(CONFIG_FSL_ENETC_VF), yy) -fsl-enetc-vf-objs := enetc_vf.o -else -fsl-enetc-vf-$(CONFIG_FSL_ENETC_VF) += enetc.o enetc_cbdr.o \ - enetc_ethtool.o -fsl-enetc-vf-objs := enetc_vf.o $(fsl-enetc-vf-y) -endif +obj-$(CONFIG_FSL_ENETC_MDIO) += fsl-enetc-mdio.o +fsl-enetc-mdio-y := enetc_pci_mdio.o enetc_mdio.o obj-$(CONFIG_FSL_ENETC_PTP_CLOCK) += fsl-enetc-ptp.o -fsl-enetc-ptp-$(CONFIG_FSL_ENETC_PTP_CLOCK) += enetc_ptp.o +fsl-enetc-ptp-y := enetc_ptp.o diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c index 223709443ea4..b6ff89307409 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc.c +++ b/drivers/net/ethernet/freescale/enetc/enetc.c @@ -110,7 +110,7 @@ static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb, int active_offloads) { struct enetc_tx_swbd *tx_swbd; - struct skb_frag_struct *frag; + skb_frag_t *frag; int len = skb_headlen(skb); union enetc_tx_bd temp_bd; union enetc_tx_bd *txbd; diff --git a/drivers/net/ethernet/freescale/enetc/enetc_mdio.c b/drivers/net/ethernet/freescale/enetc/enetc_mdio.c index 77b9cd10ba2b..149883c8f0b8 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_mdio.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_mdio.c @@ -6,18 +6,20 @@ #include <linux/iopoll.h> #include <linux/of.h> -#include "enetc_pf.h" +#include "enetc_mdio.h" -struct enetc_mdio_regs { - u32 mdio_cfg; /* MDIO configuration and status */ - u32 mdio_ctl; /* MDIO control */ - u32 mdio_data; /* MDIO data */ - u32 mdio_addr; /* MDIO address */ -}; +#define ENETC_MDIO_REG_OFFSET 0x1c00 +#define ENETC_MDIO_CFG 0x0 /* MDIO configuration and status */ +#define ENETC_MDIO_CTL 0x4 /* MDIO control */ +#define ENETC_MDIO_DATA 0x8 /* MDIO data */ +#define ENETC_MDIO_ADDR 0xc /* MDIO address */ -#define bus_to_enetc_regs(bus) (struct enetc_mdio_regs __iomem *)((bus)->priv) +#define enetc_mdio_rd(hw, off) \ + enetc_port_rd(hw, ENETC_##off + ENETC_MDIO_REG_OFFSET) +#define enetc_mdio_wr(hw, off, val) \ + enetc_port_wr(hw, ENETC_##off + ENETC_MDIO_REG_OFFSET, val) +#define enetc_mdio_rd_reg(off) enetc_mdio_rd(hw, off) -#define ENETC_MDIO_REG_OFFSET 0x1c00 #define ENETC_MDC_DIV 258 #define MDIO_CFG_CLKDIV(x) ((((x) >> 1) & 0xff) << 8) @@ -33,18 +35,18 @@ struct enetc_mdio_regs { #define MDIO_DATA(x) ((x) & 0xffff) #define TIMEOUT 1000 -static int enetc_mdio_wait_complete(struct enetc_mdio_regs __iomem *regs) +static int enetc_mdio_wait_complete(struct enetc_hw *hw) { u32 val; - return readx_poll_timeout(enetc_rd_reg, ®s->mdio_cfg, val, + return readx_poll_timeout(enetc_mdio_rd_reg, MDIO_CFG, val, !(val & MDIO_CFG_BSY), 10, 10 * TIMEOUT); } -static int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum, - u16 value) +int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 value) { - struct enetc_mdio_regs __iomem *regs = bus_to_enetc_regs(bus); + struct enetc_mdio_priv *mdio_priv = bus->priv; + struct enetc_hw *hw = mdio_priv->hw; u32 mdio_ctl, mdio_cfg; u16 dev_addr; int ret; @@ -59,38 +61,39 @@ static int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum, mdio_cfg &= ~MDIO_CFG_ENC45; } - enetc_wr_reg(®s->mdio_cfg, mdio_cfg); + enetc_mdio_wr(hw, MDIO_CFG, mdio_cfg); - ret = enetc_mdio_wait_complete(regs); + ret = enetc_mdio_wait_complete(hw); if (ret) return ret; /* set port and dev addr */ mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr); - enetc_wr_reg(®s->mdio_ctl, mdio_ctl); + enetc_mdio_wr(hw, MDIO_CTL, mdio_ctl); /* set the register address */ if (regnum & MII_ADDR_C45) { - enetc_wr_reg(®s->mdio_addr, regnum & 0xffff); + enetc_mdio_wr(hw, MDIO_ADDR, regnum & 0xffff); - ret = enetc_mdio_wait_complete(regs); + ret = enetc_mdio_wait_complete(hw); if (ret) return ret; } /* write the value */ - enetc_wr_reg(®s->mdio_data, MDIO_DATA(value)); + enetc_mdio_wr(hw, MDIO_DATA, MDIO_DATA(value)); - ret = enetc_mdio_wait_complete(regs); + ret = enetc_mdio_wait_complete(hw); if (ret) return ret; return 0; } -static int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum) +int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum) { - struct enetc_mdio_regs __iomem *regs = bus_to_enetc_regs(bus); + struct enetc_mdio_priv *mdio_priv = bus->priv; + struct enetc_hw *hw = mdio_priv->hw; u32 mdio_ctl, mdio_cfg; u16 dev_addr, value; int ret; @@ -104,41 +107,41 @@ static int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum) mdio_cfg &= ~MDIO_CFG_ENC45; } - enetc_wr_reg(®s->mdio_cfg, mdio_cfg); + enetc_mdio_wr(hw, MDIO_CFG, mdio_cfg); - ret = enetc_mdio_wait_complete(regs); + ret = enetc_mdio_wait_complete(hw); if (ret) return ret; /* set port and device addr */ mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr); - enetc_wr_reg(®s->mdio_ctl, mdio_ctl); + enetc_mdio_wr(hw, MDIO_CTL, mdio_ctl); /* set the register address */ if (regnum & MII_ADDR_C45) { - enetc_wr_reg(®s->mdio_addr, regnum & 0xffff); + enetc_mdio_wr(hw, MDIO_ADDR, regnum & 0xffff); - ret = enetc_mdio_wait_complete(regs); + ret = enetc_mdio_wait_complete(hw); if (ret) return ret; } /* initiate the read */ - enetc_wr_reg(®s->mdio_ctl, mdio_ctl | MDIO_CTL_READ); + enetc_mdio_wr(hw, MDIO_CTL, mdio_ctl | MDIO_CTL_READ); - ret = enetc_mdio_wait_complete(regs); + ret = enetc_mdio_wait_complete(hw); if (ret) return ret; /* return all Fs if nothing was there */ - if (enetc_rd_reg(®s->mdio_cfg) & MDIO_CFG_RD_ER) { + if (enetc_mdio_rd(hw, MDIO_CFG) & MDIO_CFG_RD_ER) { dev_dbg(&bus->dev, "Error while reading PHY%d reg at %d.%hhu\n", phy_id, dev_addr, regnum); return 0xffff; } - value = enetc_rd_reg(®s->mdio_data) & 0xffff; + value = enetc_mdio_rd(hw, MDIO_DATA) & 0xffff; return value; } @@ -146,12 +149,12 @@ static int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum) int enetc_mdio_probe(struct enetc_pf *pf) { struct device *dev = &pf->si->pdev->dev; - struct enetc_mdio_regs __iomem *regs; + struct enetc_mdio_priv *mdio_priv; struct device_node *np; struct mii_bus *bus; - int ret; + int err; - bus = mdiobus_alloc_size(sizeof(regs)); + bus = devm_mdiobus_alloc_size(dev, sizeof(*mdio_priv)); if (!bus) return -ENOMEM; @@ -159,41 +162,31 @@ int enetc_mdio_probe(struct enetc_pf *pf) bus->read = enetc_mdio_read; bus->write = enetc_mdio_write; bus->parent = dev; + mdio_priv = bus->priv; + mdio_priv->hw = &pf->si->hw; snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev)); - /* store the enetc mdio base address for this bus */ - regs = pf->si->hw.port + ENETC_MDIO_REG_OFFSET; - bus->priv = regs; - np = of_get_child_by_name(dev->of_node, "mdio"); if (!np) { dev_err(dev, "MDIO node missing\n"); - ret = -EINVAL; - goto err_registration; + return -EINVAL; } - ret = of_mdiobus_register(bus, np); - if (ret) { + err = of_mdiobus_register(bus, np); + if (err) { of_node_put(np); dev_err(dev, "cannot register MDIO bus\n"); - goto err_registration; + return err; } of_node_put(np); pf->mdio = bus; return 0; - -err_registration: - mdiobus_free(bus); - - return ret; } void enetc_mdio_remove(struct enetc_pf *pf) { - if (pf->mdio) { + if (pf->mdio) mdiobus_unregister(pf->mdio); - mdiobus_free(pf->mdio); - } } diff --git a/drivers/net/ethernet/freescale/enetc/enetc_mdio.h b/drivers/net/ethernet/freescale/enetc/enetc_mdio.h new file mode 100644 index 000000000000..60c9a3889824 --- /dev/null +++ b/drivers/net/ethernet/freescale/enetc/enetc_mdio.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ +/* Copyright 2019 NXP */ + +#include <linux/phy.h> +#include "enetc_pf.h" + +struct enetc_mdio_priv { + struct enetc_hw *hw; +}; + +int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 value); +int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum); diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pci_mdio.c b/drivers/net/ethernet/freescale/enetc/enetc_pci_mdio.c new file mode 100644 index 000000000000..fbd41ce01f06 --- /dev/null +++ b/drivers/net/ethernet/freescale/enetc/enetc_pci_mdio.c @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* Copyright 2019 NXP */ +#include <linux/of_mdio.h> +#include "enetc_mdio.h" + +#define ENETC_MDIO_DEV_ID 0xee01 +#define ENETC_MDIO_DEV_NAME "FSL PCIe IE Central MDIO" +#define ENETC_MDIO_BUS_NAME ENETC_MDIO_DEV_NAME " Bus" +#define ENETC_MDIO_DRV_NAME ENETC_MDIO_DEV_NAME " driver" + +static int enetc_pci_mdio_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct enetc_mdio_priv *mdio_priv; + struct device *dev = &pdev->dev; + struct enetc_hw *hw; + struct mii_bus *bus; + int err; + + hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL); + if (!hw) + return -ENOMEM; + + bus = devm_mdiobus_alloc_size(dev, sizeof(*mdio_priv)); + if (!bus) + return -ENOMEM; + + bus->name = ENETC_MDIO_BUS_NAME; + bus->read = enetc_mdio_read; + bus->write = enetc_mdio_write; + bus->parent = dev; + mdio_priv = bus->priv; + mdio_priv->hw = hw; + snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev)); + + pcie_flr(pdev); + err = pci_enable_device_mem(pdev); + if (err) { + dev_err(dev, "device enable failed\n"); + return err; + } + + err = pci_request_region(pdev, 0, KBUILD_MODNAME); + if (err) { + dev_err(dev, "pci_request_region failed\n"); + goto err_pci_mem_reg; + } + + hw->port = pci_iomap(pdev, 0, 0); + if (!hw->port) { + err = -ENXIO; + dev_err(dev, "iomap failed\n"); + goto err_ioremap; + } + + err = of_mdiobus_register(bus, dev->of_node); + if (err) + goto err_mdiobus_reg; + + pci_set_drvdata(pdev, bus); + + return 0; + +err_mdiobus_reg: + iounmap(mdio_priv->hw->port); +err_ioremap: + pci_release_mem_regions(pdev); +err_pci_mem_reg: + pci_disable_device(pdev); + + return err; +} + +static void enetc_pci_mdio_remove(struct pci_dev *pdev) +{ + struct mii_bus *bus = pci_get_drvdata(pdev); + struct enetc_mdio_priv *mdio_priv; + + mdiobus_unregister(bus); + mdio_priv = bus->priv; + iounmap(mdio_priv->hw->port); + pci_release_mem_regions(pdev); + pci_disable_device(pdev); +} + +static const struct pci_device_id enetc_pci_mdio_id_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_MDIO_DEV_ID) }, + { 0, } /* End of table. */ +}; +MODULE_DEVICE_TABLE(pci, enetc_pci_mdio_id_table); + +static struct pci_driver enetc_pci_mdio_driver = { + .name = KBUILD_MODNAME, + .id_table = enetc_pci_mdio_id_table, + .probe = enetc_pci_mdio_probe, + .remove = enetc_pci_mdio_remove, +}; +module_pci_driver(enetc_pci_mdio_driver); + +MODULE_DESCRIPTION(ENETC_MDIO_DRV_NAME); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c index 258b3cb38a6f..7d6513ff8507 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c @@ -750,6 +750,7 @@ static int enetc_of_get_phy(struct enetc_ndev_priv *priv) { struct enetc_pf *pf = enetc_si_priv(priv->si); struct device_node *np = priv->dev->of_node; + struct device_node *mdio_np; int err; if (!np) { @@ -773,7 +774,9 @@ static int enetc_of_get_phy(struct enetc_ndev_priv *priv) priv->phy_node = of_node_get(np); } - if (!of_phy_is_fixed_link(np)) { + mdio_np = of_get_child_by_name(np, "mdio"); + if (mdio_np) { + of_node_put(mdio_np); err = enetc_mdio_probe(pf); if (err) { of_node_put(priv->phy_node); |