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 address-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. Cc: Mark Brown Signed-off-by: Vladimir Oltean --- v1->v2: - s/sja1105_create_regmap()/devm_sja1105_create_regmap()/ for clarity in sja1105_probe() that teardown is not needed. - drop unnecessary priv->regmap drivers/net/dsa/sja1105/sja1105.h | 3 ++ drivers/net/dsa/sja1105/sja1105_main.c | 6 +++ drivers/net/dsa/sja1105/sja1105_spi.c | 55 ++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) diff --git a/drivers/net/dsa/sja1105/sja1105.h b/drivers/net/dsa/sja1105/sja1105.h index dceb96ae9c83..8d4c0c8df326 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 @@ -338,6 +340,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 devm_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 2a4a0fe20dae..e9e091cf8998 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -3291,6 +3291,12 @@ static int sja1105_probe(struct spi_device *spi) priv->info = of_device_get_match_data(dev); + rc = devm_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..856a751de53a 100644 --- a/drivers/net/dsa/sja1105/sja1105_spi.c +++ b/drivers/net/dsa/sja1105/sja1105_spi.c @@ -408,6 +408,61 @@ 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); +} + +/* The primary purpose of this is to pass it to child devices, + * not to abstract SPI access for the main driver. + */ +int devm_sja1105_create_regmap(struct sja1105_private *priv) +{ + static const 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, + }; + static const struct regmap_config regmap_config = { + .name = "regs", + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + }; + struct device *dev = &priv->spidev->dev; + struct regmap *regmap; + + regmap = devm_regmap_init(dev, &sja1105_regmap_bus, priv, + ®map_config); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + return 0; +} + static const struct sja1105_regs sja1105et_regs = { .device_id = 0x0, .prod_id = 0x100BC3, -- 2.34.1