From be7a79145d85af1a9d65a45560b9243b13a67782 Mon Sep 17 00:00:00 2001 From: Kyle Hendry Date: Wed, 23 Jul 2025 20:52:40 -0700 Subject: [PATCH 1/7] net: dsa: b53: Add phy_enable(), phy_disable() methods Add phy enable/disable to b53 ops to be called when enabling/disabling ports. Signed-off-by: Kyle Hendry Reviewed-by: Florian Fainelli Link: https://patch.msgid.link/20250724035300.20497-2-kylehendrydev@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/dsa/b53/b53_common.c | 6 ++++++ drivers/net/dsa/b53/b53_priv.h | 2 ++ 2 files changed, 8 insertions(+) diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c index 46978757c972..77acc7b8abfb 100644 --- a/drivers/net/dsa/b53/b53_common.c +++ b/drivers/net/dsa/b53/b53_common.c @@ -689,6 +689,9 @@ int b53_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy) cpu_port = dsa_to_port(ds, port)->cpu_dp->index; + if (dev->ops->phy_enable) + dev->ops->phy_enable(dev, port); + if (dev->ops->irq_enable) ret = dev->ops->irq_enable(dev, port); if (ret) @@ -727,6 +730,9 @@ void b53_disable_port(struct dsa_switch *ds, int port) reg |= PORT_CTRL_RX_DISABLE | PORT_CTRL_TX_DISABLE; b53_write8(dev, B53_CTRL_PAGE, B53_PORT_CTRL(port), reg); + if (dev->ops->phy_disable) + dev->ops->phy_disable(dev, port); + if (dev->ops->irq_disable) dev->ops->irq_disable(dev, port); } diff --git a/drivers/net/dsa/b53/b53_priv.h b/drivers/net/dsa/b53/b53_priv.h index b1b9e8882ba4..f1124f5e50da 100644 --- a/drivers/net/dsa/b53/b53_priv.h +++ b/drivers/net/dsa/b53/b53_priv.h @@ -45,6 +45,8 @@ struct b53_io_ops { int (*phy_write16)(struct b53_device *dev, int addr, int reg, u16 value); int (*irq_enable)(struct b53_device *dev, int port); void (*irq_disable)(struct b53_device *dev, int port); + void (*phy_enable)(struct b53_device *dev, int port); + void (*phy_disable)(struct b53_device *dev, int port); void (*phylink_get_caps)(struct b53_device *dev, int port, struct phylink_config *config); struct phylink_pcs *(*phylink_mac_select_pcs)(struct b53_device *dev, From cce3563875c7903210398644e7eba89d70d022d7 Mon Sep 17 00:00:00 2001 From: Kyle Hendry Date: Wed, 23 Jul 2025 20:52:41 -0700 Subject: [PATCH 2/7] dt-bindings: net: dsa: b53: Document brcm,gpio-ctrl property Add description for bcm63xx gpio-ctrl phandle which allows access to registers that control phy functionality. Signed-off-by: Kyle Hendry Reviewed-by: Rob Herring (Arm) Link: https://patch.msgid.link/20250724035300.20497-3-kylehendrydev@gmail.com Signed-off-by: Jakub Kicinski --- Documentation/devicetree/bindings/net/dsa/brcm,b53.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/net/dsa/brcm,b53.yaml b/Documentation/devicetree/bindings/net/dsa/brcm,b53.yaml index d6c957a33b48..fbab3a1a8d3e 100644 --- a/Documentation/devicetree/bindings/net/dsa/brcm,b53.yaml +++ b/Documentation/devicetree/bindings/net/dsa/brcm,b53.yaml @@ -66,6 +66,12 @@ properties: - brcm,bcm63268-switch - const: brcm,bcm63xx-switch + brcm,gpio-ctrl: + description: + A phandle to the syscon node of the bcm63xx gpio controller + which contains phy control registers + $ref: /schemas/types.yaml#/definitions/phandle + required: - compatible - reg From fcf02a462fab52fbfcb24e617dd940745afd0dff Mon Sep 17 00:00:00 2001 From: Kyle Hendry Date: Wed, 23 Jul 2025 20:52:42 -0700 Subject: [PATCH 3/7] net: dsa: b53: Define chip IDs for more bcm63xx SoCs Add defines for bcm6318, bcm6328, bcm6362, bcm6368 chip IDs, update tables and switch init. Signed-off-by: Kyle Hendry Reviewed-by: Florian Fainelli Link: https://patch.msgid.link/20250724035300.20497-4-kylehendrydev@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/dsa/b53/b53_common.c | 21 ++++++--------------- drivers/net/dsa/b53/b53_mmap.c | 8 ++++---- drivers/net/dsa/b53/b53_priv.h | 13 +++++++++++-- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c index 77acc7b8abfb..9942fb6f7f4b 100644 --- a/drivers/net/dsa/b53/b53_common.c +++ b/drivers/net/dsa/b53/b53_common.c @@ -1410,7 +1410,7 @@ static void b53_adjust_63xx_rgmii(struct dsa_switch *ds, int port, b53_read8(dev, B53_CTRL_PAGE, B53_RGMII_CTRL_P(port), &rgmii_ctrl); rgmii_ctrl &= ~(RGMII_CTRL_DLL_RXC | RGMII_CTRL_DLL_TXC); - if (is63268(dev)) + if (is6318_268(dev)) rgmii_ctrl |= RGMII_CTRL_MII_OVERRIDE; rgmii_ctrl |= RGMII_CTRL_ENABLE_GMII; @@ -2774,19 +2774,6 @@ static const struct b53_chip_data b53_switch_chips[] = { .jumbo_pm_reg = B53_JUMBO_PORT_MASK_63XX, .jumbo_size_reg = B53_JUMBO_MAX_SIZE_63XX, }, - { - .chip_id = BCM63268_DEVICE_ID, - .dev_name = "BCM63268", - .vlans = 4096, - .enabled_ports = 0, /* pdata must provide them */ - .arl_bins = 4, - .arl_buckets = 1024, - .imp_port = 8, - .vta_regs = B53_VTA_REGS_63XX, - .duplex_reg = B53_DUPLEX_STAT_63XX, - .jumbo_pm_reg = B53_JUMBO_PORT_MASK_63XX, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE_63XX, - }, { .chip_id = BCM53010_DEVICE_ID, .dev_name = "BCM53010", @@ -2936,13 +2923,17 @@ static const struct b53_chip_data b53_switch_chips[] = { static int b53_switch_init(struct b53_device *dev) { + u32 chip_id = dev->chip_id; unsigned int i; int ret; + if (is63xx(dev)) + chip_id = BCM63XX_DEVICE_ID; + for (i = 0; i < ARRAY_SIZE(b53_switch_chips); i++) { const struct b53_chip_data *chip = &b53_switch_chips[i]; - if (chip->chip_id == dev->chip_id) { + if (chip->chip_id == chip_id) { if (!dev->enabled_ports) dev->enabled_ports = chip->enabled_ports; dev->name = chip->dev_name; diff --git a/drivers/net/dsa/b53/b53_mmap.c b/drivers/net/dsa/b53/b53_mmap.c index c687360a5b7f..f97556c6ca2a 100644 --- a/drivers/net/dsa/b53/b53_mmap.c +++ b/drivers/net/dsa/b53/b53_mmap.c @@ -348,16 +348,16 @@ static const struct of_device_id b53_mmap_of_table[] = { .data = (void *)BCM63XX_DEVICE_ID, }, { .compatible = "brcm,bcm6318-switch", - .data = (void *)BCM63268_DEVICE_ID, + .data = (void *)BCM6318_DEVICE_ID, }, { .compatible = "brcm,bcm6328-switch", - .data = (void *)BCM63XX_DEVICE_ID, + .data = (void *)BCM6328_DEVICE_ID, }, { .compatible = "brcm,bcm6362-switch", - .data = (void *)BCM63XX_DEVICE_ID, + .data = (void *)BCM6362_DEVICE_ID, }, { .compatible = "brcm,bcm6368-switch", - .data = (void *)BCM63XX_DEVICE_ID, + .data = (void *)BCM6368_DEVICE_ID, }, { .compatible = "brcm,bcm63268-switch", .data = (void *)BCM63268_DEVICE_ID, diff --git a/drivers/net/dsa/b53/b53_priv.h b/drivers/net/dsa/b53/b53_priv.h index f1124f5e50da..458775f95164 100644 --- a/drivers/net/dsa/b53/b53_priv.h +++ b/drivers/net/dsa/b53/b53_priv.h @@ -73,6 +73,10 @@ enum { BCM53125_DEVICE_ID = 0x53125, BCM53128_DEVICE_ID = 0x53128, BCM63XX_DEVICE_ID = 0x6300, + BCM6318_DEVICE_ID = 0x6318, + BCM6328_DEVICE_ID = 0x6328, + BCM6362_DEVICE_ID = 0x6362, + BCM6368_DEVICE_ID = 0x6368, BCM63268_DEVICE_ID = 0x63268, BCM53010_DEVICE_ID = 0x53010, BCM53011_DEVICE_ID = 0x53011, @@ -220,12 +224,17 @@ static inline int is531x5(struct b53_device *dev) static inline int is63xx(struct b53_device *dev) { return dev->chip_id == BCM63XX_DEVICE_ID || + dev->chip_id == BCM6318_DEVICE_ID || + dev->chip_id == BCM6328_DEVICE_ID || + dev->chip_id == BCM6362_DEVICE_ID || + dev->chip_id == BCM6368_DEVICE_ID || dev->chip_id == BCM63268_DEVICE_ID; } -static inline int is63268(struct b53_device *dev) +static inline int is6318_268(struct b53_device *dev) { - return dev->chip_id == BCM63268_DEVICE_ID; + return dev->chip_id == BCM6318_DEVICE_ID || + dev->chip_id == BCM63268_DEVICE_ID; } static inline int is5301x(struct b53_device *dev) From aed2aaa3c963f8aabbfa061a177022fee826ebfb Mon Sep 17 00:00:00 2001 From: Kyle Hendry Date: Wed, 23 Jul 2025 20:52:43 -0700 Subject: [PATCH 4/7] net: dsa: b53: mmap: Add syscon reference and register layout for bcm63268 On bcm63xx SoCs there are registers that control the PHYs in the GPIO controller. Allow the b53 driver to access them by passing in the syscon through the device tree. Add a structure to describe the ephy control register and add register info for bcm63268. Signed-off-by: Kyle Hendry Reviewed-by: Florian Fainelli Link: https://patch.msgid.link/20250724035300.20497-5-kylehendrydev@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/dsa/b53/b53_mmap.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/drivers/net/dsa/b53/b53_mmap.c b/drivers/net/dsa/b53/b53_mmap.c index f97556c6ca2a..35bf39ab2771 100644 --- a/drivers/net/dsa/b53/b53_mmap.c +++ b/drivers/net/dsa/b53/b53_mmap.c @@ -21,13 +21,32 @@ #include #include #include +#include #include #include #include "b53_priv.h" +struct b53_phy_info { + u32 ephy_enable_mask; + u32 ephy_port_mask; + u32 ephy_bias_bit; + const u32 *ephy_offset; +}; + struct b53_mmap_priv { void __iomem *regs; + struct regmap *gpio_ctrl; + const struct b53_phy_info *phy_info; +}; + +static const u32 bcm63268_ephy_offsets[] = {4, 9, 14}; + +static const struct b53_phy_info bcm63268_ephy_info = { + .ephy_enable_mask = GENMASK(4, 0), + .ephy_port_mask = GENMASK((ARRAY_SIZE(bcm63268_ephy_offsets) - 1), 0), + .ephy_bias_bit = 24, + .ephy_offset = bcm63268_ephy_offsets, }; static int b53_mmap_read8(struct b53_device *dev, u8 page, u8 reg, u8 *val) @@ -313,6 +332,12 @@ static int b53_mmap_probe(struct platform_device *pdev) priv->regs = pdata->regs; + priv->gpio_ctrl = syscon_regmap_lookup_by_phandle(np, "brcm,gpio-ctrl"); + if (!IS_ERR(priv->gpio_ctrl)) { + if (pdata->chip_id == BCM63268_DEVICE_ID) + priv->phy_info = &bcm63268_ephy_info; + } + dev = b53_switch_alloc(&pdev->dev, &b53_mmap_ops, priv); if (!dev) return -ENOMEM; From c251304ab021ff21c77e83e0babcb9eb76f8787a Mon Sep 17 00:00:00 2001 From: Kyle Hendry Date: Wed, 23 Jul 2025 20:52:44 -0700 Subject: [PATCH 5/7] net: dsa: b53: mmap: Add register layout for bcm6318 Add ephy register info for bcm6318, which also applies to bcm6328 and bcm6362. Signed-off-by: Kyle Hendry Reviewed-by: Florian Fainelli Link: https://patch.msgid.link/20250724035300.20497-6-kylehendrydev@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/dsa/b53/b53_mmap.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/net/dsa/b53/b53_mmap.c b/drivers/net/dsa/b53/b53_mmap.c index 35bf39ab2771..51303f075a1f 100644 --- a/drivers/net/dsa/b53/b53_mmap.c +++ b/drivers/net/dsa/b53/b53_mmap.c @@ -40,6 +40,15 @@ struct b53_mmap_priv { const struct b53_phy_info *phy_info; }; +static const u32 bcm6318_ephy_offsets[] = {4, 5, 6, 7}; + +static const struct b53_phy_info bcm6318_ephy_info = { + .ephy_enable_mask = BIT(0) | BIT(4) | BIT(8) | BIT(12) | BIT(16), + .ephy_port_mask = GENMASK((ARRAY_SIZE(bcm6318_ephy_offsets) - 1), 0), + .ephy_bias_bit = 24, + .ephy_offset = bcm6318_ephy_offsets, +}; + static const u32 bcm63268_ephy_offsets[] = {4, 9, 14}; static const struct b53_phy_info bcm63268_ephy_info = { @@ -334,7 +343,11 @@ static int b53_mmap_probe(struct platform_device *pdev) priv->gpio_ctrl = syscon_regmap_lookup_by_phandle(np, "brcm,gpio-ctrl"); if (!IS_ERR(priv->gpio_ctrl)) { - if (pdata->chip_id == BCM63268_DEVICE_ID) + if (pdata->chip_id == BCM6318_DEVICE_ID || + pdata->chip_id == BCM6328_DEVICE_ID || + pdata->chip_id == BCM6362_DEVICE_ID) + priv->phy_info = &bcm6318_ephy_info; + else if (pdata->chip_id == BCM63268_DEVICE_ID) priv->phy_info = &bcm63268_ephy_info; } From e8e13073dff7052b144d002bae2cfe9ddfa27e2a Mon Sep 17 00:00:00 2001 From: Kyle Hendry Date: Wed, 23 Jul 2025 20:52:45 -0700 Subject: [PATCH 6/7] net: dsa: b53: mmap: Add register layout for bcm6368 Add ephy register info for bcm6368. Signed-off-by: Kyle Hendry Reviewed-by: Florian Fainelli Link: https://patch.msgid.link/20250724035300.20497-7-kylehendrydev@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/dsa/b53/b53_mmap.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/net/dsa/b53/b53_mmap.c b/drivers/net/dsa/b53/b53_mmap.c index 51303f075a1f..8f5914e2a790 100644 --- a/drivers/net/dsa/b53/b53_mmap.c +++ b/drivers/net/dsa/b53/b53_mmap.c @@ -49,6 +49,15 @@ static const struct b53_phy_info bcm6318_ephy_info = { .ephy_offset = bcm6318_ephy_offsets, }; +static const u32 bcm6368_ephy_offsets[] = {2, 3, 4, 5}; + +static const struct b53_phy_info bcm6368_ephy_info = { + .ephy_enable_mask = BIT(0), + .ephy_port_mask = GENMASK((ARRAY_SIZE(bcm6368_ephy_offsets) - 1), 0), + .ephy_bias_bit = 0, + .ephy_offset = bcm6368_ephy_offsets, +}; + static const u32 bcm63268_ephy_offsets[] = {4, 9, 14}; static const struct b53_phy_info bcm63268_ephy_info = { @@ -347,6 +356,8 @@ static int b53_mmap_probe(struct platform_device *pdev) pdata->chip_id == BCM6328_DEVICE_ID || pdata->chip_id == BCM6362_DEVICE_ID) priv->phy_info = &bcm6318_ephy_info; + else if (pdata->chip_id == BCM6368_DEVICE_ID) + priv->phy_info = &bcm6368_ephy_info; else if (pdata->chip_id == BCM63268_DEVICE_ID) priv->phy_info = &bcm63268_ephy_info; } From 5ac00023852d960528a0c1d10ae6c17893fc4113 Mon Sep 17 00:00:00 2001 From: Kyle Hendry Date: Wed, 23 Jul 2025 20:52:46 -0700 Subject: [PATCH 7/7] net: dsa: b53: mmap: Implement bcm63xx ephy power control Implement the phy enable/disable calls for b53 mmap, and set the power down registers in the ephy control register appropriately. Signed-off-by: Kyle Hendry Reviewed-by: Florian Fainelli Link: https://patch.msgid.link/20250724035300.20497-8-kylehendrydev@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/dsa/b53/b53_mmap.c | 50 ++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/drivers/net/dsa/b53/b53_mmap.c b/drivers/net/dsa/b53/b53_mmap.c index 8f5914e2a790..f06c3e0cc42a 100644 --- a/drivers/net/dsa/b53/b53_mmap.c +++ b/drivers/net/dsa/b53/b53_mmap.c @@ -24,9 +24,12 @@ #include #include #include +#include #include "b53_priv.h" +#define BCM63XX_EPHY_REG 0x3C + struct b53_phy_info { u32 ephy_enable_mask; u32 ephy_port_mask; @@ -38,6 +41,7 @@ struct b53_mmap_priv { void __iomem *regs; struct regmap *gpio_ctrl; const struct b53_phy_info *phy_info; + u32 phys_enabled; }; static const u32 bcm6318_ephy_offsets[] = {4, 5, 6, 7}; @@ -266,6 +270,50 @@ static int b53_mmap_phy_write16(struct b53_device *dev, int addr, int reg, return -EIO; } +static int bcm63xx_ephy_set(struct b53_device *dev, int port, bool enable) +{ + struct b53_mmap_priv *priv = dev->priv; + const struct b53_phy_info *info = priv->phy_info; + struct regmap *gpio_ctrl = priv->gpio_ctrl; + u32 mask, val; + + if (enable) { + mask = (info->ephy_enable_mask << info->ephy_offset[port]) + | BIT(info->ephy_bias_bit); + val = 0; + } else { + mask = (info->ephy_enable_mask << info->ephy_offset[port]); + if (!((priv->phys_enabled & ~BIT(port)) & info->ephy_port_mask)) + mask |= BIT(info->ephy_bias_bit); + val = mask; + } + return regmap_update_bits(gpio_ctrl, BCM63XX_EPHY_REG, mask, val); +} + +static void b53_mmap_phy_enable(struct b53_device *dev, int port) +{ + struct b53_mmap_priv *priv = dev->priv; + int ret = 0; + + if (priv->phy_info && (BIT(port) & priv->phy_info->ephy_port_mask)) + ret = bcm63xx_ephy_set(dev, port, true); + + if (!ret) + priv->phys_enabled |= BIT(port); +} + +static void b53_mmap_phy_disable(struct b53_device *dev, int port) +{ + struct b53_mmap_priv *priv = dev->priv; + int ret = 0; + + if (priv->phy_info && (BIT(port) & priv->phy_info->ephy_port_mask)) + ret = bcm63xx_ephy_set(dev, port, false); + + if (!ret) + priv->phys_enabled &= ~BIT(port); +} + static const struct b53_io_ops b53_mmap_ops = { .read8 = b53_mmap_read8, .read16 = b53_mmap_read16, @@ -279,6 +327,8 @@ static const struct b53_io_ops b53_mmap_ops = { .write64 = b53_mmap_write64, .phy_read16 = b53_mmap_phy_read16, .phy_write16 = b53_mmap_phy_write16, + .phy_enable = b53_mmap_phy_enable, + .phy_disable = b53_mmap_phy_disable, }; static int b53_mmap_probe_of(struct platform_device *pdev,