Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

regmap: Introduce max_raw_read/write for regmap_bulk_read/write

There are some buses which have a limit on the maximum number of bytes
that can be send/received. An example for this is
I2C_FUNC_SMBUS_I2C_BLOCK which does not support any reads/writes of more
than 32 bytes. The regmap_bulk operations should still be able to
utilize the full 32 bytes in this case.

Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Markus Pargmann and committed by
Mark Brown
adaac459 10524612

+78 -15
+4
drivers/base/regmap/internal.h
··· 146 146 /* if set, the device supports multi write mode */ 147 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 153 struct rb_root range_tree; 150 154 void *selector_work_buf; /* Scratch buffer used for selector */ 151 155 };
+70 -15
drivers/base/regmap/regmap.c
··· 579 579 map->use_single_read = config->use_single_rw || !bus || !bus->read; 580 580 map->use_single_write = config->use_single_rw || !bus || !bus->write; 581 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 584 map->dev = dev; 583 585 map->bus = bus; 584 586 map->bus_context = bus_context; ··· 1676 1674 { 1677 1675 int ret = 0, i; 1678 1676 size_t val_bytes = map->format.val_bytes; 1677 + size_t total_size = val_bytes * val_count; 1679 1678 1680 1679 if (map->bus && !map->format.parse_inplace) 1681 1680 return -EINVAL; ··· 1725 1722 } 1726 1723 out: 1727 1724 map->unlock(map->lock_arg); 1728 - } else if (map->use_single_write) { 1725 + } else if (map->use_single_write || 1726 + (map->max_raw_write && map->max_raw_write < total_size)) { 1727 + int chunk_stride = map->reg_stride; 1728 + size_t chunk_size = val_bytes; 1729 + size_t chunk_count = val_count; 1730 + 1731 + if (!map->use_single_write) { 1732 + chunk_size = map->max_raw_write; 1733 + if (chunk_size % val_bytes) 1734 + chunk_size -= chunk_size % val_bytes; 1735 + chunk_count = total_size / chunk_size; 1736 + chunk_stride *= chunk_size / val_bytes; 1737 + } 1738 + 1729 1739 map->lock(map->lock_arg); 1730 - for (i = 0; i < val_count; i++) { 1740 + /* Write as many bytes as possible with chunk_size */ 1741 + for (i = 0; i < chunk_count; i++) { 1731 1742 ret = _regmap_raw_write(map, 1732 - reg + (i * map->reg_stride), 1733 - val + (i * val_bytes), 1734 - val_bytes); 1743 + reg + (i * chunk_stride), 1744 + val + (i * chunk_size), 1745 + chunk_size); 1735 1746 if (ret) 1736 1747 break; 1748 + } 1749 + 1750 + /* Write remaining bytes */ 1751 + if (!ret && chunk_size * i < total_size) { 1752 + ret = _regmap_raw_write(map, reg + (i * chunk_stride), 1753 + val + (i * chunk_size), 1754 + total_size - i * chunk_size); 1737 1755 } 1738 1756 map->unlock(map->lock_arg); 1739 1757 } else { ··· 2343 2319 * Some devices does not support bulk read, for 2344 2320 * them we have a series of single read operations. 2345 2321 */ 2346 - if (map->use_single_read) { 2347 - for (i = 0; i < val_count; i++) { 2348 - ret = regmap_raw_read(map, 2349 - reg + (i * map->reg_stride), 2350 - val + (i * val_bytes), 2351 - val_bytes); 2352 - if (ret != 0) 2353 - return ret; 2354 - } 2355 - } else { 2322 + size_t total_size = val_bytes * val_count; 2323 + 2324 + if (!map->use_single_read && 2325 + (!map->max_raw_read || map->max_raw_read > total_size)) { 2356 2326 ret = regmap_raw_read(map, reg, val, 2357 2327 val_bytes * val_count); 2358 2328 if (ret != 0) 2359 2329 return ret; 2330 + } else { 2331 + /* 2332 + * Some devices do not support bulk read or do not 2333 + * support large bulk reads, for them we have a series 2334 + * of read operations. 2335 + */ 2336 + int chunk_stride = map->reg_stride; 2337 + size_t chunk_size = val_bytes; 2338 + size_t chunk_count = val_count; 2339 + 2340 + if (!map->use_single_read) { 2341 + chunk_size = map->max_raw_read; 2342 + if (chunk_size % val_bytes) 2343 + chunk_size -= chunk_size % val_bytes; 2344 + chunk_count = total_size / chunk_size; 2345 + chunk_stride *= chunk_size / val_bytes; 2346 + } 2347 + 2348 + /* Read bytes that fit into a multiple of chunk_size */ 2349 + for (i = 0; i < chunk_count; i++) { 2350 + ret = regmap_raw_read(map, 2351 + reg + (i * chunk_stride), 2352 + val + (i * chunk_size), 2353 + chunk_size); 2354 + if (ret != 0) 2355 + return ret; 2356 + } 2357 + 2358 + /* Read remaining bytes */ 2359 + if (chunk_size * i < total_size) { 2360 + ret = regmap_raw_read(map, 2361 + reg + (i * chunk_stride), 2362 + val + (i * chunk_size), 2363 + total_size - i * chunk_size); 2364 + if (ret != 0) 2365 + return ret; 2366 + } 2360 2367 } 2361 2368 2362 2369 for (i = 0; i < val_count * val_bytes; i += val_bytes)
+4
include/linux/regmap.h
··· 311 311 * @val_format_endian_default: Default endianness for formatted register 312 312 * values. Used when the regmap_config specifies DEFAULT. If this is 313 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 */ 315 317 struct regmap_bus { 316 318 bool fast_io; ··· 327 325 u8 read_flag_mask; 328 326 enum regmap_endian reg_format_endian_default; 329 327 enum regmap_endian val_format_endian_default; 328 + size_t max_raw_read; 329 + size_t max_raw_write; 330 330 }; 331 331 332 332 struct regmap *regmap_init(struct device *dev,