diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-26 22:24:33 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-26 22:24:33 -0400 |
commit | ae9799975ccf5f1b2c30227d6d02aa4129750a64 (patch) | |
tree | ddce82a458a041554a95477b67e728f2a8916efa /drivers/base | |
parent | 1cd04d293c818687795b83cd8f2626bd4662feeb (diff) | |
parent | efeb1a3ab91dc6bead3b5a522c0ceca1d711feb1 (diff) |
Merge tag 'regmap-v4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap
Pull regmap updates from Mark Brown:
"Several small updates and API enhancements:
- provide transparent unrolling of bulk writes into individual writes
so they can be used with devices without raw formatting.
- fix compatibility between I2C controllers supporting block commands
and devices with more than 8 bit wide registers.
- add some helpers for iopoll-like functionality and workarounds for
weird interrupt controllers"
* tag 'regmap-v4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap:
regmap: add iopoll-like polling macro
regmap: Support bulk writes for devices without raw formatting
regmap-i2c: Use i2c block command only if register value width is 8 bit
regmap: irq: Add support to call client specific pre/post interrupt service
regmap: Add file patterns for regmap device tree bindings
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/regmap/regmap-i2c.c | 2 | ||||
-rw-r--r-- | drivers/base/regmap/regmap-irq.c | 15 | ||||
-rw-r--r-- | drivers/base/regmap/regmap.c | 31 |
3 files changed, 40 insertions, 8 deletions
diff --git a/drivers/base/regmap/regmap-i2c.c b/drivers/base/regmap/regmap-i2c.c index 1a8ec3b2b601..4735318f4268 100644 --- a/drivers/base/regmap/regmap-i2c.c +++ b/drivers/base/regmap/regmap-i2c.c | |||
@@ -259,7 +259,7 @@ static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c, | |||
259 | { | 259 | { |
260 | if (i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C)) | 260 | if (i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C)) |
261 | return ®map_i2c; | 261 | return ®map_i2c; |
262 | else if (config->reg_bits == 8 && | 262 | else if (config->val_bits == 8 && config->reg_bits == 8 && |
263 | i2c_check_functionality(i2c->adapter, | 263 | i2c_check_functionality(i2c->adapter, |
264 | I2C_FUNC_SMBUS_I2C_BLOCK)) | 264 | I2C_FUNC_SMBUS_I2C_BLOCK)) |
265 | return ®map_i2c_smbus_i2c_block; | 265 | return ®map_i2c_smbus_i2c_block; |
diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c index 26f799e71c82..ec262476d043 100644 --- a/drivers/base/regmap/regmap-irq.c +++ b/drivers/base/regmap/regmap-irq.c | |||
@@ -268,13 +268,16 @@ static irqreturn_t regmap_irq_thread(int irq, void *d) | |||
268 | bool handled = false; | 268 | bool handled = false; |
269 | u32 reg; | 269 | u32 reg; |
270 | 270 | ||
271 | if (chip->handle_pre_irq) | ||
272 | chip->handle_pre_irq(chip->irq_drv_data); | ||
273 | |||
271 | if (chip->runtime_pm) { | 274 | if (chip->runtime_pm) { |
272 | ret = pm_runtime_get_sync(map->dev); | 275 | ret = pm_runtime_get_sync(map->dev); |
273 | if (ret < 0) { | 276 | if (ret < 0) { |
274 | dev_err(map->dev, "IRQ thread failed to resume: %d\n", | 277 | dev_err(map->dev, "IRQ thread failed to resume: %d\n", |
275 | ret); | 278 | ret); |
276 | pm_runtime_put(map->dev); | 279 | pm_runtime_put(map->dev); |
277 | return IRQ_NONE; | 280 | goto exit; |
278 | } | 281 | } |
279 | } | 282 | } |
280 | 283 | ||
@@ -296,7 +299,7 @@ static irqreturn_t regmap_irq_thread(int irq, void *d) | |||
296 | if (ret != 0) { | 299 | if (ret != 0) { |
297 | dev_err(map->dev, "Failed to read IRQ status: %d\n", | 300 | dev_err(map->dev, "Failed to read IRQ status: %d\n", |
298 | ret); | 301 | ret); |
299 | return IRQ_NONE; | 302 | goto exit; |
300 | } | 303 | } |
301 | 304 | ||
302 | for (i = 0; i < data->chip->num_regs; i++) { | 305 | for (i = 0; i < data->chip->num_regs; i++) { |
@@ -312,7 +315,7 @@ static irqreturn_t regmap_irq_thread(int irq, void *d) | |||
312 | break; | 315 | break; |
313 | default: | 316 | default: |
314 | BUG(); | 317 | BUG(); |
315 | return IRQ_NONE; | 318 | goto exit; |
316 | } | 319 | } |
317 | } | 320 | } |
318 | 321 | ||
@@ -329,7 +332,7 @@ static irqreturn_t regmap_irq_thread(int irq, void *d) | |||
329 | ret); | 332 | ret); |
330 | if (chip->runtime_pm) | 333 | if (chip->runtime_pm) |
331 | pm_runtime_put(map->dev); | 334 | pm_runtime_put(map->dev); |
332 | return IRQ_NONE; | 335 | goto exit; |
333 | } | 336 | } |
334 | } | 337 | } |
335 | } | 338 | } |
@@ -365,6 +368,10 @@ static irqreturn_t regmap_irq_thread(int irq, void *d) | |||
365 | if (chip->runtime_pm) | 368 | if (chip->runtime_pm) |
366 | pm_runtime_put(map->dev); | 369 | pm_runtime_put(map->dev); |
367 | 370 | ||
371 | exit: | ||
372 | if (chip->handle_post_irq) | ||
373 | chip->handle_post_irq(chip->irq_drv_data); | ||
374 | |||
368 | if (handled) | 375 | if (handled) |
369 | return IRQ_HANDLED; | 376 | return IRQ_HANDLED; |
370 | else | 377 | else |
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index df2d2ef5d6b3..51fa7d66a393 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c | |||
@@ -1777,8 +1777,6 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, | |||
1777 | size_t val_bytes = map->format.val_bytes; | 1777 | size_t val_bytes = map->format.val_bytes; |
1778 | size_t total_size = val_bytes * val_count; | 1778 | size_t total_size = val_bytes * val_count; |
1779 | 1779 | ||
1780 | if (map->bus && !map->format.parse_inplace) | ||
1781 | return -EINVAL; | ||
1782 | if (!IS_ALIGNED(reg, map->reg_stride)) | 1780 | if (!IS_ALIGNED(reg, map->reg_stride)) |
1783 | return -EINVAL; | 1781 | return -EINVAL; |
1784 | 1782 | ||
@@ -1789,7 +1787,8 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, | |||
1789 | * | 1787 | * |
1790 | * The first if block is used for memory mapped io. It does not allow | 1788 | * The first if block is used for memory mapped io. It does not allow |
1791 | * val_bytes of 3 for example. | 1789 | * val_bytes of 3 for example. |
1792 | * The second one is used for busses which do not have this limitation | 1790 | * The second one is for busses that do not provide raw I/O. |
1791 | * The third one is used for busses which do not have these limitations | ||
1793 | * and can write arbitrary value lengths. | 1792 | * and can write arbitrary value lengths. |
1794 | */ | 1793 | */ |
1795 | if (!map->bus) { | 1794 | if (!map->bus) { |
@@ -1825,6 +1824,32 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, | |||
1825 | } | 1824 | } |
1826 | out: | 1825 | out: |
1827 | map->unlock(map->lock_arg); | 1826 | map->unlock(map->lock_arg); |
1827 | } else if (map->bus && !map->format.parse_inplace) { | ||
1828 | const u8 *u8 = val; | ||
1829 | const u16 *u16 = val; | ||
1830 | const u32 *u32 = val; | ||
1831 | unsigned int ival; | ||
1832 | |||
1833 | for (i = 0; i < val_count; i++) { | ||
1834 | switch (map->format.val_bytes) { | ||
1835 | case 4: | ||
1836 | ival = u32[i]; | ||
1837 | break; | ||
1838 | case 2: | ||
1839 | ival = u16[i]; | ||
1840 | break; | ||
1841 | case 1: | ||
1842 | ival = u8[i]; | ||
1843 | break; | ||
1844 | default: | ||
1845 | return -EINVAL; | ||
1846 | } | ||
1847 | |||
1848 | ret = regmap_write(map, reg + (i * map->reg_stride), | ||
1849 | ival); | ||
1850 | if (ret) | ||
1851 | return ret; | ||
1852 | } | ||
1828 | } else if (map->use_single_write || | 1853 | } else if (map->use_single_write || |
1829 | (map->max_raw_write && map->max_raw_write < total_size)) { | 1854 | (map->max_raw_write && map->max_raw_write < total_size)) { |
1830 | int chunk_stride = map->reg_stride; | 1855 | int chunk_stride = map->reg_stride; |