summaryrefslogtreecommitdiff
path: root/drivers/base/regmap/regmap.c
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2016-09-15 23:56:10 +0300
committerMark Brown <broonie@kernel.org>2016-09-16 14:06:24 +0300
commitf50e38c9966076465bc8d9dd0bc582c268a0031e (patch)
tree094910c3f36be602c126d4fe6fd5edb4e631c68e /drivers/base/regmap/regmap.c
parent29b4817d4018df78086157ea3a55c1d9424a7cfc (diff)
downloadlinux-f50e38c9966076465bc8d9dd0bc582c268a0031e.tar.xz
regmap: Allow longer flag masks for read and write
We currently only support masking the top bit for read and write flags. Let's make the mask unsigned long and mask the bytes based on the configured register length to make things more generic. This allows using regmap for more exotic combinations like SPI devices that need little endian addressing. Signed-off-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/base/regmap/regmap.c')
-rw-r--r--drivers/base/regmap/regmap.c32
1 files changed, 19 insertions, 13 deletions
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 51fa7d66a393..a6a5236b6c8d 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -1296,12 +1296,26 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg,
return 0;
}
+static void regmap_set_work_buf_flag_mask(struct regmap *map, int max_bytes,
+ unsigned long mask)
+{
+ u8 *buf;
+ int i;
+
+ if (!mask || !map->work_buf)
+ return;
+
+ buf = map->work_buf;
+
+ for (i = 0; i < max_bytes; i++)
+ buf[i] |= (mask >> (8 * i)) & 0xff;
+}
+
int _regmap_raw_write(struct regmap *map, unsigned int reg,
const void *val, size_t val_len)
{
struct regmap_range_node *range;
unsigned long flags;
- u8 *u8 = map->work_buf;
void *work_val = map->work_buf + map->format.reg_bytes +
map->format.pad_bytes;
void *buf;
@@ -1370,8 +1384,8 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
}
map->format.format_reg(map->work_buf, reg, map->reg_shift);
-
- u8[0] |= map->write_flag_mask;
+ regmap_set_work_buf_flag_mask(map, map->format.reg_bytes,
+ map->write_flag_mask);
/*
* Essentially all I/O mechanisms will be faster with a single
@@ -2245,7 +2259,6 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
unsigned int val_len)
{
struct regmap_range_node *range;
- u8 *u8 = map->work_buf;
int ret;
WARN_ON(!map->bus);
@@ -2262,15 +2275,8 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
}
map->format.format_reg(map->work_buf, reg, map->reg_shift);
-
- /*
- * Some buses or devices flag reads by setting the high bits in the
- * register address; since it's always the high bits for all
- * current formats we can do this here rather than in
- * formatting. This may break if we get interesting formats.
- */
- u8[0] |= map->read_flag_mask;
-
+ regmap_set_work_buf_flag_mask(map, map->format.reg_bytes,
+ map->read_flag_mask);
trace_regmap_hw_read_start(map, reg, val_len / map->format.val_bytes);
ret = map->bus->read(map->bus_context, map->work_buf,