diff options
-rw-r--r-- | drivers/base/regmap/internal.h | 5 | ||||
-rw-r--r-- | drivers/base/regmap/regmap-debugfs.c | 16 | ||||
-rw-r--r-- | drivers/base/regmap/regmap.c | 64 | ||||
-rw-r--r-- | include/linux/regmap.h | 8 |
4 files changed, 71 insertions, 22 deletions
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h index a0380338946a..2a4435d76028 100644 --- a/drivers/base/regmap/internal.h +++ b/drivers/base/regmap/internal.h | |||
@@ -105,8 +105,8 @@ struct regmap { | |||
105 | 105 | ||
106 | bool defer_caching; | 106 | bool defer_caching; |
107 | 107 | ||
108 | u8 read_flag_mask; | 108 | unsigned long read_flag_mask; |
109 | u8 write_flag_mask; | 109 | unsigned long write_flag_mask; |
110 | 110 | ||
111 | /* number of bits to (left) shift the reg value when formatting*/ | 111 | /* number of bits to (left) shift the reg value when formatting*/ |
112 | int reg_shift; | 112 | int reg_shift; |
@@ -173,6 +173,7 @@ struct regcache_ops { | |||
173 | int (*drop)(struct regmap *map, unsigned int min, unsigned int max); | 173 | int (*drop)(struct regmap *map, unsigned int min, unsigned int max); |
174 | }; | 174 | }; |
175 | 175 | ||
176 | bool regmap_cached(struct regmap *map, unsigned int reg); | ||
176 | bool regmap_writeable(struct regmap *map, unsigned int reg); | 177 | bool regmap_writeable(struct regmap *map, unsigned int reg); |
177 | bool regmap_readable(struct regmap *map, unsigned int reg); | 178 | bool regmap_readable(struct regmap *map, unsigned int reg); |
178 | bool regmap_volatile(struct regmap *map, unsigned int reg); | 179 | bool regmap_volatile(struct regmap *map, unsigned int reg); |
diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c index 1ee3d40861c7..36ce3511c733 100644 --- a/drivers/base/regmap/regmap-debugfs.c +++ b/drivers/base/regmap/regmap-debugfs.c | |||
@@ -77,6 +77,17 @@ static void regmap_debugfs_free_dump_cache(struct regmap *map) | |||
77 | } | 77 | } |
78 | } | 78 | } |
79 | 79 | ||
80 | static bool regmap_printable(struct regmap *map, unsigned int reg) | ||
81 | { | ||
82 | if (regmap_precious(map, reg)) | ||
83 | return false; | ||
84 | |||
85 | if (!regmap_readable(map, reg) && !regmap_cached(map, reg)) | ||
86 | return false; | ||
87 | |||
88 | return true; | ||
89 | } | ||
90 | |||
80 | /* | 91 | /* |
81 | * Work out where the start offset maps into register numbers, bearing | 92 | * Work out where the start offset maps into register numbers, bearing |
82 | * in mind that we suppress hidden registers. | 93 | * in mind that we suppress hidden registers. |
@@ -105,8 +116,7 @@ static unsigned int regmap_debugfs_get_dump_start(struct regmap *map, | |||
105 | if (list_empty(&map->debugfs_off_cache)) { | 116 | if (list_empty(&map->debugfs_off_cache)) { |
106 | for (; i <= map->max_register; i += map->reg_stride) { | 117 | for (; i <= map->max_register; i += map->reg_stride) { |
107 | /* Skip unprinted registers, closing off cache entry */ | 118 | /* Skip unprinted registers, closing off cache entry */ |
108 | if (!regmap_readable(map, i) || | 119 | if (!regmap_printable(map, i)) { |
109 | regmap_precious(map, i)) { | ||
110 | if (c) { | 120 | if (c) { |
111 | c->max = p - 1; | 121 | c->max = p - 1; |
112 | c->max_reg = i - map->reg_stride; | 122 | c->max_reg = i - map->reg_stride; |
@@ -204,7 +214,7 @@ static ssize_t regmap_read_debugfs(struct regmap *map, unsigned int from, | |||
204 | start_reg = regmap_debugfs_get_dump_start(map, from, *ppos, &p); | 214 | start_reg = regmap_debugfs_get_dump_start(map, from, *ppos, &p); |
205 | 215 | ||
206 | for (i = start_reg; i <= to; i += map->reg_stride) { | 216 | for (i = start_reg; i <= to; i += map->reg_stride) { |
207 | if (!regmap_readable(map, i)) | 217 | if (!regmap_readable(map, i) && !regmap_cached(map, i)) |
208 | continue; | 218 | continue; |
209 | 219 | ||
210 | if (regmap_precious(map, i)) | 220 | if (regmap_precious(map, i)) |
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index e964d068874d..ae63bb0875ea 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c | |||
@@ -93,6 +93,29 @@ bool regmap_writeable(struct regmap *map, unsigned int reg) | |||
93 | return true; | 93 | return true; |
94 | } | 94 | } |
95 | 95 | ||
96 | bool regmap_cached(struct regmap *map, unsigned int reg) | ||
97 | { | ||
98 | int ret; | ||
99 | unsigned int val; | ||
100 | |||
101 | if (map->cache == REGCACHE_NONE) | ||
102 | return false; | ||
103 | |||
104 | if (!map->cache_ops) | ||
105 | return false; | ||
106 | |||
107 | if (map->max_register && reg > map->max_register) | ||
108 | return false; | ||
109 | |||
110 | map->lock(map->lock_arg); | ||
111 | ret = regcache_read(map, reg, &val); | ||
112 | map->unlock(map->lock_arg); | ||
113 | if (ret) | ||
114 | return false; | ||
115 | |||
116 | return true; | ||
117 | } | ||
118 | |||
96 | bool regmap_readable(struct regmap *map, unsigned int reg) | 119 | bool regmap_readable(struct regmap *map, unsigned int reg) |
97 | { | 120 | { |
98 | if (!map->reg_read) | 121 | if (!map->reg_read) |
@@ -749,6 +772,9 @@ struct regmap *__regmap_init(struct device *dev, | |||
749 | case REGMAP_ENDIAN_BIG: | 772 | case REGMAP_ENDIAN_BIG: |
750 | map->format.format_reg = regmap_format_16_be; | 773 | map->format.format_reg = regmap_format_16_be; |
751 | break; | 774 | break; |
775 | case REGMAP_ENDIAN_LITTLE: | ||
776 | map->format.format_reg = regmap_format_16_le; | ||
777 | break; | ||
752 | case REGMAP_ENDIAN_NATIVE: | 778 | case REGMAP_ENDIAN_NATIVE: |
753 | map->format.format_reg = regmap_format_16_native; | 779 | map->format.format_reg = regmap_format_16_native; |
754 | break; | 780 | break; |
@@ -768,6 +794,9 @@ struct regmap *__regmap_init(struct device *dev, | |||
768 | case REGMAP_ENDIAN_BIG: | 794 | case REGMAP_ENDIAN_BIG: |
769 | map->format.format_reg = regmap_format_32_be; | 795 | map->format.format_reg = regmap_format_32_be; |
770 | break; | 796 | break; |
797 | case REGMAP_ENDIAN_LITTLE: | ||
798 | map->format.format_reg = regmap_format_32_le; | ||
799 | break; | ||
771 | case REGMAP_ENDIAN_NATIVE: | 800 | case REGMAP_ENDIAN_NATIVE: |
772 | map->format.format_reg = regmap_format_32_native; | 801 | map->format.format_reg = regmap_format_32_native; |
773 | break; | 802 | break; |
@@ -782,6 +811,9 @@ struct regmap *__regmap_init(struct device *dev, | |||
782 | case REGMAP_ENDIAN_BIG: | 811 | case REGMAP_ENDIAN_BIG: |
783 | map->format.format_reg = regmap_format_64_be; | 812 | map->format.format_reg = regmap_format_64_be; |
784 | break; | 813 | break; |
814 | case REGMAP_ENDIAN_LITTLE: | ||
815 | map->format.format_reg = regmap_format_64_le; | ||
816 | break; | ||
785 | case REGMAP_ENDIAN_NATIVE: | 817 | case REGMAP_ENDIAN_NATIVE: |
786 | map->format.format_reg = regmap_format_64_native; | 818 | map->format.format_reg = regmap_format_64_native; |
787 | break; | 819 | break; |
@@ -1296,12 +1328,26 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg, | |||
1296 | return 0; | 1328 | return 0; |
1297 | } | 1329 | } |
1298 | 1330 | ||
1331 | static void regmap_set_work_buf_flag_mask(struct regmap *map, int max_bytes, | ||
1332 | unsigned long mask) | ||
1333 | { | ||
1334 | u8 *buf; | ||
1335 | int i; | ||
1336 | |||
1337 | if (!mask || !map->work_buf) | ||
1338 | return; | ||
1339 | |||
1340 | buf = map->work_buf; | ||
1341 | |||
1342 | for (i = 0; i < max_bytes; i++) | ||
1343 | buf[i] |= (mask >> (8 * i)) & 0xff; | ||
1344 | } | ||
1345 | |||
1299 | int _regmap_raw_write(struct regmap *map, unsigned int reg, | 1346 | int _regmap_raw_write(struct regmap *map, unsigned int reg, |
1300 | const void *val, size_t val_len) | 1347 | const void *val, size_t val_len) |
1301 | { | 1348 | { |
1302 | struct regmap_range_node *range; | 1349 | struct regmap_range_node *range; |
1303 | unsigned long flags; | 1350 | unsigned long flags; |
1304 | u8 *u8 = map->work_buf; | ||
1305 | void *work_val = map->work_buf + map->format.reg_bytes + | 1351 | void *work_val = map->work_buf + map->format.reg_bytes + |
1306 | map->format.pad_bytes; | 1352 | map->format.pad_bytes; |
1307 | void *buf; | 1353 | void *buf; |
@@ -1370,8 +1416,8 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg, | |||
1370 | } | 1416 | } |
1371 | 1417 | ||
1372 | map->format.format_reg(map->work_buf, reg, map->reg_shift); | 1418 | map->format.format_reg(map->work_buf, reg, map->reg_shift); |
1373 | 1419 | regmap_set_work_buf_flag_mask(map, map->format.reg_bytes, | |
1374 | u8[0] |= map->write_flag_mask; | 1420 | map->write_flag_mask); |
1375 | 1421 | ||
1376 | /* | 1422 | /* |
1377 | * Essentially all I/O mechanisms will be faster with a single | 1423 | * Essentially all I/O mechanisms will be faster with a single |
@@ -2251,7 +2297,6 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, | |||
2251 | unsigned int val_len) | 2297 | unsigned int val_len) |
2252 | { | 2298 | { |
2253 | struct regmap_range_node *range; | 2299 | struct regmap_range_node *range; |
2254 | u8 *u8 = map->work_buf; | ||
2255 | int ret; | 2300 | int ret; |
2256 | 2301 | ||
2257 | WARN_ON(!map->bus); | 2302 | WARN_ON(!map->bus); |
@@ -2268,15 +2313,8 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, | |||
2268 | } | 2313 | } |
2269 | 2314 | ||
2270 | map->format.format_reg(map->work_buf, reg, map->reg_shift); | 2315 | map->format.format_reg(map->work_buf, reg, map->reg_shift); |
2271 | 2316 | regmap_set_work_buf_flag_mask(map, map->format.reg_bytes, | |
2272 | /* | 2317 | map->read_flag_mask); |
2273 | * Some buses or devices flag reads by setting the high bits in the | ||
2274 | * register address; since it's always the high bits for all | ||
2275 | * current formats we can do this here rather than in | ||
2276 | * formatting. This may break if we get interesting formats. | ||
2277 | */ | ||
2278 | u8[0] |= map->read_flag_mask; | ||
2279 | |||
2280 | trace_regmap_hw_read_start(map, reg, val_len / map->format.val_bytes); | 2318 | trace_regmap_hw_read_start(map, reg, val_len / map->format.val_bytes); |
2281 | 2319 | ||
2282 | ret = map->bus->read(map->bus_context, map->work_buf, | 2320 | ret = map->bus->read(map->bus_context, map->work_buf, |
diff --git a/include/linux/regmap.h b/include/linux/regmap.h index 2c12cc5af744..9adc7b21903d 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h | |||
@@ -241,9 +241,9 @@ typedef void (*regmap_unlock)(void *); | |||
241 | * register cache support). | 241 | * register cache support). |
242 | * @num_reg_defaults: Number of elements in reg_defaults. | 242 | * @num_reg_defaults: Number of elements in reg_defaults. |
243 | * | 243 | * |
244 | * @read_flag_mask: Mask to be set in the top byte of the register when doing | 244 | * @read_flag_mask: Mask to be set in the top bytes of the register when doing |
245 | * a read. | 245 | * a read. |
246 | * @write_flag_mask: Mask to be set in the top byte of the register when doing | 246 | * @write_flag_mask: Mask to be set in the top bytes of the register when doing |
247 | * a write. If both read_flag_mask and write_flag_mask are | 247 | * a write. If both read_flag_mask and write_flag_mask are |
248 | * empty the regmap_bus default masks are used. | 248 | * empty the regmap_bus default masks are used. |
249 | * @use_single_rw: If set, converts the bulk read and write operations into | 249 | * @use_single_rw: If set, converts the bulk read and write operations into |
@@ -299,8 +299,8 @@ struct regmap_config { | |||
299 | const void *reg_defaults_raw; | 299 | const void *reg_defaults_raw; |
300 | unsigned int num_reg_defaults_raw; | 300 | unsigned int num_reg_defaults_raw; |
301 | 301 | ||
302 | u8 read_flag_mask; | 302 | unsigned long read_flag_mask; |
303 | u8 write_flag_mask; | 303 | unsigned long write_flag_mask; |
304 | 304 | ||
305 | bool use_single_rw; | 305 | bool use_single_rw; |
306 | bool can_multi_write; | 306 | bool can_multi_write; |