Skip to content

Commit 4a670ac

Browse files
minimaxwellbroonie
authored andcommitted
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>
1 parent 383b323 commit 4a670ac

4 files changed

Lines changed: 22 additions & 7 deletions

File tree

drivers/base/regmap/internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ struct regmap_format {
3131
size_t buf_size;
3232
size_t reg_bytes;
3333
size_t pad_bytes;
34-
size_t reg_downshift;
3534
size_t val_bytes;
35+
s8 reg_shift;
3636
void (*format_write)(struct regmap *map,
3737
unsigned int reg, unsigned int val);
3838
void (*format_reg)(void *buf, unsigned int reg, unsigned int shift);

drivers/base/regmap/regmap.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -814,7 +814,7 @@ struct regmap *__regmap_init(struct device *dev,
814814

815815
map->format.reg_bytes = DIV_ROUND_UP(config->reg_bits, 8);
816816
map->format.pad_bytes = config->pad_bits / 8;
817-
map->format.reg_downshift = config->reg_downshift;
817+
map->format.reg_shift = config->reg_shift;
818818
map->format.val_bytes = DIV_ROUND_UP(config->val_bits, 8);
819819
map->format.buf_size = DIV_ROUND_UP(config->reg_bits +
820820
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,
16791679
static unsigned int regmap_reg_addr(struct regmap *map, unsigned int reg)
16801680
{
16811681
reg += map->reg_base;
1682-
return reg >> map->format.reg_downshift;
1682+
1683+
if (map->format.reg_shift > 0)
1684+
reg >>= map->format.reg_shift;
1685+
else if (map->format.reg_shift < 0)
1686+
reg <<= -(map->format.reg_shift);
1687+
1688+
return reg;
16831689
}
16841690

16851691
static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg,

drivers/mfd/ocelot-spi.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ static int ocelot_spi_initialize(struct device *dev)
125125
static const struct regmap_config ocelot_spi_regmap_config = {
126126
.reg_bits = 24,
127127
.reg_stride = 4,
128-
.reg_downshift = 2,
128+
.reg_shift = REGMAP_DOWNSHIFT(2),
129129
.val_bits = 32,
130130

131131
.write_flag_mask = 0x80,

include/linux/regmap.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,14 @@ struct sdw_slave;
4646
#define REGMAP_MDIO_C45_DEVAD_MASK GENMASK(20, 16)
4747
#define REGMAP_MDIO_C45_REGNUM_MASK GENMASK(15, 0)
4848

49+
/*
50+
* regmap.reg_shift indicates by how much we must shift registers prior to
51+
* performing any operation. It's a signed value, positive numbers means
52+
* downshifting the register's address, while negative numbers means upshifting.
53+
*/
54+
#define REGMAP_UPSHIFT(s) (-(s))
55+
#define REGMAP_DOWNSHIFT(s) (s)
56+
4957
/* An enum of all the supported cache types */
5058
enum regcache_type {
5159
REGCACHE_NONE,
@@ -246,8 +254,9 @@ typedef void (*regmap_unlock)(void *);
246254
* @reg_stride: The register address stride. Valid register addresses are a
247255
* multiple of this value. If set to 0, a value of 1 will be
248256
* used.
249-
* @reg_downshift: The number of bits to downshift the register before
250-
* performing any operations.
257+
* @reg_shift: The number of bits to shift the register before performing any
258+
* operations. Any positive number will be downshifted, and negative
259+
* values will be upshifted
251260
* @reg_base: Value to be added to every register address before performing any
252261
* operation.
253262
* @pad_bits: Number of bits of padding between register and value.
@@ -381,7 +390,7 @@ struct regmap_config {
381390

382391
int reg_bits;
383392
int reg_stride;
384-
int reg_downshift;
393+
int reg_shift;
385394
unsigned int reg_base;
386395
int pad_bits;
387396
int val_bits;

0 commit comments

Comments
 (0)