Commit 0d4529c534c1c664f25088eb5f5b4d7ce0ee2510

Authored by Davide Ciminaghi
Committed by Mark Brown
1 parent ddffeb8c4d

regmap: make lock/unlock functions customizable

It is sometimes convenient for a regmap user to override the standard
regmap lock/unlock functions with custom functions.
For instance this can be useful in case an already existing spinlock
or mutex has to be used for locking a set of registers instead of the
internal regmap spinlock/mutex.
Note that the fast_io field of struct regmap_bus is ignored in case
custom locking functions are used.

Signed-off-by: Davide Ciminaghi <ciminaghi@gnudd.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>

Showing 3 changed files with 54 additions and 31 deletions Side-by-side Diff

drivers/base/regmap/internal.h
... ... @@ -31,14 +31,12 @@
31 31 unsigned int (*parse_val)(void *buf);
32 32 };
33 33  
34   -typedef void (*regmap_lock)(struct regmap *map);
35   -typedef void (*regmap_unlock)(struct regmap *map);
36   -
37 34 struct regmap {
38 35 struct mutex mutex;
39 36 spinlock_t spinlock;
40 37 regmap_lock lock;
41 38 regmap_unlock unlock;
  39 + void *lock_arg; /* This is passed to lock/unlock functions */
42 40  
43 41 struct device *dev; /* Device we do I/O on */
44 42 void *work_buf; /* Scratch buffer used to format I/O */
drivers/base/regmap/regmap.c
... ... @@ -214,23 +214,27 @@
214 214 return *(u32 *)buf;
215 215 }
216 216  
217   -static void regmap_lock_mutex(struct regmap *map)
  217 +static void regmap_lock_mutex(void *__map)
218 218 {
  219 + struct regmap *map = __map;
219 220 mutex_lock(&map->mutex);
220 221 }
221 222  
222   -static void regmap_unlock_mutex(struct regmap *map)
  223 +static void regmap_unlock_mutex(void *__map)
223 224 {
  225 + struct regmap *map = __map;
224 226 mutex_unlock(&map->mutex);
225 227 }
226 228  
227   -static void regmap_lock_spinlock(struct regmap *map)
  229 +static void regmap_lock_spinlock(void *__map)
228 230 {
  231 + struct regmap *map = __map;
229 232 spin_lock(&map->spinlock);
230 233 }
231 234  
232   -static void regmap_unlock_spinlock(struct regmap *map)
  235 +static void regmap_unlock_spinlock(void *__map)
233 236 {
  237 + struct regmap *map = __map;
234 238 spin_unlock(&map->spinlock);
235 239 }
236 240  
237 241  
... ... @@ -335,14 +339,21 @@
335 339 goto err;
336 340 }
337 341  
338   - if (bus->fast_io) {
339   - spin_lock_init(&map->spinlock);
340   - map->lock = regmap_lock_spinlock;
341   - map->unlock = regmap_unlock_spinlock;
  342 + if (config->lock && config->unlock) {
  343 + map->lock = config->lock;
  344 + map->unlock = config->unlock;
  345 + map->lock_arg = config->lock_arg;
342 346 } else {
343   - mutex_init(&map->mutex);
344   - map->lock = regmap_lock_mutex;
345   - map->unlock = regmap_unlock_mutex;
  347 + if (bus->fast_io) {
  348 + spin_lock_init(&map->spinlock);
  349 + map->lock = regmap_lock_spinlock;
  350 + map->unlock = regmap_unlock_spinlock;
  351 + } else {
  352 + mutex_init(&map->mutex);
  353 + map->lock = regmap_lock_mutex;
  354 + map->unlock = regmap_unlock_mutex;
  355 + }
  356 + map->lock_arg = map;
346 357 }
347 358 map->format.reg_bytes = DIV_ROUND_UP(config->reg_bits, 8);
348 359 map->format.pad_bytes = config->pad_bits / 8;
349 360  
... ... @@ -939,11 +950,11 @@
939 950 if (reg % map->reg_stride)
940 951 return -EINVAL;
941 952  
942   - map->lock(map);
  953 + map->lock(map->lock_arg);
943 954  
944 955 ret = _regmap_write(map, reg, val);
945 956  
946   - map->unlock(map);
  957 + map->unlock(map->lock_arg);
947 958  
948 959 return ret;
949 960 }
950 961  
... ... @@ -975,11 +986,11 @@
975 986 if (reg % map->reg_stride)
976 987 return -EINVAL;
977 988  
978   - map->lock(map);
  989 + map->lock(map->lock_arg);
979 990  
980 991 ret = _regmap_raw_write(map, reg, val, val_len);
981 992  
982   - map->unlock(map);
  993 + map->unlock(map->lock_arg);
983 994  
984 995 return ret;
985 996 }
... ... @@ -1011,7 +1022,7 @@
1011 1022 if (reg % map->reg_stride)
1012 1023 return -EINVAL;
1013 1024  
1014   - map->lock(map);
  1025 + map->lock(map->lock_arg);
1015 1026  
1016 1027 /* No formatting is require if val_byte is 1 */
1017 1028 if (val_bytes == 1) {
... ... @@ -1047,7 +1058,7 @@
1047 1058 kfree(wval);
1048 1059  
1049 1060 out:
1050   - map->unlock(map);
  1061 + map->unlock(map->lock_arg);
1051 1062 return ret;
1052 1063 }
1053 1064 EXPORT_SYMBOL_GPL(regmap_bulk_write);
1054 1065  
... ... @@ -1137,11 +1148,11 @@
1137 1148 if (reg % map->reg_stride)
1138 1149 return -EINVAL;
1139 1150  
1140   - map->lock(map);
  1151 + map->lock(map->lock_arg);
1141 1152  
1142 1153 ret = _regmap_read(map, reg, val);
1143 1154  
1144   - map->unlock(map);
  1155 + map->unlock(map->lock_arg);
1145 1156  
1146 1157 return ret;
1147 1158 }
... ... @@ -1171,7 +1182,7 @@
1171 1182 if (reg % map->reg_stride)
1172 1183 return -EINVAL;
1173 1184  
1174   - map->lock(map);
  1185 + map->lock(map->lock_arg);
1175 1186  
1176 1187 if (regmap_volatile_range(map, reg, val_count) || map->cache_bypass ||
1177 1188 map->cache_type == REGCACHE_NONE) {
... ... @@ -1193,7 +1204,7 @@
1193 1204 }
1194 1205  
1195 1206 out:
1196   - map->unlock(map);
  1207 + map->unlock(map->lock_arg);
1197 1208  
1198 1209 return ret;
1199 1210 }
1200 1211  
... ... @@ -1300,9 +1311,9 @@
1300 1311 bool change;
1301 1312 int ret;
1302 1313  
1303   - map->lock(map);
  1314 + map->lock(map->lock_arg);
1304 1315 ret = _regmap_update_bits(map, reg, mask, val, &change);
1305   - map->unlock(map);
  1316 + map->unlock(map->lock_arg);
1306 1317  
1307 1318 return ret;
1308 1319 }
1309 1320  
... ... @@ -1326,9 +1337,9 @@
1326 1337 {
1327 1338 int ret;
1328 1339  
1329   - map->lock(map);
  1340 + map->lock(map->lock_arg);
1330 1341 ret = _regmap_update_bits(map, reg, mask, val, change);
1331   - map->unlock(map);
  1342 + map->unlock(map->lock_arg);
1332 1343 return ret;
1333 1344 }
1334 1345 EXPORT_SYMBOL_GPL(regmap_update_bits_check);
... ... @@ -1357,7 +1368,7 @@
1357 1368 if (map->patch)
1358 1369 return -EBUSY;
1359 1370  
1360   - map->lock(map);
  1371 + map->lock(map->lock_arg);
1361 1372  
1362 1373 bypass = map->cache_bypass;
1363 1374  
... ... @@ -1385,7 +1396,7 @@
1385 1396 out:
1386 1397 map->cache_bypass = bypass;
1387 1398  
1388   - map->unlock(map);
  1399 + map->unlock(map->lock_arg);
1389 1400  
1390 1401 return ret;
1391 1402 }
include/linux/regmap.h
... ... @@ -53,6 +53,9 @@
53 53 REGMAP_ENDIAN_NATIVE,
54 54 };
55 55  
  56 +typedef void (*regmap_lock)(void *);
  57 +typedef void (*regmap_unlock)(void *);
  58 +
56 59 /**
57 60 * Configuration for the register map of a device.
58 61 *
... ... @@ -75,6 +78,12 @@
75 78 * @precious_reg: Optional callback returning true if the rgister
76 79 * should not be read outside of a call from the driver
77 80 * (eg, a clear on read interrupt status register).
  81 + * @lock: Optional lock callback (overrides regmap's default lock
  82 + * function, based on spinlock or mutex).
  83 + * @unlock: As above for unlocking.
  84 + * @lock_arg: this field is passed as the only argument of lock/unlock
  85 + * functions (ignored in case regular lock/unlock functions
  86 + * are not overridden).
78 87 *
79 88 * @max_register: Optional, specifies the maximum valid register index.
80 89 * @reg_defaults: Power on reset values for registers (for use with
... ... @@ -116,6 +125,9 @@
116 125 bool (*readable_reg)(struct device *dev, unsigned int reg);
117 126 bool (*volatile_reg)(struct device *dev, unsigned int reg);
118 127 bool (*precious_reg)(struct device *dev, unsigned int reg);
  128 + regmap_lock lock;
  129 + regmap_unlock unlock;
  130 + void *lock_arg;
119 131  
120 132 unsigned int max_register;
121 133 const struct reg_default *reg_defaults;
... ... @@ -181,7 +193,9 @@
181 193 * Description of a hardware bus for the register map infrastructure.
182 194 *
183 195 * @fast_io: Register IO is fast. Use a spinlock instead of a mutex
184   - * to perform locking.
  196 + * to perform locking. This field is ignored if custom lock/unlock
  197 + * functions are used (see fields lock/unlock of
  198 + * struct regmap_config).
185 199 * @write: Write operation.
186 200 * @gather_write: Write operation with split register/value, return -ENOTSUPP
187 201 * if not implemented on a given device.