Merge tag 'regmap-v5.19' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 24 May 2022 22:02:58 +0000 (15:02 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 24 May 2022 22:02:58 +0000 (15:02 -0700)
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

drivers/base/regmap/internal.h
drivers/base/regmap/regcache.c
drivers/base/regmap/regmap-i3c.c
drivers/base/regmap/regmap-sccb.c
drivers/base/regmap/regmap-sdw-mbq.c
drivers/base/regmap/regmap-sdw.c
drivers/base/regmap/regmap-slimbus.c
drivers/base/regmap/regmap-w1.c
drivers/base/regmap/regmap.c
include/linux/regmap.h

index b4df36c7b17d17b301a1dab2e0aaa994a5272f61..da8996e7a1f1cdf960b01216da27464dd654473a 100644 (file)
@@ -110,6 +110,10 @@ struct regmap {
        int (*reg_write)(void *context, unsigned int reg, unsigned int val);
        int (*reg_update_bits)(void *context, unsigned int reg,
                               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;
 
index f2469d3435ca384db5f014c031ca3bd2e4687dd9..d0f5bc8279783adcab51bd42df7775000e1dad67 100644 (file)
@@ -183,8 +183,8 @@ int regcache_init(struct regmap *map, const struct regmap_config *config)
                        return 0;
        }
 
-       if (!map->max_register)
-               map->max_register = map->num_reg_defaults_raw;
+       if (!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) {
                dev_dbg(map->dev, "Initializing %s cache\n",
index 1578fb50668399c82b4bb8de6d3f43dbfe52d1cf..0328b0b34284f8e45e7e556eae408041d1e0362b 100644 (file)
@@ -40,7 +40,7 @@ static int regmap_i3c_read(void *context,
        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,
        .read = regmap_i3c_read,
 };
index 597042e2d0094887519c330bc11de21a8bc53fe7..986af26d88c244d3da3a277af09d70e7da202864 100644 (file)
@@ -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);
 }
 
-static struct regmap_bus regmap_sccb_bus = {
+static const struct regmap_bus regmap_sccb_bus = {
        .reg_write = regmap_sccb_write,
        .reg_read = regmap_sccb_read,
 };
index fe3ac26b66ad73a415b2fb4eb60dc067db67ccf2..388c3a087bd90b9dbdf9285d9eb442833a46a082 100644 (file)
@@ -42,7 +42,7 @@ static int regmap_sdw_mbq_read(void *context, unsigned int reg, unsigned int *va
        return 0;
 }
 
-static struct regmap_bus regmap_sdw_mbq = {
+static const struct regmap_bus regmap_sdw_mbq = {
        .reg_read = regmap_sdw_mbq_read,
        .reg_write = regmap_sdw_mbq_write,
        .reg_format_endian_default = REGMAP_ENDIAN_LITTLE,
index 966de8a136d9004247b94d5a99bb5f8af1a26ac4..81b0327f719d87d8341237162df4bc56929c97ba 100644 (file)
@@ -30,7 +30,7 @@ static int regmap_sdw_read(void *context, unsigned int reg, unsigned int *val)
        return 0;
 }
 
-static struct regmap_bus regmap_sdw = {
+static const struct regmap_bus regmap_sdw = {
        .reg_read = regmap_sdw_read,
        .reg_write = regmap_sdw_write,
        .reg_format_endian_default = REGMAP_ENDIAN_LITTLE,
index 0968059f1ef57be468c421865a23747fd958b30e..8075db788b39ad1a32c3723c4ba33d5d4a48475b 100644 (file)
@@ -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);
 }
 
-static struct regmap_bus regmap_slimbus_bus = {
+static const struct regmap_bus regmap_slimbus_bus = {
        .write = regmap_slimbus_write,
        .read = regmap_slimbus_read,
        .reg_format_endian_default = REGMAP_ENDIAN_LITTLE,
index 1fbaaad71ca5b58d1d67d2cfa3830727b8050e2b..3a8b402db8526c48d4b159200eb417b1b22f2ba1 100644 (file)
@@ -172,17 +172,17 @@ static int w1_reg_a16_v16_write(void *context, unsigned int reg,
  * 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_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_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_write = w1_reg_a16_v16_write,
 };
index 5e12f7cb51471388e33f56c6b762839d3f367a5b..2221d98638317a7b1003c5befed3b860f4f94847 100644 (file)
@@ -838,12 +838,15 @@ struct regmap *__regmap_init(struct device *dev,
                map->reg_stride_order = ilog2(map->reg_stride);
        else
                map->reg_stride_order = -1;
-       map->use_single_read = config->use_single_read || !bus || !bus->read;
-       map->use_single_write = config->use_single_write || !bus || !bus->write;
-       map->can_multi_write = config->can_multi_write && bus && bus->write;
+       map->use_single_read = config->use_single_read || !(config->read || (bus && bus->read));
+       map->use_single_write = config->use_single_write || !(config->write || (bus && bus->write));
+       map->can_multi_write = config->can_multi_write && (config->write || (bus && bus->write));
        if (bus) {
                map->max_raw_read = bus->max_raw_read;
                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->bus = bus;
@@ -877,7 +880,16 @@ struct regmap *__regmap_init(struct device *dev,
                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_write = config->reg_write;
                map->reg_update_bits = config->reg_update_bits;
@@ -894,10 +906,13 @@ struct regmap *__regmap_init(struct device *dev,
        } else {
                map->reg_read  = _regmap_bus_read;
                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);
-       val_endian = regmap_get_val_endian(dev, bus, config);
+               reg_endian = regmap_get_reg_endian(bus, config);
+               val_endian = regmap_get_val_endian(dev, bus, config);
+       }
 
        switch (config->reg_bits + map->reg_shift) {
        case 2:
@@ -1671,8 +1686,6 @@ static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg,
        size_t len;
        int i;
 
-       WARN_ON(!map->bus);
-
        /* Check for unwritable or noinc registers in range
         * before we start
         */
@@ -1754,7 +1767,7 @@ static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg,
                val = work_val;
        }
 
-       if (map->async && map->bus->async_write) {
+       if (map->async && map->bus && map->bus->async_write) {
                struct regmap_async *async;
 
                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,
         * write.
         */
        if (val == work_val)
-               ret = map->bus->write(map->bus_context, map->work_buf,
-                                     map->format.reg_bytes +
-                                     map->format.pad_bytes +
-                                     val_len);
-       else if (map->bus->gather_write)
+               ret = map->write(map->bus_context, map->work_buf,
+                                map->format.reg_bytes +
+                                map->format.pad_bytes +
+                                val_len);
+       else if (map->bus && map->bus->gather_write)
                ret = map->bus->gather_write(map->bus_context, map->work_buf,
                                             map->format.reg_bytes +
                                             map->format.pad_bytes,
@@ -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->format.reg_bytes + map->format.pad_bytes,
                       val, val_len);
-               ret = map->bus->write(map->bus_context, buf, len);
+               ret = map->write(map->bus_context, buf, len);
 
                kfree(buf);
        } 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,
        struct regmap_range_node *range;
        struct regmap *map = context;
 
-       WARN_ON(!map->bus || !map->format.format_write);
+       WARN_ON(!map->format.format_write);
 
        range = _regmap_range_lookup(map, reg);
        if (range) {
@@ -1916,8 +1929,7 @@ static int _regmap_bus_formatted_write(void *context, unsigned int reg,
 
        trace_regmap_hw_write_start(map, reg, 1);
 
-       ret = map->bus->write(map->bus_context, map->work_buf,
-                             map->format.buf_size);
+       ret = map->write(map->bus_context, map->work_buf, map->format.buf_size);
 
        trace_regmap_hw_write_done(map, reg, 1);
 
@@ -1937,7 +1949,7 @@ static int _regmap_bus_raw_write(void *context, unsigned int reg,
 {
        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.pad_bytes, val, 0);
@@ -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)
 {
-       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,
@@ -2363,7 +2375,7 @@ static int _regmap_raw_multi_reg_write(struct regmap *map,
        u8 = buf;
        *u8 |= map->write_flag_mask;
 
-       ret = map->bus->write(map->bus_context, buf, len);
+       ret = map->write(map->bus_context, buf, len);
 
        kfree(buf);
 
@@ -2669,9 +2681,7 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
        struct regmap_range_node *range;
        int ret;
 
-       WARN_ON(!map->bus);
-
-       if (!map->bus || !map->bus->read)
+       if (!map->read)
                return -EINVAL;
 
        range = _regmap_range_lookup(map, reg);
@@ -2689,9 +2699,9 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
                                      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,
-                            map->format.reg_bytes + map->format.pad_bytes,
-                            val, val_len);
+       ret = map->read(map->bus_context, map->work_buf,
+                       map->format.reg_bytes + map->format.pad_bytes,
+                       val, val_len);
 
        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,
        unsigned int v;
        int ret, i;
 
-       if (!map->bus)
-               return -EINVAL;
        if (val_len % map->format.val_bytes)
                return -EINVAL;
        if (!IS_ALIGNED(reg, map->reg_stride))
@@ -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_regs = val_count;
 
-               if (!map->bus->read) {
+               if (!map->read) {
                        ret = -ENOTSUPP;
                        goto out;
                }
@@ -2878,7 +2886,7 @@ EXPORT_SYMBOL_GPL(regmap_raw_read);
  * @val: Pointer to data buffer
  * @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
  * operation read will read from an internal FIFO.
  *
@@ -2896,10 +2904,6 @@ int regmap_noinc_read(struct regmap *map, unsigned int reg,
        size_t read_len;
        int ret;
 
-       if (!map->bus)
-               return -EINVAL;
-       if (!map->bus->read)
-               return -ENOTSUPP;
        if (val_len % map->format.val_bytes)
                return -EINVAL;
        if (!IS_ALIGNED(reg, map->reg_stride))
@@ -3013,7 +3017,7 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
        if (val_count == 0)
                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);
                if (ret != 0)
                        return ret;
index de81a94d7b307aa9e6a2f532185fddff99b0c33a..8952fa3d0d59332d494f95e5a94bc97aee838d29 100644 (file)
@@ -299,6 +299,12 @@ typedef void (*regmap_unlock)(void *);
  *                  if the function require special handling with lock and reg
  *                  handling and the operation cannot be represented as a simple
  *                  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
  *               to perform locking. This field is ignored if custom lock/unlock
  *               functions are used (see fields lock/unlock of struct regmap_config).
@@ -385,6 +391,12 @@ struct regmap_config {
        int (*reg_write)(void *context, unsigned int reg, unsigned int val);
        int (*reg_update_bits)(void *context, unsigned int reg,
                               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;