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>
This commit is contained in:
Maxime Chevallier
2023-04-07 17:26:04 +02:00
committed by Mark Brown
parent 383b323273
commit 4a670ac3e7
4 changed files with 22 additions and 7 deletions

View File

@@ -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,