diff options
Diffstat (limited to 'target/linux/ipq40xx/patches-5.4')
-rw-r--r-- | target/linux/ipq40xx/patches-5.4/0005-01-v5.8-net-phy-mdio-add-IPQ4019-MDIO-driver.patch | 210 | ||||
-rw-r--r-- | target/linux/ipq40xx/patches-5.4/0005-02-v5.8-02-ARM-dts-qcom-ipq4019-add-MDIO-node.patch (renamed from target/linux/ipq40xx/patches-5.4/0005-v5.8-02-ARM-dts-qcom-ipq4019-add-MDIO-node.patch) | 0 | ||||
-rw-r--r-- | target/linux/ipq40xx/patches-5.4/700-net-add-qualcomm-mdio.patch | 225 |
3 files changed, 210 insertions, 225 deletions
diff --git a/target/linux/ipq40xx/patches-5.4/0005-01-v5.8-net-phy-mdio-add-IPQ4019-MDIO-driver.patch b/target/linux/ipq40xx/patches-5.4/0005-01-v5.8-net-phy-mdio-add-IPQ4019-MDIO-driver.patch new file mode 100644 index 0000000000..d678f761f5 --- /dev/null +++ b/target/linux/ipq40xx/patches-5.4/0005-01-v5.8-net-phy-mdio-add-IPQ4019-MDIO-driver.patch @@ -0,0 +1,210 @@ +From 466ed24fb22342f3ae1c10758a6a0c6a8c081b2d Mon Sep 17 00:00:00 2001 +From: Robert Marko <robert.marko@sartura.hr> +Date: Thu, 30 Apr 2020 11:07:05 +0200 +Subject: [PATCH] net: phy: mdio: add IPQ4019 MDIO driver + +This patch adds the driver for the MDIO interface +inside of Qualcomm IPQ40xx series SoC-s. + +Signed-off-by: Christian Lamparter <chunkeey@gmail.com> +Signed-off-by: Robert Marko <robert.marko@sartura.hr> +Reviewed-by: Andrew Lunn <andrew@lunn.ch> +Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> +Cc: Luka Perkov <luka.perkov@sartura.hr> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + drivers/net/phy/Kconfig | 7 ++ + drivers/net/phy/Makefile | 1 + + drivers/net/phy/mdio-ipq4019.c | 160 +++++++++++++++++++++++++++++++++ + 3 files changed, 168 insertions(+) + create mode 100644 drivers/net/phy/mdio-ipq4019.c + +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -156,6 +156,13 @@ config MDIO_I2C + + 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_MOXART + tristate "MOXA ART MDIO interface support" + depends on ARCH_MOXART || COMPILE_TEST +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -50,6 +50,7 @@ obj-$(CONFIG_MDIO_CAVIUM) += mdio-cavium + 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_MOXART) += mdio-moxart.o + obj-$(CONFIG_MDIO_MSCC_MIIM) += mdio-mscc-miim.o + obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o +--- /dev/null ++++ b/drivers/net/phy/mdio-ipq4019.c +@@ -0,0 +1,160 @@ ++// 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/target/linux/ipq40xx/patches-5.4/0005-v5.8-02-ARM-dts-qcom-ipq4019-add-MDIO-node.patch b/target/linux/ipq40xx/patches-5.4/0005-02-v5.8-02-ARM-dts-qcom-ipq4019-add-MDIO-node.patch index 1976686e8f..1976686e8f 100644 --- a/target/linux/ipq40xx/patches-5.4/0005-v5.8-02-ARM-dts-qcom-ipq4019-add-MDIO-node.patch +++ b/target/linux/ipq40xx/patches-5.4/0005-02-v5.8-02-ARM-dts-qcom-ipq4019-add-MDIO-node.patch diff --git a/target/linux/ipq40xx/patches-5.4/700-net-add-qualcomm-mdio.patch b/target/linux/ipq40xx/patches-5.4/700-net-add-qualcomm-mdio.patch deleted file mode 100644 index 3345d84fb8..0000000000 --- a/target/linux/ipq40xx/patches-5.4/700-net-add-qualcomm-mdio.patch +++ /dev/null @@ -1,225 +0,0 @@ ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -577,6 +577,13 @@ config XILINX_GMII2RGMII - the Reduced Gigabit Media Independent Interface(RGMII) between - Ethernet physical media devices and the Gigabit Ethernet controller. - -+config MDIO_IPQ40XX -+ tristate "Qualcomm Atheros ipq40xx MDIO interface" -+ depends on HAS_IOMEM && OF -+ ---help--- -+ This driver supports the MDIO interface found in Qualcomm -+ Atheros ipq40xx Soc chip. -+ - endif # PHYLIB - - config MICREL_KS8995MA ---- a/drivers/net/phy/Makefile -+++ b/drivers/net/phy/Makefile -@@ -50,6 +50,7 @@ obj-$(CONFIG_MDIO_CAVIUM) += mdio-cavium - 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_IPQ40XX) += mdio-ipq40xx.o - obj-$(CONFIG_MDIO_MOXART) += mdio-moxart.o - obj-$(CONFIG_MDIO_MSCC_MIIM) += mdio-mscc-miim.o - obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o ---- /dev/null -+++ b/drivers/net/phy/mdio-ipq40xx.c -@@ -0,0 +1,196 @@ -+/* -+ * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for -+ * any purpose with or without fee is hereby granted, provided that the -+ * above copyright notice and this permission notice appear in all copies. -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#include <linux/delay.h> -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/mutex.h> -+#include <linux/io.h> -+#include <linux/of_address.h> -+#include <linux/of_mdio.h> -+#include <linux/phy.h> -+#include <linux/platform_device.h> -+ -+#define MDIO_CTRL_0_REG 0x40 -+#define MDIO_CTRL_1_REG 0x44 -+#define MDIO_CTRL_2_REG 0x48 -+#define MDIO_CTRL_3_REG 0x4c -+#define MDIO_CTRL_4_REG 0x50 -+#define MDIO_CTRL_4_ACCESS_BUSY BIT(16) -+#define MDIO_CTRL_4_ACCESS_START BIT(8) -+#define MDIO_CTRL_4_ACCESS_CODE_READ 0 -+#define MDIO_CTRL_4_ACCESS_CODE_WRITE 1 -+#define CTRL_0_REG_DEFAULT_VALUE 0x150FF -+ -+#define IPQ40XX_MDIO_RETRY 1000 -+#define IPQ40XX_MDIO_DELAY 10 -+ -+struct ipq40xx_mdio_data { -+ struct mii_bus *mii_bus; -+ void __iomem *membase; -+ struct device *dev; -+}; -+ -+static int ipq40xx_mdio_wait_busy(struct ipq40xx_mdio_data *am) -+{ -+ int i; -+ -+ for (i = 0; i < IPQ40XX_MDIO_RETRY; i++) { -+ unsigned int busy; -+ -+ busy = readl(am->membase + MDIO_CTRL_4_REG) & -+ MDIO_CTRL_4_ACCESS_BUSY; -+ if (!busy) -+ return 0; -+ -+ /* BUSY might take to be cleard by 15~20 times of loop */ -+ udelay(IPQ40XX_MDIO_DELAY); -+ } -+ -+ dev_err(am->dev, "%s: MDIO operation timed out\n", am->mii_bus->name); -+ -+ return -ETIMEDOUT; -+} -+ -+static int ipq40xx_mdio_read(struct mii_bus *bus, int mii_id, int regnum) -+{ -+ struct ipq40xx_mdio_data *am = bus->priv; -+ int value = 0; -+ unsigned int cmd = 0; -+ -+ lockdep_assert_held(&bus->mdio_lock); -+ -+ if (ipq40xx_mdio_wait_busy(am)) -+ return -ETIMEDOUT; -+ -+ /* issue the phy address and reg */ -+ writel((mii_id << 8) | regnum, am->membase + MDIO_CTRL_1_REG); -+ -+ cmd = MDIO_CTRL_4_ACCESS_START|MDIO_CTRL_4_ACCESS_CODE_READ; -+ -+ /* issue read command */ -+ writel(cmd, am->membase + MDIO_CTRL_4_REG); -+ -+ /* Wait read complete */ -+ if (ipq40xx_mdio_wait_busy(am)) -+ return -ETIMEDOUT; -+ -+ /* Read data */ -+ value = readl(am->membase + MDIO_CTRL_3_REG); -+ -+ return value; -+} -+ -+static int ipq40xx_mdio_write(struct mii_bus *bus, int mii_id, int regnum, -+ u16 value) -+{ -+ struct ipq40xx_mdio_data *am = bus->priv; -+ unsigned int cmd = 0; -+ -+ lockdep_assert_held(&bus->mdio_lock); -+ -+ if (ipq40xx_mdio_wait_busy(am)) -+ return -ETIMEDOUT; -+ -+ /* issue the phy address and reg */ -+ writel((mii_id << 8) | regnum, am->membase + MDIO_CTRL_1_REG); -+ -+ /* issue write data */ -+ writel(value, am->membase + MDIO_CTRL_2_REG); -+ -+ cmd = MDIO_CTRL_4_ACCESS_START|MDIO_CTRL_4_ACCESS_CODE_WRITE; -+ /* issue write command */ -+ writel(cmd, am->membase + MDIO_CTRL_4_REG); -+ -+ /* Wait write complete */ -+ if (ipq40xx_mdio_wait_busy(am)) -+ return -ETIMEDOUT; -+ -+ return 0; -+} -+ -+static int ipq40xx_mdio_probe(struct platform_device *pdev) -+{ -+ struct ipq40xx_mdio_data *am; -+ struct resource *res; -+ int i; -+ -+ am = devm_kzalloc(&pdev->dev, sizeof(*am), GFP_KERNEL); -+ if (!am) -+ return -ENOMEM; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!res) { -+ dev_err(&pdev->dev, "no iomem resource found\n"); -+ return -ENXIO; -+ } -+ -+ am->membase = devm_ioremap_resource(&pdev->dev, res); -+ if (IS_ERR(am->membase)) { -+ dev_err(&pdev->dev, "unable to ioremap registers\n"); -+ return PTR_ERR(am->membase); -+ } -+ -+ am->mii_bus = devm_mdiobus_alloc(&pdev->dev); -+ if (!am->mii_bus) -+ return -ENOMEM; -+ -+ writel(CTRL_0_REG_DEFAULT_VALUE, am->membase + MDIO_CTRL_0_REG); -+ -+ am->mii_bus->name = "ipq40xx_mdio"; -+ am->mii_bus->read = ipq40xx_mdio_read; -+ am->mii_bus->write = ipq40xx_mdio_write; -+ am->mii_bus->priv = am; -+ am->mii_bus->parent = &pdev->dev; -+ snprintf(am->mii_bus->id, MII_BUS_ID_SIZE, "%s", dev_name(&pdev->dev)); -+ -+ am->dev = &pdev->dev; -+ platform_set_drvdata(pdev, am); -+ -+ return of_mdiobus_register(am->mii_bus, pdev->dev.of_node); -+} -+ -+static int ipq40xx_mdio_remove(struct platform_device *pdev) -+{ -+ struct ipq40xx_mdio_data *am = platform_get_drvdata(pdev); -+ -+ mdiobus_unregister(am->mii_bus); -+ -+ return 0; -+} -+ -+static const struct of_device_id ipq40xx_mdio_dt_ids[] = { -+ { .compatible = "qcom,ipq4019-mdio" }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, ipq40xx_mdio_dt_ids); -+ -+static struct platform_driver ipq40xx_mdio_driver = { -+ .probe = ipq40xx_mdio_probe, -+ .remove = ipq40xx_mdio_remove, -+ .driver = { -+ .name = "ipq40xx-mdio", -+ .of_match_table = ipq40xx_mdio_dt_ids, -+ }, -+}; -+ -+module_platform_driver(ipq40xx_mdio_driver); -+ -+#define DRV_VERSION "1.0" -+ -+MODULE_DESCRIPTION("IPQ40XX MDIO interface driver"); -+MODULE_AUTHOR("Qualcomm Atheros"); -+MODULE_VERSION(DRV_VERSION); -+MODULE_LICENSE("Dual BSD/GPL"); |