summaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-07-26 22:24:33 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-07-26 22:24:33 -0400
commitae9799975ccf5f1b2c30227d6d02aa4129750a64 (patch)
treeddce82a458a041554a95477b67e728f2a8916efa /drivers/base
parent1cd04d293c818687795b83cd8f2626bd4662feeb (diff)
parentefeb1a3ab91dc6bead3b5a522c0ceca1d711feb1 (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.c2
-rw-r--r--drivers/base/regmap/regmap-irq.c15
-rw-r--r--drivers/base/regmap/regmap.c31
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 &regmap_i2c; 261 return &regmap_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 &regmap_i2c_smbus_i2c_block; 265 return &regmap_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
371exit:
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 }
1826out: 1825out:
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;