diff options
author | Álvaro Fernández Rojas <noltari@gmail.com> | 2021-03-01 08:21:59 +0100 |
---|---|---|
committer | Álvaro Fernández Rojas <noltari@gmail.com> | 2021-03-14 12:05:17 +0100 |
commit | 28dcb74de3a15fbdb0fd9afa16457b2de1181cd7 (patch) | |
tree | 80d2ecf31f784a814e0df5e6b906616d0f339f9a /target/linux/bmips/patches-5.10 | |
parent | bf4aa0c6a2f57951f995b2ac6f394c45ac852b9d (diff) | |
download | upstream-28dcb74de3a15fbdb0fd9afa16457b2de1181cd7.tar.gz upstream-28dcb74de3a15fbdb0fd9afa16457b2de1181cd7.tar.bz2 upstream-28dcb74de3a15fbdb0fd9afa16457b2de1181cd7.zip |
bmips: add experimental ethernet support
This adds experimental ethernet support for BCM6318, BCM6328, BCM6362, BCM6368
and BCM63268.
BCM6358 needs a different driver, so there's no support for now.
Working devices:
- Comtrend AR-5315u
- Comtrend AR-5387un
- Comtrend VR-3025u
- Comtrend VR-3032u
Not working devices:
- Netgear DGND3700 v2 (no idea on how the external switch is connected)
- Huawei HG556a ver B (BCM6358 needs a separate driveer)
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Diffstat (limited to 'target/linux/bmips/patches-5.10')
5 files changed, 597 insertions, 0 deletions
diff --git a/target/linux/bmips/patches-5.10/500-net-dsa-b53-relax-is63xx-condition.patch b/target/linux/bmips/patches-5.10/500-net-dsa-b53-relax-is63xx-condition.patch new file mode 100644 index 0000000000..f5dd4e2c59 --- /dev/null +++ b/target/linux/bmips/patches-5.10/500-net-dsa-b53-relax-is63xx-condition.patch @@ -0,0 +1,29 @@ +From cd6906754bbe3e0665ecaeca2cfb26d927fe9277 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com> +Date: Mon, 1 Mar 2021 07:29:29 +0100 +Subject: [PATCH 1/3] net: dsa: b53: relax is63xx() condition +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +BCM63xx switches are present on bcm63xx and bmips devices. + +Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com> +--- + drivers/net/dsa/b53/b53_priv.h | 4 ---- + 1 file changed, 4 deletions(-) + +--- a/drivers/net/dsa/b53/b53_priv.h ++++ b/drivers/net/dsa/b53/b53_priv.h +@@ -185,11 +185,7 @@ static inline int is531x5(struct b53_dev + + static inline int is63xx(struct b53_device *dev) + { +-#ifdef CONFIG_BCM63XX + return dev->chip_id == BCM63XX_DEVICE_ID; +-#else +- return 0; +-#endif + } + + static inline int is5301x(struct b53_device *dev) diff --git a/target/linux/bmips/patches-5.10/501-net-dsa-b53-mmap-Add-device-tree-support.patch b/target/linux/bmips/patches-5.10/501-net-dsa-b53-mmap-Add-device-tree-support.patch new file mode 100644 index 0000000000..e9eb87cb5c --- /dev/null +++ b/target/linux/bmips/patches-5.10/501-net-dsa-b53-mmap-Add-device-tree-support.patch @@ -0,0 +1,82 @@ +From f5419e7f362ae1c462baf28a2da7360267f8e4f9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com> +Date: Mon, 1 Mar 2021 07:32:32 +0100 +Subject: [PATCH 2/3] net: dsa: b53: mmap: Add device tree support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add device tree support to b53_mmap.c while keeping platform devices support. + +Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com> +--- + drivers/net/dsa/b53/b53_mmap.c | 36 ++++++++++++++++++++++++++++++++++ + 1 file changed, 36 insertions(+) + +--- a/drivers/net/dsa/b53/b53_mmap.c ++++ b/drivers/net/dsa/b53/b53_mmap.c +@@ -228,12 +228,64 @@ static const struct b53_io_ops b53_mmap_ + .write64 = b53_mmap_write64, + }; + ++static int b53_mmap_probe_of(struct platform_device *pdev, ++ struct b53_platform_data **ppdata) ++{ ++ struct device *dev = &pdev->dev; ++ struct device_node *np = dev->of_node; ++ struct device_node *of_ports, *of_port; ++ struct b53_platform_data *pdata; ++ void __iomem *mem; ++ ++ mem = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(mem)) ++ return PTR_ERR(mem); ++ ++ pdata = devm_kzalloc(dev, sizeof(struct b53_platform_data), ++ GFP_KERNEL); ++ if (!pdata) ++ return -ENOMEM; ++ ++ pdata->regs = mem; ++ pdata->chip_id = BCM63XX_DEVICE_ID; ++ pdata->big_endian = of_property_read_bool(np, "big-endian"); ++ ++ of_ports = of_get_child_by_name(np, "ports"); ++ if (!of_ports) { ++ dev_err(dev, "no ports child node found\n"); ++ return -EINVAL; ++ } ++ ++ for_each_available_child_of_node(of_ports, of_port) { ++ u32 reg; ++ ++ if (of_property_read_u32(of_port, "reg", ®)) ++ continue; ++ ++ if (reg < B53_CPU_PORT) ++ pdata->enabled_ports |= BIT(reg); ++ } ++ ++ *ppdata = pdata; ++ ++ return 0; ++} ++ + static int b53_mmap_probe(struct platform_device *pdev) + { ++ struct device_node *np = pdev->dev.of_node; + struct b53_platform_data *pdata = pdev->dev.platform_data; + struct b53_mmap_priv *priv; + struct b53_device *dev; + ++ if (np) { ++ int ret = b53_mmap_probe_of(pdev, &pdata); ++ if (ret) { ++ dev_err(&pdev->dev, "OF probe error\n"); ++ return ret; ++ } ++ } ++ + if (!pdata) + return -EINVAL; + diff --git a/target/linux/bmips/patches-5.10/502-net-dsa-b53-support-tags-for-legacy-switches.patch b/target/linux/bmips/patches-5.10/502-net-dsa-b53-support-tags-for-legacy-switches.patch new file mode 100644 index 0000000000..b8aa8b844d --- /dev/null +++ b/target/linux/bmips/patches-5.10/502-net-dsa-b53-support-tags-for-legacy-switches.patch @@ -0,0 +1,209 @@ +From 3bc3d79efdff6e29b80bf35f7a56baaa36e4d8fe Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com> +Date: Fri, 12 Mar 2021 12:35:39 +0100 +Subject: [PATCH] net: dsa: b53: support tags for legacy switches +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com> +--- + drivers/net/dsa/b53/Kconfig | 1 + + drivers/net/dsa/b53/b53_common.c | 6 +++ + include/net/dsa.h | 2 + + net/dsa/Kconfig | 7 +++ + net/dsa/tag_brcm.c | 93 ++++++++++++++++++++++++++++++++ + 5 files changed, 109 insertions(+) + +--- a/drivers/net/dsa/b53/Kconfig ++++ b/drivers/net/dsa/b53/Kconfig +@@ -3,6 +3,7 @@ menuconfig B53 + tristate "Broadcom BCM53xx managed switch support" + depends on NET_DSA + select NET_DSA_TAG_BRCM ++ select NET_DSA_TAG_BRCM_LEGACY + select NET_DSA_TAG_BRCM_PREPEND + help + This driver adds support for Broadcom managed switch chips. It supports +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -1992,6 +1992,7 @@ static bool b53_can_enable_brcm_tags(str + + switch (tag_protocol) { + case DSA_TAG_PROTO_BRCM: ++ case DSA_TAG_PROTO_BRCM_LEGACY: + case DSA_TAG_PROTO_BRCM_PREPEND: + dev_warn(ds->dev, + "Port %d is stacked to Broadcom tag switch\n", port); +@@ -2013,12 +2014,16 @@ enum dsa_tag_protocol b53_get_tag_protoc + /* Older models (5325, 5365) support a different tag format that we do + * not support in net/dsa/tag_brcm.c yet. + */ +- if (is5325(dev) || is5365(dev) || +- !b53_can_enable_brcm_tags(ds, port, mprot)) { ++ if (!b53_can_enable_brcm_tags(ds, port, mprot)) { + dev->tag_protocol = DSA_TAG_PROTO_NONE; + goto out; + } + ++ if (is5325(dev) || is5365(dev) || is63xx(dev)) { ++ dev->tag_protocol = DSA_TAG_PROTO_BRCM_LEGACY; ++ goto out; ++ } ++ + /* Broadcom BCM58xx chips have a flow accelerator on Port 8 + * which requires us to use the prepended Broadcom tag type + */ +--- a/include/net/dsa.h ++++ b/include/net/dsa.h +@@ -45,10 +45,12 @@ struct phylink_link_state; + #define DSA_TAG_PROTO_OCELOT_VALUE 15 + #define DSA_TAG_PROTO_AR9331_VALUE 16 + #define DSA_TAG_PROTO_RTL4_A_VALUE 17 ++#define DSA_TAG_PROTO_BRCM_LEGACY_VALUE 22 + + enum dsa_tag_protocol { + DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE, + DSA_TAG_PROTO_BRCM = DSA_TAG_PROTO_BRCM_VALUE, ++ DSA_TAG_PROTO_BRCM_LEGACY = DSA_TAG_PROTO_BRCM_LEGACY_VALUE, + DSA_TAG_PROTO_BRCM_PREPEND = DSA_TAG_PROTO_BRCM_PREPEND_VALUE, + DSA_TAG_PROTO_DSA = DSA_TAG_PROTO_DSA_VALUE, + DSA_TAG_PROTO_EDSA = DSA_TAG_PROTO_EDSA_VALUE, +--- a/net/dsa/Kconfig ++++ b/net/dsa/Kconfig +@@ -47,6 +47,13 @@ config NET_DSA_TAG_BRCM + Say Y if you want to enable support for tagging frames for the + Broadcom switches which place the tag after the MAC source address. + ++config NET_DSA_TAG_BRCM_LEGACY ++ tristate "Tag driver for Broadcom legacy switches using in-frame headers" ++ select NET_DSA_TAG_BRCM_COMMON ++ help ++ Say Y if you want to enable support for tagging frames for the ++ Broadcom legacy switches which place the tag after the MAC source ++ address. + + config NET_DSA_TAG_BRCM_PREPEND + tristate "Tag driver for Broadcom switches using prepended headers" +--- a/net/dsa/tag_brcm.c ++++ b/net/dsa/tag_brcm.c +@@ -8,9 +8,23 @@ + #include <linux/etherdevice.h> + #include <linux/list.h> + #include <linux/slab.h> ++#include <linux/types.h> + + #include "dsa_priv.h" + ++struct bcm_legacy_tag { ++ uint16_t type; ++#define BRCM_LEG_TYPE 0x8874 ++ ++ uint32_t tag; ++#define BRCM_LEG_TAG_PORT_ID (0xf) ++#define BRCM_LEG_TAG_MULTICAST (1 << 29) ++#define BRCM_LEG_TAG_EGRESS (2 << 29) ++#define BRCM_LEG_TAG_INGRESS (3 << 29) ++} __attribute__((packed)); ++ ++#define BRCM_LEG_TAG_LEN sizeof(struct bcm_legacy_tag) ++ + /* This tag length is 4 bytes, older ones were 6 bytes, we do not + * handle them + */ +@@ -197,6 +211,85 @@ DSA_TAG_DRIVER(brcm_netdev_ops); + MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_BRCM); + #endif + ++#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_LEGACY) ++static struct sk_buff *brcm_leg_tag_xmit(struct sk_buff *skb, ++ struct net_device *dev) ++{ ++ struct dsa_port *dp = dsa_slave_to_port(dev); ++ struct bcm_legacy_tag *brcm_tag; ++ ++ if (skb_cow_head(skb, BRCM_LEG_TAG_LEN) < 0) ++ return NULL; ++ ++ /* The Ethernet switch we are interfaced with needs packets to be at ++ * least 64 bytes (including FCS) otherwise they will be discarded when ++ * they enter the switch port logic. When Broadcom tags are enabled, we ++ * need to make sure that packets are at least 70 bytes ++ * (including FCS and tag) because the length verification is done after ++ * the Broadcom tag is stripped off the ingress packet. ++ * ++ * Let dsa_slave_xmit() free the SKB ++ */ ++ if (__skb_put_padto(skb, ETH_ZLEN + BRCM_LEG_TAG_LEN, false)) ++ return NULL; ++ ++ skb_push(skb, BRCM_LEG_TAG_LEN); ++ ++ memmove(skb->data, skb->data + BRCM_LEG_TAG_LEN, 2 * ETH_ALEN); ++ ++ brcm_tag = (struct bcm_legacy_tag *) (skb->data + 2 * ETH_ALEN); ++ ++ brcm_tag->type = BRCM_LEG_TYPE; ++ brcm_tag->tag = BRCM_LEG_TAG_EGRESS; ++ brcm_tag->tag |= dp->index & BRCM_LEG_TAG_PORT_ID; ++ ++ return skb; ++} ++ ++ ++static struct sk_buff *brcm_leg_tag_rcv(struct sk_buff *skb, ++ struct net_device *dev, ++ struct packet_type *pt) ++{ ++ int source_port; ++ struct bcm_legacy_tag *brcm_tag; ++ ++ if (unlikely(!pskb_may_pull(skb, BRCM_LEG_TAG_LEN))) ++ return NULL; ++ ++ brcm_tag = (struct bcm_legacy_tag *) (skb->data - 2); ++ ++ source_port = brcm_tag->tag & BRCM_LEG_TAG_PORT_ID; ++ ++ skb->dev = dsa_master_find_slave(dev, 0, source_port); ++ if (!skb->dev) ++ return NULL; ++ ++ /* Remove Broadcom tag and update checksum */ ++ skb_pull_rcsum(skb, BRCM_LEG_TAG_LEN); ++ ++ skb->offload_fwd_mark = 1; ++ ++ /* Move the Ethernet DA and SA */ ++ memmove(skb->data - ETH_HLEN, ++ skb->data - ETH_HLEN - BRCM_LEG_TAG_LEN, ++ 2 * ETH_ALEN); ++ ++ return skb; ++} ++ ++static const struct dsa_device_ops brcm_legacy_netdev_ops = { ++ .name = "brcm-legacy", ++ .proto = DSA_TAG_PROTO_BRCM_LEGACY, ++ .xmit = brcm_leg_tag_xmit, ++ .rcv = brcm_leg_tag_rcv, ++ .overhead = BRCM_LEG_TAG_LEN, ++}; ++ ++DSA_TAG_DRIVER(brcm_legacy_netdev_ops); ++MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_BRCM_LEGACY); ++#endif /* CONFIG_NET_DSA_TAG_BRCM_LEGACY */ ++ + #if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_PREPEND) + static struct sk_buff *brcm_tag_xmit_prepend(struct sk_buff *skb, + struct net_device *dev) +@@ -229,6 +322,9 @@ static struct dsa_tag_driver *dsa_tag_dr + #if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM) + &DSA_TAG_DRIVER_NAME(brcm_netdev_ops), + #endif ++#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_LEGACY) ++ &DSA_TAG_DRIVER_NAME(brcm_legacy_netdev_ops), ++#endif + #if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_PREPEND) + &DSA_TAG_DRIVER_NAME(brcm_prepend_netdev_ops), + #endif diff --git a/target/linux/bmips/patches-5.10/503-net-broadcom-add-BCM6368-enetsw-controller-driver.patch b/target/linux/bmips/patches-5.10/503-net-broadcom-add-BCM6368-enetsw-controller-driver.patch new file mode 100644 index 0000000000..c2c2e968e9 --- /dev/null +++ b/target/linux/bmips/patches-5.10/503-net-broadcom-add-BCM6368-enetsw-controller-driver.patch @@ -0,0 +1,46 @@ +From 590b60fb08cb1e70fe02d3f407c6b3dbe9ad06ff Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com> +Date: Mon, 1 Mar 2021 07:34:39 +0100 +Subject: [PATCH 3/4] net: broadcom: add BCM6368 enetsw controller driver +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 <noltari@gmail.com> +--- + drivers/net/ethernet/broadcom/Kconfig | 8 + + drivers/net/ethernet/broadcom/Makefile | 1 + + .../net/ethernet/broadcom/bcm6368-enetsw.c | 1111 +++++++++++++++++ + 3 files changed, 1120 insertions(+) + create mode 100644 drivers/net/ethernet/broadcom/bcm6368-enetsw.c + +--- a/drivers/net/ethernet/broadcom/Kconfig ++++ b/drivers/net/ethernet/broadcom/Kconfig +@@ -60,6 +60,14 @@ config BCM63XX_ENET + This driver supports the ethernet MACs in the Broadcom 63xx + MIPS chipset family (BCM63XX). + ++config BCM6368_ENETSW ++ tristate "Broadcom BCM6368 internal mac support" ++ depends on BMIPS_GENERIC || COMPILE_TEST ++ default y ++ help ++ This driver supports Ethernet controller integrated into Broadcom ++ BCM6368 family SoCs. ++ + config BCMGENET + tristate "Broadcom GENET internal MAC support" + depends on HAS_IOMEM +--- a/drivers/net/ethernet/broadcom/Makefile ++++ b/drivers/net/ethernet/broadcom/Makefile +@@ -5,6 +5,7 @@ + + obj-$(CONFIG_B44) += b44.o + obj-$(CONFIG_BCM63XX_ENET) += bcm63xx_enet.o ++obj-$(CONFIG_BCM6368_ENETSW) += bcm6368-enetsw.o + obj-$(CONFIG_BCMGENET) += genet/ + obj-$(CONFIG_BNX2) += bnx2.o + obj-$(CONFIG_CNIC) += cnic.o diff --git a/target/linux/bmips/patches-5.10/504-net-mdio-Add-BCM6368-MDIO-mux-bus-controller.patch b/target/linux/bmips/patches-5.10/504-net-mdio-Add-BCM6368-MDIO-mux-bus-controller.patch new file mode 100644 index 0000000000..a869681312 --- /dev/null +++ b/target/linux/bmips/patches-5.10/504-net-mdio-Add-BCM6368-MDIO-mux-bus-controller.patch @@ -0,0 +1,231 @@ +From b6ecb2bca2b8ff80ae4b1b15f09dcf071f4ceaf4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com> +Date: Mon, 1 Mar 2021 16:42:12 +0100 +Subject: [PATCH] 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 <noltari@gmail.com> +--- + drivers/net/mdio/Kconfig | 11 ++ + drivers/net/mdio/Makefile | 1 + + drivers/net/mdio/mdio-mux-bcm6368.c | 179 ++++++++++++++++++++++++++++ + 3 files changed, 191 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,179 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Broadcom BCM6368 mdiomux bus controller driver ++ * ++ * Copyright (C) 2021 Álvaro Fernández Rojas <noltari@gmail.com> ++ */ ++ ++#include <linux/delay.h> ++#include <linux/io.h> ++#include <linux/kernel.h> ++#include <linux/mdio-mux.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 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); |