regmap: Updates for v4.9
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. -----BEGIN PGP SIGNATURE----- iQEwBAABCAAaBQJX8x9EExxicm9vbmllQGtlcm5lbC5vcmcACgkQJNaLcl1Uh9Dc mQf8Do/0T9bM0vTQFB9fcdOtYEa73vuDNbo0zCVAXEGJp862Z9OFB1oS5UInH9Os T6gahxFR4tApv+89p9f7WGE2ppeiclkc9rpBdig6sBUtDGzF3+VT+N0LLV5I1TgA FcYRFBXxewwk7qWywEd1IypRa6s2fazOqj7eYdqSpaFAyewpXMRKrnPNbtxbYDkx MkIBADyT4ZfzOQQjxyff7vjVpWn8A41bD/ojhm9WLJL/Mxu/1q23nyTUYH7qqAAL HC1DZFqUt2jbshmNozF9JlKuEGb1M2hXRptKLUJlynyVsnk2RO3OEUOW8haoxFBh 7Puxh+SsERDRHKiBkbFYnuBjLA== =0fj2 -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
808c2b0583
4 changed files with 71 additions and 22 deletions
|
@ -105,8 +105,8 @@ struct regmap {
|
|||
|
||||
bool defer_caching;
|
||||
|
||||
u8 read_flag_mask;
|
||||
u8 write_flag_mask;
|
||||
unsigned long read_flag_mask;
|
||||
unsigned long write_flag_mask;
|
||||
|
||||
/* number of bits to (left) shift the reg value when formatting*/
|
||||
int reg_shift;
|
||||
|
@ -173,6 +173,7 @@ struct regcache_ops {
|
|||
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_readable(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)
|
|||
}
|
||||
}
|
||||
|
||||
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
|
||||
* in mind that we suppress hidden registers.
|
||||
|
@ -105,8 +116,7 @@ static unsigned int regmap_debugfs_get_dump_start(struct regmap *map,
|
|||
if (list_empty(&map->debugfs_off_cache)) {
|
||||
for (; i <= map->max_register; i += map->reg_stride) {
|
||||
/* Skip unprinted registers, closing off cache entry */
|
||||
if (!regmap_readable(map, i) ||
|
||||
regmap_precious(map, i)) {
|
||||
if (!regmap_printable(map, i)) {
|
||||
if (c) {
|
||||
c->max = p - 1;
|
||||
c->max_reg = i - map->reg_stride;
|
||||
|
@ -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);
|
||||
|
||||
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;
|
||||
|
||||
if (regmap_precious(map, i))
|
||||
|
|
|
@ -93,6 +93,29 @@ bool regmap_writeable(struct regmap *map, unsigned int reg)
|
|||
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)
|
||||
{
|
||||
if (!map->reg_read)
|
||||
|
@ -749,6 +772,9 @@ struct regmap *__regmap_init(struct device *dev,
|
|||
case REGMAP_ENDIAN_BIG:
|
||||
map->format.format_reg = regmap_format_16_be;
|
||||
break;
|
||||
case REGMAP_ENDIAN_LITTLE:
|
||||
map->format.format_reg = regmap_format_16_le;
|
||||
break;
|
||||
case REGMAP_ENDIAN_NATIVE:
|
||||
map->format.format_reg = regmap_format_16_native;
|
||||
break;
|
||||
|
@ -768,6 +794,9 @@ struct regmap *__regmap_init(struct device *dev,
|
|||
case REGMAP_ENDIAN_BIG:
|
||||
map->format.format_reg = regmap_format_32_be;
|
||||
break;
|
||||
case REGMAP_ENDIAN_LITTLE:
|
||||
map->format.format_reg = regmap_format_32_le;
|
||||
break;
|
||||
case REGMAP_ENDIAN_NATIVE:
|
||||
map->format.format_reg = regmap_format_32_native;
|
||||
break;
|
||||
|
@ -782,6 +811,9 @@ struct regmap *__regmap_init(struct device *dev,
|
|||
case REGMAP_ENDIAN_BIG:
|
||||
map->format.format_reg = regmap_format_64_be;
|
||||
break;
|
||||
case REGMAP_ENDIAN_LITTLE:
|
||||
map->format.format_reg = regmap_format_64_le;
|
||||
break;
|
||||
case REGMAP_ENDIAN_NATIVE:
|
||||
map->format.format_reg = regmap_format_64_native;
|
||||
break;
|
||||
|
@ -1296,12 +1328,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 +1416,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
|
||||
|
@ -2251,7 +2297,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);
|
||||
|
@ -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);
|
||||
|
||||
/*
|
||||
* 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,
|
||||
|
|
|
@ -241,9 +241,9 @@ typedef void (*regmap_unlock)(void *);
|
|||
* register cache support).
|
||||
* @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.
|
||||
* @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
|
||||
* empty the regmap_bus default masks are used.
|
||||
* @use_single_rw: If set, converts the bulk read and write operations into
|
||||
|
@ -299,8 +299,8 @@ struct regmap_config {
|
|||
const void *reg_defaults_raw;
|
||||
unsigned int num_reg_defaults_raw;
|
||||
|
||||
u8 read_flag_mask;
|
||||
u8 write_flag_mask;
|
||||
unsigned long read_flag_mask;
|
||||
unsigned long write_flag_mask;
|
||||
|
||||
bool use_single_rw;
|
||||
bool can_multi_write;
|
||||
|
|
Loading…
Reference in a new issue