| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272 |
- // SPDX-License-Identifier: GPL-2.0
- /*
- * Analog Devices AD7091R8 12-bit SAR ADC driver
- *
- * Copyright 2023 Analog Devices Inc.
- */
- #include <linux/bitfield.h>
- #include <linux/iio/iio.h>
- #include <linux/module.h>
- #include <linux/regmap.h>
- #include <linux/gpio/consumer.h>
- #include <linux/spi/spi.h>
- #include "ad7091r-base.h"
- #define AD7091R8_REG_ADDR_MSK GENMASK(15, 11)
- #define AD7091R8_RD_WR_FLAG_MSK BIT(10)
- #define AD7091R8_REG_DATA_MSK GENMASK(9, 0)
- #define AD7091R_SPI_REGMAP_CONFIG(n) { \
- .reg_bits = 8, \
- .val_bits = 16, \
- .volatile_reg = ad7091r_volatile_reg, \
- .writeable_reg = ad7091r_writeable_reg, \
- .max_register = AD7091R_REG_CH_HYSTERESIS(n), \
- }
- static int ad7091r8_set_mode(struct ad7091r_state *st, enum ad7091r_mode mode)
- {
- /* AD7091R-2/-4/-8 don't set sample/command/autocycle mode in conf reg */
- st->mode = mode;
- return 0;
- }
- static unsigned int ad7091r8_reg_result_chan_id(unsigned int val)
- {
- return AD7091R8_REG_RESULT_CH_ID(val);
- }
- #define AD7091R_SPI_CHIP_INFO(_n, _name) { \
- .name = _name, \
- .channels = ad7091r##_n##_channels, \
- .num_channels = ARRAY_SIZE(ad7091r##_n##_channels), \
- .vref_mV = 2500, \
- .reg_result_chan_id = &ad7091r8_reg_result_chan_id, \
- .set_mode = &ad7091r8_set_mode, \
- }
- #define AD7091R_SPI_CHIP_INFO_IRQ(_n, _name) { \
- .name = _name, \
- .channels = ad7091r##_n##_channels_irq, \
- .num_channels = ARRAY_SIZE(ad7091r##_n##_channels_irq), \
- .vref_mV = 2500, \
- .reg_result_chan_id = &ad7091r8_reg_result_chan_id, \
- .set_mode = &ad7091r8_set_mode, \
- }
- enum ad7091r8_info_ids {
- AD7091R2_INFO,
- AD7091R4_INFO,
- AD7091R4_INFO_IRQ,
- AD7091R8_INFO,
- AD7091R8_INFO_IRQ,
- };
- static const struct iio_chan_spec ad7091r2_channels[] = {
- AD7091R_CHANNEL(0, 12, NULL, 0),
- AD7091R_CHANNEL(1, 12, NULL, 0),
- };
- static const struct iio_chan_spec ad7091r4_channels[] = {
- AD7091R_CHANNEL(0, 12, NULL, 0),
- AD7091R_CHANNEL(1, 12, NULL, 0),
- AD7091R_CHANNEL(2, 12, NULL, 0),
- AD7091R_CHANNEL(3, 12, NULL, 0),
- };
- static const struct iio_chan_spec ad7091r4_channels_irq[] = {
- AD7091R_CHANNEL(0, 12, ad7091r_events, ARRAY_SIZE(ad7091r_events)),
- AD7091R_CHANNEL(1, 12, ad7091r_events, ARRAY_SIZE(ad7091r_events)),
- AD7091R_CHANNEL(2, 12, ad7091r_events, ARRAY_SIZE(ad7091r_events)),
- AD7091R_CHANNEL(3, 12, ad7091r_events, ARRAY_SIZE(ad7091r_events)),
- };
- static const struct iio_chan_spec ad7091r8_channels[] = {
- AD7091R_CHANNEL(0, 12, NULL, 0),
- AD7091R_CHANNEL(1, 12, NULL, 0),
- AD7091R_CHANNEL(2, 12, NULL, 0),
- AD7091R_CHANNEL(3, 12, NULL, 0),
- AD7091R_CHANNEL(4, 12, NULL, 0),
- AD7091R_CHANNEL(5, 12, NULL, 0),
- AD7091R_CHANNEL(6, 12, NULL, 0),
- AD7091R_CHANNEL(7, 12, NULL, 0),
- };
- static const struct iio_chan_spec ad7091r8_channels_irq[] = {
- AD7091R_CHANNEL(0, 12, ad7091r_events, ARRAY_SIZE(ad7091r_events)),
- AD7091R_CHANNEL(1, 12, ad7091r_events, ARRAY_SIZE(ad7091r_events)),
- AD7091R_CHANNEL(2, 12, ad7091r_events, ARRAY_SIZE(ad7091r_events)),
- AD7091R_CHANNEL(3, 12, ad7091r_events, ARRAY_SIZE(ad7091r_events)),
- AD7091R_CHANNEL(4, 12, ad7091r_events, ARRAY_SIZE(ad7091r_events)),
- AD7091R_CHANNEL(5, 12, ad7091r_events, ARRAY_SIZE(ad7091r_events)),
- AD7091R_CHANNEL(6, 12, ad7091r_events, ARRAY_SIZE(ad7091r_events)),
- AD7091R_CHANNEL(7, 12, ad7091r_events, ARRAY_SIZE(ad7091r_events)),
- };
- static void ad7091r_pulse_convst(struct ad7091r_state *st)
- {
- gpiod_set_value_cansleep(st->convst_gpio, 1);
- gpiod_set_value_cansleep(st->convst_gpio, 0);
- }
- static int ad7091r_regmap_bus_reg_read(void *context, unsigned int reg,
- unsigned int *val)
- {
- struct ad7091r_state *st = context;
- struct spi_device *spi = container_of(st->dev, struct spi_device, dev);
- int ret;
- struct spi_transfer t[] = {
- {
- .tx_buf = &st->tx_buf,
- .len = 2,
- .cs_change = 1,
- }, {
- .rx_buf = &st->rx_buf,
- .len = 2,
- }
- };
- if (reg == AD7091R_REG_RESULT)
- ad7091r_pulse_convst(st);
- st->tx_buf = cpu_to_be16(reg << 11);
- ret = spi_sync_transfer(spi, t, ARRAY_SIZE(t));
- if (ret < 0)
- return ret;
- *val = be16_to_cpu(st->rx_buf);
- return 0;
- }
- static int ad7091r_regmap_bus_reg_write(void *context, unsigned int reg,
- unsigned int val)
- {
- struct ad7091r_state *st = context;
- struct spi_device *spi = container_of(st->dev, struct spi_device, dev);
- /*
- * AD7091R-2/-4/-8 protocol (datasheet page 31) is to do a single SPI
- * transfer with reg address set in bits B15:B11 and value set in B9:B0.
- */
- st->tx_buf = cpu_to_be16(FIELD_PREP(AD7091R8_REG_DATA_MSK, val) |
- FIELD_PREP(AD7091R8_RD_WR_FLAG_MSK, 1) |
- FIELD_PREP(AD7091R8_REG_ADDR_MSK, reg));
- return spi_write(spi, &st->tx_buf, 2);
- }
- static const struct regmap_bus ad7091r8_regmap_bus = {
- .reg_read = ad7091r_regmap_bus_reg_read,
- .reg_write = ad7091r_regmap_bus_reg_write,
- .reg_format_endian_default = REGMAP_ENDIAN_BIG,
- .val_format_endian_default = REGMAP_ENDIAN_BIG,
- };
- static const struct ad7091r_chip_info ad7091r8_infos[] = {
- [AD7091R2_INFO] = AD7091R_SPI_CHIP_INFO(2, "ad7091r-2"),
- [AD7091R4_INFO] = AD7091R_SPI_CHIP_INFO(4, "ad7091r-4"),
- [AD7091R4_INFO_IRQ] = AD7091R_SPI_CHIP_INFO_IRQ(4, "ad7091r-4"),
- [AD7091R8_INFO] = AD7091R_SPI_CHIP_INFO(8, "ad7091r-8"),
- [AD7091R8_INFO_IRQ] = AD7091R_SPI_CHIP_INFO_IRQ(8, "ad7091r-8")
- };
- static const struct regmap_config ad7091r2_reg_conf = AD7091R_SPI_REGMAP_CONFIG(2);
- static const struct regmap_config ad7091r4_reg_conf = AD7091R_SPI_REGMAP_CONFIG(4);
- static const struct regmap_config ad7091r8_reg_conf = AD7091R_SPI_REGMAP_CONFIG(8);
- static void ad7091r8_regmap_init(struct ad7091r_state *st,
- const struct regmap_config *regmap_conf)
- {
- st->map = devm_regmap_init(st->dev, &ad7091r8_regmap_bus, st,
- regmap_conf);
- }
- static int ad7091r8_gpio_setup(struct ad7091r_state *st)
- {
- st->convst_gpio = devm_gpiod_get(st->dev, "convst", GPIOD_OUT_LOW);
- if (IS_ERR(st->convst_gpio))
- return dev_err_probe(st->dev, PTR_ERR(st->convst_gpio),
- "Error getting convst GPIO\n");
- st->reset_gpio = devm_gpiod_get_optional(st->dev, "reset",
- GPIOD_OUT_HIGH);
- if (IS_ERR(st->reset_gpio))
- return dev_err_probe(st->dev, PTR_ERR(st->reset_gpio),
- "Error on requesting reset GPIO\n");
- if (st->reset_gpio) {
- fsleep(20);
- gpiod_set_value_cansleep(st->reset_gpio, 0);
- }
- return 0;
- }
- static struct ad7091r_init_info ad7091r2_init_info = {
- .info_no_irq = &ad7091r8_infos[AD7091R2_INFO],
- .regmap_config = &ad7091r2_reg_conf,
- .init_adc_regmap = &ad7091r8_regmap_init,
- .setup = &ad7091r8_gpio_setup
- };
- static struct ad7091r_init_info ad7091r4_init_info = {
- .info_no_irq = &ad7091r8_infos[AD7091R4_INFO],
- .info_irq = &ad7091r8_infos[AD7091R4_INFO_IRQ],
- .regmap_config = &ad7091r4_reg_conf,
- .init_adc_regmap = &ad7091r8_regmap_init,
- .setup = &ad7091r8_gpio_setup
- };
- static struct ad7091r_init_info ad7091r8_init_info = {
- .info_no_irq = &ad7091r8_infos[AD7091R8_INFO],
- .info_irq = &ad7091r8_infos[AD7091R8_INFO_IRQ],
- .regmap_config = &ad7091r8_reg_conf,
- .init_adc_regmap = &ad7091r8_regmap_init,
- .setup = &ad7091r8_gpio_setup
- };
- static int ad7091r8_spi_probe(struct spi_device *spi)
- {
- const struct ad7091r_init_info *init_info;
- init_info = spi_get_device_match_data(spi);
- if (!init_info)
- return -EINVAL;
- return ad7091r_probe(&spi->dev, init_info, spi->irq);
- }
- static const struct of_device_id ad7091r8_of_match[] = {
- { .compatible = "adi,ad7091r2", .data = &ad7091r2_init_info },
- { .compatible = "adi,ad7091r4", .data = &ad7091r4_init_info },
- { .compatible = "adi,ad7091r8", .data = &ad7091r8_init_info },
- { }
- };
- MODULE_DEVICE_TABLE(of, ad7091r8_of_match);
- static const struct spi_device_id ad7091r8_spi_id[] = {
- { "ad7091r2", (kernel_ulong_t)&ad7091r2_init_info },
- { "ad7091r4", (kernel_ulong_t)&ad7091r4_init_info },
- { "ad7091r8", (kernel_ulong_t)&ad7091r8_init_info },
- { }
- };
- MODULE_DEVICE_TABLE(spi, ad7091r8_spi_id);
- static struct spi_driver ad7091r8_driver = {
- .driver = {
- .name = "ad7091r8",
- .of_match_table = ad7091r8_of_match,
- },
- .probe = ad7091r8_spi_probe,
- .id_table = ad7091r8_spi_id,
- };
- module_spi_driver(ad7091r8_driver);
- MODULE_AUTHOR("Marcelo Schmitt <marcelo.schmitt@analog.com>");
- MODULE_DESCRIPTION("Analog Devices AD7091R8 ADC driver");
- MODULE_LICENSE("GPL");
- MODULE_IMPORT_NS(IIO_AD7091R);
|