diff mbox series

[RFC,vN,net-next,1/2] net: mscc: ocelot: add support for non-mmio regmaps

Message ID 20210504051130.1207550-1-colin.foster@in-advantage.com (mailing list archive)
State RFC
Delegated to: Netdev Maintainers
Headers show
Series [RFC,vN,net-next,1/2] net: mscc: ocelot: add support for non-mmio regmaps | expand

Checks

Context Check Description
netdev/cover_letter success Link
netdev/fixes_present success Link
netdev/patch_count success Link
netdev/tree_selection success Clearly marked for net-next
netdev/subject_prefix success Link
netdev/cc_maintainers success CCed 11 of 11 maintainers
netdev/source_inline success Was 0 now: 0
netdev/verify_signedoff success Link
netdev/module_param success Was 0 now: 0
netdev/build_32bit fail Errors and warnings before: 0 this patch: 8
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/verify_fixes success Link
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 141 lines checked
netdev/build_allmodconfig_warn fail Errors and warnings before: 0 this patch: 8
netdev/header_inline success Link

Commit Message

Colin Foster May 4, 2021, 5:11 a.m. UTC
Control for external VSC75XX chips can be performed via non-mmio
interfaces, e.g. SPI. Adding the offets array (one per target) and
the offset element per port allows the ability to track this
location that would otherwise be found in the MMIO regmap resource.

Tracking this offset in the ocelot driver and allowing the
ocelot_regmap_init function to be overloaded with a device-specific
initializer. This driver could update the *offset element to handle the
value that would otherwise be mapped via resource *res->start.

Signed-off-by: Colin Foster <colin.foster@in-advantage.com>
---
 drivers/net/dsa/ocelot/felix.c           |  6 ++++--
 drivers/net/dsa/ocelot/felix.h           |  2 ++
 drivers/net/dsa/ocelot/felix_vsc9959.c   |  1 +
 drivers/net/dsa/ocelot/seville_vsc9953.c |  1 +
 drivers/net/ethernet/mscc/ocelot_io.c    | 27 +++++++++++++++++-------
 include/soc/mscc/ocelot.h                |  5 ++++-
 6 files changed, 31 insertions(+), 11 deletions(-)
diff mbox series

Patch

diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c
index 628afb47b579..71aa11b209e8 100644
--- a/drivers/net/dsa/ocelot/felix.c
+++ b/drivers/net/dsa/ocelot/felix.c
@@ -1122,7 +1122,8 @@  static int felix_init_structs(struct felix *felix, int num_phys_ports)
 		res.start += felix->switch_base;
 		res.end += felix->switch_base;
 
-		target = ocelot_regmap_init(ocelot, &res);
+		target = felix->info->init_regmap(ocelot, &res,
+						  &ocelot->offsets[i]);
 		if (IS_ERR(target)) {
 			dev_err(ocelot->dev,
 				"Failed to map device memory space\n");
@@ -1159,7 +1160,8 @@  static int felix_init_structs(struct felix *felix, int num_phys_ports)
 		res.start += felix->switch_base;
 		res.end += felix->switch_base;
 
-		target = ocelot_regmap_init(ocelot, &res);
+		target = felix->info->init_regmap(ocelot, &res,
+						  &ocelot_port->offset);
 		if (IS_ERR(target)) {
 			dev_err(ocelot->dev,
 				"Failed to map memory space for port %d\n",
diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h
index 4d96cad815d5..03ae576e018a 100644
--- a/drivers/net/dsa/ocelot/felix.h
+++ b/drivers/net/dsa/ocelot/felix.h
@@ -47,6 +47,8 @@  struct felix_info {
 				 enum tc_setup_type type, void *type_data);
 	void	(*port_sched_speed_set)(struct ocelot *ocelot, int port,
 					u32 speed);
+	struct regmap *(*init_regmap)(struct ocelot *ocelot,
+				      struct resource *res, u32 *offset);
 };
 
 extern const struct dsa_switch_ops felix_switch_ops;
diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c
index 5ff623ee76a6..87178345116b 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -1362,6 +1362,7 @@  static const 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,
+	.init_regmap		= ocelot_regmap_init,
 };
 
 static irqreturn_t felix_irq_handler(int irq, void *data)
diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c
index 84f93a874d50..d88a9729222c 100644
--- a/drivers/net/dsa/ocelot/seville_vsc9953.c
+++ b/drivers/net/dsa/ocelot/seville_vsc9953.c
@@ -1181,6 +1181,7 @@  static const struct felix_info seville_info_vsc9953 = {
 	.mdio_bus_free		= vsc9953_mdio_bus_free,
 	.phylink_validate	= vsc9953_phylink_validate,
 	.prevalidate_phy_mode	= vsc9953_prevalidate_phy_mode,
+	.init_regmap		= ocelot_regmap_init,
 };
 
 static int seville_probe(struct platform_device *pdev)
diff --git a/drivers/net/ethernet/mscc/ocelot_io.c b/drivers/net/ethernet/mscc/ocelot_io.c
index ea4e83410fe4..8f314639faff 100644
--- a/drivers/net/ethernet/mscc/ocelot_io.c
+++ b/drivers/net/ethernet/mscc/ocelot_io.c
@@ -18,7 +18,8 @@  u32 __ocelot_read_ix(struct ocelot *ocelot, u32 reg, u32 offset)
 	WARN_ON(!target);
 
 	regmap_read(ocelot->targets[target],
-		    ocelot->map[target][reg & REG_MASK] + offset, &val);
+		    ocelot->offsets[target] +
+			    ocelot->map[target][reg & REG_MASK] + offset, &val);
 	return val;
 }
 EXPORT_SYMBOL(__ocelot_read_ix);
@@ -30,7 +31,8 @@  void __ocelot_write_ix(struct ocelot *ocelot, u32 val, u32 reg, u32 offset)
 	WARN_ON(!target);
 
 	regmap_write(ocelot->targets[target],
-		     ocelot->map[target][reg & REG_MASK] + offset, val);
+		     ocelot->offsets[target] +
+			     ocelot->map[target][reg & REG_MASK] + offset, val);
 }
 EXPORT_SYMBOL(__ocelot_write_ix);
 
@@ -42,7 +44,8 @@  void __ocelot_rmw_ix(struct ocelot *ocelot, u32 val, u32 mask, u32 reg,
 	WARN_ON(!target);
 
 	regmap_update_bits(ocelot->targets[target],
-			   ocelot->map[target][reg & REG_MASK] + offset,
+			   ocelot->offsets[target] +
+				   ocelot->map[target][reg & REG_MASK] + offset,
 			   mask, val);
 }
 EXPORT_SYMBOL(__ocelot_rmw_ix);
@@ -55,7 +58,8 @@  u32 ocelot_port_readl(struct ocelot_port *port, u32 reg)
 
 	WARN_ON(!target);
 
-	regmap_read(port->target, ocelot->map[target][reg & REG_MASK], &val);
+	regmap_read(port->target,
+		    port->offset + ocelot->map[target][reg & REG_MASK], &val);
 	return val;
 }
 EXPORT_SYMBOL(ocelot_port_readl);
@@ -67,7 +71,8 @@  void ocelot_port_writel(struct ocelot_port *port, u32 val, u32 reg)
 
 	WARN_ON(!target);
 
-	regmap_write(port->target, ocelot->map[target][reg & REG_MASK], val);
+	regmap_write(port->target,
+		     port->offset + ocelot->map[target][reg & REG_MASK], val);
 }
 EXPORT_SYMBOL(ocelot_port_writel);
 
@@ -85,7 +90,8 @@  u32 __ocelot_target_read_ix(struct ocelot *ocelot, enum ocelot_target target,
 	u32 val;
 
 	regmap_read(ocelot->targets[target],
-		    ocelot->map[target][reg] + offset, &val);
+		    ocelot->offsets[target] + ocelot->map[target][reg] + offset,
+		    &val);
 	return val;
 }
 
@@ -93,7 +99,9 @@  void __ocelot_target_write_ix(struct ocelot *ocelot, enum ocelot_target target,
 			      u32 val, u32 reg, u32 offset)
 {
 	regmap_write(ocelot->targets[target],
-		     ocelot->map[target][reg] + offset, val);
+		     ocelot->offsets[target] + ocelot->map[target][reg] +
+			     offset,
+		     val);
 }
 
 int ocelot_regfields_init(struct ocelot *ocelot,
@@ -136,10 +144,13 @@  static struct regmap_config ocelot_regmap_config = {
 	.reg_stride	= 4,
 };
 
-struct regmap *ocelot_regmap_init(struct ocelot *ocelot, struct resource *res)
+struct regmap *ocelot_regmap_init(struct ocelot *ocelot, struct resource *res,
+				  u32 *offset)
 {
 	void __iomem *regs;
 
+	*offset = 0;
+
 	regs = devm_ioremap_resource(ocelot->dev, res);
 	if (IS_ERR(regs))
 		return ERR_CAST(regs);
diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
index 425ff29d9389..ad45c1af4be9 100644
--- a/include/soc/mscc/ocelot.h
+++ b/include/soc/mscc/ocelot.h
@@ -591,6 +591,7 @@  struct ocelot_port {
 	struct ocelot			*ocelot;
 
 	struct regmap			*target;
+	u32				offset;
 
 	bool				vlan_aware;
 	/* VLAN that untagged frames are classified to, on ingress */
@@ -621,6 +622,7 @@  struct ocelot {
 	const struct ocelot_ops		*ops;
 	struct regmap			*targets[TARGET_MAX];
 	struct regmap_field		*regfields[REGFIELD_MAX];
+	u32				offsets[TARGET_MAX];
 	const u32 *const		*map;
 	const struct ocelot_stat_layout	*stats_layout;
 	unsigned int			num_stats;
@@ -780,7 +782,8 @@  static inline void ocelot_drain_cpu_queue(struct ocelot *ocelot, int grp)
 /* Hardware initialization */
 int ocelot_regfields_init(struct ocelot *ocelot,
 			  const struct reg_field *const regfields);
-struct regmap *ocelot_regmap_init(struct ocelot *ocelot, struct resource *res);
+struct regmap *ocelot_regmap_init(struct ocelot *ocelot, struct resource *res,
+				  u32 *offset);
 int ocelot_init(struct ocelot *ocelot);
 void ocelot_deinit(struct ocelot *ocelot);
 void ocelot_init_port(struct ocelot *ocelot, int port);