162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * AD5755, AD5755-1, AD5757, AD5735, AD5737 Digital to analog converters driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2012 Analog Devices Inc. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/device.h> 962306a36Sopenharmony_ci#include <linux/err.h> 1062306a36Sopenharmony_ci#include <linux/module.h> 1162306a36Sopenharmony_ci#include <linux/kernel.h> 1262306a36Sopenharmony_ci#include <linux/spi/spi.h> 1362306a36Sopenharmony_ci#include <linux/slab.h> 1462306a36Sopenharmony_ci#include <linux/sysfs.h> 1562306a36Sopenharmony_ci#include <linux/delay.h> 1662306a36Sopenharmony_ci#include <linux/property.h> 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#include <linux/iio/iio.h> 1962306a36Sopenharmony_ci#include <linux/iio/sysfs.h> 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#define AD5755_NUM_CHANNELS 4 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#define AD5755_ADDR(x) ((x) << 16) 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#define AD5755_WRITE_REG_DATA(chan) (chan) 2662306a36Sopenharmony_ci#define AD5755_WRITE_REG_GAIN(chan) (0x08 | (chan)) 2762306a36Sopenharmony_ci#define AD5755_WRITE_REG_OFFSET(chan) (0x10 | (chan)) 2862306a36Sopenharmony_ci#define AD5755_WRITE_REG_CTRL(chan) (0x1c | (chan)) 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#define AD5755_READ_REG_DATA(chan) (chan) 3162306a36Sopenharmony_ci#define AD5755_READ_REG_CTRL(chan) (0x4 | (chan)) 3262306a36Sopenharmony_ci#define AD5755_READ_REG_GAIN(chan) (0x8 | (chan)) 3362306a36Sopenharmony_ci#define AD5755_READ_REG_OFFSET(chan) (0xc | (chan)) 3462306a36Sopenharmony_ci#define AD5755_READ_REG_CLEAR(chan) (0x10 | (chan)) 3562306a36Sopenharmony_ci#define AD5755_READ_REG_SLEW(chan) (0x14 | (chan)) 3662306a36Sopenharmony_ci#define AD5755_READ_REG_STATUS 0x18 3762306a36Sopenharmony_ci#define AD5755_READ_REG_MAIN 0x19 3862306a36Sopenharmony_ci#define AD5755_READ_REG_DC_DC 0x1a 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci#define AD5755_CTRL_REG_SLEW 0x0 4162306a36Sopenharmony_ci#define AD5755_CTRL_REG_MAIN 0x1 4262306a36Sopenharmony_ci#define AD5755_CTRL_REG_DAC 0x2 4362306a36Sopenharmony_ci#define AD5755_CTRL_REG_DC_DC 0x3 4462306a36Sopenharmony_ci#define AD5755_CTRL_REG_SW 0x4 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci#define AD5755_READ_FLAG 0x800000 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci#define AD5755_NOOP 0x1CE000 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci#define AD5755_DAC_INT_EN BIT(8) 5162306a36Sopenharmony_ci#define AD5755_DAC_CLR_EN BIT(7) 5262306a36Sopenharmony_ci#define AD5755_DAC_OUT_EN BIT(6) 5362306a36Sopenharmony_ci#define AD5755_DAC_INT_CURRENT_SENSE_RESISTOR BIT(5) 5462306a36Sopenharmony_ci#define AD5755_DAC_DC_DC_EN BIT(4) 5562306a36Sopenharmony_ci#define AD5755_DAC_VOLTAGE_OVERRANGE_EN BIT(3) 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci#define AD5755_DC_DC_MAXV 0 5862306a36Sopenharmony_ci#define AD5755_DC_DC_FREQ_SHIFT 2 5962306a36Sopenharmony_ci#define AD5755_DC_DC_PHASE_SHIFT 4 6062306a36Sopenharmony_ci#define AD5755_EXT_DC_DC_COMP_RES BIT(6) 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci#define AD5755_SLEW_STEP_SIZE_SHIFT 0 6362306a36Sopenharmony_ci#define AD5755_SLEW_RATE_SHIFT 3 6462306a36Sopenharmony_ci#define AD5755_SLEW_ENABLE BIT(12) 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_cienum ad5755_mode { 6762306a36Sopenharmony_ci AD5755_MODE_VOLTAGE_0V_5V = 0, 6862306a36Sopenharmony_ci AD5755_MODE_VOLTAGE_0V_10V = 1, 6962306a36Sopenharmony_ci AD5755_MODE_VOLTAGE_PLUSMINUS_5V = 2, 7062306a36Sopenharmony_ci AD5755_MODE_VOLTAGE_PLUSMINUS_10V = 3, 7162306a36Sopenharmony_ci AD5755_MODE_CURRENT_4mA_20mA = 4, 7262306a36Sopenharmony_ci AD5755_MODE_CURRENT_0mA_20mA = 5, 7362306a36Sopenharmony_ci AD5755_MODE_CURRENT_0mA_24mA = 6, 7462306a36Sopenharmony_ci}; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_cienum ad5755_dc_dc_phase { 7762306a36Sopenharmony_ci AD5755_DC_DC_PHASE_ALL_SAME_EDGE = 0, 7862306a36Sopenharmony_ci AD5755_DC_DC_PHASE_A_B_SAME_EDGE_C_D_OPP_EDGE = 1, 7962306a36Sopenharmony_ci AD5755_DC_DC_PHASE_A_C_SAME_EDGE_B_D_OPP_EDGE = 2, 8062306a36Sopenharmony_ci AD5755_DC_DC_PHASE_90_DEGREE = 3, 8162306a36Sopenharmony_ci}; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_cienum ad5755_dc_dc_freq { 8462306a36Sopenharmony_ci AD5755_DC_DC_FREQ_250kHZ = 0, 8562306a36Sopenharmony_ci AD5755_DC_DC_FREQ_410kHZ = 1, 8662306a36Sopenharmony_ci AD5755_DC_DC_FREQ_650kHZ = 2, 8762306a36Sopenharmony_ci}; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_cienum ad5755_dc_dc_maxv { 9062306a36Sopenharmony_ci AD5755_DC_DC_MAXV_23V = 0, 9162306a36Sopenharmony_ci AD5755_DC_DC_MAXV_24V5 = 1, 9262306a36Sopenharmony_ci AD5755_DC_DC_MAXV_27V = 2, 9362306a36Sopenharmony_ci AD5755_DC_DC_MAXV_29V5 = 3, 9462306a36Sopenharmony_ci}; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_cienum ad5755_slew_rate { 9762306a36Sopenharmony_ci AD5755_SLEW_RATE_64k = 0, 9862306a36Sopenharmony_ci AD5755_SLEW_RATE_32k = 1, 9962306a36Sopenharmony_ci AD5755_SLEW_RATE_16k = 2, 10062306a36Sopenharmony_ci AD5755_SLEW_RATE_8k = 3, 10162306a36Sopenharmony_ci AD5755_SLEW_RATE_4k = 4, 10262306a36Sopenharmony_ci AD5755_SLEW_RATE_2k = 5, 10362306a36Sopenharmony_ci AD5755_SLEW_RATE_1k = 6, 10462306a36Sopenharmony_ci AD5755_SLEW_RATE_500 = 7, 10562306a36Sopenharmony_ci AD5755_SLEW_RATE_250 = 8, 10662306a36Sopenharmony_ci AD5755_SLEW_RATE_125 = 9, 10762306a36Sopenharmony_ci AD5755_SLEW_RATE_64 = 10, 10862306a36Sopenharmony_ci AD5755_SLEW_RATE_32 = 11, 10962306a36Sopenharmony_ci AD5755_SLEW_RATE_16 = 12, 11062306a36Sopenharmony_ci AD5755_SLEW_RATE_8 = 13, 11162306a36Sopenharmony_ci AD5755_SLEW_RATE_4 = 14, 11262306a36Sopenharmony_ci AD5755_SLEW_RATE_0_5 = 15, 11362306a36Sopenharmony_ci}; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_cienum ad5755_slew_step_size { 11662306a36Sopenharmony_ci AD5755_SLEW_STEP_SIZE_1 = 0, 11762306a36Sopenharmony_ci AD5755_SLEW_STEP_SIZE_2 = 1, 11862306a36Sopenharmony_ci AD5755_SLEW_STEP_SIZE_4 = 2, 11962306a36Sopenharmony_ci AD5755_SLEW_STEP_SIZE_8 = 3, 12062306a36Sopenharmony_ci AD5755_SLEW_STEP_SIZE_16 = 4, 12162306a36Sopenharmony_ci AD5755_SLEW_STEP_SIZE_32 = 5, 12262306a36Sopenharmony_ci AD5755_SLEW_STEP_SIZE_64 = 6, 12362306a36Sopenharmony_ci AD5755_SLEW_STEP_SIZE_128 = 7, 12462306a36Sopenharmony_ci AD5755_SLEW_STEP_SIZE_256 = 8, 12562306a36Sopenharmony_ci}; 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci/** 12862306a36Sopenharmony_ci * struct ad5755_platform_data - AD5755 DAC driver platform data 12962306a36Sopenharmony_ci * @ext_dc_dc_compenstation_resistor: Whether an external DC-DC converter 13062306a36Sopenharmony_ci * compensation register is used. 13162306a36Sopenharmony_ci * @dc_dc_phase: DC-DC converter phase. 13262306a36Sopenharmony_ci * @dc_dc_freq: DC-DC converter frequency. 13362306a36Sopenharmony_ci * @dc_dc_maxv: DC-DC maximum allowed boost voltage. 13462306a36Sopenharmony_ci * @dac: Per DAC instance parameters. 13562306a36Sopenharmony_ci * @dac.mode: The mode to be used for the DAC output. 13662306a36Sopenharmony_ci * @dac.ext_current_sense_resistor: Whether an external current sense resistor 13762306a36Sopenharmony_ci * is used. 13862306a36Sopenharmony_ci * @dac.enable_voltage_overrange: Whether to enable 20% voltage output overrange. 13962306a36Sopenharmony_ci * @dac.slew.enable: Whether to enable digital slew. 14062306a36Sopenharmony_ci * @dac.slew.rate: Slew rate of the digital slew. 14162306a36Sopenharmony_ci * @dac.slew.step_size: Slew step size of the digital slew. 14262306a36Sopenharmony_ci **/ 14362306a36Sopenharmony_cistruct ad5755_platform_data { 14462306a36Sopenharmony_ci bool ext_dc_dc_compenstation_resistor; 14562306a36Sopenharmony_ci enum ad5755_dc_dc_phase dc_dc_phase; 14662306a36Sopenharmony_ci enum ad5755_dc_dc_freq dc_dc_freq; 14762306a36Sopenharmony_ci enum ad5755_dc_dc_maxv dc_dc_maxv; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci struct { 15062306a36Sopenharmony_ci enum ad5755_mode mode; 15162306a36Sopenharmony_ci bool ext_current_sense_resistor; 15262306a36Sopenharmony_ci bool enable_voltage_overrange; 15362306a36Sopenharmony_ci struct { 15462306a36Sopenharmony_ci bool enable; 15562306a36Sopenharmony_ci enum ad5755_slew_rate rate; 15662306a36Sopenharmony_ci enum ad5755_slew_step_size step_size; 15762306a36Sopenharmony_ci } slew; 15862306a36Sopenharmony_ci } dac[4]; 15962306a36Sopenharmony_ci}; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci/** 16262306a36Sopenharmony_ci * struct ad5755_chip_info - chip specific information 16362306a36Sopenharmony_ci * @channel_template: channel specification 16462306a36Sopenharmony_ci * @calib_shift: shift for the calibration data registers 16562306a36Sopenharmony_ci * @has_voltage_out: whether the chip has voltage outputs 16662306a36Sopenharmony_ci */ 16762306a36Sopenharmony_cistruct ad5755_chip_info { 16862306a36Sopenharmony_ci const struct iio_chan_spec channel_template; 16962306a36Sopenharmony_ci unsigned int calib_shift; 17062306a36Sopenharmony_ci bool has_voltage_out; 17162306a36Sopenharmony_ci}; 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci/** 17462306a36Sopenharmony_ci * struct ad5755_state - driver instance specific data 17562306a36Sopenharmony_ci * @spi: spi device the driver is attached to 17662306a36Sopenharmony_ci * @chip_info: chip model specific constants, available modes etc 17762306a36Sopenharmony_ci * @pwr_down: bitmask which contains hether a channel is powered down or not 17862306a36Sopenharmony_ci * @ctrl: software shadow of the channel ctrl registers 17962306a36Sopenharmony_ci * @channels: iio channel spec for the device 18062306a36Sopenharmony_ci * @lock: lock to protect the data buffer during SPI ops 18162306a36Sopenharmony_ci * @data: spi transfer buffers 18262306a36Sopenharmony_ci */ 18362306a36Sopenharmony_cistruct ad5755_state { 18462306a36Sopenharmony_ci struct spi_device *spi; 18562306a36Sopenharmony_ci const struct ad5755_chip_info *chip_info; 18662306a36Sopenharmony_ci unsigned int pwr_down; 18762306a36Sopenharmony_ci unsigned int ctrl[AD5755_NUM_CHANNELS]; 18862306a36Sopenharmony_ci struct iio_chan_spec channels[AD5755_NUM_CHANNELS]; 18962306a36Sopenharmony_ci struct mutex lock; 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci /* 19262306a36Sopenharmony_ci * DMA (thus cache coherency maintenance) may require the 19362306a36Sopenharmony_ci * transfer buffers to live in their own cache lines. 19462306a36Sopenharmony_ci */ 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci union { 19762306a36Sopenharmony_ci __be32 d32; 19862306a36Sopenharmony_ci u8 d8[4]; 19962306a36Sopenharmony_ci } data[2] __aligned(IIO_DMA_MINALIGN); 20062306a36Sopenharmony_ci}; 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_cienum ad5755_type { 20362306a36Sopenharmony_ci ID_AD5755, 20462306a36Sopenharmony_ci ID_AD5757, 20562306a36Sopenharmony_ci ID_AD5735, 20662306a36Sopenharmony_ci ID_AD5737, 20762306a36Sopenharmony_ci}; 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_cistatic const int ad5755_dcdc_freq_table[][2] = { 21062306a36Sopenharmony_ci { 250000, AD5755_DC_DC_FREQ_250kHZ }, 21162306a36Sopenharmony_ci { 410000, AD5755_DC_DC_FREQ_410kHZ }, 21262306a36Sopenharmony_ci { 650000, AD5755_DC_DC_FREQ_650kHZ } 21362306a36Sopenharmony_ci}; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_cistatic const int ad5755_dcdc_maxv_table[][2] = { 21662306a36Sopenharmony_ci { 23000000, AD5755_DC_DC_MAXV_23V }, 21762306a36Sopenharmony_ci { 24500000, AD5755_DC_DC_MAXV_24V5 }, 21862306a36Sopenharmony_ci { 27000000, AD5755_DC_DC_MAXV_27V }, 21962306a36Sopenharmony_ci { 29500000, AD5755_DC_DC_MAXV_29V5 }, 22062306a36Sopenharmony_ci}; 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_cistatic const int ad5755_slew_rate_table[][2] = { 22362306a36Sopenharmony_ci { 64000, AD5755_SLEW_RATE_64k }, 22462306a36Sopenharmony_ci { 32000, AD5755_SLEW_RATE_32k }, 22562306a36Sopenharmony_ci { 16000, AD5755_SLEW_RATE_16k }, 22662306a36Sopenharmony_ci { 8000, AD5755_SLEW_RATE_8k }, 22762306a36Sopenharmony_ci { 4000, AD5755_SLEW_RATE_4k }, 22862306a36Sopenharmony_ci { 2000, AD5755_SLEW_RATE_2k }, 22962306a36Sopenharmony_ci { 1000, AD5755_SLEW_RATE_1k }, 23062306a36Sopenharmony_ci { 500, AD5755_SLEW_RATE_500 }, 23162306a36Sopenharmony_ci { 250, AD5755_SLEW_RATE_250 }, 23262306a36Sopenharmony_ci { 125, AD5755_SLEW_RATE_125 }, 23362306a36Sopenharmony_ci { 64, AD5755_SLEW_RATE_64 }, 23462306a36Sopenharmony_ci { 32, AD5755_SLEW_RATE_32 }, 23562306a36Sopenharmony_ci { 16, AD5755_SLEW_RATE_16 }, 23662306a36Sopenharmony_ci { 8, AD5755_SLEW_RATE_8 }, 23762306a36Sopenharmony_ci { 4, AD5755_SLEW_RATE_4 }, 23862306a36Sopenharmony_ci { 0, AD5755_SLEW_RATE_0_5 }, 23962306a36Sopenharmony_ci}; 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_cistatic const int ad5755_slew_step_table[][2] = { 24262306a36Sopenharmony_ci { 256, AD5755_SLEW_STEP_SIZE_256 }, 24362306a36Sopenharmony_ci { 128, AD5755_SLEW_STEP_SIZE_128 }, 24462306a36Sopenharmony_ci { 64, AD5755_SLEW_STEP_SIZE_64 }, 24562306a36Sopenharmony_ci { 32, AD5755_SLEW_STEP_SIZE_32 }, 24662306a36Sopenharmony_ci { 16, AD5755_SLEW_STEP_SIZE_16 }, 24762306a36Sopenharmony_ci { 4, AD5755_SLEW_STEP_SIZE_4 }, 24862306a36Sopenharmony_ci { 2, AD5755_SLEW_STEP_SIZE_2 }, 24962306a36Sopenharmony_ci { 1, AD5755_SLEW_STEP_SIZE_1 }, 25062306a36Sopenharmony_ci}; 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_cistatic int ad5755_write_unlocked(struct iio_dev *indio_dev, 25362306a36Sopenharmony_ci unsigned int reg, unsigned int val) 25462306a36Sopenharmony_ci{ 25562306a36Sopenharmony_ci struct ad5755_state *st = iio_priv(indio_dev); 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci st->data[0].d32 = cpu_to_be32((reg << 16) | val); 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci return spi_write(st->spi, &st->data[0].d8[1], 3); 26062306a36Sopenharmony_ci} 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_cistatic int ad5755_write_ctrl_unlocked(struct iio_dev *indio_dev, 26362306a36Sopenharmony_ci unsigned int channel, unsigned int reg, unsigned int val) 26462306a36Sopenharmony_ci{ 26562306a36Sopenharmony_ci return ad5755_write_unlocked(indio_dev, 26662306a36Sopenharmony_ci AD5755_WRITE_REG_CTRL(channel), (reg << 13) | val); 26762306a36Sopenharmony_ci} 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_cistatic int ad5755_write(struct iio_dev *indio_dev, unsigned int reg, 27062306a36Sopenharmony_ci unsigned int val) 27162306a36Sopenharmony_ci{ 27262306a36Sopenharmony_ci struct ad5755_state *st = iio_priv(indio_dev); 27362306a36Sopenharmony_ci int ret; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci mutex_lock(&st->lock); 27662306a36Sopenharmony_ci ret = ad5755_write_unlocked(indio_dev, reg, val); 27762306a36Sopenharmony_ci mutex_unlock(&st->lock); 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci return ret; 28062306a36Sopenharmony_ci} 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_cistatic int ad5755_write_ctrl(struct iio_dev *indio_dev, unsigned int channel, 28362306a36Sopenharmony_ci unsigned int reg, unsigned int val) 28462306a36Sopenharmony_ci{ 28562306a36Sopenharmony_ci struct ad5755_state *st = iio_priv(indio_dev); 28662306a36Sopenharmony_ci int ret; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci mutex_lock(&st->lock); 28962306a36Sopenharmony_ci ret = ad5755_write_ctrl_unlocked(indio_dev, channel, reg, val); 29062306a36Sopenharmony_ci mutex_unlock(&st->lock); 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci return ret; 29362306a36Sopenharmony_ci} 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_cistatic int ad5755_read(struct iio_dev *indio_dev, unsigned int addr) 29662306a36Sopenharmony_ci{ 29762306a36Sopenharmony_ci struct ad5755_state *st = iio_priv(indio_dev); 29862306a36Sopenharmony_ci int ret; 29962306a36Sopenharmony_ci struct spi_transfer t[] = { 30062306a36Sopenharmony_ci { 30162306a36Sopenharmony_ci .tx_buf = &st->data[0].d8[1], 30262306a36Sopenharmony_ci .len = 3, 30362306a36Sopenharmony_ci .cs_change = 1, 30462306a36Sopenharmony_ci }, { 30562306a36Sopenharmony_ci .tx_buf = &st->data[1].d8[1], 30662306a36Sopenharmony_ci .rx_buf = &st->data[1].d8[1], 30762306a36Sopenharmony_ci .len = 3, 30862306a36Sopenharmony_ci }, 30962306a36Sopenharmony_ci }; 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci mutex_lock(&st->lock); 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci st->data[0].d32 = cpu_to_be32(AD5755_READ_FLAG | (addr << 16)); 31462306a36Sopenharmony_ci st->data[1].d32 = cpu_to_be32(AD5755_NOOP); 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t)); 31762306a36Sopenharmony_ci if (ret >= 0) 31862306a36Sopenharmony_ci ret = be32_to_cpu(st->data[1].d32) & 0xffff; 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci mutex_unlock(&st->lock); 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci return ret; 32362306a36Sopenharmony_ci} 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_cistatic int ad5755_update_dac_ctrl(struct iio_dev *indio_dev, 32662306a36Sopenharmony_ci unsigned int channel, unsigned int set, unsigned int clr) 32762306a36Sopenharmony_ci{ 32862306a36Sopenharmony_ci struct ad5755_state *st = iio_priv(indio_dev); 32962306a36Sopenharmony_ci int ret; 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci st->ctrl[channel] |= set; 33262306a36Sopenharmony_ci st->ctrl[channel] &= ~clr; 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci ret = ad5755_write_ctrl_unlocked(indio_dev, channel, 33562306a36Sopenharmony_ci AD5755_CTRL_REG_DAC, st->ctrl[channel]); 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci return ret; 33862306a36Sopenharmony_ci} 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_cistatic int ad5755_set_channel_pwr_down(struct iio_dev *indio_dev, 34162306a36Sopenharmony_ci unsigned int channel, bool pwr_down) 34262306a36Sopenharmony_ci{ 34362306a36Sopenharmony_ci struct ad5755_state *st = iio_priv(indio_dev); 34462306a36Sopenharmony_ci unsigned int mask = BIT(channel); 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci mutex_lock(&st->lock); 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci if ((bool)(st->pwr_down & mask) == pwr_down) 34962306a36Sopenharmony_ci goto out_unlock; 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci if (!pwr_down) { 35262306a36Sopenharmony_ci st->pwr_down &= ~mask; 35362306a36Sopenharmony_ci ad5755_update_dac_ctrl(indio_dev, channel, 35462306a36Sopenharmony_ci AD5755_DAC_INT_EN | AD5755_DAC_DC_DC_EN, 0); 35562306a36Sopenharmony_ci udelay(200); 35662306a36Sopenharmony_ci ad5755_update_dac_ctrl(indio_dev, channel, 35762306a36Sopenharmony_ci AD5755_DAC_OUT_EN, 0); 35862306a36Sopenharmony_ci } else { 35962306a36Sopenharmony_ci st->pwr_down |= mask; 36062306a36Sopenharmony_ci ad5755_update_dac_ctrl(indio_dev, channel, 36162306a36Sopenharmony_ci 0, AD5755_DAC_INT_EN | AD5755_DAC_OUT_EN | 36262306a36Sopenharmony_ci AD5755_DAC_DC_DC_EN); 36362306a36Sopenharmony_ci } 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ciout_unlock: 36662306a36Sopenharmony_ci mutex_unlock(&st->lock); 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci return 0; 36962306a36Sopenharmony_ci} 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_cistatic const int ad5755_min_max_table[][2] = { 37262306a36Sopenharmony_ci [AD5755_MODE_VOLTAGE_0V_5V] = { 0, 5000 }, 37362306a36Sopenharmony_ci [AD5755_MODE_VOLTAGE_0V_10V] = { 0, 10000 }, 37462306a36Sopenharmony_ci [AD5755_MODE_VOLTAGE_PLUSMINUS_5V] = { -5000, 5000 }, 37562306a36Sopenharmony_ci [AD5755_MODE_VOLTAGE_PLUSMINUS_10V] = { -10000, 10000 }, 37662306a36Sopenharmony_ci [AD5755_MODE_CURRENT_4mA_20mA] = { 4, 20 }, 37762306a36Sopenharmony_ci [AD5755_MODE_CURRENT_0mA_20mA] = { 0, 20 }, 37862306a36Sopenharmony_ci [AD5755_MODE_CURRENT_0mA_24mA] = { 0, 24 }, 37962306a36Sopenharmony_ci}; 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_cistatic void ad5755_get_min_max(struct ad5755_state *st, 38262306a36Sopenharmony_ci struct iio_chan_spec const *chan, int *min, int *max) 38362306a36Sopenharmony_ci{ 38462306a36Sopenharmony_ci enum ad5755_mode mode = st->ctrl[chan->channel] & 7; 38562306a36Sopenharmony_ci *min = ad5755_min_max_table[mode][0]; 38662306a36Sopenharmony_ci *max = ad5755_min_max_table[mode][1]; 38762306a36Sopenharmony_ci} 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_cistatic inline int ad5755_get_offset(struct ad5755_state *st, 39062306a36Sopenharmony_ci struct iio_chan_spec const *chan) 39162306a36Sopenharmony_ci{ 39262306a36Sopenharmony_ci int min, max; 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci ad5755_get_min_max(st, chan, &min, &max); 39562306a36Sopenharmony_ci return (min * (1 << chan->scan_type.realbits)) / (max - min); 39662306a36Sopenharmony_ci} 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_cistatic int ad5755_chan_reg_info(struct ad5755_state *st, 39962306a36Sopenharmony_ci struct iio_chan_spec const *chan, long info, bool write, 40062306a36Sopenharmony_ci unsigned int *reg, unsigned int *shift, unsigned int *offset) 40162306a36Sopenharmony_ci{ 40262306a36Sopenharmony_ci switch (info) { 40362306a36Sopenharmony_ci case IIO_CHAN_INFO_RAW: 40462306a36Sopenharmony_ci if (write) 40562306a36Sopenharmony_ci *reg = AD5755_WRITE_REG_DATA(chan->address); 40662306a36Sopenharmony_ci else 40762306a36Sopenharmony_ci *reg = AD5755_READ_REG_DATA(chan->address); 40862306a36Sopenharmony_ci *shift = chan->scan_type.shift; 40962306a36Sopenharmony_ci *offset = 0; 41062306a36Sopenharmony_ci break; 41162306a36Sopenharmony_ci case IIO_CHAN_INFO_CALIBBIAS: 41262306a36Sopenharmony_ci if (write) 41362306a36Sopenharmony_ci *reg = AD5755_WRITE_REG_OFFSET(chan->address); 41462306a36Sopenharmony_ci else 41562306a36Sopenharmony_ci *reg = AD5755_READ_REG_OFFSET(chan->address); 41662306a36Sopenharmony_ci *shift = st->chip_info->calib_shift; 41762306a36Sopenharmony_ci *offset = 32768; 41862306a36Sopenharmony_ci break; 41962306a36Sopenharmony_ci case IIO_CHAN_INFO_CALIBSCALE: 42062306a36Sopenharmony_ci if (write) 42162306a36Sopenharmony_ci *reg = AD5755_WRITE_REG_GAIN(chan->address); 42262306a36Sopenharmony_ci else 42362306a36Sopenharmony_ci *reg = AD5755_READ_REG_GAIN(chan->address); 42462306a36Sopenharmony_ci *shift = st->chip_info->calib_shift; 42562306a36Sopenharmony_ci *offset = 0; 42662306a36Sopenharmony_ci break; 42762306a36Sopenharmony_ci default: 42862306a36Sopenharmony_ci return -EINVAL; 42962306a36Sopenharmony_ci } 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci return 0; 43262306a36Sopenharmony_ci} 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_cistatic int ad5755_read_raw(struct iio_dev *indio_dev, 43562306a36Sopenharmony_ci const struct iio_chan_spec *chan, int *val, int *val2, long info) 43662306a36Sopenharmony_ci{ 43762306a36Sopenharmony_ci struct ad5755_state *st = iio_priv(indio_dev); 43862306a36Sopenharmony_ci unsigned int reg, shift, offset; 43962306a36Sopenharmony_ci int min, max; 44062306a36Sopenharmony_ci int ret; 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci switch (info) { 44362306a36Sopenharmony_ci case IIO_CHAN_INFO_SCALE: 44462306a36Sopenharmony_ci ad5755_get_min_max(st, chan, &min, &max); 44562306a36Sopenharmony_ci *val = max - min; 44662306a36Sopenharmony_ci *val2 = chan->scan_type.realbits; 44762306a36Sopenharmony_ci return IIO_VAL_FRACTIONAL_LOG2; 44862306a36Sopenharmony_ci case IIO_CHAN_INFO_OFFSET: 44962306a36Sopenharmony_ci *val = ad5755_get_offset(st, chan); 45062306a36Sopenharmony_ci return IIO_VAL_INT; 45162306a36Sopenharmony_ci default: 45262306a36Sopenharmony_ci ret = ad5755_chan_reg_info(st, chan, info, false, 45362306a36Sopenharmony_ci ®, &shift, &offset); 45462306a36Sopenharmony_ci if (ret) 45562306a36Sopenharmony_ci return ret; 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci ret = ad5755_read(indio_dev, reg); 45862306a36Sopenharmony_ci if (ret < 0) 45962306a36Sopenharmony_ci return ret; 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci *val = (ret - offset) >> shift; 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci return IIO_VAL_INT; 46462306a36Sopenharmony_ci } 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci return -EINVAL; 46762306a36Sopenharmony_ci} 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_cistatic int ad5755_write_raw(struct iio_dev *indio_dev, 47062306a36Sopenharmony_ci const struct iio_chan_spec *chan, int val, int val2, long info) 47162306a36Sopenharmony_ci{ 47262306a36Sopenharmony_ci struct ad5755_state *st = iio_priv(indio_dev); 47362306a36Sopenharmony_ci unsigned int shift, reg, offset; 47462306a36Sopenharmony_ci int ret; 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci ret = ad5755_chan_reg_info(st, chan, info, true, 47762306a36Sopenharmony_ci ®, &shift, &offset); 47862306a36Sopenharmony_ci if (ret) 47962306a36Sopenharmony_ci return ret; 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci val <<= shift; 48262306a36Sopenharmony_ci val += offset; 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_ci if (val < 0 || val > 0xffff) 48562306a36Sopenharmony_ci return -EINVAL; 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci return ad5755_write(indio_dev, reg, val); 48862306a36Sopenharmony_ci} 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_cistatic ssize_t ad5755_read_powerdown(struct iio_dev *indio_dev, uintptr_t priv, 49162306a36Sopenharmony_ci const struct iio_chan_spec *chan, char *buf) 49262306a36Sopenharmony_ci{ 49362306a36Sopenharmony_ci struct ad5755_state *st = iio_priv(indio_dev); 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci return sysfs_emit(buf, "%d\n", 49662306a36Sopenharmony_ci (bool)(st->pwr_down & (1 << chan->channel))); 49762306a36Sopenharmony_ci} 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_cistatic ssize_t ad5755_write_powerdown(struct iio_dev *indio_dev, uintptr_t priv, 50062306a36Sopenharmony_ci struct iio_chan_spec const *chan, const char *buf, size_t len) 50162306a36Sopenharmony_ci{ 50262306a36Sopenharmony_ci bool pwr_down; 50362306a36Sopenharmony_ci int ret; 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_ci ret = kstrtobool(buf, &pwr_down); 50662306a36Sopenharmony_ci if (ret) 50762306a36Sopenharmony_ci return ret; 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci ret = ad5755_set_channel_pwr_down(indio_dev, chan->channel, pwr_down); 51062306a36Sopenharmony_ci return ret ? ret : len; 51162306a36Sopenharmony_ci} 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_cistatic const struct iio_info ad5755_info = { 51462306a36Sopenharmony_ci .read_raw = ad5755_read_raw, 51562306a36Sopenharmony_ci .write_raw = ad5755_write_raw, 51662306a36Sopenharmony_ci}; 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_cistatic const struct iio_chan_spec_ext_info ad5755_ext_info[] = { 51962306a36Sopenharmony_ci { 52062306a36Sopenharmony_ci .name = "powerdown", 52162306a36Sopenharmony_ci .read = ad5755_read_powerdown, 52262306a36Sopenharmony_ci .write = ad5755_write_powerdown, 52362306a36Sopenharmony_ci .shared = IIO_SEPARATE, 52462306a36Sopenharmony_ci }, 52562306a36Sopenharmony_ci { }, 52662306a36Sopenharmony_ci}; 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ci#define AD5755_CHANNEL(_bits) { \ 52962306a36Sopenharmony_ci .indexed = 1, \ 53062306a36Sopenharmony_ci .output = 1, \ 53162306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ 53262306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_SCALE) | \ 53362306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_OFFSET) | \ 53462306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_CALIBSCALE) | \ 53562306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_CALIBBIAS), \ 53662306a36Sopenharmony_ci .scan_type = { \ 53762306a36Sopenharmony_ci .sign = 'u', \ 53862306a36Sopenharmony_ci .realbits = (_bits), \ 53962306a36Sopenharmony_ci .storagebits = 16, \ 54062306a36Sopenharmony_ci .shift = 16 - (_bits), \ 54162306a36Sopenharmony_ci }, \ 54262306a36Sopenharmony_ci .ext_info = ad5755_ext_info, \ 54362306a36Sopenharmony_ci} 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_cistatic const struct ad5755_chip_info ad5755_chip_info_tbl[] = { 54662306a36Sopenharmony_ci [ID_AD5735] = { 54762306a36Sopenharmony_ci .channel_template = AD5755_CHANNEL(14), 54862306a36Sopenharmony_ci .has_voltage_out = true, 54962306a36Sopenharmony_ci .calib_shift = 4, 55062306a36Sopenharmony_ci }, 55162306a36Sopenharmony_ci [ID_AD5737] = { 55262306a36Sopenharmony_ci .channel_template = AD5755_CHANNEL(14), 55362306a36Sopenharmony_ci .has_voltage_out = false, 55462306a36Sopenharmony_ci .calib_shift = 4, 55562306a36Sopenharmony_ci }, 55662306a36Sopenharmony_ci [ID_AD5755] = { 55762306a36Sopenharmony_ci .channel_template = AD5755_CHANNEL(16), 55862306a36Sopenharmony_ci .has_voltage_out = true, 55962306a36Sopenharmony_ci .calib_shift = 0, 56062306a36Sopenharmony_ci }, 56162306a36Sopenharmony_ci [ID_AD5757] = { 56262306a36Sopenharmony_ci .channel_template = AD5755_CHANNEL(16), 56362306a36Sopenharmony_ci .has_voltage_out = false, 56462306a36Sopenharmony_ci .calib_shift = 0, 56562306a36Sopenharmony_ci }, 56662306a36Sopenharmony_ci}; 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_cistatic bool ad5755_is_valid_mode(struct ad5755_state *st, enum ad5755_mode mode) 56962306a36Sopenharmony_ci{ 57062306a36Sopenharmony_ci switch (mode) { 57162306a36Sopenharmony_ci case AD5755_MODE_VOLTAGE_0V_5V: 57262306a36Sopenharmony_ci case AD5755_MODE_VOLTAGE_0V_10V: 57362306a36Sopenharmony_ci case AD5755_MODE_VOLTAGE_PLUSMINUS_5V: 57462306a36Sopenharmony_ci case AD5755_MODE_VOLTAGE_PLUSMINUS_10V: 57562306a36Sopenharmony_ci return st->chip_info->has_voltage_out; 57662306a36Sopenharmony_ci case AD5755_MODE_CURRENT_4mA_20mA: 57762306a36Sopenharmony_ci case AD5755_MODE_CURRENT_0mA_20mA: 57862306a36Sopenharmony_ci case AD5755_MODE_CURRENT_0mA_24mA: 57962306a36Sopenharmony_ci return true; 58062306a36Sopenharmony_ci default: 58162306a36Sopenharmony_ci return false; 58262306a36Sopenharmony_ci } 58362306a36Sopenharmony_ci} 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_cistatic int ad5755_setup_pdata(struct iio_dev *indio_dev, 58662306a36Sopenharmony_ci const struct ad5755_platform_data *pdata) 58762306a36Sopenharmony_ci{ 58862306a36Sopenharmony_ci struct ad5755_state *st = iio_priv(indio_dev); 58962306a36Sopenharmony_ci unsigned int val; 59062306a36Sopenharmony_ci unsigned int i; 59162306a36Sopenharmony_ci int ret; 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci if (pdata->dc_dc_phase > AD5755_DC_DC_PHASE_90_DEGREE || 59462306a36Sopenharmony_ci pdata->dc_dc_freq > AD5755_DC_DC_FREQ_650kHZ || 59562306a36Sopenharmony_ci pdata->dc_dc_maxv > AD5755_DC_DC_MAXV_29V5) 59662306a36Sopenharmony_ci return -EINVAL; 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci val = pdata->dc_dc_maxv << AD5755_DC_DC_MAXV; 59962306a36Sopenharmony_ci val |= pdata->dc_dc_freq << AD5755_DC_DC_FREQ_SHIFT; 60062306a36Sopenharmony_ci val |= pdata->dc_dc_phase << AD5755_DC_DC_PHASE_SHIFT; 60162306a36Sopenharmony_ci if (pdata->ext_dc_dc_compenstation_resistor) 60262306a36Sopenharmony_ci val |= AD5755_EXT_DC_DC_COMP_RES; 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci ret = ad5755_write_ctrl(indio_dev, 0, AD5755_CTRL_REG_DC_DC, val); 60562306a36Sopenharmony_ci if (ret < 0) 60662306a36Sopenharmony_ci return ret; 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(pdata->dac); ++i) { 60962306a36Sopenharmony_ci val = pdata->dac[i].slew.step_size << 61062306a36Sopenharmony_ci AD5755_SLEW_STEP_SIZE_SHIFT; 61162306a36Sopenharmony_ci val |= pdata->dac[i].slew.rate << 61262306a36Sopenharmony_ci AD5755_SLEW_RATE_SHIFT; 61362306a36Sopenharmony_ci if (pdata->dac[i].slew.enable) 61462306a36Sopenharmony_ci val |= AD5755_SLEW_ENABLE; 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ci ret = ad5755_write_ctrl(indio_dev, i, 61762306a36Sopenharmony_ci AD5755_CTRL_REG_SLEW, val); 61862306a36Sopenharmony_ci if (ret < 0) 61962306a36Sopenharmony_ci return ret; 62062306a36Sopenharmony_ci } 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(pdata->dac); ++i) { 62362306a36Sopenharmony_ci if (!ad5755_is_valid_mode(st, pdata->dac[i].mode)) 62462306a36Sopenharmony_ci return -EINVAL; 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci val = 0; 62762306a36Sopenharmony_ci if (!pdata->dac[i].ext_current_sense_resistor) 62862306a36Sopenharmony_ci val |= AD5755_DAC_INT_CURRENT_SENSE_RESISTOR; 62962306a36Sopenharmony_ci if (pdata->dac[i].enable_voltage_overrange) 63062306a36Sopenharmony_ci val |= AD5755_DAC_VOLTAGE_OVERRANGE_EN; 63162306a36Sopenharmony_ci val |= pdata->dac[i].mode; 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci ret = ad5755_update_dac_ctrl(indio_dev, i, val, 0); 63462306a36Sopenharmony_ci if (ret < 0) 63562306a36Sopenharmony_ci return ret; 63662306a36Sopenharmony_ci } 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci return 0; 63962306a36Sopenharmony_ci} 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_cistatic bool ad5755_is_voltage_mode(enum ad5755_mode mode) 64262306a36Sopenharmony_ci{ 64362306a36Sopenharmony_ci switch (mode) { 64462306a36Sopenharmony_ci case AD5755_MODE_VOLTAGE_0V_5V: 64562306a36Sopenharmony_ci case AD5755_MODE_VOLTAGE_0V_10V: 64662306a36Sopenharmony_ci case AD5755_MODE_VOLTAGE_PLUSMINUS_5V: 64762306a36Sopenharmony_ci case AD5755_MODE_VOLTAGE_PLUSMINUS_10V: 64862306a36Sopenharmony_ci return true; 64962306a36Sopenharmony_ci default: 65062306a36Sopenharmony_ci return false; 65162306a36Sopenharmony_ci } 65262306a36Sopenharmony_ci} 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_cistatic int ad5755_init_channels(struct iio_dev *indio_dev, 65562306a36Sopenharmony_ci const struct ad5755_platform_data *pdata) 65662306a36Sopenharmony_ci{ 65762306a36Sopenharmony_ci struct ad5755_state *st = iio_priv(indio_dev); 65862306a36Sopenharmony_ci struct iio_chan_spec *channels = st->channels; 65962306a36Sopenharmony_ci unsigned int i; 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci for (i = 0; i < AD5755_NUM_CHANNELS; ++i) { 66262306a36Sopenharmony_ci channels[i] = st->chip_info->channel_template; 66362306a36Sopenharmony_ci channels[i].channel = i; 66462306a36Sopenharmony_ci channels[i].address = i; 66562306a36Sopenharmony_ci if (pdata && ad5755_is_voltage_mode(pdata->dac[i].mode)) 66662306a36Sopenharmony_ci channels[i].type = IIO_VOLTAGE; 66762306a36Sopenharmony_ci else 66862306a36Sopenharmony_ci channels[i].type = IIO_CURRENT; 66962306a36Sopenharmony_ci } 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_ci indio_dev->channels = channels; 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_ci return 0; 67462306a36Sopenharmony_ci} 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_ci#define AD5755_DEFAULT_DAC_PDATA { \ 67762306a36Sopenharmony_ci .mode = AD5755_MODE_CURRENT_4mA_20mA, \ 67862306a36Sopenharmony_ci .ext_current_sense_resistor = true, \ 67962306a36Sopenharmony_ci .enable_voltage_overrange = false, \ 68062306a36Sopenharmony_ci .slew = { \ 68162306a36Sopenharmony_ci .enable = false, \ 68262306a36Sopenharmony_ci .rate = AD5755_SLEW_RATE_64k, \ 68362306a36Sopenharmony_ci .step_size = AD5755_SLEW_STEP_SIZE_1, \ 68462306a36Sopenharmony_ci }, \ 68562306a36Sopenharmony_ci } 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_cistatic const struct ad5755_platform_data ad5755_default_pdata = { 68862306a36Sopenharmony_ci .ext_dc_dc_compenstation_resistor = false, 68962306a36Sopenharmony_ci .dc_dc_phase = AD5755_DC_DC_PHASE_ALL_SAME_EDGE, 69062306a36Sopenharmony_ci .dc_dc_freq = AD5755_DC_DC_FREQ_410kHZ, 69162306a36Sopenharmony_ci .dc_dc_maxv = AD5755_DC_DC_MAXV_23V, 69262306a36Sopenharmony_ci .dac = { 69362306a36Sopenharmony_ci [0] = AD5755_DEFAULT_DAC_PDATA, 69462306a36Sopenharmony_ci [1] = AD5755_DEFAULT_DAC_PDATA, 69562306a36Sopenharmony_ci [2] = AD5755_DEFAULT_DAC_PDATA, 69662306a36Sopenharmony_ci [3] = AD5755_DEFAULT_DAC_PDATA, 69762306a36Sopenharmony_ci }, 69862306a36Sopenharmony_ci}; 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_cistatic struct ad5755_platform_data *ad5755_parse_fw(struct device *dev) 70162306a36Sopenharmony_ci{ 70262306a36Sopenharmony_ci struct fwnode_handle *pp; 70362306a36Sopenharmony_ci struct ad5755_platform_data *pdata; 70462306a36Sopenharmony_ci unsigned int tmp; 70562306a36Sopenharmony_ci unsigned int tmparray[3]; 70662306a36Sopenharmony_ci int devnr, i; 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_ci if (!dev_fwnode(dev)) 70962306a36Sopenharmony_ci return NULL; 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_ci pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); 71262306a36Sopenharmony_ci if (!pdata) 71362306a36Sopenharmony_ci return NULL; 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_ci pdata->ext_dc_dc_compenstation_resistor = 71662306a36Sopenharmony_ci device_property_read_bool(dev, "adi,ext-dc-dc-compenstation-resistor"); 71762306a36Sopenharmony_ci 71862306a36Sopenharmony_ci pdata->dc_dc_phase = AD5755_DC_DC_PHASE_ALL_SAME_EDGE; 71962306a36Sopenharmony_ci device_property_read_u32(dev, "adi,dc-dc-phase", &pdata->dc_dc_phase); 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci pdata->dc_dc_freq = AD5755_DC_DC_FREQ_410kHZ; 72262306a36Sopenharmony_ci if (!device_property_read_u32(dev, "adi,dc-dc-freq-hz", &tmp)) { 72362306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(ad5755_dcdc_freq_table); i++) { 72462306a36Sopenharmony_ci if (tmp == ad5755_dcdc_freq_table[i][0]) { 72562306a36Sopenharmony_ci pdata->dc_dc_freq = ad5755_dcdc_freq_table[i][1]; 72662306a36Sopenharmony_ci break; 72762306a36Sopenharmony_ci } 72862306a36Sopenharmony_ci } 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci if (i == ARRAY_SIZE(ad5755_dcdc_freq_table)) 73162306a36Sopenharmony_ci dev_err(dev, 73262306a36Sopenharmony_ci "adi,dc-dc-freq out of range selecting 410kHz\n"); 73362306a36Sopenharmony_ci } 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ci pdata->dc_dc_maxv = AD5755_DC_DC_MAXV_23V; 73662306a36Sopenharmony_ci if (!device_property_read_u32(dev, "adi,dc-dc-max-microvolt", &tmp)) { 73762306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(ad5755_dcdc_maxv_table); i++) { 73862306a36Sopenharmony_ci if (tmp == ad5755_dcdc_maxv_table[i][0]) { 73962306a36Sopenharmony_ci pdata->dc_dc_maxv = ad5755_dcdc_maxv_table[i][1]; 74062306a36Sopenharmony_ci break; 74162306a36Sopenharmony_ci } 74262306a36Sopenharmony_ci } 74362306a36Sopenharmony_ci if (i == ARRAY_SIZE(ad5755_dcdc_maxv_table)) 74462306a36Sopenharmony_ci dev_err(dev, 74562306a36Sopenharmony_ci "adi,dc-dc-maxv out of range selecting 23V\n"); 74662306a36Sopenharmony_ci } 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_ci devnr = 0; 74962306a36Sopenharmony_ci device_for_each_child_node(dev, pp) { 75062306a36Sopenharmony_ci if (devnr >= AD5755_NUM_CHANNELS) { 75162306a36Sopenharmony_ci dev_err(dev, 75262306a36Sopenharmony_ci "There are too many channels defined in DT\n"); 75362306a36Sopenharmony_ci goto error_out; 75462306a36Sopenharmony_ci } 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_ci pdata->dac[devnr].mode = AD5755_MODE_CURRENT_4mA_20mA; 75762306a36Sopenharmony_ci fwnode_property_read_u32(pp, "adi,mode", &pdata->dac[devnr].mode); 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci pdata->dac[devnr].ext_current_sense_resistor = 76062306a36Sopenharmony_ci fwnode_property_read_bool(pp, "adi,ext-current-sense-resistor"); 76162306a36Sopenharmony_ci 76262306a36Sopenharmony_ci pdata->dac[devnr].enable_voltage_overrange = 76362306a36Sopenharmony_ci fwnode_property_read_bool(pp, "adi,enable-voltage-overrange"); 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ci if (!fwnode_property_read_u32_array(pp, "adi,slew", tmparray, 3)) { 76662306a36Sopenharmony_ci pdata->dac[devnr].slew.enable = tmparray[0]; 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_ci pdata->dac[devnr].slew.rate = AD5755_SLEW_RATE_64k; 76962306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(ad5755_slew_rate_table); i++) { 77062306a36Sopenharmony_ci if (tmparray[1] == ad5755_slew_rate_table[i][0]) { 77162306a36Sopenharmony_ci pdata->dac[devnr].slew.rate = 77262306a36Sopenharmony_ci ad5755_slew_rate_table[i][1]; 77362306a36Sopenharmony_ci break; 77462306a36Sopenharmony_ci } 77562306a36Sopenharmony_ci } 77662306a36Sopenharmony_ci if (i == ARRAY_SIZE(ad5755_slew_rate_table)) 77762306a36Sopenharmony_ci dev_err(dev, 77862306a36Sopenharmony_ci "channel %d slew rate out of range selecting 64kHz\n", 77962306a36Sopenharmony_ci devnr); 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_ci pdata->dac[devnr].slew.step_size = AD5755_SLEW_STEP_SIZE_1; 78262306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(ad5755_slew_step_table); i++) { 78362306a36Sopenharmony_ci if (tmparray[2] == ad5755_slew_step_table[i][0]) { 78462306a36Sopenharmony_ci pdata->dac[devnr].slew.step_size = 78562306a36Sopenharmony_ci ad5755_slew_step_table[i][1]; 78662306a36Sopenharmony_ci break; 78762306a36Sopenharmony_ci } 78862306a36Sopenharmony_ci } 78962306a36Sopenharmony_ci if (i == ARRAY_SIZE(ad5755_slew_step_table)) 79062306a36Sopenharmony_ci dev_err(dev, 79162306a36Sopenharmony_ci "channel %d slew step size out of range selecting 1 LSB\n", 79262306a36Sopenharmony_ci devnr); 79362306a36Sopenharmony_ci } else { 79462306a36Sopenharmony_ci pdata->dac[devnr].slew.enable = false; 79562306a36Sopenharmony_ci pdata->dac[devnr].slew.rate = AD5755_SLEW_RATE_64k; 79662306a36Sopenharmony_ci pdata->dac[devnr].slew.step_size = 79762306a36Sopenharmony_ci AD5755_SLEW_STEP_SIZE_1; 79862306a36Sopenharmony_ci } 79962306a36Sopenharmony_ci devnr++; 80062306a36Sopenharmony_ci } 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ci return pdata; 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_ci error_out: 80562306a36Sopenharmony_ci fwnode_handle_put(pp); 80662306a36Sopenharmony_ci devm_kfree(dev, pdata); 80762306a36Sopenharmony_ci return NULL; 80862306a36Sopenharmony_ci} 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_cistatic int ad5755_probe(struct spi_device *spi) 81162306a36Sopenharmony_ci{ 81262306a36Sopenharmony_ci enum ad5755_type type = spi_get_device_id(spi)->driver_data; 81362306a36Sopenharmony_ci const struct ad5755_platform_data *pdata; 81462306a36Sopenharmony_ci struct iio_dev *indio_dev; 81562306a36Sopenharmony_ci struct ad5755_state *st; 81662306a36Sopenharmony_ci int ret; 81762306a36Sopenharmony_ci 81862306a36Sopenharmony_ci indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); 81962306a36Sopenharmony_ci if (indio_dev == NULL) { 82062306a36Sopenharmony_ci dev_err(&spi->dev, "Failed to allocate iio device\n"); 82162306a36Sopenharmony_ci return -ENOMEM; 82262306a36Sopenharmony_ci } 82362306a36Sopenharmony_ci 82462306a36Sopenharmony_ci st = iio_priv(indio_dev); 82562306a36Sopenharmony_ci spi_set_drvdata(spi, indio_dev); 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_ci st->chip_info = &ad5755_chip_info_tbl[type]; 82862306a36Sopenharmony_ci st->spi = spi; 82962306a36Sopenharmony_ci st->pwr_down = 0xf; 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci indio_dev->name = spi_get_device_id(spi)->name; 83262306a36Sopenharmony_ci indio_dev->info = &ad5755_info; 83362306a36Sopenharmony_ci indio_dev->modes = INDIO_DIRECT_MODE; 83462306a36Sopenharmony_ci indio_dev->num_channels = AD5755_NUM_CHANNELS; 83562306a36Sopenharmony_ci 83662306a36Sopenharmony_ci mutex_init(&st->lock); 83762306a36Sopenharmony_ci 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_ci pdata = ad5755_parse_fw(&spi->dev); 84062306a36Sopenharmony_ci if (!pdata) { 84162306a36Sopenharmony_ci dev_warn(&spi->dev, "no firmware provided parameters? using default\n"); 84262306a36Sopenharmony_ci pdata = &ad5755_default_pdata; 84362306a36Sopenharmony_ci } 84462306a36Sopenharmony_ci 84562306a36Sopenharmony_ci ret = ad5755_init_channels(indio_dev, pdata); 84662306a36Sopenharmony_ci if (ret) 84762306a36Sopenharmony_ci return ret; 84862306a36Sopenharmony_ci 84962306a36Sopenharmony_ci ret = ad5755_setup_pdata(indio_dev, pdata); 85062306a36Sopenharmony_ci if (ret) 85162306a36Sopenharmony_ci return ret; 85262306a36Sopenharmony_ci 85362306a36Sopenharmony_ci return devm_iio_device_register(&spi->dev, indio_dev); 85462306a36Sopenharmony_ci} 85562306a36Sopenharmony_ci 85662306a36Sopenharmony_cistatic const struct spi_device_id ad5755_id[] = { 85762306a36Sopenharmony_ci { "ad5755", ID_AD5755 }, 85862306a36Sopenharmony_ci { "ad5755-1", ID_AD5755 }, 85962306a36Sopenharmony_ci { "ad5757", ID_AD5757 }, 86062306a36Sopenharmony_ci { "ad5735", ID_AD5735 }, 86162306a36Sopenharmony_ci { "ad5737", ID_AD5737 }, 86262306a36Sopenharmony_ci {} 86362306a36Sopenharmony_ci}; 86462306a36Sopenharmony_ciMODULE_DEVICE_TABLE(spi, ad5755_id); 86562306a36Sopenharmony_ci 86662306a36Sopenharmony_cistatic const struct of_device_id ad5755_of_match[] = { 86762306a36Sopenharmony_ci { .compatible = "adi,ad5755" }, 86862306a36Sopenharmony_ci { .compatible = "adi,ad5755-1" }, 86962306a36Sopenharmony_ci { .compatible = "adi,ad5757" }, 87062306a36Sopenharmony_ci { .compatible = "adi,ad5735" }, 87162306a36Sopenharmony_ci { .compatible = "adi,ad5737" }, 87262306a36Sopenharmony_ci { } 87362306a36Sopenharmony_ci}; 87462306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, ad5755_of_match); 87562306a36Sopenharmony_ci 87662306a36Sopenharmony_cistatic struct spi_driver ad5755_driver = { 87762306a36Sopenharmony_ci .driver = { 87862306a36Sopenharmony_ci .name = "ad5755", 87962306a36Sopenharmony_ci }, 88062306a36Sopenharmony_ci .probe = ad5755_probe, 88162306a36Sopenharmony_ci .id_table = ad5755_id, 88262306a36Sopenharmony_ci}; 88362306a36Sopenharmony_cimodule_spi_driver(ad5755_driver); 88462306a36Sopenharmony_ci 88562306a36Sopenharmony_ciMODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); 88662306a36Sopenharmony_ciMODULE_DESCRIPTION("Analog Devices AD5755/55-1/57/35/37 DAC"); 88762306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 888