Prepare a single regmap covering the entire SPI address space of the SJA1105 and SJA1110 switches which can be given to MDIO buses, XPCS, irqchip drivers etc. This regmap is zero-based, can access the entire switch address space, and child devices are supposed to access their respective memory region with the help of struct resource (IORESOURCE_REG, to be precise). Nothing is currently done with the regmap, it is just allocated and added to the device's devres list, so it doesn't need to be freed. Signed-off-by: Vladimir Oltean --- drivers/net/dsa/sja1105/sja1105.h | 4 ++ drivers/net/dsa/sja1105/sja1105_main.c | 6 +++ drivers/net/dsa/sja1105/sja1105_spi.c | 58 ++++++++++++++++++++++++++ 3 files changed, 68 insertions(+) diff --git a/drivers/net/dsa/sja1105/sja1105.h b/drivers/net/dsa/sja1105/sja1105.h index dceb96ae9c83..e952917b67b6 100644 --- a/drivers/net/dsa/sja1105/sja1105.h +++ b/drivers/net/dsa/sja1105/sja1105.h @@ -11,6 +11,8 @@ #include #include #include +#include + #include "sja1105_static_config.h" #define SJA1105ET_FDB_BIN_SIZE 4 @@ -273,6 +275,7 @@ struct sja1105_private { u8 ts_id; /* Serializes access to the dynamic config interface */ struct mutex dynamic_config_lock; + struct regmap *regmap; struct devlink_region **regions; struct sja1105_cbs_entry *cbs; struct mii_bus *mdio_base_t1; @@ -338,6 +341,7 @@ int static_config_buf_prepare_for_upload(struct sja1105_private *priv, int sja1105_static_config_upload(struct sja1105_private *priv); int sja1105_inhibit_tx(const struct sja1105_private *priv, unsigned long port_bitmap, bool tx_inhibited); +int sja1105_create_regmap(struct sja1105_private *priv); extern const struct sja1105_info sja1105e_info; extern const struct sja1105_info sja1105t_info; diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index 9f62cc7e1bd1..622264c13fdb 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -3318,6 +3318,12 @@ static int sja1105_probe(struct spi_device *spi) priv->info = of_device_get_match_data(dev); + rc = sja1105_create_regmap(priv); + if (rc < 0) { + dev_err(dev, "Failed to create regmap: %pe\n", ERR_PTR(rc)); + return rc; + } + /* Detect hardware device */ rc = sja1105_check_device_id(priv); if (rc < 0) { diff --git a/drivers/net/dsa/sja1105/sja1105_spi.c b/drivers/net/dsa/sja1105/sja1105_spi.c index 834b5c1b4db0..cfc76af8a65b 100644 --- a/drivers/net/dsa/sja1105/sja1105_spi.c +++ b/drivers/net/dsa/sja1105/sja1105_spi.c @@ -408,6 +408,64 @@ int sja1105_static_config_upload(struct sja1105_private *priv) return rc; } +static int sja1105_regmap_bus_reg_read(void *ctx, unsigned int reg, + unsigned int *val) +{ + struct sja1105_private *priv = ctx; + u32 tmp; + int rc; + + rc = sja1105_xfer_u32(priv, SPI_READ, SJA1110_SPI_ADDR(reg), &tmp, + NULL); + if (rc) + return rc; + + *val = tmp; + + return 0; +} + +static int sja1105_regmap_bus_reg_write(void *ctx, unsigned int reg, + unsigned int val) +{ + struct sja1105_private *priv = ctx; + u32 tmp = val; + + return sja1105_xfer_u32(priv, SPI_WRITE, SJA1110_SPI_ADDR(reg), &tmp, + NULL); +} + +static struct regmap_bus sja1105_regmap_bus = { + .reg_read = sja1105_regmap_bus_reg_read, + .reg_write = sja1105_regmap_bus_reg_write, + .reg_format_endian_default = REGMAP_ENDIAN_NATIVE, + .val_format_endian_default = REGMAP_ENDIAN_NATIVE, +}; + +/* The primary purpose of this is to pass it to child devices, + * not to abstract SPI access for the main driver. + */ +int sja1105_create_regmap(struct sja1105_private *priv) +{ + struct device *dev = &priv->spidev->dev; + struct regmap_config regmap_config = { + .name = "switch", + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + }; + struct regmap *regmap; + + regmap = devm_regmap_init(dev, &sja1105_regmap_bus, priv, + ®map_config); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + priv->regmap = regmap; + + return 0; +} + static const struct sja1105_regs sja1105et_regs = { .device_id = 0x0, .prod_id = 0x100BC3, -- 2.34.1