Lines Matching +full:int +full:- +full:fwd +full:- +full:mask

1 // SPDX-License-Identifier: GPL-2.0
45 unsigned int offset;
47 int stats64_offset;
50 #define XRS700X_MIB_ETHTOOL_ONLY(o, n) {o, n, -1}
86 static void xrs700x_get_strings(struct dsa_switch *ds, int port, in xrs700x_get_strings()
89 int i; in xrs700x_get_strings()
98 static int xrs700x_get_sset_count(struct dsa_switch *ds, int port, int sset) in xrs700x_get_sset_count()
101 return -EOPNOTSUPP; in xrs700x_get_sset_count()
106 static void xrs700x_read_port_counters(struct xrs700x *priv, int port) in xrs700x_read_port_counters()
108 struct xrs700x_port *p = &priv->ports[port]; in xrs700x_read_port_counters()
111 int i; in xrs700x_read_port_counters()
115 mutex_lock(&p->mib_mutex); in xrs700x_read_port_counters()
118 regmap_write(priv->regmap, XRS_CNT_CTRL(port), 1); in xrs700x_read_port_counters()
121 unsigned int high = 0, low = 0, reg; in xrs700x_read_port_counters()
124 regmap_read(priv->regmap, reg, &low); in xrs700x_read_port_counters()
125 regmap_read(priv->regmap, reg + 2, &high); in xrs700x_read_port_counters()
127 p->mib_data[i] += (high << 16) | low; in xrs700x_read_port_counters()
131 *(u64 *)s += p->mib_data[i]; in xrs700x_read_port_counters()
140 flags = u64_stats_update_begin_irqsave(&p->syncp); in xrs700x_read_port_counters()
141 p->stats64 = stats; in xrs700x_read_port_counters()
142 u64_stats_update_end_irqrestore(&p->syncp, flags); in xrs700x_read_port_counters()
144 mutex_unlock(&p->mib_mutex); in xrs700x_read_port_counters()
151 int i; in xrs700x_mib_work()
153 for (i = 0; i < priv->ds->num_ports; i++) in xrs700x_mib_work()
156 schedule_delayed_work(&priv->mib_work, XRS700X_MIB_INTERVAL); in xrs700x_mib_work()
159 static void xrs700x_get_ethtool_stats(struct dsa_switch *ds, int port, in xrs700x_get_ethtool_stats()
162 struct xrs700x *priv = ds->priv; in xrs700x_get_ethtool_stats()
163 struct xrs700x_port *p = &priv->ports[port]; in xrs700x_get_ethtool_stats()
167 mutex_lock(&p->mib_mutex); in xrs700x_get_ethtool_stats()
168 memcpy(data, p->mib_data, sizeof(*data) * ARRAY_SIZE(xrs700x_mibs)); in xrs700x_get_ethtool_stats()
169 mutex_unlock(&p->mib_mutex); in xrs700x_get_ethtool_stats()
172 static void xrs700x_get_stats64(struct dsa_switch *ds, int port, in xrs700x_get_stats64()
175 struct xrs700x *priv = ds->priv; in xrs700x_get_stats64()
176 struct xrs700x_port *p = &priv->ports[port]; in xrs700x_get_stats64()
177 unsigned int start; in xrs700x_get_stats64()
180 start = u64_stats_fetch_begin(&p->syncp); in xrs700x_get_stats64()
181 *s = p->stats64; in xrs700x_get_stats64()
182 } while (u64_stats_fetch_retry(&p->syncp, start)); in xrs700x_get_stats64()
185 static int xrs700x_setup_regmap_range(struct xrs700x *priv) in xrs700x_setup_regmap_range()
190 priv->ds->num_ports, in xrs700x_setup_regmap_range()
192 .rmf = &priv->ps_forward in xrs700x_setup_regmap_range()
196 priv->ds->num_ports, in xrs700x_setup_regmap_range()
198 .rmf = &priv->ps_management in xrs700x_setup_regmap_range()
202 priv->ds->num_ports, in xrs700x_setup_regmap_range()
204 .rmf = &priv->ps_sel_speed in xrs700x_setup_regmap_range()
208 priv->ds->num_ports, in xrs700x_setup_regmap_range()
210 .rmf = &priv->ps_cur_speed in xrs700x_setup_regmap_range()
213 int i = 0; in xrs700x_setup_regmap_range()
216 *regfields[i].rmf = devm_regmap_field_alloc(priv->dev, in xrs700x_setup_regmap_range()
217 priv->regmap, in xrs700x_setup_regmap_range()
227 int port, in xrs700x_get_tag_protocol()
233 static int xrs700x_reset(struct dsa_switch *ds) in xrs700x_reset()
235 struct xrs700x *priv = ds->priv; in xrs700x_reset()
236 unsigned int val; in xrs700x_reset()
237 int ret; in xrs700x_reset()
239 ret = regmap_write(priv->regmap, XRS_GENERAL, XRS_GENERAL_RESET); in xrs700x_reset()
243 ret = regmap_read_poll_timeout(priv->regmap, XRS_GENERAL, in xrs700x_reset()
248 dev_err_ratelimited(priv->dev, "error resetting switch: %d\n", in xrs700x_reset()
255 static void xrs700x_port_stp_state_set(struct dsa_switch *ds, int port, in xrs700x_port_stp_state_set()
258 struct xrs700x *priv = ds->priv; in xrs700x_port_stp_state_set()
259 unsigned int bpdus = 1; in xrs700x_port_stp_state_set()
260 unsigned int val; in xrs700x_port_stp_state_set()
277 dev_err(ds->dev, "invalid STP state: %d\n", state); in xrs700x_port_stp_state_set()
281 regmap_fields_write(priv->ps_forward, port, val); in xrs700x_port_stp_state_set()
287 regmap_update_bits(priv->regmap, XRS_ETH_ADDR_CFG(port, 0), 1, bpdus); in xrs700x_port_stp_state_set()
289 dev_dbg_ratelimited(priv->dev, "%s - port: %d, state: %u, val: 0x%x\n", in xrs700x_port_stp_state_set()
297 static int xrs700x_port_add_bpdu_ipf(struct dsa_switch *ds, int port) in xrs700x_port_add_bpdu_ipf()
299 struct xrs700x *priv = ds->priv; in xrs700x_port_add_bpdu_ipf()
300 unsigned int val = 0; in xrs700x_port_add_bpdu_ipf()
301 int i = 0; in xrs700x_port_add_bpdu_ipf()
302 int ret; in xrs700x_port_add_bpdu_ipf()
305 ret = regmap_write(priv->regmap, XRS_ETH_ADDR_CFG(port, 0), 48 << 2); in xrs700x_port_add_bpdu_ipf()
311 ret = regmap_write(priv->regmap, XRS_ETH_ADDR_0(port, 0) + i, in xrs700x_port_add_bpdu_ipf()
319 for (i = 0; i < ds->num_ports; i++) { in xrs700x_port_add_bpdu_ipf()
324 ret = regmap_write(priv->regmap, XRS_ETH_ADDR_FWD_MIRROR(port, 0), val); in xrs700x_port_add_bpdu_ipf()
328 ret = regmap_write(priv->regmap, XRS_ETH_ADDR_FWD_ALLOW(port, 0), 0); in xrs700x_port_add_bpdu_ipf()
340 static int xrs700x_port_add_hsrsup_ipf(struct dsa_switch *ds, int port, in xrs700x_port_add_hsrsup_ipf()
341 int fwdport) in xrs700x_port_add_hsrsup_ipf()
343 struct xrs700x *priv = ds->priv; in xrs700x_port_add_hsrsup_ipf()
344 unsigned int val = 0; in xrs700x_port_add_hsrsup_ipf()
345 int i = 0; in xrs700x_port_add_hsrsup_ipf()
346 int ret; in xrs700x_port_add_hsrsup_ipf()
349 ret = regmap_write(priv->regmap, XRS_ETH_ADDR_CFG(port, 1), 40 << 2); in xrs700x_port_add_hsrsup_ipf()
355 ret = regmap_write(priv->regmap, XRS_ETH_ADDR_0(port, 1) + i, in xrs700x_port_add_hsrsup_ipf()
363 for (i = 0; i < ds->num_ports; i++) { in xrs700x_port_add_hsrsup_ipf()
368 ret = regmap_write(priv->regmap, XRS_ETH_ADDR_FWD_MIRROR(port, 1), val); in xrs700x_port_add_hsrsup_ipf()
376 ret = regmap_write(priv->regmap, XRS_ETH_ADDR_FWD_ALLOW(port, 1), val); in xrs700x_port_add_hsrsup_ipf()
383 static int xrs700x_port_setup(struct dsa_switch *ds, int port) in xrs700x_port_setup()
386 struct xrs700x *priv = ds->priv; in xrs700x_port_setup()
387 unsigned int val = 0; in xrs700x_port_setup()
388 int ret, i; in xrs700x_port_setup()
392 /* Disable forwarding to non-CPU ports */ in xrs700x_port_setup()
393 for (i = 0; i < ds->num_ports; i++) { in xrs700x_port_setup()
399 ret = regmap_write(priv->regmap, XRS_PORT_FWD_MASK(port), val); in xrs700x_port_setup()
404 ret = regmap_fields_write(priv->ps_management, port, val); in xrs700x_port_setup()
417 static int xrs700x_setup(struct dsa_switch *ds) in xrs700x_setup()
419 struct xrs700x *priv = ds->priv; in xrs700x_setup()
420 int ret, i; in xrs700x_setup()
426 for (i = 0; i < ds->num_ports; i++) { in xrs700x_setup()
432 schedule_delayed_work(&priv->mib_work, XRS700X_MIB_INTERVAL); in xrs700x_setup()
439 struct xrs700x *priv = ds->priv; in xrs700x_teardown()
441 cancel_delayed_work_sync(&priv->mib_work); in xrs700x_teardown()
444 static void xrs700x_phylink_get_caps(struct dsa_switch *ds, int port, in xrs700x_phylink_get_caps()
450 config->supported_interfaces); in xrs700x_phylink_get_caps()
451 config->mac_capabilities = MAC_10FD | MAC_100FD; in xrs700x_phylink_get_caps()
457 phy_interface_set_rgmii(config->supported_interfaces); in xrs700x_phylink_get_caps()
458 config->mac_capabilities = MAC_10FD | MAC_100FD | MAC_1000FD; in xrs700x_phylink_get_caps()
462 dev_err(ds->dev, "Unsupported port: %i\n", port); in xrs700x_phylink_get_caps()
467 static void xrs700x_mac_config(struct phylink_config *config, unsigned int mode, in xrs700x_mac_config()
473 unsigned int mode, phy_interface_t interface) in xrs700x_mac_link_down()
479 unsigned int mode, phy_interface_t interface, in xrs700x_mac_link_up()
480 int speed, int duplex, in xrs700x_mac_link_up()
484 struct xrs700x *priv = dp->ds->priv; in xrs700x_mac_link_up()
485 int port = dp->index; in xrs700x_mac_link_up()
486 unsigned int val; in xrs700x_mac_link_up()
502 regmap_fields_write(priv->ps_sel_speed, port, val); in xrs700x_mac_link_up()
504 dev_dbg_ratelimited(priv->dev, "%s: port: %d mode: %u speed: %u\n", in xrs700x_mac_link_up()
508 static int xrs700x_bridge_common(struct dsa_switch *ds, int port, in xrs700x_bridge_common()
511 unsigned int i, cpu_mask = 0, mask = 0; in xrs700x_bridge_common() local
512 struct xrs700x *priv = ds->priv; in xrs700x_bridge_common()
513 int ret; in xrs700x_bridge_common()
515 for (i = 0; i < ds->num_ports; i++) { in xrs700x_bridge_common()
524 mask |= BIT(i); in xrs700x_bridge_common()
527 for (i = 0; i < ds->num_ports; i++) { in xrs700x_bridge_common()
532 ret = regmap_write(priv->regmap, XRS_PORT_FWD_MASK(i), mask); in xrs700x_bridge_common()
538 ret = regmap_write(priv->regmap, XRS_PORT_FWD_MASK(port), in xrs700x_bridge_common()
547 static int xrs700x_bridge_join(struct dsa_switch *ds, int port, in xrs700x_bridge_join()
554 static void xrs700x_bridge_leave(struct dsa_switch *ds, int port, in xrs700x_bridge_leave()
560 static int xrs700x_hsr_join(struct dsa_switch *ds, int port, in xrs700x_hsr_join()
564 unsigned int val = XRS_HSR_CFG_HSR_PRP; in xrs700x_hsr_join()
566 struct xrs700x *priv = ds->priv; in xrs700x_hsr_join()
568 int ret, i, hsr_pair[2]; in xrs700x_hsr_join()
570 bool fwd = false; in xrs700x_hsr_join() local
579 return -EOPNOTSUPP; in xrs700x_hsr_join()
589 return -EOPNOTSUPP; in xrs700x_hsr_join()
593 if (dp->index != port) { in xrs700x_hsr_join()
605 regmap_fields_write(priv->ps_forward, partner->index, in xrs700x_hsr_join()
607 regmap_fields_write(priv->ps_forward, port, XRS_PORT_DISABLED); in xrs700x_hsr_join()
609 regmap_write(priv->regmap, XRS_HSR_CFG(partner->index), in xrs700x_hsr_join()
611 regmap_write(priv->regmap, XRS_HSR_CFG(port), in xrs700x_hsr_join()
617 val = GENMASK(ds->num_ports - 1, 0); in xrs700x_hsr_join()
619 val &= ~BIT(partner->index); in xrs700x_hsr_join()
621 fwd = true; in xrs700x_hsr_join()
624 regmap_write(priv->regmap, XRS_PORT_FWD_MASK(partner->index), val); in xrs700x_hsr_join()
625 regmap_write(priv->regmap, XRS_PORT_FWD_MASK(port), val); in xrs700x_hsr_join()
627 regmap_fields_write(priv->ps_forward, partner->index, in xrs700x_hsr_join()
629 regmap_fields_write(priv->ps_forward, port, XRS_PORT_FORWARDING); in xrs700x_hsr_join()
636 ret = xrs700x_port_add_hsrsup_ipf(ds, partner->index, fwd ? port : -1); in xrs700x_hsr_join()
640 ret = xrs700x_port_add_hsrsup_ipf(ds, port, fwd ? partner->index : -1); in xrs700x_hsr_join()
644 regmap_update_bits(priv->regmap, in xrs700x_hsr_join()
645 XRS_ETH_ADDR_CFG(partner->index, 1), 1, 1); in xrs700x_hsr_join()
646 regmap_update_bits(priv->regmap, XRS_ETH_ADDR_CFG(port, 1), 1, 1); in xrs700x_hsr_join()
649 hsr_pair[1] = partner->index; in xrs700x_hsr_join()
651 user = dsa_to_port(ds, hsr_pair[i])->user; in xrs700x_hsr_join()
652 user->features |= XRS7000X_SUPPORTED_HSR_FEATURES; in xrs700x_hsr_join()
658 static int xrs700x_hsr_leave(struct dsa_switch *ds, int port, in xrs700x_hsr_leave()
662 struct xrs700x *priv = ds->priv; in xrs700x_hsr_leave()
664 int i, hsr_pair[2]; in xrs700x_hsr_leave()
665 unsigned int val; in xrs700x_hsr_leave()
668 if (dp->index != port) { in xrs700x_hsr_leave()
677 regmap_fields_write(priv->ps_forward, partner->index, in xrs700x_hsr_leave()
679 regmap_fields_write(priv->ps_forward, port, XRS_PORT_DISABLED); in xrs700x_hsr_leave()
681 regmap_write(priv->regmap, XRS_HSR_CFG(partner->index), 0); in xrs700x_hsr_leave()
682 regmap_write(priv->regmap, XRS_HSR_CFG(port), 0); in xrs700x_hsr_leave()
685 val = GENMASK(ds->num_ports - 1, 0); in xrs700x_hsr_leave()
687 regmap_write(priv->regmap, XRS_PORT_FWD_MASK(partner->index), val); in xrs700x_hsr_leave()
688 regmap_write(priv->regmap, XRS_PORT_FWD_MASK(port), val); in xrs700x_hsr_leave()
690 regmap_fields_write(priv->ps_forward, partner->index, in xrs700x_hsr_leave()
692 regmap_fields_write(priv->ps_forward, port, XRS_PORT_FORWARDING); in xrs700x_hsr_leave()
698 regmap_update_bits(priv->regmap, in xrs700x_hsr_leave()
699 XRS_ETH_ADDR_CFG(partner->index, 1), 1, 0); in xrs700x_hsr_leave()
700 regmap_update_bits(priv->regmap, XRS_ETH_ADDR_CFG(port, 1), 1, 0); in xrs700x_hsr_leave()
703 hsr_pair[1] = partner->index; in xrs700x_hsr_leave()
705 user = dsa_to_port(ds, hsr_pair[i])->user; in xrs700x_hsr_leave()
706 user->features &= ~XRS7000X_SUPPORTED_HSR_FEATURES; in xrs700x_hsr_leave()
734 static int xrs700x_detect(struct xrs700x *priv) in xrs700x_detect()
737 unsigned int id; in xrs700x_detect()
738 int ret; in xrs700x_detect()
740 ret = regmap_read(priv->regmap, XRS_DEV_ID0, &id); in xrs700x_detect()
742 dev_err(priv->dev, "error %d while reading switch id.\n", in xrs700x_detect()
747 info = of_device_get_match_data(priv->dev); in xrs700x_detect()
749 return -EINVAL; in xrs700x_detect()
751 if (info->id == id) { in xrs700x_detect()
752 priv->ds->num_ports = info->num_ports; in xrs700x_detect()
753 dev_info(priv->dev, "%s detected.\n", info->name); in xrs700x_detect()
757 dev_err(priv->dev, "expected switch id 0x%x but found 0x%x.\n", in xrs700x_detect()
758 info->id, id); in xrs700x_detect()
760 return -ENODEV; in xrs700x_detect()
772 ds->dev = base; in xrs700x_switch_alloc()
778 INIT_DELAYED_WORK(&priv->mib_work, xrs700x_mib_work); in xrs700x_switch_alloc()
780 ds->ops = &xrs700x_ops; in xrs700x_switch_alloc()
781 ds->phylink_mac_ops = &xrs700x_phylink_mac_ops; in xrs700x_switch_alloc()
782 ds->priv = priv; in xrs700x_switch_alloc()
783 priv->dev = base; in xrs700x_switch_alloc()
785 priv->ds = ds; in xrs700x_switch_alloc()
786 priv->priv = devpriv; in xrs700x_switch_alloc()
792 static int xrs700x_alloc_port_mib(struct xrs700x *priv, int port) in xrs700x_alloc_port_mib()
794 struct xrs700x_port *p = &priv->ports[port]; in xrs700x_alloc_port_mib()
796 p->mib_data = devm_kcalloc(priv->dev, ARRAY_SIZE(xrs700x_mibs), in xrs700x_alloc_port_mib()
797 sizeof(*p->mib_data), GFP_KERNEL); in xrs700x_alloc_port_mib()
798 if (!p->mib_data) in xrs700x_alloc_port_mib()
799 return -ENOMEM; in xrs700x_alloc_port_mib()
801 mutex_init(&p->mib_mutex); in xrs700x_alloc_port_mib()
802 u64_stats_init(&p->syncp); in xrs700x_alloc_port_mib()
807 int xrs700x_switch_register(struct xrs700x *priv) in xrs700x_switch_register()
809 int ret; in xrs700x_switch_register()
810 int i; in xrs700x_switch_register()
820 priv->ports = devm_kcalloc(priv->dev, priv->ds->num_ports, in xrs700x_switch_register()
821 sizeof(*priv->ports), GFP_KERNEL); in xrs700x_switch_register()
822 if (!priv->ports) in xrs700x_switch_register()
823 return -ENOMEM; in xrs700x_switch_register()
825 for (i = 0; i < priv->ds->num_ports; i++) { in xrs700x_switch_register()
831 return dsa_register_switch(priv->ds); in xrs700x_switch_register()
837 dsa_unregister_switch(priv->ds); in xrs700x_switch_remove()
843 dsa_switch_shutdown(priv->ds); in xrs700x_switch_shutdown()