Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'regmap-v6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap

Pull regmap updates from Mark Brown:
"A few new APIs here, support for the FSI bus (which is used in some
PowerPC systems) plus a couple of new APIs, one allowing abstractions
built on top of regmap to tell if the regmap can be used in an atomic
context and one providing a callback for an in flight device which
can't do interrupt masking very well.

There's also a fix that I never got round to sending because it really
should be fixed better but that's not happened yet and it does avoid
the problem, the fix was in -next for a long time"

* tag 'regmap-v6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap:
regmap-irq: Add handle_mask_sync() callback
regmap: Add FSI bus support
regmap: add regmap_might_sleep()
regmap-irq: Use the new num_config_regs property in regmap_add_irq_chip_fwnode

+341 -18
+5 -1
drivers/base/regmap/Kconfig
··· 4 4 # subsystems should select the appropriate symbols. 5 5 6 6 config REGMAP 7 - default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_W1 || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ || REGMAP_SOUNDWIRE || REGMAP_SOUNDWIRE_MBQ || REGMAP_SCCB || REGMAP_I3C || REGMAP_SPI_AVMM || REGMAP_MDIO) 7 + default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_W1 || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ || REGMAP_SOUNDWIRE || REGMAP_SOUNDWIRE_MBQ || REGMAP_SCCB || REGMAP_I3C || REGMAP_SPI_AVMM || REGMAP_MDIO || REGMAP_FSI) 8 8 select IRQ_DOMAIN if REGMAP_IRQ 9 9 select MDIO_BUS if REGMAP_MDIO 10 10 bool ··· 65 65 config REGMAP_SPI_AVMM 66 66 tristate 67 67 depends on SPI 68 + 69 + config REGMAP_FSI 70 + tristate 71 + depends on FSI
+1
drivers/base/regmap/Makefile
··· 20 20 obj-$(CONFIG_REGMAP_I3C) += regmap-i3c.o 21 21 obj-$(CONFIG_REGMAP_SPI_AVMM) += regmap-spi-avmm.o 22 22 obj-$(CONFIG_REGMAP_MDIO) += regmap-mdio.o 23 + obj-$(CONFIG_REGMAP_FSI) += regmap-fsi.o
+231
drivers/base/regmap/regmap-fsi.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // 3 + // Register map access API - FSI support 4 + // 5 + // Copyright 2022 IBM Corp 6 + // 7 + // Author: Eddie James <eajames@linux.ibm.com> 8 + 9 + #include <linux/fsi.h> 10 + #include <linux/module.h> 11 + #include <linux/regmap.h> 12 + 13 + #include "internal.h" 14 + 15 + static int regmap_fsi32_reg_read(void *context, unsigned int reg, unsigned int *val) 16 + { 17 + u32 v; 18 + int ret; 19 + 20 + ret = fsi_slave_read(context, reg, &v, sizeof(v)); 21 + if (ret) 22 + return ret; 23 + 24 + *val = v; 25 + return 0; 26 + } 27 + 28 + static int regmap_fsi32_reg_write(void *context, unsigned int reg, unsigned int val) 29 + { 30 + u32 v = val; 31 + 32 + return fsi_slave_write(context, reg, &v, sizeof(v)); 33 + } 34 + 35 + static const struct regmap_bus regmap_fsi32 = { 36 + .reg_write = regmap_fsi32_reg_write, 37 + .reg_read = regmap_fsi32_reg_read, 38 + }; 39 + 40 + static int regmap_fsi32le_reg_read(void *context, unsigned int reg, unsigned int *val) 41 + { 42 + __be32 v; 43 + int ret; 44 + 45 + ret = fsi_slave_read(context, reg, &v, sizeof(v)); 46 + if (ret) 47 + return ret; 48 + 49 + *val = be32_to_cpu(v); 50 + return 0; 51 + } 52 + 53 + static int regmap_fsi32le_reg_write(void *context, unsigned int reg, unsigned int val) 54 + { 55 + __be32 v = cpu_to_be32(val); 56 + 57 + return fsi_slave_write(context, reg, &v, sizeof(v)); 58 + } 59 + 60 + static const struct regmap_bus regmap_fsi32le = { 61 + .reg_write = regmap_fsi32le_reg_write, 62 + .reg_read = regmap_fsi32le_reg_read, 63 + }; 64 + 65 + static int regmap_fsi16_reg_read(void *context, unsigned int reg, unsigned int *val) 66 + { 67 + u16 v; 68 + int ret; 69 + 70 + ret = fsi_slave_read(context, reg, &v, sizeof(v)); 71 + if (ret) 72 + return ret; 73 + 74 + *val = v; 75 + return 0; 76 + } 77 + 78 + static int regmap_fsi16_reg_write(void *context, unsigned int reg, unsigned int val) 79 + { 80 + u16 v; 81 + 82 + if (val > 0xffff) 83 + return -EINVAL; 84 + 85 + v = val; 86 + return fsi_slave_write(context, reg, &v, sizeof(v)); 87 + } 88 + 89 + static const struct regmap_bus regmap_fsi16 = { 90 + .reg_write = regmap_fsi16_reg_write, 91 + .reg_read = regmap_fsi16_reg_read, 92 + }; 93 + 94 + static int regmap_fsi16le_reg_read(void *context, unsigned int reg, unsigned int *val) 95 + { 96 + __be16 v; 97 + int ret; 98 + 99 + ret = fsi_slave_read(context, reg, &v, sizeof(v)); 100 + if (ret) 101 + return ret; 102 + 103 + *val = be16_to_cpu(v); 104 + return 0; 105 + } 106 + 107 + static int regmap_fsi16le_reg_write(void *context, unsigned int reg, unsigned int val) 108 + { 109 + __be16 v; 110 + 111 + if (val > 0xffff) 112 + return -EINVAL; 113 + 114 + v = cpu_to_be16(val); 115 + return fsi_slave_write(context, reg, &v, sizeof(v)); 116 + } 117 + 118 + static const struct regmap_bus regmap_fsi16le = { 119 + .reg_write = regmap_fsi16le_reg_write, 120 + .reg_read = regmap_fsi16le_reg_read, 121 + }; 122 + 123 + static int regmap_fsi8_reg_read(void *context, unsigned int reg, unsigned int *val) 124 + { 125 + u8 v; 126 + int ret; 127 + 128 + ret = fsi_slave_read(context, reg, &v, sizeof(v)); 129 + if (ret) 130 + return ret; 131 + 132 + *val = v; 133 + return 0; 134 + } 135 + 136 + static int regmap_fsi8_reg_write(void *context, unsigned int reg, unsigned int val) 137 + { 138 + u8 v; 139 + 140 + if (val > 0xff) 141 + return -EINVAL; 142 + 143 + v = val; 144 + return fsi_slave_write(context, reg, &v, sizeof(v)); 145 + } 146 + 147 + static const struct regmap_bus regmap_fsi8 = { 148 + .reg_write = regmap_fsi8_reg_write, 149 + .reg_read = regmap_fsi8_reg_read, 150 + }; 151 + 152 + static const struct regmap_bus *regmap_get_fsi_bus(struct fsi_device *fsi_dev, 153 + const struct regmap_config *config) 154 + { 155 + const struct regmap_bus *bus = NULL; 156 + 157 + if (config->reg_bits == 8 || config->reg_bits == 16 || config->reg_bits == 32) { 158 + switch (config->val_bits) { 159 + case 8: 160 + bus = &regmap_fsi8; 161 + break; 162 + case 16: 163 + switch (regmap_get_val_endian(&fsi_dev->dev, NULL, config)) { 164 + case REGMAP_ENDIAN_LITTLE: 165 + #ifdef __LITTLE_ENDIAN 166 + case REGMAP_ENDIAN_NATIVE: 167 + #endif 168 + bus = &regmap_fsi16le; 169 + break; 170 + case REGMAP_ENDIAN_DEFAULT: 171 + case REGMAP_ENDIAN_BIG: 172 + #ifdef __BIG_ENDIAN 173 + case REGMAP_ENDIAN_NATIVE: 174 + #endif 175 + bus = &regmap_fsi16; 176 + break; 177 + default: 178 + break; 179 + } 180 + break; 181 + case 32: 182 + switch (regmap_get_val_endian(&fsi_dev->dev, NULL, config)) { 183 + case REGMAP_ENDIAN_LITTLE: 184 + #ifdef __LITTLE_ENDIAN 185 + case REGMAP_ENDIAN_NATIVE: 186 + #endif 187 + bus = &regmap_fsi32le; 188 + break; 189 + case REGMAP_ENDIAN_DEFAULT: 190 + case REGMAP_ENDIAN_BIG: 191 + #ifdef __BIG_ENDIAN 192 + case REGMAP_ENDIAN_NATIVE: 193 + #endif 194 + bus = &regmap_fsi32; 195 + break; 196 + default: 197 + break; 198 + } 199 + break; 200 + } 201 + } 202 + 203 + return bus ?: ERR_PTR(-EOPNOTSUPP); 204 + } 205 + 206 + struct regmap *__regmap_init_fsi(struct fsi_device *fsi_dev, const struct regmap_config *config, 207 + struct lock_class_key *lock_key, const char *lock_name) 208 + { 209 + const struct regmap_bus *bus = regmap_get_fsi_bus(fsi_dev, config); 210 + 211 + if (IS_ERR(bus)) 212 + return ERR_CAST(bus); 213 + 214 + return __regmap_init(&fsi_dev->dev, bus, fsi_dev->slave, config, lock_key, lock_name); 215 + } 216 + EXPORT_SYMBOL_GPL(__regmap_init_fsi); 217 + 218 + struct regmap *__devm_regmap_init_fsi(struct fsi_device *fsi_dev, 219 + const struct regmap_config *config, 220 + struct lock_class_key *lock_key, const char *lock_name) 221 + { 222 + const struct regmap_bus *bus = regmap_get_fsi_bus(fsi_dev, config); 223 + 224 + if (IS_ERR(bus)) 225 + return ERR_CAST(bus); 226 + 227 + return __devm_regmap_init(&fsi_dev->dev, bus, fsi_dev->slave, config, lock_key, lock_name); 228 + } 229 + EXPORT_SYMBOL_GPL(__devm_regmap_init_fsi); 230 + 231 + MODULE_LICENSE("GPL");
+42 -17
drivers/base/regmap/regmap-irq.c
··· 115 115 */ 116 116 for (i = 0; i < d->chip->num_regs; i++) { 117 117 if (d->mask_base) { 118 - reg = d->get_irq_reg(d, d->mask_base, i); 119 - ret = regmap_update_bits(d->map, reg, 120 - d->mask_buf_def[i], d->mask_buf[i]); 121 - if (ret) 122 - dev_err(d->map->dev, "Failed to sync masks in %x\n", 123 - reg); 118 + if (d->chip->handle_mask_sync) 119 + d->chip->handle_mask_sync(d->map, i, 120 + d->mask_buf_def[i], 121 + d->mask_buf[i], 122 + d->chip->irq_drv_data); 123 + else { 124 + reg = d->get_irq_reg(d, d->mask_base, i); 125 + ret = regmap_update_bits(d->map, reg, 126 + d->mask_buf_def[i], 127 + d->mask_buf[i]); 128 + if (ret) 129 + dev_err(d->map->dev, "Failed to sync masks in %x\n", 130 + reg); 131 + } 124 132 } 125 133 126 134 if (d->unmask_base) { ··· 730 722 int i; 731 723 int ret = -ENOMEM; 732 724 int num_type_reg; 725 + int num_regs; 733 726 u32 reg; 734 727 735 728 if (chip->num_regs <= 0) ··· 805 796 goto err_alloc; 806 797 } 807 798 808 - num_type_reg = chip->type_in_mask ? chip->num_regs : chip->num_type_reg; 809 - if (num_type_reg) { 810 - d->type_buf_def = kcalloc(num_type_reg, 799 + /* 800 + * Use num_config_regs if defined, otherwise fall back to num_type_reg 801 + * to maintain backward compatibility. 802 + */ 803 + num_type_reg = chip->num_config_regs ? chip->num_config_regs 804 + : chip->num_type_reg; 805 + num_regs = chip->type_in_mask ? chip->num_regs : num_type_reg; 806 + if (num_regs) { 807 + d->type_buf_def = kcalloc(num_regs, 811 808 sizeof(*d->type_buf_def), GFP_KERNEL); 812 809 if (!d->type_buf_def) 813 810 goto err_alloc; 814 811 815 - d->type_buf = kcalloc(num_type_reg, sizeof(*d->type_buf), 812 + d->type_buf = kcalloc(num_regs, sizeof(*d->type_buf), 816 813 GFP_KERNEL); 817 814 if (!d->type_buf) 818 815 goto err_alloc; ··· 932 917 d->mask_buf[i] = d->mask_buf_def[i]; 933 918 934 919 if (d->mask_base) { 935 - reg = d->get_irq_reg(d, d->mask_base, i); 936 - ret = regmap_update_bits(d->map, reg, 937 - d->mask_buf_def[i], d->mask_buf[i]); 938 - if (ret) { 939 - dev_err(map->dev, "Failed to set masks in 0x%x: %d\n", 940 - reg, ret); 941 - goto err_alloc; 920 + if (chip->handle_mask_sync) { 921 + ret = chip->handle_mask_sync(d->map, i, 922 + d->mask_buf_def[i], 923 + d->mask_buf[i], 924 + chip->irq_drv_data); 925 + if (ret) 926 + goto err_alloc; 927 + } else { 928 + reg = d->get_irq_reg(d, d->mask_base, i); 929 + ret = regmap_update_bits(d->map, reg, 930 + d->mask_buf_def[i], 931 + d->mask_buf[i]); 932 + if (ret) { 933 + dev_err(map->dev, "Failed to set masks in 0x%x: %d\n", 934 + reg, ret); 935 + goto err_alloc; 936 + } 942 937 } 943 938 } 944 939
+13
drivers/base/regmap/regmap.c
··· 3486 3486 } 3487 3487 EXPORT_SYMBOL_GPL(regmap_get_reg_stride); 3488 3488 3489 + /** 3490 + * regmap_might_sleep() - Returns whether a regmap access might sleep. 3491 + * 3492 + * @map: Register map to operate on. 3493 + * 3494 + * Returns true if an access to the register might sleep, else false. 3495 + */ 3496 + bool regmap_might_sleep(struct regmap *map) 3497 + { 3498 + return map->can_sleep; 3499 + } 3500 + EXPORT_SYMBOL_GPL(regmap_might_sleep); 3501 + 3489 3502 int regmap_parse_val(struct regmap *map, const void *buf, 3490 3503 unsigned int *val) 3491 3504 {
+49
include/linux/regmap.h
··· 24 24 struct clk; 25 25 struct device; 26 26 struct device_node; 27 + struct fsi_device; 27 28 struct i2c_client; 28 29 struct i3c_device; 29 30 struct irq_domain; ··· 629 628 const struct regmap_config *config, 630 629 struct lock_class_key *lock_key, 631 630 const char *lock_name); 631 + struct regmap *__regmap_init_fsi(struct fsi_device *fsi_dev, 632 + const struct regmap_config *config, 633 + struct lock_class_key *lock_key, 634 + const char *lock_name); 632 635 633 636 struct regmap *__devm_regmap_init(struct device *dev, 634 637 const struct regmap_bus *bus, ··· 698 693 const struct regmap_config *config, 699 694 struct lock_class_key *lock_key, 700 695 const char *lock_name); 696 + struct regmap *__devm_regmap_init_fsi(struct fsi_device *fsi_dev, 697 + const struct regmap_config *config, 698 + struct lock_class_key *lock_key, 699 + const char *lock_name); 700 + 701 701 /* 702 702 * Wrapper for regmap_init macros to include a unique lockdep key and name 703 703 * for each call. No-op if CONFIG_LOCKDEP is not set. ··· 928 918 #define regmap_init_spi_avmm(spi, config) \ 929 919 __regmap_lockdep_wrapper(__regmap_init_spi_avmm, #config, \ 930 920 spi, config) 921 + 922 + /** 923 + * regmap_init_fsi() - Initialise register map 924 + * 925 + * @fsi_dev: Device that will be interacted with 926 + * @config: Configuration for register map 927 + * 928 + * The return value will be an ERR_PTR() on error or a valid pointer to 929 + * a struct regmap. 930 + */ 931 + #define regmap_init_fsi(fsi_dev, config) \ 932 + __regmap_lockdep_wrapper(__regmap_init_fsi, #config, fsi_dev, \ 933 + config) 931 934 932 935 /** 933 936 * devm_regmap_init() - Initialise managed register map ··· 1171 1148 __regmap_lockdep_wrapper(__devm_regmap_init_spi_avmm, #config, \ 1172 1149 spi, config) 1173 1150 1151 + /** 1152 + * devm_regmap_init_fsi() - Initialise managed register map 1153 + * 1154 + * @fsi_dev: Device that will be interacted with 1155 + * @config: Configuration for register map 1156 + * 1157 + * The return value will be an ERR_PTR() on error or a valid pointer 1158 + * to a struct regmap. The regmap will be automatically freed by the 1159 + * device management code. 1160 + */ 1161 + #define devm_regmap_init_fsi(fsi_dev, config) \ 1162 + __regmap_lockdep_wrapper(__devm_regmap_init_fsi, #config, \ 1163 + fsi_dev, config) 1164 + 1174 1165 int regmap_mmio_attach_clk(struct regmap *map, struct clk *clk); 1175 1166 void regmap_mmio_detach_clk(struct regmap *map); 1176 1167 void regmap_exit(struct regmap *map); ··· 1256 1219 int regmap_get_val_bytes(struct regmap *map); 1257 1220 int regmap_get_max_register(struct regmap *map); 1258 1221 int regmap_get_reg_stride(struct regmap *map); 1222 + bool regmap_might_sleep(struct regmap *map); 1259 1223 int regmap_async_complete(struct regmap *map); 1260 1224 bool regmap_can_raw_write(struct regmap *map); 1261 1225 size_t regmap_get_raw_read_max(struct regmap *map); ··· 1580 1542 * before regmap_irq_handler process the interrupts. 1581 1543 * @handle_post_irq: Driver specific callback to handle interrupt from device 1582 1544 * after handling the interrupts in regmap_irq_handler(). 1545 + * @handle_mask_sync: Callback used to handle IRQ mask syncs. The index will be 1546 + * in the range [0, num_regs) 1583 1547 * @set_type_virt: Driver specific callback to extend regmap_irq_set_type() 1584 1548 * and configure virt regs. Deprecated, use @set_type_config 1585 1549 * callback and config registers instead. ··· 1643 1603 1644 1604 int (*handle_pre_irq)(void *irq_drv_data); 1645 1605 int (*handle_post_irq)(void *irq_drv_data); 1606 + int (*handle_mask_sync)(struct regmap *map, int index, 1607 + unsigned int mask_buf_def, 1608 + unsigned int mask_buf, void *irq_drv_data); 1646 1609 int (*set_type_virt)(unsigned int **buf, unsigned int type, 1647 1610 unsigned long hwirq, int reg); 1648 1611 int (*set_type_config)(unsigned int **buf, unsigned int type, ··· 1946 1903 { 1947 1904 WARN_ONCE(1, "regmap API is disabled"); 1948 1905 return -EINVAL; 1906 + } 1907 + 1908 + static inline bool regmap_might_sleep(struct regmap *map) 1909 + { 1910 + WARN_ONCE(1, "regmap API is disabled"); 1911 + return true; 1949 1912 } 1950 1913 1951 1914 static inline int regcache_sync(struct regmap *map)