diff --git a/drivers/net/dsa/microchip/ksz8795.c b/drivers/net/dsa/microchip/ksz8795.c index 0df2140b7ccc..30052dc5b9a1 100644 --- a/drivers/net/dsa/microchip/ksz8795.c +++ b/drivers/net/dsa/microchip/ksz8795.c @@ -1368,10 +1368,25 @@ static int ksz8_handle_global_errata(struct dsa_switch *ds) return ret; } +static int ksz8_enable_stp_addr(struct ksz_device *dev) +{ + struct alu_struct alu; + + /* Setup STP address for STP operation. */ + memset(&alu, 0, sizeof(alu)); + ether_addr_copy(alu.mac, eth_stp_addr); + alu.is_static = true; + alu.is_override = true; + alu.port_forward = dev->info->cpu_ports; + + ksz8_w_sta_mac_table(dev, 0, &alu); + + return 0; +} + static int ksz8_setup(struct dsa_switch *ds) { struct ksz_device *dev = ds->priv; - struct alu_struct alu; int i, ret = 0; dev->vlan_cache = devm_kcalloc(dev->dev, sizeof(struct vlan_table), @@ -1422,14 +1437,7 @@ static int ksz8_setup(struct dsa_switch *ds) for (i = 0; i < (dev->info->num_vlans / 4); i++) ksz8_r_vlan_entries(dev, i); - /* Setup STP address for STP operation. */ - memset(&alu, 0, sizeof(alu)); - ether_addr_copy(alu.mac, eth_stp_addr); - alu.is_static = true; - alu.is_override = true; - alu.port_forward = dev->info->cpu_ports; - - ksz8_w_sta_mac_table(dev, 0, &alu); + dev->dev_ops->enable_stp_addr(dev); ksz_init_mib_timer(dev); @@ -1546,6 +1554,7 @@ static const struct ksz_dev_ops ksz8_dev_ops = { .mirror_del = ksz8_port_mirror_del, .get_caps = ksz8_get_caps, .config_cpu_port = ksz8_config_cpu_port, + .enable_stp_addr = ksz8_enable_stp_addr, .reset = ksz8_reset_switch, .init = ksz8_switch_init, .exit = ksz8_switch_exit, diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c index fef8142440cf..6ca0d5753df0 100644 --- a/drivers/net/dsa/microchip/ksz9477.c +++ b/drivers/net/dsa/microchip/ksz9477.c @@ -1236,6 +1236,36 @@ static void ksz9477_config_cpu_port(struct dsa_switch *ds) } } +static int ksz9477_enable_stp_addr(struct ksz_device *dev) +{ + u32 data; + int ret; + + /* Enable Reserved multicast table */ + ksz_cfg(dev, REG_SW_LUE_CTRL_0, SW_RESV_MCAST_ENABLE, true); + + /* Set the Override bit for forwarding BPDU packet to CPU */ + ret = ksz_write32(dev, REG_SW_ALU_VAL_B, + ALU_V_OVERRIDE | BIT(dev->cpu_port)); + if (ret < 0) + return ret; + + data = ALU_STAT_START | ALU_RESV_MCAST_ADDR; + + ret = ksz_write32(dev, REG_SW_ALU_STAT_CTRL__4, data); + if (ret < 0) + return ret; + + /* wait to be finished */ + ret = ksz9477_wait_alu_sta_ready(dev); + if (ret < 0) { + dev_err(dev->dev, "Failed to update Reserved Multicast table\n"); + return ret; + } + + return 0; +} + static int ksz9477_setup(struct dsa_switch *ds) { struct ksz_device *dev = ds->priv; @@ -1281,6 +1311,8 @@ static int ksz9477_setup(struct dsa_switch *ds) /* start switch */ ksz_cfg(dev, REG_SW_OPERATION, SW_START, true); + dev->dev_ops->enable_stp_addr(dev); + ksz_init_mib_timer(dev); ds->configure_vlan_while_not_filtering = false; @@ -1401,6 +1433,7 @@ static const struct ksz_dev_ops ksz9477_dev_ops = { .change_mtu = ksz9477_change_mtu, .max_mtu = ksz9477_max_mtu, .config_cpu_port = ksz9477_config_cpu_port, + .enable_stp_addr = ksz9477_enable_stp_addr, .reset = ksz9477_reset_switch, .init = ksz9477_switch_init, .exit = ksz9477_switch_exit, diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h index d5b53b5b7b51..e38bdf1f5b41 100644 --- a/drivers/net/dsa/microchip/ksz_common.h +++ b/drivers/net/dsa/microchip/ksz_common.h @@ -205,6 +205,7 @@ struct ksz_dev_ops { void (*freeze_mib)(struct ksz_device *dev, int port, bool freeze); void (*port_init_cnt)(struct ksz_device *dev, int port); void (*config_cpu_port)(struct dsa_switch *ds); + int (*enable_stp_addr)(struct ksz_device *dev); int (*reset)(struct ksz_device *dev); int (*init)(struct ksz_device *dev); void (*exit)(struct ksz_device *dev);