Commit f50e38c9 authored by Tony Lindgren's avatar Tony Lindgren Committed by Mark Brown

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: default avatarTony Lindgren <tony@atomide.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 29b4817d
...@@ -105,8 +105,8 @@ struct regmap { ...@@ -105,8 +105,8 @@ struct regmap {
bool defer_caching; bool defer_caching;
u8 read_flag_mask; unsigned long read_flag_mask;
u8 write_flag_mask; unsigned long write_flag_mask;
/* number of bits to (left) shift the reg value when formatting*/ /* number of bits to (left) shift the reg value when formatting*/
int reg_shift; int reg_shift;
......
...@@ -1296,12 +1296,26 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg, ...@@ -1296,12 +1296,26 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg,
return 0; 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, int _regmap_raw_write(struct regmap *map, unsigned int reg,
const void *val, size_t val_len) const void *val, size_t val_len)
{ {
struct regmap_range_node *range; struct regmap_range_node *range;
unsigned long flags; unsigned long flags;
u8 *u8 = map->work_buf;
void *work_val = map->work_buf + map->format.reg_bytes + void *work_val = map->work_buf + map->format.reg_bytes +
map->format.pad_bytes; map->format.pad_bytes;
void *buf; void *buf;
...@@ -1370,8 +1384,8 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg, ...@@ -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); map->format.format_reg(map->work_buf, reg, map->reg_shift);
regmap_set_work_buf_flag_mask(map, map->format.reg_bytes,
u8[0] |= map->write_flag_mask; map->write_flag_mask);
/* /*
* Essentially all I/O mechanisms will be faster with a single * 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, ...@@ -2245,7 +2259,6 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
unsigned int val_len) unsigned int val_len)
{ {
struct regmap_range_node *range; struct regmap_range_node *range;
u8 *u8 = map->work_buf;
int ret; int ret;
WARN_ON(!map->bus); WARN_ON(!map->bus);
...@@ -2262,15 +2275,8 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, ...@@ -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); map->format.format_reg(map->work_buf, reg, map->reg_shift);
regmap_set_work_buf_flag_mask(map, map->format.reg_bytes,
/* map->read_flag_mask);
* 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;
trace_regmap_hw_read_start(map, reg, val_len / map->format.val_bytes); trace_regmap_hw_read_start(map, reg, val_len / map->format.val_bytes);
ret = map->bus->read(map->bus_context, map->work_buf, ret = map->bus->read(map->bus_context, map->work_buf,
......
...@@ -241,9 +241,9 @@ typedef void (*regmap_unlock)(void *); ...@@ -241,9 +241,9 @@ typedef void (*regmap_unlock)(void *);
* register cache support). * register cache support).
* @num_reg_defaults: Number of elements in reg_defaults. * @num_reg_defaults: Number of elements in reg_defaults.
* *
* @read_flag_mask: Mask to be set in the top byte of the register when doing * @read_flag_mask: Mask to be set in the top bytes of the register when doing
* a read. * a read.
* @write_flag_mask: Mask to be set in the top byte of the register when doing * @write_flag_mask: Mask to be set in the top bytes of the register when doing
* a write. If both read_flag_mask and write_flag_mask are * a write. If both read_flag_mask and write_flag_mask are
* empty the regmap_bus default masks are used. * empty the regmap_bus default masks are used.
* @use_single_rw: If set, converts the bulk read and write operations into * @use_single_rw: If set, converts the bulk read and write operations into
...@@ -299,8 +299,8 @@ struct regmap_config { ...@@ -299,8 +299,8 @@ struct regmap_config {
const void *reg_defaults_raw; const void *reg_defaults_raw;
unsigned int num_reg_defaults_raw; unsigned int num_reg_defaults_raw;
u8 read_flag_mask; unsigned long read_flag_mask;
u8 write_flag_mask; unsigned long write_flag_mask;
bool use_single_rw; bool use_single_rw;
bool can_multi_write; bool can_multi_write;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment