562 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * mcp4725.c - Support for Microchip MCP4725/64 *5 * Copyright (C) 2012 Peter Meerwald <pmeerw@pmeerw.net>6 *7 * Based on max517 by Roland Stigge <stigge@antcom.de>8 *9 * driver for the Microchip I2C 12-bit digital-to-analog converter (DAC)10 * (7-bit I2C slave address 0x60, the three LSBs can be configured in11 * hardware)12 */13 14#include <linux/module.h>15#include <linux/i2c.h>16#include <linux/err.h>17#include <linux/delay.h>18#include <linux/regulator/consumer.h>19#include <linux/mod_devicetable.h>20#include <linux/property.h>21 22#include <linux/iio/iio.h>23#include <linux/iio/sysfs.h>24 25#include <linux/iio/dac/mcp4725.h>26 27#define MCP4725_DRV_NAME "mcp4725"28 29#define MCP472X_REF_VDD 0x0030#define MCP472X_REF_VREF_UNBUFFERED 0x0231#define MCP472X_REF_VREF_BUFFERED 0x0332 33struct mcp4725_chip_info {34 const struct iio_chan_spec *chan_spec;35 u8 dac_reg_offset;36 bool use_ext_ref_voltage;37};38 39struct mcp4725_data {40 struct i2c_client *client;41 unsigned ref_mode;42 bool vref_buffered;43 u16 dac_value;44 bool powerdown;45 unsigned powerdown_mode;46 struct regulator *vdd_reg;47 struct regulator *vref_reg;48};49 50static int mcp4725_suspend(struct device *dev)51{52 struct mcp4725_data *data = iio_priv(i2c_get_clientdata(53 to_i2c_client(dev)));54 u8 outbuf[2];55 int ret;56 57 outbuf[0] = (data->powerdown_mode + 1) << 4;58 outbuf[1] = 0;59 data->powerdown = true;60 61 ret = i2c_master_send(data->client, outbuf, 2);62 if (ret < 0)63 return ret;64 else if (ret != 2)65 return -EIO;66 return 0;67}68 69static int mcp4725_resume(struct device *dev)70{71 struct mcp4725_data *data = iio_priv(i2c_get_clientdata(72 to_i2c_client(dev)));73 u8 outbuf[2];74 int ret;75 76 /* restore previous DAC value */77 outbuf[0] = (data->dac_value >> 8) & 0xf;78 outbuf[1] = data->dac_value & 0xff;79 data->powerdown = false;80 81 ret = i2c_master_send(data->client, outbuf, 2);82 if (ret < 0)83 return ret;84 else if (ret != 2)85 return -EIO;86 return 0;87}88static DEFINE_SIMPLE_DEV_PM_OPS(mcp4725_pm_ops, mcp4725_suspend,89 mcp4725_resume);90 91static ssize_t mcp4725_store_eeprom(struct device *dev,92 struct device_attribute *attr, const char *buf, size_t len)93{94 struct iio_dev *indio_dev = dev_to_iio_dev(dev);95 struct mcp4725_data *data = iio_priv(indio_dev);96 int tries = 20;97 u8 inoutbuf[3];98 bool state;99 int ret;100 101 ret = kstrtobool(buf, &state);102 if (ret < 0)103 return ret;104 105 if (!state)106 return 0;107 108 inoutbuf[0] = 0x60; /* write EEPROM */109 inoutbuf[0] |= data->ref_mode << 3;110 inoutbuf[0] |= data->powerdown ? ((data->powerdown_mode + 1) << 1) : 0;111 inoutbuf[1] = data->dac_value >> 4;112 inoutbuf[2] = (data->dac_value & 0xf) << 4;113 114 ret = i2c_master_send(data->client, inoutbuf, 3);115 if (ret < 0)116 return ret;117 else if (ret != 3)118 return -EIO;119 120 /* wait for write complete, takes up to 50ms */121 while (tries--) {122 msleep(20);123 ret = i2c_master_recv(data->client, inoutbuf, 3);124 if (ret < 0)125 return ret;126 else if (ret != 3)127 return -EIO;128 129 if (inoutbuf[0] & 0x80)130 break;131 }132 133 if (tries < 0) {134 dev_err(&data->client->dev,135 "mcp4725_store_eeprom() failed, incomplete\n");136 return -EIO;137 }138 139 return len;140}141 142static IIO_DEVICE_ATTR(store_eeprom, S_IWUSR, NULL, mcp4725_store_eeprom, 0);143 144static struct attribute *mcp4725_attributes[] = {145 &iio_dev_attr_store_eeprom.dev_attr.attr,146 NULL,147};148 149static const struct attribute_group mcp4725_attribute_group = {150 .attrs = mcp4725_attributes,151};152 153static const char * const mcp4725_powerdown_modes[] = {154 "1kohm_to_gnd",155 "100kohm_to_gnd",156 "500kohm_to_gnd"157};158 159static const char * const mcp4726_powerdown_modes[] = {160 "1kohm_to_gnd",161 "125kohm_to_gnd",162 "640kohm_to_gnd"163};164 165static int mcp4725_get_powerdown_mode(struct iio_dev *indio_dev,166 const struct iio_chan_spec *chan)167{168 struct mcp4725_data *data = iio_priv(indio_dev);169 170 return data->powerdown_mode;171}172 173static int mcp4725_set_powerdown_mode(struct iio_dev *indio_dev,174 const struct iio_chan_spec *chan, unsigned mode)175{176 struct mcp4725_data *data = iio_priv(indio_dev);177 178 data->powerdown_mode = mode;179 180 return 0;181}182 183static ssize_t mcp4725_read_powerdown(struct iio_dev *indio_dev,184 uintptr_t private, const struct iio_chan_spec *chan, char *buf)185{186 struct mcp4725_data *data = iio_priv(indio_dev);187 188 return sysfs_emit(buf, "%d\n", data->powerdown);189}190 191static ssize_t mcp4725_write_powerdown(struct iio_dev *indio_dev,192 uintptr_t private, const struct iio_chan_spec *chan,193 const char *buf, size_t len)194{195 struct mcp4725_data *data = iio_priv(indio_dev);196 bool state;197 int ret;198 199 ret = kstrtobool(buf, &state);200 if (ret)201 return ret;202 203 if (state)204 ret = mcp4725_suspend(&data->client->dev);205 else206 ret = mcp4725_resume(&data->client->dev);207 if (ret < 0)208 return ret;209 210 return len;211}212 213enum chip_id {214 MCP4725,215 MCP4726,216};217 218static const struct iio_enum mcp472x_powerdown_mode_enum[] = {219 [MCP4725] = {220 .items = mcp4725_powerdown_modes,221 .num_items = ARRAY_SIZE(mcp4725_powerdown_modes),222 .get = mcp4725_get_powerdown_mode,223 .set = mcp4725_set_powerdown_mode,224 },225 [MCP4726] = {226 .items = mcp4726_powerdown_modes,227 .num_items = ARRAY_SIZE(mcp4726_powerdown_modes),228 .get = mcp4725_get_powerdown_mode,229 .set = mcp4725_set_powerdown_mode,230 },231};232 233static const struct iio_chan_spec_ext_info mcp4725_ext_info[] = {234 {235 .name = "powerdown",236 .read = mcp4725_read_powerdown,237 .write = mcp4725_write_powerdown,238 .shared = IIO_SEPARATE,239 },240 IIO_ENUM("powerdown_mode", IIO_SEPARATE,241 &mcp472x_powerdown_mode_enum[MCP4725]),242 IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE,243 &mcp472x_powerdown_mode_enum[MCP4725]),244 { },245};246 247static const struct iio_chan_spec_ext_info mcp4726_ext_info[] = {248 {249 .name = "powerdown",250 .read = mcp4725_read_powerdown,251 .write = mcp4725_write_powerdown,252 .shared = IIO_SEPARATE,253 },254 IIO_ENUM("powerdown_mode", IIO_SEPARATE,255 &mcp472x_powerdown_mode_enum[MCP4726]),256 IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE,257 &mcp472x_powerdown_mode_enum[MCP4726]),258 { },259};260 261static const struct iio_chan_spec mcp472x_channel[] = {262 [MCP4725] = {263 .type = IIO_VOLTAGE,264 .indexed = 1,265 .output = 1,266 .channel = 0,267 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),268 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),269 .ext_info = mcp4725_ext_info,270 },271 [MCP4726] = {272 .type = IIO_VOLTAGE,273 .indexed = 1,274 .output = 1,275 .channel = 0,276 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),277 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),278 .ext_info = mcp4726_ext_info,279 },280};281 282static int mcp4725_set_value(struct iio_dev *indio_dev, int val)283{284 struct mcp4725_data *data = iio_priv(indio_dev);285 u8 outbuf[2];286 int ret;287 288 if (val >= (1 << 12) || val < 0)289 return -EINVAL;290 291 outbuf[0] = (val >> 8) & 0xf;292 outbuf[1] = val & 0xff;293 294 ret = i2c_master_send(data->client, outbuf, 2);295 if (ret < 0)296 return ret;297 else if (ret != 2)298 return -EIO;299 else300 return 0;301}302 303static int mcp4726_set_cfg(struct iio_dev *indio_dev)304{305 struct mcp4725_data *data = iio_priv(indio_dev);306 u8 outbuf[3];307 int ret;308 309 outbuf[0] = 0x40;310 outbuf[0] |= data->ref_mode << 3;311 if (data->powerdown)312 outbuf[0] |= data->powerdown << 1;313 outbuf[1] = data->dac_value >> 4;314 outbuf[2] = (data->dac_value & 0xf) << 4;315 316 ret = i2c_master_send(data->client, outbuf, 3);317 if (ret < 0)318 return ret;319 else if (ret != 3)320 return -EIO;321 else322 return 0;323}324 325static int mcp4725_read_raw(struct iio_dev *indio_dev,326 struct iio_chan_spec const *chan,327 int *val, int *val2, long mask)328{329 struct mcp4725_data *data = iio_priv(indio_dev);330 int ret;331 332 switch (mask) {333 case IIO_CHAN_INFO_RAW:334 *val = data->dac_value;335 return IIO_VAL_INT;336 case IIO_CHAN_INFO_SCALE:337 if (data->ref_mode == MCP472X_REF_VDD)338 ret = regulator_get_voltage(data->vdd_reg);339 else340 ret = regulator_get_voltage(data->vref_reg);341 342 if (ret < 0)343 return ret;344 345 *val = ret / 1000;346 *val2 = 12;347 return IIO_VAL_FRACTIONAL_LOG2;348 }349 return -EINVAL;350}351 352static int mcp4725_write_raw(struct iio_dev *indio_dev,353 struct iio_chan_spec const *chan,354 int val, int val2, long mask)355{356 struct mcp4725_data *data = iio_priv(indio_dev);357 int ret;358 359 switch (mask) {360 case IIO_CHAN_INFO_RAW:361 ret = mcp4725_set_value(indio_dev, val);362 data->dac_value = val;363 break;364 default:365 ret = -EINVAL;366 break;367 }368 369 return ret;370}371 372static const struct iio_info mcp4725_info = {373 .read_raw = mcp4725_read_raw,374 .write_raw = mcp4725_write_raw,375 .attrs = &mcp4725_attribute_group,376};377 378static int mcp4725_probe_dt(struct device *dev,379 struct mcp4725_platform_data *pdata)380{381 /* check if is the vref-supply defined */382 pdata->use_vref = device_property_read_bool(dev, "vref-supply");383 pdata->vref_buffered =384 device_property_read_bool(dev, "microchip,vref-buffered");385 386 return 0;387}388 389static int mcp4725_probe(struct i2c_client *client)390{391 const struct i2c_device_id *id = i2c_client_get_device_id(client);392 const struct mcp4725_chip_info *info;393 struct mcp4725_data *data;394 struct iio_dev *indio_dev;395 struct mcp4725_platform_data *pdata, pdata_dt;396 u8 inbuf[4];397 u8 pd;398 u8 ref;399 int err;400 401 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));402 if (indio_dev == NULL)403 return -ENOMEM;404 data = iio_priv(indio_dev);405 i2c_set_clientdata(client, indio_dev);406 data->client = client;407 info = i2c_get_match_data(client);408 pdata = dev_get_platdata(&client->dev);409 410 if (!pdata) {411 err = mcp4725_probe_dt(&client->dev, &pdata_dt);412 if (err) {413 dev_err(&client->dev,414 "invalid platform or devicetree data");415 return err;416 }417 pdata = &pdata_dt;418 }419 420 if (info->use_ext_ref_voltage && pdata->use_vref) {421 dev_err(&client->dev,422 "external reference is unavailable on MCP4725");423 return -EINVAL;424 }425 426 if (!pdata->use_vref && pdata->vref_buffered) {427 dev_err(&client->dev,428 "buffering is unavailable on the internal reference");429 return -EINVAL;430 }431 432 if (!pdata->use_vref)433 data->ref_mode = MCP472X_REF_VDD;434 else435 data->ref_mode = pdata->vref_buffered ?436 MCP472X_REF_VREF_BUFFERED :437 MCP472X_REF_VREF_UNBUFFERED;438 439 data->vdd_reg = devm_regulator_get(&client->dev, "vdd");440 if (IS_ERR(data->vdd_reg))441 return PTR_ERR(data->vdd_reg);442 443 err = regulator_enable(data->vdd_reg);444 if (err)445 return err;446 447 if (pdata->use_vref) {448 data->vref_reg = devm_regulator_get(&client->dev, "vref");449 if (IS_ERR(data->vref_reg)) {450 err = PTR_ERR(data->vref_reg);451 goto err_disable_vdd_reg;452 }453 454 err = regulator_enable(data->vref_reg);455 if (err)456 goto err_disable_vdd_reg;457 }458 459 indio_dev->name = id->name;460 indio_dev->info = &mcp4725_info;461 indio_dev->channels = info->chan_spec;462 indio_dev->num_channels = 1;463 indio_dev->modes = INDIO_DIRECT_MODE;464 465 /* read current DAC value and settings */466 err = i2c_master_recv(client, inbuf, info->dac_reg_offset);467 468 if (err < 0) {469 dev_err(&client->dev, "failed to read DAC value");470 goto err_disable_vref_reg;471 }472 pd = (inbuf[0] >> 1) & 0x3;473 data->powerdown = pd > 0;474 data->powerdown_mode = pd ? pd - 1 : 2; /* largest resistor to gnd */475 data->dac_value = (inbuf[1] << 4) | (inbuf[2] >> 4);476 if (!info->use_ext_ref_voltage)477 ref = (inbuf[3] >> 3) & 0x3;478 479 if (!info->use_ext_ref_voltage && ref != data->ref_mode) {480 dev_info(&client->dev,481 "voltage reference mode differs (conf: %u, eeprom: %u), setting %u",482 data->ref_mode, ref, data->ref_mode);483 err = mcp4726_set_cfg(indio_dev);484 if (err < 0)485 goto err_disable_vref_reg;486 }487 488 err = iio_device_register(indio_dev);489 if (err)490 goto err_disable_vref_reg;491 492 return 0;493 494err_disable_vref_reg:495 if (data->vref_reg)496 regulator_disable(data->vref_reg);497 498err_disable_vdd_reg:499 regulator_disable(data->vdd_reg);500 501 return err;502}503 504static void mcp4725_remove(struct i2c_client *client)505{506 struct iio_dev *indio_dev = i2c_get_clientdata(client);507 struct mcp4725_data *data = iio_priv(indio_dev);508 509 iio_device_unregister(indio_dev);510 511 if (data->vref_reg)512 regulator_disable(data->vref_reg);513 regulator_disable(data->vdd_reg);514}515 516static const struct mcp4725_chip_info mcp4725 = {517 .chan_spec = &mcp472x_channel[MCP4725],518 .dac_reg_offset = 3,519 .use_ext_ref_voltage = true,520};521 522static const struct mcp4725_chip_info mcp4726 = {523 .chan_spec = &mcp472x_channel[MCP4726],524 .dac_reg_offset = 4,525};526 527static const struct i2c_device_id mcp4725_id[] = {528 { "mcp4725", (kernel_ulong_t)&mcp4725 },529 { "mcp4726", (kernel_ulong_t)&mcp4726 },530 { }531};532MODULE_DEVICE_TABLE(i2c, mcp4725_id);533 534static const struct of_device_id mcp4725_of_match[] = {535 {536 .compatible = "microchip,mcp4725",537 .data = &mcp4725538 },539 {540 .compatible = "microchip,mcp4726",541 .data = &mcp4726542 },543 { }544};545MODULE_DEVICE_TABLE(of, mcp4725_of_match);546 547static struct i2c_driver mcp4725_driver = {548 .driver = {549 .name = MCP4725_DRV_NAME,550 .of_match_table = mcp4725_of_match,551 .pm = pm_sleep_ptr(&mcp4725_pm_ops),552 },553 .probe = mcp4725_probe,554 .remove = mcp4725_remove,555 .id_table = mcp4725_id,556};557module_i2c_driver(mcp4725_driver);558 559MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");560MODULE_DESCRIPTION("MCP4725/6 12-bit DAC");561MODULE_LICENSE("GPL");562