diff options
Diffstat (limited to 'drivers/net/dsa/b53')
-rw-r--r-- | drivers/net/dsa/b53/b53_common.c | 109 | ||||
-rw-r--r-- | drivers/net/dsa/b53/b53_mdio.c | 5 | ||||
-rw-r--r-- | drivers/net/dsa/b53/b53_priv.h | 9 | ||||
-rw-r--r-- | drivers/net/dsa/b53/b53_srab.c | 4 |
4 files changed, 113 insertions, 14 deletions
diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c index 78616787f2a3..5e010b1592f7 100644 --- a/drivers/net/dsa/b53/b53_common.c +++ b/drivers/net/dsa/b53/b53_common.c @@ -684,7 +684,8 @@ static int b53_switch_reset(struct b53_device *dev) * still use this driver as a library and need to perform the reset * earlier. */ - if (dev->chip_id == BCM58XX_DEVICE_ID) { + if (dev->chip_id == BCM58XX_DEVICE_ID || + dev->chip_id == BCM583XX_DEVICE_ID) { b53_read8(dev, B53_CTRL_PAGE, B53_SOFTRESET, ®); reg |= SW_RST | EN_SW_RST | EN_CH_RST; b53_write8(dev, B53_CTRL_PAGE, B53_SOFTRESET, reg); @@ -806,16 +807,39 @@ static unsigned int b53_get_mib_size(struct b53_device *dev) return B53_MIBS_SIZE; } -void b53_get_strings(struct dsa_switch *ds, int port, uint8_t *data) +static struct phy_device *b53_get_phy_device(struct dsa_switch *ds, int port) +{ + /* These ports typically do not have built-in PHYs */ + switch (port) { + case B53_CPU_PORT_25: + case 7: + case B53_CPU_PORT: + return NULL; + } + + return mdiobus_get_phy(ds->slave_mii_bus, port); +} + +void b53_get_strings(struct dsa_switch *ds, int port, u32 stringset, + uint8_t *data) { struct b53_device *dev = ds->priv; const struct b53_mib_desc *mibs = b53_get_mib(dev); unsigned int mib_size = b53_get_mib_size(dev); + struct phy_device *phydev; unsigned int i; - for (i = 0; i < mib_size; i++) - strlcpy(data + i * ETH_GSTRING_LEN, - mibs[i].name, ETH_GSTRING_LEN); + if (stringset == ETH_SS_STATS) { + for (i = 0; i < mib_size; i++) + strlcpy(data + i * ETH_GSTRING_LEN, + mibs[i].name, ETH_GSTRING_LEN); + } else if (stringset == ETH_SS_PHY_STATS) { + phydev = b53_get_phy_device(ds, port); + if (!phydev) + return; + + phy_ethtool_get_strings(phydev, data); + } } EXPORT_SYMBOL(b53_get_strings); @@ -852,11 +876,34 @@ void b53_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data) } EXPORT_SYMBOL(b53_get_ethtool_stats); -int b53_get_sset_count(struct dsa_switch *ds, int port) +void b53_get_ethtool_phy_stats(struct dsa_switch *ds, int port, uint64_t *data) +{ + struct phy_device *phydev; + + phydev = b53_get_phy_device(ds, port); + if (!phydev) + return; + + phy_ethtool_get_stats(phydev, NULL, data); +} +EXPORT_SYMBOL(b53_get_ethtool_phy_stats); + +int b53_get_sset_count(struct dsa_switch *ds, int port, int sset) { struct b53_device *dev = ds->priv; + struct phy_device *phydev; + + if (sset == ETH_SS_STATS) { + return b53_get_mib_size(dev); + } else if (sset == ETH_SS_PHY_STATS) { + phydev = b53_get_phy_device(ds, port); + if (!phydev) + return 0; - return b53_get_mib_size(dev); + return phy_ethtool_get_sset_count(phydev); + } + + return 0; } EXPORT_SYMBOL(b53_get_sset_count); @@ -1477,7 +1524,7 @@ void b53_br_fast_age(struct dsa_switch *ds, int port) } EXPORT_SYMBOL(b53_br_fast_age); -static bool b53_can_enable_brcm_tags(struct dsa_switch *ds, int port) +static bool b53_possible_cpu_port(struct dsa_switch *ds, int port) { /* Broadcom switches will accept enabling Broadcom tags on the * following ports: 5, 7 and 8, any other port is not supported @@ -1489,10 +1536,19 @@ static bool b53_can_enable_brcm_tags(struct dsa_switch *ds, int port) return true; } - dev_warn(ds->dev, "Port %d is not Broadcom tag capable\n", port); return false; } +static bool b53_can_enable_brcm_tags(struct dsa_switch *ds, int port) +{ + bool ret = b53_possible_cpu_port(ds, port); + + if (!ret) + dev_warn(ds->dev, "Port %d is not Broadcom tag capable\n", + port); + return ret; +} + enum dsa_tag_protocol b53_get_tag_protocol(struct dsa_switch *ds, int port) { struct b53_device *dev = ds->priv; @@ -1650,6 +1706,7 @@ static const struct dsa_switch_ops b53_switch_ops = { .get_strings = b53_get_strings, .get_ethtool_stats = b53_get_ethtool_stats, .get_sset_count = b53_get_sset_count, + .get_ethtool_phy_stats = b53_get_ethtool_phy_stats, .phy_read = b53_phy_read16, .phy_write = b53_phy_write16, .adjust_link = b53_adjust_link, @@ -1712,6 +1769,18 @@ static const struct b53_chip_data b53_switch_chips[] = { .duplex_reg = B53_DUPLEX_STAT_FE, }, { + .chip_id = BCM5389_DEVICE_ID, + .dev_name = "BCM5389", + .vlans = 4096, + .enabled_ports = 0x1f, + .arl_entries = 4, + .cpu_port = B53_CPU_PORT, + .vta_regs = B53_VTA_REGS, + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, + .jumbo_size_reg = B53_JUMBO_MAX_SIZE, + }, + { .chip_id = BCM5395_DEVICE_ID, .dev_name = "BCM5395", .vlans = 4096, @@ -1868,6 +1937,18 @@ static const struct b53_chip_data b53_switch_chips[] = { .jumbo_size_reg = B53_JUMBO_MAX_SIZE, }, { + .chip_id = BCM583XX_DEVICE_ID, + .dev_name = "BCM583xx/11360", + .vlans = 4096, + .enabled_ports = 0x103, + .arl_entries = 4, + .cpu_port = B53_CPU_PORT, + .vta_regs = B53_VTA_REGS, + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, + .jumbo_size_reg = B53_JUMBO_MAX_SIZE, + }, + { .chip_id = BCM7445_DEVICE_ID, .dev_name = "BCM7445", .vlans = 4096, @@ -1954,6 +2035,15 @@ static int b53_switch_init(struct b53_device *dev) dev->num_ports = dev->cpu_port + 1; dev->enabled_ports |= BIT(dev->cpu_port); + /* Include non standard CPU port built-in PHYs to be probed */ + if (is539x(dev) || is531x5(dev)) { + for (i = 0; i < dev->num_ports; i++) { + if (!(dev->ds->phys_mii_mask & BIT(i)) && + !b53_possible_cpu_port(dev->ds, i)) + dev->ds->phys_mii_mask |= BIT(i); + } + } + dev->ports = devm_kzalloc(dev->dev, sizeof(struct b53_port) * dev->num_ports, GFP_KERNEL); @@ -2034,6 +2124,7 @@ int b53_switch_detect(struct b53_device *dev) else dev->chip_id = BCM5365_DEVICE_ID; break; + case BCM5389_DEVICE_ID: case BCM5395_DEVICE_ID: case BCM5397_DEVICE_ID: case BCM5398_DEVICE_ID: diff --git a/drivers/net/dsa/b53/b53_mdio.c b/drivers/net/dsa/b53/b53_mdio.c index fa7556f5d4fb..a533a90e3904 100644 --- a/drivers/net/dsa/b53/b53_mdio.c +++ b/drivers/net/dsa/b53/b53_mdio.c @@ -285,6 +285,7 @@ static const struct b53_io_ops b53_mdio_ops = { #define B53_BRCM_OUI_1 0x0143bc00 #define B53_BRCM_OUI_2 0x03625c00 #define B53_BRCM_OUI_3 0x00406000 +#define B53_BRCM_OUI_4 0x01410c00 static int b53_mdio_probe(struct mdio_device *mdiodev) { @@ -311,7 +312,8 @@ static int b53_mdio_probe(struct mdio_device *mdiodev) */ if ((phy_id & 0xfffffc00) != B53_BRCM_OUI_1 && (phy_id & 0xfffffc00) != B53_BRCM_OUI_2 && - (phy_id & 0xfffffc00) != B53_BRCM_OUI_3) { + (phy_id & 0xfffffc00) != B53_BRCM_OUI_3 && + (phy_id & 0xfffffc00) != B53_BRCM_OUI_4) { dev_err(&mdiodev->dev, "Unsupported device: 0x%08x\n", phy_id); return -ENODEV; } @@ -360,6 +362,7 @@ static const struct of_device_id b53_of_match[] = { { .compatible = "brcm,bcm53125" }, { .compatible = "brcm,bcm53128" }, { .compatible = "brcm,bcm5365" }, + { .compatible = "brcm,bcm5389" }, { .compatible = "brcm,bcm5395" }, { .compatible = "brcm,bcm5397" }, { .compatible = "brcm,bcm5398" }, diff --git a/drivers/net/dsa/b53/b53_priv.h b/drivers/net/dsa/b53/b53_priv.h index 1187ebd79287..df149756c282 100644 --- a/drivers/net/dsa/b53/b53_priv.h +++ b/drivers/net/dsa/b53/b53_priv.h @@ -48,6 +48,7 @@ struct b53_io_ops { enum { BCM5325_DEVICE_ID = 0x25, BCM5365_DEVICE_ID = 0x65, + BCM5389_DEVICE_ID = 0x89, BCM5395_DEVICE_ID = 0x95, BCM5397_DEVICE_ID = 0x97, BCM5398_DEVICE_ID = 0x98, @@ -61,6 +62,7 @@ enum { BCM53018_DEVICE_ID = 0x53018, BCM53019_DEVICE_ID = 0x53019, BCM58XX_DEVICE_ID = 0x5800, + BCM583XX_DEVICE_ID = 0x58300, BCM7445_DEVICE_ID = 0x7445, BCM7278_DEVICE_ID = 0x7278, }; @@ -180,6 +182,7 @@ static inline int is5301x(struct b53_device *dev) static inline int is58xx(struct b53_device *dev) { return dev->chip_id == BCM58XX_DEVICE_ID || + dev->chip_id == BCM583XX_DEVICE_ID || dev->chip_id == BCM7445_DEVICE_ID || dev->chip_id == BCM7278_DEVICE_ID; } @@ -286,9 +289,11 @@ static inline int b53_switch_get_reset_gpio(struct b53_device *dev) /* Exported functions towards other drivers */ void b53_imp_vlan_setup(struct dsa_switch *ds, int cpu_port); int b53_configure_vlan(struct dsa_switch *ds); -void b53_get_strings(struct dsa_switch *ds, int port, uint8_t *data); +void b53_get_strings(struct dsa_switch *ds, int port, u32 stringset, + uint8_t *data); void b53_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data); -int b53_get_sset_count(struct dsa_switch *ds, int port); +int b53_get_sset_count(struct dsa_switch *ds, int port, int sset); +void b53_get_ethtool_phy_stats(struct dsa_switch *ds, int port, uint64_t *data); int b53_br_join(struct dsa_switch *ds, int port, struct net_device *bridge); void b53_br_leave(struct dsa_switch *ds, int port, struct net_device *bridge); void b53_br_set_stp_state(struct dsa_switch *ds, int port, u8 state); diff --git a/drivers/net/dsa/b53/b53_srab.c b/drivers/net/dsa/b53/b53_srab.c index c37ffd1b6833..8247481eaa06 100644 --- a/drivers/net/dsa/b53/b53_srab.c +++ b/drivers/net/dsa/b53/b53_srab.c @@ -364,7 +364,7 @@ static const struct of_device_id b53_srab_of_match[] = { { .compatible = "brcm,bcm53018-srab" }, { .compatible = "brcm,bcm53019-srab" }, { .compatible = "brcm,bcm5301x-srab" }, - { .compatible = "brcm,bcm11360-srab", .data = (void *)BCM58XX_DEVICE_ID }, + { .compatible = "brcm,bcm11360-srab", .data = (void *)BCM583XX_DEVICE_ID }, { .compatible = "brcm,bcm58522-srab", .data = (void *)BCM58XX_DEVICE_ID }, { .compatible = "brcm,bcm58525-srab", .data = (void *)BCM58XX_DEVICE_ID }, { .compatible = "brcm,bcm58535-srab", .data = (void *)BCM58XX_DEVICE_ID }, @@ -372,7 +372,7 @@ static const struct of_device_id b53_srab_of_match[] = { { .compatible = "brcm,bcm58623-srab", .data = (void *)BCM58XX_DEVICE_ID }, { .compatible = "brcm,bcm58625-srab", .data = (void *)BCM58XX_DEVICE_ID }, { .compatible = "brcm,bcm88312-srab", .data = (void *)BCM58XX_DEVICE_ID }, - { .compatible = "brcm,cygnus-srab", .data = (void *)BCM58XX_DEVICE_ID }, + { .compatible = "brcm,cygnus-srab", .data = (void *)BCM583XX_DEVICE_ID }, { .compatible = "brcm,nsp-srab", .data = (void *)BCM58XX_DEVICE_ID }, { /* sentinel */ }, }; |