Commit 808c2b05 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'regmap-v4.9' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap

Pull regmap updates from Mark Brown:
 "Another quiet release, a few small extensions to the set of register
  maps we support and an improvement in the debugfs code:

   - allow viewing of cached contents for write only registers via
     debugfs.

   - support a wider range of read/write flag masks in register formats.

   - support more little endian formats"

* tag 'regmap-v4.9' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap:
  regmap: Add missing little endian functions
  regmap: Allow longer flag masks for read and write
  regmap: debugfs: Add support for dumping write only device registers
  regmap: Add a function to check if a regmap register is cached
parents 5617c122 f785fb2e
...@@ -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;
...@@ -173,6 +173,7 @@ struct regcache_ops { ...@@ -173,6 +173,7 @@ struct regcache_ops {
int (*drop)(struct regmap *map, unsigned int min, unsigned int max); int (*drop)(struct regmap *map, unsigned int min, unsigned int max);
}; };
bool regmap_cached(struct regmap *map, unsigned int reg);
bool regmap_writeable(struct regmap *map, unsigned int reg); bool regmap_writeable(struct regmap *map, unsigned int reg);
bool regmap_readable(struct regmap *map, unsigned int reg); bool regmap_readable(struct regmap *map, unsigned int reg);
bool regmap_volatile(struct regmap *map, unsigned int reg); bool regmap_volatile(struct regmap *map, unsigned int reg);
......
...@@ -77,6 +77,17 @@ static void regmap_debugfs_free_dump_cache(struct regmap *map) ...@@ -77,6 +77,17 @@ static void regmap_debugfs_free_dump_cache(struct regmap *map)
} }
} }
static bool regmap_printable(struct regmap *map, unsigned int reg)
{
if (regmap_precious(map, reg))
return false;
if (!regmap_readable(map, reg) && !regmap_cached(map, reg))
return false;
return true;
}
/* /*
* Work out where the start offset maps into register numbers, bearing * Work out where the start offset maps into register numbers, bearing
* in mind that we suppress hidden registers. * in mind that we suppress hidden registers.
...@@ -105,8 +116,7 @@ static unsigned int regmap_debugfs_get_dump_start(struct regmap *map, ...@@ -105,8 +116,7 @@ static unsigned int regmap_debugfs_get_dump_start(struct regmap *map,
if (list_empty(&map->debugfs_off_cache)) { if (list_empty(&map->debugfs_off_cache)) {
for (; i <= map->max_register; i += map->reg_stride) { for (; i <= map->max_register; i += map->reg_stride) {
/* Skip unprinted registers, closing off cache entry */ /* Skip unprinted registers, closing off cache entry */
if (!regmap_readable(map, i) || if (!regmap_printable(map, i)) {
regmap_precious(map, i)) {
if (c) { if (c) {
c->max = p - 1; c->max = p - 1;
c->max_reg = i - map->reg_stride; c->max_reg = i - map->reg_stride;
...@@ -204,7 +214,7 @@ static ssize_t regmap_read_debugfs(struct regmap *map, unsigned int from, ...@@ -204,7 +214,7 @@ static ssize_t regmap_read_debugfs(struct regmap *map, unsigned int from,
start_reg = regmap_debugfs_get_dump_start(map, from, *ppos, &p); start_reg = regmap_debugfs_get_dump_start(map, from, *ppos, &p);
for (i = start_reg; i <= to; i += map->reg_stride) { for (i = start_reg; i <= to; i += map->reg_stride) {
if (!regmap_readable(map, i)) if (!regmap_readable(map, i) && !regmap_cached(map, i))
continue; continue;
if (regmap_precious(map, i)) if (regmap_precious(map, i))
......
...@@ -93,6 +93,29 @@ bool regmap_writeable(struct regmap *map, unsigned int reg) ...@@ -93,6 +93,29 @@ bool regmap_writeable(struct regmap *map, unsigned int reg)
return true; return true;
} }
bool regmap_cached(struct regmap *map, unsigned int reg)
{
int ret;
unsigned int val;
if (map->cache == REGCACHE_NONE)
return false;
if (!map->cache_ops)
return false;
if (map->max_register && reg > map->max_register)
return false;
map->lock(map->lock_arg);
ret = regcache_read(map, reg, &val);
map->unlock(map->lock_arg);
if (ret)
return false;
return true;
}
bool regmap_readable(struct regmap *map, unsigned int reg) bool regmap_readable(struct regmap *map, unsigned int reg)
{ {
if (!map->reg_read) if (!map->reg_read)
...@@ -749,6 +772,9 @@ struct regmap *__regmap_init(struct device *dev, ...@@ -749,6 +772,9 @@ struct regmap *__regmap_init(struct device *dev,
case REGMAP_ENDIAN_BIG: case REGMAP_ENDIAN_BIG:
map->format.format_reg = regmap_format_16_be; map->format.format_reg = regmap_format_16_be;
break; break;
case REGMAP_ENDIAN_LITTLE:
map->format.format_reg = regmap_format_16_le;
break;
case REGMAP_ENDIAN_NATIVE: case REGMAP_ENDIAN_NATIVE:
map->format.format_reg = regmap_format_16_native; map->format.format_reg = regmap_format_16_native;
break; break;
...@@ -768,6 +794,9 @@ struct regmap *__regmap_init(struct device *dev, ...@@ -768,6 +794,9 @@ struct regmap *__regmap_init(struct device *dev,
case REGMAP_ENDIAN_BIG: case REGMAP_ENDIAN_BIG:
map->format.format_reg = regmap_format_32_be; map->format.format_reg = regmap_format_32_be;
break; break;
case REGMAP_ENDIAN_LITTLE:
map->format.format_reg = regmap_format_32_le;
break;
case REGMAP_ENDIAN_NATIVE: case REGMAP_ENDIAN_NATIVE:
map->format.format_reg = regmap_format_32_native; map->format.format_reg = regmap_format_32_native;
break; break;
...@@ -782,6 +811,9 @@ struct regmap *__regmap_init(struct device *dev, ...@@ -782,6 +811,9 @@ struct regmap *__regmap_init(struct device *dev,
case REGMAP_ENDIAN_BIG: case REGMAP_ENDIAN_BIG:
map->format.format_reg = regmap_format_64_be; map->format.format_reg = regmap_format_64_be;
break; break;
case REGMAP_ENDIAN_LITTLE:
map->format.format_reg = regmap_format_64_le;
break;
case REGMAP_ENDIAN_NATIVE: case REGMAP_ENDIAN_NATIVE:
map->format.format_reg = regmap_format_64_native; map->format.format_reg = regmap_format_64_native;
break; break;
...@@ -1296,12 +1328,26 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg, ...@@ -1296,12 +1328,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 +1416,8 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg, ...@@ -1370,8 +1416,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
...@@ -2251,7 +2297,6 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, ...@@ -2251,7 +2297,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);
...@@ -2268,15 +2313,8 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, ...@@ -2268,15 +2313,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