diff options
author | Davide Ciminaghi <ciminaghi@gnudd.com> | 2012-10-16 09:56:59 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-10-17 03:52:02 -0400 |
commit | 0d4529c534c1c664f25088eb5f5b4d7ce0ee2510 (patch) | |
tree | 5b080ef0a319b90fbcb0ab4eb768aae54851915e /drivers | |
parent | ddffeb8c4d0331609ef2581d84de4d763607bd37 (diff) |
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/base/regmap/internal.h | 4 | ||||
-rw-r--r-- | drivers/base/regmap/regmap.c | 65 |
2 files changed, 39 insertions, 30 deletions
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h index 80f9ab9c3aa4..b1ee824e2a5f 100644 --- a/drivers/base/regmap/internal.h +++ b/drivers/base/regmap/internal.h | |||
@@ -31,14 +31,12 @@ struct regmap_format { | |||
31 | unsigned int (*parse_val)(void *buf); | 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 | struct regmap { | 34 | struct regmap { |
38 | struct mutex mutex; | 35 | struct mutex mutex; |
39 | spinlock_t spinlock; | 36 | spinlock_t spinlock; |
40 | regmap_lock lock; | 37 | regmap_lock lock; |
41 | regmap_unlock unlock; | 38 | regmap_unlock unlock; |
39 | void *lock_arg; /* This is passed to lock/unlock functions */ | ||
42 | 40 | ||
43 | struct device *dev; /* Device we do I/O on */ | 41 | struct device *dev; /* Device we do I/O on */ |
44 | void *work_buf; /* Scratch buffer used to format I/O */ | 42 | void *work_buf; /* Scratch buffer used to format I/O */ |
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 52069d29ff12..5d8b75255b50 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c | |||
@@ -214,23 +214,27 @@ static unsigned int regmap_parse_32_native(void *buf) | |||
214 | return *(u32 *)buf; | 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 | mutex_lock(&map->mutex); | 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 | mutex_unlock(&map->mutex); | 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 | spin_lock(&map->spinlock); | 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 | spin_unlock(&map->spinlock); | 238 | spin_unlock(&map->spinlock); |
235 | } | 239 | } |
236 | 240 | ||
@@ -335,14 +339,21 @@ struct regmap *regmap_init(struct device *dev, | |||
335 | goto err; | 339 | goto err; |
336 | } | 340 | } |
337 | 341 | ||
338 | if (bus->fast_io) { | 342 | if (config->lock && config->unlock) { |
339 | spin_lock_init(&map->spinlock); | 343 | map->lock = config->lock; |
340 | map->lock = regmap_lock_spinlock; | 344 | map->unlock = config->unlock; |
341 | map->unlock = regmap_unlock_spinlock; | 345 | map->lock_arg = config->lock_arg; |
342 | } else { | 346 | } else { |
343 | mutex_init(&map->mutex); | 347 | if (bus->fast_io) { |
344 | map->lock = regmap_lock_mutex; | 348 | spin_lock_init(&map->spinlock); |
345 | map->unlock = regmap_unlock_mutex; | 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 | map->format.reg_bytes = DIV_ROUND_UP(config->reg_bits, 8); | 358 | map->format.reg_bytes = DIV_ROUND_UP(config->reg_bits, 8); |
348 | map->format.pad_bytes = config->pad_bits / 8; | 359 | map->format.pad_bytes = config->pad_bits / 8; |
@@ -939,11 +950,11 @@ int regmap_write(struct regmap *map, unsigned int reg, unsigned int val) | |||
939 | if (reg % map->reg_stride) | 950 | if (reg % map->reg_stride) |
940 | return -EINVAL; | 951 | return -EINVAL; |
941 | 952 | ||
942 | map->lock(map); | 953 | map->lock(map->lock_arg); |
943 | 954 | ||
944 | ret = _regmap_write(map, reg, val); | 955 | ret = _regmap_write(map, reg, val); |
945 | 956 | ||
946 | map->unlock(map); | 957 | map->unlock(map->lock_arg); |
947 | 958 | ||
948 | return ret; | 959 | return ret; |
949 | } | 960 | } |
@@ -975,11 +986,11 @@ int regmap_raw_write(struct regmap *map, unsigned int reg, | |||
975 | if (reg % map->reg_stride) | 986 | if (reg % map->reg_stride) |
976 | return -EINVAL; | 987 | return -EINVAL; |
977 | 988 | ||
978 | map->lock(map); | 989 | map->lock(map->lock_arg); |
979 | 990 | ||
980 | ret = _regmap_raw_write(map, reg, val, val_len); | 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 | return ret; | 995 | return ret; |
985 | } | 996 | } |
@@ -1011,7 +1022,7 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, | |||
1011 | if (reg % map->reg_stride) | 1022 | if (reg % map->reg_stride) |
1012 | return -EINVAL; | 1023 | return -EINVAL; |
1013 | 1024 | ||
1014 | map->lock(map); | 1025 | map->lock(map->lock_arg); |
1015 | 1026 | ||
1016 | /* No formatting is require if val_byte is 1 */ | 1027 | /* No formatting is require if val_byte is 1 */ |
1017 | if (val_bytes == 1) { | 1028 | if (val_bytes == 1) { |
@@ -1047,7 +1058,7 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, | |||
1047 | kfree(wval); | 1058 | kfree(wval); |
1048 | 1059 | ||
1049 | out: | 1060 | out: |
1050 | map->unlock(map); | 1061 | map->unlock(map->lock_arg); |
1051 | return ret; | 1062 | return ret; |
1052 | } | 1063 | } |
1053 | EXPORT_SYMBOL_GPL(regmap_bulk_write); | 1064 | EXPORT_SYMBOL_GPL(regmap_bulk_write); |
@@ -1137,11 +1148,11 @@ int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val) | |||
1137 | if (reg % map->reg_stride) | 1148 | if (reg % map->reg_stride) |
1138 | return -EINVAL; | 1149 | return -EINVAL; |
1139 | 1150 | ||
1140 | map->lock(map); | 1151 | map->lock(map->lock_arg); |
1141 | 1152 | ||
1142 | ret = _regmap_read(map, reg, val); | 1153 | ret = _regmap_read(map, reg, val); |
1143 | 1154 | ||
1144 | map->unlock(map); | 1155 | map->unlock(map->lock_arg); |
1145 | 1156 | ||
1146 | return ret; | 1157 | return ret; |
1147 | } | 1158 | } |
@@ -1171,7 +1182,7 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val, | |||
1171 | if (reg % map->reg_stride) | 1182 | if (reg % map->reg_stride) |
1172 | return -EINVAL; | 1183 | return -EINVAL; |
1173 | 1184 | ||
1174 | map->lock(map); | 1185 | map->lock(map->lock_arg); |
1175 | 1186 | ||
1176 | if (regmap_volatile_range(map, reg, val_count) || map->cache_bypass || | 1187 | if (regmap_volatile_range(map, reg, val_count) || map->cache_bypass || |
1177 | map->cache_type == REGCACHE_NONE) { | 1188 | map->cache_type == REGCACHE_NONE) { |
@@ -1193,7 +1204,7 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val, | |||
1193 | } | 1204 | } |
1194 | 1205 | ||
1195 | out: | 1206 | out: |
1196 | map->unlock(map); | 1207 | map->unlock(map->lock_arg); |
1197 | 1208 | ||
1198 | return ret; | 1209 | return ret; |
1199 | } | 1210 | } |
@@ -1300,9 +1311,9 @@ int regmap_update_bits(struct regmap *map, unsigned int reg, | |||
1300 | bool change; | 1311 | bool change; |
1301 | int ret; | 1312 | int ret; |
1302 | 1313 | ||
1303 | map->lock(map); | 1314 | map->lock(map->lock_arg); |
1304 | ret = _regmap_update_bits(map, reg, mask, val, &change); | 1315 | ret = _regmap_update_bits(map, reg, mask, val, &change); |
1305 | map->unlock(map); | 1316 | map->unlock(map->lock_arg); |
1306 | 1317 | ||
1307 | return ret; | 1318 | return ret; |
1308 | } | 1319 | } |
@@ -1326,9 +1337,9 @@ int regmap_update_bits_check(struct regmap *map, unsigned int reg, | |||
1326 | { | 1337 | { |
1327 | int ret; | 1338 | int ret; |
1328 | 1339 | ||
1329 | map->lock(map); | 1340 | map->lock(map->lock_arg); |
1330 | ret = _regmap_update_bits(map, reg, mask, val, change); | 1341 | ret = _regmap_update_bits(map, reg, mask, val, change); |
1331 | map->unlock(map); | 1342 | map->unlock(map->lock_arg); |
1332 | return ret; | 1343 | return ret; |
1333 | } | 1344 | } |
1334 | EXPORT_SYMBOL_GPL(regmap_update_bits_check); | 1345 | EXPORT_SYMBOL_GPL(regmap_update_bits_check); |
@@ -1357,7 +1368,7 @@ int regmap_register_patch(struct regmap *map, const struct reg_default *regs, | |||
1357 | if (map->patch) | 1368 | if (map->patch) |
1358 | return -EBUSY; | 1369 | return -EBUSY; |
1359 | 1370 | ||
1360 | map->lock(map); | 1371 | map->lock(map->lock_arg); |
1361 | 1372 | ||
1362 | bypass = map->cache_bypass; | 1373 | bypass = map->cache_bypass; |
1363 | 1374 | ||
@@ -1385,7 +1396,7 @@ int regmap_register_patch(struct regmap *map, const struct reg_default *regs, | |||
1385 | out: | 1396 | out: |
1386 | map->cache_bypass = bypass; | 1397 | map->cache_bypass = bypass; |
1387 | 1398 | ||
1388 | map->unlock(map); | 1399 | map->unlock(map->lock_arg); |
1389 | 1400 | ||
1390 | return ret; | 1401 | return ret; |
1391 | } | 1402 | } |