felix.c (8c1c6c7588b2faf9dd45fb3cfb7497fd09bbfe7c) felix.c (2d44b097bbb9d0af0f3b94304fee4b639ab14171)
1// SPDX-License-Identifier: GPL-2.0
2/* Copyright 2019 NXP Semiconductors
3 *
4 * This is an umbrella module for all network switches that are
5 * register-compatible with Ocelot and that perform I/O to their host CPU
6 * through an NPI (Node Processor Interface) Ethernet port.
7 */
8#include <uapi/linux/if_bridge.h>

--- 5 unchanged lines hidden (view full) ---

14#include <soc/mscc/ocelot_ptp.h>
15#include <soc/mscc/ocelot.h>
16#include <linux/platform_device.h>
17#include <linux/packing.h>
18#include <linux/module.h>
19#include <linux/of_net.h>
20#include <linux/pci.h>
21#include <linux/of.h>
1// SPDX-License-Identifier: GPL-2.0
2/* Copyright 2019 NXP Semiconductors
3 *
4 * This is an umbrella module for all network switches that are
5 * register-compatible with Ocelot and that perform I/O to their host CPU
6 * through an NPI (Node Processor Interface) Ethernet port.
7 */
8#include <uapi/linux/if_bridge.h>

--- 5 unchanged lines hidden (view full) ---

14#include <soc/mscc/ocelot_ptp.h>
15#include <soc/mscc/ocelot.h>
16#include <linux/platform_device.h>
17#include <linux/packing.h>
18#include <linux/module.h>
19#include <linux/of_net.h>
20#include <linux/pci.h>
21#include <linux/of.h>
22#include <linux/pcs-lynx.h>
22#include <net/pkt_sched.h>
23#include <net/dsa.h>
24#include "felix.h"
25
26static enum dsa_tag_protocol felix_get_tag_protocol(struct dsa_switch *ds,
27 int port,
28 enum dsa_tag_protocol mp)
29{

--- 161 unchanged lines hidden (view full) ---

191{
192 struct ocelot *ocelot = ds->priv;
193 struct felix *felix = ocelot_to_felix(ocelot);
194
195 if (felix->info->phylink_validate)
196 felix->info->phylink_validate(ocelot, port, supported, state);
197}
198
23#include <net/pkt_sched.h>
24#include <net/dsa.h>
25#include "felix.h"
26
27static enum dsa_tag_protocol felix_get_tag_protocol(struct dsa_switch *ds,
28 int port,
29 enum dsa_tag_protocol mp)
30{

--- 161 unchanged lines hidden (view full) ---

192{
193 struct ocelot *ocelot = ds->priv;
194 struct felix *felix = ocelot_to_felix(ocelot);
195
196 if (felix->info->phylink_validate)
197 felix->info->phylink_validate(ocelot, port, supported, state);
198}
199
199static int felix_phylink_mac_pcs_get_state(struct dsa_switch *ds, int port,
200 struct phylink_link_state *state)
201{
202 struct ocelot *ocelot = ds->priv;
203 struct felix *felix = ocelot_to_felix(ocelot);
204
205 if (felix->info->pcs_link_state)
206 felix->info->pcs_link_state(ocelot, port, state);
207
208 return 0;
209}
210
211static void felix_phylink_mac_config(struct dsa_switch *ds, int port,
212 unsigned int link_an_mode,
213 const struct phylink_link_state *state)
214{
215 struct ocelot *ocelot = ds->priv;
216 struct felix *felix = ocelot_to_felix(ocelot);
200static void felix_phylink_mac_config(struct dsa_switch *ds, int port,
201 unsigned int link_an_mode,
202 const struct phylink_link_state *state)
203{
204 struct ocelot *ocelot = ds->priv;
205 struct felix *felix = ocelot_to_felix(ocelot);
206 struct dsa_port *dp = dsa_to_port(ds, port);
217
207
218 if (felix->info->pcs_config)
219 felix->info->pcs_config(ocelot, port, link_an_mode, state);
208 if (felix->pcs[port])
209 phylink_set_pcs(dp->pl, &felix->pcs[port]->pcs);
220}
221
222static void felix_phylink_mac_link_down(struct dsa_switch *ds, int port,
223 unsigned int link_an_mode,
224 phy_interface_t interface)
225{
226 struct ocelot *ocelot = ds->priv;
227 struct ocelot_port *ocelot_port = ocelot->ports[port];

--- 73 unchanged lines hidden (view full) ---

301 ANA_PORT_PORT_CFG_RECV_ENA |
302 ANA_PORT_PORT_CFG_PORTID_VAL(port),
303 ANA_PORT_PORT_CFG, port);
304
305 /* Core: Enable port for frame transfer */
306 ocelot_fields_write(ocelot, port,
307 QSYS_SWITCH_PORT_MODE_PORT_ENA, 1);
308
210}
211
212static void felix_phylink_mac_link_down(struct dsa_switch *ds, int port,
213 unsigned int link_an_mode,
214 phy_interface_t interface)
215{
216 struct ocelot *ocelot = ds->priv;
217 struct ocelot_port *ocelot_port = ocelot->ports[port];

--- 73 unchanged lines hidden (view full) ---

291 ANA_PORT_PORT_CFG_RECV_ENA |
292 ANA_PORT_PORT_CFG_PORTID_VAL(port),
293 ANA_PORT_PORT_CFG, port);
294
295 /* Core: Enable port for frame transfer */
296 ocelot_fields_write(ocelot, port,
297 QSYS_SWITCH_PORT_MODE_PORT_ENA, 1);
298
309 if (felix->info->pcs_link_up)
310 felix->info->pcs_link_up(ocelot, port, link_an_mode, interface,
311 speed, duplex);
312
313 if (felix->info->port_sched_speed_set)
314 felix->info->port_sched_speed_set(ocelot, port, speed);
315}
316
317static void felix_port_qos_map_init(struct ocelot *ocelot, int port)
318{
319 int i;
320

--- 127 unchanged lines hidden (view full) ---

448 ocelot->stats_layout = felix->info->stats_layout;
449 ocelot->num_stats = felix->info->num_stats;
450 ocelot->shared_queue_sz = felix->info->shared_queue_sz;
451 ocelot->num_mact_rows = felix->info->num_mact_rows;
452 ocelot->vcap_is2_keys = felix->info->vcap_is2_keys;
453 ocelot->vcap_is2_actions= felix->info->vcap_is2_actions;
454 ocelot->vcap = felix->info->vcap;
455 ocelot->ops = felix->info->ops;
299 if (felix->info->port_sched_speed_set)
300 felix->info->port_sched_speed_set(ocelot, port, speed);
301}
302
303static void felix_port_qos_map_init(struct ocelot *ocelot, int port)
304{
305 int i;
306

--- 127 unchanged lines hidden (view full) ---

434 ocelot->stats_layout = felix->info->stats_layout;
435 ocelot->num_stats = felix->info->num_stats;
436 ocelot->shared_queue_sz = felix->info->shared_queue_sz;
437 ocelot->num_mact_rows = felix->info->num_mact_rows;
438 ocelot->vcap_is2_keys = felix->info->vcap_is2_keys;
439 ocelot->vcap_is2_actions= felix->info->vcap_is2_actions;
440 ocelot->vcap = felix->info->vcap;
441 ocelot->ops = felix->info->ops;
442 ocelot->inj_prefix = OCELOT_TAG_PREFIX_NONE;
443 ocelot->xtr_prefix = OCELOT_TAG_PREFIX_LONG;
456
457 port_phy_modes = kcalloc(num_phys_ports, sizeof(phy_interface_t),
458 GFP_KERNEL);
459 if (!port_phy_modes)
460 return -ENOMEM;
461
462 err = felix_parse_dt(felix, port_phy_modes);
463 if (err) {

--- 83 unchanged lines hidden (view full) ---

547 err = felix->info->mdio_bus_alloc(ocelot);
548 if (err < 0)
549 return err;
550 }
551
552 return 0;
553}
554
444
445 port_phy_modes = kcalloc(num_phys_ports, sizeof(phy_interface_t),
446 GFP_KERNEL);
447 if (!port_phy_modes)
448 return -ENOMEM;
449
450 err = felix_parse_dt(felix, port_phy_modes);
451 if (err) {

--- 83 unchanged lines hidden (view full) ---

535 err = felix->info->mdio_bus_alloc(ocelot);
536 if (err < 0)
537 return err;
538 }
539
540 return 0;
541}
542
555static struct ptp_clock_info ocelot_ptp_clock_info = {
556 .owner = THIS_MODULE,
557 .name = "felix ptp",
558 .max_adj = 0x7fffffff,
559 .n_alarm = 0,
560 .n_ext_ts = 0,
561 .n_per_out = OCELOT_PTP_PINS_NUM,
562 .n_pins = OCELOT_PTP_PINS_NUM,
563 .pps = 0,
564 .gettime64 = ocelot_ptp_gettime64,
565 .settime64 = ocelot_ptp_settime64,
566 .adjtime = ocelot_ptp_adjtime,
567 .adjfine = ocelot_ptp_adjfine,
568 .verify = ocelot_ptp_verify,
569 .enable = ocelot_ptp_enable,
570};
543/* The CPU port module is connected to the Node Processor Interface (NPI). This
544 * is the mode through which frames can be injected from and extracted to an
545 * external CPU, over Ethernet.
546 */
547static void felix_npi_port_init(struct ocelot *ocelot, int port)
548{
549 ocelot->npi = port;
571
550
551 ocelot_write(ocelot, QSYS_EXT_CPU_CFG_EXT_CPUQ_MSK_M |
552 QSYS_EXT_CPU_CFG_EXT_CPU_PORT(port),
553 QSYS_EXT_CPU_CFG);
554
555 /* NPI port Injection/Extraction configuration */
556 ocelot_fields_write(ocelot, port, SYS_PORT_MODE_INCL_XTR_HDR,
557 ocelot->xtr_prefix);
558 ocelot_fields_write(ocelot, port, SYS_PORT_MODE_INCL_INJ_HDR,
559 ocelot->inj_prefix);
560
561 /* Disable transmission of pause frames */
562 ocelot_fields_write(ocelot, port, SYS_PAUSE_CFG_PAUSE_ENA, 0);
563}
564
572/* Hardware initialization done here so that we can allocate structures with
573 * devm without fear of dsa_register_switch returning -EPROBE_DEFER and causing
574 * us to allocate structures twice (leak memory) and map PCI memory twice
575 * (which will not work).
576 */
577static int felix_setup(struct dsa_switch *ds)
578{
579 struct ocelot *ocelot = ds->priv;

--- 5 unchanged lines hidden (view full) ---

585 if (err)
586 return err;
587
588 err = ocelot_init(ocelot);
589 if (err)
590 return err;
591
592 if (ocelot->ptp) {
565/* Hardware initialization done here so that we can allocate structures with
566 * devm without fear of dsa_register_switch returning -EPROBE_DEFER and causing
567 * us to allocate structures twice (leak memory) and map PCI memory twice
568 * (which will not work).
569 */
570static int felix_setup(struct dsa_switch *ds)
571{
572 struct ocelot *ocelot = ds->priv;

--- 5 unchanged lines hidden (view full) ---

578 if (err)
579 return err;
580
581 err = ocelot_init(ocelot);
582 if (err)
583 return err;
584
585 if (ocelot->ptp) {
593 err = ocelot_init_timestamp(ocelot, &ocelot_ptp_clock_info);
586 err = ocelot_init_timestamp(ocelot, felix->info->ptp_caps);
594 if (err) {
595 dev_err(ocelot->dev,
596 "Timestamp initialization failed\n");
597 ocelot->ptp = 0;
598 }
599 }
600
601 for (port = 0; port < ds->num_ports; port++) {
602 ocelot_init_port(ocelot, port);
603
587 if (err) {
588 dev_err(ocelot->dev,
589 "Timestamp initialization failed\n");
590 ocelot->ptp = 0;
591 }
592 }
593
594 for (port = 0; port < ds->num_ports; port++) {
595 ocelot_init_port(ocelot, port);
596
604 /* Bring up the CPU port module and configure the NPI port */
605 if (dsa_is_cpu_port(ds, port))
597 if (dsa_is_cpu_port(ds, port))
606 ocelot_configure_cpu(ocelot, port,
607 OCELOT_TAG_PREFIX_NONE,
608 OCELOT_TAG_PREFIX_LONG);
598 felix_npi_port_init(ocelot, port);
609
610 /* Set the default QoS Classification based on PCP and DEI
611 * bits of vlan tag.
612 */
613 felix_port_qos_map_init(ocelot, port);
614 }
615
616 /* Include the CPU port module in the forwarding mask for unknown

--- 8 unchanged lines hidden (view full) ---

625 for (tc = 0; tc < FELIX_NUM_TC; tc++)
626 ocelot_write_rix(ocelot, ANA_FLOODING_FLD_MULTICAST(PGID_MC) |
627 ANA_FLOODING_FLD_BROADCAST(PGID_MC) |
628 ANA_FLOODING_FLD_UNICAST(PGID_UC),
629 ANA_FLOODING, tc);
630
631 ds->mtu_enforcement_ingress = true;
632 ds->configure_vlan_while_not_filtering = true;
599
600 /* Set the default QoS Classification based on PCP and DEI
601 * bits of vlan tag.
602 */
603 felix_port_qos_map_init(ocelot, port);
604 }
605
606 /* Include the CPU port module in the forwarding mask for unknown

--- 8 unchanged lines hidden (view full) ---

615 for (tc = 0; tc < FELIX_NUM_TC; tc++)
616 ocelot_write_rix(ocelot, ANA_FLOODING_FLD_MULTICAST(PGID_MC) |
617 ANA_FLOODING_FLD_BROADCAST(PGID_MC) |
618 ANA_FLOODING_FLD_UNICAST(PGID_UC),
619 ANA_FLOODING, tc);
620
621 ds->mtu_enforcement_ingress = true;
622 ds->configure_vlan_while_not_filtering = true;
633 /* It looks like the MAC/PCS interrupt register - PM0_IEVENT (0x8040)
634 * isn't instantiated for the Felix PF.
635 * In-band AN may take a few ms to complete, so we need to poll.
636 */
637 ds->pcs_poll = true;
638
639 return 0;
640}
641
642static void felix_teardown(struct dsa_switch *ds)
643{
644 struct ocelot *ocelot = ds->priv;
645 struct felix *felix = ocelot_to_felix(ocelot);

--- 54 unchanged lines hidden (view full) ---

700}
701
702static bool felix_txtstamp(struct dsa_switch *ds, int port,
703 struct sk_buff *clone, unsigned int type)
704{
705 struct ocelot *ocelot = ds->priv;
706 struct ocelot_port *ocelot_port = ocelot->ports[port];
707
623
624 return 0;
625}
626
627static void felix_teardown(struct dsa_switch *ds)
628{
629 struct ocelot *ocelot = ds->priv;
630 struct felix *felix = ocelot_to_felix(ocelot);

--- 54 unchanged lines hidden (view full) ---

685}
686
687static bool felix_txtstamp(struct dsa_switch *ds, int port,
688 struct sk_buff *clone, unsigned int type)
689{
690 struct ocelot *ocelot = ds->priv;
691 struct ocelot_port *ocelot_port = ocelot->ports[port];
692
708 if (!ocelot_port_add_txtstamp_skb(ocelot_port, clone))
693 if (ocelot->ptp && (skb_shinfo(clone)->tx_flags & SKBTX_HW_TSTAMP) &&
694 ocelot_port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP) {
695 ocelot_port_add_txtstamp_skb(ocelot, port, clone);
709 return true;
696 return true;
697 }
710
711 return false;
712}
713
714static int felix_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
715{
716 struct ocelot *ocelot = ds->priv;
717

--- 70 unchanged lines hidden (view full) ---

788 .setup = felix_setup,
789 .teardown = felix_teardown,
790 .set_ageing_time = felix_set_ageing_time,
791 .get_strings = felix_get_strings,
792 .get_ethtool_stats = felix_get_ethtool_stats,
793 .get_sset_count = felix_get_sset_count,
794 .get_ts_info = felix_get_ts_info,
795 .phylink_validate = felix_phylink_validate,
698
699 return false;
700}
701
702static int felix_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
703{
704 struct ocelot *ocelot = ds->priv;
705

--- 70 unchanged lines hidden (view full) ---

776 .setup = felix_setup,
777 .teardown = felix_teardown,
778 .set_ageing_time = felix_set_ageing_time,
779 .get_strings = felix_get_strings,
780 .get_ethtool_stats = felix_get_ethtool_stats,
781 .get_sset_count = felix_get_sset_count,
782 .get_ts_info = felix_get_ts_info,
783 .phylink_validate = felix_phylink_validate,
796 .phylink_mac_link_state = felix_phylink_mac_pcs_get_state,
797 .phylink_mac_config = felix_phylink_mac_config,
798 .phylink_mac_link_down = felix_phylink_mac_link_down,
799 .phylink_mac_link_up = felix_phylink_mac_link_up,
800 .port_enable = felix_port_enable,
801 .port_disable = felix_port_disable,
802 .port_fdb_dump = felix_fdb_dump,
803 .port_fdb_add = felix_fdb_add,
804 .port_fdb_del = felix_fdb_del,

--- 13 unchanged lines hidden (view full) ---

818 .port_txtstamp = felix_txtstamp,
819 .port_change_mtu = felix_change_mtu,
820 .port_max_mtu = felix_get_max_mtu,
821 .port_policer_add = felix_port_policer_add,
822 .port_policer_del = felix_port_policer_del,
823 .cls_flower_add = felix_cls_flower_add,
824 .cls_flower_del = felix_cls_flower_del,
825 .cls_flower_stats = felix_cls_flower_stats,
784 .phylink_mac_config = felix_phylink_mac_config,
785 .phylink_mac_link_down = felix_phylink_mac_link_down,
786 .phylink_mac_link_up = felix_phylink_mac_link_up,
787 .port_enable = felix_port_enable,
788 .port_disable = felix_port_disable,
789 .port_fdb_dump = felix_fdb_dump,
790 .port_fdb_add = felix_fdb_add,
791 .port_fdb_del = felix_fdb_del,

--- 13 unchanged lines hidden (view full) ---

805 .port_txtstamp = felix_txtstamp,
806 .port_change_mtu = felix_change_mtu,
807 .port_max_mtu = felix_get_max_mtu,
808 .port_policer_add = felix_port_policer_add,
809 .port_policer_del = felix_port_policer_del,
810 .cls_flower_add = felix_cls_flower_add,
811 .cls_flower_del = felix_cls_flower_del,
812 .cls_flower_stats = felix_cls_flower_stats,
826 .port_setup_tc = felix_port_setup_tc,
813 .port_setup_tc = felix_port_setup_tc,
827};
814};
828
829static int __init felix_init(void)
830{
831 int err;
832
833 err = pci_register_driver(&felix_vsc9959_pci_driver);
834 if (err)
835 return err;
836
837 err = platform_driver_register(&seville_vsc9953_driver);
838 if (err)
839 return err;
840
841 return 0;
842}
843module_init(felix_init);
844
845static void __exit felix_exit(void)
846{
847 pci_unregister_driver(&felix_vsc9959_pci_driver);
848 platform_driver_unregister(&seville_vsc9953_driver);
849}
850module_exit(felix_exit);
851
852MODULE_DESCRIPTION("Felix Switch driver");
853MODULE_LICENSE("GPL v2");