Commit 5d23bb5f authored by Linus Torvalds's avatar Linus Torvalds

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

Pull regmap updates from Mark Brown:
 "The main change here is Marek's addition of bulk read/write callbacks
  for individual regmaps, we've supported single register operations for
  a while but there's enough hardware out there which can use bulk
  equivalents to make it worthwhile"

* tag 'regmap-v5.19' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap:
  regmap: Add missing map->bus check
  regmap: Add bulk read/write callbacks into regmap_config
  regmap: cache: set max_register with reg_stride
  regmap: Constify static regmap_bus structs
parents 638971b7 5c422f0b
...@@ -110,6 +110,10 @@ struct regmap { ...@@ -110,6 +110,10 @@ struct regmap {
int (*reg_write)(void *context, unsigned int reg, unsigned int val); int (*reg_write)(void *context, unsigned int reg, unsigned int val);
int (*reg_update_bits)(void *context, unsigned int reg, int (*reg_update_bits)(void *context, unsigned int reg,
unsigned int mask, unsigned int val); unsigned int mask, unsigned int val);
/* Bulk read/write */
int (*read)(void *context, const void *reg_buf, size_t reg_size,
void *val_buf, size_t val_size);
int (*write)(void *context, const void *data, size_t count);
bool defer_caching; bool defer_caching;
......
...@@ -183,8 +183,8 @@ int regcache_init(struct regmap *map, const struct regmap_config *config) ...@@ -183,8 +183,8 @@ int regcache_init(struct regmap *map, const struct regmap_config *config)
return 0; return 0;
} }
if (!map->max_register) if (!map->max_register && map->num_reg_defaults_raw)
map->max_register = map->num_reg_defaults_raw; map->max_register = (map->num_reg_defaults_raw - 1) * map->reg_stride;
if (map->cache_ops->init) { if (map->cache_ops->init) {
dev_dbg(map->dev, "Initializing %s cache\n", dev_dbg(map->dev, "Initializing %s cache\n",
......
...@@ -40,7 +40,7 @@ static int regmap_i3c_read(void *context, ...@@ -40,7 +40,7 @@ static int regmap_i3c_read(void *context,
return i3c_device_do_priv_xfers(i3c, xfers, 2); return i3c_device_do_priv_xfers(i3c, xfers, 2);
} }
static struct regmap_bus regmap_i3c = { static const struct regmap_bus regmap_i3c = {
.write = regmap_i3c_write, .write = regmap_i3c_write,
.read = regmap_i3c_read, .read = regmap_i3c_read,
}; };
......
...@@ -80,7 +80,7 @@ static int regmap_sccb_write(void *context, unsigned int reg, unsigned int val) ...@@ -80,7 +80,7 @@ static int regmap_sccb_write(void *context, unsigned int reg, unsigned int val)
return i2c_smbus_write_byte_data(i2c, reg, val); return i2c_smbus_write_byte_data(i2c, reg, val);
} }
static struct regmap_bus regmap_sccb_bus = { static const struct regmap_bus regmap_sccb_bus = {
.reg_write = regmap_sccb_write, .reg_write = regmap_sccb_write,
.reg_read = regmap_sccb_read, .reg_read = regmap_sccb_read,
}; };
......
...@@ -42,7 +42,7 @@ static int regmap_sdw_mbq_read(void *context, unsigned int reg, unsigned int *va ...@@ -42,7 +42,7 @@ static int regmap_sdw_mbq_read(void *context, unsigned int reg, unsigned int *va
return 0; return 0;
} }
static struct regmap_bus regmap_sdw_mbq = { static const struct regmap_bus regmap_sdw_mbq = {
.reg_read = regmap_sdw_mbq_read, .reg_read = regmap_sdw_mbq_read,
.reg_write = regmap_sdw_mbq_write, .reg_write = regmap_sdw_mbq_write,
.reg_format_endian_default = REGMAP_ENDIAN_LITTLE, .reg_format_endian_default = REGMAP_ENDIAN_LITTLE,
......
...@@ -30,7 +30,7 @@ static int regmap_sdw_read(void *context, unsigned int reg, unsigned int *val) ...@@ -30,7 +30,7 @@ static int regmap_sdw_read(void *context, unsigned int reg, unsigned int *val)
return 0; return 0;
} }
static struct regmap_bus regmap_sdw = { static const struct regmap_bus regmap_sdw = {
.reg_read = regmap_sdw_read, .reg_read = regmap_sdw_read,
.reg_write = regmap_sdw_write, .reg_write = regmap_sdw_write,
.reg_format_endian_default = REGMAP_ENDIAN_LITTLE, .reg_format_endian_default = REGMAP_ENDIAN_LITTLE,
......
...@@ -22,7 +22,7 @@ static int regmap_slimbus_read(void *context, const void *reg, size_t reg_size, ...@@ -22,7 +22,7 @@ static int regmap_slimbus_read(void *context, const void *reg, size_t reg_size,
return slim_read(sdev, *(u16 *)reg, val_size, val); return slim_read(sdev, *(u16 *)reg, val_size, val);
} }
static struct regmap_bus regmap_slimbus_bus = { static const struct regmap_bus regmap_slimbus_bus = {
.write = regmap_slimbus_write, .write = regmap_slimbus_write,
.read = regmap_slimbus_read, .read = regmap_slimbus_read,
.reg_format_endian_default = REGMAP_ENDIAN_LITTLE, .reg_format_endian_default = REGMAP_ENDIAN_LITTLE,
......
...@@ -172,17 +172,17 @@ static int w1_reg_a16_v16_write(void *context, unsigned int reg, ...@@ -172,17 +172,17 @@ static int w1_reg_a16_v16_write(void *context, unsigned int reg,
* Various types of supported bus addressing * Various types of supported bus addressing
*/ */
static struct regmap_bus regmap_w1_bus_a8_v8 = { static const struct regmap_bus regmap_w1_bus_a8_v8 = {
.reg_read = w1_reg_a8_v8_read, .reg_read = w1_reg_a8_v8_read,
.reg_write = w1_reg_a8_v8_write, .reg_write = w1_reg_a8_v8_write,
}; };
static struct regmap_bus regmap_w1_bus_a8_v16 = { static const struct regmap_bus regmap_w1_bus_a8_v16 = {
.reg_read = w1_reg_a8_v16_read, .reg_read = w1_reg_a8_v16_read,
.reg_write = w1_reg_a8_v16_write, .reg_write = w1_reg_a8_v16_write,
}; };
static struct regmap_bus regmap_w1_bus_a16_v16 = { static const struct regmap_bus regmap_w1_bus_a16_v16 = {
.reg_read = w1_reg_a16_v16_read, .reg_read = w1_reg_a16_v16_read,
.reg_write = w1_reg_a16_v16_write, .reg_write = w1_reg_a16_v16_write,
}; };
......
...@@ -838,12 +838,15 @@ struct regmap *__regmap_init(struct device *dev, ...@@ -838,12 +838,15 @@ struct regmap *__regmap_init(struct device *dev,
map->reg_stride_order = ilog2(map->reg_stride); map->reg_stride_order = ilog2(map->reg_stride);
else else
map->reg_stride_order = -1; map->reg_stride_order = -1;
map->use_single_read = config->use_single_read || !bus || !bus->read; map->use_single_read = config->use_single_read || !(config->read || (bus && bus->read));
map->use_single_write = config->use_single_write || !bus || !bus->write; map->use_single_write = config->use_single_write || !(config->write || (bus && bus->write));
map->can_multi_write = config->can_multi_write && bus && bus->write; map->can_multi_write = config->can_multi_write && (config->write || (bus && bus->write));
if (bus) { if (bus) {
map->max_raw_read = bus->max_raw_read; map->max_raw_read = bus->max_raw_read;
map->max_raw_write = bus->max_raw_write; map->max_raw_write = bus->max_raw_write;
} else if (config->max_raw_read && config->max_raw_write) {
map->max_raw_read = config->max_raw_read;
map->max_raw_write = config->max_raw_write;
} }
map->dev = dev; map->dev = dev;
map->bus = bus; map->bus = bus;
...@@ -877,7 +880,16 @@ struct regmap *__regmap_init(struct device *dev, ...@@ -877,7 +880,16 @@ struct regmap *__regmap_init(struct device *dev,
map->read_flag_mask = bus->read_flag_mask; map->read_flag_mask = bus->read_flag_mask;
} }
if (!bus) { if (config && config->read && config->write) {
map->reg_read = _regmap_bus_read;
/* Bulk read/write */
map->read = config->read;
map->write = config->write;
reg_endian = REGMAP_ENDIAN_NATIVE;
val_endian = REGMAP_ENDIAN_NATIVE;
} else if (!bus) {
map->reg_read = config->reg_read; map->reg_read = config->reg_read;
map->reg_write = config->reg_write; map->reg_write = config->reg_write;
map->reg_update_bits = config->reg_update_bits; map->reg_update_bits = config->reg_update_bits;
...@@ -894,10 +906,13 @@ struct regmap *__regmap_init(struct device *dev, ...@@ -894,10 +906,13 @@ struct regmap *__regmap_init(struct device *dev,
} else { } else {
map->reg_read = _regmap_bus_read; map->reg_read = _regmap_bus_read;
map->reg_update_bits = bus->reg_update_bits; map->reg_update_bits = bus->reg_update_bits;
} /* Bulk read/write */
map->read = bus->read;
map->write = bus->write;
reg_endian = regmap_get_reg_endian(bus, config); reg_endian = regmap_get_reg_endian(bus, config);
val_endian = regmap_get_val_endian(dev, bus, config); val_endian = regmap_get_val_endian(dev, bus, config);
}
switch (config->reg_bits + map->reg_shift) { switch (config->reg_bits + map->reg_shift) {
case 2: case 2:
...@@ -1671,8 +1686,6 @@ static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg, ...@@ -1671,8 +1686,6 @@ static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg,
size_t len; size_t len;
int i; int i;
WARN_ON(!map->bus);
/* Check for unwritable or noinc registers in range /* Check for unwritable or noinc registers in range
* before we start * before we start
*/ */
...@@ -1754,7 +1767,7 @@ static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg, ...@@ -1754,7 +1767,7 @@ static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg,
val = work_val; val = work_val;
} }
if (map->async && map->bus->async_write) { if (map->async && map->bus && map->bus->async_write) {
struct regmap_async *async; struct regmap_async *async;
trace_regmap_async_write_start(map, reg, val_len); trace_regmap_async_write_start(map, reg, val_len);
...@@ -1822,11 +1835,11 @@ static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg, ...@@ -1822,11 +1835,11 @@ static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg,
* write. * write.
*/ */
if (val == work_val) if (val == work_val)
ret = map->bus->write(map->bus_context, map->work_buf, ret = map->write(map->bus_context, map->work_buf,
map->format.reg_bytes + map->format.reg_bytes +
map->format.pad_bytes + map->format.pad_bytes +
val_len); val_len);
else if (map->bus->gather_write) else if (map->bus && map->bus->gather_write)
ret = map->bus->gather_write(map->bus_context, map->work_buf, ret = map->bus->gather_write(map->bus_context, map->work_buf,
map->format.reg_bytes + map->format.reg_bytes +
map->format.pad_bytes, map->format.pad_bytes,
...@@ -1844,7 +1857,7 @@ static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg, ...@@ -1844,7 +1857,7 @@ static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg,
memcpy(buf, map->work_buf, map->format.reg_bytes); memcpy(buf, map->work_buf, map->format.reg_bytes);
memcpy(buf + map->format.reg_bytes + map->format.pad_bytes, memcpy(buf + map->format.reg_bytes + map->format.pad_bytes,
val, val_len); val, val_len);
ret = map->bus->write(map->bus_context, buf, len); ret = map->write(map->bus_context, buf, len);
kfree(buf); kfree(buf);
} else if (ret != 0 && !map->cache_bypass && map->format.parse_val) { } else if (ret != 0 && !map->cache_bypass && map->format.parse_val) {
...@@ -1901,7 +1914,7 @@ static int _regmap_bus_formatted_write(void *context, unsigned int reg, ...@@ -1901,7 +1914,7 @@ static int _regmap_bus_formatted_write(void *context, unsigned int reg,
struct regmap_range_node *range; struct regmap_range_node *range;
struct regmap *map = context; struct regmap *map = context;
WARN_ON(!map->bus || !map->format.format_write); WARN_ON(!map->format.format_write);
range = _regmap_range_lookup(map, reg); range = _regmap_range_lookup(map, reg);
if (range) { if (range) {
...@@ -1916,8 +1929,7 @@ static int _regmap_bus_formatted_write(void *context, unsigned int reg, ...@@ -1916,8 +1929,7 @@ static int _regmap_bus_formatted_write(void *context, unsigned int reg,
trace_regmap_hw_write_start(map, reg, 1); trace_regmap_hw_write_start(map, reg, 1);
ret = map->bus->write(map->bus_context, map->work_buf, ret = map->write(map->bus_context, map->work_buf, map->format.buf_size);
map->format.buf_size);
trace_regmap_hw_write_done(map, reg, 1); trace_regmap_hw_write_done(map, reg, 1);
...@@ -1937,7 +1949,7 @@ static int _regmap_bus_raw_write(void *context, unsigned int reg, ...@@ -1937,7 +1949,7 @@ static int _regmap_bus_raw_write(void *context, unsigned int reg,
{ {
struct regmap *map = context; struct regmap *map = context;
WARN_ON(!map->bus || !map->format.format_val); WARN_ON(!map->format.format_val);
map->format.format_val(map->work_buf + map->format.reg_bytes map->format.format_val(map->work_buf + map->format.reg_bytes
+ map->format.pad_bytes, val, 0); + map->format.pad_bytes, val, 0);
...@@ -1951,7 +1963,7 @@ static int _regmap_bus_raw_write(void *context, unsigned int reg, ...@@ -1951,7 +1963,7 @@ static int _regmap_bus_raw_write(void *context, unsigned int reg,
static inline void *_regmap_map_get_context(struct regmap *map) static inline void *_regmap_map_get_context(struct regmap *map)
{ {
return (map->bus) ? map : map->bus_context; return (map->bus || (!map->bus && map->read)) ? map : map->bus_context;
} }
int _regmap_write(struct regmap *map, unsigned int reg, int _regmap_write(struct regmap *map, unsigned int reg,
...@@ -2363,7 +2375,7 @@ static int _regmap_raw_multi_reg_write(struct regmap *map, ...@@ -2363,7 +2375,7 @@ static int _regmap_raw_multi_reg_write(struct regmap *map,
u8 = buf; u8 = buf;
*u8 |= map->write_flag_mask; *u8 |= map->write_flag_mask;
ret = map->bus->write(map->bus_context, buf, len); ret = map->write(map->bus_context, buf, len);
kfree(buf); kfree(buf);
...@@ -2669,9 +2681,7 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, ...@@ -2669,9 +2681,7 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
struct regmap_range_node *range; struct regmap_range_node *range;
int ret; int ret;
WARN_ON(!map->bus); if (!map->read)
if (!map->bus || !map->bus->read)
return -EINVAL; return -EINVAL;
range = _regmap_range_lookup(map, reg); range = _regmap_range_lookup(map, reg);
...@@ -2689,9 +2699,9 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, ...@@ -2689,9 +2699,9 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
map->read_flag_mask); 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->read(map->bus_context, map->work_buf,
map->format.reg_bytes + map->format.pad_bytes, map->format.reg_bytes + map->format.pad_bytes,
val, val_len); val, val_len);
trace_regmap_hw_read_done(map, reg, val_len / map->format.val_bytes); trace_regmap_hw_read_done(map, reg, val_len / map->format.val_bytes);
...@@ -2802,8 +2812,6 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val, ...@@ -2802,8 +2812,6 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
unsigned int v; unsigned int v;
int ret, i; int ret, i;
if (!map->bus)
return -EINVAL;
if (val_len % map->format.val_bytes) if (val_len % map->format.val_bytes)
return -EINVAL; return -EINVAL;
if (!IS_ALIGNED(reg, map->reg_stride)) if (!IS_ALIGNED(reg, map->reg_stride))
...@@ -2818,7 +2826,7 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val, ...@@ -2818,7 +2826,7 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
size_t chunk_count, chunk_bytes; size_t chunk_count, chunk_bytes;
size_t chunk_regs = val_count; size_t chunk_regs = val_count;
if (!map->bus->read) { if (!map->read) {
ret = -ENOTSUPP; ret = -ENOTSUPP;
goto out; goto out;
} }
...@@ -2878,7 +2886,7 @@ EXPORT_SYMBOL_GPL(regmap_raw_read); ...@@ -2878,7 +2886,7 @@ EXPORT_SYMBOL_GPL(regmap_raw_read);
* @val: Pointer to data buffer * @val: Pointer to data buffer
* @val_len: Length of output buffer in bytes. * @val_len: Length of output buffer in bytes.
* *
* The regmap API usually assumes that bulk bus read operations will read a * The regmap API usually assumes that bulk read operations will read a
* range of registers. Some devices have certain registers for which a read * range of registers. Some devices have certain registers for which a read
* operation read will read from an internal FIFO. * operation read will read from an internal FIFO.
* *
...@@ -2896,10 +2904,6 @@ int regmap_noinc_read(struct regmap *map, unsigned int reg, ...@@ -2896,10 +2904,6 @@ int regmap_noinc_read(struct regmap *map, unsigned int reg,
size_t read_len; size_t read_len;
int ret; int ret;
if (!map->bus)
return -EINVAL;
if (!map->bus->read)
return -ENOTSUPP;
if (val_len % map->format.val_bytes) if (val_len % map->format.val_bytes)
return -EINVAL; return -EINVAL;
if (!IS_ALIGNED(reg, map->reg_stride)) if (!IS_ALIGNED(reg, map->reg_stride))
...@@ -3013,7 +3017,7 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val, ...@@ -3013,7 +3017,7 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
if (val_count == 0) if (val_count == 0)
return -EINVAL; return -EINVAL;
if (map->bus && map->format.parse_inplace && (vol || map->cache_type == REGCACHE_NONE)) { if (map->format.parse_inplace && (vol || map->cache_type == REGCACHE_NONE)) {
ret = regmap_raw_read(map, reg, val, val_bytes * val_count); ret = regmap_raw_read(map, reg, val, val_bytes * val_count);
if (ret != 0) if (ret != 0)
return ret; return ret;
......
...@@ -299,6 +299,12 @@ typedef void (*regmap_unlock)(void *); ...@@ -299,6 +299,12 @@ typedef void (*regmap_unlock)(void *);
* if the function require special handling with lock and reg * if the function require special handling with lock and reg
* handling and the operation cannot be represented as a simple * handling and the operation cannot be represented as a simple
* update_bits operation on a bus such as SPI, I2C, etc. * update_bits operation on a bus such as SPI, I2C, etc.
* @read: Optional callback that if filled will be used to perform all the
* bulk reads from the registers. Data is returned in the buffer used
* to transmit data.
* @write: Same as above for writing.
* @max_raw_read: Max raw read size that can be used on the device.
* @max_raw_write: Max raw write size that can be used on the device.
* @fast_io: Register IO is fast. Use a spinlock instead of a mutex * @fast_io: Register IO is fast. Use a spinlock instead of a mutex
* to perform locking. This field is ignored if custom lock/unlock * to perform locking. This field is ignored if custom lock/unlock
* functions are used (see fields lock/unlock of struct regmap_config). * functions are used (see fields lock/unlock of struct regmap_config).
...@@ -385,6 +391,12 @@ struct regmap_config { ...@@ -385,6 +391,12 @@ struct regmap_config {
int (*reg_write)(void *context, unsigned int reg, unsigned int val); int (*reg_write)(void *context, unsigned int reg, unsigned int val);
int (*reg_update_bits)(void *context, unsigned int reg, int (*reg_update_bits)(void *context, unsigned int reg,
unsigned int mask, unsigned int val); unsigned int mask, unsigned int val);
/* Bulk read/write */
int (*read)(void *context, const void *reg_buf, size_t reg_size,
void *val_buf, size_t val_size);
int (*write)(void *context, const void *data, size_t count);
size_t max_raw_read;
size_t max_raw_write;
bool fast_io; bool fast_io;
......
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