Skip to content

Commit cf51016

Browse files
committed
Merge branch 'net-dsa-b53-mmap-add-bcm63xx-ephy-power-control'
Kyle Hendry says: ==================== net: dsa: b53: mmap: Add bcm63xx EPHY power control The gpio controller on some bcm63xx SoCs has a register for controlling functionality of the internal fast ethernet phys. These patches allow the b53 driver to enable/disable phy power. The register also contains reset bits which will be set by a reset driver in another patch series: https://lore.kernel.org/all/20250715234605.36216-1-kylehendrydev@gmail.com/ v1: https://lore.kernel.org/20250716002922.230807-1-kylehendrydev@gmail.com ==================== Link: https://patch.msgid.link/20250724035300.20497-1-kylehendrydev@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2 parents 33360f2 + 5ac0002 commit cf51016

4 files changed

Lines changed: 134 additions & 21 deletions

File tree

Documentation/devicetree/bindings/net/dsa/brcm,b53.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ properties:
6666
- brcm,bcm63268-switch
6767
- const: brcm,bcm63xx-switch
6868

69+
brcm,gpio-ctrl:
70+
description:
71+
A phandle to the syscon node of the bcm63xx gpio controller
72+
which contains phy control registers
73+
$ref: /schemas/types.yaml#/definitions/phandle
74+
6975
required:
7076
- compatible
7177
- reg

drivers/net/dsa/b53/b53_common.c

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,9 @@ int b53_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy)
689689

690690
cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
691691

692+
if (dev->ops->phy_enable)
693+
dev->ops->phy_enable(dev, port);
694+
692695
if (dev->ops->irq_enable)
693696
ret = dev->ops->irq_enable(dev, port);
694697
if (ret)
@@ -727,6 +730,9 @@ void b53_disable_port(struct dsa_switch *ds, int port)
727730
reg |= PORT_CTRL_RX_DISABLE | PORT_CTRL_TX_DISABLE;
728731
b53_write8(dev, B53_CTRL_PAGE, B53_PORT_CTRL(port), reg);
729732

733+
if (dev->ops->phy_disable)
734+
dev->ops->phy_disable(dev, port);
735+
730736
if (dev->ops->irq_disable)
731737
dev->ops->irq_disable(dev, port);
732738
}
@@ -1404,7 +1410,7 @@ static void b53_adjust_63xx_rgmii(struct dsa_switch *ds, int port,
14041410
b53_read8(dev, B53_CTRL_PAGE, B53_RGMII_CTRL_P(port), &rgmii_ctrl);
14051411
rgmii_ctrl &= ~(RGMII_CTRL_DLL_RXC | RGMII_CTRL_DLL_TXC);
14061412

1407-
if (is63268(dev))
1413+
if (is6318_268(dev))
14081414
rgmii_ctrl |= RGMII_CTRL_MII_OVERRIDE;
14091415

14101416
rgmii_ctrl |= RGMII_CTRL_ENABLE_GMII;
@@ -2768,19 +2774,6 @@ static const struct b53_chip_data b53_switch_chips[] = {
27682774
.jumbo_pm_reg = B53_JUMBO_PORT_MASK_63XX,
27692775
.jumbo_size_reg = B53_JUMBO_MAX_SIZE_63XX,
27702776
},
2771-
{
2772-
.chip_id = BCM63268_DEVICE_ID,
2773-
.dev_name = "BCM63268",
2774-
.vlans = 4096,
2775-
.enabled_ports = 0, /* pdata must provide them */
2776-
.arl_bins = 4,
2777-
.arl_buckets = 1024,
2778-
.imp_port = 8,
2779-
.vta_regs = B53_VTA_REGS_63XX,
2780-
.duplex_reg = B53_DUPLEX_STAT_63XX,
2781-
.jumbo_pm_reg = B53_JUMBO_PORT_MASK_63XX,
2782-
.jumbo_size_reg = B53_JUMBO_MAX_SIZE_63XX,
2783-
},
27842777
{
27852778
.chip_id = BCM53010_DEVICE_ID,
27862779
.dev_name = "BCM53010",
@@ -2930,13 +2923,17 @@ static const struct b53_chip_data b53_switch_chips[] = {
29302923

29312924
static int b53_switch_init(struct b53_device *dev)
29322925
{
2926+
u32 chip_id = dev->chip_id;
29332927
unsigned int i;
29342928
int ret;
29352929

2930+
if (is63xx(dev))
2931+
chip_id = BCM63XX_DEVICE_ID;
2932+
29362933
for (i = 0; i < ARRAY_SIZE(b53_switch_chips); i++) {
29372934
const struct b53_chip_data *chip = &b53_switch_chips[i];
29382935

2939-
if (chip->chip_id == dev->chip_id) {
2936+
if (chip->chip_id == chip_id) {
29402937
if (!dev->enabled_ports)
29412938
dev->enabled_ports = chip->enabled_ports;
29422939
dev->name = chip->dev_name;

drivers/net/dsa/b53/b53_mmap.c

Lines changed: 103 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,54 @@
2121
#include <linux/module.h>
2222
#include <linux/of.h>
2323
#include <linux/io.h>
24+
#include <linux/mfd/syscon.h>
2425
#include <linux/platform_device.h>
2526
#include <linux/platform_data/b53.h>
27+
#include <linux/regmap.h>
2628

2729
#include "b53_priv.h"
2830

31+
#define BCM63XX_EPHY_REG 0x3C
32+
33+
struct b53_phy_info {
34+
u32 ephy_enable_mask;
35+
u32 ephy_port_mask;
36+
u32 ephy_bias_bit;
37+
const u32 *ephy_offset;
38+
};
39+
2940
struct b53_mmap_priv {
3041
void __iomem *regs;
42+
struct regmap *gpio_ctrl;
43+
const struct b53_phy_info *phy_info;
44+
u32 phys_enabled;
45+
};
46+
47+
static const u32 bcm6318_ephy_offsets[] = {4, 5, 6, 7};
48+
49+
static const struct b53_phy_info bcm6318_ephy_info = {
50+
.ephy_enable_mask = BIT(0) | BIT(4) | BIT(8) | BIT(12) | BIT(16),
51+
.ephy_port_mask = GENMASK((ARRAY_SIZE(bcm6318_ephy_offsets) - 1), 0),
52+
.ephy_bias_bit = 24,
53+
.ephy_offset = bcm6318_ephy_offsets,
54+
};
55+
56+
static const u32 bcm6368_ephy_offsets[] = {2, 3, 4, 5};
57+
58+
static const struct b53_phy_info bcm6368_ephy_info = {
59+
.ephy_enable_mask = BIT(0),
60+
.ephy_port_mask = GENMASK((ARRAY_SIZE(bcm6368_ephy_offsets) - 1), 0),
61+
.ephy_bias_bit = 0,
62+
.ephy_offset = bcm6368_ephy_offsets,
63+
};
64+
65+
static const u32 bcm63268_ephy_offsets[] = {4, 9, 14};
66+
67+
static const struct b53_phy_info bcm63268_ephy_info = {
68+
.ephy_enable_mask = GENMASK(4, 0),
69+
.ephy_port_mask = GENMASK((ARRAY_SIZE(bcm63268_ephy_offsets) - 1), 0),
70+
.ephy_bias_bit = 24,
71+
.ephy_offset = bcm63268_ephy_offsets,
3172
};
3273

3374
static int b53_mmap_read8(struct b53_device *dev, u8 page, u8 reg, u8 *val)
@@ -229,6 +270,50 @@ static int b53_mmap_phy_write16(struct b53_device *dev, int addr, int reg,
229270
return -EIO;
230271
}
231272

273+
static int bcm63xx_ephy_set(struct b53_device *dev, int port, bool enable)
274+
{
275+
struct b53_mmap_priv *priv = dev->priv;
276+
const struct b53_phy_info *info = priv->phy_info;
277+
struct regmap *gpio_ctrl = priv->gpio_ctrl;
278+
u32 mask, val;
279+
280+
if (enable) {
281+
mask = (info->ephy_enable_mask << info->ephy_offset[port])
282+
| BIT(info->ephy_bias_bit);
283+
val = 0;
284+
} else {
285+
mask = (info->ephy_enable_mask << info->ephy_offset[port]);
286+
if (!((priv->phys_enabled & ~BIT(port)) & info->ephy_port_mask))
287+
mask |= BIT(info->ephy_bias_bit);
288+
val = mask;
289+
}
290+
return regmap_update_bits(gpio_ctrl, BCM63XX_EPHY_REG, mask, val);
291+
}
292+
293+
static void b53_mmap_phy_enable(struct b53_device *dev, int port)
294+
{
295+
struct b53_mmap_priv *priv = dev->priv;
296+
int ret = 0;
297+
298+
if (priv->phy_info && (BIT(port) & priv->phy_info->ephy_port_mask))
299+
ret = bcm63xx_ephy_set(dev, port, true);
300+
301+
if (!ret)
302+
priv->phys_enabled |= BIT(port);
303+
}
304+
305+
static void b53_mmap_phy_disable(struct b53_device *dev, int port)
306+
{
307+
struct b53_mmap_priv *priv = dev->priv;
308+
int ret = 0;
309+
310+
if (priv->phy_info && (BIT(port) & priv->phy_info->ephy_port_mask))
311+
ret = bcm63xx_ephy_set(dev, port, false);
312+
313+
if (!ret)
314+
priv->phys_enabled &= ~BIT(port);
315+
}
316+
232317
static const struct b53_io_ops b53_mmap_ops = {
233318
.read8 = b53_mmap_read8,
234319
.read16 = b53_mmap_read16,
@@ -242,6 +327,8 @@ static const struct b53_io_ops b53_mmap_ops = {
242327
.write64 = b53_mmap_write64,
243328
.phy_read16 = b53_mmap_phy_read16,
244329
.phy_write16 = b53_mmap_phy_write16,
330+
.phy_enable = b53_mmap_phy_enable,
331+
.phy_disable = b53_mmap_phy_disable,
245332
};
246333

247334
static int b53_mmap_probe_of(struct platform_device *pdev,
@@ -313,6 +400,18 @@ static int b53_mmap_probe(struct platform_device *pdev)
313400

314401
priv->regs = pdata->regs;
315402

403+
priv->gpio_ctrl = syscon_regmap_lookup_by_phandle(np, "brcm,gpio-ctrl");
404+
if (!IS_ERR(priv->gpio_ctrl)) {
405+
if (pdata->chip_id == BCM6318_DEVICE_ID ||
406+
pdata->chip_id == BCM6328_DEVICE_ID ||
407+
pdata->chip_id == BCM6362_DEVICE_ID)
408+
priv->phy_info = &bcm6318_ephy_info;
409+
else if (pdata->chip_id == BCM6368_DEVICE_ID)
410+
priv->phy_info = &bcm6368_ephy_info;
411+
else if (pdata->chip_id == BCM63268_DEVICE_ID)
412+
priv->phy_info = &bcm63268_ephy_info;
413+
}
414+
316415
dev = b53_switch_alloc(&pdev->dev, &b53_mmap_ops, priv);
317416
if (!dev)
318417
return -ENOMEM;
@@ -348,16 +447,16 @@ static const struct of_device_id b53_mmap_of_table[] = {
348447
.data = (void *)BCM63XX_DEVICE_ID,
349448
}, {
350449
.compatible = "brcm,bcm6318-switch",
351-
.data = (void *)BCM63268_DEVICE_ID,
450+
.data = (void *)BCM6318_DEVICE_ID,
352451
}, {
353452
.compatible = "brcm,bcm6328-switch",
354-
.data = (void *)BCM63XX_DEVICE_ID,
453+
.data = (void *)BCM6328_DEVICE_ID,
355454
}, {
356455
.compatible = "brcm,bcm6362-switch",
357-
.data = (void *)BCM63XX_DEVICE_ID,
456+
.data = (void *)BCM6362_DEVICE_ID,
358457
}, {
359458
.compatible = "brcm,bcm6368-switch",
360-
.data = (void *)BCM63XX_DEVICE_ID,
459+
.data = (void *)BCM6368_DEVICE_ID,
361460
}, {
362461
.compatible = "brcm,bcm63268-switch",
363462
.data = (void *)BCM63268_DEVICE_ID,

drivers/net/dsa/b53/b53_priv.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ struct b53_io_ops {
4545
int (*phy_write16)(struct b53_device *dev, int addr, int reg, u16 value);
4646
int (*irq_enable)(struct b53_device *dev, int port);
4747
void (*irq_disable)(struct b53_device *dev, int port);
48+
void (*phy_enable)(struct b53_device *dev, int port);
49+
void (*phy_disable)(struct b53_device *dev, int port);
4850
void (*phylink_get_caps)(struct b53_device *dev, int port,
4951
struct phylink_config *config);
5052
struct phylink_pcs *(*phylink_mac_select_pcs)(struct b53_device *dev,
@@ -71,6 +73,10 @@ enum {
7173
BCM53125_DEVICE_ID = 0x53125,
7274
BCM53128_DEVICE_ID = 0x53128,
7375
BCM63XX_DEVICE_ID = 0x6300,
76+
BCM6318_DEVICE_ID = 0x6318,
77+
BCM6328_DEVICE_ID = 0x6328,
78+
BCM6362_DEVICE_ID = 0x6362,
79+
BCM6368_DEVICE_ID = 0x6368,
7480
BCM63268_DEVICE_ID = 0x63268,
7581
BCM53010_DEVICE_ID = 0x53010,
7682
BCM53011_DEVICE_ID = 0x53011,
@@ -218,12 +224,17 @@ static inline int is531x5(struct b53_device *dev)
218224
static inline int is63xx(struct b53_device *dev)
219225
{
220226
return dev->chip_id == BCM63XX_DEVICE_ID ||
227+
dev->chip_id == BCM6318_DEVICE_ID ||
228+
dev->chip_id == BCM6328_DEVICE_ID ||
229+
dev->chip_id == BCM6362_DEVICE_ID ||
230+
dev->chip_id == BCM6368_DEVICE_ID ||
221231
dev->chip_id == BCM63268_DEVICE_ID;
222232
}
223233

224-
static inline int is63268(struct b53_device *dev)
234+
static inline int is6318_268(struct b53_device *dev)
225235
{
226-
return dev->chip_id == BCM63268_DEVICE_ID;
236+
return dev->chip_id == BCM6318_DEVICE_ID ||
237+
dev->chip_id == BCM63268_DEVICE_ID;
227238
}
228239

229240
static inline int is5301x(struct b53_device *dev)

0 commit comments

Comments
 (0)