156051948SVladimir Oltean // SPDX-License-Identifier: GPL-2.0 256051948SVladimir Oltean /* Copyright 2019 NXP Semiconductors 356051948SVladimir Oltean */ 456051948SVladimir Oltean #include <uapi/linux/if_bridge.h> 507d985eeSVladimir Oltean #include <soc/mscc/ocelot_vcap.h> 6bdeced75SVladimir Oltean #include <soc/mscc/ocelot_qsys.h> 7bdeced75SVladimir Oltean #include <soc/mscc/ocelot_sys.h> 8bdeced75SVladimir Oltean #include <soc/mscc/ocelot_dev.h> 9bdeced75SVladimir Oltean #include <soc/mscc/ocelot_ana.h> 102b49d128SYangbo Lu #include <soc/mscc/ocelot_ptp.h> 1156051948SVladimir Oltean #include <soc/mscc/ocelot.h> 12c0bcf537SYangbo Lu #include <linux/packing.h> 1356051948SVladimir Oltean #include <linux/module.h> 14bdeced75SVladimir Oltean #include <linux/of_net.h> 1556051948SVladimir Oltean #include <linux/pci.h> 1656051948SVladimir Oltean #include <linux/of.h> 17fc411eaaSVladimir Oltean #include <net/pkt_sched.h> 1856051948SVladimir Oltean #include <net/dsa.h> 1956051948SVladimir Oltean #include "felix.h" 2056051948SVladimir Oltean 2156051948SVladimir Oltean static enum dsa_tag_protocol felix_get_tag_protocol(struct dsa_switch *ds, 224d776482SFlorian Fainelli int port, 234d776482SFlorian Fainelli enum dsa_tag_protocol mp) 2456051948SVladimir Oltean { 2556051948SVladimir Oltean return DSA_TAG_PROTO_OCELOT; 2656051948SVladimir Oltean } 2756051948SVladimir Oltean 2856051948SVladimir Oltean static int felix_set_ageing_time(struct dsa_switch *ds, 2956051948SVladimir Oltean unsigned int ageing_time) 3056051948SVladimir Oltean { 3156051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 3256051948SVladimir Oltean 3356051948SVladimir Oltean ocelot_set_ageing_time(ocelot, ageing_time); 3456051948SVladimir Oltean 3556051948SVladimir Oltean return 0; 3656051948SVladimir Oltean } 3756051948SVladimir Oltean 3856051948SVladimir Oltean static int felix_fdb_dump(struct dsa_switch *ds, int port, 3956051948SVladimir Oltean dsa_fdb_dump_cb_t *cb, void *data) 4056051948SVladimir Oltean { 4156051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 4256051948SVladimir Oltean 4356051948SVladimir Oltean return ocelot_fdb_dump(ocelot, port, cb, data); 4456051948SVladimir Oltean } 4556051948SVladimir Oltean 4656051948SVladimir Oltean static int felix_fdb_add(struct dsa_switch *ds, int port, 4756051948SVladimir Oltean const unsigned char *addr, u16 vid) 4856051948SVladimir Oltean { 4956051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 5056051948SVladimir Oltean 5187b0f983SVladimir Oltean return ocelot_fdb_add(ocelot, port, addr, vid); 5256051948SVladimir Oltean } 5356051948SVladimir Oltean 5456051948SVladimir Oltean static int felix_fdb_del(struct dsa_switch *ds, int port, 5556051948SVladimir Oltean const unsigned char *addr, u16 vid) 5656051948SVladimir Oltean { 5756051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 5856051948SVladimir Oltean 5956051948SVladimir Oltean return ocelot_fdb_del(ocelot, port, addr, vid); 6056051948SVladimir Oltean } 6156051948SVladimir Oltean 6256051948SVladimir Oltean static void felix_bridge_stp_state_set(struct dsa_switch *ds, int port, 6356051948SVladimir Oltean u8 state) 6456051948SVladimir Oltean { 6556051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 6656051948SVladimir Oltean 6756051948SVladimir Oltean return ocelot_bridge_stp_state_set(ocelot, port, state); 6856051948SVladimir Oltean } 6956051948SVladimir Oltean 7056051948SVladimir Oltean static int felix_bridge_join(struct dsa_switch *ds, int port, 7156051948SVladimir Oltean struct net_device *br) 7256051948SVladimir Oltean { 7356051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 7456051948SVladimir Oltean 7556051948SVladimir Oltean return ocelot_port_bridge_join(ocelot, port, br); 7656051948SVladimir Oltean } 7756051948SVladimir Oltean 7856051948SVladimir Oltean static void felix_bridge_leave(struct dsa_switch *ds, int port, 7956051948SVladimir Oltean struct net_device *br) 8056051948SVladimir Oltean { 8156051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 8256051948SVladimir Oltean 8356051948SVladimir Oltean ocelot_port_bridge_leave(ocelot, port, br); 8456051948SVladimir Oltean } 8556051948SVladimir Oltean 8656051948SVladimir Oltean /* This callback needs to be present */ 8756051948SVladimir Oltean static int felix_vlan_prepare(struct dsa_switch *ds, int port, 8856051948SVladimir Oltean const struct switchdev_obj_port_vlan *vlan) 8956051948SVladimir Oltean { 9056051948SVladimir Oltean return 0; 9156051948SVladimir Oltean } 9256051948SVladimir Oltean 9356051948SVladimir Oltean static int felix_vlan_filtering(struct dsa_switch *ds, int port, bool enabled) 9456051948SVladimir Oltean { 9556051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 9656051948SVladimir Oltean 9756051948SVladimir Oltean ocelot_port_vlan_filtering(ocelot, port, enabled); 9856051948SVladimir Oltean 9956051948SVladimir Oltean return 0; 10056051948SVladimir Oltean } 10156051948SVladimir Oltean 10256051948SVladimir Oltean static void felix_vlan_add(struct dsa_switch *ds, int port, 10356051948SVladimir Oltean const struct switchdev_obj_port_vlan *vlan) 10456051948SVladimir Oltean { 10556051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 10656051948SVladimir Oltean u16 vid; 10756051948SVladimir Oltean int err; 10856051948SVladimir Oltean 10956051948SVladimir Oltean for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) { 11056051948SVladimir Oltean err = ocelot_vlan_add(ocelot, port, vid, 11156051948SVladimir Oltean vlan->flags & BRIDGE_VLAN_INFO_PVID, 11256051948SVladimir Oltean vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED); 11356051948SVladimir Oltean if (err) { 11456051948SVladimir Oltean dev_err(ds->dev, "Failed to add VLAN %d to port %d: %d\n", 11556051948SVladimir Oltean vid, port, err); 11656051948SVladimir Oltean return; 11756051948SVladimir Oltean } 11856051948SVladimir Oltean } 11956051948SVladimir Oltean } 12056051948SVladimir Oltean 12156051948SVladimir Oltean static int felix_vlan_del(struct dsa_switch *ds, int port, 12256051948SVladimir Oltean const struct switchdev_obj_port_vlan *vlan) 12356051948SVladimir Oltean { 12456051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 12556051948SVladimir Oltean u16 vid; 12656051948SVladimir Oltean int err; 12756051948SVladimir Oltean 12856051948SVladimir Oltean for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) { 12956051948SVladimir Oltean err = ocelot_vlan_del(ocelot, port, vid); 13056051948SVladimir Oltean if (err) { 13156051948SVladimir Oltean dev_err(ds->dev, "Failed to remove VLAN %d from port %d: %d\n", 13256051948SVladimir Oltean vid, port, err); 13356051948SVladimir Oltean return err; 13456051948SVladimir Oltean } 13556051948SVladimir Oltean } 13656051948SVladimir Oltean return 0; 13756051948SVladimir Oltean } 13856051948SVladimir Oltean 13956051948SVladimir Oltean static int felix_port_enable(struct dsa_switch *ds, int port, 14056051948SVladimir Oltean struct phy_device *phy) 14156051948SVladimir Oltean { 14256051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 14356051948SVladimir Oltean 14456051948SVladimir Oltean ocelot_port_enable(ocelot, port, phy); 14556051948SVladimir Oltean 14656051948SVladimir Oltean return 0; 14756051948SVladimir Oltean } 14856051948SVladimir Oltean 14956051948SVladimir Oltean static void felix_port_disable(struct dsa_switch *ds, int port) 15056051948SVladimir Oltean { 15156051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 15256051948SVladimir Oltean 15356051948SVladimir Oltean return ocelot_port_disable(ocelot, port); 15456051948SVladimir Oltean } 15556051948SVladimir Oltean 156bdeced75SVladimir Oltean static void felix_phylink_validate(struct dsa_switch *ds, int port, 157bdeced75SVladimir Oltean unsigned long *supported, 158bdeced75SVladimir Oltean struct phylink_link_state *state) 159bdeced75SVladimir Oltean { 160bdeced75SVladimir Oltean struct ocelot *ocelot = ds->priv; 161bdeced75SVladimir Oltean struct ocelot_port *ocelot_port = ocelot->ports[port]; 162bdeced75SVladimir Oltean __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; 163bdeced75SVladimir Oltean 164bdeced75SVladimir Oltean if (state->interface != PHY_INTERFACE_MODE_NA && 165bdeced75SVladimir Oltean state->interface != ocelot_port->phy_mode) { 166bdeced75SVladimir Oltean bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); 167bdeced75SVladimir Oltean return; 168bdeced75SVladimir Oltean } 169bdeced75SVladimir Oltean 170bdeced75SVladimir Oltean /* No half-duplex. */ 171bdeced75SVladimir Oltean phylink_set_port_modes(mask); 172bdeced75SVladimir Oltean phylink_set(mask, Autoneg); 173bdeced75SVladimir Oltean phylink_set(mask, Pause); 174bdeced75SVladimir Oltean phylink_set(mask, Asym_Pause); 175bdeced75SVladimir Oltean phylink_set(mask, 10baseT_Full); 176bdeced75SVladimir Oltean phylink_set(mask, 100baseT_Full); 177bdeced75SVladimir Oltean phylink_set(mask, 1000baseT_Full); 17874984a19SAlex Marginean 17928a134f5SVladimir Oltean if (state->interface == PHY_INTERFACE_MODE_INTERNAL || 180bdeced75SVladimir Oltean state->interface == PHY_INTERFACE_MODE_2500BASEX || 181bdeced75SVladimir Oltean state->interface == PHY_INTERFACE_MODE_USXGMII) { 182bdeced75SVladimir Oltean phylink_set(mask, 2500baseT_Full); 183bdeced75SVladimir Oltean phylink_set(mask, 2500baseX_Full); 184bdeced75SVladimir Oltean } 185bdeced75SVladimir Oltean 186bdeced75SVladimir Oltean bitmap_and(supported, supported, mask, 187bdeced75SVladimir Oltean __ETHTOOL_LINK_MODE_MASK_NBITS); 188bdeced75SVladimir Oltean bitmap_and(state->advertising, state->advertising, mask, 189bdeced75SVladimir Oltean __ETHTOOL_LINK_MODE_MASK_NBITS); 190bdeced75SVladimir Oltean } 191bdeced75SVladimir Oltean 192bdeced75SVladimir Oltean static int felix_phylink_mac_pcs_get_state(struct dsa_switch *ds, int port, 193bdeced75SVladimir Oltean struct phylink_link_state *state) 194bdeced75SVladimir Oltean { 195bdeced75SVladimir Oltean struct ocelot *ocelot = ds->priv; 196bdeced75SVladimir Oltean struct felix *felix = ocelot_to_felix(ocelot); 197bdeced75SVladimir Oltean 198bdeced75SVladimir Oltean if (felix->info->pcs_link_state) 199bdeced75SVladimir Oltean felix->info->pcs_link_state(ocelot, port, state); 200bdeced75SVladimir Oltean 201bdeced75SVladimir Oltean return 0; 202bdeced75SVladimir Oltean } 203bdeced75SVladimir Oltean 204bdeced75SVladimir Oltean static void felix_phylink_mac_config(struct dsa_switch *ds, int port, 205bdeced75SVladimir Oltean unsigned int link_an_mode, 206bdeced75SVladimir Oltean const struct phylink_link_state *state) 207bdeced75SVladimir Oltean { 208bdeced75SVladimir Oltean struct ocelot *ocelot = ds->priv; 209bdeced75SVladimir Oltean struct ocelot_port *ocelot_port = ocelot->ports[port]; 210bdeced75SVladimir Oltean struct felix *felix = ocelot_to_felix(ocelot); 211bdeced75SVladimir Oltean u32 mac_fc_cfg; 212bdeced75SVladimir Oltean 213bdeced75SVladimir Oltean /* Take port out of reset by clearing the MAC_TX_RST, MAC_RX_RST and 214bdeced75SVladimir Oltean * PORT_RST bits in CLOCK_CFG 215bdeced75SVladimir Oltean */ 216bdeced75SVladimir Oltean ocelot_port_writel(ocelot_port, DEV_CLOCK_CFG_LINK_SPEED(state->speed), 217bdeced75SVladimir Oltean DEV_CLOCK_CFG); 218bdeced75SVladimir Oltean 219bdeced75SVladimir Oltean /* Flow control. Link speed is only used here to evaluate the time 220bdeced75SVladimir Oltean * specification in incoming pause frames. 221bdeced75SVladimir Oltean */ 222bdeced75SVladimir Oltean mac_fc_cfg = SYS_MAC_FC_CFG_FC_LINK_SPEED(state->speed); 223f3660937SAlex Marginean 224f3660937SAlex Marginean /* handle Rx pause in all cases, with 2500base-X this is used for rate 225f3660937SAlex Marginean * adaptation. 226f3660937SAlex Marginean */ 227bdeced75SVladimir Oltean mac_fc_cfg |= SYS_MAC_FC_CFG_RX_FC_ENA; 228f3660937SAlex Marginean 229bdeced75SVladimir Oltean if (state->pause & MLO_PAUSE_TX) 230bdeced75SVladimir Oltean mac_fc_cfg |= SYS_MAC_FC_CFG_TX_FC_ENA | 231bdeced75SVladimir Oltean SYS_MAC_FC_CFG_PAUSE_VAL_CFG(0xffff) | 232bdeced75SVladimir Oltean SYS_MAC_FC_CFG_FC_LATENCY_CFG(0x7) | 233bdeced75SVladimir Oltean SYS_MAC_FC_CFG_ZERO_PAUSE_ENA; 234bdeced75SVladimir Oltean ocelot_write_rix(ocelot, mac_fc_cfg, SYS_MAC_FC_CFG, port); 235bdeced75SVladimir Oltean 236bdeced75SVladimir Oltean ocelot_write_rix(ocelot, 0, ANA_POL_FLOWC, port); 237bdeced75SVladimir Oltean 238bdeced75SVladimir Oltean if (felix->info->pcs_init) 239bdeced75SVladimir Oltean felix->info->pcs_init(ocelot, port, link_an_mode, state); 240*de143c0eSXiaoliang Yang 241*de143c0eSXiaoliang Yang if (felix->info->port_sched_speed_set) 242*de143c0eSXiaoliang Yang felix->info->port_sched_speed_set(ocelot, port, 243*de143c0eSXiaoliang Yang state->speed); 244bdeced75SVladimir Oltean } 245bdeced75SVladimir Oltean 246bdeced75SVladimir Oltean static void felix_phylink_mac_an_restart(struct dsa_switch *ds, int port) 247bdeced75SVladimir Oltean { 248bdeced75SVladimir Oltean struct ocelot *ocelot = ds->priv; 249bdeced75SVladimir Oltean struct felix *felix = ocelot_to_felix(ocelot); 250bdeced75SVladimir Oltean 251bdeced75SVladimir Oltean if (felix->info->pcs_an_restart) 252bdeced75SVladimir Oltean felix->info->pcs_an_restart(ocelot, port); 253bdeced75SVladimir Oltean } 254bdeced75SVladimir Oltean 255bdeced75SVladimir Oltean static void felix_phylink_mac_link_down(struct dsa_switch *ds, int port, 256bdeced75SVladimir Oltean unsigned int link_an_mode, 257bdeced75SVladimir Oltean phy_interface_t interface) 258bdeced75SVladimir Oltean { 259bdeced75SVladimir Oltean struct ocelot *ocelot = ds->priv; 260bdeced75SVladimir Oltean struct ocelot_port *ocelot_port = ocelot->ports[port]; 261bdeced75SVladimir Oltean 262bdeced75SVladimir Oltean ocelot_port_writel(ocelot_port, 0, DEV_MAC_ENA_CFG); 263bdeced75SVladimir Oltean ocelot_rmw_rix(ocelot, 0, QSYS_SWITCH_PORT_MODE_PORT_ENA, 264bdeced75SVladimir Oltean QSYS_SWITCH_PORT_MODE, port); 265bdeced75SVladimir Oltean } 266bdeced75SVladimir Oltean 267bdeced75SVladimir Oltean static void felix_phylink_mac_link_up(struct dsa_switch *ds, int port, 268bdeced75SVladimir Oltean unsigned int link_an_mode, 269bdeced75SVladimir Oltean phy_interface_t interface, 2705b502a7bSRussell King struct phy_device *phydev, 2715b502a7bSRussell King int speed, int duplex, 2725b502a7bSRussell King bool tx_pause, bool rx_pause) 273bdeced75SVladimir Oltean { 274bdeced75SVladimir Oltean struct ocelot *ocelot = ds->priv; 275bdeced75SVladimir Oltean struct ocelot_port *ocelot_port = ocelot->ports[port]; 276bdeced75SVladimir Oltean 277bdeced75SVladimir Oltean /* Enable MAC module */ 278bdeced75SVladimir Oltean ocelot_port_writel(ocelot_port, DEV_MAC_ENA_CFG_RX_ENA | 279bdeced75SVladimir Oltean DEV_MAC_ENA_CFG_TX_ENA, DEV_MAC_ENA_CFG); 280bdeced75SVladimir Oltean 281bdeced75SVladimir Oltean /* Enable receiving frames on the port, and activate auto-learning of 282bdeced75SVladimir Oltean * MAC addresses. 283bdeced75SVladimir Oltean */ 284bdeced75SVladimir Oltean ocelot_write_gix(ocelot, ANA_PORT_PORT_CFG_LEARNAUTO | 285bdeced75SVladimir Oltean ANA_PORT_PORT_CFG_RECV_ENA | 286bdeced75SVladimir Oltean ANA_PORT_PORT_CFG_PORTID_VAL(port), 287bdeced75SVladimir Oltean ANA_PORT_PORT_CFG, port); 288bdeced75SVladimir Oltean 289bdeced75SVladimir Oltean /* Core: Enable port for frame transfer */ 290bdeced75SVladimir Oltean ocelot_write_rix(ocelot, QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE | 291bdeced75SVladimir Oltean QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG(1) | 292bdeced75SVladimir Oltean QSYS_SWITCH_PORT_MODE_PORT_ENA, 293bdeced75SVladimir Oltean QSYS_SWITCH_PORT_MODE, port); 294bdeced75SVladimir Oltean } 295bdeced75SVladimir Oltean 296bd2b3161SXiaoliang Yang static void felix_port_qos_map_init(struct ocelot *ocelot, int port) 297bd2b3161SXiaoliang Yang { 298bd2b3161SXiaoliang Yang int i; 299bd2b3161SXiaoliang Yang 300bd2b3161SXiaoliang Yang ocelot_rmw_gix(ocelot, 301bd2b3161SXiaoliang Yang ANA_PORT_QOS_CFG_QOS_PCP_ENA, 302bd2b3161SXiaoliang Yang ANA_PORT_QOS_CFG_QOS_PCP_ENA, 303bd2b3161SXiaoliang Yang ANA_PORT_QOS_CFG, 304bd2b3161SXiaoliang Yang port); 305bd2b3161SXiaoliang Yang 306bd2b3161SXiaoliang Yang for (i = 0; i < FELIX_NUM_TC * 2; i++) { 307bd2b3161SXiaoliang Yang ocelot_rmw_ix(ocelot, 308bd2b3161SXiaoliang Yang (ANA_PORT_PCP_DEI_MAP_DP_PCP_DEI_VAL & i) | 309bd2b3161SXiaoliang Yang ANA_PORT_PCP_DEI_MAP_QOS_PCP_DEI_VAL(i), 310bd2b3161SXiaoliang Yang ANA_PORT_PCP_DEI_MAP_DP_PCP_DEI_VAL | 311bd2b3161SXiaoliang Yang ANA_PORT_PCP_DEI_MAP_QOS_PCP_DEI_VAL_M, 312bd2b3161SXiaoliang Yang ANA_PORT_PCP_DEI_MAP, 313bd2b3161SXiaoliang Yang port, i); 314bd2b3161SXiaoliang Yang } 315bd2b3161SXiaoliang Yang } 316bd2b3161SXiaoliang Yang 31756051948SVladimir Oltean static void felix_get_strings(struct dsa_switch *ds, int port, 31856051948SVladimir Oltean u32 stringset, u8 *data) 31956051948SVladimir Oltean { 32056051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 32156051948SVladimir Oltean 32256051948SVladimir Oltean return ocelot_get_strings(ocelot, port, stringset, data); 32356051948SVladimir Oltean } 32456051948SVladimir Oltean 32556051948SVladimir Oltean static void felix_get_ethtool_stats(struct dsa_switch *ds, int port, u64 *data) 32656051948SVladimir Oltean { 32756051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 32856051948SVladimir Oltean 32956051948SVladimir Oltean ocelot_get_ethtool_stats(ocelot, port, data); 33056051948SVladimir Oltean } 33156051948SVladimir Oltean 33256051948SVladimir Oltean static int felix_get_sset_count(struct dsa_switch *ds, int port, int sset) 33356051948SVladimir Oltean { 33456051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 33556051948SVladimir Oltean 33656051948SVladimir Oltean return ocelot_get_sset_count(ocelot, port, sset); 33756051948SVladimir Oltean } 33856051948SVladimir Oltean 33956051948SVladimir Oltean static int felix_get_ts_info(struct dsa_switch *ds, int port, 34056051948SVladimir Oltean struct ethtool_ts_info *info) 34156051948SVladimir Oltean { 34256051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 34356051948SVladimir Oltean 34456051948SVladimir Oltean return ocelot_get_ts_info(ocelot, port, info); 34556051948SVladimir Oltean } 34656051948SVladimir Oltean 347bdeced75SVladimir Oltean static int felix_parse_ports_node(struct felix *felix, 348bdeced75SVladimir Oltean struct device_node *ports_node, 349bdeced75SVladimir Oltean phy_interface_t *port_phy_modes) 350bdeced75SVladimir Oltean { 351bdeced75SVladimir Oltean struct ocelot *ocelot = &felix->ocelot; 352bdeced75SVladimir Oltean struct device *dev = felix->ocelot.dev; 353bdeced75SVladimir Oltean struct device_node *child; 354bdeced75SVladimir Oltean 35537fe45adSVladimir Oltean for_each_available_child_of_node(ports_node, child) { 356bdeced75SVladimir Oltean phy_interface_t phy_mode; 357bdeced75SVladimir Oltean u32 port; 358bdeced75SVladimir Oltean int err; 359bdeced75SVladimir Oltean 360bdeced75SVladimir Oltean /* Get switch port number from DT */ 361bdeced75SVladimir Oltean if (of_property_read_u32(child, "reg", &port) < 0) { 362bdeced75SVladimir Oltean dev_err(dev, "Port number not defined in device tree " 363bdeced75SVladimir Oltean "(property \"reg\")\n"); 364bdeced75SVladimir Oltean of_node_put(child); 365bdeced75SVladimir Oltean return -ENODEV; 366bdeced75SVladimir Oltean } 367bdeced75SVladimir Oltean 368bdeced75SVladimir Oltean /* Get PHY mode from DT */ 369bdeced75SVladimir Oltean err = of_get_phy_mode(child, &phy_mode); 370bdeced75SVladimir Oltean if (err) { 371bdeced75SVladimir Oltean dev_err(dev, "Failed to read phy-mode or " 372bdeced75SVladimir Oltean "phy-interface-type property for port %d\n", 373bdeced75SVladimir Oltean port); 374bdeced75SVladimir Oltean of_node_put(child); 375bdeced75SVladimir Oltean return -ENODEV; 376bdeced75SVladimir Oltean } 377bdeced75SVladimir Oltean 378bdeced75SVladimir Oltean err = felix->info->prevalidate_phy_mode(ocelot, port, phy_mode); 379bdeced75SVladimir Oltean if (err < 0) { 380bdeced75SVladimir Oltean dev_err(dev, "Unsupported PHY mode %s on port %d\n", 381bdeced75SVladimir Oltean phy_modes(phy_mode), port); 382bdeced75SVladimir Oltean return err; 383bdeced75SVladimir Oltean } 384bdeced75SVladimir Oltean 385bdeced75SVladimir Oltean port_phy_modes[port] = phy_mode; 386bdeced75SVladimir Oltean } 387bdeced75SVladimir Oltean 388bdeced75SVladimir Oltean return 0; 389bdeced75SVladimir Oltean } 390bdeced75SVladimir Oltean 391bdeced75SVladimir Oltean static int felix_parse_dt(struct felix *felix, phy_interface_t *port_phy_modes) 392bdeced75SVladimir Oltean { 393bdeced75SVladimir Oltean struct device *dev = felix->ocelot.dev; 394bdeced75SVladimir Oltean struct device_node *switch_node; 395bdeced75SVladimir Oltean struct device_node *ports_node; 396bdeced75SVladimir Oltean int err; 397bdeced75SVladimir Oltean 398bdeced75SVladimir Oltean switch_node = dev->of_node; 399bdeced75SVladimir Oltean 400bdeced75SVladimir Oltean ports_node = of_get_child_by_name(switch_node, "ports"); 401bdeced75SVladimir Oltean if (!ports_node) { 402bdeced75SVladimir Oltean dev_err(dev, "Incorrect bindings: absent \"ports\" node\n"); 403bdeced75SVladimir Oltean return -ENODEV; 404bdeced75SVladimir Oltean } 405bdeced75SVladimir Oltean 406bdeced75SVladimir Oltean err = felix_parse_ports_node(felix, ports_node, port_phy_modes); 407bdeced75SVladimir Oltean of_node_put(ports_node); 408bdeced75SVladimir Oltean 409bdeced75SVladimir Oltean return err; 410bdeced75SVladimir Oltean } 411bdeced75SVladimir Oltean 41256051948SVladimir Oltean static int felix_init_structs(struct felix *felix, int num_phys_ports) 41356051948SVladimir Oltean { 41456051948SVladimir Oltean struct ocelot *ocelot = &felix->ocelot; 415bdeced75SVladimir Oltean phy_interface_t *port_phy_modes; 416bdeced75SVladimir Oltean resource_size_t switch_base; 41756051948SVladimir Oltean int port, i, err; 41856051948SVladimir Oltean 41956051948SVladimir Oltean ocelot->num_phys_ports = num_phys_ports; 42056051948SVladimir Oltean ocelot->ports = devm_kcalloc(ocelot->dev, num_phys_ports, 42156051948SVladimir Oltean sizeof(struct ocelot_port *), GFP_KERNEL); 42256051948SVladimir Oltean if (!ocelot->ports) 42356051948SVladimir Oltean return -ENOMEM; 42456051948SVladimir Oltean 42556051948SVladimir Oltean ocelot->map = felix->info->map; 42656051948SVladimir Oltean ocelot->stats_layout = felix->info->stats_layout; 42756051948SVladimir Oltean ocelot->num_stats = felix->info->num_stats; 42856051948SVladimir Oltean ocelot->shared_queue_sz = felix->info->shared_queue_sz; 42921ce7f3eSVladimir Oltean ocelot->num_mact_rows = felix->info->num_mact_rows; 43007d985eeSVladimir Oltean ocelot->vcap_is2_keys = felix->info->vcap_is2_keys; 43107d985eeSVladimir Oltean ocelot->vcap_is2_actions= felix->info->vcap_is2_actions; 43207d985eeSVladimir Oltean ocelot->vcap = felix->info->vcap; 43356051948SVladimir Oltean ocelot->ops = felix->info->ops; 43456051948SVladimir Oltean 435bdeced75SVladimir Oltean port_phy_modes = kcalloc(num_phys_ports, sizeof(phy_interface_t), 436bdeced75SVladimir Oltean GFP_KERNEL); 437bdeced75SVladimir Oltean if (!port_phy_modes) 438bdeced75SVladimir Oltean return -ENOMEM; 439bdeced75SVladimir Oltean 440bdeced75SVladimir Oltean err = felix_parse_dt(felix, port_phy_modes); 441bdeced75SVladimir Oltean if (err) { 442bdeced75SVladimir Oltean kfree(port_phy_modes); 443bdeced75SVladimir Oltean return err; 444bdeced75SVladimir Oltean } 445bdeced75SVladimir Oltean 446bdeced75SVladimir Oltean switch_base = pci_resource_start(felix->pdev, 447bdeced75SVladimir Oltean felix->info->switch_pci_bar); 44856051948SVladimir Oltean 44956051948SVladimir Oltean for (i = 0; i < TARGET_MAX; i++) { 45056051948SVladimir Oltean struct regmap *target; 45156051948SVladimir Oltean struct resource *res; 45256051948SVladimir Oltean 45356051948SVladimir Oltean if (!felix->info->target_io_res[i].name) 45456051948SVladimir Oltean continue; 45556051948SVladimir Oltean 45656051948SVladimir Oltean res = &felix->info->target_io_res[i]; 45756051948SVladimir Oltean res->flags = IORESOURCE_MEM; 458bdeced75SVladimir Oltean res->start += switch_base; 459bdeced75SVladimir Oltean res->end += switch_base; 46056051948SVladimir Oltean 46156051948SVladimir Oltean target = ocelot_regmap_init(ocelot, res); 46256051948SVladimir Oltean if (IS_ERR(target)) { 46356051948SVladimir Oltean dev_err(ocelot->dev, 46456051948SVladimir Oltean "Failed to map device memory space\n"); 465bdeced75SVladimir Oltean kfree(port_phy_modes); 46656051948SVladimir Oltean return PTR_ERR(target); 46756051948SVladimir Oltean } 46856051948SVladimir Oltean 46956051948SVladimir Oltean ocelot->targets[i] = target; 47056051948SVladimir Oltean } 47156051948SVladimir Oltean 47256051948SVladimir Oltean err = ocelot_regfields_init(ocelot, felix->info->regfields); 47356051948SVladimir Oltean if (err) { 47456051948SVladimir Oltean dev_err(ocelot->dev, "failed to init reg fields map\n"); 475bdeced75SVladimir Oltean kfree(port_phy_modes); 47656051948SVladimir Oltean return err; 47756051948SVladimir Oltean } 47856051948SVladimir Oltean 47956051948SVladimir Oltean for (port = 0; port < num_phys_ports; port++) { 48056051948SVladimir Oltean struct ocelot_port *ocelot_port; 48156051948SVladimir Oltean void __iomem *port_regs; 48256051948SVladimir Oltean struct resource *res; 48356051948SVladimir Oltean 48456051948SVladimir Oltean ocelot_port = devm_kzalloc(ocelot->dev, 48556051948SVladimir Oltean sizeof(struct ocelot_port), 48656051948SVladimir Oltean GFP_KERNEL); 48756051948SVladimir Oltean if (!ocelot_port) { 48856051948SVladimir Oltean dev_err(ocelot->dev, 48956051948SVladimir Oltean "failed to allocate port memory\n"); 490bdeced75SVladimir Oltean kfree(port_phy_modes); 49156051948SVladimir Oltean return -ENOMEM; 49256051948SVladimir Oltean } 49356051948SVladimir Oltean 49456051948SVladimir Oltean res = &felix->info->port_io_res[port]; 49556051948SVladimir Oltean res->flags = IORESOURCE_MEM; 496bdeced75SVladimir Oltean res->start += switch_base; 497bdeced75SVladimir Oltean res->end += switch_base; 49856051948SVladimir Oltean 49956051948SVladimir Oltean port_regs = devm_ioremap_resource(ocelot->dev, res); 50056051948SVladimir Oltean if (IS_ERR(port_regs)) { 50156051948SVladimir Oltean dev_err(ocelot->dev, 50256051948SVladimir Oltean "failed to map registers for port %d\n", port); 503bdeced75SVladimir Oltean kfree(port_phy_modes); 50456051948SVladimir Oltean return PTR_ERR(port_regs); 50556051948SVladimir Oltean } 50656051948SVladimir Oltean 507bdeced75SVladimir Oltean ocelot_port->phy_mode = port_phy_modes[port]; 50856051948SVladimir Oltean ocelot_port->ocelot = ocelot; 50956051948SVladimir Oltean ocelot_port->regs = port_regs; 51056051948SVladimir Oltean ocelot->ports[port] = ocelot_port; 51156051948SVladimir Oltean } 51256051948SVladimir Oltean 513bdeced75SVladimir Oltean kfree(port_phy_modes); 514bdeced75SVladimir Oltean 515bdeced75SVladimir Oltean if (felix->info->mdio_bus_alloc) { 516bdeced75SVladimir Oltean err = felix->info->mdio_bus_alloc(ocelot); 517bdeced75SVladimir Oltean if (err < 0) 518bdeced75SVladimir Oltean return err; 519bdeced75SVladimir Oltean } 520bdeced75SVladimir Oltean 52156051948SVladimir Oltean return 0; 52256051948SVladimir Oltean } 52356051948SVladimir Oltean 5242b49d128SYangbo Lu static struct ptp_clock_info ocelot_ptp_clock_info = { 5252b49d128SYangbo Lu .owner = THIS_MODULE, 5262b49d128SYangbo Lu .name = "felix ptp", 5272b49d128SYangbo Lu .max_adj = 0x7fffffff, 5282b49d128SYangbo Lu .n_alarm = 0, 5292b49d128SYangbo Lu .n_ext_ts = 0, 5305287be40SYangbo Lu .n_per_out = OCELOT_PTP_PINS_NUM, 5315287be40SYangbo Lu .n_pins = OCELOT_PTP_PINS_NUM, 5322b49d128SYangbo Lu .pps = 0, 5332b49d128SYangbo Lu .gettime64 = ocelot_ptp_gettime64, 5342b49d128SYangbo Lu .settime64 = ocelot_ptp_settime64, 5352b49d128SYangbo Lu .adjtime = ocelot_ptp_adjtime, 5362b49d128SYangbo Lu .adjfine = ocelot_ptp_adjfine, 5375287be40SYangbo Lu .verify = ocelot_ptp_verify, 5385287be40SYangbo Lu .enable = ocelot_ptp_enable, 5392b49d128SYangbo Lu }; 5402b49d128SYangbo Lu 54156051948SVladimir Oltean /* Hardware initialization done here so that we can allocate structures with 54256051948SVladimir Oltean * devm without fear of dsa_register_switch returning -EPROBE_DEFER and causing 54356051948SVladimir Oltean * us to allocate structures twice (leak memory) and map PCI memory twice 54456051948SVladimir Oltean * (which will not work). 54556051948SVladimir Oltean */ 54656051948SVladimir Oltean static int felix_setup(struct dsa_switch *ds) 54756051948SVladimir Oltean { 54856051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 54956051948SVladimir Oltean struct felix *felix = ocelot_to_felix(ocelot); 55056051948SVladimir Oltean int port, err; 5513c7b51bdSXiaoliang Yang int tc; 55256051948SVladimir Oltean 55356051948SVladimir Oltean err = felix_init_structs(felix, ds->num_ports); 55456051948SVladimir Oltean if (err) 55556051948SVladimir Oltean return err; 55656051948SVladimir Oltean 55756051948SVladimir Oltean ocelot_init(ocelot); 5582b49d128SYangbo Lu if (ocelot->ptp) { 5592b49d128SYangbo Lu err = ocelot_init_timestamp(ocelot, &ocelot_ptp_clock_info); 5602b49d128SYangbo Lu if (err) { 5612b49d128SYangbo Lu dev_err(ocelot->dev, 5622b49d128SYangbo Lu "Timestamp initialization failed\n"); 5632b49d128SYangbo Lu ocelot->ptp = 0; 5642b49d128SYangbo Lu } 5652b49d128SYangbo Lu } 56656051948SVladimir Oltean 56756051948SVladimir Oltean for (port = 0; port < ds->num_ports; port++) { 56856051948SVladimir Oltean ocelot_init_port(ocelot, port); 56956051948SVladimir Oltean 57069df578cSVladimir Oltean /* Bring up the CPU port module and configure the NPI port */ 571b8fc7177SVladimir Oltean if (dsa_is_cpu_port(ds, port)) 57269df578cSVladimir Oltean ocelot_configure_cpu(ocelot, port, 57356051948SVladimir Oltean OCELOT_TAG_PREFIX_NONE, 57456051948SVladimir Oltean OCELOT_TAG_PREFIX_LONG); 575bd2b3161SXiaoliang Yang 576bd2b3161SXiaoliang Yang /* Set the default QoS Classification based on PCP and DEI 577bd2b3161SXiaoliang Yang * bits of vlan tag. 578bd2b3161SXiaoliang Yang */ 579bd2b3161SXiaoliang Yang felix_port_qos_map_init(ocelot, port); 58056051948SVladimir Oltean } 58156051948SVladimir Oltean 5821cf3299bSVladimir Oltean /* Include the CPU port module in the forwarding mask for unknown 5831cf3299bSVladimir Oltean * unicast - the hardware default value for ANA_FLOODING_FLD_UNICAST 5841cf3299bSVladimir Oltean * excludes BIT(ocelot->num_phys_ports), and so does ocelot_init, since 5851cf3299bSVladimir Oltean * Ocelot relies on whitelisting MAC addresses towards PGID_CPU. 5861cf3299bSVladimir Oltean */ 5871cf3299bSVladimir Oltean ocelot_write_rix(ocelot, 5881cf3299bSVladimir Oltean ANA_PGID_PGID_PGID(GENMASK(ocelot->num_phys_ports, 0)), 5891cf3299bSVladimir Oltean ANA_PGID_PGID, PGID_UC); 5903c7b51bdSXiaoliang Yang /* Setup the per-traffic class flooding PGIDs */ 5913c7b51bdSXiaoliang Yang for (tc = 0; tc < FELIX_NUM_TC; tc++) 5923c7b51bdSXiaoliang Yang ocelot_write_rix(ocelot, ANA_FLOODING_FLD_MULTICAST(PGID_MC) | 5933c7b51bdSXiaoliang Yang ANA_FLOODING_FLD_BROADCAST(PGID_MC) | 5943c7b51bdSXiaoliang Yang ANA_FLOODING_FLD_UNICAST(PGID_UC), 5953c7b51bdSXiaoliang Yang ANA_FLOODING, tc); 5961cf3299bSVladimir Oltean 5970b912fc9SVladimir Oltean ds->mtu_enforcement_ingress = true; 598bdeced75SVladimir Oltean /* It looks like the MAC/PCS interrupt register - PM0_IEVENT (0x8040) 599bdeced75SVladimir Oltean * isn't instantiated for the Felix PF. 600bdeced75SVladimir Oltean * In-band AN may take a few ms to complete, so we need to poll. 601bdeced75SVladimir Oltean */ 602bdeced75SVladimir Oltean ds->pcs_poll = true; 603bdeced75SVladimir Oltean 60456051948SVladimir Oltean return 0; 60556051948SVladimir Oltean } 60656051948SVladimir Oltean 60756051948SVladimir Oltean static void felix_teardown(struct dsa_switch *ds) 60856051948SVladimir Oltean { 60956051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 610bdeced75SVladimir Oltean struct felix *felix = ocelot_to_felix(ocelot); 611bdeced75SVladimir Oltean 612bdeced75SVladimir Oltean if (felix->info->mdio_bus_free) 613bdeced75SVladimir Oltean felix->info->mdio_bus_free(ocelot); 61456051948SVladimir Oltean 6152b49d128SYangbo Lu ocelot_deinit_timestamp(ocelot); 61656051948SVladimir Oltean /* stop workqueue thread */ 61756051948SVladimir Oltean ocelot_deinit(ocelot); 61856051948SVladimir Oltean } 61956051948SVladimir Oltean 620c0bcf537SYangbo Lu static int felix_hwtstamp_get(struct dsa_switch *ds, int port, 621c0bcf537SYangbo Lu struct ifreq *ifr) 622c0bcf537SYangbo Lu { 623c0bcf537SYangbo Lu struct ocelot *ocelot = ds->priv; 624c0bcf537SYangbo Lu 625c0bcf537SYangbo Lu return ocelot_hwstamp_get(ocelot, port, ifr); 626c0bcf537SYangbo Lu } 627c0bcf537SYangbo Lu 628c0bcf537SYangbo Lu static int felix_hwtstamp_set(struct dsa_switch *ds, int port, 629c0bcf537SYangbo Lu struct ifreq *ifr) 630c0bcf537SYangbo Lu { 631c0bcf537SYangbo Lu struct ocelot *ocelot = ds->priv; 632c0bcf537SYangbo Lu 633c0bcf537SYangbo Lu return ocelot_hwstamp_set(ocelot, port, ifr); 634c0bcf537SYangbo Lu } 635c0bcf537SYangbo Lu 636c0bcf537SYangbo Lu static bool felix_rxtstamp(struct dsa_switch *ds, int port, 637c0bcf537SYangbo Lu struct sk_buff *skb, unsigned int type) 638c0bcf537SYangbo Lu { 639c0bcf537SYangbo Lu struct skb_shared_hwtstamps *shhwtstamps; 640c0bcf537SYangbo Lu struct ocelot *ocelot = ds->priv; 641c0bcf537SYangbo Lu u8 *extraction = skb->data - ETH_HLEN - OCELOT_TAG_LEN; 642c0bcf537SYangbo Lu u32 tstamp_lo, tstamp_hi; 643c0bcf537SYangbo Lu struct timespec64 ts; 644c0bcf537SYangbo Lu u64 tstamp, val; 645c0bcf537SYangbo Lu 646c0bcf537SYangbo Lu ocelot_ptp_gettime64(&ocelot->ptp_info, &ts); 647c0bcf537SYangbo Lu tstamp = ktime_set(ts.tv_sec, ts.tv_nsec); 648c0bcf537SYangbo Lu 649c0bcf537SYangbo Lu packing(extraction, &val, 116, 85, OCELOT_TAG_LEN, UNPACK, 0); 650c0bcf537SYangbo Lu tstamp_lo = (u32)val; 651c0bcf537SYangbo Lu 652c0bcf537SYangbo Lu tstamp_hi = tstamp >> 32; 653c0bcf537SYangbo Lu if ((tstamp & 0xffffffff) < tstamp_lo) 654c0bcf537SYangbo Lu tstamp_hi--; 655c0bcf537SYangbo Lu 656c0bcf537SYangbo Lu tstamp = ((u64)tstamp_hi << 32) | tstamp_lo; 657c0bcf537SYangbo Lu 658c0bcf537SYangbo Lu shhwtstamps = skb_hwtstamps(skb); 659c0bcf537SYangbo Lu memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps)); 660c0bcf537SYangbo Lu shhwtstamps->hwtstamp = tstamp; 661c0bcf537SYangbo Lu return false; 662c0bcf537SYangbo Lu } 663c0bcf537SYangbo Lu 6643243e04aSChen Wandun static bool felix_txtstamp(struct dsa_switch *ds, int port, 665c0bcf537SYangbo Lu struct sk_buff *clone, unsigned int type) 666c0bcf537SYangbo Lu { 667c0bcf537SYangbo Lu struct ocelot *ocelot = ds->priv; 668c0bcf537SYangbo Lu struct ocelot_port *ocelot_port = ocelot->ports[port]; 669c0bcf537SYangbo Lu 670c0bcf537SYangbo Lu if (!ocelot_port_add_txtstamp_skb(ocelot_port, clone)) 671c0bcf537SYangbo Lu return true; 672c0bcf537SYangbo Lu 673c0bcf537SYangbo Lu return false; 674c0bcf537SYangbo Lu } 675c0bcf537SYangbo Lu 6760b912fc9SVladimir Oltean static int felix_change_mtu(struct dsa_switch *ds, int port, int new_mtu) 6770b912fc9SVladimir Oltean { 6780b912fc9SVladimir Oltean struct ocelot *ocelot = ds->priv; 6790b912fc9SVladimir Oltean 6800b912fc9SVladimir Oltean ocelot_port_set_maxlen(ocelot, port, new_mtu); 6810b912fc9SVladimir Oltean 6820b912fc9SVladimir Oltean return 0; 6830b912fc9SVladimir Oltean } 6840b912fc9SVladimir Oltean 6850b912fc9SVladimir Oltean static int felix_get_max_mtu(struct dsa_switch *ds, int port) 6860b912fc9SVladimir Oltean { 6870b912fc9SVladimir Oltean struct ocelot *ocelot = ds->priv; 6880b912fc9SVladimir Oltean 6890b912fc9SVladimir Oltean return ocelot_get_max_mtu(ocelot, port); 6900b912fc9SVladimir Oltean } 6910b912fc9SVladimir Oltean 69207d985eeSVladimir Oltean static int felix_cls_flower_add(struct dsa_switch *ds, int port, 69307d985eeSVladimir Oltean struct flow_cls_offload *cls, bool ingress) 69407d985eeSVladimir Oltean { 69507d985eeSVladimir Oltean struct ocelot *ocelot = ds->priv; 69607d985eeSVladimir Oltean 69707d985eeSVladimir Oltean return ocelot_cls_flower_replace(ocelot, port, cls, ingress); 69807d985eeSVladimir Oltean } 69907d985eeSVladimir Oltean 70007d985eeSVladimir Oltean static int felix_cls_flower_del(struct dsa_switch *ds, int port, 70107d985eeSVladimir Oltean struct flow_cls_offload *cls, bool ingress) 70207d985eeSVladimir Oltean { 70307d985eeSVladimir Oltean struct ocelot *ocelot = ds->priv; 70407d985eeSVladimir Oltean 70507d985eeSVladimir Oltean return ocelot_cls_flower_destroy(ocelot, port, cls, ingress); 70607d985eeSVladimir Oltean } 70707d985eeSVladimir Oltean 70807d985eeSVladimir Oltean static int felix_cls_flower_stats(struct dsa_switch *ds, int port, 70907d985eeSVladimir Oltean struct flow_cls_offload *cls, bool ingress) 71007d985eeSVladimir Oltean { 71107d985eeSVladimir Oltean struct ocelot *ocelot = ds->priv; 71207d985eeSVladimir Oltean 71307d985eeSVladimir Oltean return ocelot_cls_flower_stats(ocelot, port, cls, ingress); 71407d985eeSVladimir Oltean } 71507d985eeSVladimir Oltean 716fc411eaaSVladimir Oltean static int felix_port_policer_add(struct dsa_switch *ds, int port, 717fc411eaaSVladimir Oltean struct dsa_mall_policer_tc_entry *policer) 718fc411eaaSVladimir Oltean { 719fc411eaaSVladimir Oltean struct ocelot *ocelot = ds->priv; 720fc411eaaSVladimir Oltean struct ocelot_policer pol = { 721fc411eaaSVladimir Oltean .rate = div_u64(policer->rate_bytes_per_sec, 1000) * 8, 722fc411eaaSVladimir Oltean .burst = div_u64(policer->rate_bytes_per_sec * 723fc411eaaSVladimir Oltean PSCHED_NS2TICKS(policer->burst), 724fc411eaaSVladimir Oltean PSCHED_TICKS_PER_SEC), 725fc411eaaSVladimir Oltean }; 726fc411eaaSVladimir Oltean 727fc411eaaSVladimir Oltean return ocelot_port_policer_add(ocelot, port, &pol); 728fc411eaaSVladimir Oltean } 729fc411eaaSVladimir Oltean 730fc411eaaSVladimir Oltean static void felix_port_policer_del(struct dsa_switch *ds, int port) 731fc411eaaSVladimir Oltean { 732fc411eaaSVladimir Oltean struct ocelot *ocelot = ds->priv; 733fc411eaaSVladimir Oltean 734fc411eaaSVladimir Oltean ocelot_port_policer_del(ocelot, port); 735fc411eaaSVladimir Oltean } 736fc411eaaSVladimir Oltean 737*de143c0eSXiaoliang Yang static int felix_port_setup_tc(struct dsa_switch *ds, int port, 738*de143c0eSXiaoliang Yang enum tc_setup_type type, 739*de143c0eSXiaoliang Yang void *type_data) 740*de143c0eSXiaoliang Yang { 741*de143c0eSXiaoliang Yang struct ocelot *ocelot = ds->priv; 742*de143c0eSXiaoliang Yang struct felix *felix = ocelot_to_felix(ocelot); 743*de143c0eSXiaoliang Yang 744*de143c0eSXiaoliang Yang if (felix->info->port_setup_tc) 745*de143c0eSXiaoliang Yang return felix->info->port_setup_tc(ds, port, type, type_data); 746*de143c0eSXiaoliang Yang else 747*de143c0eSXiaoliang Yang return -EOPNOTSUPP; 748*de143c0eSXiaoliang Yang } 749*de143c0eSXiaoliang Yang 75056051948SVladimir Oltean static const struct dsa_switch_ops felix_switch_ops = { 75156051948SVladimir Oltean .get_tag_protocol = felix_get_tag_protocol, 75256051948SVladimir Oltean .setup = felix_setup, 75356051948SVladimir Oltean .teardown = felix_teardown, 75456051948SVladimir Oltean .set_ageing_time = felix_set_ageing_time, 75556051948SVladimir Oltean .get_strings = felix_get_strings, 75656051948SVladimir Oltean .get_ethtool_stats = felix_get_ethtool_stats, 75756051948SVladimir Oltean .get_sset_count = felix_get_sset_count, 75856051948SVladimir Oltean .get_ts_info = felix_get_ts_info, 759bdeced75SVladimir Oltean .phylink_validate = felix_phylink_validate, 760bdeced75SVladimir Oltean .phylink_mac_link_state = felix_phylink_mac_pcs_get_state, 761bdeced75SVladimir Oltean .phylink_mac_config = felix_phylink_mac_config, 762bdeced75SVladimir Oltean .phylink_mac_an_restart = felix_phylink_mac_an_restart, 763bdeced75SVladimir Oltean .phylink_mac_link_down = felix_phylink_mac_link_down, 764bdeced75SVladimir Oltean .phylink_mac_link_up = felix_phylink_mac_link_up, 76556051948SVladimir Oltean .port_enable = felix_port_enable, 76656051948SVladimir Oltean .port_disable = felix_port_disable, 76756051948SVladimir Oltean .port_fdb_dump = felix_fdb_dump, 76856051948SVladimir Oltean .port_fdb_add = felix_fdb_add, 76956051948SVladimir Oltean .port_fdb_del = felix_fdb_del, 77056051948SVladimir Oltean .port_bridge_join = felix_bridge_join, 77156051948SVladimir Oltean .port_bridge_leave = felix_bridge_leave, 77256051948SVladimir Oltean .port_stp_state_set = felix_bridge_stp_state_set, 77356051948SVladimir Oltean .port_vlan_prepare = felix_vlan_prepare, 77456051948SVladimir Oltean .port_vlan_filtering = felix_vlan_filtering, 77556051948SVladimir Oltean .port_vlan_add = felix_vlan_add, 77656051948SVladimir Oltean .port_vlan_del = felix_vlan_del, 777c0bcf537SYangbo Lu .port_hwtstamp_get = felix_hwtstamp_get, 778c0bcf537SYangbo Lu .port_hwtstamp_set = felix_hwtstamp_set, 779c0bcf537SYangbo Lu .port_rxtstamp = felix_rxtstamp, 780c0bcf537SYangbo Lu .port_txtstamp = felix_txtstamp, 7810b912fc9SVladimir Oltean .port_change_mtu = felix_change_mtu, 7820b912fc9SVladimir Oltean .port_max_mtu = felix_get_max_mtu, 783fc411eaaSVladimir Oltean .port_policer_add = felix_port_policer_add, 784fc411eaaSVladimir Oltean .port_policer_del = felix_port_policer_del, 78507d985eeSVladimir Oltean .cls_flower_add = felix_cls_flower_add, 78607d985eeSVladimir Oltean .cls_flower_del = felix_cls_flower_del, 78707d985eeSVladimir Oltean .cls_flower_stats = felix_cls_flower_stats, 788*de143c0eSXiaoliang Yang .port_setup_tc = felix_port_setup_tc, 78956051948SVladimir Oltean }; 79056051948SVladimir Oltean 79156051948SVladimir Oltean static struct felix_info *felix_instance_tbl[] = { 79256051948SVladimir Oltean [FELIX_INSTANCE_VSC9959] = &felix_info_vsc9959, 79356051948SVladimir Oltean }; 79456051948SVladimir Oltean 795c0bcf537SYangbo Lu static irqreturn_t felix_irq_handler(int irq, void *data) 796c0bcf537SYangbo Lu { 797c0bcf537SYangbo Lu struct ocelot *ocelot = (struct ocelot *)data; 798c0bcf537SYangbo Lu 799c0bcf537SYangbo Lu /* The INTB interrupt is used for both PTP TX timestamp interrupt 800c0bcf537SYangbo Lu * and preemption status change interrupt on each port. 801c0bcf537SYangbo Lu * 802c0bcf537SYangbo Lu * - Get txtstamp if have 803c0bcf537SYangbo Lu * - TODO: handle preemption. Without handling it, driver may get 804c0bcf537SYangbo Lu * interrupt storm. 805c0bcf537SYangbo Lu */ 806c0bcf537SYangbo Lu 807c0bcf537SYangbo Lu ocelot_get_txtstamp(ocelot); 808c0bcf537SYangbo Lu 809c0bcf537SYangbo Lu return IRQ_HANDLED; 810c0bcf537SYangbo Lu } 811c0bcf537SYangbo Lu 81256051948SVladimir Oltean static int felix_pci_probe(struct pci_dev *pdev, 81356051948SVladimir Oltean const struct pci_device_id *id) 81456051948SVladimir Oltean { 81556051948SVladimir Oltean enum felix_instance instance = id->driver_data; 81656051948SVladimir Oltean struct dsa_switch *ds; 81756051948SVladimir Oltean struct ocelot *ocelot; 81856051948SVladimir Oltean struct felix *felix; 81956051948SVladimir Oltean int err; 82056051948SVladimir Oltean 821e90c9fceSMichael Walle if (pdev->dev.of_node && !of_device_is_available(pdev->dev.of_node)) { 822e90c9fceSMichael Walle dev_info(&pdev->dev, "device is disabled, skipping\n"); 823e90c9fceSMichael Walle return -ENODEV; 824e90c9fceSMichael Walle } 825e90c9fceSMichael Walle 82656051948SVladimir Oltean err = pci_enable_device(pdev); 82756051948SVladimir Oltean if (err) { 82856051948SVladimir Oltean dev_err(&pdev->dev, "device enable failed\n"); 82956051948SVladimir Oltean goto err_pci_enable; 83056051948SVladimir Oltean } 83156051948SVladimir Oltean 83256051948SVladimir Oltean /* set up for high or low dma */ 83356051948SVladimir Oltean err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); 83456051948SVladimir Oltean if (err) { 83556051948SVladimir Oltean err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); 83656051948SVladimir Oltean if (err) { 83756051948SVladimir Oltean dev_err(&pdev->dev, 83856051948SVladimir Oltean "DMA configuration failed: 0x%x\n", err); 83956051948SVladimir Oltean goto err_dma; 84056051948SVladimir Oltean } 84156051948SVladimir Oltean } 84256051948SVladimir Oltean 84356051948SVladimir Oltean felix = kzalloc(sizeof(struct felix), GFP_KERNEL); 84456051948SVladimir Oltean if (!felix) { 84556051948SVladimir Oltean err = -ENOMEM; 84656051948SVladimir Oltean dev_err(&pdev->dev, "Failed to allocate driver memory\n"); 84756051948SVladimir Oltean goto err_alloc_felix; 84856051948SVladimir Oltean } 84956051948SVladimir Oltean 85056051948SVladimir Oltean pci_set_drvdata(pdev, felix); 85156051948SVladimir Oltean ocelot = &felix->ocelot; 85256051948SVladimir Oltean ocelot->dev = &pdev->dev; 85356051948SVladimir Oltean felix->pdev = pdev; 85456051948SVladimir Oltean felix->info = felix_instance_tbl[instance]; 85556051948SVladimir Oltean 85656051948SVladimir Oltean pci_set_master(pdev); 85756051948SVladimir Oltean 858c0bcf537SYangbo Lu err = devm_request_threaded_irq(&pdev->dev, pdev->irq, NULL, 859c0bcf537SYangbo Lu &felix_irq_handler, IRQF_ONESHOT, 860c0bcf537SYangbo Lu "felix-intb", ocelot); 861c0bcf537SYangbo Lu if (err) { 862c0bcf537SYangbo Lu dev_err(&pdev->dev, "Failed to request irq\n"); 863c0bcf537SYangbo Lu goto err_alloc_irq; 864c0bcf537SYangbo Lu } 865c0bcf537SYangbo Lu 866c0bcf537SYangbo Lu ocelot->ptp = 1; 867c0bcf537SYangbo Lu 86856051948SVladimir Oltean ds = kzalloc(sizeof(struct dsa_switch), GFP_KERNEL); 86956051948SVladimir Oltean if (!ds) { 87056051948SVladimir Oltean err = -ENOMEM; 87156051948SVladimir Oltean dev_err(&pdev->dev, "Failed to allocate DSA switch\n"); 87256051948SVladimir Oltean goto err_alloc_ds; 87356051948SVladimir Oltean } 87456051948SVladimir Oltean 87556051948SVladimir Oltean ds->dev = &pdev->dev; 87656051948SVladimir Oltean ds->num_ports = felix->info->num_ports; 877*de143c0eSXiaoliang Yang ds->num_tx_queues = felix->info->num_tx_queues; 87856051948SVladimir Oltean ds->ops = &felix_switch_ops; 87956051948SVladimir Oltean ds->priv = ocelot; 88056051948SVladimir Oltean felix->ds = ds; 88156051948SVladimir Oltean 88256051948SVladimir Oltean err = dsa_register_switch(ds); 88356051948SVladimir Oltean if (err) { 88456051948SVladimir Oltean dev_err(&pdev->dev, "Failed to register DSA switch: %d\n", err); 88556051948SVladimir Oltean goto err_register_ds; 88656051948SVladimir Oltean } 88756051948SVladimir Oltean 88856051948SVladimir Oltean return 0; 88956051948SVladimir Oltean 89056051948SVladimir Oltean err_register_ds: 89156051948SVladimir Oltean kfree(ds); 89256051948SVladimir Oltean err_alloc_ds: 893c0bcf537SYangbo Lu err_alloc_irq: 89456051948SVladimir Oltean err_alloc_felix: 89556051948SVladimir Oltean kfree(felix); 89656051948SVladimir Oltean err_dma: 89756051948SVladimir Oltean pci_disable_device(pdev); 89856051948SVladimir Oltean err_pci_enable: 89956051948SVladimir Oltean return err; 90056051948SVladimir Oltean } 90156051948SVladimir Oltean 90256051948SVladimir Oltean static void felix_pci_remove(struct pci_dev *pdev) 90356051948SVladimir Oltean { 90456051948SVladimir Oltean struct felix *felix; 90556051948SVladimir Oltean 90656051948SVladimir Oltean felix = pci_get_drvdata(pdev); 90756051948SVladimir Oltean 90856051948SVladimir Oltean dsa_unregister_switch(felix->ds); 90956051948SVladimir Oltean 91056051948SVladimir Oltean kfree(felix->ds); 91156051948SVladimir Oltean kfree(felix); 91256051948SVladimir Oltean 91356051948SVladimir Oltean pci_disable_device(pdev); 91456051948SVladimir Oltean } 91556051948SVladimir Oltean 91656051948SVladimir Oltean static struct pci_device_id felix_ids[] = { 91756051948SVladimir Oltean { 91856051948SVladimir Oltean /* NXP LS1028A */ 91956051948SVladimir Oltean PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, 0xEEF0), 92056051948SVladimir Oltean .driver_data = FELIX_INSTANCE_VSC9959, 92156051948SVladimir Oltean }, 92256051948SVladimir Oltean { 0, } 92356051948SVladimir Oltean }; 92456051948SVladimir Oltean MODULE_DEVICE_TABLE(pci, felix_ids); 92556051948SVladimir Oltean 92656051948SVladimir Oltean static struct pci_driver felix_pci_driver = { 92756051948SVladimir Oltean .name = KBUILD_MODNAME, 92856051948SVladimir Oltean .id_table = felix_ids, 92956051948SVladimir Oltean .probe = felix_pci_probe, 93056051948SVladimir Oltean .remove = felix_pci_remove, 93156051948SVladimir Oltean }; 93256051948SVladimir Oltean 93356051948SVladimir Oltean module_pci_driver(felix_pci_driver); 93456051948SVladimir Oltean 93556051948SVladimir Oltean MODULE_DESCRIPTION("Felix Switch driver"); 93656051948SVladimir Oltean MODULE_LICENSE("GPL v2"); 937