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"); | |