diff options
| -rw-r--r-- | MAINTAINERS | 1 | ||||
| -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 | ||||
| -rw-r--r-- | include/linux/regmap.h | 49 |
5 files changed, 90 insertions, 8 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index f4698b1cf847..b407c5f5caa4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -9691,6 +9691,7 @@ M: Mark Brown <broonie@kernel.org> | |||
| 9691 | L: linux-kernel@vger.kernel.org | 9691 | L: linux-kernel@vger.kernel.org |
| 9692 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap.git | 9692 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap.git |
| 9693 | S: Supported | 9693 | S: Supported |
| 9694 | F: Documentation/devicetree/bindings/regmap/ | ||
| 9694 | F: drivers/base/regmap/ | 9695 | F: drivers/base/regmap/ |
| 9695 | F: include/linux/regmap.h | 9696 | F: include/linux/regmap.h |
| 9696 | 9697 | ||
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; |
diff --git a/include/linux/regmap.h b/include/linux/regmap.h index 3dc08ce15426..2c12cc5af744 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h | |||
| @@ -95,6 +95,45 @@ struct reg_sequence { | |||
| 95 | #define regmap_fields_force_update_bits(field, id, mask, val) \ | 95 | #define regmap_fields_force_update_bits(field, id, mask, val) \ |
| 96 | regmap_fields_update_bits_base(field, id, mask, val, NULL, false, true) | 96 | regmap_fields_update_bits_base(field, id, mask, val, NULL, false, true) |
| 97 | 97 | ||
| 98 | /** | ||
| 99 | * regmap_read_poll_timeout - Poll until a condition is met or a timeout occurs | ||
| 100 | * @map: Regmap to read from | ||
| 101 | * @addr: Address to poll | ||
| 102 | * @val: Unsigned integer variable to read the value into | ||
| 103 | * @cond: Break condition (usually involving @val) | ||
| 104 | * @sleep_us: Maximum time to sleep between reads in us (0 | ||
| 105 | * tight-loops). Should be less than ~20ms since usleep_range | ||
| 106 | * is used (see Documentation/timers/timers-howto.txt). | ||
| 107 | * @timeout_us: Timeout in us, 0 means never timeout | ||
| 108 | * | ||
| 109 | * Returns 0 on success and -ETIMEDOUT upon a timeout or the regmap_read | ||
| 110 | * error return value in case of a error read. In the two former cases, | ||
| 111 | * the last read value at @addr is stored in @val. Must not be called | ||
| 112 | * from atomic context if sleep_us or timeout_us are used. | ||
| 113 | * | ||
| 114 | * This is modelled after the readx_poll_timeout macros in linux/iopoll.h. | ||
| 115 | */ | ||
| 116 | #define regmap_read_poll_timeout(map, addr, val, cond, sleep_us, timeout_us) \ | ||
| 117 | ({ \ | ||
| 118 | ktime_t timeout = ktime_add_us(ktime_get(), timeout_us); \ | ||
| 119 | int ret; \ | ||
| 120 | might_sleep_if(sleep_us); \ | ||
| 121 | for (;;) { \ | ||
| 122 | ret = regmap_read((map), (addr), &(val)); \ | ||
| 123 | if (ret) \ | ||
| 124 | break; \ | ||
| 125 | if (cond) \ | ||
| 126 | break; \ | ||
| 127 | if (timeout_us && ktime_compare(ktime_get(), timeout) > 0) { \ | ||
| 128 | ret = regmap_read((map), (addr), &(val)); \ | ||
| 129 | break; \ | ||
| 130 | } \ | ||
| 131 | if (sleep_us) \ | ||
| 132 | usleep_range((sleep_us >> 2) + 1, sleep_us); \ | ||
| 133 | } \ | ||
| 134 | ret ?: ((cond) ? 0 : -ETIMEDOUT); \ | ||
| 135 | }) | ||
| 136 | |||
| 98 | #ifdef CONFIG_REGMAP | 137 | #ifdef CONFIG_REGMAP |
| 99 | 138 | ||
| 100 | enum regmap_endian { | 139 | enum regmap_endian { |
| @@ -851,6 +890,12 @@ struct regmap_irq { | |||
| 851 | * @num_type_reg: Number of type registers. | 890 | * @num_type_reg: Number of type registers. |
| 852 | * @type_reg_stride: Stride to use for chips where type registers are not | 891 | * @type_reg_stride: Stride to use for chips where type registers are not |
| 853 | * contiguous. | 892 | * contiguous. |
| 893 | * @handle_pre_irq: Driver specific callback to handle interrupt from device | ||
| 894 | * before regmap_irq_handler process the interrupts. | ||
| 895 | * @handle_post_irq: Driver specific callback to handle interrupt from device | ||
| 896 | * after handling the interrupts in regmap_irq_handler(). | ||
| 897 | * @irq_drv_data: Driver specific IRQ data which is passed as parameter when | ||
| 898 | * driver specific pre/post interrupt handler is called. | ||
| 854 | */ | 899 | */ |
| 855 | struct regmap_irq_chip { | 900 | struct regmap_irq_chip { |
| 856 | const char *name; | 901 | const char *name; |
| @@ -877,6 +922,10 @@ struct regmap_irq_chip { | |||
| 877 | 922 | ||
| 878 | int num_type_reg; | 923 | int num_type_reg; |
| 879 | unsigned int type_reg_stride; | 924 | unsigned int type_reg_stride; |
| 925 | |||
| 926 | int (*handle_pre_irq)(void *irq_drv_data); | ||
| 927 | int (*handle_post_irq)(void *irq_drv_data); | ||
| 928 | void *irq_drv_data; | ||
| 880 | }; | 929 | }; |
| 881 | 930 | ||
| 882 | struct regmap_irq_chip_data; | 931 | struct regmap_irq_chip_data; |
