summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/base/regmap/internal.h4
-rw-r--r--drivers/base/regmap/regmap.c85
-rw-r--r--include/linux/regmap.h4
3 files changed, 78 insertions, 15 deletions
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index d744ae3926dd..fc554e357c5d 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -146,6 +146,10 @@ struct regmap {
146 /* if set, the device supports multi write mode */ 146 /* if set, the device supports multi write mode */
147 bool can_multi_write; 147 bool can_multi_write;
148 148
149 /* if set, raw reads/writes are limited to this size */
150 size_t max_raw_read;
151 size_t max_raw_write;
152
149 struct rb_root range_tree; 153 struct rb_root range_tree;
150 void *selector_work_buf; /* Scratch buffer used for selector */ 154 void *selector_work_buf; /* Scratch buffer used for selector */
151}; 155};
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index a6b6f7ee87ee..7cbe42680877 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -579,6 +579,8 @@ struct regmap *regmap_init(struct device *dev,
579 map->use_single_read = config->use_single_rw || !bus || !bus->read; 579 map->use_single_read = config->use_single_rw || !bus || !bus->read;
580 map->use_single_write = config->use_single_rw || !bus || !bus->write; 580 map->use_single_write = config->use_single_rw || !bus || !bus->write;
581 map->can_multi_write = config->can_multi_write && bus && bus->write; 581 map->can_multi_write = config->can_multi_write && bus && bus->write;
582 map->max_raw_read = bus->max_raw_read;
583 map->max_raw_write = bus->max_raw_write;
582 map->dev = dev; 584 map->dev = dev;
583 map->bus = bus; 585 map->bus = bus;
584 map->bus_context = bus_context; 586 map->bus_context = bus_context;
@@ -1674,6 +1676,7 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
1674{ 1676{
1675 int ret = 0, i; 1677 int ret = 0, i;
1676 size_t val_bytes = map->format.val_bytes; 1678 size_t val_bytes = map->format.val_bytes;
1679 size_t total_size = val_bytes * val_count;
1677 1680
1678 if (map->bus && !map->format.parse_inplace) 1681 if (map->bus && !map->format.parse_inplace)
1679 return -EINVAL; 1682 return -EINVAL;
@@ -1722,16 +1725,37 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
1722 } 1725 }
1723out: 1726out:
1724 map->unlock(map->lock_arg); 1727 map->unlock(map->lock_arg);
1725 } else if (map->use_single_write) { 1728 } else if (map->use_single_write ||
1729 (map->max_raw_write && map->max_raw_write < total_size)) {
1730 int chunk_stride = map->reg_stride;
1731 size_t chunk_size = val_bytes;
1732 size_t chunk_count = val_count;
1733
1734 if (!map->use_single_write) {
1735 chunk_size = map->max_raw_write;
1736 if (chunk_size % val_bytes)
1737 chunk_size -= chunk_size % val_bytes;
1738 chunk_count = total_size / chunk_size;
1739 chunk_stride *= chunk_size / val_bytes;
1740 }
1741
1726 map->lock(map->lock_arg); 1742 map->lock(map->lock_arg);
1727 for (i = 0; i < val_count; i++) { 1743 /* Write as many bytes as possible with chunk_size */
1744 for (i = 0; i < chunk_count; i++) {
1728 ret = _regmap_raw_write(map, 1745 ret = _regmap_raw_write(map,
1729 reg + (i * map->reg_stride), 1746 reg + (i * chunk_stride),
1730 val + (i * val_bytes), 1747 val + (i * chunk_size),
1731 val_bytes); 1748 chunk_size);
1732 if (ret) 1749 if (ret)
1733 break; 1750 break;
1734 } 1751 }
1752
1753 /* Write remaining bytes */
1754 if (!ret && chunk_size * i < total_size) {
1755 ret = _regmap_raw_write(map, reg + (i * chunk_stride),
1756 val + (i * chunk_size),
1757 total_size - i * chunk_size);
1758 }
1735 map->unlock(map->lock_arg); 1759 map->unlock(map->lock_arg);
1736 } else { 1760 } else {
1737 void *wval; 1761 void *wval;
@@ -2319,20 +2343,51 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
2319 * Some devices does not support bulk read, for 2343 * Some devices does not support bulk read, for
2320 * them we have a series of single read operations. 2344 * them we have a series of single read operations.
2321 */ 2345 */
2322 if (map->use_single_read) { 2346 size_t total_size = val_bytes * val_count;
2323 for (i = 0; i < val_count; i++) { 2347
2324 ret = regmap_raw_read(map, 2348 if (!map->use_single_read &&
2325 reg + (i * map->reg_stride), 2349 (!map->max_raw_read || map->max_raw_read > total_size)) {
2326 val + (i * val_bytes),
2327 val_bytes);
2328 if (ret != 0)
2329 return ret;
2330 }
2331 } else {
2332 ret = regmap_raw_read(map, reg, val, 2350 ret = regmap_raw_read(map, reg, val,
2333 val_bytes * val_count); 2351 val_bytes * val_count);
2334 if (ret != 0) 2352 if (ret != 0)
2335 return ret; 2353 return ret;
2354 } else {
2355 /*
2356 * Some devices do not support bulk read or do not
2357 * support large bulk reads, for them we have a series
2358 * of read operations.
2359 */
2360 int chunk_stride = map->reg_stride;
2361 size_t chunk_size = val_bytes;
2362 size_t chunk_count = val_count;
2363
2364 if (!map->use_single_read) {
2365 chunk_size = map->max_raw_read;
2366 if (chunk_size % val_bytes)
2367 chunk_size -= chunk_size % val_bytes;
2368 chunk_count = total_size / chunk_size;
2369 chunk_stride *= chunk_size / val_bytes;
2370 }
2371
2372 /* Read bytes that fit into a multiple of chunk_size */
2373 for (i = 0; i < chunk_count; i++) {
2374 ret = regmap_raw_read(map,
2375 reg + (i * chunk_stride),
2376 val + (i * chunk_size),
2377 chunk_size);
2378 if (ret != 0)
2379 return ret;
2380 }
2381
2382 /* Read remaining bytes */
2383 if (chunk_size * i < total_size) {
2384 ret = regmap_raw_read(map,
2385 reg + (i * chunk_stride),
2386 val + (i * chunk_size),
2387 total_size - i * chunk_size);
2388 if (ret != 0)
2389 return ret;
2390 }
2336 } 2391 }
2337 2392
2338 for (i = 0; i < val_count * val_bytes; i += val_bytes) 2393 for (i = 0; i < val_count * val_bytes; i += val_bytes)
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index 73fc34d0c4c2..327b8f291d3f 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -311,6 +311,8 @@ typedef void (*regmap_hw_free_context)(void *context);
311 * @val_format_endian_default: Default endianness for formatted register 311 * @val_format_endian_default: Default endianness for formatted register
312 * values. Used when the regmap_config specifies DEFAULT. If this is 312 * values. Used when the regmap_config specifies DEFAULT. If this is
313 * DEFAULT, BIG is assumed. 313 * DEFAULT, BIG is assumed.
314 * @max_raw_read: Max raw read size that can be used on the bus.
315 * @max_raw_write: Max raw write size that can be used on the bus.
314 */ 316 */
315struct regmap_bus { 317struct regmap_bus {
316 bool fast_io; 318 bool fast_io;
@@ -325,6 +327,8 @@ struct regmap_bus {
325 u8 read_flag_mask; 327 u8 read_flag_mask;
326 enum regmap_endian reg_format_endian_default; 328 enum regmap_endian reg_format_endian_default;
327 enum regmap_endian val_format_endian_default; 329 enum regmap_endian val_format_endian_default;
330 size_t max_raw_read;
331 size_t max_raw_write;
328}; 332};
329 333
330struct regmap *regmap_init(struct device *dev, 334struct regmap *regmap_init(struct device *dev,