summaryrefslogtreecommitdiff
path: root/drivers/base
diff options
context:
space:
mode:
authorMaxime Chevallier <maxime.chevallier@bootlin.com>2023-04-07 18:26:04 +0300
committerMark Brown <broonie@kernel.org>2023-04-07 19:28:19 +0300
commit4a670ac3e75e517c96cbd01ef870dbd598c3ce71 (patch)
tree178ae97c2c5108439db90558848096d6179d3187 /drivers/base
parent383b3232732dca5b084a8f90b529d53c18b03e74 (diff)
downloadlinux-4a670ac3e75e517c96cbd01ef870dbd598c3ce71.tar.xz
regmap: allow upshifting register addresses before performing operations
Similar to the existing reg_downshift mechanism, that is used to translate register addresses on busses that have a smaller address stride, it's also possible to want to upshift register addresses. Such a case was encountered when network PHYs and PCS that usually sit on a MDIO bus (16-bits register with a stride of 1) are integrated directly as memory-mapped devices. Here, the same register layout defined in 802.3 is used, but the register now have a larger stride. Introduce a mechanism to also allow upshifting register addresses. Re-purpose reg_downshift into a more generic, signed reg_shift, whose sign indicates the direction of the shift. To avoid confusion, also introduce macros to explicitly indicate if we want to downshift or upshift. For bisectability, change any use of reg_downshift to use reg_shift. Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com> Tested-by: Colin Foster <colin.foster@in-advantage.com> Link: https://lore.kernel.org/r/20230407152604.105467-1-maxime.chevallier@bootlin.com Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/regmap/internal.h2
-rw-r--r--drivers/base/regmap/regmap.c10
2 files changed, 9 insertions, 3 deletions
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index 6361df6f553a..9bd0dfd1e259 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -31,8 +31,8 @@ struct regmap_format {
size_t buf_size;
size_t reg_bytes;
size_t pad_bytes;
- size_t reg_downshift;
size_t val_bytes;
+ s8 reg_shift;
void (*format_write)(struct regmap *map,
unsigned int reg, unsigned int val);
void (*format_reg)(void *buf, unsigned int reg, unsigned int shift);
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 473b65b102db..db7851f0e3b8 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -814,7 +814,7 @@ struct regmap *__regmap_init(struct device *dev,
map->format.reg_bytes = DIV_ROUND_UP(config->reg_bits, 8);
map->format.pad_bytes = config->pad_bits / 8;
- map->format.reg_downshift = config->reg_downshift;
+ map->format.reg_shift = config->reg_shift;
map->format.val_bytes = DIV_ROUND_UP(config->val_bits, 8);
map->format.buf_size = DIV_ROUND_UP(config->reg_bits +
config->val_bits + config->pad_bits, 8);
@@ -1679,7 +1679,13 @@ static void regmap_set_work_buf_flag_mask(struct regmap *map, int max_bytes,
static unsigned int regmap_reg_addr(struct regmap *map, unsigned int reg)
{
reg += map->reg_base;
- return reg >> map->format.reg_downshift;
+
+ if (map->format.reg_shift > 0)
+ reg >>= map->format.reg_shift;
+ else if (map->format.reg_shift < 0)
+ reg <<= -(map->format.reg_shift);
+
+ return reg;
}
static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg,