aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-10-07 20:57:56 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-10-07 20:57:56 -0400
commitc831dd7352c0eedb270b9b6430590da5991bb65c (patch)
tree89d808ddea1eeb039eeff2e5815d2ba3b55a1cba
parent2b425a3f112aa24666fc5f415c8bf0e9132bb6c0 (diff)
parentf5b313a2bcd4c436560c044c726d9ad84a3e4bb3 (diff)
Merge tag 'regmap-v3.18' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap
Pull regmap updates from Mark Brown: "The main update this time around is the addition of a standard DT binding for specifying the endianness of devices. This allows drivers to support any endianness of device register map without any code, useful for configurable IP blocks. There's also a few bug fixes that I didn't get round to sending, none of them terribly severe or new, and a reduction in size for struct regmap" * tag 'regmap-v3.18' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap: regmap: Fix debugfs-file 'registers' mode regmap: fix possible ZERO_SIZE_PTR pointer dereferencing error. regmap: debugfs: fix possbile NULL pointer dereference regmap: fix NULL pointer dereference in _regmap_write/read regmap: fix NULL pointer dereference in regmap_get_val_endian regmap: cache: Do not fail silently from regcache_sync calls regmap: change struct regmap's internal locks as union regmap: Split regmap_get_endian() in two functions regmap: of_regmap_get_endian() cleanup regmap: Fix DT endianess parsing logic regmap: Add explicit dependencies to catch "select" misuse regmap: Restore L: linux-kernel@vger.kernel.org entry regmap: Add the DT binding documentation for endianness regmap: add DT endianness binding support.
-rw-r--r--Documentation/devicetree/bindings/regmap/regmap.txt47
-rw-r--r--MAINTAINERS1
-rw-r--r--drivers/base/regmap/Kconfig3
-rw-r--r--drivers/base/regmap/internal.h6
-rw-r--r--drivers/base/regmap/regcache.c13
-rw-r--r--drivers/base/regmap/regmap-debugfs.c8
-rw-r--r--drivers/base/regmap/regmap-i2c.c2
-rw-r--r--drivers/base/regmap/regmap-spi.c2
-rw-r--r--drivers/base/regmap/regmap.c86
9 files changed, 149 insertions, 19 deletions
diff --git a/Documentation/devicetree/bindings/regmap/regmap.txt b/Documentation/devicetree/bindings/regmap/regmap.txt
new file mode 100644
index 000000000000..b494f8b8ef72
--- /dev/null
+++ b/Documentation/devicetree/bindings/regmap/regmap.txt
@@ -0,0 +1,47 @@
1Device-Tree binding for regmap
2
3The endianness mode of CPU & Device scenarios:
4Index Device Endianness properties
5---------------------------------------------------
61 BE 'big-endian'
72 LE 'little-endian'
8
9For one device driver, which will run in different scenarios above
10on different SoCs using the devicetree, we need one way to simplify
11this.
12
13Required properties:
14- {big,little}-endian: these are boolean properties, if absent
15 meaning that the CPU and the Device are in the same endianness mode,
16 these properties are for register values and all the buffers only.
17
18Examples:
19Scenario 1 : CPU in LE mode & device in LE mode.
20dev: dev@40031000 {
21 compatible = "name";
22 reg = <0x40031000 0x1000>;
23 ...
24};
25
26Scenario 2 : CPU in LE mode & device in BE mode.
27dev: dev@40031000 {
28 compatible = "name";
29 reg = <0x40031000 0x1000>;
30 ...
31 big-endian;
32};
33
34Scenario 3 : CPU in BE mode & device in BE mode.
35dev: dev@40031000 {
36 compatible = "name";
37 reg = <0x40031000 0x1000>;
38 ...
39};
40
41Scenario 4 : CPU in BE mode & device in LE mode.
42dev: dev@40031000 {
43 compatible = "name";
44 reg = <0x40031000 0x1000>;
45 ...
46 little-endian;
47};
diff --git a/MAINTAINERS b/MAINTAINERS
index f107230fc73d..8d9567186aa9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7595,6 +7595,7 @@ F: fs/reiserfs/
7595 7595
7596REGISTER MAP ABSTRACTION 7596REGISTER MAP ABSTRACTION
7597M: Mark Brown <broonie@kernel.org> 7597M: Mark Brown <broonie@kernel.org>
7598L: linux-kernel@vger.kernel.org
7598T: git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap.git 7599T: git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap.git
7599S: Supported 7600S: Supported
7600F: drivers/base/regmap/ 7601F: drivers/base/regmap/
diff --git a/drivers/base/regmap/Kconfig b/drivers/base/regmap/Kconfig
index 4251570610c9..8a3f51f7b1b9 100644
--- a/drivers/base/regmap/Kconfig
+++ b/drivers/base/regmap/Kconfig
@@ -11,12 +11,15 @@ config REGMAP
11 11
12config REGMAP_I2C 12config REGMAP_I2C
13 tristate 13 tristate
14 depends on I2C
14 15
15config REGMAP_SPI 16config REGMAP_SPI
16 tristate 17 tristate
18 depends on SPI
17 19
18config REGMAP_SPMI 20config REGMAP_SPMI
19 tristate 21 tristate
22 depends on SPMI
20 23
21config REGMAP_MMIO 24config REGMAP_MMIO
22 tristate 25 tristate
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index bfc90b8547f2..0da5865df5b1 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -49,8 +49,10 @@ struct regmap_async {
49}; 49};
50 50
51struct regmap { 51struct regmap {
52 struct mutex mutex; 52 union {
53 spinlock_t spinlock; 53 struct mutex mutex;
54 spinlock_t spinlock;
55 };
54 unsigned long spinlock_flags; 56 unsigned long spinlock_flags;
55 regmap_lock lock; 57 regmap_lock lock;
56 regmap_unlock unlock; 58 regmap_unlock unlock;
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index 5617da6dc898..f1280dc356d0 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -269,8 +269,11 @@ static int regcache_default_sync(struct regmap *map, unsigned int min,
269 map->cache_bypass = 1; 269 map->cache_bypass = 1;
270 ret = _regmap_write(map, reg, val); 270 ret = _regmap_write(map, reg, val);
271 map->cache_bypass = 0; 271 map->cache_bypass = 0;
272 if (ret) 272 if (ret) {
273 dev_err(map->dev, "Unable to sync register %#x. %d\n",
274 reg, ret);
273 return ret; 275 return ret;
276 }
274 dev_dbg(map->dev, "Synced register %#x, value %#x\n", reg, val); 277 dev_dbg(map->dev, "Synced register %#x, value %#x\n", reg, val);
275 } 278 }
276 279
@@ -615,8 +618,11 @@ static int regcache_sync_block_single(struct regmap *map, void *block,
615 ret = _regmap_write(map, regtmp, val); 618 ret = _regmap_write(map, regtmp, val);
616 619
617 map->cache_bypass = 0; 620 map->cache_bypass = 0;
618 if (ret != 0) 621 if (ret != 0) {
622 dev_err(map->dev, "Unable to sync register %#x. %d\n",
623 regtmp, ret);
619 return ret; 624 return ret;
625 }
620 dev_dbg(map->dev, "Synced register %#x, value %#x\n", 626 dev_dbg(map->dev, "Synced register %#x, value %#x\n",
621 regtmp, val); 627 regtmp, val);
622 } 628 }
@@ -641,6 +647,9 @@ static int regcache_sync_block_raw_flush(struct regmap *map, const void **data,
641 map->cache_bypass = 1; 647 map->cache_bypass = 1;
642 648
643 ret = _regmap_raw_write(map, base, *data, count * val_bytes); 649 ret = _regmap_raw_write(map, base, *data, count * val_bytes);
650 if (ret)
651 dev_err(map->dev, "Unable to sync registers %#x-%#x. %d\n",
652 base, cur - map->reg_stride, ret);
644 653
645 map->cache_bypass = 0; 654 map->cache_bypass = 0;
646 655
diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c
index 0c94b661c16f..5799a0b9e6cc 100644
--- a/drivers/base/regmap/regmap-debugfs.c
+++ b/drivers/base/regmap/regmap-debugfs.c
@@ -473,6 +473,7 @@ void regmap_debugfs_init(struct regmap *map, const char *name)
473{ 473{
474 struct rb_node *next; 474 struct rb_node *next;
475 struct regmap_range_node *range_node; 475 struct regmap_range_node *range_node;
476 const char *devname = "dummy";
476 477
477 /* If we don't have the debugfs root yet, postpone init */ 478 /* If we don't have the debugfs root yet, postpone init */
478 if (!regmap_debugfs_root) { 479 if (!regmap_debugfs_root) {
@@ -491,12 +492,15 @@ void regmap_debugfs_init(struct regmap *map, const char *name)
491 INIT_LIST_HEAD(&map->debugfs_off_cache); 492 INIT_LIST_HEAD(&map->debugfs_off_cache);
492 mutex_init(&map->cache_lock); 493 mutex_init(&map->cache_lock);
493 494
495 if (map->dev)
496 devname = dev_name(map->dev);
497
494 if (name) { 498 if (name) {
495 map->debugfs_name = kasprintf(GFP_KERNEL, "%s-%s", 499 map->debugfs_name = kasprintf(GFP_KERNEL, "%s-%s",
496 dev_name(map->dev), name); 500 devname, name);
497 name = map->debugfs_name; 501 name = map->debugfs_name;
498 } else { 502 } else {
499 name = dev_name(map->dev); 503 name = devname;
500 } 504 }
501 505
502 map->debugfs = debugfs_create_dir(name, regmap_debugfs_root); 506 map->debugfs = debugfs_create_dir(name, regmap_debugfs_root);
diff --git a/drivers/base/regmap/regmap-i2c.c b/drivers/base/regmap/regmap-i2c.c
index ca193d1ef47c..053150a7f9f2 100644
--- a/drivers/base/regmap/regmap-i2c.c
+++ b/drivers/base/regmap/regmap-i2c.c
@@ -168,6 +168,8 @@ static struct regmap_bus regmap_i2c = {
168 .write = regmap_i2c_write, 168 .write = regmap_i2c_write,
169 .gather_write = regmap_i2c_gather_write, 169 .gather_write = regmap_i2c_gather_write,
170 .read = regmap_i2c_read, 170 .read = regmap_i2c_read,
171 .reg_format_endian_default = REGMAP_ENDIAN_BIG,
172 .val_format_endian_default = REGMAP_ENDIAN_BIG,
171}; 173};
172 174
173static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c, 175static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c,
diff --git a/drivers/base/regmap/regmap-spi.c b/drivers/base/regmap/regmap-spi.c
index 0eb3097c0d76..53d1148e80a0 100644
--- a/drivers/base/regmap/regmap-spi.c
+++ b/drivers/base/regmap/regmap-spi.c
@@ -109,6 +109,8 @@ static struct regmap_bus regmap_spi = {
109 .async_alloc = regmap_spi_async_alloc, 109 .async_alloc = regmap_spi_async_alloc,
110 .read = regmap_spi_read, 110 .read = regmap_spi_read,
111 .read_flag_mask = 0x80, 111 .read_flag_mask = 0x80,
112 .reg_format_endian_default = REGMAP_ENDIAN_BIG,
113 .val_format_endian_default = REGMAP_ENDIAN_BIG,
112}; 114};
113 115
114/** 116/**
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 1cf427bc0d4a..d2f8a818d200 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -15,6 +15,7 @@
15#include <linux/export.h> 15#include <linux/export.h>
16#include <linux/mutex.h> 16#include <linux/mutex.h>
17#include <linux/err.h> 17#include <linux/err.h>
18#include <linux/of.h>
18#include <linux/rbtree.h> 19#include <linux/rbtree.h>
19#include <linux/sched.h> 20#include <linux/sched.h>
20 21
@@ -448,6 +449,71 @@ int regmap_attach_dev(struct device *dev, struct regmap *map,
448} 449}
449EXPORT_SYMBOL_GPL(regmap_attach_dev); 450EXPORT_SYMBOL_GPL(regmap_attach_dev);
450 451
452static enum regmap_endian regmap_get_reg_endian(const struct regmap_bus *bus,
453 const struct regmap_config *config)
454{
455 enum regmap_endian endian;
456
457 /* Retrieve the endianness specification from the regmap config */
458 endian = config->reg_format_endian;
459
460 /* If the regmap config specified a non-default value, use that */
461 if (endian != REGMAP_ENDIAN_DEFAULT)
462 return endian;
463
464 /* Retrieve the endianness specification from the bus config */
465 if (bus && bus->reg_format_endian_default)
466 endian = bus->reg_format_endian_default;
467
468 /* If the bus specified a non-default value, use that */
469 if (endian != REGMAP_ENDIAN_DEFAULT)
470 return endian;
471
472 /* Use this if no other value was found */
473 return REGMAP_ENDIAN_BIG;
474}
475
476static enum regmap_endian regmap_get_val_endian(struct device *dev,
477 const struct regmap_bus *bus,
478 const struct regmap_config *config)
479{
480 struct device_node *np;
481 enum regmap_endian endian;
482
483 /* Retrieve the endianness specification from the regmap config */
484 endian = config->val_format_endian;
485
486 /* If the regmap config specified a non-default value, use that */
487 if (endian != REGMAP_ENDIAN_DEFAULT)
488 return endian;
489
490 /* If the dev and dev->of_node exist try to get endianness from DT */
491 if (dev && dev->of_node) {
492 np = dev->of_node;
493
494 /* Parse the device's DT node for an endianness specification */
495 if (of_property_read_bool(np, "big-endian"))
496 endian = REGMAP_ENDIAN_BIG;
497 else if (of_property_read_bool(np, "little-endian"))
498 endian = REGMAP_ENDIAN_LITTLE;
499
500 /* If the endianness was specified in DT, use that */
501 if (endian != REGMAP_ENDIAN_DEFAULT)
502 return endian;
503 }
504
505 /* Retrieve the endianness specification from the bus config */
506 if (bus && bus->val_format_endian_default)
507 endian = bus->val_format_endian_default;
508
509 /* If the bus specified a non-default value, use that */
510 if (endian != REGMAP_ENDIAN_DEFAULT)
511 return endian;
512
513 /* Use this if no other value was found */
514 return REGMAP_ENDIAN_BIG;
515}
516
451/** 517/**
452 * regmap_init(): Initialise register map 518 * regmap_init(): Initialise register map
453 * 519 *
@@ -551,17 +617,8 @@ struct regmap *regmap_init(struct device *dev,
551 map->reg_read = _regmap_bus_read; 617 map->reg_read = _regmap_bus_read;
552 } 618 }
553 619
554 reg_endian = config->reg_format_endian; 620 reg_endian = regmap_get_reg_endian(bus, config);
555 if (reg_endian == REGMAP_ENDIAN_DEFAULT) 621 val_endian = regmap_get_val_endian(dev, bus, config);
556 reg_endian = bus->reg_format_endian_default;
557 if (reg_endian == REGMAP_ENDIAN_DEFAULT)
558 reg_endian = REGMAP_ENDIAN_BIG;
559
560 val_endian = config->val_format_endian;
561 if (val_endian == REGMAP_ENDIAN_DEFAULT)
562 val_endian = bus->val_format_endian_default;
563 if (val_endian == REGMAP_ENDIAN_DEFAULT)
564 val_endian = REGMAP_ENDIAN_BIG;
565 622
566 switch (config->reg_bits + map->reg_shift) { 623 switch (config->reg_bits + map->reg_shift) {
567 case 2: 624 case 2:
@@ -1408,7 +1465,7 @@ int _regmap_write(struct regmap *map, unsigned int reg,
1408 } 1465 }
1409 1466
1410#ifdef LOG_DEVICE 1467#ifdef LOG_DEVICE
1411 if (strcmp(dev_name(map->dev), LOG_DEVICE) == 0) 1468 if (map->dev && strcmp(dev_name(map->dev), LOG_DEVICE) == 0)
1412 dev_info(map->dev, "%x <= %x\n", reg, val); 1469 dev_info(map->dev, "%x <= %x\n", reg, val);
1413#endif 1470#endif
1414 1471
@@ -1659,6 +1716,9 @@ out:
1659 } else { 1716 } else {
1660 void *wval; 1717 void *wval;
1661 1718
1719 if (!val_count)
1720 return -EINVAL;
1721
1662 wval = kmemdup(val, val_count * val_bytes, GFP_KERNEL); 1722 wval = kmemdup(val, val_count * val_bytes, GFP_KERNEL);
1663 if (!wval) { 1723 if (!wval) {
1664 dev_err(map->dev, "Error in memory allocation\n"); 1724 dev_err(map->dev, "Error in memory allocation\n");
@@ -2058,7 +2118,7 @@ static int _regmap_read(struct regmap *map, unsigned int reg,
2058 ret = map->reg_read(context, reg, val); 2118 ret = map->reg_read(context, reg, val);
2059 if (ret == 0) { 2119 if (ret == 0) {
2060#ifdef LOG_DEVICE 2120#ifdef LOG_DEVICE
2061 if (strcmp(dev_name(map->dev), LOG_DEVICE) == 0) 2121 if (map->dev && strcmp(dev_name(map->dev), LOG_DEVICE) == 0)
2062 dev_info(map->dev, "%x => %x\n", reg, *val); 2122 dev_info(map->dev, "%x => %x\n", reg, *val);
2063#endif 2123#endif
2064 2124