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.

iio: adc: ad4695: add 2nd regmap for 16-bit registers

The AD4695 and similar chips have some multibyte registers that have
to be read/written in a single operation. So we need to add a 2nd regmap
for these registers.

These registers are removed from the 8-bit regmap allowable ranges and
AD4695_MAX_REG is dropped since it would be ambiguous now.

debugfs register access is also updated to automatically use the correct
regmap depending on the register address.

Signed-off-by: David Lechner <dlechner@baylibre.com>
Link: https://patch.msgid.link/20240820-ad4695-gain-offset-v1-1-c8f6e3b47551@baylibre.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

David Lechner and committed by
Jonathan Cameron
2ba49fc4 16531118

+68 -15
+68 -15
drivers/iio/adc/ad4695.c
··· 34 34 /* AD4695 registers */ 35 35 #define AD4695_REG_SPI_CONFIG_A 0x0000 36 36 #define AD4695_REG_SPI_CONFIG_A_SW_RST (BIT(7) | BIT(0)) 37 + #define AD4695_REG_SPI_CONFIG_A_ADDR_DIR BIT(5) 37 38 #define AD4695_REG_SPI_CONFIG_B 0x0001 38 39 #define AD4695_REG_SPI_CONFIG_B_INST_MODE BIT(7) 39 40 #define AD4695_REG_DEVICE_TYPE 0x0003 ··· 78 77 #define AD4695_REG_GAIN_IN(n) (0x00C0 | (2 * (n))) 79 78 #define AD4695_REG_AS_SLOT(n) (0x0100 | (n)) 80 79 #define AD4695_REG_AS_SLOT_INX GENMASK(3, 0) 81 - #define AD4695_MAX_REG 0x017F 82 80 83 81 /* Conversion mode commands */ 84 82 #define AD4695_CMD_EXIT_CNV_MODE 0x0A ··· 121 121 struct ad4695_state { 122 122 struct spi_device *spi; 123 123 struct regmap *regmap; 124 + struct regmap *regmap16; 124 125 struct gpio_desc *reset_gpio; 125 126 /* voltages channels plus temperature and timestamp */ 126 127 struct iio_chan_spec iio_chan[AD4695_MAX_CHANNELS + 2]; ··· 151 150 regmap_reg_range(AD4695_REG_SPI_CONFIG_C, AD4695_REG_SPI_STATUS), 152 151 regmap_reg_range(AD4695_REG_STATUS, AD4695_REG_ALERT_STATUS2), 153 152 regmap_reg_range(AD4695_REG_CLAMP_STATUS, AD4695_REG_CLAMP_STATUS), 154 - regmap_reg_range(AD4695_REG_SETUP, AD4695_REG_TEMP_CTRL), 155 - regmap_reg_range(AD4695_REG_CONFIG_IN(0), AD4695_MAX_REG), 153 + regmap_reg_range(AD4695_REG_SETUP, AD4695_REG_AC_CTRL), 154 + regmap_reg_range(AD4695_REG_GPIO_CTRL, AD4695_REG_TEMP_CTRL), 155 + regmap_reg_range(AD4695_REG_CONFIG_IN(0), AD4695_REG_CONFIG_IN(15)), 156 + regmap_reg_range(AD4695_REG_AS_SLOT(0), AD4695_REG_AS_SLOT(127)), 156 157 }; 157 158 158 159 static const struct regmap_access_table ad4695_regmap_rd_table = { ··· 167 164 regmap_reg_range(AD4695_REG_SCRATCH_PAD, AD4695_REG_SCRATCH_PAD), 168 165 regmap_reg_range(AD4695_REG_LOOP_MODE, AD4695_REG_LOOP_MODE), 169 166 regmap_reg_range(AD4695_REG_SPI_CONFIG_C, AD4695_REG_SPI_STATUS), 170 - regmap_reg_range(AD4695_REG_SETUP, AD4695_REG_TEMP_CTRL), 171 - regmap_reg_range(AD4695_REG_CONFIG_IN(0), AD4695_MAX_REG), 167 + regmap_reg_range(AD4695_REG_SETUP, AD4695_REG_AC_CTRL), 168 + regmap_reg_range(AD4695_REG_GPIO_CTRL, AD4695_REG_TEMP_CTRL), 169 + regmap_reg_range(AD4695_REG_CONFIG_IN(0), AD4695_REG_CONFIG_IN(15)), 170 + regmap_reg_range(AD4695_REG_AS_SLOT(0), AD4695_REG_AS_SLOT(127)), 172 171 }; 173 172 174 173 static const struct regmap_access_table ad4695_regmap_wr_table = { ··· 179 174 }; 180 175 181 176 static const struct regmap_config ad4695_regmap_config = { 182 - .name = "ad4695", 177 + .name = "ad4695-8", 183 178 .reg_bits = 16, 184 179 .val_bits = 8, 185 - .max_register = AD4695_MAX_REG, 180 + .max_register = AD4695_REG_AS_SLOT(127), 186 181 .rd_table = &ad4695_regmap_rd_table, 187 182 .wr_table = &ad4695_regmap_wr_table, 183 + .can_multi_write = true, 184 + }; 185 + 186 + static const struct regmap_range ad4695_regmap16_rd_ranges[] = { 187 + regmap_reg_range(AD4695_REG_STD_SEQ_CONFIG, AD4695_REG_STD_SEQ_CONFIG), 188 + regmap_reg_range(AD4695_REG_UPPER_IN(0), AD4695_REG_GAIN_IN(15)), 189 + }; 190 + 191 + static const struct regmap_access_table ad4695_regmap16_rd_table = { 192 + .yes_ranges = ad4695_regmap16_rd_ranges, 193 + .n_yes_ranges = ARRAY_SIZE(ad4695_regmap16_rd_ranges), 194 + }; 195 + 196 + static const struct regmap_range ad4695_regmap16_wr_ranges[] = { 197 + regmap_reg_range(AD4695_REG_STD_SEQ_CONFIG, AD4695_REG_STD_SEQ_CONFIG), 198 + regmap_reg_range(AD4695_REG_UPPER_IN(0), AD4695_REG_GAIN_IN(15)), 199 + }; 200 + 201 + static const struct regmap_access_table ad4695_regmap16_wr_table = { 202 + .yes_ranges = ad4695_regmap16_wr_ranges, 203 + .n_yes_ranges = ARRAY_SIZE(ad4695_regmap16_wr_ranges), 204 + }; 205 + 206 + static const struct regmap_config ad4695_regmap16_config = { 207 + .name = "ad4695-16", 208 + .reg_bits = 16, 209 + .reg_stride = 2, 210 + .val_bits = 16, 211 + .val_format_endian = REGMAP_ENDIAN_LITTLE, 212 + .max_register = AD4695_REG_GAIN_IN(15), 213 + .rd_table = &ad4695_regmap16_rd_table, 214 + .wr_table = &ad4695_regmap16_wr_table, 188 215 .can_multi_write = true, 189 216 }; 190 217 ··· 683 646 struct ad4695_state *st = iio_priv(indio_dev); 684 647 685 648 iio_device_claim_direct_scoped(return -EBUSY, indio_dev) { 686 - if (readval) 687 - return regmap_read(st->regmap, reg, readval); 688 - 689 - return regmap_write(st->regmap, reg, writeval); 649 + if (readval) { 650 + if (regmap_check_range_table(st->regmap, reg, 651 + &ad4695_regmap_rd_table)) 652 + return regmap_read(st->regmap, reg, readval); 653 + if (regmap_check_range_table(st->regmap16, reg, 654 + &ad4695_regmap16_rd_table)) 655 + return regmap_read(st->regmap16, reg, readval); 656 + } else { 657 + if (regmap_check_range_table(st->regmap, reg, 658 + &ad4695_regmap_wr_table)) 659 + return regmap_write(st->regmap, reg, writeval); 660 + if (regmap_check_range_table(st->regmap16, reg, 661 + &ad4695_regmap16_wr_table)) 662 + return regmap_write(st->regmap16, reg, writeval); 663 + } 690 664 } 691 665 692 - unreachable(); 666 + return -EINVAL; 693 667 } 694 668 695 669 static const struct iio_info ad4695_info = { ··· 855 807 return dev_err_probe(dev, PTR_ERR(st->regmap), 856 808 "Failed to initialize regmap\n"); 857 809 810 + st->regmap16 = devm_regmap_init_spi(spi, &ad4695_regmap16_config); 811 + if (IS_ERR(st->regmap16)) 812 + return dev_err_probe(dev, PTR_ERR(st->regmap16), 813 + "Failed to initialize regmap16\n"); 814 + 858 815 ret = devm_regulator_bulk_get_enable(dev, 859 816 ARRAY_SIZE(ad4695_power_supplies), 860 817 ad4695_power_supplies); ··· 929 876 msleep(AD4695_T_WAKEUP_SW_MS); 930 877 } 931 878 932 - /* Needed for debugfs since it only access registers 1 byte at a time. */ 933 - ret = regmap_set_bits(st->regmap, AD4695_REG_SPI_CONFIG_C, 934 - AD4695_REG_SPI_CONFIG_C_MB_STRICT); 879 + /* Needed for regmap16 to be able to work correctly. */ 880 + ret = regmap_set_bits(st->regmap, AD4695_REG_SPI_CONFIG_A, 881 + AD4695_REG_SPI_CONFIG_A_ADDR_DIR); 935 882 if (ret) 936 883 return ret; 937 884