| .. | .. |
|---|
| 1 | | -/* |
|---|
| 2 | | - * Register map access API |
|---|
| 3 | | - * |
|---|
| 4 | | - * Copyright 2011 Wolfson Microelectronics plc |
|---|
| 5 | | - * |
|---|
| 6 | | - * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
|---|
| 7 | | - * |
|---|
| 8 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 9 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 10 | | - * published by the Free Software Foundation. |
|---|
| 11 | | - */ |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
|---|
| 2 | +// |
|---|
| 3 | +// Register map access API |
|---|
| 4 | +// |
|---|
| 5 | +// Copyright 2011 Wolfson Microelectronics plc |
|---|
| 6 | +// |
|---|
| 7 | +// Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
|---|
| 12 | 8 | |
|---|
| 13 | 9 | #include <linux/device.h> |
|---|
| 14 | 10 | #include <linux/slab.h> |
|---|
| 15 | 11 | #include <linux/export.h> |
|---|
| 16 | 12 | #include <linux/mutex.h> |
|---|
| 17 | 13 | #include <linux/err.h> |
|---|
| 18 | | -#include <linux/of.h> |
|---|
| 14 | +#include <linux/property.h> |
|---|
| 19 | 15 | #include <linux/rbtree.h> |
|---|
| 20 | 16 | #include <linux/sched.h> |
|---|
| 21 | 17 | #include <linux/delay.h> |
|---|
| .. | .. |
|---|
| 35 | 31 | * register I/O on a specific device. |
|---|
| 36 | 32 | */ |
|---|
| 37 | 33 | #undef LOG_DEVICE |
|---|
| 34 | + |
|---|
| 35 | +#ifdef LOG_DEVICE |
|---|
| 36 | +static inline bool regmap_should_log(struct regmap *map) |
|---|
| 37 | +{ |
|---|
| 38 | + return (map->dev && strcmp(dev_name(map->dev), LOG_DEVICE) == 0); |
|---|
| 39 | +} |
|---|
| 40 | +#else |
|---|
| 41 | +static inline bool regmap_should_log(struct regmap *map) { return false; } |
|---|
| 42 | +#endif |
|---|
| 43 | + |
|---|
| 38 | 44 | |
|---|
| 39 | 45 | static int _regmap_update_bits(struct regmap *map, unsigned int reg, |
|---|
| 40 | 46 | unsigned int mask, unsigned int val, |
|---|
| .. | .. |
|---|
| 169 | 175 | return false; |
|---|
| 170 | 176 | } |
|---|
| 171 | 177 | |
|---|
| 178 | +bool regmap_writeable_noinc(struct regmap *map, unsigned int reg) |
|---|
| 179 | +{ |
|---|
| 180 | + if (map->writeable_noinc_reg) |
|---|
| 181 | + return map->writeable_noinc_reg(map->dev, reg); |
|---|
| 182 | + |
|---|
| 183 | + if (map->wr_noinc_table) |
|---|
| 184 | + return regmap_check_range_table(map, reg, map->wr_noinc_table); |
|---|
| 185 | + |
|---|
| 186 | + return true; |
|---|
| 187 | +} |
|---|
| 188 | + |
|---|
| 172 | 189 | bool regmap_readable_noinc(struct regmap *map, unsigned int reg) |
|---|
| 173 | 190 | { |
|---|
| 174 | 191 | if (map->readable_noinc_reg) |
|---|
| .. | .. |
|---|
| 191 | 208 | |
|---|
| 192 | 209 | return true; |
|---|
| 193 | 210 | } |
|---|
| 211 | + |
|---|
| 212 | +static void regmap_format_12_20_write(struct regmap *map, |
|---|
| 213 | + unsigned int reg, unsigned int val) |
|---|
| 214 | +{ |
|---|
| 215 | + u8 *out = map->work_buf; |
|---|
| 216 | + |
|---|
| 217 | + out[0] = reg >> 4; |
|---|
| 218 | + out[1] = (reg << 4) | (val >> 16); |
|---|
| 219 | + out[2] = val >> 8; |
|---|
| 220 | + out[3] = val; |
|---|
| 221 | +} |
|---|
| 222 | + |
|---|
| 194 | 223 | |
|---|
| 195 | 224 | static void regmap_format_2_6_write(struct regmap *map, |
|---|
| 196 | 225 | unsigned int reg, unsigned int val) |
|---|
| .. | .. |
|---|
| 564 | 593 | kfree(map->selector_work_buf); |
|---|
| 565 | 594 | } |
|---|
| 566 | 595 | |
|---|
| 596 | +static int regmap_set_name(struct regmap *map, const struct regmap_config *config) |
|---|
| 597 | +{ |
|---|
| 598 | + if (config->name) { |
|---|
| 599 | + const char *name = kstrdup_const(config->name, GFP_KERNEL); |
|---|
| 600 | + |
|---|
| 601 | + if (!name) |
|---|
| 602 | + return -ENOMEM; |
|---|
| 603 | + |
|---|
| 604 | + kfree_const(map->name); |
|---|
| 605 | + map->name = name; |
|---|
| 606 | + } |
|---|
| 607 | + |
|---|
| 608 | + return 0; |
|---|
| 609 | +} |
|---|
| 610 | + |
|---|
| 567 | 611 | int regmap_attach_dev(struct device *dev, struct regmap *map, |
|---|
| 568 | 612 | const struct regmap_config *config) |
|---|
| 569 | 613 | { |
|---|
| 570 | 614 | struct regmap **m; |
|---|
| 615 | + int ret; |
|---|
| 571 | 616 | |
|---|
| 572 | 617 | map->dev = dev; |
|---|
| 573 | 618 | |
|---|
| 574 | | - regmap_debugfs_init(map, config->name); |
|---|
| 619 | + ret = regmap_set_name(map, config); |
|---|
| 620 | + if (ret) |
|---|
| 621 | + return ret; |
|---|
| 622 | + |
|---|
| 623 | + regmap_debugfs_exit(map); |
|---|
| 624 | + regmap_debugfs_init(map); |
|---|
| 575 | 625 | |
|---|
| 576 | 626 | /* Add a devres resource for dev_get_regmap() */ |
|---|
| 577 | 627 | m = devres_alloc(dev_get_regmap_release, sizeof(*m), GFP_KERNEL); |
|---|
| .. | .. |
|---|
| 614 | 664 | const struct regmap_bus *bus, |
|---|
| 615 | 665 | const struct regmap_config *config) |
|---|
| 616 | 666 | { |
|---|
| 617 | | - struct device_node *np; |
|---|
| 667 | + struct fwnode_handle *fwnode = dev ? dev_fwnode(dev) : NULL; |
|---|
| 618 | 668 | enum regmap_endian endian; |
|---|
| 619 | 669 | |
|---|
| 620 | 670 | /* Retrieve the endianness specification from the regmap config */ |
|---|
| .. | .. |
|---|
| 624 | 674 | if (endian != REGMAP_ENDIAN_DEFAULT) |
|---|
| 625 | 675 | return endian; |
|---|
| 626 | 676 | |
|---|
| 627 | | - /* If the dev and dev->of_node exist try to get endianness from DT */ |
|---|
| 628 | | - if (dev && dev->of_node) { |
|---|
| 629 | | - np = dev->of_node; |
|---|
| 677 | + /* If the firmware node exist try to get endianness from it */ |
|---|
| 678 | + if (fwnode_property_read_bool(fwnode, "big-endian")) |
|---|
| 679 | + endian = REGMAP_ENDIAN_BIG; |
|---|
| 680 | + else if (fwnode_property_read_bool(fwnode, "little-endian")) |
|---|
| 681 | + endian = REGMAP_ENDIAN_LITTLE; |
|---|
| 682 | + else if (fwnode_property_read_bool(fwnode, "native-endian")) |
|---|
| 683 | + endian = REGMAP_ENDIAN_NATIVE; |
|---|
| 630 | 684 | |
|---|
| 631 | | - /* Parse the device's DT node for an endianness specification */ |
|---|
| 632 | | - if (of_property_read_bool(np, "big-endian")) |
|---|
| 633 | | - endian = REGMAP_ENDIAN_BIG; |
|---|
| 634 | | - else if (of_property_read_bool(np, "little-endian")) |
|---|
| 635 | | - endian = REGMAP_ENDIAN_LITTLE; |
|---|
| 636 | | - else if (of_property_read_bool(np, "native-endian")) |
|---|
| 637 | | - endian = REGMAP_ENDIAN_NATIVE; |
|---|
| 638 | | - |
|---|
| 639 | | - /* If the endianness was specified in DT, use that */ |
|---|
| 640 | | - if (endian != REGMAP_ENDIAN_DEFAULT) |
|---|
| 641 | | - return endian; |
|---|
| 642 | | - } |
|---|
| 685 | + /* If the endianness was specified in fwnode, use that */ |
|---|
| 686 | + if (endian != REGMAP_ENDIAN_DEFAULT) |
|---|
| 687 | + return endian; |
|---|
| 643 | 688 | |
|---|
| 644 | 689 | /* Retrieve the endianness specification from the bus config */ |
|---|
| 645 | 690 | if (bus && bus->val_format_endian_default) |
|---|
| .. | .. |
|---|
| 675 | 720 | goto err; |
|---|
| 676 | 721 | } |
|---|
| 677 | 722 | |
|---|
| 678 | | - if (config->name) { |
|---|
| 679 | | - map->name = kstrdup_const(config->name, GFP_KERNEL); |
|---|
| 680 | | - if (!map->name) { |
|---|
| 681 | | - ret = -ENOMEM; |
|---|
| 682 | | - goto err_map; |
|---|
| 683 | | - } |
|---|
| 684 | | - } |
|---|
| 723 | + ret = regmap_set_name(map, config); |
|---|
| 724 | + if (ret) |
|---|
| 725 | + goto err_map; |
|---|
| 726 | + |
|---|
| 727 | + ret = -EINVAL; /* Later error paths rely on this */ |
|---|
| 685 | 728 | |
|---|
| 686 | 729 | if (config->disable_locking) { |
|---|
| 687 | 730 | map->lock = map->unlock = regmap_lock_unlock_none; |
|---|
| 731 | + map->can_sleep = config->can_sleep; |
|---|
| 688 | 732 | regmap_debugfs_disable(map); |
|---|
| 689 | 733 | } else if (config->lock && config->unlock) { |
|---|
| 690 | 734 | map->lock = config->lock; |
|---|
| 691 | 735 | map->unlock = config->unlock; |
|---|
| 692 | 736 | map->lock_arg = config->lock_arg; |
|---|
| 737 | + map->can_sleep = config->can_sleep; |
|---|
| 693 | 738 | } else if (config->use_hwlock) { |
|---|
| 694 | 739 | map->hwlock = hwspin_lock_request_specific(config->hwlock_id); |
|---|
| 695 | 740 | if (!map->hwlock) { |
|---|
| .. | .. |
|---|
| 725 | 770 | mutex_init(&map->mutex); |
|---|
| 726 | 771 | map->lock = regmap_lock_mutex; |
|---|
| 727 | 772 | map->unlock = regmap_unlock_mutex; |
|---|
| 773 | + map->can_sleep = true; |
|---|
| 728 | 774 | lockdep_set_class_and_name(&map->mutex, |
|---|
| 729 | 775 | lock_key, lock_name); |
|---|
| 730 | 776 | } |
|---|
| .. | .. |
|---|
| 754 | 800 | map->reg_stride_order = ilog2(map->reg_stride); |
|---|
| 755 | 801 | else |
|---|
| 756 | 802 | map->reg_stride_order = -1; |
|---|
| 757 | | - map->use_single_read = config->use_single_rw || !bus || !bus->read; |
|---|
| 758 | | - map->use_single_write = config->use_single_rw || !bus || !bus->write; |
|---|
| 803 | + map->use_single_read = config->use_single_read || !bus || !bus->read; |
|---|
| 804 | + map->use_single_write = config->use_single_write || !bus || !bus->write; |
|---|
| 759 | 805 | map->can_multi_write = config->can_multi_write && bus && bus->write; |
|---|
| 760 | 806 | if (bus) { |
|---|
| 761 | 807 | map->max_raw_read = bus->max_raw_read; |
|---|
| .. | .. |
|---|
| 769 | 815 | map->rd_table = config->rd_table; |
|---|
| 770 | 816 | map->volatile_table = config->volatile_table; |
|---|
| 771 | 817 | map->precious_table = config->precious_table; |
|---|
| 818 | + map->wr_noinc_table = config->wr_noinc_table; |
|---|
| 772 | 819 | map->rd_noinc_table = config->rd_noinc_table; |
|---|
| 773 | 820 | map->writeable_reg = config->writeable_reg; |
|---|
| 774 | 821 | map->readable_reg = config->readable_reg; |
|---|
| 775 | 822 | map->volatile_reg = config->volatile_reg; |
|---|
| 776 | 823 | map->precious_reg = config->precious_reg; |
|---|
| 824 | + map->writeable_noinc_reg = config->writeable_noinc_reg; |
|---|
| 777 | 825 | map->readable_noinc_reg = config->readable_noinc_reg; |
|---|
| 778 | 826 | map->cache_type = config->cache_type; |
|---|
| 779 | 827 | |
|---|
| .. | .. |
|---|
| 800 | 848 | } else if (!bus->read || !bus->write) { |
|---|
| 801 | 849 | map->reg_read = _regmap_bus_reg_read; |
|---|
| 802 | 850 | map->reg_write = _regmap_bus_reg_write; |
|---|
| 851 | + map->reg_update_bits = bus->reg_update_bits; |
|---|
| 803 | 852 | |
|---|
| 804 | 853 | map->defer_caching = false; |
|---|
| 805 | 854 | goto skip_format_initialization; |
|---|
| .. | .. |
|---|
| 846 | 895 | switch (config->val_bits) { |
|---|
| 847 | 896 | case 14: |
|---|
| 848 | 897 | map->format.format_write = regmap_format_10_14_write; |
|---|
| 898 | + break; |
|---|
| 899 | + default: |
|---|
| 900 | + goto err_hwlock; |
|---|
| 901 | + } |
|---|
| 902 | + break; |
|---|
| 903 | + |
|---|
| 904 | + case 12: |
|---|
| 905 | + switch (config->val_bits) { |
|---|
| 906 | + case 20: |
|---|
| 907 | + map->format.format_write = regmap_format_12_20_write; |
|---|
| 849 | 908 | break; |
|---|
| 850 | 909 | default: |
|---|
| 851 | 910 | goto err_hwlock; |
|---|
| .. | .. |
|---|
| 1122 | 1181 | if (ret != 0) |
|---|
| 1123 | 1182 | goto err_regcache; |
|---|
| 1124 | 1183 | } else { |
|---|
| 1125 | | - regmap_debugfs_init(map, config->name); |
|---|
| 1184 | + regmap_debugfs_init(map); |
|---|
| 1126 | 1185 | } |
|---|
| 1127 | 1186 | |
|---|
| 1128 | 1187 | return map; |
|---|
| .. | .. |
|---|
| 1212 | 1271 | } |
|---|
| 1213 | 1272 | EXPORT_SYMBOL_GPL(devm_regmap_field_alloc); |
|---|
| 1214 | 1273 | |
|---|
| 1274 | + |
|---|
| 1275 | +/** |
|---|
| 1276 | + * regmap_field_bulk_alloc() - Allocate and initialise a bulk register field. |
|---|
| 1277 | + * |
|---|
| 1278 | + * @regmap: regmap bank in which this register field is located. |
|---|
| 1279 | + * @rm_field: regmap register fields within the bank. |
|---|
| 1280 | + * @reg_field: Register fields within the bank. |
|---|
| 1281 | + * @num_fields: Number of register fields. |
|---|
| 1282 | + * |
|---|
| 1283 | + * The return value will be an -ENOMEM on error or zero for success. |
|---|
| 1284 | + * Newly allocated regmap_fields should be freed by calling |
|---|
| 1285 | + * regmap_field_bulk_free() |
|---|
| 1286 | + */ |
|---|
| 1287 | +int regmap_field_bulk_alloc(struct regmap *regmap, |
|---|
| 1288 | + struct regmap_field **rm_field, |
|---|
| 1289 | + struct reg_field *reg_field, |
|---|
| 1290 | + int num_fields) |
|---|
| 1291 | +{ |
|---|
| 1292 | + struct regmap_field *rf; |
|---|
| 1293 | + int i; |
|---|
| 1294 | + |
|---|
| 1295 | + rf = kcalloc(num_fields, sizeof(*rf), GFP_KERNEL); |
|---|
| 1296 | + if (!rf) |
|---|
| 1297 | + return -ENOMEM; |
|---|
| 1298 | + |
|---|
| 1299 | + for (i = 0; i < num_fields; i++) { |
|---|
| 1300 | + regmap_field_init(&rf[i], regmap, reg_field[i]); |
|---|
| 1301 | + rm_field[i] = &rf[i]; |
|---|
| 1302 | + } |
|---|
| 1303 | + |
|---|
| 1304 | + return 0; |
|---|
| 1305 | +} |
|---|
| 1306 | +EXPORT_SYMBOL_GPL(regmap_field_bulk_alloc); |
|---|
| 1307 | + |
|---|
| 1308 | +/** |
|---|
| 1309 | + * devm_regmap_field_bulk_alloc() - Allocate and initialise a bulk register |
|---|
| 1310 | + * fields. |
|---|
| 1311 | + * |
|---|
| 1312 | + * @dev: Device that will be interacted with |
|---|
| 1313 | + * @regmap: regmap bank in which this register field is located. |
|---|
| 1314 | + * @rm_field: regmap register fields within the bank. |
|---|
| 1315 | + * @reg_field: Register fields within the bank. |
|---|
| 1316 | + * @num_fields: Number of register fields. |
|---|
| 1317 | + * |
|---|
| 1318 | + * The return value will be an -ENOMEM on error or zero for success. |
|---|
| 1319 | + * Newly allocated regmap_fields will be automatically freed by the |
|---|
| 1320 | + * device management code. |
|---|
| 1321 | + */ |
|---|
| 1322 | +int devm_regmap_field_bulk_alloc(struct device *dev, |
|---|
| 1323 | + struct regmap *regmap, |
|---|
| 1324 | + struct regmap_field **rm_field, |
|---|
| 1325 | + struct reg_field *reg_field, |
|---|
| 1326 | + int num_fields) |
|---|
| 1327 | +{ |
|---|
| 1328 | + struct regmap_field *rf; |
|---|
| 1329 | + int i; |
|---|
| 1330 | + |
|---|
| 1331 | + rf = devm_kcalloc(dev, num_fields, sizeof(*rf), GFP_KERNEL); |
|---|
| 1332 | + if (!rf) |
|---|
| 1333 | + return -ENOMEM; |
|---|
| 1334 | + |
|---|
| 1335 | + for (i = 0; i < num_fields; i++) { |
|---|
| 1336 | + regmap_field_init(&rf[i], regmap, reg_field[i]); |
|---|
| 1337 | + rm_field[i] = &rf[i]; |
|---|
| 1338 | + } |
|---|
| 1339 | + |
|---|
| 1340 | + return 0; |
|---|
| 1341 | +} |
|---|
| 1342 | +EXPORT_SYMBOL_GPL(devm_regmap_field_bulk_alloc); |
|---|
| 1343 | + |
|---|
| 1344 | +/** |
|---|
| 1345 | + * regmap_field_bulk_free() - Free register field allocated using |
|---|
| 1346 | + * regmap_field_bulk_alloc. |
|---|
| 1347 | + * |
|---|
| 1348 | + * @field: regmap fields which should be freed. |
|---|
| 1349 | + */ |
|---|
| 1350 | +void regmap_field_bulk_free(struct regmap_field *field) |
|---|
| 1351 | +{ |
|---|
| 1352 | + kfree(field); |
|---|
| 1353 | +} |
|---|
| 1354 | +EXPORT_SYMBOL_GPL(regmap_field_bulk_free); |
|---|
| 1355 | + |
|---|
| 1356 | +/** |
|---|
| 1357 | + * devm_regmap_field_bulk_free() - Free a bulk register field allocated using |
|---|
| 1358 | + * devm_regmap_field_bulk_alloc. |
|---|
| 1359 | + * |
|---|
| 1360 | + * @dev: Device that will be interacted with |
|---|
| 1361 | + * @field: regmap field which should be freed. |
|---|
| 1362 | + * |
|---|
| 1363 | + * Free register field allocated using devm_regmap_field_bulk_alloc(). Usually |
|---|
| 1364 | + * drivers need not call this function, as the memory allocated via devm |
|---|
| 1365 | + * will be freed as per device-driver life-cycle. |
|---|
| 1366 | + */ |
|---|
| 1367 | +void devm_regmap_field_bulk_free(struct device *dev, |
|---|
| 1368 | + struct regmap_field *field) |
|---|
| 1369 | +{ |
|---|
| 1370 | + devm_kfree(dev, field); |
|---|
| 1371 | +} |
|---|
| 1372 | +EXPORT_SYMBOL_GPL(devm_regmap_field_bulk_free); |
|---|
| 1373 | + |
|---|
| 1215 | 1374 | /** |
|---|
| 1216 | 1375 | * devm_regmap_field_free() - Free a register field allocated using |
|---|
| 1217 | 1376 | * devm_regmap_field_alloc. |
|---|
| .. | .. |
|---|
| 1282 | 1441 | */ |
|---|
| 1283 | 1442 | int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config) |
|---|
| 1284 | 1443 | { |
|---|
| 1444 | + int ret; |
|---|
| 1445 | + |
|---|
| 1285 | 1446 | regcache_exit(map); |
|---|
| 1286 | 1447 | regmap_debugfs_exit(map); |
|---|
| 1287 | 1448 | |
|---|
| .. | .. |
|---|
| 1290 | 1451 | map->readable_reg = config->readable_reg; |
|---|
| 1291 | 1452 | map->volatile_reg = config->volatile_reg; |
|---|
| 1292 | 1453 | map->precious_reg = config->precious_reg; |
|---|
| 1454 | + map->writeable_noinc_reg = config->writeable_noinc_reg; |
|---|
| 1293 | 1455 | map->readable_noinc_reg = config->readable_noinc_reg; |
|---|
| 1294 | 1456 | map->cache_type = config->cache_type; |
|---|
| 1295 | 1457 | |
|---|
| 1296 | | - regmap_debugfs_init(map, config->name); |
|---|
| 1458 | + ret = regmap_set_name(map, config); |
|---|
| 1459 | + if (ret) |
|---|
| 1460 | + return ret; |
|---|
| 1461 | + |
|---|
| 1462 | + regmap_debugfs_init(map); |
|---|
| 1297 | 1463 | |
|---|
| 1298 | 1464 | map->cache_bypass = false; |
|---|
| 1299 | 1465 | map->cache_only = false; |
|---|
| .. | .. |
|---|
| 1327 | 1493 | } |
|---|
| 1328 | 1494 | if (map->hwlock) |
|---|
| 1329 | 1495 | hwspin_lock_free(map->hwlock); |
|---|
| 1496 | + if (map->lock == regmap_lock_mutex) |
|---|
| 1497 | + mutex_destroy(&map->mutex); |
|---|
| 1330 | 1498 | kfree_const(map->name); |
|---|
| 1331 | 1499 | kfree(map->patch); |
|---|
| 1332 | 1500 | kfree(map); |
|---|
| .. | .. |
|---|
| 1448 | 1616 | } |
|---|
| 1449 | 1617 | |
|---|
| 1450 | 1618 | static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg, |
|---|
| 1451 | | - const void *val, size_t val_len) |
|---|
| 1619 | + const void *val, size_t val_len, bool noinc) |
|---|
| 1452 | 1620 | { |
|---|
| 1453 | 1621 | struct regmap_range_node *range; |
|---|
| 1454 | 1622 | unsigned long flags; |
|---|
| .. | .. |
|---|
| 1461 | 1629 | |
|---|
| 1462 | 1630 | WARN_ON(!map->bus); |
|---|
| 1463 | 1631 | |
|---|
| 1464 | | - /* Check for unwritable registers before we start */ |
|---|
| 1465 | | - if (map->writeable_reg) |
|---|
| 1466 | | - for (i = 0; i < val_len / map->format.val_bytes; i++) |
|---|
| 1467 | | - if (!map->writeable_reg(map->dev, |
|---|
| 1468 | | - reg + regmap_get_offset(map, i))) |
|---|
| 1632 | + /* Check for unwritable or noinc registers in range |
|---|
| 1633 | + * before we start |
|---|
| 1634 | + */ |
|---|
| 1635 | + if (!regmap_writeable_noinc(map, reg)) { |
|---|
| 1636 | + for (i = 0; i < val_len / map->format.val_bytes; i++) { |
|---|
| 1637 | + unsigned int element = |
|---|
| 1638 | + reg + regmap_get_offset(map, i); |
|---|
| 1639 | + if (!regmap_writeable(map, element) || |
|---|
| 1640 | + regmap_writeable_noinc(map, element)) |
|---|
| 1469 | 1641 | return -EINVAL; |
|---|
| 1642 | + } |
|---|
| 1643 | + } |
|---|
| 1470 | 1644 | |
|---|
| 1471 | 1645 | if (!map->cache_bypass && map->format.parse_val) { |
|---|
| 1472 | 1646 | unsigned int ival; |
|---|
| .. | .. |
|---|
| 1501 | 1675 | win_residue, val_len / map->format.val_bytes); |
|---|
| 1502 | 1676 | ret = _regmap_raw_write_impl(map, reg, val, |
|---|
| 1503 | 1677 | win_residue * |
|---|
| 1504 | | - map->format.val_bytes); |
|---|
| 1678 | + map->format.val_bytes, noinc); |
|---|
| 1505 | 1679 | if (ret != 0) |
|---|
| 1506 | 1680 | return ret; |
|---|
| 1507 | 1681 | |
|---|
| .. | .. |
|---|
| 1515 | 1689 | win_residue = range->window_len - win_offset; |
|---|
| 1516 | 1690 | } |
|---|
| 1517 | 1691 | |
|---|
| 1518 | | - ret = _regmap_select_page(map, ®, range, val_num); |
|---|
| 1692 | + ret = _regmap_select_page(map, ®, range, noinc ? 1 : val_num); |
|---|
| 1519 | 1693 | if (ret != 0) |
|---|
| 1520 | 1694 | return ret; |
|---|
| 1521 | 1695 | } |
|---|
| .. | .. |
|---|
| 1723 | 1897 | map->work_buf + |
|---|
| 1724 | 1898 | map->format.reg_bytes + |
|---|
| 1725 | 1899 | map->format.pad_bytes, |
|---|
| 1726 | | - map->format.val_bytes); |
|---|
| 1900 | + map->format.val_bytes, |
|---|
| 1901 | + false); |
|---|
| 1727 | 1902 | } |
|---|
| 1728 | 1903 | |
|---|
| 1729 | 1904 | static inline void *_regmap_map_get_context(struct regmap *map) |
|---|
| .. | .. |
|---|
| 1750 | 1925 | } |
|---|
| 1751 | 1926 | } |
|---|
| 1752 | 1927 | |
|---|
| 1753 | | -#ifdef LOG_DEVICE |
|---|
| 1754 | | - if (map->dev && strcmp(dev_name(map->dev), LOG_DEVICE) == 0) |
|---|
| 1928 | + if (regmap_should_log(map)) |
|---|
| 1755 | 1929 | dev_info(map->dev, "%x <= %x\n", reg, val); |
|---|
| 1756 | | -#endif |
|---|
| 1757 | 1930 | |
|---|
| 1758 | 1931 | trace_regmap_reg_write(map, reg, val); |
|---|
| 1759 | 1932 | |
|---|
| .. | .. |
|---|
| 1819 | 1992 | EXPORT_SYMBOL_GPL(regmap_write_async); |
|---|
| 1820 | 1993 | |
|---|
| 1821 | 1994 | int _regmap_raw_write(struct regmap *map, unsigned int reg, |
|---|
| 1822 | | - const void *val, size_t val_len) |
|---|
| 1995 | + const void *val, size_t val_len, bool noinc) |
|---|
| 1823 | 1996 | { |
|---|
| 1824 | 1997 | size_t val_bytes = map->format.val_bytes; |
|---|
| 1825 | 1998 | size_t val_count = val_len / val_bytes; |
|---|
| .. | .. |
|---|
| 1840 | 2013 | |
|---|
| 1841 | 2014 | /* Write as many bytes as possible with chunk_size */ |
|---|
| 1842 | 2015 | for (i = 0; i < chunk_count; i++) { |
|---|
| 1843 | | - ret = _regmap_raw_write_impl(map, reg, val, chunk_bytes); |
|---|
| 2016 | + ret = _regmap_raw_write_impl(map, reg, val, chunk_bytes, noinc); |
|---|
| 1844 | 2017 | if (ret) |
|---|
| 1845 | 2018 | return ret; |
|---|
| 1846 | 2019 | |
|---|
| .. | .. |
|---|
| 1851 | 2024 | |
|---|
| 1852 | 2025 | /* Write remaining bytes */ |
|---|
| 1853 | 2026 | if (val_len) |
|---|
| 1854 | | - ret = _regmap_raw_write_impl(map, reg, val, val_len); |
|---|
| 2027 | + ret = _regmap_raw_write_impl(map, reg, val, val_len, noinc); |
|---|
| 1855 | 2028 | |
|---|
| 1856 | 2029 | return ret; |
|---|
| 1857 | 2030 | } |
|---|
| .. | .. |
|---|
| 1884 | 2057 | |
|---|
| 1885 | 2058 | map->lock(map->lock_arg); |
|---|
| 1886 | 2059 | |
|---|
| 1887 | | - ret = _regmap_raw_write(map, reg, val, val_len); |
|---|
| 2060 | + ret = _regmap_raw_write(map, reg, val, val_len, false); |
|---|
| 1888 | 2061 | |
|---|
| 1889 | 2062 | map->unlock(map->lock_arg); |
|---|
| 1890 | 2063 | |
|---|
| 1891 | 2064 | return ret; |
|---|
| 1892 | 2065 | } |
|---|
| 1893 | 2066 | EXPORT_SYMBOL_GPL(regmap_raw_write); |
|---|
| 2067 | + |
|---|
| 2068 | +/** |
|---|
| 2069 | + * regmap_noinc_write(): Write data from a register without incrementing the |
|---|
| 2070 | + * register number |
|---|
| 2071 | + * |
|---|
| 2072 | + * @map: Register map to write to |
|---|
| 2073 | + * @reg: Register to write to |
|---|
| 2074 | + * @val: Pointer to data buffer |
|---|
| 2075 | + * @val_len: Length of output buffer in bytes. |
|---|
| 2076 | + * |
|---|
| 2077 | + * The regmap API usually assumes that bulk bus write operations will write a |
|---|
| 2078 | + * range of registers. Some devices have certain registers for which a write |
|---|
| 2079 | + * operation can write to an internal FIFO. |
|---|
| 2080 | + * |
|---|
| 2081 | + * The target register must be volatile but registers after it can be |
|---|
| 2082 | + * completely unrelated cacheable registers. |
|---|
| 2083 | + * |
|---|
| 2084 | + * This will attempt multiple writes as required to write val_len bytes. |
|---|
| 2085 | + * |
|---|
| 2086 | + * A value of zero will be returned on success, a negative errno will be |
|---|
| 2087 | + * returned in error cases. |
|---|
| 2088 | + */ |
|---|
| 2089 | +int regmap_noinc_write(struct regmap *map, unsigned int reg, |
|---|
| 2090 | + const void *val, size_t val_len) |
|---|
| 2091 | +{ |
|---|
| 2092 | + size_t write_len; |
|---|
| 2093 | + int ret; |
|---|
| 2094 | + |
|---|
| 2095 | + if (!map->bus) |
|---|
| 2096 | + return -EINVAL; |
|---|
| 2097 | + if (!map->bus->write) |
|---|
| 2098 | + return -ENOTSUPP; |
|---|
| 2099 | + if (val_len % map->format.val_bytes) |
|---|
| 2100 | + return -EINVAL; |
|---|
| 2101 | + if (!IS_ALIGNED(reg, map->reg_stride)) |
|---|
| 2102 | + return -EINVAL; |
|---|
| 2103 | + if (val_len == 0) |
|---|
| 2104 | + return -EINVAL; |
|---|
| 2105 | + |
|---|
| 2106 | + map->lock(map->lock_arg); |
|---|
| 2107 | + |
|---|
| 2108 | + if (!regmap_volatile(map, reg) || !regmap_writeable_noinc(map, reg)) { |
|---|
| 2109 | + ret = -EINVAL; |
|---|
| 2110 | + goto out_unlock; |
|---|
| 2111 | + } |
|---|
| 2112 | + |
|---|
| 2113 | + while (val_len) { |
|---|
| 2114 | + if (map->max_raw_write && map->max_raw_write < val_len) |
|---|
| 2115 | + write_len = map->max_raw_write; |
|---|
| 2116 | + else |
|---|
| 2117 | + write_len = val_len; |
|---|
| 2118 | + ret = _regmap_raw_write(map, reg, val, write_len, true); |
|---|
| 2119 | + if (ret) |
|---|
| 2120 | + goto out_unlock; |
|---|
| 2121 | + val = ((u8 *)val) + write_len; |
|---|
| 2122 | + val_len -= write_len; |
|---|
| 2123 | + } |
|---|
| 2124 | + |
|---|
| 2125 | +out_unlock: |
|---|
| 2126 | + map->unlock(map->lock_arg); |
|---|
| 2127 | + return ret; |
|---|
| 2128 | +} |
|---|
| 2129 | +EXPORT_SYMBOL_GPL(regmap_noinc_write); |
|---|
| 1894 | 2130 | |
|---|
| 1895 | 2131 | /** |
|---|
| 1896 | 2132 | * regmap_field_update_bits_base() - Perform a read/modify/write cycle a |
|---|
| .. | .. |
|---|
| 1936 | 2172 | * A value of zero will be returned on success, a negative errno will |
|---|
| 1937 | 2173 | * be returned in error cases. |
|---|
| 1938 | 2174 | */ |
|---|
| 1939 | | -int regmap_fields_update_bits_base(struct regmap_field *field, unsigned int id, |
|---|
| 2175 | +int regmap_fields_update_bits_base(struct regmap_field *field, unsigned int id, |
|---|
| 1940 | 2176 | unsigned int mask, unsigned int val, |
|---|
| 1941 | 2177 | bool *change, bool async, bool force) |
|---|
| 1942 | 2178 | { |
|---|
| .. | .. |
|---|
| 2147 | 2383 | if (ret != 0) |
|---|
| 2148 | 2384 | return ret; |
|---|
| 2149 | 2385 | |
|---|
| 2150 | | - if (regs[i].delay_us) |
|---|
| 2151 | | - udelay(regs[i].delay_us); |
|---|
| 2386 | + if (regs[i].delay_us) { |
|---|
| 2387 | + if (map->can_sleep) |
|---|
| 2388 | + fsleep(regs[i].delay_us); |
|---|
| 2389 | + else |
|---|
| 2390 | + udelay(regs[i].delay_us); |
|---|
| 2391 | + } |
|---|
| 2152 | 2392 | |
|---|
| 2153 | 2393 | base += n; |
|---|
| 2154 | 2394 | n = 0; |
|---|
| .. | .. |
|---|
| 2184 | 2424 | if (ret != 0) |
|---|
| 2185 | 2425 | return ret; |
|---|
| 2186 | 2426 | |
|---|
| 2187 | | - if (regs[i].delay_us) |
|---|
| 2188 | | - udelay(regs[i].delay_us); |
|---|
| 2427 | + if (regs[i].delay_us) { |
|---|
| 2428 | + if (map->can_sleep) |
|---|
| 2429 | + fsleep(regs[i].delay_us); |
|---|
| 2430 | + else |
|---|
| 2431 | + udelay(regs[i].delay_us); |
|---|
| 2432 | + } |
|---|
| 2189 | 2433 | } |
|---|
| 2190 | 2434 | return 0; |
|---|
| 2191 | 2435 | } |
|---|
| .. | .. |
|---|
| 2356 | 2600 | |
|---|
| 2357 | 2601 | map->async = true; |
|---|
| 2358 | 2602 | |
|---|
| 2359 | | - ret = _regmap_raw_write(map, reg, val, val_len); |
|---|
| 2603 | + ret = _regmap_raw_write(map, reg, val, val_len, false); |
|---|
| 2360 | 2604 | |
|---|
| 2361 | 2605 | map->async = false; |
|---|
| 2362 | 2606 | |
|---|
| .. | .. |
|---|
| 2445 | 2689 | |
|---|
| 2446 | 2690 | ret = map->reg_read(context, reg, val); |
|---|
| 2447 | 2691 | if (ret == 0) { |
|---|
| 2448 | | -#ifdef LOG_DEVICE |
|---|
| 2449 | | - if (map->dev && strcmp(dev_name(map->dev), LOG_DEVICE) == 0) |
|---|
| 2692 | + if (regmap_should_log(map)) |
|---|
| 2450 | 2693 | dev_info(map->dev, "%x => %x\n", reg, *val); |
|---|
| 2451 | | -#endif |
|---|
| 2452 | 2694 | |
|---|
| 2453 | 2695 | trace_regmap_reg_read(map, reg, *val); |
|---|
| 2454 | 2696 | |
|---|
| .. | .. |
|---|
| 2844 | 3086 | } |
|---|
| 2845 | 3087 | EXPORT_SYMBOL_GPL(regmap_update_bits_base); |
|---|
| 2846 | 3088 | |
|---|
| 3089 | +/** |
|---|
| 3090 | + * regmap_test_bits() - Check if all specified bits are set in a register. |
|---|
| 3091 | + * |
|---|
| 3092 | + * @map: Register map to operate on |
|---|
| 3093 | + * @reg: Register to read from |
|---|
| 3094 | + * @bits: Bits to test |
|---|
| 3095 | + * |
|---|
| 3096 | + * Returns 0 if at least one of the tested bits is not set, 1 if all tested |
|---|
| 3097 | + * bits are set and a negative error number if the underlying regmap_read() |
|---|
| 3098 | + * fails. |
|---|
| 3099 | + */ |
|---|
| 3100 | +int regmap_test_bits(struct regmap *map, unsigned int reg, unsigned int bits) |
|---|
| 3101 | +{ |
|---|
| 3102 | + unsigned int val, ret; |
|---|
| 3103 | + |
|---|
| 3104 | + ret = regmap_read(map, reg, &val); |
|---|
| 3105 | + if (ret) |
|---|
| 3106 | + return ret; |
|---|
| 3107 | + |
|---|
| 3108 | + return (val & bits) == bits; |
|---|
| 3109 | +} |
|---|
| 3110 | +EXPORT_SYMBOL_GPL(regmap_test_bits); |
|---|
| 3111 | + |
|---|
| 2847 | 3112 | void regmap_async_complete_cb(struct regmap_async *async, int ret) |
|---|
| 2848 | 3113 | { |
|---|
| 2849 | 3114 | struct regmap *map = async->map; |
|---|