From 34f898ec29fa1e5254347b8a3dc41c9fecd87fd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Tue, 16 Mar 2021 20:06:00 +0100 Subject: bmips: backport bcm6368-mdio-mux support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch has been accepted for linux v5.13. Signed-off-by: Álvaro Fernández Rojas --- ...-mdio-Add-BCM6368-MDIO-mux-bus-controller.patch | 237 +++++++++++++++++++++ 1 file changed, 237 insertions(+) create mode 100644 target/linux/bmips/patches-5.10/047-v5.13-net-mdio-Add-BCM6368-MDIO-mux-bus-controller.patch (limited to 'target/linux/bmips/patches-5.10/047-v5.13-net-mdio-Add-BCM6368-MDIO-mux-bus-controller.patch') diff --git a/target/linux/bmips/patches-5.10/047-v5.13-net-mdio-Add-BCM6368-MDIO-mux-bus-controller.patch b/target/linux/bmips/patches-5.10/047-v5.13-net-mdio-Add-BCM6368-MDIO-mux-bus-controller.patch new file mode 100644 index 0000000000..0f1a2cd9ca --- /dev/null +++ b/target/linux/bmips/patches-5.10/047-v5.13-net-mdio-Add-BCM6368-MDIO-mux-bus-controller.patch @@ -0,0 +1,237 @@ +From e239756717b5c866958823a1609e2ccf268435be Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= +Date: Mon, 15 Mar 2021 16:45:28 +0100 +Subject: [PATCH 2/2] net: mdio: Add BCM6368 MDIO mux bus controller +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This controller is present on BCM6318, BCM6328, BCM6362, BCM6368 and BCM63268 +SoCs. + +Signed-off-by: Álvaro Fernández Rojas +Signed-off-by: David S. Miller +--- + drivers/net/mdio/Kconfig | 11 ++ + drivers/net/mdio/Makefile | 1 + + drivers/net/mdio/mdio-mux-bcm6368.c | 184 ++++++++++++++++++++++++++++ + 3 files changed, 196 insertions(+) + create mode 100644 drivers/net/mdio/mdio-mux-bcm6368.c + +--- a/drivers/net/mdio/Kconfig ++++ b/drivers/net/mdio/Kconfig +@@ -200,6 +200,17 @@ config MDIO_BUS_MUX_MESON_G12A + the amlogic g12a SoC. The multiplexers connects either the external + or the internal MDIO bus to the parent bus. + ++config MDIO_BUS_MUX_BCM6368 ++ tristate "Broadcom BCM6368 MDIO bus multiplexers" ++ depends on OF && OF_MDIO && (BMIPS_GENERIC || COMPILE_TEST) ++ select MDIO_BUS_MUX ++ default BMIPS_GENERIC ++ help ++ This module provides a driver for MDIO bus multiplexers found in ++ BCM6368 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_BCM_IPROC + tristate "Broadcom iProc based MDIO bus multiplexers" + depends on OF && OF_MDIO && (ARCH_BCM_IPROC || COMPILE_TEST) +--- a/drivers/net/mdio/Makefile ++++ b/drivers/net/mdio/Makefile +@@ -22,6 +22,7 @@ obj-$(CONFIG_MDIO_THUNDER) += mdio-thun + obj-$(CONFIG_MDIO_XGENE) += mdio-xgene.o + + obj-$(CONFIG_MDIO_BUS_MUX) += mdio-mux.o ++obj-$(CONFIG_MDIO_BUS_MUX_BCM6368) += mdio-mux-bcm6368.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 +--- /dev/null ++++ b/drivers/net/mdio/mdio-mux-bcm6368.c +@@ -0,0 +1,184 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Broadcom BCM6368 mdiomux bus controller driver ++ * ++ * Copyright (C) 2021 Álvaro Fernández Rojas ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MDIOC_REG 0x0 ++#define MDIOC_EXT_MASK BIT(16) ++#define MDIOC_REG_SHIFT 20 ++#define MDIOC_PHYID_SHIFT 25 ++#define MDIOC_RD_MASK BIT(30) ++#define MDIOC_WR_MASK BIT(31) ++ ++#define MDIOD_REG 0x4 ++ ++struct bcm6368_mdiomux_desc { ++ void *mux_handle; ++ void __iomem *base; ++ struct device *dev; ++ struct mii_bus *mii_bus; ++ int ext_phy; ++}; ++ ++static int bcm6368_mdiomux_read(struct mii_bus *bus, int phy_id, int loc) ++{ ++ struct bcm6368_mdiomux_desc *md = bus->priv; ++ uint32_t reg; ++ int ret; ++ ++ __raw_writel(0, md->base + MDIOC_REG); ++ ++ reg = MDIOC_RD_MASK | ++ (phy_id << MDIOC_PHYID_SHIFT) | ++ (loc << MDIOC_REG_SHIFT); ++ if (md->ext_phy) ++ reg |= MDIOC_EXT_MASK; ++ ++ __raw_writel(reg, md->base + MDIOC_REG); ++ udelay(50); ++ ret = __raw_readw(md->base + MDIOD_REG); ++ ++ return ret; ++} ++ ++static int bcm6368_mdiomux_write(struct mii_bus *bus, int phy_id, int loc, ++ uint16_t val) ++{ ++ struct bcm6368_mdiomux_desc *md = bus->priv; ++ uint32_t reg; ++ ++ __raw_writel(0, md->base + MDIOC_REG); ++ ++ reg = MDIOC_WR_MASK | ++ (phy_id << MDIOC_PHYID_SHIFT) | ++ (loc << MDIOC_REG_SHIFT); ++ if (md->ext_phy) ++ reg |= MDIOC_EXT_MASK; ++ reg |= val; ++ ++ __raw_writel(reg, md->base + MDIOC_REG); ++ udelay(50); ++ ++ return 0; ++} ++ ++static int bcm6368_mdiomux_switch_fn(int current_child, int desired_child, ++ void *data) ++{ ++ struct bcm6368_mdiomux_desc *md = data; ++ ++ md->ext_phy = desired_child; ++ ++ return 0; ++} ++ ++static int bcm6368_mdiomux_probe(struct platform_device *pdev) ++{ ++ struct bcm6368_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) ++ return -EINVAL; ++ ++ /* ++ * Just ioremap, as this MDIO block is usually integrated into an ++ * Ethernet MAC controller register range ++ */ ++ md->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); ++ if (!md->base) { ++ dev_err(&pdev->dev, "failed to ioremap register\n"); ++ return -ENOMEM; ++ } ++ ++ md->mii_bus = devm_mdiobus_alloc(&pdev->dev); ++ if (!md->mii_bus) { ++ dev_err(&pdev->dev, "mdiomux bus alloc failed\n"); ++ return ENOMEM; ++ } ++ ++ bus = md->mii_bus; ++ bus->priv = md; ++ bus->name = "BCM6368 MDIO mux bus"; ++ snprintf(bus->id, MII_BUS_ID_SIZE, "%s-%d", pdev->name, pdev->id); ++ bus->parent = &pdev->dev; ++ bus->read = bcm6368_mdiomux_read; ++ bus->write = bcm6368_mdiomux_write; ++ bus->phy_mask = 0x3f; ++ bus->dev.of_node = pdev->dev.of_node; ++ ++ rc = mdiobus_register(bus); ++ if (rc) { ++ dev_err(&pdev->dev, "mdiomux registration failed\n"); ++ return rc; ++ } ++ ++ platform_set_drvdata(pdev, md); ++ ++ rc = mdio_mux_init(md->dev, md->dev->of_node, ++ bcm6368_mdiomux_switch_fn, &md->mux_handle, md, ++ md->mii_bus); ++ if (rc) { ++ dev_info(md->dev, "mdiomux initialization failed\n"); ++ goto out_register; ++ } ++ ++ dev_info(&pdev->dev, "Broadcom BCM6368 MDIO mux bus\n"); ++ ++ return 0; ++ ++out_register: ++ mdiobus_unregister(bus); ++ return rc; ++} ++ ++static int bcm6368_mdiomux_remove(struct platform_device *pdev) ++{ ++ struct bcm6368_mdiomux_desc *md = platform_get_drvdata(pdev); ++ ++ mdio_mux_uninit(md->mux_handle); ++ mdiobus_unregister(md->mii_bus); ++ ++ return 0; ++} ++ ++static const struct of_device_id bcm6368_mdiomux_ids[] = { ++ { .compatible = "brcm,bcm6368-mdio-mux", }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, bcm6368_mdiomux_ids); ++ ++static struct platform_driver bcm6368_mdiomux_driver = { ++ .driver = { ++ .name = "bcm6368-mdio-mux", ++ .of_match_table = bcm6368_mdiomux_ids, ++ }, ++ .probe = bcm6368_mdiomux_probe, ++ .remove = bcm6368_mdiomux_remove, ++}; ++module_platform_driver(bcm6368_mdiomux_driver); ++ ++MODULE_AUTHOR("Álvaro Fernández Rojas "); ++MODULE_DESCRIPTION("BCM6368 mdiomux bus controller driver"); ++MODULE_LICENSE("GPL v2"); -- cgit v1.2.3