600 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Support for Microchip MCP47284 *5 * Copyright (C) 2023 Andrea Collamati <andrea.collamati@gmail.com>6 *7 * Based on mcp4725 by Peter Meerwald <pmeerw@pmeerw.net>8 *9 * Driver for the Microchip I2C 12-bit digital-to-analog quad channels10 * converter (DAC).11 *12 * (7-bit I2C slave address 0x60, the three LSBs can be configured in13 * hardware)14 */15 16#include <linux/bitfield.h>17#include <linux/delay.h>18#include <linux/err.h>19#include <linux/i2c.h>20#include <linux/iio/iio.h>21#include <linux/iio/sysfs.h>22#include <linux/module.h>23#include <linux/mod_devicetable.h>24#include <linux/property.h>25#include <linux/regulator/consumer.h>26 27#define MCP4728_RESOLUTION 1228#define MCP4728_N_CHANNELS 429 30#define MCP4728_CMD_MASK GENMASK(7, 3)31#define MCP4728_CHSEL_MASK GENMASK(2, 1)32#define MCP4728_UDAC_MASK BIT(0)33 34#define MCP4728_VREF_MASK BIT(7)35#define MCP4728_PDMODE_MASK GENMASK(6, 5)36#define MCP4728_GAIN_MASK BIT(4)37 38#define MCP4728_DAC_H_MASK GENMASK(3, 0)39#define MCP4728_DAC_L_MASK GENMASK(7, 0)40 41#define MCP4728_RDY_MASK BIT(7)42 43#define MCP4728_MW_CMD 0x08 /* Multiwrite Command */44#define MCP4728_SW_CMD 0x0A /* Sequential Write Command with EEPROM */45 46#define MCP4728_READ_RESPONSE_LEN (MCP4728_N_CHANNELS * 3 * 2)47#define MCP4728_WRITE_EEPROM_LEN (1 + MCP4728_N_CHANNELS * 2)48 49enum vref_mode {50 MCP4728_VREF_EXTERNAL_VDD = 0,51 MCP4728_VREF_INTERNAL_2048mV = 1,52};53 54enum gain_mode {55 MCP4728_GAIN_X1 = 0,56 MCP4728_GAIN_X2 = 1,57};58 59enum iio_powerdown_mode {60 MCP4728_IIO_1K,61 MCP4728_IIO_100K,62 MCP4728_IIO_500K,63};64 65struct mcp4728_channel_data {66 enum vref_mode ref_mode;67 enum iio_powerdown_mode pd_mode;68 enum gain_mode g_mode;69 u16 dac_value;70};71 72/* MCP4728 Full Scale Ranges73 * the device available ranges are74 * - VREF = VDD FSR = from 0.0V to VDD75 * - VREF = Internal Gain = 1 FSR = from 0.0V to VREF76 * - VREF = Internal Gain = 2 FSR = from 0.0V to 2*VREF77 */78enum mcp4728_scale {79 MCP4728_SCALE_VDD,80 MCP4728_SCALE_VINT_NO_GAIN,81 MCP4728_SCALE_VINT_GAIN_X2,82 MCP4728_N_SCALES83};84 85struct mcp4728_data {86 struct i2c_client *client;87 bool powerdown;88 int scales_avail[MCP4728_N_SCALES * 2];89 struct mcp4728_channel_data chdata[MCP4728_N_CHANNELS];90};91 92#define MCP4728_CHAN(chan) { \93 .type = IIO_VOLTAGE, \94 .output = 1, \95 .indexed = 1, \96 .channel = chan, \97 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \98 BIT(IIO_CHAN_INFO_SCALE), \99 .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SCALE), \100 .ext_info = mcp4728_ext_info, \101}102 103static int mcp4728_suspend(struct device *dev);104static int mcp4728_resume(struct device *dev);105 106static ssize_t mcp4728_store_eeprom(struct device *dev,107 struct device_attribute *attr,108 const char *buf, size_t len)109{110 struct iio_dev *indio_dev = dev_to_iio_dev(dev);111 struct mcp4728_data *data = iio_priv(indio_dev);112 u8 outbuf[MCP4728_WRITE_EEPROM_LEN];113 int tries = 20;114 u8 inbuf[3];115 bool state;116 int ret;117 unsigned int i;118 119 ret = kstrtobool(buf, &state);120 if (ret < 0)121 return ret;122 123 if (!state)124 return 0;125 126 outbuf[0] = FIELD_PREP(MCP4728_CMD_MASK, MCP4728_SW_CMD);127 128 for (i = 0; i < MCP4728_N_CHANNELS; i++) {129 struct mcp4728_channel_data *ch = &data->chdata[i];130 int offset = 1 + i * 2;131 132 outbuf[offset] = FIELD_PREP(MCP4728_VREF_MASK, ch->ref_mode);133 134 if (data->powerdown) {135 u8 mcp4728_pd_mode = ch->pd_mode + 1;136 137 outbuf[offset] |= FIELD_PREP(MCP4728_PDMODE_MASK,138 mcp4728_pd_mode);139 }140 141 outbuf[offset] |= FIELD_PREP(MCP4728_GAIN_MASK, ch->g_mode);142 outbuf[offset] |=143 FIELD_PREP(MCP4728_DAC_H_MASK, ch->dac_value >> 8);144 outbuf[offset + 1] =145 FIELD_PREP(MCP4728_DAC_L_MASK, ch->dac_value);146 }147 148 ret = i2c_master_send(data->client, outbuf, MCP4728_WRITE_EEPROM_LEN);149 if (ret < 0)150 return ret;151 else if (ret != MCP4728_WRITE_EEPROM_LEN)152 return -EIO;153 154 /* wait RDY signal for write complete, takes up to 50ms */155 while (tries--) {156 msleep(20);157 ret = i2c_master_recv(data->client, inbuf, 3);158 if (ret < 0)159 return ret;160 else if (ret != 3)161 return -EIO;162 163 if (FIELD_GET(MCP4728_RDY_MASK, inbuf[0]))164 break;165 }166 167 if (tries < 0) {168 dev_err(&data->client->dev, "%s failed, incomplete\n",169 __func__);170 return -EIO;171 }172 return len;173}174 175static IIO_DEVICE_ATTR(store_eeprom, 0200, NULL, mcp4728_store_eeprom, 0);176 177static struct attribute *mcp4728_attributes[] = {178 &iio_dev_attr_store_eeprom.dev_attr.attr,179 NULL,180};181 182static const struct attribute_group mcp4728_attribute_group = {183 .attrs = mcp4728_attributes,184};185 186static int mcp4728_program_channel_cfg(int channel, struct iio_dev *indio_dev)187{188 struct mcp4728_data *data = iio_priv(indio_dev);189 struct mcp4728_channel_data *ch = &data->chdata[channel];190 u8 outbuf[3];191 int ret;192 193 outbuf[0] = FIELD_PREP(MCP4728_CMD_MASK, MCP4728_MW_CMD);194 outbuf[0] |= FIELD_PREP(MCP4728_CHSEL_MASK, channel);195 outbuf[0] |= FIELD_PREP(MCP4728_UDAC_MASK, 0);196 197 outbuf[1] = FIELD_PREP(MCP4728_VREF_MASK, ch->ref_mode);198 199 if (data->powerdown)200 outbuf[1] |= FIELD_PREP(MCP4728_PDMODE_MASK, ch->pd_mode + 1);201 202 outbuf[1] |= FIELD_PREP(MCP4728_GAIN_MASK, ch->g_mode);203 outbuf[1] |= FIELD_PREP(MCP4728_DAC_H_MASK, ch->dac_value >> 8);204 outbuf[2] = FIELD_PREP(MCP4728_DAC_L_MASK, ch->dac_value);205 206 ret = i2c_master_send(data->client, outbuf, 3);207 if (ret < 0)208 return ret;209 else if (ret != 3)210 return -EIO;211 212 return 0;213}214 215static const char *const mcp4728_powerdown_modes[] = { "1kohm_to_gnd",216 "100kohm_to_gnd",217 "500kohm_to_gnd" };218 219static int mcp4728_get_powerdown_mode(struct iio_dev *indio_dev,220 const struct iio_chan_spec *chan)221{222 struct mcp4728_data *data = iio_priv(indio_dev);223 224 return data->chdata[chan->channel].pd_mode;225}226 227static int mcp4728_set_powerdown_mode(struct iio_dev *indio_dev,228 const struct iio_chan_spec *chan,229 unsigned int mode)230{231 struct mcp4728_data *data = iio_priv(indio_dev);232 233 data->chdata[chan->channel].pd_mode = mode;234 235 return 0;236}237 238static ssize_t mcp4728_read_powerdown(struct iio_dev *indio_dev,239 uintptr_t private,240 const struct iio_chan_spec *chan,241 char *buf)242{243 struct mcp4728_data *data = iio_priv(indio_dev);244 245 return sysfs_emit(buf, "%d\n", data->powerdown);246}247 248static ssize_t mcp4728_write_powerdown(struct iio_dev *indio_dev,249 uintptr_t private,250 const struct iio_chan_spec *chan,251 const char *buf, size_t len)252{253 struct mcp4728_data *data = iio_priv(indio_dev);254 bool state;255 int ret;256 257 ret = kstrtobool(buf, &state);258 if (ret)259 return ret;260 261 if (state)262 ret = mcp4728_suspend(&data->client->dev);263 else264 ret = mcp4728_resume(&data->client->dev);265 266 if (ret < 0)267 return ret;268 269 return len;270}271 272static const struct iio_enum mcp4728_powerdown_mode_enum = {273 .items = mcp4728_powerdown_modes,274 .num_items = ARRAY_SIZE(mcp4728_powerdown_modes),275 .get = mcp4728_get_powerdown_mode,276 .set = mcp4728_set_powerdown_mode,277};278 279static const struct iio_chan_spec_ext_info mcp4728_ext_info[] = {280 {281 .name = "powerdown",282 .read = mcp4728_read_powerdown,283 .write = mcp4728_write_powerdown,284 .shared = IIO_SEPARATE,285 },286 IIO_ENUM("powerdown_mode", IIO_SEPARATE, &mcp4728_powerdown_mode_enum),287 IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE,288 &mcp4728_powerdown_mode_enum),289 {},290};291 292static const struct iio_chan_spec mcp4728_channels[MCP4728_N_CHANNELS] = {293 MCP4728_CHAN(0),294 MCP4728_CHAN(1),295 MCP4728_CHAN(2),296 MCP4728_CHAN(3),297};298 299static void mcp4728_get_scale_avail(enum mcp4728_scale scale,300 struct mcp4728_data *data, int *val,301 int *val2)302{303 *val = data->scales_avail[scale * 2];304 *val2 = data->scales_avail[scale * 2 + 1];305}306 307static void mcp4728_get_scale(int channel, struct mcp4728_data *data, int *val,308 int *val2)309{310 int ref_mode = data->chdata[channel].ref_mode;311 int g_mode = data->chdata[channel].g_mode;312 313 if (ref_mode == MCP4728_VREF_EXTERNAL_VDD) {314 mcp4728_get_scale_avail(MCP4728_SCALE_VDD, data, val, val2);315 } else {316 if (g_mode == MCP4728_GAIN_X1) {317 mcp4728_get_scale_avail(MCP4728_SCALE_VINT_NO_GAIN,318 data, val, val2);319 } else {320 mcp4728_get_scale_avail(MCP4728_SCALE_VINT_GAIN_X2,321 data, val, val2);322 }323 }324}325 326static int mcp4728_find_matching_scale(struct mcp4728_data *data, int val,327 int val2)328{329 for (int i = 0; i < MCP4728_N_SCALES; i++) {330 if (data->scales_avail[i * 2] == val &&331 data->scales_avail[i * 2 + 1] == val2)332 return i;333 }334 return -EINVAL;335}336 337static int mcp4728_set_scale(int channel, struct mcp4728_data *data, int val,338 int val2)339{340 int scale = mcp4728_find_matching_scale(data, val, val2);341 342 if (scale < 0)343 return scale;344 345 switch (scale) {346 case MCP4728_SCALE_VDD:347 data->chdata[channel].ref_mode = MCP4728_VREF_EXTERNAL_VDD;348 return 0;349 case MCP4728_SCALE_VINT_NO_GAIN:350 data->chdata[channel].ref_mode = MCP4728_VREF_INTERNAL_2048mV;351 data->chdata[channel].g_mode = MCP4728_GAIN_X1;352 return 0;353 case MCP4728_SCALE_VINT_GAIN_X2:354 data->chdata[channel].ref_mode = MCP4728_VREF_INTERNAL_2048mV;355 data->chdata[channel].g_mode = MCP4728_GAIN_X2;356 return 0;357 default:358 return -EINVAL;359 }360}361 362static int mcp4728_read_raw(struct iio_dev *indio_dev,363 struct iio_chan_spec const *chan, int *val,364 int *val2, long mask)365{366 struct mcp4728_data *data = iio_priv(indio_dev);367 368 switch (mask) {369 case IIO_CHAN_INFO_RAW:370 *val = data->chdata[chan->channel].dac_value;371 return IIO_VAL_INT;372 case IIO_CHAN_INFO_SCALE:373 mcp4728_get_scale(chan->channel, data, val, val2);374 return IIO_VAL_INT_PLUS_MICRO;375 }376 return -EINVAL;377}378 379static int mcp4728_write_raw(struct iio_dev *indio_dev,380 struct iio_chan_spec const *chan, int val,381 int val2, long mask)382{383 struct mcp4728_data *data = iio_priv(indio_dev);384 int ret;385 386 switch (mask) {387 case IIO_CHAN_INFO_RAW:388 if (val < 0 || val > GENMASK(MCP4728_RESOLUTION - 1, 0))389 return -EINVAL;390 data->chdata[chan->channel].dac_value = val;391 return mcp4728_program_channel_cfg(chan->channel, indio_dev);392 case IIO_CHAN_INFO_SCALE:393 ret = mcp4728_set_scale(chan->channel, data, val, val2);394 if (ret)395 return ret;396 397 return mcp4728_program_channel_cfg(chan->channel, indio_dev);398 default:399 return -EINVAL;400 }401}402 403static void mcp4728_init_scale_avail(enum mcp4728_scale scale, int vref_mv,404 struct mcp4728_data *data)405{406 s64 tmp;407 int value_micro;408 int value_int;409 410 tmp = (s64)vref_mv * 1000000LL >> MCP4728_RESOLUTION;411 value_int = div_s64_rem(tmp, 1000000LL, &value_micro);412 413 data->scales_avail[scale * 2] = value_int;414 data->scales_avail[scale * 2 + 1] = value_micro;415}416 417static int mcp4728_init_scales_avail(struct mcp4728_data *data, int vdd_mv)418{419 mcp4728_init_scale_avail(MCP4728_SCALE_VDD, vdd_mv, data);420 mcp4728_init_scale_avail(MCP4728_SCALE_VINT_NO_GAIN, 2048, data);421 mcp4728_init_scale_avail(MCP4728_SCALE_VINT_GAIN_X2, 4096, data);422 423 return 0;424}425 426static int mcp4728_read_avail(struct iio_dev *indio_dev,427 struct iio_chan_spec const *chan,428 const int **vals, int *type, int *length,429 long info)430{431 struct mcp4728_data *data = iio_priv(indio_dev);432 433 switch (info) {434 case IIO_CHAN_INFO_SCALE:435 *type = IIO_VAL_INT_PLUS_MICRO;436 437 switch (chan->type) {438 case IIO_VOLTAGE:439 *vals = data->scales_avail;440 *length = MCP4728_N_SCALES * 2;441 return IIO_AVAIL_LIST;442 default:443 return -EINVAL;444 }445 default:446 return -EINVAL;447 }448}449 450static const struct iio_info mcp4728_info = {451 .read_raw = mcp4728_read_raw,452 .write_raw = mcp4728_write_raw,453 .read_avail = &mcp4728_read_avail,454 .attrs = &mcp4728_attribute_group,455};456 457static int mcp4728_suspend(struct device *dev)458{459 struct iio_dev *indio_dev = dev_get_drvdata(dev);460 struct mcp4728_data *data = iio_priv(indio_dev);461 unsigned int i;462 463 data->powerdown = true;464 465 for (i = 0; i < MCP4728_N_CHANNELS; i++) {466 int err = mcp4728_program_channel_cfg(i, indio_dev);467 468 if (err)469 return err;470 }471 return 0;472}473 474static int mcp4728_resume(struct device *dev)475{476 struct iio_dev *indio_dev = dev_get_drvdata(dev);477 struct mcp4728_data *data = iio_priv(indio_dev);478 int err = 0;479 unsigned int i;480 481 data->powerdown = false;482 483 for (i = 0; i < MCP4728_N_CHANNELS; i++) {484 int ret = mcp4728_program_channel_cfg(i, indio_dev);485 486 if (ret)487 err = ret;488 }489 return err;490}491 492static DEFINE_SIMPLE_DEV_PM_OPS(mcp4728_pm_ops, mcp4728_suspend,493 mcp4728_resume);494 495static int mcp4728_init_channels_data(struct mcp4728_data *data)496{497 u8 inbuf[MCP4728_READ_RESPONSE_LEN];498 int ret;499 unsigned int i;500 501 ret = i2c_master_recv(data->client, inbuf, MCP4728_READ_RESPONSE_LEN);502 if (ret < 0) {503 return dev_err_probe(&data->client->dev, ret,504 "failed to read mcp4728 conf.\n");505 } else if (ret != MCP4728_READ_RESPONSE_LEN) {506 return dev_err_probe(&data->client->dev, -EIO,507 "failed to read mcp4728 conf. Wrong Response Len ret=%d\n",508 ret);509 }510 511 for (i = 0; i < MCP4728_N_CHANNELS; i++) {512 struct mcp4728_channel_data *ch = &data->chdata[i];513 u8 r2 = inbuf[i * 6 + 1];514 u8 r3 = inbuf[i * 6 + 2];515 516 ch->dac_value = FIELD_GET(MCP4728_DAC_H_MASK, r2) << 8 |517 FIELD_GET(MCP4728_DAC_L_MASK, r3);518 ch->ref_mode = FIELD_GET(MCP4728_VREF_MASK, r2);519 ch->pd_mode = FIELD_GET(MCP4728_PDMODE_MASK, r2);520 ch->g_mode = FIELD_GET(MCP4728_GAIN_MASK, r2);521 }522 523 return 0;524}525 526static int mcp4728_probe(struct i2c_client *client)527{528 const struct i2c_device_id *id = i2c_client_get_device_id(client);529 struct mcp4728_data *data;530 struct iio_dev *indio_dev;531 int ret, vdd_mv;532 533 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));534 if (!indio_dev)535 return -ENOMEM;536 537 data = iio_priv(indio_dev);538 i2c_set_clientdata(client, indio_dev);539 data->client = client;540 541 ret = devm_regulator_get_enable_read_voltage(&client->dev, "vdd");542 if (ret < 0)543 return ret;544 545 vdd_mv = ret / 1000;546 547 /*548 * MCP4728 has internal EEPROM that save each channel boot549 * configuration. It means that device configuration is unknown to the550 * driver at kernel boot. mcp4728_init_channels_data() reads back DAC551 * settings and stores them in data structure.552 */553 ret = mcp4728_init_channels_data(data);554 if (ret) {555 return dev_err_probe(&client->dev, ret,556 "failed to read mcp4728 current configuration\n");557 }558 559 ret = mcp4728_init_scales_avail(data, vdd_mv);560 if (ret) {561 return dev_err_probe(&client->dev, ret,562 "failed to init scales\n");563 }564 565 indio_dev->name = id->name;566 indio_dev->info = &mcp4728_info;567 indio_dev->channels = mcp4728_channels;568 indio_dev->num_channels = MCP4728_N_CHANNELS;569 indio_dev->modes = INDIO_DIRECT_MODE;570 571 return devm_iio_device_register(&client->dev, indio_dev);572}573 574static const struct i2c_device_id mcp4728_id[] = {575 { "mcp4728" },576 {}577};578MODULE_DEVICE_TABLE(i2c, mcp4728_id);579 580static const struct of_device_id mcp4728_of_match[] = {581 { .compatible = "microchip,mcp4728" },582 {}583};584MODULE_DEVICE_TABLE(of, mcp4728_of_match);585 586static struct i2c_driver mcp4728_driver = {587 .driver = {588 .name = "mcp4728",589 .of_match_table = mcp4728_of_match,590 .pm = pm_sleep_ptr(&mcp4728_pm_ops),591 },592 .probe = mcp4728_probe,593 .id_table = mcp4728_id,594};595module_i2c_driver(mcp4728_driver);596 597MODULE_AUTHOR("Andrea Collamati <andrea.collamati@gmail.com>");598MODULE_DESCRIPTION("MCP4728 12-bit DAC");599MODULE_LICENSE("GPL");600