1/* 2 * AD5624R, AD5644R, AD5664R Digital to analog convertors spi driver 3 * 4 * Copyright 2010-2011 Analog Devices Inc. 5 * 6 * Licensed under the GPL-2. 7 */ 8 9#include <linux/interrupt.h> 10#include <linux/fs.h> 11#include <linux/device.h> 12#include <linux/kernel.h> 13#include <linux/spi/spi.h> 14#include <linux/slab.h> 15#include <linux/sysfs.h> 16#include <linux/regulator/consumer.h> 17#include <linux/module.h> 18 19#include <linux/iio/iio.h> 20#include <linux/iio/sysfs.h> 21 22#include "ad5624r.h" 23 24static int ad5624r_spi_write(struct spi_device *spi, 25 u8 cmd, u8 addr, u16 val, u8 shift) 26{ 27 u32 data; 28 u8 msg[3]; 29 30 /* 31 * The input shift register is 24 bits wide. The first two bits are 32 * don't care bits. The next three are the command bits, C2 to C0, 33 * followed by the 3-bit DAC address, A2 to A0, and then the 34 * 16-, 14-, 12-bit data-word. The data-word comprises the 16-, 35 * 14-, 12-bit input code followed by 0, 2, or 4 don't care bits, 36 * for the AD5664R, AD5644R, and AD5624R, respectively. 37 */ 38 data = (0 << 22) | (cmd << 19) | (addr << 16) | (val << shift); 39 msg[0] = data >> 16; 40 msg[1] = data >> 8; 41 msg[2] = data; 42 43 return spi_write(spi, msg, 3); 44} 45 46static int ad5624r_read_raw(struct iio_dev *indio_dev, 47 struct iio_chan_spec const *chan, 48 int *val, 49 int *val2, 50 long m) 51{ 52 struct ad5624r_state *st = iio_priv(indio_dev); 53 54 switch (m) { 55 case IIO_CHAN_INFO_SCALE: 56 *val = st->vref_mv; 57 *val2 = chan->scan_type.realbits; 58 return IIO_VAL_FRACTIONAL_LOG2; 59 } 60 return -EINVAL; 61} 62 63static int ad5624r_write_raw(struct iio_dev *indio_dev, 64 struct iio_chan_spec const *chan, 65 int val, 66 int val2, 67 long mask) 68{ 69 struct ad5624r_state *st = iio_priv(indio_dev); 70 71 switch (mask) { 72 case IIO_CHAN_INFO_RAW: 73 if (val >= (1 << chan->scan_type.realbits) || val < 0) 74 return -EINVAL; 75 76 return ad5624r_spi_write(st->us, 77 AD5624R_CMD_WRITE_INPUT_N_UPDATE_N, 78 chan->address, val, 79 chan->scan_type.shift); 80 default: 81 return -EINVAL; 82 } 83} 84 85static const char * const ad5624r_powerdown_modes[] = { 86 "1kohm_to_gnd", 87 "100kohm_to_gnd", 88 "three_state" 89}; 90 91static int ad5624r_get_powerdown_mode(struct iio_dev *indio_dev, 92 const struct iio_chan_spec *chan) 93{ 94 struct ad5624r_state *st = iio_priv(indio_dev); 95 96 return st->pwr_down_mode; 97} 98 99static int ad5624r_set_powerdown_mode(struct iio_dev *indio_dev, 100 const struct iio_chan_spec *chan, unsigned int mode) 101{ 102 struct ad5624r_state *st = iio_priv(indio_dev); 103 104 st->pwr_down_mode = mode; 105 106 return 0; 107} 108 109static const struct iio_enum ad5624r_powerdown_mode_enum = { 110 .items = ad5624r_powerdown_modes, 111 .num_items = ARRAY_SIZE(ad5624r_powerdown_modes), 112 .get = ad5624r_get_powerdown_mode, 113 .set = ad5624r_set_powerdown_mode, 114}; 115 116static ssize_t ad5624r_read_dac_powerdown(struct iio_dev *indio_dev, 117 uintptr_t private, const struct iio_chan_spec *chan, char *buf) 118{ 119 struct ad5624r_state *st = iio_priv(indio_dev); 120 121 return sprintf(buf, "%d\n", 122 !!(st->pwr_down_mask & (1 << chan->channel))); 123} 124 125static ssize_t ad5624r_write_dac_powerdown(struct iio_dev *indio_dev, 126 uintptr_t private, const struct iio_chan_spec *chan, const char *buf, 127 size_t len) 128{ 129 bool pwr_down; 130 int ret; 131 struct ad5624r_state *st = iio_priv(indio_dev); 132 133 ret = strtobool(buf, &pwr_down); 134 if (ret) 135 return ret; 136 137 if (pwr_down) 138 st->pwr_down_mask |= (1 << chan->channel); 139 else 140 st->pwr_down_mask &= ~(1 << chan->channel); 141 142 ret = ad5624r_spi_write(st->us, AD5624R_CMD_POWERDOWN_DAC, 0, 143 (st->pwr_down_mode << 4) | 144 st->pwr_down_mask, 16); 145 146 return ret ? ret : len; 147} 148 149static const struct iio_info ad5624r_info = { 150 .write_raw = ad5624r_write_raw, 151 .read_raw = ad5624r_read_raw, 152 .driver_module = THIS_MODULE, 153}; 154 155static const struct iio_chan_spec_ext_info ad5624r_ext_info[] = { 156 { 157 .name = "powerdown", 158 .read = ad5624r_read_dac_powerdown, 159 .write = ad5624r_write_dac_powerdown, 160 .shared = IIO_SEPARATE, 161 }, 162 IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE, 163 &ad5624r_powerdown_mode_enum), 164 IIO_ENUM_AVAILABLE("powerdown_mode", &ad5624r_powerdown_mode_enum), 165 { }, 166}; 167 168#define AD5624R_CHANNEL(_chan, _bits) { \ 169 .type = IIO_VOLTAGE, \ 170 .indexed = 1, \ 171 .output = 1, \ 172 .channel = (_chan), \ 173 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 174 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 175 .address = (_chan), \ 176 .scan_type = { \ 177 .sign = 'u', \ 178 .realbits = (_bits), \ 179 .storagebits = 16, \ 180 .shift = 16 - (_bits), \ 181 }, \ 182 .ext_info = ad5624r_ext_info, \ 183} 184 185#define DECLARE_AD5624R_CHANNELS(_name, _bits) \ 186 const struct iio_chan_spec _name##_channels[] = { \ 187 AD5624R_CHANNEL(0, _bits), \ 188 AD5624R_CHANNEL(1, _bits), \ 189 AD5624R_CHANNEL(2, _bits), \ 190 AD5624R_CHANNEL(3, _bits), \ 191} 192 193static DECLARE_AD5624R_CHANNELS(ad5624r, 12); 194static DECLARE_AD5624R_CHANNELS(ad5644r, 14); 195static DECLARE_AD5624R_CHANNELS(ad5664r, 16); 196 197static const struct ad5624r_chip_info ad5624r_chip_info_tbl[] = { 198 [ID_AD5624R3] = { 199 .channels = ad5624r_channels, 200 .int_vref_mv = 1250, 201 }, 202 [ID_AD5624R5] = { 203 .channels = ad5624r_channels, 204 .int_vref_mv = 2500, 205 }, 206 [ID_AD5644R3] = { 207 .channels = ad5644r_channels, 208 .int_vref_mv = 1250, 209 }, 210 [ID_AD5644R5] = { 211 .channels = ad5644r_channels, 212 .int_vref_mv = 2500, 213 }, 214 [ID_AD5664R3] = { 215 .channels = ad5664r_channels, 216 .int_vref_mv = 1250, 217 }, 218 [ID_AD5664R5] = { 219 .channels = ad5664r_channels, 220 .int_vref_mv = 2500, 221 }, 222}; 223 224static int ad5624r_probe(struct spi_device *spi) 225{ 226 struct ad5624r_state *st; 227 struct iio_dev *indio_dev; 228 int ret, voltage_uv = 0; 229 230 indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); 231 if (!indio_dev) 232 return -ENOMEM; 233 st = iio_priv(indio_dev); 234 st->reg = devm_regulator_get(&spi->dev, "vcc"); 235 if (!IS_ERR(st->reg)) { 236 ret = regulator_enable(st->reg); 237 if (ret) 238 return ret; 239 240 ret = regulator_get_voltage(st->reg); 241 if (ret < 0) 242 goto error_disable_reg; 243 244 voltage_uv = ret; 245 } 246 247 spi_set_drvdata(spi, indio_dev); 248 st->chip_info = 249 &ad5624r_chip_info_tbl[spi_get_device_id(spi)->driver_data]; 250 251 if (voltage_uv) 252 st->vref_mv = voltage_uv / 1000; 253 else 254 st->vref_mv = st->chip_info->int_vref_mv; 255 256 st->us = spi; 257 258 indio_dev->dev.parent = &spi->dev; 259 indio_dev->name = spi_get_device_id(spi)->name; 260 indio_dev->info = &ad5624r_info; 261 indio_dev->modes = INDIO_DIRECT_MODE; 262 indio_dev->channels = st->chip_info->channels; 263 indio_dev->num_channels = AD5624R_DAC_CHANNELS; 264 265 ret = ad5624r_spi_write(spi, AD5624R_CMD_INTERNAL_REFER_SETUP, 0, 266 !!voltage_uv, 16); 267 if (ret) 268 goto error_disable_reg; 269 270 ret = iio_device_register(indio_dev); 271 if (ret) 272 goto error_disable_reg; 273 274 return 0; 275 276error_disable_reg: 277 if (!IS_ERR(st->reg)) 278 regulator_disable(st->reg); 279 280 return ret; 281} 282 283static int ad5624r_remove(struct spi_device *spi) 284{ 285 struct iio_dev *indio_dev = spi_get_drvdata(spi); 286 struct ad5624r_state *st = iio_priv(indio_dev); 287 288 iio_device_unregister(indio_dev); 289 if (!IS_ERR(st->reg)) 290 regulator_disable(st->reg); 291 292 return 0; 293} 294 295static const struct spi_device_id ad5624r_id[] = { 296 {"ad5624r3", ID_AD5624R3}, 297 {"ad5644r3", ID_AD5644R3}, 298 {"ad5664r3", ID_AD5664R3}, 299 {"ad5624r5", ID_AD5624R5}, 300 {"ad5644r5", ID_AD5644R5}, 301 {"ad5664r5", ID_AD5664R5}, 302 {} 303}; 304MODULE_DEVICE_TABLE(spi, ad5624r_id); 305 306static struct spi_driver ad5624r_driver = { 307 .driver = { 308 .name = "ad5624r", 309 }, 310 .probe = ad5624r_probe, 311 .remove = ad5624r_remove, 312 .id_table = ad5624r_id, 313}; 314module_spi_driver(ad5624r_driver); 315 316MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); 317MODULE_DESCRIPTION("Analog Devices AD5624/44/64R DAC spi driver"); 318MODULE_LICENSE("GPL v2"); 319