Skip to content

Commit b5856f9

Browse files
committed
Merge tag 'regmap-v4.16' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap
Pull regmap updates from Mark Brown: "A very busy release for regmap, all fairly specialist stuff but useful: - Support for disabling locking from Bartosz Golaszewski, allowing users that handle their own locking to save some overhead. - Support for hwspinlocks in syscons in MFD from Baolin Wang, this is going through the regmap tree since the first users turned up some some cases that needed interface tweaks with 0 being used as a syscon identifier. - Support for devices with no read or write flag from Andrew F. Davis. - Basic support for devices on SoundWire buses from Vinod Koul" * tag 'regmap-v4.16' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap: mfd: syscon: Add hardware spinlock support regmap: Allow empty read/write_flag_mask regcache: flat: Un-inline index lookup from cache access regmap: Add SoundWire bus support regmap: Add one flag to indicate if a hwlock should be used regmap: debugfs: document why we don't create the debugfs entries regmap: debugfs: emit a debug message when locking is disabled regmap: use proper part of work_buf for storing val regmap: potentially duplicate the name string stored in regmap regmap: Disable debugfs when locking is disabled regmap: rename regmap_lock_unlock_empty() to regmap_lock_unlock_none() regmap: allow to disable all locking mechanisms regmap: Remove the redundant config to select hwspinlock
2 parents dc38787 + a75de77 commit b5856f9

File tree

10 files changed

+229
-25
lines changed

10 files changed

+229
-25
lines changed

Documentation/devicetree/bindings/mfd/syscon.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,17 @@ Required properties:
1616
Optional property:
1717
- reg-io-width: the size (in bytes) of the IO accesses that should be
1818
performed on the device.
19+
- hwlocks: reference to a phandle of a hardware spinlock provider node.
1920

2021
Examples:
2122
gpr: iomuxc-gpr@20e0000 {
2223
compatible = "fsl,imx6q-iomuxc-gpr", "syscon";
2324
reg = <0x020e0000 0x38>;
25+
hwlocks = <&hwlock1 1>;
26+
};
27+
28+
hwlock1: hwspinlock@40500000 {
29+
...
30+
reg = <0x40500000 0x1000>;
31+
#hwlock-cells = <1>;
2432
};

drivers/base/regmap/Kconfig

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
config REGMAP
77
default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_W1 || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ)
88
select IRQ_DOMAIN if REGMAP_IRQ
9-
select REGMAP_HWSPINLOCK if HWSPINLOCK=y
109
bool
1110

1211
config REGCACHE_COMPRESSED
@@ -39,5 +38,6 @@ config REGMAP_MMIO
3938
config REGMAP_IRQ
4039
bool
4140

42-
config REGMAP_HWSPINLOCK
43-
bool
41+
config REGMAP_SOUNDWIRE
42+
tristate
43+
depends on SOUNDWIRE_BUS

drivers/base/regmap/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ obj-$(CONFIG_REGMAP_SPMI) += regmap-spmi.o
1313
obj-$(CONFIG_REGMAP_MMIO) += regmap-mmio.o
1414
obj-$(CONFIG_REGMAP_IRQ) += regmap-irq.o
1515
obj-$(CONFIG_REGMAP_W1) += regmap-w1.o
16+
obj-$(CONFIG_REGMAP_SOUNDWIRE) += regmap-sdw.o

drivers/base/regmap/internal.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ struct regmap {
7777
int async_ret;
7878

7979
#ifdef CONFIG_DEBUG_FS
80+
bool debugfs_disable;
8081
struct dentry *debugfs;
8182
const char *debugfs_name;
8283

@@ -215,10 +216,17 @@ struct regmap_field {
215216
extern void regmap_debugfs_initcall(void);
216217
extern void regmap_debugfs_init(struct regmap *map, const char *name);
217218
extern void regmap_debugfs_exit(struct regmap *map);
219+
220+
static inline void regmap_debugfs_disable(struct regmap *map)
221+
{
222+
map->debugfs_disable = true;
223+
}
224+
218225
#else
219226
static inline void regmap_debugfs_initcall(void) { }
220227
static inline void regmap_debugfs_init(struct regmap *map, const char *name) { }
221228
static inline void regmap_debugfs_exit(struct regmap *map) { }
229+
static inline void regmap_debugfs_disable(struct regmap *map) { }
222230
#endif
223231

224232
/* regcache core declarations */

drivers/base/regmap/regcache-flat.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,12 @@ static int regcache_flat_init(struct regmap *map)
3737

3838
cache = map->cache;
3939

40-
for (i = 0; i < map->num_reg_defaults; i++)
41-
cache[regcache_flat_get_index(map, map->reg_defaults[i].reg)] =
42-
map->reg_defaults[i].def;
40+
for (i = 0; i < map->num_reg_defaults; i++) {
41+
unsigned int reg = map->reg_defaults[i].reg;
42+
unsigned int index = regcache_flat_get_index(map, reg);
43+
44+
cache[index] = map->reg_defaults[i].def;
45+
}
4346

4447
return 0;
4548
}
@@ -56,8 +59,9 @@ static int regcache_flat_read(struct regmap *map,
5659
unsigned int reg, unsigned int *value)
5760
{
5861
unsigned int *cache = map->cache;
62+
unsigned int index = regcache_flat_get_index(map, reg);
5963

60-
*value = cache[regcache_flat_get_index(map, reg)];
64+
*value = cache[index];
6165

6266
return 0;
6367
}
@@ -66,8 +70,9 @@ static int regcache_flat_write(struct regmap *map, unsigned int reg,
6670
unsigned int value)
6771
{
6872
unsigned int *cache = map->cache;
73+
unsigned int index = regcache_flat_get_index(map, reg);
6974

70-
cache[regcache_flat_get_index(map, reg)] = value;
75+
cache[index] = value;
7176

7277
return 0;
7378
}

drivers/base/regmap/regmap-debugfs.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,18 @@ void regmap_debugfs_init(struct regmap *map, const char *name)
529529
struct regmap_range_node *range_node;
530530
const char *devname = "dummy";
531531

532+
/*
533+
* Userspace can initiate reads from the hardware over debugfs.
534+
* Normally internal regmap structures and buffers are protected with
535+
* a mutex or a spinlock, but if the regmap owner decided to disable
536+
* all locking mechanisms, this is no longer the case. For safety:
537+
* don't create the debugfs entries if locking is disabled.
538+
*/
539+
if (map->debugfs_disable) {
540+
dev_dbg(map->dev, "regmap locking disabled - not creating debugfs entries\n");
541+
return;
542+
}
543+
532544
/* If we don't have the debugfs root yet, postpone init */
533545
if (!regmap_debugfs_root) {
534546
struct regmap_debugfs_node *node;

drivers/base/regmap/regmap-sdw.c

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
// Copyright(c) 2015-17 Intel Corporation.
3+
4+
#include <linux/device.h>
5+
#include <linux/mod_devicetable.h>
6+
#include <linux/module.h>
7+
#include <linux/soundwire/sdw.h>
8+
#include "internal.h"
9+
10+
static int regmap_sdw_write(void *context, unsigned int reg, unsigned int val)
11+
{
12+
struct device *dev = context;
13+
struct sdw_slave *slave = dev_to_sdw_dev(dev);
14+
15+
return sdw_write(slave, reg, val);
16+
}
17+
18+
static int regmap_sdw_read(void *context, unsigned int reg, unsigned int *val)
19+
{
20+
struct device *dev = context;
21+
struct sdw_slave *slave = dev_to_sdw_dev(dev);
22+
int read;
23+
24+
read = sdw_read(slave, reg);
25+
if (read < 0)
26+
return read;
27+
28+
*val = read;
29+
return 0;
30+
}
31+
32+
static struct regmap_bus regmap_sdw = {
33+
.reg_read = regmap_sdw_read,
34+
.reg_write = regmap_sdw_write,
35+
.reg_format_endian_default = REGMAP_ENDIAN_LITTLE,
36+
.val_format_endian_default = REGMAP_ENDIAN_LITTLE,
37+
};
38+
39+
static int regmap_sdw_config_check(const struct regmap_config *config)
40+
{
41+
/* All register are 8-bits wide as per MIPI Soundwire 1.0 Spec */
42+
if (config->val_bits != 8)
43+
return -ENOTSUPP;
44+
45+
/* Registers are 32 bits wide */
46+
if (config->reg_bits != 32)
47+
return -ENOTSUPP;
48+
49+
if (config->pad_bits != 0)
50+
return -ENOTSUPP;
51+
52+
return 0;
53+
}
54+
55+
struct regmap *__regmap_init_sdw(struct sdw_slave *sdw,
56+
const struct regmap_config *config,
57+
struct lock_class_key *lock_key,
58+
const char *lock_name)
59+
{
60+
int ret;
61+
62+
ret = regmap_sdw_config_check(config);
63+
if (ret)
64+
return ERR_PTR(ret);
65+
66+
return __regmap_init(&sdw->dev, &regmap_sdw,
67+
&sdw->dev, config, lock_key, lock_name);
68+
}
69+
EXPORT_SYMBOL_GPL(__regmap_init_sdw);
70+
71+
struct regmap *__devm_regmap_init_sdw(struct sdw_slave *sdw,
72+
const struct regmap_config *config,
73+
struct lock_class_key *lock_key,
74+
const char *lock_name)
75+
{
76+
int ret;
77+
78+
ret = regmap_sdw_config_check(config);
79+
if (ret)
80+
return ERR_PTR(ret);
81+
82+
return __devm_regmap_init(&sdw->dev, &regmap_sdw,
83+
&sdw->dev, config, lock_key, lock_name);
84+
}
85+
EXPORT_SYMBOL_GPL(__devm_regmap_init_sdw);
86+
87+
MODULE_DESCRIPTION("Regmap SoundWire Module");
88+
MODULE_LICENSE("GPL v2");

drivers/base/regmap/regmap.c

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,6 @@ static unsigned int regmap_parse_64_native(const void *buf)
414414
}
415415
#endif
416416

417-
#ifdef REGMAP_HWSPINLOCK
418417
static void regmap_lock_hwlock(void *__map)
419418
{
420419
struct regmap *map = __map;
@@ -457,7 +456,11 @@ static void regmap_unlock_hwlock_irqrestore(void *__map)
457456

458457
hwspin_unlock_irqrestore(map->hwlock, &map->spinlock_flags);
459458
}
460-
#endif
459+
460+
static void regmap_lock_unlock_none(void *__map)
461+
{
462+
463+
}
461464

462465
static void regmap_lock_mutex(void *__map)
463466
{
@@ -669,16 +672,26 @@ struct regmap *__regmap_init(struct device *dev,
669672
goto err;
670673
}
671674

672-
if (config->lock && config->unlock) {
675+
if (config->name) {
676+
map->name = kstrdup_const(config->name, GFP_KERNEL);
677+
if (!map->name) {
678+
ret = -ENOMEM;
679+
goto err_map;
680+
}
681+
}
682+
683+
if (config->disable_locking) {
684+
map->lock = map->unlock = regmap_lock_unlock_none;
685+
regmap_debugfs_disable(map);
686+
} else if (config->lock && config->unlock) {
673687
map->lock = config->lock;
674688
map->unlock = config->unlock;
675689
map->lock_arg = config->lock_arg;
676-
} else if (config->hwlock_id) {
677-
#ifdef REGMAP_HWSPINLOCK
690+
} else if (config->use_hwlock) {
678691
map->hwlock = hwspin_lock_request_specific(config->hwlock_id);
679692
if (!map->hwlock) {
680693
ret = -ENXIO;
681-
goto err_map;
694+
goto err_name;
682695
}
683696

684697
switch (config->hwlock_mode) {
@@ -697,10 +710,6 @@ struct regmap *__regmap_init(struct device *dev,
697710
}
698711

699712
map->lock_arg = map;
700-
#else
701-
ret = -EINVAL;
702-
goto err_map;
703-
#endif
704713
} else {
705714
if ((bus && bus->fast_io) ||
706715
config->fast_io) {
@@ -762,14 +771,15 @@ struct regmap *__regmap_init(struct device *dev,
762771
map->volatile_reg = config->volatile_reg;
763772
map->precious_reg = config->precious_reg;
764773
map->cache_type = config->cache_type;
765-
map->name = config->name;
766774

767775
spin_lock_init(&map->async_lock);
768776
INIT_LIST_HEAD(&map->async_list);
769777
INIT_LIST_HEAD(&map->async_free);
770778
init_waitqueue_head(&map->async_waitq);
771779

772-
if (config->read_flag_mask || config->write_flag_mask) {
780+
if (config->read_flag_mask ||
781+
config->write_flag_mask ||
782+
config->zero_flag_mask) {
773783
map->read_flag_mask = config->read_flag_mask;
774784
map->write_flag_mask = config->write_flag_mask;
775785
} else if (bus) {
@@ -1116,8 +1126,10 @@ struct regmap *__regmap_init(struct device *dev,
11161126
regmap_range_exit(map);
11171127
kfree(map->work_buf);
11181128
err_hwlock:
1119-
if (IS_ENABLED(REGMAP_HWSPINLOCK) && map->hwlock)
1129+
if (map->hwlock)
11201130
hwspin_lock_free(map->hwlock);
1131+
err_name:
1132+
kfree_const(map->name);
11211133
err_map:
11221134
kfree(map);
11231135
err:
@@ -1305,8 +1317,9 @@ void regmap_exit(struct regmap *map)
13051317
kfree(async->work_buf);
13061318
kfree(async);
13071319
}
1308-
if (IS_ENABLED(REGMAP_HWSPINLOCK) && map->hwlock)
1320+
if (map->hwlock)
13091321
hwspin_lock_free(map->hwlock);
1322+
kfree_const(map->name);
13101323
kfree(map);
13111324
}
13121325
EXPORT_SYMBOL_GPL(regmap_exit);
@@ -2423,13 +2436,15 @@ static int _regmap_bus_read(void *context, unsigned int reg,
24232436
{
24242437
int ret;
24252438
struct regmap *map = context;
2439+
void *work_val = map->work_buf + map->format.reg_bytes +
2440+
map->format.pad_bytes;
24262441

24272442
if (!map->format.parse_val)
24282443
return -EINVAL;
24292444

2430-
ret = _regmap_raw_read(map, reg, map->work_buf, map->format.val_bytes);
2445+
ret = _regmap_raw_read(map, reg, work_val, map->format.val_bytes);
24312446
if (ret == 0)
2432-
*val = map->format.parse_val(map->work_buf);
2447+
*val = map->format.parse_val(work_val);
24332448

24342449
return ret;
24352450
}

drivers/mfd/syscon.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
*/
1414

1515
#include <linux/err.h>
16+
#include <linux/hwspinlock.h>
1617
#include <linux/io.h>
1718
#include <linux/module.h>
1819
#include <linux/list.h>
@@ -87,6 +88,24 @@ static struct syscon *of_syscon_register(struct device_node *np)
8788
if (ret)
8889
reg_io_width = 4;
8990

91+
ret = of_hwspin_lock_get_id(np, 0);
92+
if (ret > 0 || (IS_ENABLED(CONFIG_HWSPINLOCK) && ret == 0)) {
93+
syscon_config.use_hwlock = true;
94+
syscon_config.hwlock_id = ret;
95+
syscon_config.hwlock_mode = HWLOCK_IRQSTATE;
96+
} else if (ret < 0) {
97+
switch (ret) {
98+
case -ENOENT:
99+
/* Ignore missing hwlock, it's optional. */
100+
break;
101+
default:
102+
pr_err("Failed to retrieve valid hwlock: %d\n", ret);
103+
/* fall-through */
104+
case -EPROBE_DEFER:
105+
goto err_regmap;
106+
}
107+
}
108+
90109
syscon_config.reg_stride = reg_io_width;
91110
syscon_config.val_bits = reg_io_width * 8;
92111
syscon_config.max_register = resource_size(&res) - reg_io_width;

0 commit comments

Comments
 (0)