156051948SVladimir Oltean // SPDX-License-Identifier: GPL-2.0 256051948SVladimir Oltean /* Copyright 2019 NXP Semiconductors 356051948SVladimir Oltean */ 456051948SVladimir Oltean #include <uapi/linux/if_bridge.h> 556051948SVladimir Oltean #include <soc/mscc/ocelot.h> 6*c0bcf537SYangbo Lu #include <linux/packing.h> 756051948SVladimir Oltean #include <linux/module.h> 856051948SVladimir Oltean #include <linux/pci.h> 956051948SVladimir Oltean #include <linux/of.h> 1056051948SVladimir Oltean #include <net/dsa.h> 1156051948SVladimir Oltean #include "felix.h" 1256051948SVladimir Oltean 1356051948SVladimir Oltean static enum dsa_tag_protocol felix_get_tag_protocol(struct dsa_switch *ds, 1456051948SVladimir Oltean int port) 1556051948SVladimir Oltean { 1656051948SVladimir Oltean return DSA_TAG_PROTO_OCELOT; 1756051948SVladimir Oltean } 1856051948SVladimir Oltean 1956051948SVladimir Oltean static int felix_set_ageing_time(struct dsa_switch *ds, 2056051948SVladimir Oltean unsigned int ageing_time) 2156051948SVladimir Oltean { 2256051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 2356051948SVladimir Oltean 2456051948SVladimir Oltean ocelot_set_ageing_time(ocelot, ageing_time); 2556051948SVladimir Oltean 2656051948SVladimir Oltean return 0; 2756051948SVladimir Oltean } 2856051948SVladimir Oltean 2956051948SVladimir Oltean static void felix_adjust_link(struct dsa_switch *ds, int port, 3056051948SVladimir Oltean struct phy_device *phydev) 3156051948SVladimir Oltean { 3256051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 3356051948SVladimir Oltean 3456051948SVladimir Oltean ocelot_adjust_link(ocelot, port, phydev); 3556051948SVladimir Oltean } 3656051948SVladimir Oltean 3756051948SVladimir Oltean static int felix_fdb_dump(struct dsa_switch *ds, int port, 3856051948SVladimir Oltean dsa_fdb_dump_cb_t *cb, void *data) 3956051948SVladimir Oltean { 4056051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 4156051948SVladimir Oltean 4256051948SVladimir Oltean return ocelot_fdb_dump(ocelot, port, cb, data); 4356051948SVladimir Oltean } 4456051948SVladimir Oltean 4556051948SVladimir Oltean static int felix_fdb_add(struct dsa_switch *ds, int port, 4656051948SVladimir Oltean const unsigned char *addr, u16 vid) 4756051948SVladimir Oltean { 4856051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 4956051948SVladimir Oltean bool vlan_aware; 5056051948SVladimir Oltean 5156051948SVladimir Oltean vlan_aware = dsa_port_is_vlan_filtering(dsa_to_port(ds, port)); 5256051948SVladimir Oltean 5356051948SVladimir Oltean return ocelot_fdb_add(ocelot, port, addr, vid, vlan_aware); 5456051948SVladimir Oltean } 5556051948SVladimir Oltean 5656051948SVladimir Oltean static int felix_fdb_del(struct dsa_switch *ds, int port, 5756051948SVladimir Oltean const unsigned char *addr, u16 vid) 5856051948SVladimir Oltean { 5956051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 6056051948SVladimir Oltean 6156051948SVladimir Oltean return ocelot_fdb_del(ocelot, port, addr, vid); 6256051948SVladimir Oltean } 6356051948SVladimir Oltean 6456051948SVladimir Oltean static void felix_bridge_stp_state_set(struct dsa_switch *ds, int port, 6556051948SVladimir Oltean u8 state) 6656051948SVladimir Oltean { 6756051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 6856051948SVladimir Oltean 6956051948SVladimir Oltean return ocelot_bridge_stp_state_set(ocelot, port, state); 7056051948SVladimir Oltean } 7156051948SVladimir Oltean 7256051948SVladimir Oltean static int felix_bridge_join(struct dsa_switch *ds, int port, 7356051948SVladimir Oltean struct net_device *br) 7456051948SVladimir Oltean { 7556051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 7656051948SVladimir Oltean 7756051948SVladimir Oltean return ocelot_port_bridge_join(ocelot, port, br); 7856051948SVladimir Oltean } 7956051948SVladimir Oltean 8056051948SVladimir Oltean static void felix_bridge_leave(struct dsa_switch *ds, int port, 8156051948SVladimir Oltean struct net_device *br) 8256051948SVladimir Oltean { 8356051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 8456051948SVladimir Oltean 8556051948SVladimir Oltean ocelot_port_bridge_leave(ocelot, port, br); 8656051948SVladimir Oltean } 8756051948SVladimir Oltean 8856051948SVladimir Oltean /* This callback needs to be present */ 8956051948SVladimir Oltean static int felix_vlan_prepare(struct dsa_switch *ds, int port, 9056051948SVladimir Oltean const struct switchdev_obj_port_vlan *vlan) 9156051948SVladimir Oltean { 9256051948SVladimir Oltean return 0; 9356051948SVladimir Oltean } 9456051948SVladimir Oltean 9556051948SVladimir Oltean static int felix_vlan_filtering(struct dsa_switch *ds, int port, bool enabled) 9656051948SVladimir Oltean { 9756051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 9856051948SVladimir Oltean 9956051948SVladimir Oltean ocelot_port_vlan_filtering(ocelot, port, enabled); 10056051948SVladimir Oltean 10156051948SVladimir Oltean return 0; 10256051948SVladimir Oltean } 10356051948SVladimir Oltean 10456051948SVladimir Oltean static void felix_vlan_add(struct dsa_switch *ds, int port, 10556051948SVladimir Oltean const struct switchdev_obj_port_vlan *vlan) 10656051948SVladimir Oltean { 10756051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 10856051948SVladimir Oltean u16 vid; 10956051948SVladimir Oltean int err; 11056051948SVladimir Oltean 11156051948SVladimir Oltean for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) { 11256051948SVladimir Oltean err = ocelot_vlan_add(ocelot, port, vid, 11356051948SVladimir Oltean vlan->flags & BRIDGE_VLAN_INFO_PVID, 11456051948SVladimir Oltean vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED); 11556051948SVladimir Oltean if (err) { 11656051948SVladimir Oltean dev_err(ds->dev, "Failed to add VLAN %d to port %d: %d\n", 11756051948SVladimir Oltean vid, port, err); 11856051948SVladimir Oltean return; 11956051948SVladimir Oltean } 12056051948SVladimir Oltean } 12156051948SVladimir Oltean } 12256051948SVladimir Oltean 12356051948SVladimir Oltean static int felix_vlan_del(struct dsa_switch *ds, int port, 12456051948SVladimir Oltean const struct switchdev_obj_port_vlan *vlan) 12556051948SVladimir Oltean { 12656051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 12756051948SVladimir Oltean u16 vid; 12856051948SVladimir Oltean int err; 12956051948SVladimir Oltean 13056051948SVladimir Oltean for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) { 13156051948SVladimir Oltean err = ocelot_vlan_del(ocelot, port, vid); 13256051948SVladimir Oltean if (err) { 13356051948SVladimir Oltean dev_err(ds->dev, "Failed to remove VLAN %d from port %d: %d\n", 13456051948SVladimir Oltean vid, port, err); 13556051948SVladimir Oltean return err; 13656051948SVladimir Oltean } 13756051948SVladimir Oltean } 13856051948SVladimir Oltean return 0; 13956051948SVladimir Oltean } 14056051948SVladimir Oltean 14156051948SVladimir Oltean static int felix_port_enable(struct dsa_switch *ds, int port, 14256051948SVladimir Oltean struct phy_device *phy) 14356051948SVladimir Oltean { 14456051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 14556051948SVladimir Oltean 14656051948SVladimir Oltean ocelot_port_enable(ocelot, port, phy); 14756051948SVladimir Oltean 14856051948SVladimir Oltean return 0; 14956051948SVladimir Oltean } 15056051948SVladimir Oltean 15156051948SVladimir Oltean static void felix_port_disable(struct dsa_switch *ds, int port) 15256051948SVladimir Oltean { 15356051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 15456051948SVladimir Oltean 15556051948SVladimir Oltean return ocelot_port_disable(ocelot, port); 15656051948SVladimir Oltean } 15756051948SVladimir Oltean 15856051948SVladimir Oltean static void felix_get_strings(struct dsa_switch *ds, int port, 15956051948SVladimir Oltean u32 stringset, u8 *data) 16056051948SVladimir Oltean { 16156051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 16256051948SVladimir Oltean 16356051948SVladimir Oltean return ocelot_get_strings(ocelot, port, stringset, data); 16456051948SVladimir Oltean } 16556051948SVladimir Oltean 16656051948SVladimir Oltean static void felix_get_ethtool_stats(struct dsa_switch *ds, int port, u64 *data) 16756051948SVladimir Oltean { 16856051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 16956051948SVladimir Oltean 17056051948SVladimir Oltean ocelot_get_ethtool_stats(ocelot, port, data); 17156051948SVladimir Oltean } 17256051948SVladimir Oltean 17356051948SVladimir Oltean static int felix_get_sset_count(struct dsa_switch *ds, int port, int sset) 17456051948SVladimir Oltean { 17556051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 17656051948SVladimir Oltean 17756051948SVladimir Oltean return ocelot_get_sset_count(ocelot, port, sset); 17856051948SVladimir Oltean } 17956051948SVladimir Oltean 18056051948SVladimir Oltean static int felix_get_ts_info(struct dsa_switch *ds, int port, 18156051948SVladimir Oltean struct ethtool_ts_info *info) 18256051948SVladimir Oltean { 18356051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 18456051948SVladimir Oltean 18556051948SVladimir Oltean return ocelot_get_ts_info(ocelot, port, info); 18656051948SVladimir Oltean } 18756051948SVladimir Oltean 18856051948SVladimir Oltean static int felix_init_structs(struct felix *felix, int num_phys_ports) 18956051948SVladimir Oltean { 19056051948SVladimir Oltean struct ocelot *ocelot = &felix->ocelot; 19156051948SVladimir Oltean resource_size_t base; 19256051948SVladimir Oltean int port, i, err; 19356051948SVladimir Oltean 19456051948SVladimir Oltean ocelot->num_phys_ports = num_phys_ports; 19556051948SVladimir Oltean ocelot->ports = devm_kcalloc(ocelot->dev, num_phys_ports, 19656051948SVladimir Oltean sizeof(struct ocelot_port *), GFP_KERNEL); 19756051948SVladimir Oltean if (!ocelot->ports) 19856051948SVladimir Oltean return -ENOMEM; 19956051948SVladimir Oltean 20056051948SVladimir Oltean ocelot->map = felix->info->map; 20156051948SVladimir Oltean ocelot->stats_layout = felix->info->stats_layout; 20256051948SVladimir Oltean ocelot->num_stats = felix->info->num_stats; 20356051948SVladimir Oltean ocelot->shared_queue_sz = felix->info->shared_queue_sz; 20456051948SVladimir Oltean ocelot->ops = felix->info->ops; 20556051948SVladimir Oltean 20656051948SVladimir Oltean base = pci_resource_start(felix->pdev, felix->info->pci_bar); 20756051948SVladimir Oltean 20856051948SVladimir Oltean for (i = 0; i < TARGET_MAX; i++) { 20956051948SVladimir Oltean struct regmap *target; 21056051948SVladimir Oltean struct resource *res; 21156051948SVladimir Oltean 21256051948SVladimir Oltean if (!felix->info->target_io_res[i].name) 21356051948SVladimir Oltean continue; 21456051948SVladimir Oltean 21556051948SVladimir Oltean res = &felix->info->target_io_res[i]; 21656051948SVladimir Oltean res->flags = IORESOURCE_MEM; 21756051948SVladimir Oltean res->start += base; 21856051948SVladimir Oltean res->end += base; 21956051948SVladimir Oltean 22056051948SVladimir Oltean target = ocelot_regmap_init(ocelot, res); 22156051948SVladimir Oltean if (IS_ERR(target)) { 22256051948SVladimir Oltean dev_err(ocelot->dev, 22356051948SVladimir Oltean "Failed to map device memory space\n"); 22456051948SVladimir Oltean return PTR_ERR(target); 22556051948SVladimir Oltean } 22656051948SVladimir Oltean 22756051948SVladimir Oltean ocelot->targets[i] = target; 22856051948SVladimir Oltean } 22956051948SVladimir Oltean 23056051948SVladimir Oltean err = ocelot_regfields_init(ocelot, felix->info->regfields); 23156051948SVladimir Oltean if (err) { 23256051948SVladimir Oltean dev_err(ocelot->dev, "failed to init reg fields map\n"); 23356051948SVladimir Oltean return err; 23456051948SVladimir Oltean } 23556051948SVladimir Oltean 23656051948SVladimir Oltean for (port = 0; port < num_phys_ports; port++) { 23756051948SVladimir Oltean struct ocelot_port *ocelot_port; 23856051948SVladimir Oltean void __iomem *port_regs; 23956051948SVladimir Oltean struct resource *res; 24056051948SVladimir Oltean 24156051948SVladimir Oltean ocelot_port = devm_kzalloc(ocelot->dev, 24256051948SVladimir Oltean sizeof(struct ocelot_port), 24356051948SVladimir Oltean GFP_KERNEL); 24456051948SVladimir Oltean if (!ocelot_port) { 24556051948SVladimir Oltean dev_err(ocelot->dev, 24656051948SVladimir Oltean "failed to allocate port memory\n"); 24756051948SVladimir Oltean return -ENOMEM; 24856051948SVladimir Oltean } 24956051948SVladimir Oltean 25056051948SVladimir Oltean res = &felix->info->port_io_res[port]; 25156051948SVladimir Oltean res->flags = IORESOURCE_MEM; 25256051948SVladimir Oltean res->start += base; 25356051948SVladimir Oltean res->end += base; 25456051948SVladimir Oltean 25556051948SVladimir Oltean port_regs = devm_ioremap_resource(ocelot->dev, res); 25656051948SVladimir Oltean if (IS_ERR(port_regs)) { 25756051948SVladimir Oltean dev_err(ocelot->dev, 25856051948SVladimir Oltean "failed to map registers for port %d\n", port); 25956051948SVladimir Oltean return PTR_ERR(port_regs); 26056051948SVladimir Oltean } 26156051948SVladimir Oltean 26256051948SVladimir Oltean ocelot_port->ocelot = ocelot; 26356051948SVladimir Oltean ocelot_port->regs = port_regs; 26456051948SVladimir Oltean ocelot->ports[port] = ocelot_port; 26556051948SVladimir Oltean } 26656051948SVladimir Oltean 26756051948SVladimir Oltean return 0; 26856051948SVladimir Oltean } 26956051948SVladimir Oltean 27056051948SVladimir Oltean /* Hardware initialization done here so that we can allocate structures with 27156051948SVladimir Oltean * devm without fear of dsa_register_switch returning -EPROBE_DEFER and causing 27256051948SVladimir Oltean * us to allocate structures twice (leak memory) and map PCI memory twice 27356051948SVladimir Oltean * (which will not work). 27456051948SVladimir Oltean */ 27556051948SVladimir Oltean static int felix_setup(struct dsa_switch *ds) 27656051948SVladimir Oltean { 27756051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 27856051948SVladimir Oltean struct felix *felix = ocelot_to_felix(ocelot); 27956051948SVladimir Oltean int port, err; 28056051948SVladimir Oltean 28156051948SVladimir Oltean err = felix_init_structs(felix, ds->num_ports); 28256051948SVladimir Oltean if (err) 28356051948SVladimir Oltean return err; 28456051948SVladimir Oltean 28556051948SVladimir Oltean ocelot_init(ocelot); 28656051948SVladimir Oltean 28756051948SVladimir Oltean for (port = 0; port < ds->num_ports; port++) { 28856051948SVladimir Oltean ocelot_init_port(ocelot, port); 28956051948SVladimir Oltean 290b8fc7177SVladimir Oltean if (dsa_is_cpu_port(ds, port)) 29156051948SVladimir Oltean ocelot_set_cpu_port(ocelot, port, 29256051948SVladimir Oltean OCELOT_TAG_PREFIX_NONE, 29356051948SVladimir Oltean OCELOT_TAG_PREFIX_LONG); 29456051948SVladimir Oltean } 29556051948SVladimir Oltean 29656051948SVladimir Oltean return 0; 29756051948SVladimir Oltean } 29856051948SVladimir Oltean 29956051948SVladimir Oltean static void felix_teardown(struct dsa_switch *ds) 30056051948SVladimir Oltean { 30156051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 30256051948SVladimir Oltean 30356051948SVladimir Oltean /* stop workqueue thread */ 30456051948SVladimir Oltean ocelot_deinit(ocelot); 30556051948SVladimir Oltean } 30656051948SVladimir Oltean 307*c0bcf537SYangbo Lu static int felix_hwtstamp_get(struct dsa_switch *ds, int port, 308*c0bcf537SYangbo Lu struct ifreq *ifr) 309*c0bcf537SYangbo Lu { 310*c0bcf537SYangbo Lu struct ocelot *ocelot = ds->priv; 311*c0bcf537SYangbo Lu 312*c0bcf537SYangbo Lu return ocelot_hwstamp_get(ocelot, port, ifr); 313*c0bcf537SYangbo Lu } 314*c0bcf537SYangbo Lu 315*c0bcf537SYangbo Lu static int felix_hwtstamp_set(struct dsa_switch *ds, int port, 316*c0bcf537SYangbo Lu struct ifreq *ifr) 317*c0bcf537SYangbo Lu { 318*c0bcf537SYangbo Lu struct ocelot *ocelot = ds->priv; 319*c0bcf537SYangbo Lu 320*c0bcf537SYangbo Lu return ocelot_hwstamp_set(ocelot, port, ifr); 321*c0bcf537SYangbo Lu } 322*c0bcf537SYangbo Lu 323*c0bcf537SYangbo Lu static bool felix_rxtstamp(struct dsa_switch *ds, int port, 324*c0bcf537SYangbo Lu struct sk_buff *skb, unsigned int type) 325*c0bcf537SYangbo Lu { 326*c0bcf537SYangbo Lu struct skb_shared_hwtstamps *shhwtstamps; 327*c0bcf537SYangbo Lu struct ocelot *ocelot = ds->priv; 328*c0bcf537SYangbo Lu u8 *extraction = skb->data - ETH_HLEN - OCELOT_TAG_LEN; 329*c0bcf537SYangbo Lu u32 tstamp_lo, tstamp_hi; 330*c0bcf537SYangbo Lu struct timespec64 ts; 331*c0bcf537SYangbo Lu u64 tstamp, val; 332*c0bcf537SYangbo Lu 333*c0bcf537SYangbo Lu ocelot_ptp_gettime64(&ocelot->ptp_info, &ts); 334*c0bcf537SYangbo Lu tstamp = ktime_set(ts.tv_sec, ts.tv_nsec); 335*c0bcf537SYangbo Lu 336*c0bcf537SYangbo Lu packing(extraction, &val, 116, 85, OCELOT_TAG_LEN, UNPACK, 0); 337*c0bcf537SYangbo Lu tstamp_lo = (u32)val; 338*c0bcf537SYangbo Lu 339*c0bcf537SYangbo Lu tstamp_hi = tstamp >> 32; 340*c0bcf537SYangbo Lu if ((tstamp & 0xffffffff) < tstamp_lo) 341*c0bcf537SYangbo Lu tstamp_hi--; 342*c0bcf537SYangbo Lu 343*c0bcf537SYangbo Lu tstamp = ((u64)tstamp_hi << 32) | tstamp_lo; 344*c0bcf537SYangbo Lu 345*c0bcf537SYangbo Lu shhwtstamps = skb_hwtstamps(skb); 346*c0bcf537SYangbo Lu memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps)); 347*c0bcf537SYangbo Lu shhwtstamps->hwtstamp = tstamp; 348*c0bcf537SYangbo Lu return false; 349*c0bcf537SYangbo Lu } 350*c0bcf537SYangbo Lu 351*c0bcf537SYangbo Lu bool felix_txtstamp(struct dsa_switch *ds, int port, 352*c0bcf537SYangbo Lu struct sk_buff *clone, unsigned int type) 353*c0bcf537SYangbo Lu { 354*c0bcf537SYangbo Lu struct ocelot *ocelot = ds->priv; 355*c0bcf537SYangbo Lu struct ocelot_port *ocelot_port = ocelot->ports[port]; 356*c0bcf537SYangbo Lu 357*c0bcf537SYangbo Lu if (!ocelot_port_add_txtstamp_skb(ocelot_port, clone)) 358*c0bcf537SYangbo Lu return true; 359*c0bcf537SYangbo Lu 360*c0bcf537SYangbo Lu return false; 361*c0bcf537SYangbo Lu } 362*c0bcf537SYangbo Lu 36356051948SVladimir Oltean static const struct dsa_switch_ops felix_switch_ops = { 36456051948SVladimir Oltean .get_tag_protocol = felix_get_tag_protocol, 36556051948SVladimir Oltean .setup = felix_setup, 36656051948SVladimir Oltean .teardown = felix_teardown, 36756051948SVladimir Oltean .set_ageing_time = felix_set_ageing_time, 36856051948SVladimir Oltean .get_strings = felix_get_strings, 36956051948SVladimir Oltean .get_ethtool_stats = felix_get_ethtool_stats, 37056051948SVladimir Oltean .get_sset_count = felix_get_sset_count, 37156051948SVladimir Oltean .get_ts_info = felix_get_ts_info, 37256051948SVladimir Oltean .adjust_link = felix_adjust_link, 37356051948SVladimir Oltean .port_enable = felix_port_enable, 37456051948SVladimir Oltean .port_disable = felix_port_disable, 37556051948SVladimir Oltean .port_fdb_dump = felix_fdb_dump, 37656051948SVladimir Oltean .port_fdb_add = felix_fdb_add, 37756051948SVladimir Oltean .port_fdb_del = felix_fdb_del, 37856051948SVladimir Oltean .port_bridge_join = felix_bridge_join, 37956051948SVladimir Oltean .port_bridge_leave = felix_bridge_leave, 38056051948SVladimir Oltean .port_stp_state_set = felix_bridge_stp_state_set, 38156051948SVladimir Oltean .port_vlan_prepare = felix_vlan_prepare, 38256051948SVladimir Oltean .port_vlan_filtering = felix_vlan_filtering, 38356051948SVladimir Oltean .port_vlan_add = felix_vlan_add, 38456051948SVladimir Oltean .port_vlan_del = felix_vlan_del, 385*c0bcf537SYangbo Lu .port_hwtstamp_get = felix_hwtstamp_get, 386*c0bcf537SYangbo Lu .port_hwtstamp_set = felix_hwtstamp_set, 387*c0bcf537SYangbo Lu .port_rxtstamp = felix_rxtstamp, 388*c0bcf537SYangbo Lu .port_txtstamp = felix_txtstamp, 38956051948SVladimir Oltean }; 39056051948SVladimir Oltean 39156051948SVladimir Oltean static struct felix_info *felix_instance_tbl[] = { 39256051948SVladimir Oltean [FELIX_INSTANCE_VSC9959] = &felix_info_vsc9959, 39356051948SVladimir Oltean }; 39456051948SVladimir Oltean 395*c0bcf537SYangbo Lu static irqreturn_t felix_irq_handler(int irq, void *data) 396*c0bcf537SYangbo Lu { 397*c0bcf537SYangbo Lu struct ocelot *ocelot = (struct ocelot *)data; 398*c0bcf537SYangbo Lu 399*c0bcf537SYangbo Lu /* The INTB interrupt is used for both PTP TX timestamp interrupt 400*c0bcf537SYangbo Lu * and preemption status change interrupt on each port. 401*c0bcf537SYangbo Lu * 402*c0bcf537SYangbo Lu * - Get txtstamp if have 403*c0bcf537SYangbo Lu * - TODO: handle preemption. Without handling it, driver may get 404*c0bcf537SYangbo Lu * interrupt storm. 405*c0bcf537SYangbo Lu */ 406*c0bcf537SYangbo Lu 407*c0bcf537SYangbo Lu ocelot_get_txtstamp(ocelot); 408*c0bcf537SYangbo Lu 409*c0bcf537SYangbo Lu return IRQ_HANDLED; 410*c0bcf537SYangbo Lu } 411*c0bcf537SYangbo Lu 41256051948SVladimir Oltean static int felix_pci_probe(struct pci_dev *pdev, 41356051948SVladimir Oltean const struct pci_device_id *id) 41456051948SVladimir Oltean { 41556051948SVladimir Oltean enum felix_instance instance = id->driver_data; 41656051948SVladimir Oltean struct dsa_switch *ds; 41756051948SVladimir Oltean struct ocelot *ocelot; 41856051948SVladimir Oltean struct felix *felix; 41956051948SVladimir Oltean int err; 42056051948SVladimir Oltean 42156051948SVladimir Oltean err = pci_enable_device(pdev); 42256051948SVladimir Oltean if (err) { 42356051948SVladimir Oltean dev_err(&pdev->dev, "device enable failed\n"); 42456051948SVladimir Oltean goto err_pci_enable; 42556051948SVladimir Oltean } 42656051948SVladimir Oltean 42756051948SVladimir Oltean /* set up for high or low dma */ 42856051948SVladimir Oltean err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); 42956051948SVladimir Oltean if (err) { 43056051948SVladimir Oltean err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); 43156051948SVladimir Oltean if (err) { 43256051948SVladimir Oltean dev_err(&pdev->dev, 43356051948SVladimir Oltean "DMA configuration failed: 0x%x\n", err); 43456051948SVladimir Oltean goto err_dma; 43556051948SVladimir Oltean } 43656051948SVladimir Oltean } 43756051948SVladimir Oltean 43856051948SVladimir Oltean felix = kzalloc(sizeof(struct felix), GFP_KERNEL); 43956051948SVladimir Oltean if (!felix) { 44056051948SVladimir Oltean err = -ENOMEM; 44156051948SVladimir Oltean dev_err(&pdev->dev, "Failed to allocate driver memory\n"); 44256051948SVladimir Oltean goto err_alloc_felix; 44356051948SVladimir Oltean } 44456051948SVladimir Oltean 44556051948SVladimir Oltean pci_set_drvdata(pdev, felix); 44656051948SVladimir Oltean ocelot = &felix->ocelot; 44756051948SVladimir Oltean ocelot->dev = &pdev->dev; 44856051948SVladimir Oltean felix->pdev = pdev; 44956051948SVladimir Oltean felix->info = felix_instance_tbl[instance]; 45056051948SVladimir Oltean 45156051948SVladimir Oltean pci_set_master(pdev); 45256051948SVladimir Oltean 453*c0bcf537SYangbo Lu err = devm_request_threaded_irq(&pdev->dev, pdev->irq, NULL, 454*c0bcf537SYangbo Lu &felix_irq_handler, IRQF_ONESHOT, 455*c0bcf537SYangbo Lu "felix-intb", ocelot); 456*c0bcf537SYangbo Lu if (err) { 457*c0bcf537SYangbo Lu dev_err(&pdev->dev, "Failed to request irq\n"); 458*c0bcf537SYangbo Lu goto err_alloc_irq; 459*c0bcf537SYangbo Lu } 460*c0bcf537SYangbo Lu 461*c0bcf537SYangbo Lu ocelot->ptp = 1; 462*c0bcf537SYangbo Lu 46356051948SVladimir Oltean ds = kzalloc(sizeof(struct dsa_switch), GFP_KERNEL); 46456051948SVladimir Oltean if (!ds) { 46556051948SVladimir Oltean err = -ENOMEM; 46656051948SVladimir Oltean dev_err(&pdev->dev, "Failed to allocate DSA switch\n"); 46756051948SVladimir Oltean goto err_alloc_ds; 46856051948SVladimir Oltean } 46956051948SVladimir Oltean 47056051948SVladimir Oltean ds->dev = &pdev->dev; 47156051948SVladimir Oltean ds->num_ports = felix->info->num_ports; 47256051948SVladimir Oltean ds->ops = &felix_switch_ops; 47356051948SVladimir Oltean ds->priv = ocelot; 47456051948SVladimir Oltean felix->ds = ds; 47556051948SVladimir Oltean 47656051948SVladimir Oltean err = dsa_register_switch(ds); 47756051948SVladimir Oltean if (err) { 47856051948SVladimir Oltean dev_err(&pdev->dev, "Failed to register DSA switch: %d\n", err); 47956051948SVladimir Oltean goto err_register_ds; 48056051948SVladimir Oltean } 48156051948SVladimir Oltean 48256051948SVladimir Oltean return 0; 48356051948SVladimir Oltean 48456051948SVladimir Oltean err_register_ds: 48556051948SVladimir Oltean kfree(ds); 48656051948SVladimir Oltean err_alloc_ds: 487*c0bcf537SYangbo Lu err_alloc_irq: 48856051948SVladimir Oltean err_alloc_felix: 48956051948SVladimir Oltean kfree(felix); 49056051948SVladimir Oltean err_dma: 49156051948SVladimir Oltean pci_disable_device(pdev); 49256051948SVladimir Oltean err_pci_enable: 49356051948SVladimir Oltean return err; 49456051948SVladimir Oltean } 49556051948SVladimir Oltean 49656051948SVladimir Oltean static void felix_pci_remove(struct pci_dev *pdev) 49756051948SVladimir Oltean { 49856051948SVladimir Oltean struct felix *felix; 49956051948SVladimir Oltean 50056051948SVladimir Oltean felix = pci_get_drvdata(pdev); 50156051948SVladimir Oltean 50256051948SVladimir Oltean dsa_unregister_switch(felix->ds); 50356051948SVladimir Oltean 50456051948SVladimir Oltean kfree(felix->ds); 50556051948SVladimir Oltean kfree(felix); 50656051948SVladimir Oltean 50756051948SVladimir Oltean pci_disable_device(pdev); 50856051948SVladimir Oltean } 50956051948SVladimir Oltean 51056051948SVladimir Oltean static struct pci_device_id felix_ids[] = { 51156051948SVladimir Oltean { 51256051948SVladimir Oltean /* NXP LS1028A */ 51356051948SVladimir Oltean PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, 0xEEF0), 51456051948SVladimir Oltean .driver_data = FELIX_INSTANCE_VSC9959, 51556051948SVladimir Oltean }, 51656051948SVladimir Oltean { 0, } 51756051948SVladimir Oltean }; 51856051948SVladimir Oltean MODULE_DEVICE_TABLE(pci, felix_ids); 51956051948SVladimir Oltean 52056051948SVladimir Oltean static struct pci_driver felix_pci_driver = { 52156051948SVladimir Oltean .name = KBUILD_MODNAME, 52256051948SVladimir Oltean .id_table = felix_ids, 52356051948SVladimir Oltean .probe = felix_pci_probe, 52456051948SVladimir Oltean .remove = felix_pci_remove, 52556051948SVladimir Oltean }; 52656051948SVladimir Oltean 52756051948SVladimir Oltean module_pci_driver(felix_pci_driver); 52856051948SVladimir Oltean 52956051948SVladimir Oltean MODULE_DESCRIPTION("Felix Switch driver"); 53056051948SVladimir Oltean MODULE_LICENSE("GPL v2"); 531