diff options
Diffstat (limited to 'drivers/iio/adc/ad7606.h')
| -rw-r--r-- | drivers/iio/adc/ad7606.h | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/drivers/iio/adc/ad7606.h b/drivers/iio/adc/ad7606.h new file mode 100644 index 000000000000..2951bb731354 --- /dev/null +++ b/drivers/iio/adc/ad7606.h @@ -0,0 +1,251 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * AD7606 ADC driver + * + * Copyright 2011 Analog Devices Inc. + */ + +#ifndef IIO_ADC_AD7606_H_ +#define IIO_ADC_AD7606_H_ + +#define AD760X_MAX_CHANNELS 16 + +#define AD7616_CONFIGURATION_REGISTER 0x02 +#define AD7616_OS_MASK GENMASK(4, 2) +#define AD7616_BURST_MODE BIT(6) +#define AD7616_SEQEN_MODE BIT(5) +#define AD7616_RANGE_CH_A_ADDR_OFF 0x04 +#define AD7616_RANGE_CH_B_ADDR_OFF 0x06 +/* + * Range of channels from a group are stored in 2 registers. + * 0, 1, 2, 3 in a register followed by 4, 5, 6, 7 in second register. + * For channels from second group(8-15) the order is the same, only with + * an offset of 2 for register address. + */ +#define AD7616_RANGE_CH_ADDR(ch) ((ch) >> 2) +/* The range of the channel is stored in 2 bits */ +#define AD7616_RANGE_CH_MSK(ch) (0b11 << (((ch) & 0b11) * 2)) +#define AD7616_RANGE_CH_MODE(ch, mode) ((mode) << ((((ch) & 0b11)) * 2)) + +#define AD7606_CONFIGURATION_REGISTER 0x02 +#define AD7606_SINGLE_DOUT 0x00 + +/* + * Range for AD7606B channels are stored in registers starting with address 0x3. + * Each register stores range for 2 channels(4 bits per channel). + */ +#define AD7606_RANGE_CH_MSK(ch) (GENMASK(3, 0) << (4 * ((ch) & 0x1))) +#define AD7606_RANGE_CH_MODE(ch, mode) \ + ((GENMASK(3, 0) & (mode)) << (4 * ((ch) & 0x1))) +#define AD7606_RANGE_CH_ADDR(ch) (0x03 + ((ch) >> 1)) +#define AD7606_OS_MODE 0x08 + +#define AD7606_CALIB_GAIN(ch) (0x09 + (ch)) +#define AD7606_CALIB_GAIN_MASK GENMASK(5, 0) +#define AD7606_CALIB_OFFSET(ch) (0x11 + (ch)) +#define AD7606_CALIB_PHASE(ch) (0x19 + (ch)) + +struct ad7606_state; + +typedef int (*ad7606_scale_setup_cb_t)(struct iio_dev *indio_dev, + struct iio_chan_spec *chan); +typedef int (*ad7606_sw_setup_cb_t)(struct iio_dev *indio_dev); + +/** + * struct ad7606_chip_info - chip specific information + * @max_samplerate: maximum supported sample rate + * @name: device name + * @bits: data width in bits + * @num_adc_channels: the number of physical voltage inputs + * @scale_setup_cb: callback to setup the scales for each channel + * @sw_setup_cb: callback to setup the software mode if available. + * @oversampling_avail: pointer to the array which stores the available + * oversampling ratios. + * @oversampling_num: number of elements stored in oversampling_avail array + * @os_req_reset: some devices require a reset to update oversampling + * @init_delay_ms: required delay in milliseconds for initialization + * after a restart + * @offload_storagebits: storage bits used by the offload hw implementation + * @calib_gain_avail: chip supports gain calibration + * @calib_offset_avail: pointer to offset calibration range/limits array + * @calib_phase_avail: pointer to phase calibration range/limits array + */ +struct ad7606_chip_info { + unsigned int max_samplerate; + const char *name; + unsigned int bits; + unsigned int num_adc_channels; + ad7606_scale_setup_cb_t scale_setup_cb; + ad7606_sw_setup_cb_t sw_setup_cb; + const unsigned int *oversampling_avail; + unsigned int oversampling_num; + bool os_req_reset; + unsigned long init_delay_ms; + u8 offload_storagebits; + bool calib_gain_avail; + const int *calib_offset_avail; + const int (*calib_phase_avail)[2]; +}; + +/** + * struct ad7606_chan_info - channel configuration + * @scale_avail: pointer to the array which stores the available scales + * @num_scales: number of elements stored in the scale_avail array + * @range: voltage range selection, selects which scale to apply + * @reg_offset: offset for the register value, to be applied when + * writing the value of 'range' to the register value + * @r_gain: gain resistor value in ohms, to be set to match the + * external r_filter value + */ +struct ad7606_chan_info { +#define AD760X_MAX_SCALES 16 + const unsigned int (*scale_avail)[2]; + unsigned int num_scales; + unsigned int range; + unsigned int reg_offset; + unsigned int r_gain; +}; + +/** + * struct ad7606_state - driver instance specific data + * @dev: pointer to kernel device + * @chip_info: entry in the table of chips that describes this device + * @bops: bus operations (SPI or parallel) + * @chan_info: scale configuration for channels + * @oversampling: oversampling selection + * @cnvst_pwm: pointer to the PWM device connected to the cnvst pin + * @base_address: address from where to read data in parallel operation + * @sw_mode_en: software mode enabled + * @oversampling_avail: pointer to the array which stores the available + * oversampling ratios. + * @num_os_ratios: number of elements stored in oversampling_avail array + * @back: pointer to the iio_backend structure, if used + * @write_scale: pointer to the function which writes the scale + * @write_os: pointer to the function which writes the os + * @lock: protect sensor state from concurrent accesses to GPIOs + * @gpio_convst: GPIO descriptor for conversion start signal (CONVST) + * @gpio_reset: GPIO descriptor for device hard-reset + * @gpio_range: GPIO descriptor for range selection + * @gpio_standby: GPIO descriptor for stand-by signal (STBY), + * controls power-down mode of device + * @gpio_frstdata: GPIO descriptor for reading from device when data + * is being read on the first channel + * @gpio_os: GPIO descriptors to control oversampling on the device + * @trig: The IIO trigger associated with the device. + * @completion: completion to indicate end of conversion + * @data: buffer for reading data from the device + * @offload_en: SPI offload enabled + * @bus_data: bus-specific variables + * @d16: be16 buffer for reading data from the device + */ +struct ad7606_state { + struct device *dev; + const struct ad7606_chip_info *chip_info; + const struct ad7606_bus_ops *bops; + struct ad7606_chan_info chan_info[AD760X_MAX_CHANNELS]; + unsigned int oversampling; + struct pwm_device *cnvst_pwm; + void __iomem *base_address; + bool sw_mode_en; + const unsigned int *oversampling_avail; + unsigned int num_os_ratios; + struct iio_backend *back; + int (*write_scale)(struct iio_dev *indio_dev, int ch, int val); + int (*write_os)(struct iio_dev *indio_dev, int val); + + struct mutex lock; /* protect sensor state */ + struct gpio_desc *gpio_convst; + struct gpio_desc *gpio_reset; + struct gpio_desc *gpio_range; + struct gpio_desc *gpio_standby; + struct gpio_desc *gpio_frstdata; + struct gpio_descs *gpio_os; + struct iio_trigger *trig; + struct completion completion; + + bool offload_en; + void *bus_data; + + /* + * DMA (thus cache coherency maintenance) may require the + * transfer buffers to live in their own cache lines. + * 16 * 16-bit samples for AD7616 + * 8 * 32-bit samples for AD7616C-18 (and similar) + */ + struct { + union { + u16 buf16[16]; + u32 buf32[8]; + }; + aligned_s64 timestamp; + } data __aligned(IIO_DMA_MINALIGN); + __be16 d16[2]; +}; + +/** + * struct ad7606_bus_ops - driver bus operations + * @iio_backend_config: function pointer for configuring the iio_backend for + * the compatibles that use it + * @read_block: function pointer for reading blocks of data + * @sw_mode_config: pointer to a function which configured the device + * for software mode + * @offload_config: function pointer for configuring offload support, + * where any + * @reg_read: function pointer for reading spi register + * @reg_write: function pointer for writing spi register + * @update_scan_mode: function pointer for handling the calls to iio_info's + * update_scan mode when enabling/disabling channels. + * @rd_wr_cmd: pointer to the function which calculates the spi address + */ +struct ad7606_bus_ops { + /* more methods added in future? */ + int (*iio_backend_config)(struct device *dev, struct iio_dev *indio_dev); + int (*offload_config)(struct device *dev, struct iio_dev *indio_dev); + int (*read_block)(struct device *dev, int num, void *data); + int (*sw_mode_config)(struct iio_dev *indio_dev); + int (*reg_read)(struct ad7606_state *st, unsigned int addr); + int (*reg_write)(struct ad7606_state *st, + unsigned int addr, + unsigned int val); + int (*update_scan_mode)(struct iio_dev *indio_dev, const unsigned long *scan_mask); + u16 (*rd_wr_cmd)(int addr, char is_write_op); +}; + +/** + * struct ad7606_bus_info - aggregate ad7606_chip_info and ad7606_bus_ops + * @chip_info: entry in the table of chips that describes this device + * @bops: bus operations (SPI or parallel) + */ +struct ad7606_bus_info { + const struct ad7606_chip_info *chip_info; + const struct ad7606_bus_ops *bops; +}; + +int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, + const struct ad7606_chip_info *info, + const struct ad7606_bus_ops *bops); + +int ad7606_reset(struct ad7606_state *st); +int ad7606_pwm_set_swing(struct ad7606_state *st); +int ad7606_pwm_set_low(struct ad7606_state *st); + +extern const struct ad7606_chip_info ad7605_4_info; +extern const struct ad7606_chip_info ad7606_8_info; +extern const struct ad7606_chip_info ad7606_6_info; +extern const struct ad7606_chip_info ad7606_4_info; +extern const struct ad7606_chip_info ad7606b_info; +extern const struct ad7606_chip_info ad7606c_16_info; +extern const struct ad7606_chip_info ad7606c_18_info; +extern const struct ad7606_chip_info ad7607_info; +extern const struct ad7606_chip_info ad7608_info; +extern const struct ad7606_chip_info ad7609_info; +extern const struct ad7606_chip_info ad7616_info; + +#ifdef CONFIG_PM_SLEEP +extern const struct dev_pm_ops ad7606_pm_ops; +#define AD7606_PM_OPS (&ad7606_pm_ops) +#else +#define AD7606_PM_OPS NULL +#endif + +#endif /* IIO_ADC_AD7606_H_ */ |
