diff options
Diffstat (limited to 'drivers/net/phy')
26 files changed, 1 insertions, 5081 deletions
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index c69cc806f064..20252d7487db 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -3,240 +3,6 @@ # PHY Layer Configuration # -menuconfig MDIO_DEVICE - tristate "MDIO bus device drivers" - help - MDIO devices and driver infrastructure code. - -if MDIO_DEVICE - -config MDIO_BUS - tristate - default m if PHYLIB=m - default MDIO_DEVICE - help - This internal symbol is used for link time dependencies and it - reflects whether the mdio_bus/mdio_device code is built as a - loadable module or built-in. - -if MDIO_BUS - -config MDIO_DEVRES - tristate - -config MDIO_ASPEED - tristate "ASPEED MDIO bus controller" - depends on ARCH_ASPEED || COMPILE_TEST - depends on OF_MDIO && HAS_IOMEM - help - This module provides a driver for the independent MDIO bus - controllers found in the ASPEED AST2600 SoC. This is a driver for the - third revision of the ASPEED MDIO register interface - the first two - revisions are the "old" and "new" interfaces found in the AST2400 and - AST2500, embedded in the MAC. For legacy reasons, FTGMAC100 driver - continues to drive the embedded MDIO controller for the AST2400 and - AST2500 SoCs, so say N if AST2600 support is not required. - -config MDIO_BCM_IPROC - tristate "Broadcom iProc MDIO bus controller" - depends on ARCH_BCM_IPROC || COMPILE_TEST - depends on HAS_IOMEM && OF_MDIO - default ARCH_BCM_IPROC - help - This module provides a driver for the MDIO busses found in the - Broadcom iProc SoC's. - -config MDIO_BCM_UNIMAC - tristate "Broadcom UniMAC MDIO bus controller" - depends on HAS_IOMEM - help - This module provides a driver for the Broadcom UniMAC MDIO busses. - This hardware can be found in the Broadcom GENET Ethernet MAC - controllers as well as some Broadcom Ethernet switches such as the - Starfighter 2 switches. - -config MDIO_BITBANG - tristate "Bitbanged MDIO buses" - help - This module implements the MDIO bus protocol in software, - for use by low level drivers that export the ability to - drive the relevant pins. - - If in doubt, say N. - -config MDIO_BUS_MUX - tristate - depends on OF_MDIO - help - This module provides a driver framework for MDIO bus - multiplexers which connect one of several child MDIO busses - to a parent bus. Switching between child busses is done by - device specific drivers. - -config MDIO_BUS_MUX_BCM_IPROC - tristate "Broadcom iProc based MDIO bus multiplexers" - depends on OF && OF_MDIO && (ARCH_BCM_IPROC || COMPILE_TEST) - select MDIO_BUS_MUX - default ARCH_BCM_IPROC - help - This module provides a driver for MDIO bus multiplexers found in - iProc based Broadcom SoCs. This multiplexer connects one of several - child MDIO bus to a parent bus. Buses could be internal as well as - external and selection logic lies inside the same multiplexer. - -config MDIO_BUS_MUX_GPIO - tristate "GPIO controlled MDIO bus multiplexers" - depends on OF_GPIO && OF_MDIO - select MDIO_BUS_MUX - help - This module provides a driver for MDIO bus multiplexers that - are controlled via GPIO lines. The multiplexer connects one of - several child MDIO busses to a parent bus. Child bus - selection is under the control of GPIO lines. - -config MDIO_BUS_MUX_MESON_G12A - tristate "Amlogic G12a based MDIO bus multiplexer" - depends on ARCH_MESON || COMPILE_TEST - depends on OF_MDIO && HAS_IOMEM && COMMON_CLK - select MDIO_BUS_MUX - default m if ARCH_MESON - help - This module provides a driver for the MDIO multiplexer/glue of - the amlogic g12a SoC. The multiplexers connects either the external - or the internal MDIO bus to the parent bus. - -config MDIO_BUS_MUX_MMIOREG - tristate "MMIO device-controlled MDIO bus multiplexers" - depends on OF_MDIO && HAS_IOMEM - select MDIO_BUS_MUX - help - This module provides a driver for MDIO bus multiplexers that - are controlled via a simple memory-mapped device, like an FPGA. - The multiplexer connects one of several child MDIO busses to a - parent bus. Child bus selection is under the control of one of - the FPGA's registers. - - Currently, only 8/16/32 bits registers are supported. - -config MDIO_BUS_MUX_MULTIPLEXER - tristate "MDIO bus multiplexer using kernel multiplexer subsystem" - depends on OF_MDIO - select MULTIPLEXER - select MDIO_BUS_MUX - help - This module provides a driver for MDIO bus multiplexer - that is controlled via the kernel multiplexer subsystem. The - bus multiplexer connects one of several child MDIO busses to - a parent bus. Child bus selection is under the control of - the kernel multiplexer subsystem. - -config MDIO_CAVIUM - tristate - -config MDIO_GPIO - tristate "GPIO lib-based bitbanged MDIO buses" - depends on MDIO_BITBANG - depends on GPIOLIB || COMPILE_TEST - help - Supports GPIO lib-based MDIO busses. - - To compile this driver as a module, choose M here: the module - will be called mdio-gpio. - -config MDIO_HISI_FEMAC - tristate "Hisilicon FEMAC MDIO bus controller" - depends on HAS_IOMEM && OF_MDIO - help - This module provides a driver for the MDIO busses found in the - Hisilicon SoC that have an Fast Ethernet MAC. - -config MDIO_I2C - tristate - depends on I2C - help - Support I2C based PHYs. This provides a MDIO bus bridged - to I2C to allow PHYs connected in I2C mode to be accessed - using the existing infrastructure. - - This is library mode. - -config MDIO_IPQ4019 - tristate "Qualcomm IPQ4019 MDIO interface support" - depends on HAS_IOMEM && OF_MDIO - help - This driver supports the MDIO interface found in Qualcomm - IPQ40xx series Soc-s. - -config MDIO_IPQ8064 - tristate "Qualcomm IPQ8064 MDIO interface support" - depends on HAS_IOMEM && OF_MDIO - depends on MFD_SYSCON - help - This driver supports the MDIO interface found in the network - interface units of the IPQ8064 SoC - -config MDIO_MOXART - tristate "MOXA ART MDIO interface support" - depends on ARCH_MOXART || COMPILE_TEST - help - This driver supports the MDIO interface found in the network - interface units of the MOXA ART SoC - -config MDIO_MSCC_MIIM - tristate "Microsemi MIIM interface support" - depends on HAS_IOMEM - select MDIO_DEVRES - help - This driver supports the MIIM (MDIO) interface found in the network - switches of the Microsemi SoCs; it is recommended to switch on - CONFIG_HIGH_RES_TIMERS - -config MDIO_MVUSB - tristate "Marvell USB to MDIO Adapter" - depends on USB - select MDIO_DEVRES - help - A USB to MDIO converter present on development boards for - Marvell's Link Street family of Ethernet switches. - -config MDIO_OCTEON - tristate "Octeon and some ThunderX SOCs MDIO buses" - depends on (64BIT && OF_MDIO) || COMPILE_TEST - depends on HAS_IOMEM - select MDIO_CAVIUM - help - This module provides a driver for the Octeon and ThunderX MDIO - buses. It is required by the Octeon and ThunderX ethernet device - drivers on some systems. - -config MDIO_SUN4I - tristate "Allwinner sun4i MDIO interface support" - depends on ARCH_SUNXI || COMPILE_TEST - help - This driver supports the MDIO interface found in the network - interface units of the Allwinner SoC that have an EMAC (A10, - A12, A10s, etc.) - -config MDIO_THUNDER - tristate "ThunderX SOCs MDIO buses" - depends on 64BIT - depends on PCI - select MDIO_CAVIUM - help - This driver supports the MDIO interfaces found on Cavium - ThunderX SoCs when the MDIO bus device appears as a PCI - device. - -config MDIO_XGENE - tristate "APM X-Gene SoC MDIO bus controller" - depends on ARCH_XGENE || COMPILE_TEST - help - This module provides a driver for the MDIO busses found in the - APM X-Gene SoC's. - -endif -endif - config PHYLINK tristate depends on NETDEVICES diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 7cd8a0d1c0d0..3d83b648e3f0 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -# Makefile for Linux PHY drivers and MDIO bus drivers +# Makefile for Linux PHY drivers libphy-y := phy.o phy-c45.o phy-core.o phy_device.o \ linkmode.o @@ -24,30 +24,6 @@ libphy-$(CONFIG_LED_TRIGGER_PHY) += phy_led_triggers.o obj-$(CONFIG_PHYLINK) += phylink.o obj-$(CONFIG_PHYLIB) += libphy.o -obj-$(CONFIG_MDIO_ASPEED) += mdio-aspeed.o -obj-$(CONFIG_MDIO_BCM_IPROC) += mdio-bcm-iproc.o -obj-$(CONFIG_MDIO_BCM_UNIMAC) += mdio-bcm-unimac.o -obj-$(CONFIG_MDIO_BITBANG) += mdio-bitbang.o -obj-$(CONFIG_MDIO_BUS_MUX) += mdio-mux.o -obj-$(CONFIG_MDIO_BUS_MUX_BCM_IPROC) += mdio-mux-bcm-iproc.o -obj-$(CONFIG_MDIO_BUS_MUX_GPIO) += mdio-mux-gpio.o -obj-$(CONFIG_MDIO_BUS_MUX_MESON_G12A) += mdio-mux-meson-g12a.o -obj-$(CONFIG_MDIO_BUS_MUX_MMIOREG) += mdio-mux-mmioreg.o -obj-$(CONFIG_MDIO_BUS_MUX_MULTIPLEXER) += mdio-mux-multiplexer.o -obj-$(CONFIG_MDIO_CAVIUM) += mdio-cavium.o -obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o -obj-$(CONFIG_MDIO_HISI_FEMAC) += mdio-hisi-femac.o -obj-$(CONFIG_MDIO_I2C) += mdio-i2c.o -obj-$(CONFIG_MDIO_IPQ4019) += mdio-ipq4019.o -obj-$(CONFIG_MDIO_IPQ8064) += mdio-ipq8064.o -obj-$(CONFIG_MDIO_MOXART) += mdio-moxart.o -obj-$(CONFIG_MDIO_MSCC_MIIM) += mdio-mscc-miim.o -obj-$(CONFIG_MDIO_MVUSB) += mdio-mvusb.o -obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o -obj-$(CONFIG_MDIO_SUN4I) += mdio-sun4i.o -obj-$(CONFIG_MDIO_THUNDER) += mdio-thunder.o -obj-$(CONFIG_MDIO_XGENE) += mdio-xgene.o - obj-$(CONFIG_NETWORK_PHY_TIMESTAMPING) += mii_timestamper.o obj-$(CONFIG_SFP) += sfp.o diff --git a/drivers/net/phy/mdio-aspeed.c b/drivers/net/phy/mdio-aspeed.c deleted file mode 100644 index cad820568f75..000000000000 --- a/drivers/net/phy/mdio-aspeed.c +++ /dev/null @@ -1,157 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* Copyright (C) 2019 IBM Corp. */ - -#include <linux/bitfield.h> -#include <linux/delay.h> -#include <linux/iopoll.h> -#include <linux/mdio.h> -#include <linux/module.h> -#include <linux/of.h> -#include <linux/of_mdio.h> -#include <linux/phy.h> -#include <linux/platform_device.h> - -#define DRV_NAME "mdio-aspeed" - -#define ASPEED_MDIO_CTRL 0x0 -#define ASPEED_MDIO_CTRL_FIRE BIT(31) -#define ASPEED_MDIO_CTRL_ST BIT(28) -#define ASPEED_MDIO_CTRL_ST_C45 0 -#define ASPEED_MDIO_CTRL_ST_C22 1 -#define ASPEED_MDIO_CTRL_OP GENMASK(27, 26) -#define MDIO_C22_OP_WRITE 0b01 -#define MDIO_C22_OP_READ 0b10 -#define ASPEED_MDIO_CTRL_PHYAD GENMASK(25, 21) -#define ASPEED_MDIO_CTRL_REGAD GENMASK(20, 16) -#define ASPEED_MDIO_CTRL_MIIWDATA GENMASK(15, 0) - -#define ASPEED_MDIO_DATA 0x4 -#define ASPEED_MDIO_DATA_MDC_THRES GENMASK(31, 24) -#define ASPEED_MDIO_DATA_MDIO_EDGE BIT(23) -#define ASPEED_MDIO_DATA_MDIO_LATCH GENMASK(22, 20) -#define ASPEED_MDIO_DATA_IDLE BIT(16) -#define ASPEED_MDIO_DATA_MIIRDATA GENMASK(15, 0) - -#define ASPEED_MDIO_INTERVAL_US 100 -#define ASPEED_MDIO_TIMEOUT_US (ASPEED_MDIO_INTERVAL_US * 10) - -struct aspeed_mdio { - void __iomem *base; -}; - -static int aspeed_mdio_read(struct mii_bus *bus, int addr, int regnum) -{ - struct aspeed_mdio *ctx = bus->priv; - u32 ctrl; - u32 data; - int rc; - - dev_dbg(&bus->dev, "%s: addr: %d, regnum: %d\n", __func__, addr, - regnum); - - /* Just clause 22 for the moment */ - if (regnum & MII_ADDR_C45) - return -EOPNOTSUPP; - - ctrl = ASPEED_MDIO_CTRL_FIRE - | FIELD_PREP(ASPEED_MDIO_CTRL_ST, ASPEED_MDIO_CTRL_ST_C22) - | FIELD_PREP(ASPEED_MDIO_CTRL_OP, MDIO_C22_OP_READ) - | FIELD_PREP(ASPEED_MDIO_CTRL_PHYAD, addr) - | FIELD_PREP(ASPEED_MDIO_CTRL_REGAD, regnum); - - iowrite32(ctrl, ctx->base + ASPEED_MDIO_CTRL); - - rc = readl_poll_timeout(ctx->base + ASPEED_MDIO_DATA, data, - data & ASPEED_MDIO_DATA_IDLE, - ASPEED_MDIO_INTERVAL_US, - ASPEED_MDIO_TIMEOUT_US); - if (rc < 0) - return rc; - - return FIELD_GET(ASPEED_MDIO_DATA_MIIRDATA, data); -} - -static int aspeed_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val) -{ - struct aspeed_mdio *ctx = bus->priv; - u32 ctrl; - - dev_dbg(&bus->dev, "%s: addr: %d, regnum: %d, val: 0x%x\n", - __func__, addr, regnum, val); - - /* Just clause 22 for the moment */ - if (regnum & MII_ADDR_C45) - return -EOPNOTSUPP; - - ctrl = ASPEED_MDIO_CTRL_FIRE - | FIELD_PREP(ASPEED_MDIO_CTRL_ST, ASPEED_MDIO_CTRL_ST_C22) - | FIELD_PREP(ASPEED_MDIO_CTRL_OP, MDIO_C22_OP_WRITE) - | FIELD_PREP(ASPEED_MDIO_CTRL_PHYAD, addr) - | FIELD_PREP(ASPEED_MDIO_CTRL_REGAD, regnum) - | FIELD_PREP(ASPEED_MDIO_CTRL_MIIWDATA, val); - - iowrite32(ctrl, ctx->base + ASPEED_MDIO_CTRL); - - return readl_poll_timeout(ctx->base + ASPEED_MDIO_CTRL, ctrl, - !(ctrl & ASPEED_MDIO_CTRL_FIRE), - ASPEED_MDIO_INTERVAL_US, - ASPEED_MDIO_TIMEOUT_US); -} - -static int aspeed_mdio_probe(struct platform_device *pdev) -{ - struct aspeed_mdio *ctx; - struct mii_bus *bus; - int rc; - - bus = devm_mdiobus_alloc_size(&pdev->dev, sizeof(*ctx)); - if (!bus) - return -ENOMEM; - - ctx = bus->priv; - ctx->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(ctx->base)) - return PTR_ERR(ctx->base); - - bus->name = DRV_NAME; - snprintf(bus->id, MII_BUS_ID_SIZE, "%s%d", pdev->name, pdev->id); - bus->parent = &pdev->dev; - bus->read = aspeed_mdio_read; - bus->write = aspeed_mdio_write; - - rc = of_mdiobus_register(bus, pdev->dev.of_node); - if (rc) { - dev_err(&pdev->dev, "Cannot register MDIO bus!\n"); - return rc; - } - - platform_set_drvdata(pdev, bus); - - return 0; -} - -static int aspeed_mdio_remove(struct platform_device *pdev) -{ - mdiobus_unregister(platform_get_drvdata(pdev)); - - return 0; -} - -static const struct of_device_id aspeed_mdio_of_match[] = { - { .compatible = "aspeed,ast2600-mdio", }, - { }, -}; - -static struct platform_driver aspeed_mdio_driver = { - .driver = { - .name = DRV_NAME, - .of_match_table = aspeed_mdio_of_match, - }, - .probe = aspeed_mdio_probe, - .remove = aspeed_mdio_remove, -}; - -module_platform_driver(aspeed_mdio_driver); - -MODULE_AUTHOR("Andrew Jeffery <andrew@aj.id.au>"); -MODULE_LICENSE("GPL"); diff --git a/drivers/net/phy/mdio-bcm-iproc.c b/drivers/net/phy/mdio-bcm-iproc.c deleted file mode 100644 index 77fc970cdfde..000000000000 --- a/drivers/net/phy/mdio-bcm-iproc.c +++ /dev/null @@ -1,221 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2015 Broadcom Corporation - */ - -#include <linux/delay.h> -#include <linux/io.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/of.h> -#include <linux/of_platform.h> -#include <linux/of_mdio.h> -#include <linux/phy.h> -#include <linux/platform_device.h> -#include <linux/sched.h> - -#define IPROC_GPHY_MDCDIV 0x1a - -#define MII_CTRL_OFFSET 0x000 - -#define MII_CTRL_DIV_SHIFT 0 -#define MII_CTRL_PRE_SHIFT 7 -#define MII_CTRL_BUSY_SHIFT 8 - -#define MII_DATA_OFFSET 0x004 -#define MII_DATA_MASK 0xffff -#define MII_DATA_TA_SHIFT 16 -#define MII_DATA_TA_VAL 2 -#define MII_DATA_RA_SHIFT 18 -#define MII_DATA_PA_SHIFT 23 -#define MII_DATA_OP_SHIFT 28 -#define MII_DATA_OP_WRITE 1 -#define MII_DATA_OP_READ 2 -#define MII_DATA_SB_SHIFT 30 - -struct iproc_mdio_priv { - struct mii_bus *mii_bus; - void __iomem *base; -}; - -static inline int iproc_mdio_wait_for_idle(void __iomem *base) -{ - u32 val; - unsigned int timeout = 1000; /* loop for 1s */ - - do { - val = readl(base + MII_CTRL_OFFSET); - if ((val & BIT(MII_CTRL_BUSY_SHIFT)) == 0) - return 0; - - usleep_range(1000, 2000); - } while (timeout--); - - return -ETIMEDOUT; -} - -static inline void iproc_mdio_config_clk(void __iomem *base) -{ - u32 val; - - val = (IPROC_GPHY_MDCDIV << MII_CTRL_DIV_SHIFT) | - BIT(MII_CTRL_PRE_SHIFT); - writel(val, base + MII_CTRL_OFFSET); -} - -static int iproc_mdio_read(struct mii_bus *bus, int phy_id, int reg) -{ - struct iproc_mdio_priv *priv = bus->priv; - u32 cmd; - int rc; - - rc = iproc_mdio_wait_for_idle(priv->base); - if (rc) - return rc; - - /* Prepare the read operation */ - cmd = (MII_DATA_TA_VAL << MII_DATA_TA_SHIFT) | - (reg << MII_DATA_RA_SHIFT) | - (phy_id << MII_DATA_PA_SHIFT) | - BIT(MII_DATA_SB_SHIFT) | - (MII_DATA_OP_READ << MII_DATA_OP_SHIFT); - - writel(cmd, priv->base + MII_DATA_OFFSET); - - rc = iproc_mdio_wait_for_idle(priv->base); - if (rc) - return rc; - - cmd = readl(priv->base + MII_DATA_OFFSET) & MII_DATA_MASK; - - return cmd; -} - -static int iproc_mdio_write(struct mii_bus *bus, int phy_id, - int reg, u16 val) -{ - struct iproc_mdio_priv *priv = bus->priv; - u32 cmd; - int rc; - - rc = iproc_mdio_wait_for_idle(priv->base); - if (rc) - return rc; - - /* Prepare the write operation */ - cmd = (MII_DATA_TA_VAL << MII_DATA_TA_SHIFT) | - (reg << MII_DATA_RA_SHIFT) | - (phy_id << MII_DATA_PA_SHIFT) | - BIT(MII_DATA_SB_SHIFT) | - (MII_DATA_OP_WRITE << MII_DATA_OP_SHIFT) | - ((u32)(val) & MII_DATA_MASK); - - writel(cmd, priv->base + MII_DATA_OFFSET); - - rc = iproc_mdio_wait_for_idle(priv->base); - if (rc) - return rc; - - return 0; -} - -static int iproc_mdio_probe(struct platform_device *pdev) -{ - struct iproc_mdio_priv *priv; - struct mii_bus *bus; - int rc; - - priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - priv->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(priv->base)) { - dev_err(&pdev->dev, "failed to ioremap register\n"); - return PTR_ERR(priv->base); - } - - priv->mii_bus = mdiobus_alloc(); - if (!priv->mii_bus) { - dev_err(&pdev->dev, "MDIO bus alloc failed\n"); - return -ENOMEM; - } - - bus = priv->mii_bus; - bus->priv = priv; - bus->name = "iProc MDIO bus"; - snprintf(bus->id, MII_BUS_ID_SIZE, "%s-%d", pdev->name, pdev->id); - bus->parent = &pdev->dev; - bus->read = iproc_mdio_read; - bus->write = iproc_mdio_write; - - iproc_mdio_config_clk(priv->base); - - rc = of_mdiobus_register(bus, pdev->dev.of_node); - if (rc) { - dev_err(&pdev->dev, "MDIO bus registration failed\n"); - goto err_iproc_mdio; - } - - platform_set_drvdata(pdev, priv); - - dev_info(&pdev->dev, "Broadcom iProc MDIO bus registered\n"); - - return 0; - -err_iproc_mdio: - mdiobus_free(bus); - return rc; -} - -static int iproc_mdio_remove(struct platform_device *pdev) -{ - struct iproc_mdio_priv *priv = platform_get_drvdata(pdev); - - mdiobus_unregister(priv->mii_bus); - mdiobus_free(priv->mii_bus); - - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static int iproc_mdio_resume(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct iproc_mdio_priv *priv = platform_get_drvdata(pdev); - - /* restore the mii clock configuration */ - iproc_mdio_config_clk(priv->base); - - return 0; -} - -static const struct dev_pm_ops iproc_mdio_pm_ops = { - .resume = iproc_mdio_resume -}; -#endif /* CONFIG_PM_SLEEP */ - -static const struct of_device_id iproc_mdio_of_match[] = { - { .compatible = "brcm,iproc-mdio", }, - { /* sentinel */ }, -}; -MODULE_DEVICE_TABLE(of, iproc_mdio_of_match); - -static struct platform_driver iproc_mdio_driver = { - .driver = { - .name = "iproc-mdio", - .of_match_table = iproc_mdio_of_match, -#ifdef CONFIG_PM_SLEEP - .pm = &iproc_mdio_pm_ops, -#endif - }, - .probe = iproc_mdio_probe, - .remove = iproc_mdio_remove, -}; - -module_platform_driver(iproc_mdio_driver); - -MODULE_AUTHOR("Broadcom Corporation"); -MODULE_DESCRIPTION("Broadcom iProc MDIO bus controller"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:iproc-mdio"); diff --git a/drivers/net/phy/mdio-bcm-unimac.c b/drivers/net/phy/mdio-bcm-unimac.c deleted file mode 100644 index fbd36891ee64..000000000000 --- a/drivers/net/phy/mdio-bcm-unimac.c +++ /dev/null @@ -1,363 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Broadcom UniMAC MDIO bus controller driver - * - * Copyright (C) 2014-2017 Broadcom - */ - -#include <linux/kernel.h> -#include <linux/phy.h> -#include <linux/platform_device.h> -#include <linux/sched.h> -#include <linux/module.h> -#include <linux/io.h> -#include <linux/delay.h> -#include <linux/clk.h> - -#include <linux/of.h> -#include <linux/of_platform.h> -#include <linux/of_mdio.h> - -#include <linux/platform_data/mdio-bcm-unimac.h> - -#define MDIO_CMD 0x00 -#define MDIO_START_BUSY (1 << 29) -#define MDIO_READ_FAIL (1 << 28) -#define MDIO_RD (2 << 26) -#define MDIO_WR (1 << 26) -#define MDIO_PMD_SHIFT 21 -#define MDIO_PMD_MASK 0x1F -#define MDIO_REG_SHIFT 16 -#define MDIO_REG_MASK 0x1F - -#define MDIO_CFG 0x04 -#define MDIO_C22 (1 << 0) -#define MDIO_C45 0 -#define MDIO_CLK_DIV_SHIFT 4 -#define MDIO_CLK_DIV_MASK 0x3F -#define MDIO_SUPP_PREAMBLE (1 << 12) - -struct unimac_mdio_priv { - struct mii_bus *mii_bus; - void __iomem *base; - int (*wait_func) (void *wait_func_data); - void *wait_func_data; - struct clk *clk; - u32 clk_freq; -}; - -static inline u32 unimac_mdio_readl(struct unimac_mdio_priv *priv, u32 offset) -{ - /* MIPS chips strapped for BE will automagically configure the - * peripheral registers for CPU-native byte order. - */ - if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) - return __raw_readl(priv->base + offset); - else - return readl_relaxed(priv->base + offset); -} - -static inline void unimac_mdio_writel(struct unimac_mdio_priv *priv, u32 val, - u32 offset) -{ - if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) - __raw_writel(val, priv->base + offset); - else - writel_relaxed(val, priv->base + offset); -} - -static inline void unimac_mdio_start(struct unimac_mdio_priv *priv) -{ - u32 reg; - - reg = unimac_mdio_readl(priv, MDIO_CMD); - reg |= MDIO_START_BUSY; - unimac_mdio_writel(priv, reg, MDIO_CMD); -} - -static inline unsigned int unimac_mdio_busy(struct unimac_mdio_priv *priv) -{ - return unimac_mdio_readl(priv, MDIO_CMD) & MDIO_START_BUSY; -} - -static int unimac_mdio_poll(void *wait_func_data) -{ - struct unimac_mdio_priv *priv = wait_func_data; - unsigned int timeout = 1000; - - do { - if (!unimac_mdio_busy(priv)) - return 0; - - usleep_range(1000, 2000); - } while (--timeout); - - return -ETIMEDOUT; -} - -static int unimac_mdio_read(struct mii_bus *bus, int phy_id, int reg) -{ - struct unimac_mdio_priv *priv = bus->priv; - int ret; - u32 cmd; - - /* Prepare the read operation */ - cmd = MDIO_RD | (phy_id << MDIO_PMD_SHIFT) | (reg << MDIO_REG_SHIFT); - unimac_mdio_writel(priv, cmd, MDIO_CMD); - - /* Start MDIO transaction */ - unimac_mdio_start(priv); - - ret = priv->wait_func(priv->wait_func_data); - if (ret) - return ret; - - cmd = unimac_mdio_readl(priv, MDIO_CMD); - - /* Some broken devices are known not to release the line during - * turn-around, e.g: Broadcom BCM53125 external switches, so check for - * that condition here and ignore the MDIO controller read failure - * indication. - */ - if (!(bus->phy_ignore_ta_mask & 1 << phy_id) && (cmd & MDIO_READ_FAIL)) - return -EIO; - - return cmd & 0xffff; -} - -static int unimac_mdio_write(struct mii_bus *bus, int phy_id, - int reg, u16 val) -{ - struct unimac_mdio_priv *priv = bus->priv; - u32 cmd; - - /* Prepare the write operation */ - cmd = MDIO_WR | (phy_id << MDIO_PMD_SHIFT) | - (reg << MDIO_REG_SHIFT) | (0xffff & val); - unimac_mdio_writel(priv, cmd, MDIO_CMD); - - unimac_mdio_start(priv); - - return priv->wait_func(priv->wait_func_data); -} - -/* Workaround for integrated BCM7xxx Gigabit PHYs which have a problem with - * their internal MDIO management controller making them fail to successfully - * be read from or written to for the first transaction. We insert a dummy - * BMSR read here to make sure that phy_get_device() and get_phy_id() can - * correctly read the PHY MII_PHYSID1/2 registers and successfully register a - * PHY device for this peripheral. - * - * Once the PHY driver is registered, we can workaround subsequent reads from - * there (e.g: during system-wide power management). - * - * bus->reset is invoked before mdiobus_scan during mdiobus_register and is - * therefore the right location to stick that workaround. Since we do not want - * to read from non-existing PHYs, we either use bus->phy_mask or do a manual - * Device Tree scan to limit the search area. - */ -static int unimac_mdio_reset(struct mii_bus *bus) -{ - struct device_node *np = bus->dev.of_node; - struct device_node *child; - u32 read_mask = 0; - int addr; - - if (!np) { - read_mask = ~bus->phy_mask; - } else { - for_each_available_child_of_node(np, child) { - addr = of_mdio_parse_addr(&bus->dev, child); - if (addr < 0) - continue; - - read_mask |= 1 << addr; - } - } - - for (addr = 0; addr < PHY_MAX_ADDR; addr++) { - if (read_mask & 1 << addr) { - dev_dbg(&bus->dev, "Workaround for PHY @ %d\n", addr); - mdiobus_read(bus, addr, MII_BMSR); - } - } - - return 0; -} - -static void unimac_mdio_clk_set(struct unimac_mdio_priv *priv) -{ - unsigned long rate; - u32 reg, div; - - /* Keep the hardware default values */ - if (!priv->clk_freq) - return; - - if (!priv->clk) - rate = 250000000; - else - rate = clk_get_rate(priv->clk); - - div = (rate / (2 * priv->clk_freq)) - 1; - if (div & ~MDIO_CLK_DIV_MASK) { - pr_warn("Incorrect MDIO clock frequency, ignoring\n"); - return; - } - - /* The MDIO clock is the reference clock (typicaly 250Mhz) divided by - * 2 x (MDIO_CLK_DIV + 1) - */ - reg = unimac_mdio_readl(priv, MDIO_CFG); - reg &= ~(MDIO_CLK_DIV_MASK << MDIO_CLK_DIV_SHIFT); - reg |= div << MDIO_CLK_DIV_SHIFT; - unimac_mdio_writel(priv, reg, MDIO_CFG); -} - -static int unimac_mdio_probe(struct platform_device *pdev) -{ - struct unimac_mdio_pdata *pdata = pdev->dev.platform_data; - struct unimac_mdio_priv *priv; - struct device_node *np; - struct mii_bus *bus; - struct resource *r; - int ret; - - np = pdev->dev.of_node; - - priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!r) - return -EINVAL; - - /* Just ioremap, as this MDIO block is usually integrated into an - * Ethernet MAC controller register range - */ - priv->base = devm_ioremap(&pdev->dev, r->start, resource_size(r)); - if (!priv->base) { - dev_err(&pdev->dev, "failed to remap register\n"); - return -ENOMEM; - } - - priv->clk = devm_clk_get_optional(&pdev->dev, NULL); - if (IS_ERR(priv->clk)) - return PTR_ERR(priv->clk); - - ret = clk_prepare_enable(priv->clk); - if (ret) - return ret; - - if (of_property_read_u32(np, "clock-frequency", &priv->clk_freq)) - priv->clk_freq = 0; - - unimac_mdio_clk_set(priv); - - priv->mii_bus = mdiobus_alloc(); - if (!priv->mii_bus) { - ret = -ENOMEM; - goto out_clk_disable; - } - - bus = priv->mii_bus; - bus->priv = priv; - if (pdata) { - bus->name = pdata->bus_name; - priv->wait_func = pdata->wait_func; - priv->wait_func_data = pdata->wait_func_data; - bus->phy_mask = ~pdata->phy_mask; - } else { - bus->name = "unimac MII bus"; - priv->wait_func_data = priv; - priv->wait_func = unimac_mdio_poll; - } - bus->parent = &pdev->dev; - bus->read = unimac_mdio_read; - bus->write = unimac_mdio_write; - bus->reset = unimac_mdio_reset; - snprintf(bus->id, MII_BUS_ID_SIZE, "%s-%d", pdev->name, pdev->id); - - ret = of_mdiobus_register(bus, np); - if (ret) { - dev_err(&pdev->dev, "MDIO bus registration failed\n"); - goto out_mdio_free; - } - - platform_set_drvdata(pdev, priv); - - dev_info(&pdev->dev, "Broadcom UniMAC MDIO bus\n"); - - return 0; - -out_mdio_free: - mdiobus_free(bus); -out_clk_disable: - clk_disable_unprepare(priv->clk); - return ret; -} - -static int unimac_mdio_remove(struct platform_device *pdev) -{ - struct unimac_mdio_priv *priv = platform_get_drvdata(pdev); - - mdiobus_unregister(priv->mii_bus); - mdiobus_free(priv->mii_bus); - clk_disable_unprepare(priv->clk); - - return 0; -} - -static int __maybe_unused unimac_mdio_suspend(struct device *d) -{ - struct unimac_mdio_priv *priv = dev_get_drvdata(d); - - clk_disable_unprepare(priv->clk); - - return 0; -} - -static int __maybe_unused unimac_mdio_resume(struct device *d) -{ - struct unimac_mdio_priv *priv = dev_get_drvdata(d); - int ret; - - ret = clk_prepare_enable(priv->clk); - if (ret) - return ret; - - unimac_mdio_clk_set(priv); - - return 0; -} - -static SIMPLE_DEV_PM_OPS(unimac_mdio_pm_ops, - unimac_mdio_suspend, unimac_mdio_resume); - -static const struct of_device_id unimac_mdio_ids[] = { - { .compatible = "brcm,genet-mdio-v5", }, - { .compatible = "brcm,genet-mdio-v4", }, - { .compatible = "brcm,genet-mdio-v3", }, - { .compatible = "brcm,genet-mdio-v2", }, - { .compatible = "brcm,genet-mdio-v1", }, - { .compatible = "brcm,unimac-mdio", }, - { /* sentinel */ }, -}; -MODULE_DEVICE_TABLE(of, unimac_mdio_ids); - -static struct platform_driver unimac_mdio_driver = { - .driver = { - .name = UNIMAC_MDIO_DRV_NAME, - .of_match_table = unimac_mdio_ids, - .pm = &unimac_mdio_pm_ops, - }, - .probe = unimac_mdio_probe, - .remove = unimac_mdio_remove, -}; -module_platform_driver(unimac_mdio_driver); - -MODULE_AUTHOR("Broadcom Corporation"); -MODULE_DESCRIPTION("Broadcom UniMAC MDIO bus controller"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:" UNIMAC_MDIO_DRV_NAME); diff --git a/drivers/net/phy/mdio-bitbang.c b/drivers/net/phy/mdio-bitbang.c deleted file mode 100644 index 5136275c8e73..000000000000 --- a/drivers/net/phy/mdio-bitbang.c +++ /dev/null @@ -1,232 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Bitbanged MDIO support. - * - * Author: Scott Wood <scottwood@freescale.com> - * Copyright (c) 2007 Freescale Semiconductor - * - * Based on CPM2 MDIO code which is: - * - * Copyright (c) 2003 Intracom S.A. - * by Pantelis Antoniou <panto@intracom.gr> - * - * 2005 (c) MontaVista Software, Inc. - * Vitaly Bordug <vbordug@ru.mvista.com> - */ - -#include <linux/module.h> -#include <linux/mdio-bitbang.h> -#include <linux/types.h> -#include <linux/delay.h> - -#define MDIO_READ 2 -#define MDIO_WRITE 1 - -#define MDIO_C45 (1<<15) -#define MDIO_C45_ADDR (MDIO_C45 | 0) -#define MDIO_C45_READ (MDIO_C45 | 3) -#define MDIO_C45_WRITE (MDIO_C45 | 1) - -#define MDIO_SETUP_TIME 10 -#define MDIO_HOLD_TIME 10 - -/* Minimum MDC period is 400 ns, plus some margin for error. MDIO_DELAY - * is done twice per period. - */ -#define MDIO_DELAY 250 - -/* The PHY may take up to 300 ns to produce data, plus some margin - * for error. - */ -#define MDIO_READ_DELAY 350 - -/* MDIO must already be configured as output. */ -static void mdiobb_send_bit(struct mdiobb_ctrl *ctrl, int val) -{ - const struct mdiobb_ops *ops = ctrl->ops; - - ops->set_mdio_data(ctrl, val); - ndelay(MDIO_DELAY); - ops->set_mdc(ctrl, 1); - ndelay(MDIO_DELAY); - ops->set_mdc(ctrl, 0); -} - -/* MDIO must already be configured as input. */ -static int mdiobb_get_bit(struct mdiobb_ctrl *ctrl) -{ - const struct mdiobb_ops *ops = ctrl->ops; - - ndelay(MDIO_DELAY); - ops->set_mdc(ctrl, 1); - ndelay(MDIO_READ_DELAY); - ops->set_mdc(ctrl, 0); - - return ops->get_mdio_data(ctrl); -} - -/* MDIO must already be configured as output. */ -static void mdiobb_send_num(struct mdiobb_ctrl *ctrl, u16 val, int bits) -{ - int i; - - for (i = bits - 1; i >= 0; i--) - mdiobb_send_bit(ctrl, (val >> i) & 1); -} - -/* MDIO must already be configured as input. */ -static u16 mdiobb_get_num(struct mdiobb_ctrl *ctrl, int bits) -{ - int i; - u16 ret = 0; - - for (i = bits - 1; i >= 0; i--) { - ret <<= 1; - ret |= mdiobb_get_bit(ctrl); - } - - return ret; -} - -/* Utility to send the preamble, address, and - * register (common to read and write). - */ -static void mdiobb_cmd(struct mdiobb_ctrl *ctrl, int op, u8 phy, u8 reg) -{ - const struct mdiobb_ops *ops = ctrl->ops; - int i; - - ops->set_mdio_dir(ctrl, 1); - - /* - * Send a 32 bit preamble ('1's) with an extra '1' bit for good - * measure. The IEEE spec says this is a PHY optional - * requirement. The AMD 79C874 requires one after power up and - * one after a MII communications error. This means that we are - * doing more preambles than we need, but it is safer and will be - * much more robust. - */ - - for (i = 0; i < 32; i++) - mdiobb_send_bit(ctrl, 1); - - /* send the start bit (01) and the read opcode (10) or write (01). - Clause 45 operation uses 00 for the start and 11, 10 for - read/write */ - mdiobb_send_bit(ctrl, 0); - if (op & MDIO_C45) - mdiobb_send_bit(ctrl, 0); - else - mdiobb_send_bit(ctrl, 1); - mdiobb_send_bit(ctrl, (op >> 1) & 1); - mdiobb_send_bit(ctrl, (op >> 0) & 1); - - mdiobb_send_num(ctrl, phy, 5); - mdiobb_send_num(ctrl, reg, 5); -} - -/* In clause 45 mode all commands are prefixed by MDIO_ADDR to specify the - lower 16 bits of the 21 bit address. This transfer is done identically to a - MDIO_WRITE except for a different code. To enable clause 45 mode or - MII_ADDR_C45 into the address. Theoretically clause 45 and normal devices - can exist on the same bus. Normal devices should ignore the MDIO_ADDR - phase. */ -static int mdiobb_cmd_addr(struct mdiobb_ctrl *ctrl, int phy, u32 addr) -{ - unsigned int dev_addr = (addr >> 16) & 0x1F; - unsigned int reg = addr & 0xFFFF; - mdiobb_cmd(ctrl, MDIO_C45_ADDR, phy, dev_addr); - - /* send the turnaround (10) */ - mdiobb_send_bit(ctrl, 1); - mdiobb_send_bit(ctrl, 0); - - mdiobb_send_num(ctrl, reg, 16); - - ctrl->ops->set_mdio_dir(ctrl, 0); - mdiobb_get_bit(ctrl); - - return dev_addr; -} - -static int mdiobb_read(struct mii_bus *bus, int phy, int reg) -{ - struct mdiobb_ctrl *ctrl = bus->priv; - int ret, i; - - if (reg & MII_ADDR_C45) { - reg = mdiobb_cmd_addr(ctrl, phy, reg); - mdiobb_cmd(ctrl, MDIO_C45_READ, phy, reg); - } else - mdiobb_cmd(ctrl, MDIO_READ, phy, reg); - - ctrl->ops->set_mdio_dir(ctrl, 0); - - /* check the turnaround bit: the PHY should be driving it to zero, if this - * PHY is listed in phy_ignore_ta_mask as having broken TA, skip that - */ - if (mdiobb_get_bit(ctrl) != 0 && - !(bus->phy_ignore_ta_mask & (1 << phy))) { - /* PHY didn't drive TA low -- flush any bits it - * may be trying to send. - */ - for (i = 0; i < 32; i++) - mdiobb_get_bit(ctrl); - - return 0xffff; - } - - ret = mdiobb_get_num(ctrl, 16); - mdiobb_get_bit(ctrl); - return ret; -} - -static int mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val) -{ - struct mdiobb_ctrl *ctrl = bus->priv; - - if (reg & MII_ADDR_C45) { - reg = mdiobb_cmd_addr(ctrl, phy, reg); - mdiobb_cmd(ctrl, MDIO_C45_WRITE, phy, reg); - } else - mdiobb_cmd(ctrl, MDIO_WRITE, phy, reg); - - /* send the turnaround (10) */ - mdiobb_send_bit(ctrl, 1); - mdiobb_send_bit(ctrl, 0); - - mdiobb_send_num(ctrl, val, 16); - - ctrl->ops->set_mdio_dir(ctrl, 0); - mdiobb_get_bit(ctrl); - return 0; -} - -struct mii_bus *alloc_mdio_bitbang(struct mdiobb_ctrl *ctrl) -{ - struct mii_bus *bus; - - bus = mdiobus_alloc(); - if (!bus) - return NULL; - - __module_get(ctrl->ops->owner); - - bus->read = mdiobb_read; - bus->write = mdiobb_write; - bus->priv = ctrl; - - return bus; -} -EXPORT_SYMBOL(alloc_mdio_bitbang); - -void free_mdio_bitbang(struct mii_bus *bus) -{ - struct mdiobb_ctrl *ctrl = bus->priv; - - module_put(ctrl->ops->owner); - mdiobus_free(bus); -} -EXPORT_SYMBOL(free_mdio_bitbang); - -MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/phy/mdio-cavium.c b/drivers/net/phy/mdio-cavium.c deleted file mode 100644 index 1afd6fc1a351..000000000000 --- a/drivers/net/phy/mdio-cavium.c +++ /dev/null @@ -1,150 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2009-2016 Cavium, Inc. - */ - -#include <linux/delay.h> -#include <linux/module.h> -#include <linux/phy.h> -#include <linux/io.h> - -#include "mdio-cavium.h" - -static void cavium_mdiobus_set_mode(struct cavium_mdiobus *p, - enum cavium_mdiobus_mode m) -{ - union cvmx_smix_clk smi_clk; - - if (m == p->mode) - return; - - smi_clk.u64 = oct_mdio_readq(p->register_base + SMI_CLK); - smi_clk.s.mode = (m == C45) ? 1 : 0; - smi_clk.s.preamble = 1; - oct_mdio_writeq(smi_clk.u64, p->register_base + SMI_CLK); - p->mode = m; -} - -static int cavium_mdiobus_c45_addr(struct cavium_mdiobus *p, - int phy_id, int regnum) -{ - union cvmx_smix_cmd smi_cmd; - union cvmx_smix_wr_dat smi_wr; - int timeout = 1000; - - cavium_mdiobus_set_mode(p, C45); - - smi_wr.u64 = 0; - smi_wr.s.dat = regnum & 0xffff; - oct_mdio_writeq(smi_wr.u64, p->register_base + SMI_WR_DAT); - - regnum = (regnum >> 16) & 0x1f; - - smi_cmd.u64 = 0; - smi_cmd.s.phy_op = 0; /* MDIO_CLAUSE_45_ADDRESS */ - smi_cmd.s.phy_adr = phy_id; - smi_cmd.s.reg_adr = regnum; - oct_mdio_writeq(smi_cmd.u64, p->register_base + SMI_CMD); - - do { - /* Wait 1000 clocks so we don't saturate the RSL bus - * doing reads. - */ - __delay(1000); - smi_wr.u64 = oct_mdio_readq(p->register_base + SMI_WR_DAT); - } while (smi_wr.s.pending && --timeout); - - if (timeout <= 0) - return -EIO; - return 0; -} - -int cavium_mdiobus_read(struct mii_bus *bus, int phy_id, int regnum) -{ - struct cavium_mdiobus *p = bus->priv; - union cvmx_smix_cmd smi_cmd; - union cvmx_smix_rd_dat smi_rd; - unsigned int op = 1; /* MDIO_CLAUSE_22_READ */ - int timeout = 1000; - - if (regnum & MII_ADDR_C45) { - int r = cavium_mdiobus_c45_addr(p, phy_id, regnum); - - if (r < 0) - return r; - - regnum = (regnum >> 16) & 0x1f; - op = 3; /* MDIO_CLAUSE_45_READ */ - } else { - cavium_mdiobus_set_mode(p, C22); - } - - smi_cmd.u64 = 0; - smi_cmd.s.phy_op = op; - smi_cmd.s.phy_adr = phy_id; - smi_cmd.s.reg_adr = regnum; - oct_mdio_writeq(smi_cmd.u64, p->register_base + SMI_CMD); - - do { - /* Wait 1000 clocks so we don't saturate the RSL bus - * doing reads. - */ - __delay(1000); - smi_rd.u64 = oct_mdio_readq(p->register_base + SMI_RD_DAT); - } while (smi_rd.s.pending && --timeout); - - if (smi_rd.s.val) - return smi_rd.s.dat; - else - return -EIO; -} -EXPORT_SYMBOL(cavium_mdiobus_read); - -int cavium_mdiobus_write(struct mii_bus *bus, int phy_id, int regnum, u16 val) -{ - struct cavium_mdiobus *p = bus->priv; - union cvmx_smix_cmd smi_cmd; - union cvmx_smix_wr_dat smi_wr; - unsigned int op = 0; /* MDIO_CLAUSE_22_WRITE */ - int timeout = 1000; - - if (regnum & MII_ADDR_C45) { - int r = cavium_mdiobus_c45_addr(p, phy_id, regnum); - - if (r < 0) - return r; - - regnum = (regnum >> 16) & 0x1f; - op = 1; /* MDIO_CLAUSE_45_WRITE */ - } else { - cavium_mdiobus_set_mode(p, C22); - } - - smi_wr.u64 = 0; - smi_wr.s.dat = val; - oct_mdio_writeq(smi_wr.u64, p->register_base + SMI_WR_DAT); - - smi_cmd.u64 = 0; - smi_cmd.s.phy_op = op; - smi_cmd.s.phy_adr = phy_id; - smi_cmd.s.reg_adr = regnum; - oct_mdio_writeq(smi_cmd.u64, p->register_base + SMI_CMD); - - do { - /* Wait 1000 clocks so we don't saturate the RSL bus - * doing reads. - */ - __delay(1000); - smi_wr.u64 = oct_mdio_readq(p->register_base + SMI_WR_DAT); - } while (smi_wr.s.pending && --timeout); - - if (timeout <= 0) - return -EIO; - - return 0; -} -EXPORT_SYMBOL(cavium_mdiobus_write); - -MODULE_DESCRIPTION("Common code for OCTEON and Thunder MDIO bus drivers"); -MODULE_AUTHOR("David Daney"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/phy/mdio-cavium.h b/drivers/net/phy/mdio-cavium.h deleted file mode 100644 index a2245d436f5d..000000000000 --- a/drivers/net/phy/mdio-cavium.h +++ /dev/null @@ -1,118 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) 2009-2016 Cavium, Inc. - */ - -enum cavium_mdiobus_mode { - UNINIT = 0, - C22, - C45 -}; - -#define SMI_CMD 0x0 -#define SMI_WR_DAT 0x8 -#define SMI_RD_DAT 0x10 -#define SMI_CLK 0x18 -#define SMI_EN 0x20 - -#ifdef __BIG_ENDIAN_BITFIELD -#define OCT_MDIO_BITFIELD_FIELD(field, more) \ - field; \ - more - -#else -#define OCT_MDIO_BITFIELD_FIELD(field, more) \ - more \ - field; - -#endif - -union cvmx_smix_clk { - u64 u64; - struct cvmx_smix_clk_s { - OCT_MDIO_BITFIELD_FIELD(u64 reserved_25_63:39, - OCT_MDIO_BITFIELD_FIELD(u64 mode:1, - OCT_MDIO_BITFIELD_FIELD(u64 reserved_21_23:3, - OCT_MDIO_BITFIELD_FIELD(u64 sample_hi:5, - OCT_MDIO_BITFIELD_FIELD(u64 sample_mode:1, - OCT_MDIO_BITFIELD_FIELD(u64 reserved_14_14:1, - OCT_MDIO_BITFIELD_FIELD(u64 clk_idle:1, - OCT_MDIO_BITFIELD_FIELD(u64 preamble:1, - OCT_MDIO_BITFIELD_FIELD(u64 sample:4, - OCT_MDIO_BITFIELD_FIELD(u64 phase:8, - ;)))))))))) - } s; -}; - -union cvmx_smix_cmd { - u64 u64; - struct cvmx_smix_cmd_s { - OCT_MDIO_BITFIELD_FIELD(u64 reserved_18_63:46, - OCT_MDIO_BITFIELD_FIELD(u64 phy_op:2, - OCT_MDIO_BITFIELD_FIELD(u64 reserved_13_15:3, - OCT_MDIO_BITFIELD_FIELD(u64 phy_adr:5, - OCT_MDIO_BITFIELD_FIELD(u64 reserved_5_7:3, - OCT_MDIO_BITFIELD_FIELD(u64 reg_adr:5, - ;)))))) - } s; -}; - -union cvmx_smix_en { - u64 u64; - struct cvmx_smix_en_s { - OCT_MDIO_BITFIELD_FIELD(u64 reserved_1_63:63, - OCT_MDIO_BITFIELD_FIELD(u64 en:1, - ;)) - } s; -}; - -union cvmx_smix_rd_dat { - u64 u64; - struct cvmx_smix_rd_dat_s { - OCT_MDIO_BITFIELD_FIELD(u64 reserved_18_63:46, - OCT_MDIO_BITFIELD_FIELD(u64 pending:1, - OCT_MDIO_BITFIELD_FIELD(u64 val:1, - OCT_MDIO_BITFIELD_FIELD(u64 dat:16, - ;)))) - } s; -}; - -union cvmx_smix_wr_dat { - u64 u64; - struct cvmx_smix_wr_dat_s { - OCT_MDIO_BITFIELD_FIELD(u64 reserved_18_63:46, - OCT_MDIO_BITFIELD_FIELD(u64 pending:1, - OCT_MDIO_BITFIELD_FIELD(u64 val:1, - OCT_MDIO_BITFIELD_FIELD(u64 dat:16, - ;)))) - } s; -}; - -struct cavium_mdiobus { - struct mii_bus *mii_bus; - void __iomem *register_base; - enum cavium_mdiobus_mode mode; -}; - -#ifdef CONFIG_CAVIUM_OCTEON_SOC - -#include <asm/octeon/octeon.h> - -static inline void oct_mdio_writeq(u64 val, void __iomem *addr) -{ - cvmx_write_csr((u64 __force)addr, val); -} - -static inline u64 oct_mdio_readq(void __iomem *addr) -{ - return cvmx_read_csr((u64 __force)addr); -} -#else -#include <linux/io-64-nonatomic-lo-hi.h> - -#define oct_mdio_writeq(val, addr) writeq(val, addr) -#define oct_mdio_readq(addr) readq(addr) -#endif - -int cavium_mdiobus_read(struct mii_bus *bus, int phy_id, int regnum); -int cavium_mdiobus_write(struct mii_bus *bus, int phy_id, int regnum, u16 val); diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c deleted file mode 100644 index 1b00235d7dc5..000000000000 --- a/drivers/net/phy/mdio-gpio.c +++ /dev/null @@ -1,217 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * GPIO based MDIO bitbang driver. - * Supports OpenFirmware. - * - * Copyright (c) 2008 CSE Semaphore Belgium. - * by Laurent Pinchart <laurentp@cse-semaphore.com> - * - * Copyright (C) 2008, Paulius Zaleckas <paulius.zaleckas@teltonika.lt> - * - * Based on earlier work by - * - * Copyright (c) 2003 Intracom S.A. - * by Pantelis Antoniou <panto@intracom.gr> - * - * 2005 (c) MontaVista Software, Inc. - * Vitaly Bordug <vbordug@ru.mvista.com> - */ - -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/platform_device.h> -#include <linux/platform_data/mdio-gpio.h> -#include <linux/mdio-bitbang.h> -#include <linux/mdio-gpio.h> -#include <linux/gpio/consumer.h> -#include <linux/of_mdio.h> - -struct mdio_gpio_info { - struct mdiobb_ctrl ctrl; - struct gpio_desc *mdc, *mdio, *mdo; -}; - -static int mdio_gpio_get_data(struct device *dev, - struct mdio_gpio_info *bitbang) -{ - bitbang->mdc = devm_gpiod_get_index(dev, NULL, MDIO_GPIO_MDC, - GPIOD_OUT_LOW); - if (IS_ERR(bitbang->mdc)) - return PTR_ERR(bitbang->mdc); - - bitbang->mdio = devm_gpiod_get_index(dev, NULL, MDIO_GPIO_MDIO, - GPIOD_IN); - if (IS_ERR(bitbang->mdio)) - return PTR_ERR(bitbang->mdio); - - bitbang->mdo = devm_gpiod_get_index_optional(dev, NULL, MDIO_GPIO_MDO, - GPIOD_OUT_LOW); - return PTR_ERR_OR_ZERO(bitbang->mdo); -} - -static void mdio_dir(struct mdiobb_ctrl *ctrl, int dir) -{ - struct mdio_gpio_info *bitbang = - container_of(ctrl, struct mdio_gpio_info, ctrl); - - if (bitbang->mdo) { - /* Separate output pin. Always set its value to high - * when changing direction. If direction is input, - * assume the pin serves as pull-up. If direction is - * output, the default value is high. - */ - gpiod_set_value_cansleep(bitbang->mdo, 1); - return; - } - - if (dir) - gpiod_direction_output(bitbang->mdio, 1); - else - gpiod_direction_input(bitbang->mdio); -} - -static int mdio_get(struct mdiobb_ctrl *ctrl) -{ - struct mdio_gpio_info *bitbang = - container_of(ctrl, struct mdio_gpio_info, ctrl); - - return gpiod_get_value_cansleep(bitbang->mdio); -} - -static void mdio_set(struct mdiobb_ctrl *ctrl, int what) -{ - struct mdio_gpio_info *bitbang = - container_of(ctrl, struct mdio_gpio_info, ctrl); - - if (bitbang->mdo) - gpiod_set_value_cansleep(bitbang->mdo, what); - else - gpiod_set_value_cansleep(bitbang->mdio, what); -} - -static void mdc_set(struct mdiobb_ctrl *ctrl, int what) -{ - struct mdio_gpio_info *bitbang = - container_of(ctrl, struct mdio_gpio_info, ctrl); - - gpiod_set_value_cansleep(bitbang->mdc, what); -} - -static const struct mdiobb_ops mdio_gpio_ops = { - .owner = THIS_MODULE, - .set_mdc = mdc_set, - .set_mdio_dir = mdio_dir, - .set_mdio_data = mdio_set, - .get_mdio_data = mdio_get, -}; - -static struct mii_bus *mdio_gpio_bus_init(struct device *dev, - struct mdio_gpio_info *bitbang, - int bus_id) -{ - struct mdio_gpio_platform_data *pdata = dev_get_platdata(dev); - struct mii_bus *new_bus; - - bitbang->ctrl.ops = &mdio_gpio_ops; - - new_bus = alloc_mdio_bitbang(&bitbang->ctrl); - if (!new_bus) - return NULL; - - new_bus->name = "GPIO Bitbanged MDIO"; - new_bus->parent = dev; - - if (bus_id != -1) - snprintf(new_bus->id, MII_BUS_ID_SIZE, "gpio-%x", bus_id); - else - strncpy(new_bus->id, "gpio", MII_BUS_ID_SIZE); - - if (pdata) { - new_bus->phy_mask = pdata->phy_mask; - new_bus->phy_ignore_ta_mask = pdata->phy_ignore_ta_mask; - } - - dev_set_drvdata(dev, new_bus); - - return new_bus; -} - -static void mdio_gpio_bus_deinit(struct device *dev) -{ - struct mii_bus *bus = dev_get_drvdata(dev); - - free_mdio_bitbang(bus); -} - -static void mdio_gpio_bus_destroy(struct device *dev) -{ - struct mii_bus *bus = dev_get_drvdata(dev); - - mdiobus_unregister(bus); - mdio_gpio_bus_deinit(dev); -} - -static int mdio_gpio_probe(struct platform_device *pdev) -{ - struct mdio_gpio_info *bitbang; - struct mii_bus *new_bus; - int ret, bus_id; - - bitbang = devm_kzalloc(&pdev->dev, sizeof(*bitbang), GFP_KERNEL); - if (!bitbang) - return -ENOMEM; - - ret = mdio_gpio_get_data(&pdev->dev, bitbang); - if (ret) - return ret; - - if (pdev->dev.of_node) { - bus_id = of_alias_get_id(pdev->dev.of_node, "mdio-gpio"); - if (bus_id < 0) { - dev_warn(&pdev->dev, "failed to get alias id\n"); - bus_id = 0; - } - } else { - bus_id = pdev->id; - } - - new_bus = mdio_gpio_bus_init(&pdev->dev, bitbang, bus_id); - if (!new_bus) - return -ENODEV; - - ret = of_mdiobus_register(new_bus, pdev->dev.of_node); - if (ret) - mdio_gpio_bus_deinit(&pdev->dev); - - return ret; -} - -static int mdio_gpio_remove(struct platform_device *pdev) -{ - mdio_gpio_bus_destroy(&pdev->dev); - - return 0; -} - -static const struct of_device_id mdio_gpio_of_match[] = { - { .compatible = "virtual,mdio-gpio", }, - { /* sentinel */ } -}; -MODULE_DEVICE_TABLE(of, mdio_gpio_of_match); - -static struct platform_driver mdio_gpio_driver = { - .probe = mdio_gpio_probe, - .remove = mdio_gpio_remove, - .driver = { - .name = "mdio-gpio", - .of_match_table = mdio_gpio_of_match, - }, -}; - -module_platform_driver(mdio_gpio_driver); - -MODULE_ALIAS("platform:mdio-gpio"); -MODULE_AUTHOR("Laurent Pinchart, Paulius Zaleckas"); -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("Generic driver for MDIO bus emulation using GPIO"); diff --git a/drivers/net/phy/mdio-hisi-femac.c b/drivers/net/phy/mdio-hisi-femac.c deleted file mode 100644 index f231c2fbb1de..000000000000 --- a/drivers/net/phy/mdio-hisi-femac.c +++ /dev/null @@ -1,152 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Hisilicon Fast Ethernet MDIO Bus Driver - * - * Copyright (c) 2016 HiSilicon Technologies Co., Ltd. - */ - -#include <linux/clk.h> -#include <linux/iopoll.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/of_address.h> -#include <linux/of_mdio.h> -#include <linux/platform_device.h> - -#define MDIO_RWCTRL 0x00 -#define MDIO_RO_DATA 0x04 -#define MDIO_WRITE BIT(13) -#define MDIO_RW_FINISH BIT(15) -#define BIT_PHY_ADDR_OFFSET 8 -#define BIT_WR_DATA_OFFSET 16 - -struct hisi_femac_mdio_data { - struct clk *clk; - void __iomem *membase; -}; - -static int hisi_femac_mdio_wait_ready(struct hisi_femac_mdio_data *data) -{ - u32 val; - - return readl_poll_timeout(data->membase + MDIO_RWCTRL, - val, val & MDIO_RW_FINISH, 20, 10000); -} - -static int hisi_femac_mdio_read(struct mii_bus *bus, int mii_id, int regnum) -{ - struct hisi_femac_mdio_data *data = bus->priv; - int ret; - - ret = hisi_femac_mdio_wait_ready(data); - if (ret) - return ret; - - writel((mii_id << BIT_PHY_ADDR_OFFSET) | regnum, - data->membase + MDIO_RWCTRL); - - ret = hisi_femac_mdio_wait_ready(data); - if (ret) - return ret; - - return readl(data->membase + MDIO_RO_DATA) & 0xFFFF; -} - -static int hisi_femac_mdio_write(struct mii_bus *bus, int mii_id, int regnum, - u16 value) -{ - struct hisi_femac_mdio_data *data = bus->priv; - int ret; - - ret = hisi_femac_mdio_wait_ready(data); - if (ret) - return ret; - - writel(MDIO_WRITE | (value << BIT_WR_DATA_OFFSET) | - (mii_id << BIT_PHY_ADDR_OFFSET) | regnum, - data->membase + MDIO_RWCTRL); - - return hisi_femac_mdio_wait_ready(data); -} - -static int hisi_femac_mdio_probe(struct platform_device *pdev) -{ - struct device_node *np = pdev->dev.of_node; - struct mii_bus *bus; - struct hisi_femac_mdio_data *data; - int ret; - - bus = mdiobus_alloc_size(sizeof(*data)); - if (!bus) - return -ENOMEM; - - bus->name = "hisi_femac_mii_bus"; - bus->read = &hisi_femac_mdio_read; - bus->write = &hisi_femac_mdio_write; - snprintf(bus->id, MII_BUS_ID_SIZE, "%s", pdev->name); - bus->parent = &pdev->dev; - - data = bus->priv; - data->membase = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(data->membase)) { - ret = PTR_ERR(data->membase); - goto err_out_free_mdiobus; - } - - data->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(data->clk)) { - ret = PTR_ERR(data->clk); - goto err_out_free_mdiobus; - } - - ret = clk_prepare_enable(data->clk); - if (ret) - goto err_out_free_mdiobus; - - ret = of_mdiobus_register(bus, np); - if (ret) - goto err_out_disable_clk; - - platform_set_drvdata(pdev, bus); - - return 0; - -err_out_disable_clk: - clk_disable_unprepare(data->clk); -err_out_free_mdiobus: - mdiobus_free(bus); - return ret; -} - -static int hisi_femac_mdio_remove(struct platform_device *pdev) -{ - struct mii_bus *bus = platform_get_drvdata(pdev); - struct hisi_femac_mdio_data *data = bus->priv; - - mdiobus_unregister(bus); - clk_disable_unprepare(data->clk); - mdiobus_free(bus); - - return 0; -} - -static const struct of_device_id hisi_femac_mdio_dt_ids[] = { - { .compatible = "hisilicon,hisi-femac-mdio" }, - { } -}; -MODULE_DEVICE_TABLE(of, hisi_femac_mdio_dt_ids); - -static struct platform_driver hisi_femac_mdio_driver = { - .probe = hisi_femac_mdio_probe, - .remove = hisi_femac_mdio_remove, - .driver = { - .name = "hisi-femac-mdio", - .of_match_table = hisi_femac_mdio_dt_ids, - }, -}; - -module_platform_driver(hisi_femac_mdio_driver); - -MODULE_DESCRIPTION("Hisilicon Fast Ethernet MAC MDIO interface driver"); -MODULE_AUTHOR("Dongpo Li <lidongpo@hisilicon.com>"); -MODULE_LICENSE("GPL"); diff --git a/drivers/net/phy/mdio-i2c.c b/drivers/net/phy/mdio-i2c.c deleted file mode 100644 index 09200a70b315..000000000000 --- a/drivers/net/phy/mdio-i2c.c +++ /dev/null @@ -1,117 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * MDIO I2C bridge - * - * Copyright (C) 2015-2016 Russell King - * - * Network PHYs can appear on I2C buses when they are part of SFP module. - * This driver exposes these PHYs to the networking PHY code, allowing - * our PHY drivers access to these PHYs, and so allowing configuration - * of their settings. - */ -#include <linux/i2c.h> -#include <linux/mdio/mdio-i2c.h> -#include <linux/phy.h> - -/* - * I2C bus addresses 0x50 and 0x51 are normally an EEPROM, which is - * specified to be present in SFP modules. These correspond with PHY - * addresses 16 and 17. Disallow access to these "phy" addresses. - */ -static bool i2c_mii_valid_phy_id(int phy_id) -{ - return phy_id != 0x10 && phy_id != 0x11; -} - -static unsigned int i2c_mii_phy_addr(int phy_id) -{ - return phy_id + 0x40; -} - -static int i2c_mii_read(struct mii_bus *bus, int phy_id, int reg) -{ - struct i2c_adapter *i2c = bus->priv; - struct i2c_msg msgs[2]; - u8 addr[3], data[2], *p; - int bus_addr, ret; - - if (!i2c_mii_valid_phy_id(phy_id)) - return 0xffff; - - p = addr; - if (reg & MII_ADDR_C45) { - *p++ = 0x20 | ((reg >> 16) & 31); - *p++ = reg >> 8; - } - *p++ = reg; - - bus_addr = i2c_mii_phy_addr(phy_id); - msgs[0].addr = bus_addr; - msgs[0].flags = 0; - msgs[0].len = p - addr; - msgs[0].buf = addr; - msgs[1].addr = bus_addr; - msgs[1].flags = I2C_M_RD; - msgs[1].len = sizeof(data); - msgs[1].buf = data; - - ret = i2c_transfer(i2c, msgs, ARRAY_SIZE(msgs)); - if (ret != ARRAY_SIZE(msgs)) - return 0xffff; - - return data[0] << 8 | data[1]; -} - -static int i2c_mii_write(struct mii_bus *bus, int phy_id, int reg, u16 val) -{ - struct i2c_adapter *i2c = bus->priv; - struct i2c_msg msg; - int ret; - u8 data[5], *p; - - if (!i2c_mii_valid_phy_id(phy_id)) - return 0; - - p = data; - if (reg & MII_ADDR_C45) { - *p++ = (reg >> 16) & 31; - *p++ = reg >> 8; - } - *p++ = reg; - *p++ = val >> 8; - *p++ = val; - - msg.addr = i2c_mii_phy_addr(phy_id); - msg.flags = 0; - msg.len = p - data; - msg.buf = data; - - ret = i2c_transfer(i2c, &msg, 1); - - return ret < 0 ? ret : 0; -} - -struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c) -{ - struct mii_bus *mii; - - if (!i2c_check_functionality(i2c, I2C_FUNC_I2C)) - return ERR_PTR(-EINVAL); - - mii = mdiobus_alloc(); - if (!mii) - return ERR_PTR(-ENOMEM); - - snprintf(mii->id, MII_BUS_ID_SIZE, "i2c:%s", dev_name(parent)); - mii->parent = parent; - mii->read = i2c_mii_read; - mii->write = i2c_mii_write; - mii->priv = i2c; - - return mii; -} -EXPORT_SYMBOL_GPL(mdio_i2c_alloc); - -MODULE_AUTHOR("Russell King"); -MODULE_DESCRIPTION("MDIO I2C bridge library"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/phy/mdio-ipq4019.c b/drivers/net/phy/mdio-ipq4019.c deleted file mode 100644 index 1ce81ff2f41d..000000000000 --- a/drivers/net/phy/mdio-ipq4019.c +++ /dev/null @@ -1,160 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause -/* Copyright (c) 2015, The Linux Foundation. All rights reserved. */ -/* Copyright (c) 2020 Sartura Ltd. */ - -#include <linux/delay.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/io.h> -#include <linux/iopoll.h> -#include <linux/of_address.h> -#include <linux/of_mdio.h> -#include <linux/phy.h> -#include <linux/platform_device.h> - -#define MDIO_ADDR_REG 0x44 -#define MDIO_DATA_WRITE_REG 0x48 -#define MDIO_DATA_READ_REG 0x4c -#define MDIO_CMD_REG 0x50 -#define MDIO_CMD_ACCESS_BUSY BIT(16) -#define MDIO_CMD_ACCESS_START BIT(8) -#define MDIO_CMD_ACCESS_CODE_READ 0 -#define MDIO_CMD_ACCESS_CODE_WRITE 1 - -#define ipq4019_MDIO_TIMEOUT 10000 -#define ipq4019_MDIO_SLEEP 10 - -struct ipq4019_mdio_data { - void __iomem *membase; -}; - -static int ipq4019_mdio_wait_busy(struct mii_bus *bus) -{ - struct ipq4019_mdio_data *priv = bus->priv; - unsigned int busy; - - return readl_poll_timeout(priv->membase + MDIO_CMD_REG, busy, - (busy & MDIO_CMD_ACCESS_BUSY) == 0, - ipq4019_MDIO_SLEEP, ipq4019_MDIO_TIMEOUT); -} - -static int ipq4019_mdio_read(struct mii_bus *bus, int mii_id, int regnum) -{ - struct ipq4019_mdio_data *priv = bus->priv; - unsigned int cmd; - - /* Reject clause 45 */ - if (regnum & MII_ADDR_C45) - return -EOPNOTSUPP; - - if (ipq4019_mdio_wait_busy(bus)) - return -ETIMEDOUT; - - /* issue the phy address and reg */ - writel((mii_id << 8) | regnum, priv->membase + MDIO_ADDR_REG); - - cmd = MDIO_CMD_ACCESS_START | MDIO_CMD_ACCESS_CODE_READ; - - /* issue read command */ - writel(cmd, priv->membase + MDIO_CMD_REG); - - /* Wait read complete */ - if (ipq4019_mdio_wait_busy(bus)) - return -ETIMEDOUT; - - /* Read and return data */ - return readl(priv->membase + MDIO_DATA_READ_REG); -} - -static int ipq4019_mdio_write(struct mii_bus *bus, int mii_id, int regnum, - u16 value) -{ - struct ipq4019_mdio_data *priv = bus->priv; - unsigned int cmd; - - /* Reject clause 45 */ - if (regnum & MII_ADDR_C45) - return -EOPNOTSUPP; - - if (ipq4019_mdio_wait_busy(bus)) - return -ETIMEDOUT; - - /* issue the phy address and reg */ - writel((mii_id << 8) | regnum, priv->membase + MDIO_ADDR_REG); - - /* issue write data */ - writel(value, priv->membase + MDIO_DATA_WRITE_REG); - - cmd = MDIO_CMD_ACCESS_START | MDIO_CMD_ACCESS_CODE_WRITE; - /* issue write command */ - writel(cmd, priv->membase + MDIO_CMD_REG); - - /* Wait write complete */ - if (ipq4019_mdio_wait_busy(bus)) - return -ETIMEDOUT; - - return 0; -} - -static int ipq4019_mdio_probe(struct platform_device *pdev) -{ - struct ipq4019_mdio_data *priv; - struct mii_bus *bus; - int ret; - - bus = devm_mdiobus_alloc_size(&pdev->dev, sizeof(*priv)); - if (!bus) - return -ENOMEM; - - priv = bus->priv; - - priv->membase = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(priv->membase)) - return PTR_ERR(priv->membase); - - bus->name = "ipq4019_mdio"; - bus->read = ipq4019_mdio_read; - bus->write = ipq4019_mdio_write; - bus->parent = &pdev->dev; - snprintf(bus->id, MII_BUS_ID_SIZE, "%s%d", pdev->name, pdev->id); - - ret = of_mdiobus_register(bus, pdev->dev.of_node); - if (ret) { - dev_err(&pdev->dev, "Cannot register MDIO bus!\n"); - return ret; - } - - platform_set_drvdata(pdev, bus); - - return 0; -} - -static int ipq4019_mdio_remove(struct platform_device *pdev) -{ - struct mii_bus *bus = platform_get_drvdata(pdev); - - mdiobus_unregister(bus); - - return 0; -} - -static const struct of_device_id ipq4019_mdio_dt_ids[] = { - { .compatible = "qcom,ipq4019-mdio" }, - { } -}; -MODULE_DEVICE_TABLE(of, ipq4019_mdio_dt_ids); - -static struct platform_driver ipq4019_mdio_driver = { - .probe = ipq4019_mdio_probe, - .remove = ipq4019_mdio_remove, - .driver = { - .name = "ipq4019-mdio", - .of_match_table = ipq4019_mdio_dt_ids, - }, -}; - -module_platform_driver(ipq4019_mdio_driver); - -MODULE_DESCRIPTION("ipq4019 MDIO interface driver"); -MODULE_AUTHOR("Qualcomm Atheros"); -MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/phy/mdio-ipq8064.c b/drivers/net/phy/mdio-ipq8064.c deleted file mode 100644 index 1bd18857e1c5..000000000000 --- a/drivers/net/phy/mdio-ipq8064.c +++ /dev/null @@ -1,166 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Qualcomm IPQ8064 MDIO interface driver - * - * Copyright (C) 2019 Christian Lamparter <chunkeey@gmail.com> - * Copyright (C) 2020 Ansuel Smith <ansuelsmth@gmail.com> - */ - -#include <linux/delay.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/regmap.h> -#include <linux/of_mdio.h> -#include <linux/phy.h> -#include <linux/platform_device.h> -#include <linux/mfd/syscon.h> - -/* MII address register definitions */ -#define MII_ADDR_REG_ADDR 0x10 -#define MII_BUSY BIT(0) -#define MII_WRITE BIT(1) -#define MII_CLKRANGE_60_100M (0 << 2) -#define MII_CLKRANGE_100_150M (1 << 2) -#define MII_CLKRANGE_20_35M (2 << 2) -#define MII_CLKRANGE_35_60M (3 << 2) -#define MII_CLKRANGE_150_250M (4 << 2) -#define MII_CLKRANGE_250_300M (5 << 2) -#define MII_CLKRANGE_MASK GENMASK(4, 2) -#define MII_REG_SHIFT 6 -#define MII_REG_MASK GENMASK(10, 6) -#define MII_ADDR_SHIFT 11 -#define MII_ADDR_MASK GENMASK(15, 11) - -#define MII_DATA_REG_ADDR 0x14 - -#define MII_MDIO_DELAY_USEC (1000) -#define MII_MDIO_RETRY_MSEC (10) - -struct ipq8064_mdio { - struct regmap *base; /* NSS_GMAC0_BASE */ -}; - -static int -ipq8064_mdio_wait_busy(struct ipq8064_mdio *priv) -{ - u32 busy; - - return regmap_read_poll_timeout(priv->base, MII_ADDR_REG_ADDR, busy, - !(busy & MII_BUSY), MII_MDIO_DELAY_USEC, - MII_MDIO_RETRY_MSEC * USEC_PER_MSEC); -} - -static int -ipq8064_mdio_read(struct mii_bus *bus, int phy_addr, int reg_offset) -{ - u32 miiaddr = MII_BUSY | MII_CLKRANGE_250_300M; - struct ipq8064_mdio *priv = bus->priv; - u32 ret_val; - int err; - - /* Reject clause 45 */ - if (reg_offset & MII_ADDR_C45) - return -EOPNOTSUPP; - - miiaddr |= ((phy_addr << MII_ADDR_SHIFT) & MII_ADDR_MASK) | - ((reg_offset << MII_REG_SHIFT) & MII_REG_MASK); - - regmap_write(priv->base, MII_ADDR_REG_ADDR, miiaddr); - usleep_range(8, 10); - - err = ipq8064_mdio_wait_busy(priv); - if (err) - return err; - - regmap_read(priv->base, MII_DATA_REG_ADDR, &ret_val); - return (int)ret_val; -} - -static int -ipq8064_mdio_write(struct mii_bus *bus, int phy_addr, int reg_offset, u16 data) -{ - u32 miiaddr = MII_WRITE | MII_BUSY | MII_CLKRANGE_250_300M; - struct ipq8064_mdio *priv = bus->priv; - - /* Reject clause 45 */ - if (reg_offset & MII_ADDR_C45) - return -EOPNOTSUPP; - - regmap_write(priv->base, MII_DATA_REG_ADDR, data); - - miiaddr |= ((phy_addr << MII_ADDR_SHIFT) & MII_ADDR_MASK) | - ((reg_offset << MII_REG_SHIFT) & MII_REG_MASK); - - regmap_write(priv->base, MII_ADDR_REG_ADDR, miiaddr); - usleep_range(8, 10); - - return ipq8064_mdio_wait_busy(priv); -} - -static int -ipq8064_mdio_probe(struct platform_device *pdev) -{ - struct device_node *np = pdev->dev.of_node; - struct ipq8064_mdio *priv; - struct mii_bus *bus; - int ret; - - bus = devm_mdiobus_alloc_size(&pdev->dev, sizeof(*priv)); - if (!bus) - return -ENOMEM; - - bus->name = "ipq8064_mdio_bus"; - bus->read = ipq8064_mdio_read; - bus->write = ipq8064_mdio_write; - snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii", dev_name(&pdev->dev)); - bus->parent = &pdev->dev; - - priv = bus->priv; - priv->base = device_node_to_regmap(np); - if (IS_ERR(priv->base)) { - if (priv->base == ERR_PTR(-EPROBE_DEFER)) - return -EPROBE_DEFER; - - dev_err(&pdev->dev, "error getting device regmap, error=%pe\n", - priv->base); - return PTR_ERR(priv->base); - } - - ret = of_mdiobus_register(bus, np); - if (ret) - return ret; - - platform_set_drvdata(pdev, bus); - return 0; -} - -static int -ipq8064_mdio_remove(struct platform_device *pdev) -{ - struct mii_bus *bus = platform_get_drvdata(pdev); - - mdiobus_unregister(bus); - - return 0; -} - -static const struct of_device_id ipq8064_mdio_dt_ids[] = { - { .compatible = "qcom,ipq8064-mdio" }, - { } -}; -MODULE_DEVICE_TABLE(of, ipq8064_mdio_dt_ids); - -static struct platform_driver ipq8064_mdio_driver = { - .probe = ipq8064_mdio_probe, - .remove = ipq8064_mdio_remove, - .driver = { - .name = "ipq8064-mdio", - .of_match_table = ipq8064_mdio_dt_ids, - }, -}; - -module_platform_driver(ipq8064_mdio_driver); - -MODULE_DESCRIPTION("Qualcomm IPQ8064 MDIO interface driver"); -MODULE_AUTHOR("Christian Lamparter <chunkeey@gmail.com>"); -MODULE_AUTHOR("Ansuel Smith <ansuelsmth@gmail.com>"); -MODULE_LICENSE("GPL"); diff --git a/drivers/net/phy/mdio-moxart.c b/drivers/net/phy/mdio-moxart.c deleted file mode 100644 index b72c6d185175..000000000000 --- a/drivers/net/phy/mdio-moxart.c +++ /dev/null @@ -1,187 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* MOXA ART Ethernet (RTL8201CP) MDIO interface driver - * - * Copyright (C) 2013 Jonas Jensen <jonas.jensen@gmail.com> - */ - -#include <linux/delay.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/mutex.h> -#include <linux/of_address.h> -#include <linux/of_mdio.h> -#include <linux/phy.h> -#include <linux/platform_device.h> - -#define REG_PHY_CTRL 0 -#define REG_PHY_WRITE_DATA 4 - -/* REG_PHY_CTRL */ -#define MIIWR BIT(27) /* init write sequence (auto cleared)*/ -#define MIIRD BIT(26) -#define REGAD_MASK 0x3e00000 -#define PHYAD_MASK 0x1f0000 -#define MIIRDATA_MASK 0xffff - -/* REG_PHY_WRITE_DATA */ -#define MIIWDATA_MASK 0xffff - -struct moxart_mdio_data { - void __iomem *base; -}; - -static int moxart_mdio_read(struct mii_bus *bus, int mii_id, int regnum) -{ - struct moxart_mdio_data *data = bus->priv; - u32 ctrl = 0; - unsigned int count = 5; - - dev_dbg(&bus->dev, "%s\n", __func__); - - ctrl |= MIIRD | ((mii_id << 16) & PHYAD_MASK) | - ((regnum << 21) & REGAD_MASK); - - writel(ctrl, data->base + REG_PHY_CTRL); - - do { - ctrl = readl(data->base + REG_PHY_CTRL); - - if (!(ctrl & MIIRD)) - return ctrl & MIIRDATA_MASK; - - mdelay(10); - count--; - } while (count > 0); - - dev_dbg(&bus->dev, "%s timed out\n", __func__); - - return -ETIMEDOUT; -} - -static int moxart_mdio_write(struct mii_bus *bus, int mii_id, - int regnum, u16 value) -{ - struct moxart_mdio_data *data = bus->priv; - u32 ctrl = 0; - unsigned int count = 5; - - dev_dbg(&bus->dev, "%s\n", __func__); - - ctrl |= MIIWR | ((mii_id << 16) & PHYAD_MASK) | - ((regnum << 21) & REGAD_MASK); - - value &= MIIWDATA_MASK; - - writel(value, data->base + REG_PHY_WRITE_DATA); - writel(ctrl, data->base + REG_PHY_CTRL); - - do { - ctrl = readl(data->base + REG_PHY_CTRL); - - if (!(ctrl & MIIWR)) - return 0; - - mdelay(10); - count--; - } while (count > 0); - - dev_dbg(&bus->dev, "%s timed out\n", __func__); - - return -ETIMEDOUT; -} - -static int moxart_mdio_reset(struct mii_bus *bus) -{ - int data, i; - - for (i = 0; i < PHY_MAX_ADDR; i++) { - data = moxart_mdio_read(bus, i, MII_BMCR); - if (data < 0) - continue; - - data |= BMCR_RESET; - if (moxart_mdio_write(bus, i, MII_BMCR, data) < 0) - continue; - } - - return 0; -} - -static int moxart_mdio_probe(struct platform_device *pdev) -{ - struct device_node *np = pdev->dev.of_node; - struct mii_bus *bus; - struct moxart_mdio_data *data; - int ret, i; - - bus = mdiobus_alloc_size(sizeof(*data)); - if (!bus) - return -ENOMEM; - - bus->name = "MOXA ART Ethernet MII"; - bus->read = &moxart_mdio_read; - bus->write = &moxart_mdio_write; - bus->reset = &moxart_mdio_reset; - snprintf(bus->id, MII_BUS_ID_SIZE, "%s-%d-mii", pdev->name, pdev->id); - bus->parent = &pdev->dev; - - /* Setting PHY_IGNORE_INTERRUPT here even if it has no effect, - * of_mdiobus_register() sets these PHY_POLL. - * Ideally, the interrupt from MAC controller could be used to - * detect link state changes, not polling, i.e. if there was - * a way phy_driver could set PHY_HAS_INTERRUPT but have that - * interrupt handled in ethernet drivercode. - */ - for (i = 0; i < PHY_MAX_ADDR; i++) - bus->irq[i] = PHY_IGNORE_INTERRUPT; - - data = bus->priv; - data->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(data->base)) { - ret = PTR_ERR(data->base); - goto err_out_free_mdiobus; - } - - ret = of_mdiobus_register(bus, np); - if (ret < 0) - goto err_out_free_mdiobus; - - platform_set_drvdata(pdev, bus); - - return 0; - -err_out_free_mdiobus: - mdiobus_free(bus); - return ret; -} - -static int moxart_mdio_remove(struct platform_device *pdev) -{ - struct mii_bus *bus = platform_get_drvdata(pdev); - - mdiobus_unregister(bus); - mdiobus_free(bus); - - return 0; -} - -static const struct of_device_id moxart_mdio_dt_ids[] = { - { .compatible = "moxa,moxart-mdio" }, - { } -}; -MODULE_DEVICE_TABLE(of, moxart_mdio_dt_ids); - -static struct platform_driver moxart_mdio_driver = { - .probe = moxart_mdio_probe, - .remove = moxart_mdio_remove, - .driver = { - .name = "moxart-mdio", - .of_match_table = moxart_mdio_dt_ids, - }, -}; - -module_platform_driver(moxart_mdio_driver); - -MODULE_DESCRIPTION("MOXA ART MDIO interface driver"); -MODULE_AUTHOR("Jonas Jensen <jonas.jensen@gmail.com>"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/phy/mdio-mscc-miim.c b/drivers/net/phy/mdio-mscc-miim.c deleted file mode 100644 index 11f583fd4611..000000000000 --- a/drivers/net/phy/mdio-mscc-miim.c +++ /dev/null @@ -1,212 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Driver for the MDIO interface of Microsemi network switches. - * - * Author: Alexandre Belloni <alexandre.belloni@bootlin.com> - * Copyright (c) 2017 Microsemi Corporation - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/phy.h> -#include <linux/platform_device.h> -#include <linux/bitops.h> -#include <linux/io.h> -#include <linux/iopoll.h> -#include <linux/of_mdio.h> - -#define MSCC_MIIM_REG_STATUS 0x0 -#define MSCC_MIIM_STATUS_STAT_PENDING BIT(2) -#define MSCC_MIIM_STATUS_STAT_BUSY BIT(3) -#define MSCC_MIIM_REG_CMD 0x8 -#define MSCC_MIIM_CMD_OPR_WRITE BIT(1) -#define MSCC_MIIM_CMD_OPR_READ BIT(2) -#define MSCC_MIIM_CMD_WRDATA_SHIFT 4 -#define MSCC_MIIM_CMD_REGAD_SHIFT 20 -#define MSCC_MIIM_CMD_PHYAD_SHIFT 25 -#define MSCC_MIIM_CMD_VLD BIT(31) -#define MSCC_MIIM_REG_DATA 0xC -#define MSCC_MIIM_DATA_ERROR (BIT(16) | BIT(17)) - -#define MSCC_PHY_REG_PHY_CFG 0x0 -#define PHY_CFG_PHY_ENA (BIT(0) | BIT(1) | BIT(2) | BIT(3)) -#define PHY_CFG_PHY_COMMON_RESET BIT(4) -#define PHY_CFG_PHY_RESET (BIT(5) | BIT(6) | BIT(7) | BIT(8)) -#define MSCC_PHY_REG_PHY_STATUS 0x4 - -struct mscc_miim_dev { - void __iomem *regs; - void __iomem *phy_regs; -}; - -/* When high resolution timers aren't built-in: we can't use usleep_range() as - * we would sleep way too long. Use udelay() instead. - */ -#define mscc_readl_poll_timeout(addr, val, cond, delay_us, timeout_us) \ -({ \ - if (!IS_ENABLED(CONFIG_HIGH_RES_TIMERS)) \ - readl_poll_timeout_atomic(addr, val, cond, delay_us, \ - timeout_us); \ - readl_poll_timeout(addr, val, cond, delay_us, timeout_us); \ -}) - -static int mscc_miim_wait_ready(struct mii_bus *bus) -{ - struct mscc_miim_dev *miim = bus->priv; - u32 val; - - return mscc_readl_poll_timeout(miim->regs + MSCC_MIIM_REG_STATUS, val, - !(val & MSCC_MIIM_STATUS_STAT_BUSY), 50, - 10000); -} - -static int mscc_miim_wait_pending(struct mii_bus *bus) -{ - struct mscc_miim_dev *miim = bus->priv; - u32 val; - - return mscc_readl_poll_timeout(miim->regs + MSCC_MIIM_REG_STATUS, val, - !(val & MSCC_MIIM_STATUS_STAT_PENDING), - 50, 10000); -} - -static int mscc_miim_read(struct mii_bus *bus, int mii_id, int regnum) -{ - struct mscc_miim_dev *miim = bus->priv; - u32 val; - int ret; - - ret = mscc_miim_wait_pending(bus); - if (ret) - goto out; - - writel(MSCC_MIIM_CMD_VLD | (mii_id << MSCC_MIIM_CMD_PHYAD_SHIFT) | - (regnum << MSCC_MIIM_CMD_REGAD_SHIFT) | MSCC_MIIM_CMD_OPR_READ, - miim->regs + MSCC_MIIM_REG_CMD); - - ret = mscc_miim_wait_ready(bus); - if (ret) - goto out; - - val = readl(miim->regs + MSCC_MIIM_REG_DATA); - if (val & MSCC_MIIM_DATA_ERROR) { - ret = -EIO; - goto out; - } - - ret = val & 0xFFFF; -out: - return ret; -} - -static int mscc_miim_write(struct mii_bus *bus, int mii_id, - int regnum, u16 value) -{ - struct mscc_miim_dev *miim = bus->priv; - int ret; - - ret = mscc_miim_wait_pending(bus); - if (ret < 0) - goto out; - - writel(MSCC_MIIM_CMD_VLD | (mii_id << MSCC_MIIM_CMD_PHYAD_SHIFT) | - (regnum << MSCC_MIIM_CMD_REGAD_SHIFT) | - (value << MSCC_MIIM_CMD_WRDATA_SHIFT) | - MSCC_MIIM_CMD_OPR_WRITE, - miim->regs + MSCC_MIIM_REG_CMD); - -out: - return ret; -} - -static int mscc_miim_reset(struct mii_bus *bus) -{ - struct mscc_miim_dev *miim = bus->priv; - - if (miim->phy_regs) { - writel(0, miim->phy_regs + MSCC_PHY_REG_PHY_CFG); - writel(0x1ff, miim->phy_regs + MSCC_PHY_REG_PHY_CFG); - mdelay(500); - } - - return 0; -} - -static int mscc_miim_probe(struct platform_device *pdev) -{ - struct resource *res; - struct mii_bus *bus; - struct mscc_miim_dev *dev; - int ret; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENODEV; - - bus = devm_mdiobus_alloc_size(&pdev->dev, sizeof(*dev)); - if (!bus) - return -ENOMEM; - - bus->name = "mscc_miim"; - bus->read = mscc_miim_read; - bus->write = mscc_miim_write; - bus->reset = mscc_miim_reset; - snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii", dev_name(&pdev->dev)); - bus->parent = &pdev->dev; - - dev = bus->priv; - dev->regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(dev->regs)) { - dev_err(&pdev->dev, "Unable to map MIIM registers\n"); - return PTR_ERR(dev->regs); - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (res) { - dev->phy_regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(dev->phy_regs)) { - dev_err(&pdev->dev, "Unable to map internal phy registers\n"); - return PTR_ERR(dev->phy_regs); - } - } - - ret = of_mdiobus_register(bus, pdev->dev.of_node); - if (ret < 0) { - dev_err(&pdev->dev, "Cannot register MDIO bus (%d)\n", ret); - return ret; - } - - platform_set_drvdata(pdev, bus); - - return 0; -} - -static int mscc_miim_remove(struct platform_device *pdev) -{ - struct mii_bus *bus = platform_get_drvdata(pdev); - - mdiobus_unregister(bus); - - return 0; -} - -static const struct of_device_id mscc_miim_match[] = { - { .compatible = "mscc,ocelot-miim" }, - { } -}; -MODULE_DEVICE_TABLE(of, mscc_miim_match); - -static struct platform_driver mscc_miim_driver = { - .probe = mscc_miim_probe, - .remove = mscc_miim_remove, - .driver = { - .name = "mscc-miim", - .of_match_table = mscc_miim_match, - }, -}; - -module_platform_driver(mscc_miim_driver); - -MODULE_DESCRIPTION("Microsemi MIIM driver"); -MODULE_AUTHOR("Alexandre Belloni <alexandre.belloni@bootlin.com>"); -MODULE_LICENSE("Dual MIT/GPL"); diff --git a/drivers/net/phy/mdio-mux-bcm-iproc.c b/drivers/net/phy/mdio-mux-bcm-iproc.c deleted file mode 100644 index 42fb5f166136..000000000000 --- a/drivers/net/phy/mdio-mux-bcm-iproc.c +++ /dev/null @@ -1,323 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright 2016 Broadcom - */ -#include <linux/clk.h> -#include <linux/platform_device.h> -#include <linux/device.h> -#include <linux/of_mdio.h> -#include <linux/module.h> -#include <linux/phy.h> -#include <linux/mdio-mux.h> -#include <linux/delay.h> -#include <linux/iopoll.h> - -#define MDIO_RATE_ADJ_EXT_OFFSET 0x000 -#define MDIO_RATE_ADJ_INT_OFFSET 0x004 -#define MDIO_RATE_ADJ_DIVIDENT_SHIFT 16 - -#define MDIO_SCAN_CTRL_OFFSET 0x008 -#define MDIO_SCAN_CTRL_OVRIDE_EXT_MSTR 28 - -#define MDIO_PARAM_OFFSET 0x23c -#define MDIO_PARAM_MIIM_CYCLE 29 -#define MDIO_PARAM_INTERNAL_SEL 25 -#define MDIO_PARAM_BUS_ID 22 -#define MDIO_PARAM_C45_SEL 21 -#define MDIO_PARAM_PHY_ID 16 -#define MDIO_PARAM_PHY_DATA 0 - -#define MDIO_READ_OFFSET 0x240 -#define MDIO_READ_DATA_MASK 0xffff -#define MDIO_ADDR_OFFSET 0x244 - -#define MDIO_CTRL_OFFSET 0x248 -#define MDIO_CTRL_WRITE_OP 0x1 -#define MDIO_CTRL_READ_OP 0x2 - -#define MDIO_STAT_OFFSET 0x24c -#define MDIO_STAT_DONE 1 - -#define BUS_MAX_ADDR 32 -#define EXT_BUS_START_ADDR 16 - -#define MDIO_REG_ADDR_SPACE_SIZE 0x250 - -#define MDIO_OPERATING_FREQUENCY 11000000 -#define MDIO_RATE_ADJ_DIVIDENT 1 - -struct iproc_mdiomux_desc { - void *mux_handle; - void __iomem *base; - struct device *dev; - struct mii_bus *mii_bus; - struct clk *core_clk; -}; - -static void mdio_mux_iproc_config(struct iproc_mdiomux_desc *md) -{ - u32 divisor; - u32 val; - - /* Disable external mdio master access */ - val = readl(md->base + MDIO_SCAN_CTRL_OFFSET); - val |= BIT(MDIO_SCAN_CTRL_OVRIDE_EXT_MSTR); - writel(val, md->base + MDIO_SCAN_CTRL_OFFSET); - - if (md->core_clk) { - /* use rate adjust regs to derrive the mdio's operating - * frequency from the specified core clock - */ - divisor = clk_get_rate(md->core_clk) / MDIO_OPERATING_FREQUENCY; - divisor = divisor / (MDIO_RATE_ADJ_DIVIDENT + 1); - val = divisor; - val |= MDIO_RATE_ADJ_DIVIDENT << MDIO_RATE_ADJ_DIVIDENT_SHIFT; - writel(val, md->base + MDIO_RATE_ADJ_EXT_OFFSET); - writel(val, md->base + MDIO_RATE_ADJ_INT_OFFSET); - } -} - -static int iproc_mdio_wait_for_idle(void __iomem *base, bool result) -{ - u32 val; - - return readl_poll_timeout(base + MDIO_STAT_OFFSET, val, - (val & MDIO_STAT_DONE) == result, - 2000, 1000000); -} - -/* start_miim_ops- Program and start MDIO transaction over mdio bus. - * @base: Base address - * @phyid: phyid of the selected bus. - * @reg: register offset to be read/written. - * @val :0 if read op else value to be written in @reg; - * @op: Operation that need to be carried out. - * MDIO_CTRL_READ_OP: Read transaction. - * MDIO_CTRL_WRITE_OP: Write transaction. - * - * Return value: Successful Read operation returns read reg values and write - * operation returns 0. Failure operation returns negative error code. - */ -static int start_miim_ops(void __iomem *base, - u16 phyid, u32 reg, u16 val, u32 op) -{ - u32 param; - int ret; - - writel(0, base + MDIO_CTRL_OFFSET); - ret = iproc_mdio_wait_for_idle(base, 0); - if (ret) - goto err; - - param = readl(base + MDIO_PARAM_OFFSET); - param |= phyid << MDIO_PARAM_PHY_ID; - param |= val << MDIO_PARAM_PHY_DATA; - if (reg & MII_ADDR_C45) - param |= BIT(MDIO_PARAM_C45_SEL); - - writel(param, base + MDIO_PARAM_OFFSET); - - writel(reg, base + MDIO_ADDR_OFFSET); - - writel(op, base + MDIO_CTRL_OFFSET); - - ret = iproc_mdio_wait_for_idle(base, 1); - if (ret) - goto err; - - if (op == MDIO_CTRL_READ_OP) - ret = readl(base + MDIO_READ_OFFSET) & MDIO_READ_DATA_MASK; -err: - return ret; -} - -static int iproc_mdiomux_read(struct mii_bus *bus, int phyid, int reg) -{ - struct iproc_mdiomux_desc *md = bus->priv; - int ret; - - ret = start_miim_ops(md->base, phyid, reg, 0, MDIO_CTRL_READ_OP); - if (ret < 0) - dev_err(&bus->dev, "mdiomux read operation failed!!!"); - - return ret; -} - -static int iproc_mdiomux_write(struct mii_bus *bus, - int phyid, int reg, u16 val) -{ - struct iproc_mdiomux_desc *md = bus->priv; - int ret; - - /* Write val at reg offset */ - ret = start_miim_ops(md->base, phyid, reg, val, MDIO_CTRL_WRITE_OP); - if (ret < 0) - dev_err(&bus->dev, "mdiomux write operation failed!!!"); - - return ret; -} - -static int mdio_mux_iproc_switch_fn(int current_child, int desired_child, - void *data) -{ - struct iproc_mdiomux_desc *md = data; - u32 param, bus_id; - bool bus_dir; - - /* select bus and its properties */ - bus_dir = (desired_child < EXT_BUS_START_ADDR); - bus_id = bus_dir ? desired_child : (desired_child - EXT_BUS_START_ADDR); - - param = (bus_dir ? 1 : 0) << MDIO_PARAM_INTERNAL_SEL; - param |= (bus_id << MDIO_PARAM_BUS_ID); - - writel(param, md->base + MDIO_PARAM_OFFSET); - return 0; -} - -static int mdio_mux_iproc_probe(struct platform_device *pdev) -{ - struct iproc_mdiomux_desc *md; - struct mii_bus *bus; - struct resource *res; - int rc; - - md = devm_kzalloc(&pdev->dev, sizeof(*md), GFP_KERNEL); - if (!md) - return -ENOMEM; - md->dev = &pdev->dev; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res->start & 0xfff) { - /* For backward compatibility in case the - * base address is specified with an offset. - */ - dev_info(&pdev->dev, "fix base address in dt-blob\n"); - res->start &= ~0xfff; - res->end = res->start + MDIO_REG_ADDR_SPACE_SIZE - 1; - } - md->base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(md->base)) { - dev_err(&pdev->dev, "failed to ioremap register\n"); - return PTR_ERR(md->base); - } - - md->mii_bus = devm_mdiobus_alloc(&pdev->dev); - if (!md->mii_bus) { - dev_err(&pdev->dev, "mdiomux bus alloc failed\n"); - return -ENOMEM; - } - - md->core_clk = devm_clk_get(&pdev->dev, NULL); - if (md->core_clk == ERR_PTR(-ENOENT) || - md->core_clk == ERR_PTR(-EINVAL)) - md->core_clk = NULL; - else if (IS_ERR(md->core_clk)) - return PTR_ERR(md->core_clk); - - rc = clk_prepare_enable(md->core_clk); - if (rc) { - dev_err(&pdev->dev, "failed to enable core clk\n"); - return rc; - } - - bus = md->mii_bus; - bus->priv = md; - bus->name = "iProc MDIO mux bus"; - snprintf(bus->id, MII_BUS_ID_SIZE, "%s-%d", pdev->name, pdev->id); - bus->parent = &pdev->dev; - bus->read = iproc_mdiomux_read; - bus->write = iproc_mdiomux_write; - - bus->phy_mask = ~0; - bus->dev.of_node = pdev->dev.of_node; - rc = mdiobus_register(bus); - if (rc) { - dev_err(&pdev->dev, "mdiomux registration failed\n"); - goto out_clk; - } - - platform_set_drvdata(pdev, md); - - rc = mdio_mux_init(md->dev, md->dev->of_node, mdio_mux_iproc_switch_fn, - &md->mux_handle, md, md->mii_bus); - if (rc) { - dev_info(md->dev, "mdiomux initialization failed\n"); - goto out_register; - } - - mdio_mux_iproc_config(md); - - dev_info(md->dev, "iProc mdiomux registered\n"); - return 0; - -out_register: - mdiobus_unregister(bus); -out_clk: - clk_disable_unprepare(md->core_clk); - return rc; -} - -static int mdio_mux_iproc_remove(struct platform_device *pdev) -{ - struct iproc_mdiomux_desc *md = platform_get_drvdata(pdev); - - mdio_mux_uninit(md->mux_handle); - mdiobus_unregister(md->mii_bus); - clk_disable_unprepare(md->core_clk); - - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static int mdio_mux_iproc_suspend(struct device *dev) -{ - struct iproc_mdiomux_desc *md = dev_get_drvdata(dev); - - clk_disable_unprepare(md->core_clk); - - return 0; -} - -static int mdio_mux_iproc_resume(struct device *dev) -{ - struct iproc_mdiomux_desc *md = dev_get_drvdata(dev); - int rc; - - rc = clk_prepare_enable(md->core_clk); - if (rc) { - dev_err(md->dev, "failed to enable core clk\n"); - return rc; - } - mdio_mux_iproc_config(md); - - return 0; -} -#endif - -static SIMPLE_DEV_PM_OPS(mdio_mux_iproc_pm_ops, - mdio_mux_iproc_suspend, mdio_mux_iproc_resume); - -static const struct of_device_id mdio_mux_iproc_match[] = { - { - .compatible = "brcm,mdio-mux-iproc", - }, - {}, -}; -MODULE_DEVICE_TABLE(of, mdio_mux_iproc_match); - -static struct platform_driver mdiomux_iproc_driver = { - .driver = { - .name = "mdio-mux-iproc", - .of_match_table = mdio_mux_iproc_match, - .pm = &mdio_mux_iproc_pm_ops, - }, - .probe = mdio_mux_iproc_probe, - .remove = mdio_mux_iproc_remove, -}; - -module_platform_driver(mdiomux_iproc_driver); - -MODULE_DESCRIPTION("iProc MDIO Mux Bus Driver"); -MODULE_AUTHOR("Pramod Kumar <pramod.kumar@broadcom.com>"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/phy/mdio-mux-gpio.c b/drivers/net/phy/mdio-mux-gpio.c deleted file mode 100644 index 10a758fdc9e6..000000000000 --- a/drivers/net/phy/mdio-mux-gpio.c +++ /dev/null @@ -1,98 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2011, 2012 Cavium, Inc. - */ - -#include <linux/platform_device.h> -#include <linux/device.h> -#include <linux/of_mdio.h> -#include <linux/module.h> -#include <linux/phy.h> -#include <linux/mdio-mux.h> -#include <linux/gpio/consumer.h> - -#define DRV_VERSION "1.1" -#define DRV_DESCRIPTION "GPIO controlled MDIO bus multiplexer driver" - -struct mdio_mux_gpio_state { - struct gpio_descs *gpios; - void *mux_handle; -}; - -static int mdio_mux_gpio_switch_fn(int current_child, int desired_child, - void *data) -{ - struct mdio_mux_gpio_state *s = data; - DECLARE_BITMAP(values, BITS_PER_TYPE(desired_child)); - - if (current_child == desired_child) - return 0; - - values[0] = desired_child; - - gpiod_set_array_value_cansleep(s->gpios->ndescs, s->gpios->desc, - s->gpios->info, values); - - return 0; -} - -static int mdio_mux_gpio_probe(struct platform_device *pdev) -{ - struct mdio_mux_gpio_state *s; - struct gpio_descs *gpios; - int r; - - gpios = devm_gpiod_get_array(&pdev->dev, NULL, GPIOD_OUT_LOW); - if (IS_ERR(gpios)) - return PTR_ERR(gpios); - - s = devm_kzalloc(&pdev->dev, sizeof(*s), GFP_KERNEL); - if (!s) - return -ENOMEM; - - s->gpios = gpios; - - r = mdio_mux_init(&pdev->dev, pdev->dev.of_node, - mdio_mux_gpio_switch_fn, &s->mux_handle, s, NULL); - - if (r != 0) - return r; - - pdev->dev.platform_data = s; - return 0; -} - -static int mdio_mux_gpio_remove(struct platform_device *pdev) -{ - struct mdio_mux_gpio_state *s = dev_get_platdata(&pdev->dev); - mdio_mux_uninit(s->mux_handle); - return 0; -} - -static const struct of_device_id mdio_mux_gpio_match[] = { - { - .compatible = "mdio-mux-gpio", - }, - { - /* Legacy compatible property. */ - .compatible = "cavium,mdio-mux-sn74cbtlv3253", - }, - {}, -}; -MODULE_DEVICE_TABLE(of, mdio_mux_gpio_match); - -static struct platform_driver mdio_mux_gpio_driver = { - .driver = { - .name = "mdio-mux-gpio", - .of_match_table = mdio_mux_gpio_match, - }, - .probe = mdio_mux_gpio_probe, - .remove = mdio_mux_gpio_remove, -}; - -module_platform_driver(mdio_mux_gpio_driver); - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_VERSION(DRV_VERSION); -MODULE_AUTHOR("David Daney"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/phy/mdio-mux-meson-g12a.c b/drivers/net/phy/mdio-mux-meson-g12a.c deleted file mode 100644 index bf86c9c7a288..000000000000 --- a/drivers/net/phy/mdio-mux-meson-g12a.c +++ /dev/null @@ -1,380 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright (c) 2019 Baylibre, SAS. - * Author: Jerome Brunet <jbrunet@baylibre.com> - */ - -#include <linux/bitfield.h> -#include <linux/clk.h> -#include <linux/clk-provider.h> -#include <linux/device.h> -#include <linux/io.h> -#include <linux/iopoll.h> -#include <linux/mdio-mux.h> -#include <linux/module.h> -#include <linux/phy.h> -#include <linux/platform_device.h> - -#define ETH_PLL_STS 0x40 -#define ETH_PLL_CTL0 0x44 -#define PLL_CTL0_LOCK_DIG BIT(30) -#define PLL_CTL0_RST BIT(29) -#define PLL_CTL0_EN BIT(28) -#define PLL_CTL0_SEL BIT(23) -#define PLL_CTL0_N GENMASK(14, 10) -#define PLL_CTL0_M GENMASK(8, 0) -#define PLL_LOCK_TIMEOUT 1000000 -#define PLL_MUX_NUM_PARENT 2 -#define ETH_PLL_CTL1 0x48 -#define ETH_PLL_CTL2 0x4c -#define ETH_PLL_CTL3 0x50 -#define ETH_PLL_CTL4 0x54 -#define ETH_PLL_CTL5 0x58 -#define ETH_PLL_CTL6 0x5c -#define ETH_PLL_CTL7 0x60 - -#define ETH_PHY_CNTL0 0x80 -#define EPHY_G12A_ID 0x33010180 -#define ETH_PHY_CNTL1 0x84 -#define PHY_CNTL1_ST_MODE GENMASK(2, 0) -#define PHY_CNTL1_ST_PHYADD GENMASK(7, 3) -#define EPHY_DFLT_ADD 8 -#define PHY_CNTL1_MII_MODE GENMASK(15, 14) -#define EPHY_MODE_RMII 0x1 -#define PHY_CNTL1_CLK_EN BIT(16) -#define PHY_CNTL1_CLKFREQ BIT(17) -#define PHY_CNTL1_PHY_ENB BIT(18) -#define ETH_PHY_CNTL2 0x88 -#define PHY_CNTL2_USE_INTERNAL BIT(5) -#define PHY_CNTL2_SMI_SRC_MAC BIT(6) -#define PHY_CNTL2_RX_CLK_EPHY BIT(9) - -#define MESON_G12A_MDIO_EXTERNAL_ID 0 -#define MESON_G12A_MDIO_INTERNAL_ID 1 - -struct g12a_mdio_mux { - bool pll_is_enabled; - void __iomem *regs; - void *mux_handle; - struct clk *pclk; - struct clk *pll; -}; - -struct g12a_ephy_pll { - void __iomem *base; - struct clk_hw hw; -}; - -#define g12a_ephy_pll_to_dev(_hw) \ - container_of(_hw, struct g12a_ephy_pll, hw) - -static unsigned long g12a_ephy_pll_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct g12a_ephy_pll *pll = g12a_ephy_pll_to_dev(hw); - u32 val, m, n; - - val = readl(pll->base + ETH_PLL_CTL0); - m = FIELD_GET(PLL_CTL0_M, val); - n = FIELD_GET(PLL_CTL0_N, val); - - return parent_rate * m / n; -} - -static int g12a_ephy_pll_enable(struct clk_hw *hw) -{ - struct g12a_ephy_pll *pll = g12a_ephy_pll_to_dev(hw); - u32 val = readl(pll->base + ETH_PLL_CTL0); - - /* Apply both enable an reset */ - val |= PLL_CTL0_RST | PLL_CTL0_EN; - writel(val, pll->base + ETH_PLL_CTL0); - - /* Clear the reset to let PLL lock */ - val &= ~PLL_CTL0_RST; - writel(val, pll->base + ETH_PLL_CTL0); - - /* Poll on the digital lock instead of the usual analog lock - * This is done because bit 31 is unreliable on some SoC. Bit - * 31 may indicate that the PLL is not lock eventhough the clock - * is actually running - */ - return readl_poll_timeout(pll->base + ETH_PLL_CTL0, val, - val & PLL_CTL0_LOCK_DIG, 0, PLL_LOCK_TIMEOUT); -} - -static void g12a_ephy_pll_disable(struct clk_hw *hw) -{ - struct g12a_ephy_pll *pll = g12a_ephy_pll_to_dev(hw); - u32 val; - - val = readl(pll->base + ETH_PLL_CTL0); - val &= ~PLL_CTL0_EN; - val |= PLL_CTL0_RST; - writel(val, pll->base + ETH_PLL_CTL0); -} - -static int g12a_ephy_pll_is_enabled(struct clk_hw *hw) -{ - struct g12a_ephy_pll *pll = g12a_ephy_pll_to_dev(hw); - unsigned int val; - - val = readl(pll->base + ETH_PLL_CTL0); - - return (val & PLL_CTL0_LOCK_DIG) ? 1 : 0; -} - -static int g12a_ephy_pll_init(struct clk_hw *hw) -{ - struct g12a_ephy_pll *pll = g12a_ephy_pll_to_dev(hw); - - /* Apply PLL HW settings */ - writel(0x29c0040a, pll->base + ETH_PLL_CTL0); - writel(0x927e0000, pll->base + ETH_PLL_CTL1); - writel(0xac5f49e5, pll->base + ETH_PLL_CTL2); - writel(0x00000000, pll->base + ETH_PLL_CTL3); - writel(0x00000000, pll->base + ETH_PLL_CTL4); - writel(0x20200000, pll->base + ETH_PLL_CTL5); - writel(0x0000c002, pll->base + ETH_PLL_CTL6); - writel(0x00000023, pll->base + ETH_PLL_CTL7); - - return 0; -} - -static const struct clk_ops g12a_ephy_pll_ops = { - .recalc_rate = g12a_ephy_pll_recalc_rate, - .is_enabled = g12a_ephy_pll_is_enabled, - .enable = g12a_ephy_pll_enable, - .disable = g12a_ephy_pll_disable, - .init = g12a_ephy_pll_init, -}; - -static int g12a_enable_internal_mdio(struct g12a_mdio_mux *priv) -{ - int ret; - - /* Enable the phy clock */ - if (!priv->pll_is_enabled) { - ret = clk_prepare_enable(priv->pll); - if (ret) - return ret; - } - - priv->pll_is_enabled = true; - - /* Initialize ephy control */ - writel(EPHY_G12A_ID, priv->regs + ETH_PHY_CNTL0); - writel(FIELD_PREP(PHY_CNTL1_ST_MODE, 3) | - FIELD_PREP(PHY_CNTL1_ST_PHYADD, EPHY_DFLT_ADD) | - FIELD_PREP(PHY_CNTL1_MII_MODE, EPHY_MODE_RMII) | - PHY_CNTL1_CLK_EN | - PHY_CNTL1_CLKFREQ | - PHY_CNTL1_PHY_ENB, - priv->regs + ETH_PHY_CNTL1); - writel(PHY_CNTL2_USE_INTERNAL | - PHY_CNTL2_SMI_SRC_MAC | - PHY_CNTL2_RX_CLK_EPHY, - priv->regs + ETH_PHY_CNTL2); - - return 0; -} - -static int g12a_enable_external_mdio(struct g12a_mdio_mux *priv) -{ - /* Reset the mdio bus mux */ - writel_relaxed(0x0, priv->regs + ETH_PHY_CNTL2); - - /* Disable the phy clock if enabled */ - if (priv->pll_is_enabled) { - clk_disable_unprepare(priv->pll); - priv->pll_is_enabled = false; - } - - return 0; -} - -static int g12a_mdio_switch_fn(int current_child, int desired_child, - void *data) -{ - struct g12a_mdio_mux *priv = dev_get_drvdata(data); - - if (current_child == desired_child) - return 0; - - switch (desired_child) { - case MESON_G12A_MDIO_EXTERNAL_ID: - return g12a_enable_external_mdio(priv); - case MESON_G12A_MDIO_INTERNAL_ID: - return g12a_enable_internal_mdio(priv); - default: - return -EINVAL; - } -} - -static const struct of_device_id g12a_mdio_mux_match[] = { - { .compatible = "amlogic,g12a-mdio-mux", }, - {}, -}; -MODULE_DEVICE_TABLE(of, g12a_mdio_mux_match); - -static int g12a_ephy_glue_clk_register(struct device *dev) -{ - struct g12a_mdio_mux *priv = dev_get_drvdata(dev); - const char *parent_names[PLL_MUX_NUM_PARENT]; - struct clk_init_data init; - struct g12a_ephy_pll *pll; - struct clk_mux *mux; - struct clk *clk; - char *name; - int i; - - /* get the mux parents */ - for (i = 0; i < PLL_MUX_NUM_PARENT; i++) { - char in_name[8]; - - snprintf(in_name, sizeof(in_name), "clkin%d", i); - clk = devm_clk_get(dev, in_name); - if (IS_ERR(clk)) { - if (PTR_ERR(clk) != -EPROBE_DEFER) - dev_err(dev, "Missing clock %s\n", in_name); - return PTR_ERR(clk); - } - - parent_names[i] = __clk_get_name(clk); - } - - /* create the input mux */ - mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL); - if (!mux) - return -ENOMEM; - - name = kasprintf(GFP_KERNEL, "%s#mux", dev_name(dev)); - if (!name) - return -ENOMEM; - - init.name = name; - init.ops = &clk_mux_ro_ops; - init.flags = 0; - init.parent_names = parent_names; - init.num_parents = PLL_MUX_NUM_PARENT; - - mux->reg = priv->regs + ETH_PLL_CTL0; - mux->shift = __ffs(PLL_CTL0_SEL); - mux->mask = PLL_CTL0_SEL >> mux->shift; - mux->hw.init = &init; - - clk = devm_clk_register(dev, &mux->hw); - kfree(name); - if (IS_ERR(clk)) { - dev_err(dev, "failed to register input mux\n"); - return PTR_ERR(clk); - } - - /* create the pll */ - pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL); - if (!pll) - return -ENOMEM; - - name = kasprintf(GFP_KERNEL, "%s#pll", dev_name(dev)); - if (!name) - return -ENOMEM; - - init.name = name; - init.ops = &g12a_ephy_pll_ops; - init.flags = 0; - parent_names[0] = __clk_get_name(clk); - init.parent_names = parent_names; - init.num_parents = 1; - - pll->base = priv->regs; - pll->hw.init = &init; - - clk = devm_clk_register(dev, &pll->hw); - kfree(name); - if (IS_ERR(clk)) { - dev_err(dev, "failed to register input mux\n"); - return PTR_ERR(clk); - } - - priv->pll = clk; - - return 0; -} - -static int g12a_mdio_mux_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct g12a_mdio_mux *priv; - int ret; - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - platform_set_drvdata(pdev, priv); - - priv->regs = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(priv->regs)) - return PTR_ERR(priv->regs); - - priv->pclk = devm_clk_get(dev, "pclk"); - if (IS_ERR(priv->pclk)) { - ret = PTR_ERR(priv->pclk); - if (ret != -EPROBE_DEFER) - dev_err(dev, "failed to get peripheral clock\n"); - return ret; - } - - /* Make sure the device registers are clocked */ - ret = clk_prepare_enable(priv->pclk); - if (ret) { - dev_err(dev, "failed to enable peripheral clock"); - return ret; - } - - /* Register PLL in CCF */ - ret = g12a_ephy_glue_clk_register(dev); - if (ret) - goto err; - - ret = mdio_mux_init(dev, dev->of_node, g12a_mdio_switch_fn, - &priv->mux_handle, dev, NULL); - if (ret) { - if (ret != -EPROBE_DEFER) - dev_err(dev, "mdio multiplexer init failed: %d", ret); - goto err; - } - - return 0; - -err: - clk_disable_unprepare(priv->pclk); - return ret; -} - -static int g12a_mdio_mux_remove(struct platform_device *pdev) -{ - struct g12a_mdio_mux *priv = platform_get_drvdata(pdev); - - mdio_mux_uninit(priv->mux_handle); - - if (priv->pll_is_enabled) - clk_disable_unprepare(priv->pll); - - clk_disable_unprepare(priv->pclk); - - return 0; -} - -static struct platform_driver g12a_mdio_mux_driver = { - .probe = g12a_mdio_mux_probe, - .remove = g12a_mdio_mux_remove, - .driver = { - .name = "g12a-mdio_mux", - .of_match_table = g12a_mdio_mux_match, - }, -}; -module_platform_driver(g12a_mdio_mux_driver); - -MODULE_DESCRIPTION("Amlogic G12a MDIO multiplexer driver"); -MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/phy/mdio-mux-mmioreg.c b/drivers/net/phy/mdio-mux-mmioreg.c deleted file mode 100644 index d1a8780e24d8..000000000000 --- a/drivers/net/phy/mdio-mux-mmioreg.c +++ /dev/null @@ -1,204 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Simple memory-mapped device MDIO MUX driver - * - * Author: Timur Tabi <timur@freescale.com> - * - * Copyright 2012 Freescale Semiconductor, Inc. - */ - -#include <linux/platform_device.h> -#include <linux/device.h> -#include <linux/of_address.h> -#include <linux/of_mdio.h> -#include <linux/module.h> -#include <linux/phy.h> -#include <linux/mdio-mux.h> - -struct mdio_mux_mmioreg_state { - void *mux_handle; - phys_addr_t phys; - unsigned int iosize; - unsigned int mask; -}; - -/* - * MDIO multiplexing switch function - * - * This function is called by the mdio-mux layer when it thinks the mdio bus - * multiplexer needs to switch. - * - * 'current_child' is the current value of the mux register (masked via - * s->mask). - * - * 'desired_child' is the value of the 'reg' property of the target child MDIO - * node. - * - * The first time this function is called, current_child == -1. - * - * If current_child == desired_child, then the mux is already set to the - * correct bus. - */ -static int mdio_mux_mmioreg_switch_fn(int current_child, int desired_child, - void *data) -{ - struct mdio_mux_mmioreg_state *s = data; - - if (current_child ^ desired_child) { - void __iomem *p = ioremap(s->phys, s->iosize); - if (!p) - return -ENOMEM; - - switch (s->iosize) { - case sizeof(uint8_t): { - uint8_t x, y; - - x = ioread8(p); - y = (x & ~s->mask) | desired_child; - if (x != y) { - iowrite8((x & ~s->mask) | desired_child, p); - pr_debug("%s: %02x -> %02x\n", __func__, x, y); - } - - break; - } - case sizeof(uint16_t): { - uint16_t x, y; - - x = ioread16(p); - y = (x & ~s->mask) | desired_child; - if (x != y) { - iowrite16((x & ~s->mask) | desired_child, p); - pr_debug("%s: %04x -> %04x\n", __func__, x, y); - } - - break; - } - case sizeof(uint32_t): { - uint32_t x, y; - - x = ioread32(p); - y = (x & ~s->mask) | desired_child; - if (x != y) { - iowrite32((x & ~s->mask) | desired_child, p); - pr_debug("%s: %08x -> %08x\n", __func__, x, y); - } - - break; - } - } - - iounmap(p); - } - - return 0; -} - -static int mdio_mux_mmioreg_probe(struct platform_device *pdev) -{ - struct device_node *np2, *np = pdev->dev.of_node; - struct mdio_mux_mmioreg_state *s; - struct resource res; - const __be32 *iprop; - int len, ret; - - dev_dbg(&pdev->dev, "probing node %pOF\n", np); - - s = devm_kzalloc(&pdev->dev, sizeof(*s), GFP_KERNEL); - if (!s) - return -ENOMEM; - - ret = of_address_to_resource(np, 0, &res); - if (ret) { - dev_err(&pdev->dev, "could not obtain memory map for node %pOF\n", - np); - return ret; - } - s->phys = res.start; - - s->iosize = resource_size(&res); - if (s->iosize != sizeof(uint8_t) && - s->iosize != sizeof(uint16_t) && - s->iosize != sizeof(uint32_t)) { - dev_err(&pdev->dev, "only 8/16/32-bit registers are supported\n"); - return -EINVAL; - } - - iprop = of_get_property(np, "mux-mask", &len); - if (!iprop || len != sizeof(uint32_t)) { - dev_err(&pdev->dev, "missing or invalid mux-mask property\n"); - return -ENODEV; - } - if (be32_to_cpup(iprop) >= BIT(s->iosize * 8)) { - dev_err(&pdev->dev, "only 8/16/32-bit registers are supported\n"); - return -EINVAL; - } - s->mask = be32_to_cpup(iprop); - - /* - * Verify that the 'reg' property of each child MDIO bus does not - * set any bits outside of the 'mask'. - */ - for_each_available_child_of_node(np, np2) { - iprop = of_get_property(np2, "reg", &len); - if (!iprop || len != sizeof(uint32_t)) { - dev_err(&pdev->dev, "mdio-mux child node %pOF is " - "missing a 'reg' property\n", np2); - of_node_put(np2); - return -ENODEV; - } - if (be32_to_cpup(iprop) & ~s->mask) { - dev_err(&pdev->dev, "mdio-mux child node %pOF has " - "a 'reg' value with unmasked bits\n", - np2); - of_node_put(np2); - return -ENODEV; - } - } - - ret = mdio_mux_init(&pdev->dev, pdev->dev.of_node, - mdio_mux_mmioreg_switch_fn, - &s->mux_handle, s, NULL); - if (ret) { - if (ret != -EPROBE_DEFER) - dev_err(&pdev->dev, - "failed to register mdio-mux bus %pOF\n", np); - return ret; - } - - pdev->dev.platform_data = s; - - return 0; -} - -static int mdio_mux_mmioreg_remove(struct platform_device *pdev) -{ - struct mdio_mux_mmioreg_state *s = dev_get_platdata(&pdev->dev); - - mdio_mux_uninit(s->mux_handle); - - return 0; -} - -static const struct of_device_id mdio_mux_mmioreg_match[] = { - { - .compatible = "mdio-mux-mmioreg", - }, - {}, -}; -MODULE_DEVICE_TABLE(of, mdio_mux_mmioreg_match); - -static struct platform_driver mdio_mux_mmioreg_driver = { - .driver = { - .name = "mdio-mux-mmioreg", - .of_match_table = mdio_mux_mmioreg_match, - }, - .probe = mdio_mux_mmioreg_probe, - .remove = mdio_mux_mmioreg_remove, -}; - -module_platform_driver(mdio_mux_mmioreg_driver); - -MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); -MODULE_DESCRIPTION("Memory-mapped device MDIO MUX driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/phy/mdio-mux-multiplexer.c b/drivers/net/phy/mdio-mux-multiplexer.c deleted file mode 100644 index d6564381aa3e..000000000000 --- a/drivers/net/phy/mdio-mux-multiplexer.c +++ /dev/null @@ -1,122 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* MDIO bus multiplexer using kernel multiplexer subsystem - * - * Copyright 2019 NXP - */ - -#include <linux/platform_device.h> -#include <linux/mdio-mux.h> -#include <linux/module.h> -#include <linux/mux/consumer.h> - -struct mdio_mux_multiplexer_state { - struct mux_control *muxc; - bool do_deselect; - void *mux_handle; -}; - -/** - * mdio_mux_multiplexer_switch_fn - This function is called by the mdio-mux - * layer when it thinks the mdio bus - * multiplexer needs to switch. - * @current_child: current value of the mux register. - * @desired_child: value of the 'reg' property of the target child MDIO node. - * @data: Private data used by this switch_fn passed to mdio_mux_init function - * via mdio_mux_init(.., .., .., .., data, ..). - * - * The first time this function is called, current_child == -1. - * If current_child == desired_child, then the mux is already set to the - * correct bus. - */ -static int mdio_mux_multiplexer_switch_fn(int current_child, int desired_child, - void *data) -{ - struct platform_device *pdev; - struct mdio_mux_multiplexer_state *s; - int ret = 0; - - pdev = (struct platform_device *)data; - s = platform_get_drvdata(pdev); - - if (!(current_child ^ desired_child)) - return 0; - - if (s->do_deselect) - ret = mux_control_deselect(s->muxc); - if (ret) { - dev_err(&pdev->dev, "mux_control_deselect failed in %s: %d\n", - __func__, ret); - return ret; - } - - ret = mux_control_select(s->muxc, desired_child); - if (!ret) { - dev_dbg(&pdev->dev, "%s %d -> %d\n", __func__, current_child, - desired_child); - s->do_deselect = true; - } else { - s->do_deselect = false; - } - - return ret; -} - -static int mdio_mux_multiplexer_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct mdio_mux_multiplexer_state *s; - int ret = 0; - - s = devm_kzalloc(&pdev->dev, sizeof(*s), GFP_KERNEL); - if (!s) - return -ENOMEM; - - s->muxc = devm_mux_control_get(dev, NULL); - if (IS_ERR(s->muxc)) { - ret = PTR_ERR(s->muxc); - if (ret != -EPROBE_DEFER) - dev_err(&pdev->dev, "Failed to get mux: %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, s); - - ret = mdio_mux_init(&pdev->dev, pdev->dev.of_node, - mdio_mux_multiplexer_switch_fn, &s->mux_handle, - pdev, NULL); - - return ret; -} - -static int mdio_mux_multiplexer_remove(struct platform_device *pdev) -{ - struct mdio_mux_multiplexer_state *s = platform_get_drvdata(pdev); - - mdio_mux_uninit(s->mux_handle); - - if (s->do_deselect) - mux_control_deselect(s->muxc); - - return 0; -} - -static const struct of_device_id mdio_mux_multiplexer_match[] = { - { .compatible = "mdio-mux-multiplexer", }, - {}, -}; -MODULE_DEVICE_TABLE(of, mdio_mux_multiplexer_match); - -static struct platform_driver mdio_mux_multiplexer_driver = { - .driver = { - .name = "mdio-mux-multiplexer", - .of_match_table = mdio_mux_multiplexer_match, - }, - .probe = mdio_mux_multiplexer_probe, - .remove = mdio_mux_multiplexer_remove, -}; - -module_platform_driver(mdio_mux_multiplexer_driver); - -MODULE_DESCRIPTION("MDIO bus multiplexer using kernel multiplexer subsystem"); -MODULE_AUTHOR("Pankaj Bansal <pankaj.bansal@nxp.com>"); -MODULE_LICENSE("GPL"); diff --git a/drivers/net/phy/mdio-mux.c b/drivers/net/phy/mdio-mux.c deleted file mode 100644 index 6a1d3540210b..000000000000 --- a/drivers/net/phy/mdio-mux.c +++ /dev/null @@ -1,210 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2011, 2012 Cavium, Inc. - */ - -#include <linux/platform_device.h> -#include <linux/mdio-mux.h> -#include <linux/of_mdio.h> -#include <linux/device.h> -#include <linux/module.h> -#include <linux/phy.h> - -#define DRV_DESCRIPTION "MDIO bus multiplexer driver" - -struct mdio_mux_child_bus; - -struct mdio_mux_parent_bus { - struct mii_bus *mii_bus; - int current_child; - int parent_id; - void *switch_data; - int (*switch_fn)(int current_child, int desired_child, void *data); - - /* List of our children linked through their next fields. */ - struct mdio_mux_child_bus *children; -}; - -struct mdio_mux_child_bus { - struct mii_bus *mii_bus; - struct mdio_mux_parent_bus *parent; - struct mdio_mux_child_bus *next; - int bus_number; -}; - -/* - * The parent bus' lock is used to order access to the switch_fn. - */ -static int mdio_mux_read(struct mii_bus *bus, int phy_id, int regnum) -{ - struct mdio_mux_child_bus *cb = bus->priv; - struct mdio_mux_parent_bus *pb = cb->parent; - int r; - - mutex_lock_nested(&pb->mii_bus->mdio_lock, MDIO_MUTEX_MUX); - r = pb->switch_fn(pb->current_child, cb->bus_number, pb->switch_data); - if (r) - goto out; - - pb->current_child = cb->bus_number; - - r = pb->mii_bus->read(pb->mii_bus, phy_id, regnum); -out: - mutex_unlock(&pb->mii_bus->mdio_lock); - - return r; -} - -/* - * The parent bus' lock is used to order access to the switch_fn. - */ -static int mdio_mux_write(struct mii_bus *bus, int phy_id, - int regnum, u16 val) -{ - struct mdio_mux_child_bus *cb = bus->priv; - struct mdio_mux_parent_bus *pb = cb->parent; - - int r; - - mutex_lock_nested(&pb->mii_bus->mdio_lock, MDIO_MUTEX_MUX); - r = pb->switch_fn(pb->current_child, cb->bus_number, pb->switch_data); - if (r) - goto out; - - pb->current_child = cb->bus_number; - - r = pb->mii_bus->write(pb->mii_bus, phy_id, regnum, val); -out: - mutex_unlock(&pb->mii_bus->mdio_lock); - - return r; -} - -static int parent_count; - -int mdio_mux_init(struct device *dev, - struct device_node *mux_node, - int (*switch_fn)(int cur, int desired, void *data), - void **mux_handle, - void *data, - struct mii_bus *mux_bus) -{ - struct device_node *parent_bus_node; - struct device_node *child_bus_node; - int r, ret_val; - struct mii_bus *parent_bus; - struct mdio_mux_parent_bus *pb; - struct mdio_mux_child_bus *cb; - - if (!mux_node) - return -ENODEV; - - if (!mux_bus) { - parent_bus_node = of_parse_phandle(mux_node, - "mdio-parent-bus", 0); - - if (!parent_bus_node) - return -ENODEV; - - parent_bus = of_mdio_find_bus(parent_bus_node); - if (!parent_bus) { - ret_val = -EPROBE_DEFER; - goto err_parent_bus; - } - } else { - parent_bus_node = NULL; - parent_bus = mux_bus; - get_device(&parent_bus->dev); - } - - pb = devm_kzalloc(dev, sizeof(*pb), GFP_KERNEL); - if (!pb) { - ret_val = -ENOMEM; - goto err_pb_kz; - } - - pb->switch_data = data; - pb->switch_fn = switch_fn; - pb->current_child = -1; - pb->parent_id = parent_count++; - pb->mii_bus = parent_bus; - - ret_val = -ENODEV; - for_each_available_child_of_node(mux_node, child_bus_node) { - int v; - - r = of_property_read_u32(child_bus_node, "reg", &v); - if (r) { - dev_err(dev, - "Error: Failed to find reg for child %pOF\n", - child_bus_node); - continue; - } - - cb = devm_kzalloc(dev, sizeof(*cb), GFP_KERNEL); - if (!cb) { - ret_val = -ENOMEM; - continue; - } - cb->bus_number = v; - cb->parent = pb; - - cb->mii_bus = mdiobus_alloc(); - if (!cb->mii_bus) { - ret_val = -ENOMEM; - devm_kfree(dev, cb); - continue; - } - cb->mii_bus->priv = cb; - - cb->mii_bus->name = "mdio_mux"; - snprintf(cb->mii_bus->id, MII_BUS_ID_SIZE, "%x.%x", - pb->parent_id, v); - cb->mii_bus->parent = dev; - cb->mii_bus->read = mdio_mux_read; - cb->mii_bus->write = mdio_mux_write; - r = of_mdiobus_register(cb->mii_bus, child_bus_node); - if (r) { - dev_err(dev, - "Error: Failed to register MDIO bus for child %pOF\n", - child_bus_node); - mdiobus_free(cb->mii_bus); - devm_kfree(dev, cb); - } else { - cb->next = pb->children; - pb->children = cb; - } - } - if (pb->children) { - *mux_handle = pb; - return 0; - } - - dev_err(dev, "Error: No acceptable child buses found\n"); - devm_kfree(dev, pb); -err_pb_kz: - put_device(&parent_bus->dev); -err_parent_bus: - of_node_put(parent_bus_node); - return ret_val; -} -EXPORT_SYMBOL_GPL(mdio_mux_init); - -void mdio_mux_uninit(void *mux_handle) -{ - struct mdio_mux_parent_bus *pb = mux_handle; - struct mdio_mux_child_bus *cb = pb->children; - - while (cb) { - mdiobus_unregister(cb->mii_bus); - mdiobus_free(cb->mii_bus); - cb = cb->next; - } - - put_device(&pb->mii_bus->dev); -} -EXPORT_SYMBOL_GPL(mdio_mux_uninit); - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR("David Daney"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/phy/mdio-mvusb.c b/drivers/net/phy/mdio-mvusb.c deleted file mode 100644 index d5eabddfdf51..000000000000 --- a/drivers/net/phy/mdio-mvusb.c +++ /dev/null @@ -1,120 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/of_mdio.h> -#include <linux/phy.h> -#include <linux/usb.h> - -#define USB_MARVELL_VID 0x1286 - -static const struct usb_device_id mvusb_mdio_table[] = { - { USB_DEVICE(USB_MARVELL_VID, 0x1fa4) }, - - {} -}; -MODULE_DEVICE_TABLE(usb, mvusb_mdio_table); - -enum { - MVUSB_CMD_PREAMBLE0, - MVUSB_CMD_PREAMBLE1, - MVUSB_CMD_ADDR, - MVUSB_CMD_VAL, -}; - -struct mvusb_mdio { - struct usb_device *udev; - struct mii_bus *mdio; - - __le16 buf[4]; -}; - -static int mvusb_mdio_read(struct mii_bus *mdio, int dev, int reg) -{ - struct mvusb_mdio *mvusb = mdio->priv; - int err, alen; - - if (dev & MII_ADDR_C45) - return -EOPNOTSUPP; - - mvusb->buf[MVUSB_CMD_ADDR] = cpu_to_le16(0xa400 | (dev << 5) | reg); - - err = usb_bulk_msg(mvusb->udev, usb_sndbulkpipe(mvusb->udev, 2), - mvusb->buf, 6, &alen, 100); - if (err) - return err; - - err = usb_bulk_msg(mvusb->udev, usb_rcvbulkpipe(mvusb->udev, 6), - &mvusb->buf[MVUSB_CMD_VAL], 2, &alen, 100); - if (err) - return err; - - return le16_to_cpu(mvusb->buf[MVUSB_CMD_VAL]); -} - -static int mvusb_mdio_write(struct mii_bus *mdio, int dev, int reg, u16 val) -{ - struct mvusb_mdio *mvusb = mdio->priv; - int alen; - - if (dev & MII_ADDR_C45) - return -EOPNOTSUPP; - - mvusb->buf[MVUSB_CMD_ADDR] = cpu_to_le16(0x8000 | (dev << 5) | reg); - mvusb->buf[MVUSB_CMD_VAL] = cpu_to_le16(val); - - return usb_bulk_msg(mvusb->udev, usb_sndbulkpipe(mvusb->udev, 2), - mvusb->buf, 8, &alen, 100); -} - -static int mvusb_mdio_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - struct device *dev = &interface->dev; - struct mvusb_mdio *mvusb; - struct mii_bus *mdio; - - mdio = devm_mdiobus_alloc_size(dev, sizeof(*mvusb)); - if (!mdio) - return -ENOMEM; - - mvusb = mdio->priv; - mvusb->mdio = mdio; - mvusb->udev = usb_get_dev(interface_to_usbdev(interface)); - - /* Reversed from USB PCAPs, no idea what these mean. */ - mvusb->buf[MVUSB_CMD_PREAMBLE0] = cpu_to_le16(0xe800); - mvusb->buf[MVUSB_CMD_PREAMBLE1] = cpu_to_le16(0x0001); - - snprintf(mdio->id, MII_BUS_ID_SIZE, "mvusb-%s", dev_name(dev)); - mdio->name = mdio->id; - mdio->parent = dev; - mdio->read = mvusb_mdio_read; - mdio->write = mvusb_mdio_write; - - usb_set_intfdata(interface, mvusb); - return of_mdiobus_register(mdio, dev->of_node); -} - -static void mvusb_mdio_disconnect(struct usb_interface *interface) -{ - struct mvusb_mdio *mvusb = usb_get_intfdata(interface); - struct usb_device *udev = mvusb->udev; - - mdiobus_unregister(mvusb->mdio); - usb_set_intfdata(interface, NULL); - usb_put_dev(udev); -} - -static struct usb_driver mvusb_mdio_driver = { - .name = "mvusb_mdio", - .id_table = mvusb_mdio_table, - .probe = mvusb_mdio_probe, - .disconnect = mvusb_mdio_disconnect, -}; - -module_usb_driver(mvusb_mdio_driver); - -MODULE_AUTHOR("Tobias Waldekranz <tobias@waldekranz.com>"); -MODULE_DESCRIPTION("Marvell USB MDIO Adapter"); -MODULE_LICENSE("GPL"); diff --git a/drivers/net/phy/mdio-octeon.c b/drivers/net/phy/mdio-octeon.c deleted file mode 100644 index d1e1009d51af..000000000000 --- a/drivers/net/phy/mdio-octeon.c +++ /dev/null @@ -1,115 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2009-2015 Cavium, Inc. - */ - -#include <linux/platform_device.h> -#include <linux/of_address.h> -#include <linux/of_mdio.h> -#include <linux/module.h> -#include <linux/gfp.h> -#include <linux/phy.h> -#include <linux/io.h> - -#include "mdio-cavium.h" - -static int octeon_mdiobus_probe(struct platform_device *pdev) -{ - struct cavium_mdiobus *bus; - struct mii_bus *mii_bus; - struct resource *res_mem; - resource_size_t mdio_phys; - resource_size_t regsize; - union cvmx_smix_en smi_en; - int err = -ENOENT; - - mii_bus = devm_mdiobus_alloc_size(&pdev->dev, sizeof(*bus)); - if (!mii_bus) - return -ENOMEM; - - res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res_mem == NULL) { - dev_err(&pdev->dev, "found no memory resource\n"); - return -ENXIO; - } - - bus = mii_bus->priv; - bus->mii_bus = mii_bus; - mdio_phys = res_mem->start; - regsize = resource_size(res_mem); - - if (!devm_request_mem_region(&pdev->dev, mdio_phys, regsize, - res_mem->name)) { - dev_err(&pdev->dev, "request_mem_region failed\n"); - return -ENXIO; - } - - bus->register_base = devm_ioremap(&pdev->dev, mdio_phys, regsize); - if (!bus->register_base) { - dev_err(&pdev->dev, "dev_ioremap failed\n"); - return -ENOMEM; - } - - smi_en.u64 = 0; - smi_en.s.en = 1; - oct_mdio_writeq(smi_en.u64, bus->register_base + SMI_EN); - - bus->mii_bus->name = KBUILD_MODNAME; - snprintf(bus->mii_bus->id, MII_BUS_ID_SIZE, "%px", bus->register_base); - bus->mii_bus->parent = &pdev->dev; - - bus->mii_bus->read = cavium_mdiobus_read; - bus->mii_bus->write = cavium_mdiobus_write; - - platform_set_drvdata(pdev, bus); - - err = of_mdiobus_register(bus->mii_bus, pdev->dev.of_node); - if (err) - goto fail_register; - - dev_info(&pdev->dev, "Probed\n"); - - return 0; -fail_register: - mdiobus_free(bus->mii_bus); - smi_en.u64 = 0; - oct_mdio_writeq(smi_en.u64, bus->register_base + SMI_EN); - return err; -} - -static int octeon_mdiobus_remove(struct platform_device *pdev) -{ - struct cavium_mdiobus *bus; - union cvmx_smix_en smi_en; - - bus = platform_get_drvdata(pdev); - - mdiobus_unregister(bus->mii_bus); - mdiobus_free(bus->mii_bus); - smi_en.u64 = 0; - oct_mdio_writeq(smi_en.u64, bus->register_base + SMI_EN); - return 0; -} - -static const struct of_device_id octeon_mdiobus_match[] = { - { - .compatible = "cavium,octeon-3860-mdio", - }, - {}, -}; -MODULE_DEVICE_TABLE(of, octeon_mdiobus_match); - -static struct platform_driver octeon_mdiobus_driver = { - .driver = { - .name = KBUILD_MODNAME, - .of_match_table = octeon_mdiobus_match, - }, - .probe = octeon_mdiobus_probe, - .remove = octeon_mdiobus_remove, -}; - -module_platform_driver(octeon_mdiobus_driver); - -MODULE_DESCRIPTION("Cavium OCTEON MDIO bus driver"); -MODULE_AUTHOR("David Daney"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/phy/mdio-sun4i.c b/drivers/net/phy/mdio-sun4i.c deleted file mode 100644 index f798de3276dc..000000000000 --- a/drivers/net/phy/mdio-sun4i.c +++ /dev/null @@ -1,180 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Allwinner EMAC MDIO interface driver - * - * Copyright 2012-2013 Stefan Roese <sr@denx.de> - * Copyright 2013 Maxime Ripard <maxime.ripard@free-electrons.com> - * - * Based on the Linux driver provided by Allwinner: - * Copyright (C) 1997 Sten Wang - */ - -#include <linux/delay.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/mutex.h> -#include <linux/of_address.h> -#include <linux/of_mdio.h> -#include <linux/phy.h> -#include <linux/platform_device.h> -#include <linux/regulator/consumer.h> - -#define EMAC_MAC_MCMD_REG (0x00) -#define EMAC_MAC_MADR_REG (0x04) -#define EMAC_MAC_MWTD_REG (0x08) -#define EMAC_MAC_MRDD_REG (0x0c) -#define EMAC_MAC_MIND_REG (0x10) -#define EMAC_MAC_SSRR_REG (0x14) - -#define MDIO_TIMEOUT (msecs_to_jiffies(100)) - -struct sun4i_mdio_data { - void __iomem *membase; - struct regulator *regulator; -}; - -static int sun4i_mdio_read(struct mii_bus *bus, int mii_id, int regnum) -{ - struct sun4i_mdio_data *data = bus->priv; - unsigned long timeout_jiffies; - int value; - - /* issue the phy address and reg */ - writel((mii_id << 8) | regnum, data->membase + EMAC_MAC_MADR_REG); - /* pull up the phy io line */ - writel(0x1, data->membase + EMAC_MAC_MCMD_REG); - - /* Wait read complete */ - timeout_jiffies = jiffies + MDIO_TIMEOUT; - while (readl(data->membase + EMAC_MAC_MIND_REG) & 0x1) { - if (time_is_before_jiffies(timeout_jiffies)) - return -ETIMEDOUT; - msleep(1); - } - - /* push down the phy io line */ - writel(0x0, data->membase + EMAC_MAC_MCMD_REG); - /* and read data */ - value = readl(data->membase + EMAC_MAC_MRDD_REG); - - return value; -} - -static int sun4i_mdio_write(struct mii_bus *bus, int mii_id, int regnum, - u16 value) -{ - struct sun4i_mdio_data *data = bus->priv; - unsigned long timeout_jiffies; - - /* issue the phy address and reg */ - writel((mii_id << 8) | regnum, data->membase + EMAC_MAC_MADR_REG); - /* pull up the phy io line */ - writel(0x1, data->membase + EMAC_MAC_MCMD_REG); - - /* Wait read complete */ - timeout_jiffies = jiffies + MDIO_TIMEOUT; - while (readl(data->membase + EMAC_MAC_MIND_REG) & 0x1) { - if (time_is_before_jiffies(timeout_jiffies)) - return -ETIMEDOUT; - msleep(1); - } - - /* push down the phy io line */ - writel(0x0, data->membase + EMAC_MAC_MCMD_REG); - /* and write data */ - writel(value, data->membase + EMAC_MAC_MWTD_REG); - - return 0; -} - -static int sun4i_mdio_probe(struct platform_device *pdev) -{ - struct device_node *np = pdev->dev.of_node; - struct mii_bus *bus; - struct sun4i_mdio_data *data; - int ret; - - bus = mdiobus_alloc_size(sizeof(*data)); - if (!bus) - return -ENOMEM; - - bus->name = "sun4i_mii_bus"; - bus->read = &sun4i_mdio_read; - bus->write = &sun4i_mdio_write; - snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii", dev_name(&pdev->dev)); - bus->parent = &pdev->dev; - - data = bus->priv; - data->membase = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(data->membase)) { - ret = PTR_ERR(data->membase); - goto err_out_free_mdiobus; - } - - data->regulator = devm_regulator_get(&pdev->dev, "phy"); - if (IS_ERR(data->regulator)) { - if (PTR_ERR(data->regulator) == -EPROBE_DEFER) { - ret = -EPROBE_DEFER; - goto err_out_free_mdiobus; - } - - dev_info(&pdev->dev, "no regulator found\n"); - data->regulator = NULL; - } else { - ret = regulator_enable(data->regulator); - if (ret) - goto err_out_free_mdiobus; - } - - ret = of_mdiobus_register(bus, np); - if (ret < 0) - goto err_out_disable_regulator; - - platform_set_drvdata(pdev, bus); - - return 0; - -err_out_disable_regulator: - if (data->regulator) - regulator_disable(data->regulator); -err_out_free_mdiobus: - mdiobus_free(bus); - return ret; -} - -static int sun4i_mdio_remove(struct platform_device *pdev) -{ - struct mii_bus *bus = platform_get_drvdata(pdev); - struct sun4i_mdio_data *data = bus->priv; - - mdiobus_unregister(bus); - if (data->regulator) - regulator_disable(data->regulator); - mdiobus_free(bus); - - return 0; -} - -static const struct of_device_id sun4i_mdio_dt_ids[] = { - { .compatible = "allwinner,sun4i-a10-mdio" }, - - /* Deprecated */ - { .compatible = "allwinner,sun4i-mdio" }, - { } -}; -MODULE_DEVICE_TABLE(of, sun4i_mdio_dt_ids); - -static struct platform_driver sun4i_mdio_driver = { - .probe = sun4i_mdio_probe, - .remove = sun4i_mdio_remove, - .driver = { - .name = "sun4i-mdio", - .of_match_table = sun4i_mdio_dt_ids, - }, -}; - -module_platform_driver(sun4i_mdio_driver); - -MODULE_DESCRIPTION("Allwinner EMAC MDIO interface driver"); -MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/phy/mdio-thunder.c b/drivers/net/phy/mdio-thunder.c deleted file mode 100644 index 3d7eda99d34e..000000000000 --- a/drivers/net/phy/mdio-thunder.c +++ /dev/null @@ -1,152 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2009-2016 Cavium, Inc. - */ - -#include <linux/of_address.h> -#include <linux/of_mdio.h> -#include <linux/module.h> -#include <linux/gfp.h> -#include <linux/phy.h> -#include <linux/io.h> -#include <linux/acpi.h> -#include <linux/pci.h> - -#include "mdio-cavium.h" - -struct thunder_mdiobus_nexus { - void __iomem *bar0; - struct cavium_mdiobus *buses[4]; -}; - -static int thunder_mdiobus_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct device_node *node; - struct fwnode_handle *fwn; - struct thunder_mdiobus_nexus *nexus; - int err; - int i; - - nexus = devm_kzalloc(&pdev->dev, sizeof(*nexus), GFP_KERNEL); - if (!nexus) - return -ENOMEM; - - pci_set_drvdata(pdev, nexus); - - err = pcim_enable_device(pdev); - if (err) { - dev_err(&pdev->dev, "Failed to enable PCI device\n"); - pci_set_drvdata(pdev, NULL); - return err; - } - - err = pci_request_regions(pdev, KBUILD_MODNAME); - if (err) { - dev_err(&pdev->dev, "pci_request_regions failed\n"); - goto err_disable_device; - } - - nexus->bar0 = pcim_iomap(pdev, 0, pci_resource_len(pdev, 0)); - if (!nexus->bar0) { - err = -ENOMEM; - goto err_release_regions; - } - - i = 0; - device_for_each_child_node(&pdev->dev, fwn) { - struct resource r; - struct mii_bus *mii_bus; - struct cavium_mdiobus *bus; - union cvmx_smix_en smi_en; - - /* If it is not an OF node we cannot handle it yet, so - * exit the loop. - */ - node = to_of_node(fwn); - if (!node) - break; - - err = of_address_to_resource(node, 0, &r); - if (err) { - dev_err(&pdev->dev, - "Couldn't translate address for \"%pOFn\"\n", - node); - break; - } - - mii_bus = devm_mdiobus_alloc_size(&pdev->dev, sizeof(*bus)); - if (!mii_bus) - break; - bus = mii_bus->priv; - bus->mii_bus = mii_bus; - - nexus->buses[i] = bus; - i++; - - bus->register_base = nexus->bar0 + - r.start - pci_resource_start(pdev, 0); - - smi_en.u64 = 0; - smi_en.s.en = 1; - oct_mdio_writeq(smi_en.u64, bus->register_base + SMI_EN); - bus->mii_bus->name = KBUILD_MODNAME; - snprintf(bus->mii_bus->id, MII_BUS_ID_SIZE, "%llx", r.start); - bus->mii_bus->parent = &pdev->dev; - bus->mii_bus->read = cavium_mdiobus_read; - bus->mii_bus->write = cavium_mdiobus_write; - - err = of_mdiobus_register(bus->mii_bus, node); - if (err) - dev_err(&pdev->dev, "of_mdiobus_register failed\n"); - - dev_info(&pdev->dev, "Added bus at %llx\n", r.start); - if (i >= ARRAY_SIZE(nexus->buses)) - break; - } - return 0; - -err_release_regions: - pci_release_regions(pdev); - -err_disable_device: - pci_set_drvdata(pdev, NULL); - return err; -} - -static void thunder_mdiobus_pci_remove(struct pci_dev *pdev) -{ - int i; - struct thunder_mdiobus_nexus *nexus = pci_get_drvdata(pdev); - - for (i = 0; i < ARRAY_SIZE(nexus->buses); i++) { - struct cavium_mdiobus *bus = nexus->buses[i]; - - if (!bus) - continue; - - mdiobus_unregister(bus->mii_bus); - mdiobus_free(bus->mii_bus); - oct_mdio_writeq(0, bus->register_base + SMI_EN); - } - pci_release_regions(pdev); - pci_set_drvdata(pdev, NULL); -} - -static const struct pci_device_id thunder_mdiobus_id_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, 0xa02b) }, - { 0, } /* End of table. */ -}; -MODULE_DEVICE_TABLE(pci, thunder_mdiobus_id_table); - -static struct pci_driver thunder_mdiobus_driver = { - .name = KBUILD_MODNAME, - .id_table = thunder_mdiobus_id_table, - .probe = thunder_mdiobus_pci_probe, - .remove = thunder_mdiobus_pci_remove, -}; - -module_pci_driver(thunder_mdiobus_driver); - -MODULE_DESCRIPTION("Cavium ThunderX MDIO bus driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/phy/mdio-xgene.c b/drivers/net/phy/mdio-xgene.c deleted file mode 100644 index 461207cdf5d6..000000000000 --- a/drivers/net/phy/mdio-xgene.c +++ /dev/null @@ -1,466 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* Applied Micro X-Gene SoC MDIO Driver - * - * Copyright (c) 2016, Applied Micro Circuits Corporation - * Author: Iyappan Subramanian <isubramanian@apm.com> - */ - -#include <linux/acpi.h> -#include <linux/clk.h> -#include <linux/device.h> -#include <linux/efi.h> -#include <linux/if_vlan.h> -#include <linux/io.h> -#include <linux/mdio/mdio-xgene.h> -#include <linux/module.h> -#include <linux/of_platform.h> -#include <linux/of_net.h> -#include <linux/of_mdio.h> -#include <linux/prefetch.h> -#include <linux/phy.h> -#include <net/ip.h> - -static bool xgene_mdio_status; - -u32 xgene_mdio_rd_mac(struct xgene_mdio_pdata *pdata, u32 rd_addr) -{ - void __iomem *addr, *rd, *cmd, *cmd_done; - u32 done, rd_data = BUSY_MASK; - u8 wait = 10; - - addr = pdata->mac_csr_addr + MAC_ADDR_REG_OFFSET; - rd = pdata->mac_csr_addr + MAC_READ_REG_OFFSET; - cmd = pdata->mac_csr_addr + MAC_COMMAND_REG_OFFSET; - cmd_done = pdata->mac_csr_addr + MAC_COMMAND_DONE_REG_OFFSET; - - spin_lock(&pdata->mac_lock); - iowrite32(rd_addr, addr); - iowrite32(XGENE_ENET_RD_CMD, cmd); - - while (!(done = ioread32(cmd_done)) && wait--) - udelay(1); - - if (done) - rd_data = ioread32(rd); - - iowrite32(0, cmd); - spin_unlock(&pdata->mac_lock); - - return rd_data; -} -EXPORT_SYMBOL(xgene_mdio_rd_mac); - -void xgene_mdio_wr_mac(struct xgene_mdio_pdata *pdata, u32 wr_addr, u32 data) -{ - void __iomem *addr, *wr, *cmd, *cmd_done; - u8 wait = 10; - u32 done; - - addr = pdata->mac_csr_addr + MAC_ADDR_REG_OFFSET; - wr = pdata->mac_csr_addr + MAC_WRITE_REG_OFFSET; - cmd = pdata->mac_csr_addr + MAC_COMMAND_REG_OFFSET; - cmd_done = pdata->mac_csr_addr + MAC_COMMAND_DONE_REG_OFFSET; - - spin_lock(&pdata->mac_lock); - iowrite32(wr_addr, addr); - iowrite32(data, wr); - iowrite32(XGENE_ENET_WR_CMD, cmd); - - while (!(done = ioread32(cmd_done)) && wait--) - udelay(1); - - if (!done) - pr_err("MCX mac write failed, addr: 0x%04x\n", wr_addr); - - iowrite32(0, cmd); - spin_unlock(&pdata->mac_lock); -} -EXPORT_SYMBOL(xgene_mdio_wr_mac); - -int xgene_mdio_rgmii_read(struct mii_bus *bus, int phy_id, int reg) -{ - struct xgene_mdio_pdata *pdata = (struct xgene_mdio_pdata *)bus->priv; - u32 data, done; - u8 wait = 10; - - data = SET_VAL(PHY_ADDR, phy_id) | SET_VAL(REG_ADDR, reg); - xgene_mdio_wr_mac(pdata, MII_MGMT_ADDRESS_ADDR, data); - xgene_mdio_wr_mac(pdata, MII_MGMT_COMMAND_ADDR, READ_CYCLE_MASK); - do { - usleep_range(5, 10); - done = xgene_mdio_rd_mac(pdata, MII_MGMT_INDICATORS_ADDR); - } while ((done & BUSY_MASK) && wait--); - - if (done & BUSY_MASK) { - dev_err(&bus->dev, "MII_MGMT read failed\n"); - return -EBUSY; - } - - data = xgene_mdio_rd_mac(pdata, MII_MGMT_STATUS_ADDR); - xgene_mdio_wr_mac(pdata, MII_MGMT_COMMAND_ADDR, 0); - - return data; -} -EXPORT_SYMBOL(xgene_mdio_rgmii_read); - -int xgene_mdio_rgmii_write(struct mii_bus *bus, int phy_id, int reg, u16 data) -{ - struct xgene_mdio_pdata *pdata = (struct xgene_mdio_pdata *)bus->priv; - u32 val, done; - u8 wait = 10; - - val = SET_VAL(PHY_ADDR, phy_id) | SET_VAL(REG_ADDR, reg); - xgene_mdio_wr_mac(pdata, MII_MGMT_ADDRESS_ADDR, val); - - xgene_mdio_wr_mac(pdata, MII_MGMT_CONTROL_ADDR, data); - do { - usleep_range(5, 10); - done = xgene_mdio_rd_mac(pdata, MII_MGMT_INDICATORS_ADDR); - } while ((done & BUSY_MASK) && wait--); - - if (done & BUSY_MASK) { - dev_err(&bus->dev, "MII_MGMT write failed\n"); - return -EBUSY; - } - - return 0; -} -EXPORT_SYMBOL(xgene_mdio_rgmii_write); - -static u32 xgene_menet_rd_diag_csr(struct xgene_mdio_pdata *pdata, u32 offset) -{ - return ioread32(pdata->diag_csr_addr + offset); -} - -static void xgene_menet_wr_diag_csr(struct xgene_mdio_pdata *pdata, - u32 offset, u32 val) -{ - iowrite32(val, pdata->diag_csr_addr + offset); -} - -static int xgene_enet_ecc_init(struct xgene_mdio_pdata *pdata) -{ - u32 data; - u8 wait = 10; - - xgene_menet_wr_diag_csr(pdata, MENET_CFG_MEM_RAM_SHUTDOWN_ADDR, 0x0); - do { - usleep_range(100, 110); - data = xgene_menet_rd_diag_csr(pdata, MENET_BLOCK_MEM_RDY_ADDR); - } while ((data != 0xffffffff) && wait--); - - if (data != 0xffffffff) { - dev_err(pdata->dev, "Failed to release memory from shutdown\n"); - return -ENODEV; - } - - return 0; -} - -static void xgene_gmac_reset(struct xgene_mdio_pdata *pdata) -{ - xgene_mdio_wr_mac(pdata, MAC_CONFIG_1_ADDR, SOFT_RESET); - xgene_mdio_wr_mac(pdata, MAC_CONFIG_1_ADDR, 0); -} - -static int xgene_mdio_reset(struct xgene_mdio_pdata *pdata) -{ - int ret; - - if (pdata->dev->of_node) { - clk_prepare_enable(pdata->clk); - udelay(5); - clk_disable_unprepare(pdata->clk); - udelay(5); - clk_prepare_enable(pdata->clk); - udelay(5); - } else { -#ifdef CONFIG_ACPI - acpi_evaluate_object(ACPI_HANDLE(pdata->dev), - "_RST", NULL, NULL); -#endif - } - - ret = xgene_enet_ecc_init(pdata); - if (ret) { - if (pdata->dev->of_node) - clk_disable_unprepare(pdata->clk); - return ret; - } - xgene_gmac_reset(pdata); - - return 0; -} - -static void xgene_enet_rd_mdio_csr(void __iomem *base_addr, - u32 offset, u32 *val) -{ - void __iomem *addr = base_addr + offset; - - *val = ioread32(addr); -} - -static void xgene_enet_wr_mdio_csr(void __iomem *base_addr, - u32 offset, u32 val) -{ - void __iomem *addr = base_addr + offset; - - iowrite32(val, addr); -} - -static int xgene_xfi_mdio_write(struct mii_bus *bus, int phy_id, - int reg, u16 data) -{ - void __iomem *addr = (void __iomem *)bus->priv; - int timeout = 100; - u32 status, val; - - val = SET_VAL(HSTPHYADX, phy_id) | SET_VAL(HSTREGADX, reg) | - SET_VAL(HSTMIIMWRDAT, data); - xgene_enet_wr_mdio_csr(addr, MIIM_FIELD_ADDR, val); - - val = HSTLDCMD | SET_VAL(HSTMIIMCMD, MIIM_CMD_LEGACY_WRITE); - xgene_enet_wr_mdio_csr(addr, MIIM_COMMAND_ADDR, val); - - do { - usleep_range(5, 10); - xgene_enet_rd_mdio_csr(addr, MIIM_INDICATOR_ADDR, &status); - } while ((status & BUSY_MASK) && timeout--); - - xgene_enet_wr_mdio_csr(addr, MIIM_COMMAND_ADDR, 0); - - return 0; -} - -static int xgene_xfi_mdio_read(struct mii_bus *bus, int phy_id, int reg) -{ - void __iomem *addr = (void __iomem *)bus->priv; - u32 data, status, val; - int timeout = 100; - - val = SET_VAL(HSTPHYADX, phy_id) | SET_VAL(HSTREGADX, reg); - xgene_enet_wr_mdio_csr(addr, MIIM_FIELD_ADDR, val); - - val = HSTLDCMD | SET_VAL(HSTMIIMCMD, MIIM_CMD_LEGACY_READ); - xgene_enet_wr_mdio_csr(addr, MIIM_COMMAND_ADDR, val); - - do { - usleep_range(5, 10); - xgene_enet_rd_mdio_csr(addr, MIIM_INDICATOR_ADDR, &status); - } while ((status & BUSY_MASK) && timeout--); - - if (status & BUSY_MASK) { - pr_err("XGENET_MII_MGMT write failed\n"); - return -EBUSY; - } - - xgene_enet_rd_mdio_csr(addr, MIIMRD_FIELD_ADDR, &data); - xgene_enet_wr_mdio_csr(addr, MIIM_COMMAND_ADDR, 0); - - return data; -} - -struct phy_device *xgene_enet_phy_register(struct mii_bus *bus, int phy_addr) -{ - struct phy_device *phy_dev; - - phy_dev = get_phy_device(bus, phy_addr, false); - if (!phy_dev || IS_ERR(phy_dev)) - return NULL; - - if (phy_device_register(phy_dev)) - phy_device_free(phy_dev); - - return phy_dev; -} -EXPORT_SYMBOL(xgene_enet_phy_register); - -#ifdef CONFIG_ACPI -static acpi_status acpi_register_phy(acpi_handle handle, u32 lvl, - void *context, void **ret) -{ - struct mii_bus *mdio = context; - struct acpi_device *adev; - struct phy_device *phy_dev; - const union acpi_object *obj; - u32 phy_addr; - - if (acpi_bus_get_device(handle, &adev)) - return AE_OK; - - if (acpi_dev_get_property(adev, "phy-channel", ACPI_TYPE_INTEGER, &obj)) - return AE_OK; - phy_addr = obj->integer.value; - - phy_dev = xgene_enet_phy_register(mdio, phy_addr); - adev->driver_data = phy_dev; - - return AE_OK; -} -#endif - -static const struct of_device_id xgene_mdio_of_match[] = { - { - .compatible = "apm,xgene-mdio-rgmii", - .data = (void *)XGENE_MDIO_RGMII - }, - { - .compatible = "apm,xgene-mdio-xfi", - .data = (void *)XGENE_MDIO_XFI - }, - {}, -}; -MODULE_DEVICE_TABLE(of, xgene_mdio_of_match); - -#ifdef CONFIG_ACPI -static const struct acpi_device_id xgene_mdio_acpi_match[] = { - { "APMC0D65", XGENE_MDIO_RGMII }, - { "APMC0D66", XGENE_MDIO_XFI }, - { } -}; - -MODULE_DEVICE_TABLE(acpi, xgene_mdio_acpi_match); -#endif - - -static int xgene_mdio_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct mii_bus *mdio_bus; - const struct of_device_id *of_id; - struct xgene_mdio_pdata *pdata; - void __iomem *csr_base; - int mdio_id = 0, ret = 0; - - of_id = of_match_device(xgene_mdio_of_match, &pdev->dev); - if (of_id) { - mdio_id = (enum xgene_mdio_id)of_id->data; - } else { -#ifdef CONFIG_ACPI - const struct acpi_device_id *acpi_id; - - acpi_id = acpi_match_device(xgene_mdio_acpi_match, &pdev->dev); - if (acpi_id) - mdio_id = (enum xgene_mdio_id)acpi_id->driver_data; -#endif - } - - if (!mdio_id) - return -ENODEV; - - pdata = devm_kzalloc(dev, sizeof(struct xgene_mdio_pdata), GFP_KERNEL); - if (!pdata) - return -ENOMEM; - pdata->mdio_id = mdio_id; - pdata->dev = dev; - - csr_base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(csr_base)) - return PTR_ERR(csr_base); - pdata->mac_csr_addr = csr_base; - pdata->mdio_csr_addr = csr_base + BLOCK_XG_MDIO_CSR_OFFSET; - pdata->diag_csr_addr = csr_base + BLOCK_DIAG_CSR_OFFSET; - - if (mdio_id == XGENE_MDIO_RGMII) - spin_lock_init(&pdata->mac_lock); - - if (dev->of_node) { - pdata->clk = devm_clk_get(dev, NULL); - if (IS_ERR(pdata->clk)) { - dev_err(dev, "Unable to retrieve clk\n"); - return PTR_ERR(pdata->clk); - } - } - - ret = xgene_mdio_reset(pdata); - if (ret) - return ret; - - mdio_bus = mdiobus_alloc(); - if (!mdio_bus) { - ret = -ENOMEM; - goto out_clk; - } - - mdio_bus->name = "APM X-Gene MDIO bus"; - - if (mdio_id == XGENE_MDIO_RGMII) { - mdio_bus->read = xgene_mdio_rgmii_read; - mdio_bus->write = xgene_mdio_rgmii_write; - mdio_bus->priv = (void __force *)pdata; - snprintf(mdio_bus->id, MII_BUS_ID_SIZE, "%s", - "xgene-mii-rgmii"); - } else { - mdio_bus->read = xgene_xfi_mdio_read; - mdio_bus->write = xgene_xfi_mdio_write; - mdio_bus->priv = (void __force *)pdata->mdio_csr_addr; - snprintf(mdio_bus->id, MII_BUS_ID_SIZE, "%s", - "xgene-mii-xfi"); - } - - mdio_bus->parent = dev; - platform_set_drvdata(pdev, pdata); - - if (dev->of_node) { - ret = of_mdiobus_register(mdio_bus, dev->of_node); - } else { -#ifdef CONFIG_ACPI - /* Mask out all PHYs from auto probing. */ - mdio_bus->phy_mask = ~0; - ret = mdiobus_register(mdio_bus); - if (ret) - goto out_mdiobus; - - acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_HANDLE(dev), 1, - acpi_register_phy, NULL, mdio_bus, NULL); -#endif - } - - if (ret) - goto out_mdiobus; - - pdata->mdio_bus = mdio_bus; - xgene_mdio_status = true; - - return 0; - -out_mdiobus: - mdiobus_free(mdio_bus); - -out_clk: - if (dev->of_node) - clk_disable_unprepare(pdata->clk); - - return ret; -} - -static int xgene_mdio_remove(struct platform_device *pdev) -{ - struct xgene_mdio_pdata *pdata = platform_get_drvdata(pdev); - struct mii_bus *mdio_bus = pdata->mdio_bus; - struct device *dev = &pdev->dev; - - mdiobus_unregister(mdio_bus); - mdiobus_free(mdio_bus); - - if (dev->of_node) - clk_disable_unprepare(pdata->clk); - - return 0; -} - -static struct platform_driver xgene_mdio_driver = { - .driver = { - .name = "xgene-mdio", - .of_match_table = of_match_ptr(xgene_mdio_of_match), - .acpi_match_table = ACPI_PTR(xgene_mdio_acpi_match), - }, - .probe = xgene_mdio_probe, - .remove = xgene_mdio_remove, -}; - -module_platform_driver(xgene_mdio_driver); - -MODULE_DESCRIPTION("APM X-Gene SoC MDIO driver"); -MODULE_AUTHOR("Iyappan Subramanian <isubramanian@apm.com>"); -MODULE_LICENSE("GPL"); |