aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/base/regmap/Kconfig4
-rw-r--r--drivers/base/regmap/internal.h2
-rw-r--r--drivers/base/regmap/regmap-spi.c2
-rw-r--r--drivers/base/regmap/regmap-spmi.c4
-rw-r--r--drivers/base/regmap/regmap.c111
5 files changed, 104 insertions, 19 deletions
diff --git a/drivers/base/regmap/Kconfig b/drivers/base/regmap/Kconfig
index 073c0b77e5b3..e7fa7b4bf9af 100644
--- a/drivers/base/regmap/Kconfig
+++ b/drivers/base/regmap/Kconfig
@@ -5,6 +5,7 @@
5config REGMAP 5config REGMAP
6 default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_W1 || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ) 6 default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_W1 || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ)
7 select IRQ_DOMAIN if REGMAP_IRQ 7 select IRQ_DOMAIN if REGMAP_IRQ
8 select REGMAP_HWSPINLOCK if HWSPINLOCK=y
8 bool 9 bool
9 10
10config REGCACHE_COMPRESSED 11config REGCACHE_COMPRESSED
@@ -36,3 +37,6 @@ config REGMAP_MMIO
36 37
37config REGMAP_IRQ 38config REGMAP_IRQ
38 bool 39 bool
40
41config REGMAP_HWSPINLOCK
42 bool
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index 2a4435d76028..8641183cac2f 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -157,6 +157,8 @@ struct regmap {
157 157
158 struct rb_root range_tree; 158 struct rb_root range_tree;
159 void *selector_work_buf; /* Scratch buffer used for selector */ 159 void *selector_work_buf; /* Scratch buffer used for selector */
160
161 struct hwspinlock *hwlock;
160}; 162};
161 163
162struct regcache_ops { 164struct regcache_ops {
diff --git a/drivers/base/regmap/regmap-spi.c b/drivers/base/regmap/regmap-spi.c
index edd9a839d004..c7150dd264d5 100644
--- a/drivers/base/regmap/regmap-spi.c
+++ b/drivers/base/regmap/regmap-spi.c
@@ -102,7 +102,7 @@ static int regmap_spi_read(void *context,
102 return spi_write_then_read(spi, reg, reg_size, val, val_size); 102 return spi_write_then_read(spi, reg, reg_size, val, val_size);
103} 103}
104 104
105static struct regmap_bus regmap_spi = { 105static const struct regmap_bus regmap_spi = {
106 .write = regmap_spi_write, 106 .write = regmap_spi_write,
107 .gather_write = regmap_spi_gather_write, 107 .gather_write = regmap_spi_gather_write,
108 .async_write = regmap_spi_async_write, 108 .async_write = regmap_spi_async_write,
diff --git a/drivers/base/regmap/regmap-spmi.c b/drivers/base/regmap/regmap-spmi.c
index 4a36e415e938..0bfb8ed244d5 100644
--- a/drivers/base/regmap/regmap-spmi.c
+++ b/drivers/base/regmap/regmap-spmi.c
@@ -83,7 +83,7 @@ static int regmap_spmi_base_write(void *context, const void *data,
83 count - 1); 83 count - 1);
84} 84}
85 85
86static struct regmap_bus regmap_spmi_base = { 86static const struct regmap_bus regmap_spmi_base = {
87 .read = regmap_spmi_base_read, 87 .read = regmap_spmi_base_read,
88 .write = regmap_spmi_base_write, 88 .write = regmap_spmi_base_write,
89 .gather_write = regmap_spmi_base_gather_write, 89 .gather_write = regmap_spmi_base_gather_write,
@@ -203,7 +203,7 @@ static int regmap_spmi_ext_write(void *context, const void *data,
203 count - 2); 203 count - 2);
204} 204}
205 205
206static struct regmap_bus regmap_spmi_ext = { 206static const struct regmap_bus regmap_spmi_ext = {
207 .read = regmap_spmi_ext_read, 207 .read = regmap_spmi_ext_read,
208 .write = regmap_spmi_ext_write, 208 .write = regmap_spmi_ext_write,
209 .gather_write = regmap_spmi_ext_gather_write, 209 .gather_write = regmap_spmi_ext_gather_write,
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index b9a779a4a739..8d516a9bfc01 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -20,6 +20,7 @@
20#include <linux/sched.h> 20#include <linux/sched.h>
21#include <linux/delay.h> 21#include <linux/delay.h>
22#include <linux/log2.h> 22#include <linux/log2.h>
23#include <linux/hwspinlock.h>
23 24
24#define CREATE_TRACE_POINTS 25#define CREATE_TRACE_POINTS
25#include "trace.h" 26#include "trace.h"
@@ -413,6 +414,51 @@ static unsigned int regmap_parse_64_native(const void *buf)
413} 414}
414#endif 415#endif
415 416
417#ifdef REGMAP_HWSPINLOCK
418static void regmap_lock_hwlock(void *__map)
419{
420 struct regmap *map = __map;
421
422 hwspin_lock_timeout(map->hwlock, UINT_MAX);
423}
424
425static void regmap_lock_hwlock_irq(void *__map)
426{
427 struct regmap *map = __map;
428
429 hwspin_lock_timeout_irq(map->hwlock, UINT_MAX);
430}
431
432static void regmap_lock_hwlock_irqsave(void *__map)
433{
434 struct regmap *map = __map;
435
436 hwspin_lock_timeout_irqsave(map->hwlock, UINT_MAX,
437 &map->spinlock_flags);
438}
439
440static void regmap_unlock_hwlock(void *__map)
441{
442 struct regmap *map = __map;
443
444 hwspin_unlock(map->hwlock);
445}
446
447static void regmap_unlock_hwlock_irq(void *__map)
448{
449 struct regmap *map = __map;
450
451 hwspin_unlock_irq(map->hwlock);
452}
453
454static void regmap_unlock_hwlock_irqrestore(void *__map)
455{
456 struct regmap *map = __map;
457
458 hwspin_unlock_irqrestore(map->hwlock, &map->spinlock_flags);
459}
460#endif
461
416static void regmap_lock_mutex(void *__map) 462static void regmap_lock_mutex(void *__map)
417{ 463{
418 struct regmap *map = __map; 464 struct regmap *map = __map;
@@ -627,6 +673,34 @@ struct regmap *__regmap_init(struct device *dev,
627 map->lock = config->lock; 673 map->lock = config->lock;
628 map->unlock = config->unlock; 674 map->unlock = config->unlock;
629 map->lock_arg = config->lock_arg; 675 map->lock_arg = config->lock_arg;
676 } else if (config->hwlock_id) {
677#ifdef REGMAP_HWSPINLOCK
678 map->hwlock = hwspin_lock_request_specific(config->hwlock_id);
679 if (!map->hwlock) {
680 ret = -ENXIO;
681 goto err_map;
682 }
683
684 switch (config->hwlock_mode) {
685 case HWLOCK_IRQSTATE:
686 map->lock = regmap_lock_hwlock_irqsave;
687 map->unlock = regmap_unlock_hwlock_irqrestore;
688 break;
689 case HWLOCK_IRQ:
690 map->lock = regmap_lock_hwlock_irq;
691 map->unlock = regmap_unlock_hwlock_irq;
692 break;
693 default:
694 map->lock = regmap_lock_hwlock;
695 map->unlock = regmap_unlock_hwlock;
696 break;
697 }
698
699 map->lock_arg = map;
700#else
701 ret = -EINVAL;
702 goto err_map;
703#endif
630 } else { 704 } else {
631 if ((bus && bus->fast_io) || 705 if ((bus && bus->fast_io) ||
632 config->fast_io) { 706 config->fast_io) {
@@ -729,7 +803,7 @@ struct regmap *__regmap_init(struct device *dev,
729 map->format.format_write = regmap_format_2_6_write; 803 map->format.format_write = regmap_format_2_6_write;
730 break; 804 break;
731 default: 805 default:
732 goto err_map; 806 goto err_hwlock;
733 } 807 }
734 break; 808 break;
735 809
@@ -739,7 +813,7 @@ struct regmap *__regmap_init(struct device *dev,
739 map->format.format_write = regmap_format_4_12_write; 813 map->format.format_write = regmap_format_4_12_write;
740 break; 814 break;
741 default: 815 default:
742 goto err_map; 816 goto err_hwlock;
743 } 817 }
744 break; 818 break;
745 819
@@ -749,7 +823,7 @@ struct regmap *__regmap_init(struct device *dev,
749 map->format.format_write = regmap_format_7_9_write; 823 map->format.format_write = regmap_format_7_9_write;
750 break; 824 break;
751 default: 825 default:
752 goto err_map; 826 goto err_hwlock;
753 } 827 }
754 break; 828 break;
755 829
@@ -759,7 +833,7 @@ struct regmap *__regmap_init(struct device *dev,
759 map->format.format_write = regmap_format_10_14_write; 833 map->format.format_write = regmap_format_10_14_write;
760 break; 834 break;
761 default: 835 default:
762 goto err_map; 836 goto err_hwlock;
763 } 837 }
764 break; 838 break;
765 839
@@ -779,13 +853,13 @@ struct regmap *__regmap_init(struct device *dev,
779 map->format.format_reg = regmap_format_16_native; 853 map->format.format_reg = regmap_format_16_native;
780 break; 854 break;
781 default: 855 default:
782 goto err_map; 856 goto err_hwlock;
783 } 857 }
784 break; 858 break;
785 859
786 case 24: 860 case 24:
787 if (reg_endian != REGMAP_ENDIAN_BIG) 861 if (reg_endian != REGMAP_ENDIAN_BIG)
788 goto err_map; 862 goto err_hwlock;
789 map->format.format_reg = regmap_format_24; 863 map->format.format_reg = regmap_format_24;
790 break; 864 break;
791 865
@@ -801,7 +875,7 @@ struct regmap *__regmap_init(struct device *dev,
801 map->format.format_reg = regmap_format_32_native; 875 map->format.format_reg = regmap_format_32_native;
802 break; 876 break;
803 default: 877 default:
804 goto err_map; 878 goto err_hwlock;
805 } 879 }
806 break; 880 break;
807 881
@@ -818,13 +892,13 @@ struct regmap *__regmap_init(struct device *dev,
818 map->format.format_reg = regmap_format_64_native; 892 map->format.format_reg = regmap_format_64_native;
819 break; 893 break;
820 default: 894 default:
821 goto err_map; 895 goto err_hwlock;
822 } 896 }
823 break; 897 break;
824#endif 898#endif
825 899
826 default: 900 default:
827 goto err_map; 901 goto err_hwlock;
828 } 902 }
829 903
830 if (val_endian == REGMAP_ENDIAN_NATIVE) 904 if (val_endian == REGMAP_ENDIAN_NATIVE)
@@ -853,12 +927,12 @@ struct regmap *__regmap_init(struct device *dev,
853 map->format.parse_val = regmap_parse_16_native; 927 map->format.parse_val = regmap_parse_16_native;
854 break; 928 break;
855 default: 929 default:
856 goto err_map; 930 goto err_hwlock;
857 } 931 }
858 break; 932 break;
859 case 24: 933 case 24:
860 if (val_endian != REGMAP_ENDIAN_BIG) 934 if (val_endian != REGMAP_ENDIAN_BIG)
861 goto err_map; 935 goto err_hwlock;
862 map->format.format_val = regmap_format_24; 936 map->format.format_val = regmap_format_24;
863 map->format.parse_val = regmap_parse_24; 937 map->format.parse_val = regmap_parse_24;
864 break; 938 break;
@@ -879,7 +953,7 @@ struct regmap *__regmap_init(struct device *dev,
879 map->format.parse_val = regmap_parse_32_native; 953 map->format.parse_val = regmap_parse_32_native;
880 break; 954 break;
881 default: 955 default:
882 goto err_map; 956 goto err_hwlock;
883 } 957 }
884 break; 958 break;
885#ifdef CONFIG_64BIT 959#ifdef CONFIG_64BIT
@@ -900,7 +974,7 @@ struct regmap *__regmap_init(struct device *dev,
900 map->format.parse_val = regmap_parse_64_native; 974 map->format.parse_val = regmap_parse_64_native;
901 break; 975 break;
902 default: 976 default:
903 goto err_map; 977 goto err_hwlock;
904 } 978 }
905 break; 979 break;
906#endif 980#endif
@@ -909,18 +983,18 @@ struct regmap *__regmap_init(struct device *dev,
909 if (map->format.format_write) { 983 if (map->format.format_write) {
910 if ((reg_endian != REGMAP_ENDIAN_BIG) || 984 if ((reg_endian != REGMAP_ENDIAN_BIG) ||
911 (val_endian != REGMAP_ENDIAN_BIG)) 985 (val_endian != REGMAP_ENDIAN_BIG))
912 goto err_map; 986 goto err_hwlock;
913 map->use_single_write = true; 987 map->use_single_write = true;
914 } 988 }
915 989
916 if (!map->format.format_write && 990 if (!map->format.format_write &&
917 !(map->format.format_reg && map->format.format_val)) 991 !(map->format.format_reg && map->format.format_val))
918 goto err_map; 992 goto err_hwlock;
919 993
920 map->work_buf = kzalloc(map->format.buf_size, GFP_KERNEL); 994 map->work_buf = kzalloc(map->format.buf_size, GFP_KERNEL);
921 if (map->work_buf == NULL) { 995 if (map->work_buf == NULL) {
922 ret = -ENOMEM; 996 ret = -ENOMEM;
923 goto err_map; 997 goto err_hwlock;
924 } 998 }
925 999
926 if (map->format.format_write) { 1000 if (map->format.format_write) {
@@ -1041,6 +1115,9 @@ err_regcache:
1041err_range: 1115err_range:
1042 regmap_range_exit(map); 1116 regmap_range_exit(map);
1043 kfree(map->work_buf); 1117 kfree(map->work_buf);
1118err_hwlock:
1119 if (IS_ENABLED(REGMAP_HWSPINLOCK) && map->hwlock)
1120 hwspin_lock_free(map->hwlock);
1044err_map: 1121err_map:
1045 kfree(map); 1122 kfree(map);
1046err: 1123err:
@@ -1228,6 +1305,8 @@ void regmap_exit(struct regmap *map)
1228 kfree(async->work_buf); 1305 kfree(async->work_buf);
1229 kfree(async); 1306 kfree(async);
1230 } 1307 }
1308 if (IS_ENABLED(REGMAP_HWSPINLOCK) && map->hwlock)
1309 hwspin_lock_free(map->hwlock);
1231 kfree(map); 1310 kfree(map);
1232} 1311}
1233EXPORT_SYMBOL_GPL(regmap_exit); 1312EXPORT_SYMBOL_GPL(regmap_exit);