388 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2 /*3 * iio/dac/max5821.c4 * Copyright (C) 2014 Philippe Reynes5 */6 7#include <linux/kernel.h>8#include <linux/module.h>9#include <linux/i2c.h>10#include <linux/iio/iio.h>11#include <linux/regulator/consumer.h>12 13#define MAX5821_MAX_DAC_CHANNELS 214 15/* command bytes */16#define MAX5821_LOAD_DAC_A_IN_REG_B 0x0017#define MAX5821_LOAD_DAC_B_IN_REG_A 0x1018#define MAX5821_EXTENDED_COMMAND_MODE 0xf019#define MAX5821_READ_DAC_A_COMMAND 0xf120#define MAX5821_READ_DAC_B_COMMAND 0xf221 22#define MAX5821_EXTENDED_POWER_UP 0x0023#define MAX5821_EXTENDED_POWER_DOWN_MODE0 0x0124#define MAX5821_EXTENDED_POWER_DOWN_MODE1 0x0225#define MAX5821_EXTENDED_POWER_DOWN_MODE2 0x0326#define MAX5821_EXTENDED_DAC_A 0x0427#define MAX5821_EXTENDED_DAC_B 0x0828 29enum max5821_device_ids {30 ID_MAX5821,31};32 33struct max5821_data {34 struct i2c_client *client;35 struct regulator *vref_reg;36 unsigned short vref_mv;37 bool powerdown[MAX5821_MAX_DAC_CHANNELS];38 u8 powerdown_mode[MAX5821_MAX_DAC_CHANNELS];39 struct mutex lock;40};41 42static const char * const max5821_powerdown_modes[] = {43 "three_state",44 "1kohm_to_gnd",45 "100kohm_to_gnd",46};47 48enum {49 MAX5821_THREE_STATE,50 MAX5821_1KOHM_TO_GND,51 MAX5821_100KOHM_TO_GND52};53 54static int max5821_get_powerdown_mode(struct iio_dev *indio_dev,55 const struct iio_chan_spec *chan)56{57 struct max5821_data *st = iio_priv(indio_dev);58 59 return st->powerdown_mode[chan->channel];60}61 62static int max5821_set_powerdown_mode(struct iio_dev *indio_dev,63 const struct iio_chan_spec *chan,64 unsigned int mode)65{66 struct max5821_data *st = iio_priv(indio_dev);67 68 st->powerdown_mode[chan->channel] = mode;69 70 return 0;71}72 73static const struct iio_enum max5821_powerdown_mode_enum = {74 .items = max5821_powerdown_modes,75 .num_items = ARRAY_SIZE(max5821_powerdown_modes),76 .get = max5821_get_powerdown_mode,77 .set = max5821_set_powerdown_mode,78};79 80static ssize_t max5821_read_dac_powerdown(struct iio_dev *indio_dev,81 uintptr_t private,82 const struct iio_chan_spec *chan,83 char *buf)84{85 struct max5821_data *st = iio_priv(indio_dev);86 87 return sysfs_emit(buf, "%d\n", st->powerdown[chan->channel]);88}89 90static int max5821_sync_powerdown_mode(struct max5821_data *data,91 const struct iio_chan_spec *chan)92{93 u8 outbuf[2];94 95 outbuf[0] = MAX5821_EXTENDED_COMMAND_MODE;96 97 if (chan->channel == 0)98 outbuf[1] = MAX5821_EXTENDED_DAC_A;99 else100 outbuf[1] = MAX5821_EXTENDED_DAC_B;101 102 if (data->powerdown[chan->channel])103 outbuf[1] |= data->powerdown_mode[chan->channel] + 1;104 else105 outbuf[1] |= MAX5821_EXTENDED_POWER_UP;106 107 return i2c_master_send(data->client, outbuf, 2);108}109 110static ssize_t max5821_write_dac_powerdown(struct iio_dev *indio_dev,111 uintptr_t private,112 const struct iio_chan_spec *chan,113 const char *buf, size_t len)114{115 struct max5821_data *data = iio_priv(indio_dev);116 bool powerdown;117 int ret;118 119 ret = kstrtobool(buf, &powerdown);120 if (ret)121 return ret;122 123 data->powerdown[chan->channel] = powerdown;124 125 ret = max5821_sync_powerdown_mode(data, chan);126 if (ret < 0)127 return ret;128 129 return len;130}131 132static const struct iio_chan_spec_ext_info max5821_ext_info[] = {133 {134 .name = "powerdown",135 .read = max5821_read_dac_powerdown,136 .write = max5821_write_dac_powerdown,137 .shared = IIO_SEPARATE,138 },139 IIO_ENUM("powerdown_mode", IIO_SEPARATE, &max5821_powerdown_mode_enum),140 IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &max5821_powerdown_mode_enum),141 { },142};143 144#define MAX5821_CHANNEL(chan) { \145 .type = IIO_VOLTAGE, \146 .indexed = 1, \147 .output = 1, \148 .channel = (chan), \149 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \150 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE), \151 .ext_info = max5821_ext_info, \152}153 154static const struct iio_chan_spec max5821_channels[] = {155 MAX5821_CHANNEL(0),156 MAX5821_CHANNEL(1)157};158 159static const u8 max5821_read_dac_command[] = {160 MAX5821_READ_DAC_A_COMMAND,161 MAX5821_READ_DAC_B_COMMAND162};163 164static const u8 max5821_load_dac_command[] = {165 MAX5821_LOAD_DAC_A_IN_REG_B,166 MAX5821_LOAD_DAC_B_IN_REG_A167};168 169static int max5821_get_value(struct iio_dev *indio_dev,170 int *val, int channel)171{172 struct max5821_data *data = iio_priv(indio_dev);173 struct i2c_client *client = data->client;174 u8 outbuf[1];175 u8 inbuf[2];176 int ret;177 178 if ((channel != 0) && (channel != 1))179 return -EINVAL;180 181 outbuf[0] = max5821_read_dac_command[channel];182 183 mutex_lock(&data->lock);184 185 ret = i2c_master_send(client, outbuf, 1);186 if (ret < 0) {187 mutex_unlock(&data->lock);188 return ret;189 } else if (ret != 1) {190 mutex_unlock(&data->lock);191 return -EIO;192 }193 194 ret = i2c_master_recv(client, inbuf, 2);195 if (ret < 0) {196 mutex_unlock(&data->lock);197 return ret;198 } else if (ret != 2) {199 mutex_unlock(&data->lock);200 return -EIO;201 }202 203 mutex_unlock(&data->lock);204 205 *val = ((inbuf[0] & 0x0f) << 6) | (inbuf[1] >> 2);206 207 return IIO_VAL_INT;208}209 210static int max5821_set_value(struct iio_dev *indio_dev,211 int val, int channel)212{213 struct max5821_data *data = iio_priv(indio_dev);214 struct i2c_client *client = data->client;215 u8 outbuf[2];216 int ret;217 218 if ((val < 0) || (val > 1023))219 return -EINVAL;220 221 if ((channel != 0) && (channel != 1))222 return -EINVAL;223 224 outbuf[0] = max5821_load_dac_command[channel];225 outbuf[0] |= val >> 6;226 outbuf[1] = (val & 0x3f) << 2;227 228 ret = i2c_master_send(client, outbuf, 2);229 if (ret < 0)230 return ret;231 else if (ret != 2)232 return -EIO;233 else234 return 0;235}236 237static int max5821_read_raw(struct iio_dev *indio_dev,238 struct iio_chan_spec const *chan,239 int *val, int *val2, long mask)240{241 struct max5821_data *data = iio_priv(indio_dev);242 243 switch (mask) {244 case IIO_CHAN_INFO_RAW:245 return max5821_get_value(indio_dev, val, chan->channel);246 case IIO_CHAN_INFO_SCALE:247 *val = data->vref_mv;248 *val2 = 10;249 return IIO_VAL_FRACTIONAL_LOG2;250 default:251 return -EINVAL;252 }253}254 255static int max5821_write_raw(struct iio_dev *indio_dev,256 struct iio_chan_spec const *chan,257 int val, int val2, long mask)258{259 if (val2 != 0)260 return -EINVAL;261 262 switch (mask) {263 case IIO_CHAN_INFO_RAW:264 return max5821_set_value(indio_dev, val, chan->channel);265 default:266 return -EINVAL;267 }268}269 270static int max5821_suspend(struct device *dev)271{272 u8 outbuf[2] = { MAX5821_EXTENDED_COMMAND_MODE,273 MAX5821_EXTENDED_DAC_A |274 MAX5821_EXTENDED_DAC_B |275 MAX5821_EXTENDED_POWER_DOWN_MODE2 };276 277 return i2c_master_send(to_i2c_client(dev), outbuf, 2);278}279 280static int max5821_resume(struct device *dev)281{282 u8 outbuf[2] = { MAX5821_EXTENDED_COMMAND_MODE,283 MAX5821_EXTENDED_DAC_A |284 MAX5821_EXTENDED_DAC_B |285 MAX5821_EXTENDED_POWER_UP };286 287 return i2c_master_send(to_i2c_client(dev), outbuf, 2);288}289 290static DEFINE_SIMPLE_DEV_PM_OPS(max5821_pm_ops, max5821_suspend,291 max5821_resume);292 293static const struct iio_info max5821_info = {294 .read_raw = max5821_read_raw,295 .write_raw = max5821_write_raw,296};297 298static void max5821_regulator_disable(void *reg)299{300 regulator_disable(reg);301}302 303static int max5821_probe(struct i2c_client *client)304{305 const struct i2c_device_id *id = i2c_client_get_device_id(client);306 struct max5821_data *data;307 struct iio_dev *indio_dev;308 u32 tmp;309 int ret;310 311 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));312 if (!indio_dev)313 return -ENOMEM;314 data = iio_priv(indio_dev);315 data->client = client;316 mutex_init(&data->lock);317 318 /* max5821 start in powerdown mode 100Kohm to ground */319 for (tmp = 0; tmp < MAX5821_MAX_DAC_CHANNELS; tmp++) {320 data->powerdown[tmp] = true;321 data->powerdown_mode[tmp] = MAX5821_100KOHM_TO_GND;322 }323 324 data->vref_reg = devm_regulator_get(&client->dev, "vref");325 if (IS_ERR(data->vref_reg))326 return dev_err_probe(&client->dev, PTR_ERR(data->vref_reg),327 "Failed to get vref regulator\n");328 329 ret = regulator_enable(data->vref_reg);330 if (ret) {331 dev_err(&client->dev,332 "Failed to enable vref regulator: %d\n", ret);333 return ret;334 }335 336 ret = devm_add_action_or_reset(&client->dev, max5821_regulator_disable,337 data->vref_reg);338 if (ret) {339 dev_err(&client->dev,340 "Failed to add action to managed regulator: %d\n", ret);341 return ret;342 }343 344 ret = regulator_get_voltage(data->vref_reg);345 if (ret < 0) {346 dev_err(&client->dev,347 "Failed to get voltage on regulator: %d\n", ret);348 return ret;349 }350 351 data->vref_mv = ret / 1000;352 353 indio_dev->name = id->name;354 indio_dev->num_channels = ARRAY_SIZE(max5821_channels);355 indio_dev->channels = max5821_channels;356 indio_dev->modes = INDIO_DIRECT_MODE;357 indio_dev->info = &max5821_info;358 359 return devm_iio_device_register(&client->dev, indio_dev);360}361 362static const struct i2c_device_id max5821_id[] = {363 { "max5821", ID_MAX5821 },364 { }365};366MODULE_DEVICE_TABLE(i2c, max5821_id);367 368static const struct of_device_id max5821_of_match[] = {369 { .compatible = "maxim,max5821" },370 { }371};372MODULE_DEVICE_TABLE(of, max5821_of_match);373 374static struct i2c_driver max5821_driver = {375 .driver = {376 .name = "max5821",377 .of_match_table = max5821_of_match,378 .pm = pm_sleep_ptr(&max5821_pm_ops),379 },380 .probe = max5821_probe,381 .id_table = max5821_id,382};383module_i2c_driver(max5821_driver);384 385MODULE_AUTHOR("Philippe Reynes <tremyfr@yahoo.fr>");386MODULE_DESCRIPTION("MAX5821 DAC");387MODULE_LICENSE("GPL v2");388