mirror of
https://github.com/torvalds/linux.git
synced 2026-06-04 12:35:52 +02:00
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>
This commit is contained in:
commit
cf51016ba8
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -1404,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;
|
||||
|
|
@ -2768,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",
|
||||
|
|
@ -2930,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;
|
||||
|
|
|
|||
|
|
@ -21,13 +21,54 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/platform_data/b53.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include "b53_priv.h"
|
||||
|
||||
#define BCM63XX_EPHY_REG 0x3C
|
||||
|
||||
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;
|
||||
u32 phys_enabled;
|
||||
};
|
||||
|
||||
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 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 = {
|
||||
.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)
|
||||
|
|
@ -229,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,
|
||||
|
|
@ -242,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,
|
||||
|
|
@ -313,6 +400,18 @@ 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 == 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 == BCM6368_DEVICE_ID)
|
||||
priv->phy_info = &bcm6368_ephy_info;
|
||||
else 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;
|
||||
|
|
@ -348,16 +447,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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
@ -71,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,
|
||||
|
|
@ -218,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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user