From aae4e500e106d2ce48d5bdb21210e36efc7460cb Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Sat, 20 Jun 2020 18:43:46 +0300 Subject: net: mscc: ocelot: generalize the "ACE/ACL" names Access Control Lists (and their respective Access Control Entries) are specifically entries in the VCAP IS2, the security enforcement block, according to the documentation. Let's rename the structures and functions to something more generic, so that VCAP IS1 structures (which would otherwise have to be called Ingress Classification Entries) can reuse the same code without confusion. Some renaming that was done: struct ocelot_ace_rule -> struct ocelot_vcap_filter struct ocelot_acl_block -> struct ocelot_vcap_block enum ocelot_ace_type -> enum ocelot_vcap_key_type struct ocelot_ace_vlan -> struct ocelot_vcap_key_vlan enum ocelot_ace_action -> enum ocelot_vcap_action struct ocelot_ace_stats -> struct ocelot_vcap_stats enum ocelot_ace_type -> enum ocelot_vcap_key_type struct ocelot_ace_frame_* -> struct ocelot_vcap_key_* No functional change is intended. Signed-off-by: Vladimir Oltean Signed-off-by: David S. Miller --- include/soc/mscc/ocelot.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include/soc/mscc') diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index 4953e9994df3..fa2c3904049e 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -470,7 +470,7 @@ struct ocelot_ops { int (*reset)(struct ocelot *ocelot); }; -struct ocelot_acl_block { +struct ocelot_vcap_block { struct list_head rules; int count; int pol_lpr; @@ -535,7 +535,7 @@ struct ocelot { struct list_head multicast; - struct ocelot_acl_block acl_block; + struct ocelot_vcap_block block; const struct vcap_field *vcap_is2_keys; const struct vcap_field *vcap_is2_actions; -- cgit v1.2.3 From 209edf95da63a0ad19750769f473f4ea1553d21d Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Sun, 21 Jun 2020 14:46:01 +0300 Subject: net: dsa: felix: call port mdb operations from ocelot This adds the mdb hooks in felix and exports the mdb functions from ocelot. Signed-off-by: Vladimir Oltean Signed-off-by: David S. Miller --- drivers/net/dsa/ocelot/felix.c | 26 ++++++++++++++++++++++++++ drivers/net/ethernet/mscc/ocelot.c | 23 ++++++++--------------- drivers/net/ethernet/mscc/ocelot.h | 5 ----- drivers/net/ethernet/mscc/ocelot_net.c | 26 ++++++++++++++++++++++++++ include/soc/mscc/ocelot.h | 4 ++++ 5 files changed, 64 insertions(+), 20 deletions(-) (limited to 'include/soc/mscc') diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index 66648986e6e3..25046777c993 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -59,6 +59,29 @@ static int felix_fdb_del(struct dsa_switch *ds, int port, return ocelot_fdb_del(ocelot, port, addr, vid); } +/* This callback needs to be present */ +static int felix_mdb_prepare(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_mdb *mdb) +{ + return 0; +} + +static void felix_mdb_add(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_mdb *mdb) +{ + struct ocelot *ocelot = ds->priv; + + ocelot_port_mdb_add(ocelot, port, mdb); +} + +static int felix_mdb_del(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_mdb *mdb) +{ + struct ocelot *ocelot = ds->priv; + + return ocelot_port_mdb_del(ocelot, port, mdb); +} + static void felix_bridge_stp_state_set(struct dsa_switch *ds, int port, u8 state) { @@ -771,6 +794,9 @@ static const struct dsa_switch_ops felix_switch_ops = { .port_fdb_dump = felix_fdb_dump, .port_fdb_add = felix_fdb_add, .port_fdb_del = felix_fdb_del, + .port_mdb_prepare = felix_mdb_prepare, + .port_mdb_add = felix_mdb_add, + .port_mdb_del = felix_mdb_del, .port_bridge_join = felix_bridge_join, .port_bridge_leave = felix_bridge_leave, .port_stp_state_set = felix_bridge_stp_state_set, diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 4aadb65a6af8..468eaf5916e5 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -944,16 +944,12 @@ static struct ocelot_multicast *ocelot_multicast_get(struct ocelot *ocelot, return NULL; } -int ocelot_port_obj_add_mdb(struct net_device *dev, - const struct switchdev_obj_port_mdb *mdb, - struct switchdev_trans *trans) +int ocelot_port_mdb_add(struct ocelot *ocelot, int port, + const struct switchdev_obj_port_mdb *mdb) { - struct ocelot_port_private *priv = netdev_priv(dev); - struct ocelot_port *ocelot_port = &priv->port; - struct ocelot *ocelot = ocelot_port->ocelot; + struct ocelot_port *ocelot_port = ocelot->ports[port]; unsigned char addr[ETH_ALEN]; struct ocelot_multicast *mc; - int port = priv->chip_port; u16 vid = mdb->vid; bool new = false; @@ -991,17 +987,14 @@ int ocelot_port_obj_add_mdb(struct net_device *dev, return ocelot_mact_learn(ocelot, 0, addr, vid, ENTRYTYPE_MACv4); } -EXPORT_SYMBOL(ocelot_port_obj_add_mdb); +EXPORT_SYMBOL(ocelot_port_mdb_add); -int ocelot_port_obj_del_mdb(struct net_device *dev, - const struct switchdev_obj_port_mdb *mdb) +int ocelot_port_mdb_del(struct ocelot *ocelot, int port, + const struct switchdev_obj_port_mdb *mdb) { - struct ocelot_port_private *priv = netdev_priv(dev); - struct ocelot_port *ocelot_port = &priv->port; - struct ocelot *ocelot = ocelot_port->ocelot; + struct ocelot_port *ocelot_port = ocelot->ports[port]; unsigned char addr[ETH_ALEN]; struct ocelot_multicast *mc; - int port = priv->chip_port; u16 vid = mdb->vid; if (port == ocelot->npi) @@ -1032,7 +1025,7 @@ int ocelot_port_obj_del_mdb(struct net_device *dev, return ocelot_mact_learn(ocelot, 0, addr, vid, ENTRYTYPE_MACv4); } -EXPORT_SYMBOL(ocelot_port_obj_del_mdb); +EXPORT_SYMBOL(ocelot_port_mdb_del); int ocelot_port_bridge_join(struct ocelot *ocelot, int port, struct net_device *bridge) diff --git a/drivers/net/ethernet/mscc/ocelot.h b/drivers/net/ethernet/mscc/ocelot.h index 0c23734a87be..be4a41646e5e 100644 --- a/drivers/net/ethernet/mscc/ocelot.h +++ b/drivers/net/ethernet/mscc/ocelot.h @@ -97,11 +97,6 @@ int ocelot_port_lag_join(struct ocelot *ocelot, int port, struct net_device *bond); void ocelot_port_lag_leave(struct ocelot *ocelot, int port, struct net_device *bond); -int ocelot_port_obj_del_mdb(struct net_device *dev, - const struct switchdev_obj_port_mdb *mdb); -int ocelot_port_obj_add_mdb(struct net_device *dev, - const struct switchdev_obj_port_mdb *mdb, - struct switchdev_trans *trans); u32 ocelot_port_readl(struct ocelot_port *port, u32 reg); void ocelot_port_writel(struct ocelot_port *port, u32 val, u32 reg); diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c index 80cb1873e9d9..1bad146a0105 100644 --- a/drivers/net/ethernet/mscc/ocelot_net.c +++ b/drivers/net/ethernet/mscc/ocelot_net.c @@ -795,6 +795,32 @@ static int ocelot_port_vlan_del_vlan(struct net_device *dev, return 0; } +static int ocelot_port_obj_add_mdb(struct net_device *dev, + const struct switchdev_obj_port_mdb *mdb, + struct switchdev_trans *trans) +{ + struct ocelot_port_private *priv = netdev_priv(dev); + struct ocelot_port *ocelot_port = &priv->port; + struct ocelot *ocelot = ocelot_port->ocelot; + int port = priv->chip_port; + + if (switchdev_trans_ph_prepare(trans)) + return 0; + + return ocelot_port_mdb_add(ocelot, port, mdb); +} + +static int ocelot_port_obj_del_mdb(struct net_device *dev, + const struct switchdev_obj_port_mdb *mdb) +{ + struct ocelot_port_private *priv = netdev_priv(dev); + struct ocelot_port *ocelot_port = &priv->port; + struct ocelot *ocelot = ocelot_port->ocelot; + int port = priv->chip_port; + + return ocelot_port_mdb_del(ocelot, port, mdb); +} + static int ocelot_port_obj_add(struct net_device *dev, const struct switchdev_obj *obj, struct switchdev_trans *trans, diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index fa2c3904049e..80415b63ccfa 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -641,5 +641,9 @@ int ocelot_cls_flower_destroy(struct ocelot *ocelot, int port, struct flow_cls_offload *f, bool ingress); int ocelot_cls_flower_stats(struct ocelot *ocelot, int port, struct flow_cls_offload *f, bool ingress); +int ocelot_port_mdb_add(struct ocelot *ocelot, int port, + const struct switchdev_obj_port_mdb *mdb); +int ocelot_port_mdb_del(struct ocelot *ocelot, int port, + const struct switchdev_obj_port_mdb *mdb); #endif -- cgit v1.2.3 From 96b029b004942ecdb50e40d3e45cdc8a3aec9135 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Sun, 21 Jun 2020 14:46:02 +0300 Subject: net: mscc: ocelot: introduce macros for iterating over PGIDs The current iterators are impossible to understand at first glance without switching back and forth between the definitions and their actual use in the for loops. So introduce some convenience names to help readability. Signed-off-by: Vladimir Oltean Signed-off-by: David S. Miller --- drivers/net/ethernet/mscc/ocelot.c | 8 ++++---- drivers/net/ethernet/mscc/ocelot_net.c | 2 +- include/soc/mscc/ocelot.h | 15 +++++++++++++++ 3 files changed, 20 insertions(+), 5 deletions(-) (limited to 'include/soc/mscc') diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 468eaf5916e5..b6254c20f2f0 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -1064,10 +1064,10 @@ static void ocelot_set_aggr_pgids(struct ocelot *ocelot) int i, port, lag; /* Reset destination and aggregation PGIDS */ - for (port = 0; port < ocelot->num_phys_ports; port++) + for_each_unicast_dest_pgid(ocelot, port) ocelot_write_rix(ocelot, BIT(port), ANA_PGID_PGID, port); - for (i = PGID_AGGR; i < PGID_SRC; i++) + for_each_aggr_pgid(ocelot, i) ocelot_write_rix(ocelot, GENMASK(ocelot->num_phys_ports - 1, 0), ANA_PGID_PGID, i); @@ -1089,7 +1089,7 @@ static void ocelot_set_aggr_pgids(struct ocelot *ocelot) aggr_count++; } - for (i = PGID_AGGR; i < PGID_SRC; i++) { + for_each_aggr_pgid(ocelot, i) { u32 ac; ac = ocelot_read_rix(ocelot, ANA_PGID_PGID, i); @@ -1451,7 +1451,7 @@ int ocelot_init(struct ocelot *ocelot) } /* Allow broadcast MAC frames. */ - for (i = ocelot->num_phys_ports + 1; i < PGID_CPU; i++) { + for_each_nonreserved_multicast_dest_pgid(ocelot, i) { u32 val = ANA_PGID_PGID_PGID(GENMASK(ocelot->num_phys_ports - 1, 0)); ocelot_write_rix(ocelot, val, ANA_PGID_PGID, i); diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c index 1bad146a0105..702b42543fb7 100644 --- a/drivers/net/ethernet/mscc/ocelot_net.c +++ b/drivers/net/ethernet/mscc/ocelot_net.c @@ -422,7 +422,7 @@ static void ocelot_set_rx_mode(struct net_device *dev) * forwarded to the CPU port. */ val = GENMASK(ocelot->num_phys_ports - 1, 0); - for (i = ocelot->num_phys_ports + 1; i < PGID_CPU; i++) + for_each_nonreserved_multicast_dest_pgid(ocelot, i) ocelot_write_rix(ocelot, val, ANA_PGID_PGID, i); __dev_mc_sync(dev, ocelot_mc_sync, ocelot_mc_unsync); diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index 80415b63ccfa..e050f8121ba2 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -65,6 +65,21 @@ #define PGID_MCIPV4 62 #define PGID_MCIPV6 63 +#define for_each_unicast_dest_pgid(ocelot, pgid) \ + for ((pgid) = 0; \ + (pgid) < (ocelot)->num_phys_ports; \ + (pgid)++) + +#define for_each_nonreserved_multicast_dest_pgid(ocelot, pgid) \ + for ((pgid) = (ocelot)->num_phys_ports + 1; \ + (pgid) < PGID_CPU; \ + (pgid)++) + +#define for_each_aggr_pgid(ocelot, pgid) \ + for ((pgid) = PGID_AGGR; \ + (pgid) < PGID_SRC; \ + (pgid)++) + /* Aggregation PGIDs, one per Link Aggregation Code */ #define PGID_AGGR 64 -- cgit v1.2.3 From 91c724cfc0cbc049f18c04634ad56080650e93b8 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Mon, 13 Jul 2020 19:57:01 +0300 Subject: net: mscc: ocelot: convert port registers to regmap At the moment, there are some minimal register differences between VSC7514 Ocelot and VSC9959 Felix. To be precise, the PCS1G registers are missing from Felix because it was integrated with an NXP PCS. But with VSC9953 Seville (not yet introduced), the register differences are more pronounced. The MAC registers are located at different offsets within the DEV_GMII target. So we need to refactor the driver to keep a regmap even for per-port registers. The callers of the ocelot_port_readl and ocelot_port_writel were kept unchanged, only the implementation is now more generic. Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/ocelot/felix.c | 13 ++--- drivers/net/dsa/ocelot/felix_vsc9959.c | 47 +++++++++++++++++- drivers/net/ethernet/mscc/ocelot.h | 3 +- drivers/net/ethernet/mscc/ocelot_io.c | 16 +++++- drivers/net/ethernet/mscc/ocelot_net.c | 5 +- drivers/net/ethernet/mscc/ocelot_vsc7514.c | 53 ++++++++++++++++++-- include/soc/mscc/ocelot.h | 42 +++++++++++++++- include/soc/mscc/ocelot_dev.h | 78 ------------------------------ 8 files changed, 158 insertions(+), 99 deletions(-) (limited to 'include/soc/mscc') diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index 75652ed99b24..bf0bd5c7b12c 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -524,7 +524,7 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports) for (port = 0; port < num_phys_ports; port++) { struct ocelot_port *ocelot_port; - void __iomem *port_regs; + struct regmap *target; ocelot_port = devm_kzalloc(ocelot->dev, sizeof(struct ocelot_port), @@ -541,17 +541,18 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports) res.start += switch_base; res.end += switch_base; - port_regs = devm_ioremap_resource(ocelot->dev, &res); - if (IS_ERR(port_regs)) { + target = ocelot_regmap_init(ocelot, &res); + if (IS_ERR(target)) { dev_err(ocelot->dev, - "failed to map registers for port %d\n", port); + "Failed to map memory space for port %d\n", + port); kfree(port_phy_modes); - return PTR_ERR(port_regs); + return PTR_ERR(target); } ocelot_port->phy_mode = port_phy_modes[port]; ocelot_port->ocelot = ocelot; - ocelot_port->regs = port_regs; + ocelot_port->target = target; ocelot->ports[port] = ocelot_port; } diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c index 19614537b1ba..0c54d67a4039 100644 --- a/drivers/net/dsa/ocelot/felix_vsc9959.c +++ b/drivers/net/dsa/ocelot/felix_vsc9959.c @@ -329,7 +329,49 @@ static const u32 vsc9959_gcb_regmap[] = { REG(GCB_SOFT_RST, 0x000004), }; -static const u32 *vsc9959_regmap[] = { +static const u32 vsc9959_dev_gmii_regmap[] = { + REG(DEV_CLOCK_CFG, 0x0), + REG(DEV_PORT_MISC, 0x4), + REG(DEV_EVENTS, 0x8), + REG(DEV_EEE_CFG, 0xc), + REG(DEV_RX_PATH_DELAY, 0x10), + REG(DEV_TX_PATH_DELAY, 0x14), + REG(DEV_PTP_PREDICT_CFG, 0x18), + REG(DEV_MAC_ENA_CFG, 0x1c), + REG(DEV_MAC_MODE_CFG, 0x20), + REG(DEV_MAC_MAXLEN_CFG, 0x24), + REG(DEV_MAC_TAGS_CFG, 0x28), + REG(DEV_MAC_ADV_CHK_CFG, 0x2c), + REG(DEV_MAC_IFG_CFG, 0x30), + REG(DEV_MAC_HDX_CFG, 0x34), + REG(DEV_MAC_DBG_CFG, 0x38), + REG(DEV_MAC_FC_MAC_LOW_CFG, 0x3c), + REG(DEV_MAC_FC_MAC_HIGH_CFG, 0x40), + REG(DEV_MAC_STICKY, 0x44), + REG_RESERVED(PCS1G_CFG), + REG_RESERVED(PCS1G_MODE_CFG), + REG_RESERVED(PCS1G_SD_CFG), + REG_RESERVED(PCS1G_ANEG_CFG), + REG_RESERVED(PCS1G_ANEG_NP_CFG), + REG_RESERVED(PCS1G_LB_CFG), + REG_RESERVED(PCS1G_DBG_CFG), + REG_RESERVED(PCS1G_CDET_CFG), + REG_RESERVED(PCS1G_ANEG_STATUS), + REG_RESERVED(PCS1G_ANEG_NP_STATUS), + REG_RESERVED(PCS1G_LINK_STATUS), + REG_RESERVED(PCS1G_LINK_DOWN_CNT), + REG_RESERVED(PCS1G_STICKY), + REG_RESERVED(PCS1G_DEBUG_STATUS), + REG_RESERVED(PCS1G_LPI_CFG), + REG_RESERVED(PCS1G_LPI_WAKE_ERROR_CNT), + REG_RESERVED(PCS1G_LPI_STATUS), + REG_RESERVED(PCS1G_TSTPAT_MODE_CFG), + REG_RESERVED(PCS1G_TSTPAT_STATUS), + REG_RESERVED(DEV_PCS_FX100_CFG), + REG_RESERVED(DEV_PCS_FX100_STATUS), +}; + +static const u32 *vsc9959_regmap[TARGET_MAX] = { [ANA] = vsc9959_ana_regmap, [QS] = vsc9959_qs_regmap, [QSYS] = vsc9959_qsys_regmap, @@ -338,10 +380,11 @@ static const u32 *vsc9959_regmap[] = { [S2] = vsc9959_s2_regmap, [PTP] = vsc9959_ptp_regmap, [GCB] = vsc9959_gcb_regmap, + [DEV_GMII] = vsc9959_dev_gmii_regmap, }; /* Addresses are relative to the PCI device's base address */ -static const struct resource vsc9959_target_io_res[] = { +static const struct resource vsc9959_target_io_res[TARGET_MAX] = { [ANA] = { .start = 0x0280000, .end = 0x028ffff, diff --git a/drivers/net/ethernet/mscc/ocelot.h b/drivers/net/ethernet/mscc/ocelot.h index 394362e23c47..814b09dd2c11 100644 --- a/drivers/net/ethernet/mscc/ocelot.h +++ b/drivers/net/ethernet/mscc/ocelot.h @@ -105,8 +105,7 @@ void ocelot_port_writel(struct ocelot_port *port, u32 val, u32 reg); #define ocelot_field_write(ocelot, reg, val) regmap_field_write((ocelot)->regfields[(reg)], (val)) #define ocelot_field_read(ocelot, reg, val) regmap_field_read((ocelot)->regfields[(reg)], (val)) -int ocelot_probe_port(struct ocelot *ocelot, u8 port, - void __iomem *regs, +int ocelot_probe_port(struct ocelot *ocelot, int port, struct regmap *target, struct phy_device *phy); void ocelot_set_cpu_port(struct ocelot *ocelot, int cpu, diff --git a/drivers/net/ethernet/mscc/ocelot_io.c b/drivers/net/ethernet/mscc/ocelot_io.c index b229b1cb68ef..741f653bc85b 100644 --- a/drivers/net/ethernet/mscc/ocelot_io.c +++ b/drivers/net/ethernet/mscc/ocelot_io.c @@ -49,13 +49,25 @@ EXPORT_SYMBOL(__ocelot_rmw_ix); u32 ocelot_port_readl(struct ocelot_port *port, u32 reg) { - return readl(port->regs + reg); + struct ocelot *ocelot = port->ocelot; + u16 target = reg >> TARGET_OFFSET; + u32 val; + + WARN_ON(!target); + + regmap_read(port->target, ocelot->map[target][reg & REG_MASK], &val); + return val; } EXPORT_SYMBOL(ocelot_port_readl); void ocelot_port_writel(struct ocelot_port *port, u32 val, u32 reg) { - writel(val, port->regs + reg); + struct ocelot *ocelot = port->ocelot; + u16 target = reg >> TARGET_OFFSET; + + WARN_ON(!target); + + regmap_write(port->target, ocelot->map[target][reg & REG_MASK], val); } EXPORT_SYMBOL(ocelot_port_writel); diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c index 41a1b5f6df95..0668d23cdbfa 100644 --- a/drivers/net/ethernet/mscc/ocelot_net.c +++ b/drivers/net/ethernet/mscc/ocelot_net.c @@ -1005,8 +1005,7 @@ struct notifier_block ocelot_switchdev_blocking_nb __read_mostly = { .notifier_call = ocelot_switchdev_blocking_event, }; -int ocelot_probe_port(struct ocelot *ocelot, u8 port, - void __iomem *regs, +int ocelot_probe_port(struct ocelot *ocelot, int port, struct regmap *target, struct phy_device *phy) { struct ocelot_port_private *priv; @@ -1024,7 +1023,7 @@ int ocelot_probe_port(struct ocelot *ocelot, u8 port, priv->chip_port = port; ocelot_port = &priv->port; ocelot_port->ocelot = ocelot; - ocelot_port->regs = regs; + ocelot_port->target = target; ocelot->ports[port] = ocelot_port; dev->netdev_ops = &ocelot_port_netdev_ops; diff --git a/drivers/net/ethernet/mscc/ocelot_vsc7514.c b/drivers/net/ethernet/mscc/ocelot_vsc7514.c index 43716e8dc0ac..63af145e744c 100644 --- a/drivers/net/ethernet/mscc/ocelot_vsc7514.c +++ b/drivers/net/ethernet/mscc/ocelot_vsc7514.c @@ -263,7 +263,49 @@ static const u32 ocelot_ptp_regmap[] = { REG(PTP_CLK_CFG_ADJ_FREQ, 0x0000a8), }; -static const u32 *ocelot_regmap[] = { +static const u32 ocelot_dev_gmii_regmap[] = { + REG(DEV_CLOCK_CFG, 0x0), + REG(DEV_PORT_MISC, 0x4), + REG(DEV_EVENTS, 0x8), + REG(DEV_EEE_CFG, 0xc), + REG(DEV_RX_PATH_DELAY, 0x10), + REG(DEV_TX_PATH_DELAY, 0x14), + REG(DEV_PTP_PREDICT_CFG, 0x18), + REG(DEV_MAC_ENA_CFG, 0x1c), + REG(DEV_MAC_MODE_CFG, 0x20), + REG(DEV_MAC_MAXLEN_CFG, 0x24), + REG(DEV_MAC_TAGS_CFG, 0x28), + REG(DEV_MAC_ADV_CHK_CFG, 0x2c), + REG(DEV_MAC_IFG_CFG, 0x30), + REG(DEV_MAC_HDX_CFG, 0x34), + REG(DEV_MAC_DBG_CFG, 0x38), + REG(DEV_MAC_FC_MAC_LOW_CFG, 0x3c), + REG(DEV_MAC_FC_MAC_HIGH_CFG, 0x40), + REG(DEV_MAC_STICKY, 0x44), + REG(PCS1G_CFG, 0x48), + REG(PCS1G_MODE_CFG, 0x4c), + REG(PCS1G_SD_CFG, 0x50), + REG(PCS1G_ANEG_CFG, 0x54), + REG(PCS1G_ANEG_NP_CFG, 0x58), + REG(PCS1G_LB_CFG, 0x5c), + REG(PCS1G_DBG_CFG, 0x60), + REG(PCS1G_CDET_CFG, 0x64), + REG(PCS1G_ANEG_STATUS, 0x68), + REG(PCS1G_ANEG_NP_STATUS, 0x6c), + REG(PCS1G_LINK_STATUS, 0x70), + REG(PCS1G_LINK_DOWN_CNT, 0x74), + REG(PCS1G_STICKY, 0x78), + REG(PCS1G_DEBUG_STATUS, 0x7c), + REG(PCS1G_LPI_CFG, 0x80), + REG(PCS1G_LPI_WAKE_ERROR_CNT, 0x84), + REG(PCS1G_LPI_STATUS, 0x88), + REG(PCS1G_TSTPAT_MODE_CFG, 0x8c), + REG(PCS1G_TSTPAT_STATUS, 0x90), + REG(DEV_PCS_FX100_CFG, 0x94), + REG(DEV_PCS_FX100_STATUS, 0x98), +}; + +static const u32 *ocelot_regmap[TARGET_MAX] = { [ANA] = ocelot_ana_regmap, [QS] = ocelot_qs_regmap, [QSYS] = ocelot_qsys_regmap, @@ -271,6 +313,7 @@ static const u32 *ocelot_regmap[] = { [SYS] = ocelot_sys_regmap, [S2] = ocelot_s2_regmap, [PTP] = ocelot_ptp_regmap, + [DEV_GMII] = ocelot_dev_gmii_regmap, }; static const struct reg_field ocelot_regfields[] = { @@ -948,9 +991,9 @@ static int mscc_ocelot_probe(struct platform_device *pdev) struct device_node *phy_node; phy_interface_t phy_mode; struct phy_device *phy; + struct regmap *target; struct resource *res; struct phy *serdes; - void __iomem *regs; char res_name[8]; u32 port; @@ -961,8 +1004,8 @@ static int mscc_ocelot_probe(struct platform_device *pdev) res = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name); - regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(regs)) + target = ocelot_regmap_init(ocelot, res); + if (IS_ERR(target)) continue; phy_node = of_parse_phandle(portnp, "phy-handle", 0); @@ -974,7 +1017,7 @@ static int mscc_ocelot_probe(struct platform_device *pdev) if (!phy) continue; - err = ocelot_probe_port(ocelot, port, regs, phy); + err = ocelot_probe_port(ocelot, port, target, phy); if (err) { of_node_put(portnp); goto out_put_ports; diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index e050f8121ba2..c2a2d0165ef1 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -126,6 +126,7 @@ enum ocelot_target { HSIO, PTP, GCB, + DEV_GMII, TARGET_MAX, }; @@ -408,6 +409,45 @@ enum ocelot_reg { PTP_CLK_CFG_ADJ_CFG, PTP_CLK_CFG_ADJ_FREQ, GCB_SOFT_RST = GCB << TARGET_OFFSET, + DEV_CLOCK_CFG = DEV_GMII << TARGET_OFFSET, + DEV_PORT_MISC, + DEV_EVENTS, + DEV_EEE_CFG, + DEV_RX_PATH_DELAY, + DEV_TX_PATH_DELAY, + DEV_PTP_PREDICT_CFG, + DEV_MAC_ENA_CFG, + DEV_MAC_MODE_CFG, + DEV_MAC_MAXLEN_CFG, + DEV_MAC_TAGS_CFG, + DEV_MAC_ADV_CHK_CFG, + DEV_MAC_IFG_CFG, + DEV_MAC_HDX_CFG, + DEV_MAC_DBG_CFG, + DEV_MAC_FC_MAC_LOW_CFG, + DEV_MAC_FC_MAC_HIGH_CFG, + DEV_MAC_STICKY, + PCS1G_CFG, + PCS1G_MODE_CFG, + PCS1G_SD_CFG, + PCS1G_ANEG_CFG, + PCS1G_ANEG_NP_CFG, + PCS1G_LB_CFG, + PCS1G_DBG_CFG, + PCS1G_CDET_CFG, + PCS1G_ANEG_STATUS, + PCS1G_ANEG_NP_STATUS, + PCS1G_LINK_STATUS, + PCS1G_LINK_DOWN_CNT, + PCS1G_STICKY, + PCS1G_DEBUG_STATUS, + PCS1G_LPI_CFG, + PCS1G_LPI_WAKE_ERROR_CNT, + PCS1G_LPI_STATUS, + PCS1G_TSTPAT_MODE_CFG, + PCS1G_TSTPAT_STATUS, + DEV_PCS_FX100_CFG, + DEV_PCS_FX100_STATUS, }; enum ocelot_regfield { @@ -494,7 +534,7 @@ struct ocelot_vcap_block { struct ocelot_port { struct ocelot *ocelot; - void __iomem *regs; + struct regmap *target; bool vlan_aware; diff --git a/include/soc/mscc/ocelot_dev.h b/include/soc/mscc/ocelot_dev.h index 7c08437061fc..0c6021f02fee 100644 --- a/include/soc/mscc/ocelot_dev.h +++ b/include/soc/mscc/ocelot_dev.h @@ -8,8 +8,6 @@ #ifndef _MSCC_OCELOT_DEV_H_ #define _MSCC_OCELOT_DEV_H_ -#define DEV_CLOCK_CFG 0x0 - #define DEV_CLOCK_CFG_MAC_TX_RST BIT(7) #define DEV_CLOCK_CFG_MAC_RX_RST BIT(6) #define DEV_CLOCK_CFG_PCS_TX_RST BIT(5) @@ -19,18 +17,12 @@ #define DEV_CLOCK_CFG_LINK_SPEED(x) ((x) & GENMASK(1, 0)) #define DEV_CLOCK_CFG_LINK_SPEED_M GENMASK(1, 0) -#define DEV_PORT_MISC 0x4 - #define DEV_PORT_MISC_FWD_ERROR_ENA BIT(4) #define DEV_PORT_MISC_FWD_PAUSE_ENA BIT(3) #define DEV_PORT_MISC_FWD_CTRL_ENA BIT(2) #define DEV_PORT_MISC_DEV_LOOP_ENA BIT(1) #define DEV_PORT_MISC_HDX_FAST_DIS BIT(0) -#define DEV_EVENTS 0x8 - -#define DEV_EEE_CFG 0xc - #define DEV_EEE_CFG_EEE_ENA BIT(22) #define DEV_EEE_CFG_EEE_TIMER_AGE(x) (((x) << 15) & GENMASK(21, 15)) #define DEV_EEE_CFG_EEE_TIMER_AGE_M GENMASK(21, 15) @@ -43,33 +35,19 @@ #define DEV_EEE_CFG_EEE_TIMER_HOLDOFF_X(x) (((x) & GENMASK(7, 1)) >> 1) #define DEV_EEE_CFG_PORT_LPI BIT(0) -#define DEV_RX_PATH_DELAY 0x10 - -#define DEV_TX_PATH_DELAY 0x14 - -#define DEV_PTP_PREDICT_CFG 0x18 - #define DEV_PTP_PREDICT_CFG_PTP_PHY_PREDICT_CFG(x) (((x) << 4) & GENMASK(11, 4)) #define DEV_PTP_PREDICT_CFG_PTP_PHY_PREDICT_CFG_M GENMASK(11, 4) #define DEV_PTP_PREDICT_CFG_PTP_PHY_PREDICT_CFG_X(x) (((x) & GENMASK(11, 4)) >> 4) #define DEV_PTP_PREDICT_CFG_PTP_PHASE_PREDICT_CFG(x) ((x) & GENMASK(3, 0)) #define DEV_PTP_PREDICT_CFG_PTP_PHASE_PREDICT_CFG_M GENMASK(3, 0) -#define DEV_MAC_ENA_CFG 0x1c - #define DEV_MAC_ENA_CFG_RX_ENA BIT(4) #define DEV_MAC_ENA_CFG_TX_ENA BIT(0) -#define DEV_MAC_MODE_CFG 0x20 - #define DEV_MAC_MODE_CFG_FC_WORD_SYNC_ENA BIT(8) #define DEV_MAC_MODE_CFG_GIGA_MODE_ENA BIT(4) #define DEV_MAC_MODE_CFG_FDX_ENA BIT(0) -#define DEV_MAC_MAXLEN_CFG 0x24 - -#define DEV_MAC_TAGS_CFG 0x28 - #define DEV_MAC_TAGS_CFG_TAG_ID(x) (((x) << 16) & GENMASK(31, 16)) #define DEV_MAC_TAGS_CFG_TAG_ID_M GENMASK(31, 16) #define DEV_MAC_TAGS_CFG_TAG_ID_X(x) (((x) & GENMASK(31, 16)) >> 16) @@ -77,12 +55,8 @@ #define DEV_MAC_TAGS_CFG_VLAN_DBL_AWR_ENA BIT(1) #define DEV_MAC_TAGS_CFG_VLAN_AWR_ENA BIT(0) -#define DEV_MAC_ADV_CHK_CFG 0x2c - #define DEV_MAC_ADV_CHK_CFG_LEN_DROP_ENA BIT(0) -#define DEV_MAC_IFG_CFG 0x30 - #define DEV_MAC_IFG_CFG_RESTORE_OLD_IPG_CHECK BIT(17) #define DEV_MAC_IFG_CFG_REDUCED_TX_IFG BIT(16) #define DEV_MAC_IFG_CFG_TX_IFG(x) (((x) << 8) & GENMASK(12, 8)) @@ -94,8 +68,6 @@ #define DEV_MAC_IFG_CFG_RX_IFG1(x) ((x) & GENMASK(3, 0)) #define DEV_MAC_IFG_CFG_RX_IFG1_M GENMASK(3, 0) -#define DEV_MAC_HDX_CFG 0x34 - #define DEV_MAC_HDX_CFG_BYPASS_COL_SYNC BIT(26) #define DEV_MAC_HDX_CFG_OB_ENA BIT(25) #define DEV_MAC_HDX_CFG_WEXC_DIS BIT(24) @@ -107,17 +79,9 @@ #define DEV_MAC_HDX_CFG_LATE_COL_POS(x) ((x) & GENMASK(6, 0)) #define DEV_MAC_HDX_CFG_LATE_COL_POS_M GENMASK(6, 0) -#define DEV_MAC_DBG_CFG 0x38 - #define DEV_MAC_DBG_CFG_TBI_MODE BIT(4) #define DEV_MAC_DBG_CFG_IFG_CRS_EXT_CHK_ENA BIT(0) -#define DEV_MAC_FC_MAC_LOW_CFG 0x3c - -#define DEV_MAC_FC_MAC_HIGH_CFG 0x40 - -#define DEV_MAC_STICKY 0x44 - #define DEV_MAC_STICKY_RX_IPG_SHRINK_STICKY BIT(9) #define DEV_MAC_STICKY_RX_PREAM_SHRINK_STICKY BIT(8) #define DEV_MAC_STICKY_RX_CARRIER_EXT_STICKY BIT(7) @@ -129,25 +93,17 @@ #define DEV_MAC_STICKY_TX_FRM_LEN_OVR_STICKY BIT(1) #define DEV_MAC_STICKY_TX_ABORT_STICKY BIT(0) -#define PCS1G_CFG 0x48 - #define PCS1G_CFG_LINK_STATUS_TYPE BIT(4) #define PCS1G_CFG_AN_LINK_CTRL_ENA BIT(1) #define PCS1G_CFG_PCS_ENA BIT(0) -#define PCS1G_MODE_CFG 0x4c - #define PCS1G_MODE_CFG_UNIDIR_MODE_ENA BIT(4) #define PCS1G_MODE_CFG_SGMII_MODE_ENA BIT(0) -#define PCS1G_SD_CFG 0x50 - #define PCS1G_SD_CFG_SD_SEL BIT(8) #define PCS1G_SD_CFG_SD_POL BIT(4) #define PCS1G_SD_CFG_SD_ENA BIT(0) -#define PCS1G_ANEG_CFG 0x54 - #define PCS1G_ANEG_CFG_ADV_ABILITY(x) (((x) << 16) & GENMASK(31, 16)) #define PCS1G_ANEG_CFG_ADV_ABILITY_M GENMASK(31, 16) #define PCS1G_ANEG_CFG_ADV_ABILITY_X(x) (((x) & GENMASK(31, 16)) >> 16) @@ -155,29 +111,19 @@ #define PCS1G_ANEG_CFG_ANEG_RESTART_ONE_SHOT BIT(1) #define PCS1G_ANEG_CFG_ANEG_ENA BIT(0) -#define PCS1G_ANEG_NP_CFG 0x58 - #define PCS1G_ANEG_NP_CFG_NP_TX(x) (((x) << 16) & GENMASK(31, 16)) #define PCS1G_ANEG_NP_CFG_NP_TX_M GENMASK(31, 16) #define PCS1G_ANEG_NP_CFG_NP_TX_X(x) (((x) & GENMASK(31, 16)) >> 16) #define PCS1G_ANEG_NP_CFG_NP_LOADED_ONE_SHOT BIT(0) -#define PCS1G_LB_CFG 0x5c - #define PCS1G_LB_CFG_RA_ENA BIT(4) #define PCS1G_LB_CFG_GMII_PHY_LB_ENA BIT(1) #define PCS1G_LB_CFG_TBI_HOST_LB_ENA BIT(0) -#define PCS1G_DBG_CFG 0x60 - #define PCS1G_DBG_CFG_UDLT BIT(0) -#define PCS1G_CDET_CFG 0x64 - #define PCS1G_CDET_CFG_CDET_ENA BIT(0) -#define PCS1G_ANEG_STATUS 0x68 - #define PCS1G_ANEG_STATUS_LP_ADV_ABILITY(x) (((x) << 16) & GENMASK(31, 16)) #define PCS1G_ANEG_STATUS_LP_ADV_ABILITY_M GENMASK(31, 16) #define PCS1G_ANEG_STATUS_LP_ADV_ABILITY_X(x) (((x) & GENMASK(31, 16)) >> 16) @@ -185,10 +131,6 @@ #define PCS1G_ANEG_STATUS_PAGE_RX_STICKY BIT(3) #define PCS1G_ANEG_STATUS_ANEG_COMPLETE BIT(0) -#define PCS1G_ANEG_NP_STATUS 0x6c - -#define PCS1G_LINK_STATUS 0x70 - #define PCS1G_LINK_STATUS_DELAY_VAR(x) (((x) << 12) & GENMASK(15, 12)) #define PCS1G_LINK_STATUS_DELAY_VAR_M GENMASK(15, 12) #define PCS1G_LINK_STATUS_DELAY_VAR_X(x) (((x) & GENMASK(15, 12)) >> 12) @@ -196,17 +138,9 @@ #define PCS1G_LINK_STATUS_LINK_STATUS BIT(4) #define PCS1G_LINK_STATUS_SYNC_STATUS BIT(0) -#define PCS1G_LINK_DOWN_CNT 0x74 - -#define PCS1G_STICKY 0x78 - #define PCS1G_STICKY_LINK_DOWN_STICKY BIT(4) #define PCS1G_STICKY_OUT_OF_SYNC_STICKY BIT(0) -#define PCS1G_DEBUG_STATUS 0x7c - -#define PCS1G_LPI_CFG 0x80 - #define PCS1G_LPI_CFG_QSGMII_MS_SEL BIT(20) #define PCS1G_LPI_CFG_RX_LPI_OUT_DIS BIT(17) #define PCS1G_LPI_CFG_LPI_TESTMODE BIT(16) @@ -215,10 +149,6 @@ #define PCS1G_LPI_CFG_LPI_RX_WTIM_X(x) (((x) & GENMASK(5, 4)) >> 4) #define PCS1G_LPI_CFG_TX_ASSERT_LPIDLE BIT(0) -#define PCS1G_LPI_WAKE_ERROR_CNT 0x84 - -#define PCS1G_LPI_STATUS 0x88 - #define PCS1G_LPI_STATUS_RX_LPI_FAIL BIT(16) #define PCS1G_LPI_STATUS_RX_LPI_EVENT_STICKY BIT(12) #define PCS1G_LPI_STATUS_RX_QUIET BIT(9) @@ -227,18 +157,12 @@ #define PCS1G_LPI_STATUS_TX_QUIET BIT(1) #define PCS1G_LPI_STATUS_TX_LPI_MODE BIT(0) -#define PCS1G_TSTPAT_MODE_CFG 0x8c - -#define PCS1G_TSTPAT_STATUS 0x90 - #define PCS1G_TSTPAT_STATUS_JTP_ERR_CNT(x) (((x) << 8) & GENMASK(15, 8)) #define PCS1G_TSTPAT_STATUS_JTP_ERR_CNT_M GENMASK(15, 8) #define PCS1G_TSTPAT_STATUS_JTP_ERR_CNT_X(x) (((x) & GENMASK(15, 8)) >> 8) #define PCS1G_TSTPAT_STATUS_JTP_ERR BIT(4) #define PCS1G_TSTPAT_STATUS_JTP_LOCK BIT(0) -#define DEV_PCS_FX100_CFG 0x94 - #define DEV_PCS_FX100_CFG_SD_SEL BIT(26) #define DEV_PCS_FX100_CFG_SD_POL BIT(25) #define DEV_PCS_FX100_CFG_SD_ENA BIT(24) @@ -259,8 +183,6 @@ #define DEV_PCS_FX100_CFG_FEFGEN_ENA BIT(1) #define DEV_PCS_FX100_CFG_PCS_ENA BIT(0) -#define DEV_PCS_FX100_STATUS 0x98 - #define DEV_PCS_FX100_STATUS_EDGE_POS_PTP(x) (((x) << 8) & GENMASK(11, 8)) #define DEV_PCS_FX100_STATUS_EDGE_POS_PTP_M GENMASK(11, 8) #define DEV_PCS_FX100_STATUS_EDGE_POS_PTP_X(x) (((x) & GENMASK(11, 8)) >> 8) -- cgit v1.2.3 From 2789658fa319f51db43a585e076bb99a3de3c6d1 Mon Sep 17 00:00:00 2001 From: Maxim Kochetkov Date: Mon, 13 Jul 2020 19:57:02 +0300 Subject: soc: mscc: ocelot: add MII registers description Add the register definitions for the MSCC MIIM MDIO controller in preparation for seville_vsc9959.c to create its accessors for the internal MDIO bus. Since we've introduced elements to ocelot_regfields that are not instantiated by felix and ocelot, we need to define the size of the regfields arrays explicitly, otherwise ocelot_regfields_init, which iterates up to REGFIELD_MAX, will fault on the undefined regfield entries (if we're lucky). Signed-off-by: Maxim Kochetkov Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/ocelot/felix_vsc9959.c | 2 +- drivers/net/ethernet/mscc/ocelot_vsc7514.c | 2 +- include/soc/mscc/ocelot.h | 5 +++++ 3 files changed, 7 insertions(+), 2 deletions(-) (limited to 'include/soc/mscc') diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c index 0c54d67a4039..b97c12a783eb 100644 --- a/drivers/net/dsa/ocelot/felix_vsc9959.c +++ b/drivers/net/dsa/ocelot/felix_vsc9959.c @@ -469,7 +469,7 @@ static const struct resource vsc9959_imdio_res = { .name = "imdio", }; -static const struct reg_field vsc9959_regfields[] = { +static const struct reg_field vsc9959_regfields[REGFIELD_MAX] = { [ANA_ADVLEARN_VLAN_CHK] = REG_FIELD(ANA_ADVLEARN, 6, 6), [ANA_ADVLEARN_LEARN_MIRROR] = REG_FIELD(ANA_ADVLEARN, 0, 5), [ANA_ANEVENTS_FLOOD_DISCARD] = REG_FIELD(ANA_ANEVENTS, 30, 30), diff --git a/drivers/net/ethernet/mscc/ocelot_vsc7514.c b/drivers/net/ethernet/mscc/ocelot_vsc7514.c index 63af145e744c..83c17c689641 100644 --- a/drivers/net/ethernet/mscc/ocelot_vsc7514.c +++ b/drivers/net/ethernet/mscc/ocelot_vsc7514.c @@ -316,7 +316,7 @@ static const u32 *ocelot_regmap[TARGET_MAX] = { [DEV_GMII] = ocelot_dev_gmii_regmap, }; -static const struct reg_field ocelot_regfields[] = { +static const struct reg_field ocelot_regfields[REGFIELD_MAX] = { [ANA_ADVLEARN_VLAN_CHK] = REG_FIELD(ANA_ADVLEARN, 11, 11), [ANA_ADVLEARN_LEARN_MIRROR] = REG_FIELD(ANA_ADVLEARN, 0, 10), [ANA_ANEVENTS_MSTI_DROP] = REG_FIELD(ANA_ANEVENTS, 27, 27), diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index c2a2d0165ef1..348fa26a349c 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -409,6 +409,9 @@ enum ocelot_reg { PTP_CLK_CFG_ADJ_CFG, PTP_CLK_CFG_ADJ_FREQ, GCB_SOFT_RST = GCB << TARGET_OFFSET, + GCB_MIIM_MII_STATUS, + GCB_MIIM_MII_CMD, + GCB_MIIM_MII_DATA, DEV_CLOCK_CFG = DEV_GMII << TARGET_OFFSET, DEV_PORT_MISC, DEV_EVENTS, @@ -496,6 +499,8 @@ enum ocelot_regfield { SYS_RESET_CFG_MEM_ENA, SYS_RESET_CFG_MEM_INIT, GCB_SOFT_RST_SWC_RST, + GCB_MIIM_MII_STATUS_PENDING, + GCB_MIIM_MII_STATUS_BUSY, REGFIELD_MAX }; -- cgit v1.2.3 From 886e1387c73d895ad0eff53353913081983570c0 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Mon, 13 Jul 2020 19:57:03 +0300 Subject: net: mscc: ocelot: convert QSYS_SWITCH_PORT_MODE and SYS_PORT_MODE to regfields Currently Felix and Ocelot share the same bit layout in these per-port registers, but Seville does not. So we need reg_fields for that. Actually since these are per-port registers, we need to also specify the number of ports, and register size per port, and use the regmap API for multiple ports. There's a more subtle point to be made about the other 2 register fields: - QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG - QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE which we are not writing any longer, for 2 reasons: - Using the previous API (ocelot_write_rix), we were only writing 1 for Felix and Ocelot, which was their hardware-default value, and which there wasn't any intention in changing. - In the case of SCH_NEXT_CFG, in fact Seville does not have this register field at all, and therefore, if we want to have common code we would be required to not write to it. Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/ocelot/felix.c | 9 +++----- drivers/net/dsa/ocelot/felix_vsc9959.c | 11 +++++++++ drivers/net/ethernet/mscc/ocelot.c | 36 ++++++++++++------------------ drivers/net/ethernet/mscc/ocelot.h | 6 ----- drivers/net/ethernet/mscc/ocelot_io.c | 2 ++ drivers/net/ethernet/mscc/ocelot_vsc7514.c | 11 +++++++++ include/soc/mscc/ocelot.h | 15 +++++++++++++ include/soc/mscc/ocelot_qsys.h | 13 ----------- include/soc/mscc/ocelot_sys.h | 13 ----------- 9 files changed, 56 insertions(+), 60 deletions(-) (limited to 'include/soc/mscc') diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index bf0bd5c7b12c..4b255ed614e4 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -249,8 +249,7 @@ static void felix_phylink_mac_link_down(struct dsa_switch *ds, int port, struct ocelot_port *ocelot_port = ocelot->ports[port]; ocelot_port_writel(ocelot_port, 0, DEV_MAC_ENA_CFG); - ocelot_rmw_rix(ocelot, 0, QSYS_SWITCH_PORT_MODE_PORT_ENA, - QSYS_SWITCH_PORT_MODE, port); + ocelot_fields_write(ocelot, port, QSYS_SWITCH_PORT_MODE_PORT_ENA, 0); } static void felix_phylink_mac_link_up(struct dsa_switch *ds, int port, @@ -326,10 +325,8 @@ static void felix_phylink_mac_link_up(struct dsa_switch *ds, int port, ANA_PORT_PORT_CFG, port); /* Core: Enable port for frame transfer */ - ocelot_write_rix(ocelot, QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE | - QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG(1) | - QSYS_SWITCH_PORT_MODE_PORT_ENA, - QSYS_SWITCH_PORT_MODE, port); + ocelot_fields_write(ocelot, port, + QSYS_SWITCH_PORT_MODE_PORT_ENA, 1); if (felix->info->pcs_link_up) felix->info->pcs_link_up(ocelot, port, link_an_mode, interface, diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c index b97c12a783eb..efbfbdccb2b6 100644 --- a/drivers/net/dsa/ocelot/felix_vsc9959.c +++ b/drivers/net/dsa/ocelot/felix_vsc9959.c @@ -503,6 +503,17 @@ static const struct reg_field vsc9959_regfields[REGFIELD_MAX] = { [ANA_TABLES_MACTINDX_M_INDEX] = REG_FIELD(ANA_TABLES_MACTINDX, 0, 10), [SYS_RESET_CFG_CORE_ENA] = REG_FIELD(SYS_RESET_CFG, 0, 0), [GCB_SOFT_RST_SWC_RST] = REG_FIELD(GCB_SOFT_RST, 0, 0), + /* Replicated per number of ports (7), register size 4 per port */ + [QSYS_SWITCH_PORT_MODE_PORT_ENA] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 14, 14, 7, 4), + [QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 11, 13, 7, 4), + [QSYS_SWITCH_PORT_MODE_YEL_RSRVD] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 10, 10, 7, 4), + [QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 9, 9, 7, 4), + [QSYS_SWITCH_PORT_MODE_TX_PFC_ENA] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 1, 8, 7, 4), + [QSYS_SWITCH_PORT_MODE_TX_PFC_MODE] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 0, 0, 7, 4), + [SYS_PORT_MODE_DATA_WO_TS] = REG_FIELD_ID(SYS_PORT_MODE, 5, 6, 7, 4), + [SYS_PORT_MODE_INCL_INJ_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 3, 4, 7, 4), + [SYS_PORT_MODE_INCL_XTR_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 1, 2, 7, 4), + [SYS_PORT_MODE_INCL_HDR_ERR] = REG_FIELD_ID(SYS_PORT_MODE, 0, 0, 7, 4), }; static const struct ocelot_stat_layout vsc9959_stats_layout[] = { diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index e815aad8d85e..36986fccedf4 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -389,10 +389,8 @@ void ocelot_adjust_link(struct ocelot *ocelot, int port, ANA_PFC_PFC_CFG, port); /* Core: Enable port for frame transfer */ - ocelot_write_rix(ocelot, QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE | - QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG(1) | - QSYS_SWITCH_PORT_MODE_PORT_ENA, - QSYS_SWITCH_PORT_MODE, port); + ocelot_fields_write(ocelot, port, + QSYS_SWITCH_PORT_MODE_PORT_ENA, 1); /* Flow control */ ocelot_write_rix(ocelot, SYS_MAC_FC_CFG_PAUSE_VAL_CFG(0xffff) | @@ -423,8 +421,7 @@ void ocelot_port_disable(struct ocelot *ocelot, int port) struct ocelot_port *ocelot_port = ocelot->ports[port]; ocelot_port_writel(ocelot_port, 0, DEV_MAC_ENA_CFG); - ocelot_rmw_rix(ocelot, 0, QSYS_SWITCH_PORT_MODE_PORT_ENA, - QSYS_SWITCH_PORT_MODE, port); + ocelot_fields_write(ocelot, port, QSYS_SWITCH_PORT_MODE_PORT_ENA, 0); } EXPORT_SYMBOL(ocelot_port_disable); @@ -1392,27 +1389,22 @@ void ocelot_configure_cpu(struct ocelot *ocelot, int npi, QSYS_EXT_CPU_CFG); /* Enable NPI port */ - ocelot_write_rix(ocelot, - QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE | - QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG(1) | - QSYS_SWITCH_PORT_MODE_PORT_ENA, - QSYS_SWITCH_PORT_MODE, npi); + ocelot_fields_write(ocelot, npi, + QSYS_SWITCH_PORT_MODE_PORT_ENA, 1); /* NPI port Injection/Extraction configuration */ - ocelot_write_rix(ocelot, - SYS_PORT_MODE_INCL_XTR_HDR(extraction) | - SYS_PORT_MODE_INCL_INJ_HDR(injection), - SYS_PORT_MODE, npi); + ocelot_fields_write(ocelot, npi, SYS_PORT_MODE_INCL_XTR_HDR, + extraction); + ocelot_fields_write(ocelot, npi, SYS_PORT_MODE_INCL_INJ_HDR, + injection); } /* Enable CPU port module */ - ocelot_write_rix(ocelot, QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE | - QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG(1) | - QSYS_SWITCH_PORT_MODE_PORT_ENA, - QSYS_SWITCH_PORT_MODE, cpu); + ocelot_fields_write(ocelot, cpu, QSYS_SWITCH_PORT_MODE_PORT_ENA, 1); /* CPU port Injection/Extraction configuration */ - ocelot_write_rix(ocelot, SYS_PORT_MODE_INCL_XTR_HDR(extraction) | - SYS_PORT_MODE_INCL_INJ_HDR(injection), - SYS_PORT_MODE, cpu); + ocelot_fields_write(ocelot, cpu, SYS_PORT_MODE_INCL_XTR_HDR, + extraction); + ocelot_fields_write(ocelot, cpu, SYS_PORT_MODE_INCL_INJ_HDR, + injection); /* Configure the CPU port to be VLAN aware */ ocelot_write_gix(ocelot, ANA_PORT_VLAN_CFG_VLAN_VID(0) | diff --git a/drivers/net/ethernet/mscc/ocelot.h b/drivers/net/ethernet/mscc/ocelot.h index 814b09dd2c11..dc29e05103a1 100644 --- a/drivers/net/ethernet/mscc/ocelot.h +++ b/drivers/net/ethernet/mscc/ocelot.h @@ -102,9 +102,6 @@ void ocelot_port_lag_leave(struct ocelot *ocelot, int port, u32 ocelot_port_readl(struct ocelot_port *port, u32 reg); void ocelot_port_writel(struct ocelot_port *port, u32 val, u32 reg); -#define ocelot_field_write(ocelot, reg, val) regmap_field_write((ocelot)->regfields[(reg)], (val)) -#define ocelot_field_read(ocelot, reg, val) regmap_field_read((ocelot)->regfields[(reg)], (val)) - int ocelot_probe_port(struct ocelot *ocelot, int port, struct regmap *target, struct phy_device *phy); @@ -116,7 +113,4 @@ extern struct notifier_block ocelot_netdevice_nb; extern struct notifier_block ocelot_switchdev_nb; extern struct notifier_block ocelot_switchdev_blocking_nb; -#define ocelot_field_write(ocelot, reg, val) regmap_field_write((ocelot)->regfields[(reg)], (val)) -#define ocelot_field_read(ocelot, reg, val) regmap_field_read((ocelot)->regfields[(reg)], (val)) - #endif diff --git a/drivers/net/ethernet/mscc/ocelot_io.c b/drivers/net/ethernet/mscc/ocelot_io.c index 741f653bc85b..d22711282183 100644 --- a/drivers/net/ethernet/mscc/ocelot_io.c +++ b/drivers/net/ethernet/mscc/ocelot_io.c @@ -89,6 +89,8 @@ int ocelot_regfields_init(struct ocelot *ocelot, regfield.reg = ocelot->map[target][reg & REG_MASK]; regfield.lsb = regfields[i].lsb; regfield.msb = regfields[i].msb; + regfield.id_size = regfields[i].id_size; + regfield.id_offset = regfields[i].id_offset; ocelot->regfields[i] = devm_regmap_field_alloc(ocelot->dev, diff --git a/drivers/net/ethernet/mscc/ocelot_vsc7514.c b/drivers/net/ethernet/mscc/ocelot_vsc7514.c index 83c17c689641..9c6a9d44871d 100644 --- a/drivers/net/ethernet/mscc/ocelot_vsc7514.c +++ b/drivers/net/ethernet/mscc/ocelot_vsc7514.c @@ -358,6 +358,17 @@ static const struct reg_field ocelot_regfields[REGFIELD_MAX] = { [SYS_RESET_CFG_CORE_ENA] = REG_FIELD(SYS_RESET_CFG, 2, 2), [SYS_RESET_CFG_MEM_ENA] = REG_FIELD(SYS_RESET_CFG, 1, 1), [SYS_RESET_CFG_MEM_INIT] = REG_FIELD(SYS_RESET_CFG, 0, 0), + /* Replicated per number of ports (11), register size 4 per port */ + [QSYS_SWITCH_PORT_MODE_PORT_ENA] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 14, 14, 11, 4), + [QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 11, 13, 11, 4), + [QSYS_SWITCH_PORT_MODE_YEL_RSRVD] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 10, 10, 11, 4), + [QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 9, 9, 11, 4), + [QSYS_SWITCH_PORT_MODE_TX_PFC_ENA] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 1, 8, 11, 4), + [QSYS_SWITCH_PORT_MODE_TX_PFC_MODE] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 0, 0, 11, 4), + [SYS_PORT_MODE_DATA_WO_TS] = REG_FIELD_ID(SYS_PORT_MODE, 5, 6, 11, 4), + [SYS_PORT_MODE_INCL_INJ_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 3, 4, 11, 4), + [SYS_PORT_MODE_INCL_XTR_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 1, 2, 11, 4), + [SYS_PORT_MODE_INCL_HDR_ERR] = REG_FIELD_ID(SYS_PORT_MODE, 0, 0, 11, 4), }; static const struct ocelot_stat_layout ocelot_stats_layout[] = { diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index 348fa26a349c..19d97585345a 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -490,11 +490,21 @@ enum ocelot_regfield { ANA_TABLES_MACACCESS_B_DOM, ANA_TABLES_MACTINDX_BUCKET, ANA_TABLES_MACTINDX_M_INDEX, + QSYS_SWITCH_PORT_MODE_PORT_ENA, + QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG, + QSYS_SWITCH_PORT_MODE_YEL_RSRVD, + QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE, + QSYS_SWITCH_PORT_MODE_TX_PFC_ENA, + QSYS_SWITCH_PORT_MODE_TX_PFC_MODE, QSYS_TIMED_FRAME_ENTRY_TFRM_VLD, QSYS_TIMED_FRAME_ENTRY_TFRM_FP, QSYS_TIMED_FRAME_ENTRY_TFRM_PORTNO, QSYS_TIMED_FRAME_ENTRY_TFRM_TM_SEL, QSYS_TIMED_FRAME_ENTRY_TFRM_TM_T, + SYS_PORT_MODE_DATA_WO_TS, + SYS_PORT_MODE_INCL_INJ_HDR, + SYS_PORT_MODE_INCL_XTR_HDR, + SYS_PORT_MODE_INCL_HDR_ERR, SYS_RESET_CFG_CORE_ENA, SYS_RESET_CFG_MEM_ENA, SYS_RESET_CFG_MEM_INIT, @@ -638,6 +648,11 @@ struct ocelot_policer { #define ocelot_rmw_rix(ocelot, val, m, reg, ri) __ocelot_rmw_ix(ocelot, val, m, reg, reg##_RSZ * (ri)) #define ocelot_rmw(ocelot, val, m, reg) __ocelot_rmw_ix(ocelot, val, m, reg, 0) +#define ocelot_field_write(ocelot, reg, val) regmap_field_write((ocelot)->regfields[(reg)], (val)) +#define ocelot_field_read(ocelot, reg, val) regmap_field_read((ocelot)->regfields[(reg)], (val)) +#define ocelot_fields_write(ocelot, id, reg, val) regmap_fields_write((ocelot)->regfields[(reg)], (id), (val)) +#define ocelot_fields_read(ocelot, id, reg, val) regmap_fields_read((ocelot)->regfields[(reg)], (id), (val)) + /* I/O */ u32 ocelot_port_readl(struct ocelot_port *port, u32 reg); void ocelot_port_writel(struct ocelot_port *port, u32 val, u32 reg); diff --git a/include/soc/mscc/ocelot_qsys.h b/include/soc/mscc/ocelot_qsys.h index d8c63aa761be..a814bc2017d8 100644 --- a/include/soc/mscc/ocelot_qsys.h +++ b/include/soc/mscc/ocelot_qsys.h @@ -13,19 +13,6 @@ #define QSYS_PORT_MODE_DEQUEUE_DIS BIT(1) #define QSYS_PORT_MODE_DEQUEUE_LATE BIT(0) -#define QSYS_SWITCH_PORT_MODE_RSZ 0x4 - -#define QSYS_SWITCH_PORT_MODE_PORT_ENA BIT(14) -#define QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG(x) (((x) << 11) & GENMASK(13, 11)) -#define QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG_M GENMASK(13, 11) -#define QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG_X(x) (((x) & GENMASK(13, 11)) >> 11) -#define QSYS_SWITCH_PORT_MODE_YEL_RSRVD BIT(10) -#define QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE BIT(9) -#define QSYS_SWITCH_PORT_MODE_TX_PFC_ENA(x) (((x) << 1) & GENMASK(8, 1)) -#define QSYS_SWITCH_PORT_MODE_TX_PFC_ENA_M GENMASK(8, 1) -#define QSYS_SWITCH_PORT_MODE_TX_PFC_ENA_X(x) (((x) & GENMASK(8, 1)) >> 1) -#define QSYS_SWITCH_PORT_MODE_TX_PFC_MODE BIT(0) - #define QSYS_STAT_CNT_CFG_TX_GREEN_CNT_MODE BIT(5) #define QSYS_STAT_CNT_CFG_TX_YELLOW_CNT_MODE BIT(4) #define QSYS_STAT_CNT_CFG_DROP_GREEN_CNT_MODE BIT(3) diff --git a/include/soc/mscc/ocelot_sys.h b/include/soc/mscc/ocelot_sys.h index 16f91e172bcb..8a95fc93fde5 100644 --- a/include/soc/mscc/ocelot_sys.h +++ b/include/soc/mscc/ocelot_sys.h @@ -12,19 +12,6 @@ #define SYS_COUNT_TX_OCTETS_RSZ 0x4 -#define SYS_PORT_MODE_RSZ 0x4 - -#define SYS_PORT_MODE_DATA_WO_TS(x) (((x) << 5) & GENMASK(6, 5)) -#define SYS_PORT_MODE_DATA_WO_TS_M GENMASK(6, 5) -#define SYS_PORT_MODE_DATA_WO_TS_X(x) (((x) & GENMASK(6, 5)) >> 5) -#define SYS_PORT_MODE_INCL_INJ_HDR(x) (((x) << 3) & GENMASK(4, 3)) -#define SYS_PORT_MODE_INCL_INJ_HDR_M GENMASK(4, 3) -#define SYS_PORT_MODE_INCL_INJ_HDR_X(x) (((x) & GENMASK(4, 3)) >> 3) -#define SYS_PORT_MODE_INCL_XTR_HDR(x) (((x) << 1) & GENMASK(2, 1)) -#define SYS_PORT_MODE_INCL_XTR_HDR_M GENMASK(2, 1) -#define SYS_PORT_MODE_INCL_XTR_HDR_X(x) (((x) & GENMASK(2, 1)) >> 1) -#define SYS_PORT_MODE_INJ_HDR_ERR BIT(0) - #define SYS_FRONT_PORT_MODE_RSZ 0x4 #define SYS_FRONT_PORT_MODE_HDX_MODE BIT(0) -- cgit v1.2.3 From 67c2404922c2c3f9cc0898aafaa4e3bea2bde084 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Mon, 13 Jul 2020 19:57:04 +0300 Subject: net: dsa: felix: create a template for the DSA tags on xmit With this patch we try to kill 2 birds with 1 stone. First of all, some switches that use tag_ocelot.c don't have the exact same bitfield layout for the DSA tags. The destination ports field is different for Seville VSC9953 for example. So the choices are to either duplicate tag_ocelot.c into a new tag_seville.c (sub-optimal) or somehow take into account a supposed ocelot->dest_ports_offset when packing this field into the DSA injection header (again not ideal). Secondly, tag_ocelot.c already needs to memset a 128-bit area to zero and call some packing() functions of dubious performance in the fastpath. And most of the values it needs to pack are pretty much constant (BYPASS=1, SRC_PORT=CPU, DEST=port index). So it would be good if we could improve that. The proposed solution is to allocate a memory area per port at probe time, initialize that with the statically defined bits as per chip hardware revision, and just perform a simpler memcpy in the fastpath. Other alternatives have been analyzed, such as: - Create a separate tag_seville.c: too much code duplication for just 1 bit field difference. - Create a separate DSA_TAG_PROTO_SEVILLE under tag_ocelot.c, just like tag_brcm.c, which would have a separate .xmit function. Again, too much code duplication for just 1 bit field difference. - Allocate the template from the init function of the tag_ocelot.c module, instead of from the driver: couldn't figure out a method of accessing the correct port template corresponding to the correct tagger in the .xmit function. Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/ocelot/felix.c | 13 +++++++++++++ drivers/net/dsa/ocelot/felix.h | 1 + drivers/net/dsa/ocelot/felix_vsc9959.c | 20 ++++++++++++++++++++ include/soc/mscc/ocelot.h | 2 ++ net/dsa/tag_ocelot.c | 21 ++++++++------------- 5 files changed, 44 insertions(+), 13 deletions(-) (limited to 'include/soc/mscc') diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index 4b255ed614e4..b9981d8c4c98 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -522,6 +522,7 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports) for (port = 0; port < num_phys_ports; port++) { struct ocelot_port *ocelot_port; struct regmap *target; + u8 *template; ocelot_port = devm_kzalloc(ocelot->dev, sizeof(struct ocelot_port), @@ -547,10 +548,22 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports) return PTR_ERR(target); } + template = devm_kzalloc(ocelot->dev, OCELOT_TAG_LEN, + GFP_KERNEL); + if (!template) { + dev_err(ocelot->dev, + "Failed to allocate memory for DSA tag\n"); + kfree(port_phy_modes); + return -ENOMEM; + } + ocelot_port->phy_mode = port_phy_modes[port]; ocelot_port->ocelot = ocelot; ocelot_port->target = target; + ocelot_port->xmit_template = template; ocelot->ports[port] = ocelot_port; + + felix->info->xmit_template_populate(ocelot, port); } kfree(port_phy_modes); diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h index 00137b64132b..a85631d716b9 100644 --- a/drivers/net/dsa/ocelot/felix.h +++ b/drivers/net/dsa/ocelot/felix.h @@ -43,6 +43,7 @@ struct felix_info { enum tc_setup_type type, void *type_data); void (*port_sched_speed_set)(struct ocelot *ocelot, int port, u32 speed); + void (*xmit_template_populate)(struct ocelot *ocelot, int port); }; extern struct felix_info felix_info_vsc9959; diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c index efbfbdccb2b6..d640146acc3d 100644 --- a/drivers/net/dsa/ocelot/felix_vsc9959.c +++ b/drivers/net/dsa/ocelot/felix_vsc9959.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -1432,6 +1433,24 @@ static int vsc9959_port_setup_tc(struct dsa_switch *ds, int port, } } +static void vsc9959_xmit_template_populate(struct ocelot *ocelot, int port) +{ + struct ocelot_port *ocelot_port = ocelot->ports[port]; + u8 *template = ocelot_port->xmit_template; + u64 bypass, dest, src; + + /* Set the source port as the CPU port module and not the + * NPI port + */ + src = ocelot->num_phys_ports; + dest = BIT(port); + bypass = true; + + packing(template, &bypass, 127, 127, OCELOT_TAG_LEN, PACK, 0); + packing(template, &dest, 68, 56, OCELOT_TAG_LEN, PACK, 0); + packing(template, &src, 46, 43, OCELOT_TAG_LEN, PACK, 0); +} + struct felix_info felix_info_vsc9959 = { .target_io_res = vsc9959_target_io_res, .port_io_res = vsc9959_port_io_res, @@ -1458,4 +1477,5 @@ struct felix_info felix_info_vsc9959 = { .prevalidate_phy_mode = vsc9959_prevalidate_phy_mode, .port_setup_tc = vsc9959_port_setup_tc, .port_sched_speed_set = vsc9959_sched_speed_set, + .xmit_template_populate = vsc9959_xmit_template_populate, }; diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index 19d97585345a..6cfbace57770 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -564,6 +564,8 @@ struct ocelot_port { u8 ts_id; phy_interface_t phy_mode; + + u8 *xmit_template; }; struct ocelot { diff --git a/net/dsa/tag_ocelot.c b/net/dsa/tag_ocelot.c index b0c98ee4e13b..42f327c06dca 100644 --- a/net/dsa/tag_ocelot.c +++ b/net/dsa/tag_ocelot.c @@ -137,11 +137,10 @@ static struct sk_buff *ocelot_xmit(struct sk_buff *skb, struct net_device *netdev) { struct dsa_port *dp = dsa_slave_to_port(netdev); - u64 bypass, dest, src, qos_class, rew_op; struct dsa_switch *ds = dp->ds; - int port = dp->index; struct ocelot *ocelot = ds->priv; - struct ocelot_port *ocelot_port = ocelot->ports[port]; + struct ocelot_port *ocelot_port; + u64 qos_class, rew_op; u8 *injection; if (unlikely(skb_cow_head(skb, OCELOT_TAG_LEN) < 0)) { @@ -149,19 +148,15 @@ static struct sk_buff *ocelot_xmit(struct sk_buff *skb, return NULL; } - injection = skb_push(skb, OCELOT_TAG_LEN); + ocelot_port = ocelot->ports[dp->index]; - memset(injection, 0, OCELOT_TAG_LEN); + injection = skb_push(skb, OCELOT_TAG_LEN); - /* Set the source port as the CPU port module and not the NPI port */ - src = ocelot->num_phys_ports; - dest = BIT(port); - bypass = true; + memcpy(injection, ocelot_port->xmit_template, OCELOT_TAG_LEN); + /* Fix up the fields which are not statically determined + * in the template + */ qos_class = skb->priority; - - packing(injection, &bypass, 127, 127, OCELOT_TAG_LEN, PACK, 0); - packing(injection, &dest, 68, 56, OCELOT_TAG_LEN, PACK, 0); - packing(injection, &src, 46, 43, OCELOT_TAG_LEN, PACK, 0); packing(injection, &qos_class, 19, 17, OCELOT_TAG_LEN, PACK, 0); if (ocelot->ptp && (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { -- cgit v1.2.3 From 541132f0961a4f17b02974902085af964adf5966 Mon Sep 17 00:00:00 2001 From: Maxim Kochetkov Date: Mon, 13 Jul 2020 19:57:07 +0300 Subject: net: mscc: ocelot: convert SYS_PAUSE_CFG register access to regfield Seville has a different bitwise layout than Ocelot and Felix. Signed-off-by: Maxim Kochetkov Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/ocelot/felix_vsc9959.c | 3 +++ drivers/net/ethernet/mscc/ocelot.c | 14 ++++++-------- drivers/net/ethernet/mscc/ocelot_vsc7514.c | 3 +++ include/soc/mscc/ocelot.h | 3 +++ include/soc/mscc/ocelot_sys.h | 10 ---------- 5 files changed, 15 insertions(+), 18 deletions(-) (limited to 'include/soc/mscc') diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c index d640146acc3d..fea482ad92c7 100644 --- a/drivers/net/dsa/ocelot/felix_vsc9959.c +++ b/drivers/net/dsa/ocelot/felix_vsc9959.c @@ -515,6 +515,9 @@ static const struct reg_field vsc9959_regfields[REGFIELD_MAX] = { [SYS_PORT_MODE_INCL_INJ_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 3, 4, 7, 4), [SYS_PORT_MODE_INCL_XTR_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 1, 2, 7, 4), [SYS_PORT_MODE_INCL_HDR_ERR] = REG_FIELD_ID(SYS_PORT_MODE, 0, 0, 7, 4), + [SYS_PAUSE_CFG_PAUSE_START] = REG_FIELD_ID(SYS_PAUSE_CFG, 10, 18, 7, 4), + [SYS_PAUSE_CFG_PAUSE_STOP] = REG_FIELD_ID(SYS_PAUSE_CFG, 1, 9, 7, 4), + [SYS_PAUSE_CFG_PAUSE_ENA] = REG_FIELD_ID(SYS_PAUSE_CFG, 0, 1, 7, 4), }; static const struct ocelot_stat_layout vsc9959_stats_layout[] = { diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 2a44305912d2..4d5222fa3397 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -1276,10 +1276,10 @@ void ocelot_port_set_maxlen(struct ocelot *ocelot, int port, size_t sdu) /* Set Pause watermark hysteresis */ pause_start = 6 * maxlen / OCELOT_BUFFER_CELL_SZ; pause_stop = 4 * maxlen / OCELOT_BUFFER_CELL_SZ; - ocelot_rmw_rix(ocelot, SYS_PAUSE_CFG_PAUSE_START(pause_start), - SYS_PAUSE_CFG_PAUSE_START_M, SYS_PAUSE_CFG, port); - ocelot_rmw_rix(ocelot, SYS_PAUSE_CFG_PAUSE_STOP(pause_stop), - SYS_PAUSE_CFG_PAUSE_STOP_M, SYS_PAUSE_CFG, port); + ocelot_fields_write(ocelot, port, SYS_PAUSE_CFG_PAUSE_START, + pause_start); + ocelot_fields_write(ocelot, port, SYS_PAUSE_CFG_PAUSE_STOP, + pause_stop); /* Tail dropping watermark */ atop_wm = (ocelot->shared_queue_sz - 9 * maxlen) / @@ -1343,8 +1343,7 @@ void ocelot_init_port(struct ocelot *ocelot, int port) ocelot_port_writel(ocelot_port, 0, DEV_MAC_FC_MAC_LOW_CFG); /* Enable transmission of pause frames */ - ocelot_rmw_rix(ocelot, SYS_PAUSE_CFG_PAUSE_ENA, SYS_PAUSE_CFG_PAUSE_ENA, - SYS_PAUSE_CFG, port); + ocelot_fields_write(ocelot, port, SYS_PAUSE_CFG_PAUSE_ENA, 1); /* Drop frames with multicast source address */ ocelot_rmw_gix(ocelot, ANA_PORT_DROP_CFG_DROP_MC_SMAC_ENA, @@ -1403,8 +1402,7 @@ void ocelot_configure_cpu(struct ocelot *ocelot, int npi, injection); /* Disable transmission of pause frames */ - ocelot_rmw_rix(ocelot, 0, SYS_PAUSE_CFG_PAUSE_ENA, - SYS_PAUSE_CFG, npi); + ocelot_fields_write(ocelot, npi, SYS_PAUSE_CFG_PAUSE_ENA, 0); } /* Enable CPU port module */ diff --git a/drivers/net/ethernet/mscc/ocelot_vsc7514.c b/drivers/net/ethernet/mscc/ocelot_vsc7514.c index 9c6a9d44871d..e9cbfbed1fc6 100644 --- a/drivers/net/ethernet/mscc/ocelot_vsc7514.c +++ b/drivers/net/ethernet/mscc/ocelot_vsc7514.c @@ -369,6 +369,9 @@ static const struct reg_field ocelot_regfields[REGFIELD_MAX] = { [SYS_PORT_MODE_INCL_INJ_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 3, 4, 11, 4), [SYS_PORT_MODE_INCL_XTR_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 1, 2, 11, 4), [SYS_PORT_MODE_INCL_HDR_ERR] = REG_FIELD_ID(SYS_PORT_MODE, 0, 0, 11, 4), + [SYS_PAUSE_CFG_PAUSE_START] = REG_FIELD_ID(SYS_PAUSE_CFG, 10, 18, 11, 4), + [SYS_PAUSE_CFG_PAUSE_STOP] = REG_FIELD_ID(SYS_PAUSE_CFG, 1, 9, 11, 4), + [SYS_PAUSE_CFG_PAUSE_ENA] = REG_FIELD_ID(SYS_PAUSE_CFG, 0, 1, 11, 4), }; static const struct ocelot_stat_layout ocelot_stats_layout[] = { diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index 6cfbace57770..71bb92bcfdf7 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -511,6 +511,9 @@ enum ocelot_regfield { GCB_SOFT_RST_SWC_RST, GCB_MIIM_MII_STATUS_PENDING, GCB_MIIM_MII_STATUS_BUSY, + SYS_PAUSE_CFG_PAUSE_START, + SYS_PAUSE_CFG_PAUSE_STOP, + SYS_PAUSE_CFG_PAUSE_ENA, REGFIELD_MAX }; diff --git a/include/soc/mscc/ocelot_sys.h b/include/soc/mscc/ocelot_sys.h index 8a95fc93fde5..79cf40ccdbe6 100644 --- a/include/soc/mscc/ocelot_sys.h +++ b/include/soc/mscc/ocelot_sys.h @@ -43,16 +43,6 @@ #define SYS_TIMESTAMP_OFFSET_TIMESTAMP_OFFSET(x) ((x) & GENMASK(5, 0)) #define SYS_TIMESTAMP_OFFSET_TIMESTAMP_OFFSET_M GENMASK(5, 0) -#define SYS_PAUSE_CFG_RSZ 0x4 - -#define SYS_PAUSE_CFG_PAUSE_START(x) (((x) << 10) & GENMASK(18, 10)) -#define SYS_PAUSE_CFG_PAUSE_START_M GENMASK(18, 10) -#define SYS_PAUSE_CFG_PAUSE_START_X(x) (((x) & GENMASK(18, 10)) >> 10) -#define SYS_PAUSE_CFG_PAUSE_STOP(x) (((x) << 1) & GENMASK(9, 1)) -#define SYS_PAUSE_CFG_PAUSE_STOP_M GENMASK(9, 1) -#define SYS_PAUSE_CFG_PAUSE_STOP_X(x) (((x) & GENMASK(9, 1)) >> 1) -#define SYS_PAUSE_CFG_PAUSE_ENA BIT(0) - #define SYS_PAUSE_TOT_CFG_PAUSE_TOT_START(x) (((x) << 9) & GENMASK(17, 9)) #define SYS_PAUSE_TOT_CFG_PAUSE_TOT_START_M GENMASK(17, 9) #define SYS_PAUSE_TOT_CFG_PAUSE_TOT_START_X(x) (((x) & GENMASK(17, 9)) >> 9) -- cgit v1.2.3 From aa92d836d5c40a7e21e563a272ad177f1bfd44dd Mon Sep 17 00:00:00 2001 From: Maxim Kochetkov Date: Mon, 13 Jul 2020 19:57:08 +0300 Subject: net: mscc: ocelot: extend watermark encoding function The ocelot_wm_encode function deals with setting thresholds for pause frame start and stop. In Ocelot and Felix the register layout is the same, but for Seville, it isn't. The easiest way to accommodate Seville hardware configuration is to introduce a function pointer for setting this up. Signed-off-by: Maxim Kochetkov Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/ocelot/felix_vsc9959.c | 13 +++++++++++++ drivers/net/ethernet/mscc/ocelot.c | 16 ++-------------- drivers/net/ethernet/mscc/ocelot_vsc7514.c | 13 +++++++++++++ include/soc/mscc/ocelot.h | 1 + 4 files changed, 29 insertions(+), 14 deletions(-) (limited to 'include/soc/mscc') diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c index fea482ad92c7..7e8a99455670 100644 --- a/drivers/net/dsa/ocelot/felix_vsc9959.c +++ b/drivers/net/dsa/ocelot/felix_vsc9959.c @@ -1149,8 +1149,21 @@ static int vsc9959_prevalidate_phy_mode(struct ocelot *ocelot, int port, } } +/* Watermark encode + * Bit 8: Unit; 0:1, 1:16 + * Bit 7-0: Value to be multiplied with unit + */ +static u16 vsc9959_wm_enc(u16 value) +{ + if (value >= BIT(8)) + return BIT(8) | (value / 16); + + return value; +} + static const struct ocelot_ops vsc9959_ops = { .reset = vsc9959_reset, + .wm_enc = vsc9959_wm_enc, }; static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot) diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 4d5222fa3397..f2d94b026d88 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -309,18 +309,6 @@ static void ocelot_vlan_init(struct ocelot *ocelot) } } -/* Watermark encode - * Bit 8: Unit; 0:1, 1:16 - * Bit 7-0: Value to be multiplied with unit - */ -static u16 ocelot_wm_enc(u16 value) -{ - if (value >= BIT(8)) - return BIT(8) | (value / 16); - - return value; -} - void ocelot_adjust_link(struct ocelot *ocelot, int port, struct phy_device *phydev) { @@ -1284,9 +1272,9 @@ void ocelot_port_set_maxlen(struct ocelot *ocelot, int port, size_t sdu) /* Tail dropping watermark */ atop_wm = (ocelot->shared_queue_sz - 9 * maxlen) / OCELOT_BUFFER_CELL_SZ; - ocelot_write_rix(ocelot, ocelot_wm_enc(9 * maxlen), + ocelot_write_rix(ocelot, ocelot->ops->wm_enc(9 * maxlen), SYS_ATOP, port); - ocelot_write(ocelot, ocelot_wm_enc(atop_wm), SYS_ATOP_TOT_CFG); + ocelot_write(ocelot, ocelot->ops->wm_enc(atop_wm), SYS_ATOP_TOT_CFG); } EXPORT_SYMBOL(ocelot_port_set_maxlen); diff --git a/drivers/net/ethernet/mscc/ocelot_vsc7514.c b/drivers/net/ethernet/mscc/ocelot_vsc7514.c index e9cbfbed1fc6..0ead1ef11c6c 100644 --- a/drivers/net/ethernet/mscc/ocelot_vsc7514.c +++ b/drivers/net/ethernet/mscc/ocelot_vsc7514.c @@ -739,8 +739,21 @@ static int ocelot_reset(struct ocelot *ocelot) return 0; } +/* Watermark encode + * Bit 8: Unit; 0:1, 1:16 + * Bit 7-0: Value to be multiplied with unit + */ +static u16 ocelot_wm_enc(u16 value) +{ + if (value >= BIT(8)) + return BIT(8) | (value / 16); + + return value; +} + static const struct ocelot_ops ocelot_ops = { .reset = ocelot_reset, + .wm_enc = ocelot_wm_enc, }; static const struct vcap_field vsc7514_vcap_is2_keys[] = { diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index 71bb92bcfdf7..da369b12005f 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -541,6 +541,7 @@ struct ocelot; struct ocelot_ops { int (*reset)(struct ocelot *ocelot); + u16 (*wm_enc)(u16 value); }; struct ocelot_vcap_block { -- cgit v1.2.3