// SPDX-License-Identifier: GPL-2.0-only
/*
* AD5024, AD5025, AD5044, AD5045, AD5064, AD5064-1, AD5065, AD5625, AD5625R,
* AD5627, AD5627R, AD5628, AD5629R, AD5645R, AD5647R, AD5648, AD5665, AD5665R,
* AD5666, AD5667, AD5667R, AD5668, AD5669R, LTC2606, LTC2607, LTC2609, LTC2616,
* LTC2617, LTC2619, LTC2626, LTC2627, LTC2629, LTC2631, LTC2633, LTC2635
* Digital to analog converters driver
*
* Copyright 2011 Analog Devices Inc.
*/
#include <linux/device.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/regulator/consumer.h>
#include <asm/unaligned.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#define AD5064_MAX_DAC_CHANNELS 8
#define AD5064_MAX_VREFS 4
#define AD5064_ADDR(x) ((x) << 20)
#define AD5064_CMD(x) ((x) << 24)
#define AD5064_ADDR_ALL_DAC 0xF
#define AD5064_CMD_WRITE_INPUT_N 0x0
#define AD5064_CMD_UPDATE_DAC_N 0x1
#define AD5064_CMD_WRITE_INPUT_N_UPDATE_ALL 0x2
#define AD5064_CMD_WRITE_INPUT_N_UPDATE_N 0x3
#define AD5064_CMD_POWERDOWN_DAC 0x4
#define AD5064_CMD_CLEAR 0x5
#define AD5064_CMD_LDAC_MASK 0x6
#define AD5064_CMD_RESET 0x7
#define AD5064_CMD_CONFIG 0x8
#define AD5064_CMD_RESET_V2 0x5
#define AD5064_CMD_CONFIG_V2 0x7
#define AD5064_CONFIG_DAISY_CHAIN_ENABLE BIT(1)
#define AD5064_CONFIG_INT_VREF_ENABLE BIT(0)
#define AD5064_LDAC_PWRDN_NONE 0x0
#define AD5064_LDAC_PWRDN_1K 0x1
#define AD5064_LDAC_PWRDN_100K 0x2
#define AD5064_LDAC_PWRDN_3STATE 0x3
/**
* enum ad5064_regmap_type - Register layout variant
* @AD5064_REGMAP_ADI: Old Analog Devices register map layout
* @AD5064_REGMAP_ADI2: New Analog Devices register map layout
* @AD5064_REGMAP_LTC: LTC register map layout
*/
enum ad5064_regmap_type {
AD5064_REGMAP_ADI,
AD5064_REGMAP_ADI2,
AD5064_REGMAP_LTC,
};
/**
* struct ad5064_chip_info - chip specific information
* @shared_vref: whether the vref supply is shared between channels
* @internal_vref: internal reference voltage. 0 if the chip has no
internal vref.
* @channel: channel specification
* @num_channels: number of channels
* @regmap_type: register map layout variant
*/
struct ad5064_chip_info {
bool shared_vref;
unsigned long internal_vref;
const struct iio_chan_spec *channels;
unsigned int num_channels;
enum ad5064_regmap_type regmap_type;
};
struct ad5064_state;
typedef int (*ad5064_write_func)(struct ad5064_state *st, unsigned int cmd,
unsigned int addr, unsigned int val);
/**
* struct ad5064_state - driver instance specific data
* @dev: the device for this driver instance
* @chip_info: chip model specific constants, available modes etc
* @vref_reg: vref supply regulators
* @pwr_down: whether channel is powered down
* @pwr_down_mode: channel's current power down mode
* @dac_cache: current DAC raw value (chip does not support readback)
* @use_internal_vref: set to true if the internal reference voltage should be
* used.
* @write: register write callback
* @data: i2c/spi transfer buffers
*/
struct ad5064_state {
struct device *dev;
const struct ad5064_chip_info *chip_info;
struct regulator_bulk_data vref_reg[AD5064_MAX_VREFS];
bool pwr_down[AD5064_MAX_DAC_CHANNELS];
u8 pwr_down_mode[AD5064_MAX_DAC_CHANNELS];
unsigned int dac_cache[AD5064_MAX_DAC_CHANNELS];
bool use_internal_vref;
ad5064_write_func write;
/* Lock used to maintain consistency between cached and dev state */
struct mutex lock;
/*
* DMA (thus cache coherency maintenance) requires the
* transfer buffers to live in their own cache lines.
*/
union {
u8 i2c[3];
__be32 spi;
} data ____cacheline_aligned;
};
enum ad5064_type {
ID_AD5024,
ID_AD5025,
ID_AD5044,
ID_AD5045,
ID_AD5064,
ID_AD5064_1,
ID_AD5065,
ID_AD5625,
ID_AD5625R_1V25,
ID_AD5625R_2V5,
ID_AD5627,
ID_AD5627R_1V25,
ID_AD5627R_2V5,
ID_AD5628_1,
ID_AD5628_2,
ID_AD5629_1,
ID_AD5629_2,
ID_AD5645R_1V25,
ID_AD5645R_2V5,
ID_AD5647R_1V25,
ID_AD5647R_2V5,
ID_AD5648_1,
ID_AD5648_2,
ID_AD5665,
ID_AD5665R_1V25,
ID_AD5665R_2V5,
ID_AD5666_1,
ID_AD5666_2,
ID_AD5667,
ID_AD5667R_1V25,
ID_AD5667R_2V5,
ID_AD5668_1,
ID_AD5668_2,
ID_AD5669_1,
ID_AD5669_2,
ID_LTC2606,
ID_LTC2607,
ID_LTC2609,
ID_LTC2616,
ID_LTC2617,
ID_LTC2619,
ID_LTC2626,
ID_LTC2627,
ID_LTC2629,
ID_LTC2631_L12,
ID_LTC2631_H12,
ID_LTC2631_L10,
ID_LTC2631_H10,
ID_LTC2631_L8,
ID_LTC2631_H8,
ID_LTC2633_L12,
ID_LTC2633_H12,
ID_LTC2633_L10,
ID_LTC2633_H10,
ID_LTC2633_L8,
ID_LTC2633_H8,
ID_LTC2635_L12,
ID_LTC2635_H12,
ID_LTC2635_L10,
ID_LTC2635_H10,
ID_LTC2635_L8,
ID_LTC2635_H8,
};
static int ad5064_write(struct ad5064_state *st, unsigned int cmd,
unsigned int addr, unsigned int val, unsigned int shift)
{
val <<= shift;
return st->write(st, cmd, addr, val);
}
static int ad5064_sync_powerdown_mode(