136edc939SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2cf35ad61SPeter Meerwald /* 335f73967SAkinobu Mita * mcp4725.c - Support for Microchip MCP4725/6 4cf35ad61SPeter Meerwald * 5cf35ad61SPeter Meerwald * Copyright (C) 2012 Peter Meerwald <pmeerw@pmeerw.net> 6cf35ad61SPeter Meerwald * 7cf35ad61SPeter Meerwald * Based on max517 by Roland Stigge <stigge@antcom.de> 8cf35ad61SPeter Meerwald * 9cf35ad61SPeter Meerwald * driver for the Microchip I2C 12-bit digital-to-analog converter (DAC) 10cf35ad61SPeter Meerwald * (7-bit I2C slave address 0x60, the three LSBs can be configured in 11cf35ad61SPeter Meerwald * hardware) 12cf35ad61SPeter Meerwald */ 13cf35ad61SPeter Meerwald 14cf35ad61SPeter Meerwald #include <linux/module.h> 15cf35ad61SPeter Meerwald #include <linux/i2c.h> 16cf35ad61SPeter Meerwald #include <linux/err.h> 17f17b77d6SPeter Meerwald #include <linux/delay.h> 18b440f1d9STomas Novotny #include <linux/regulator/consumer.h> 192de887b0SJonathan Cameron #include <linux/mod_devicetable.h> 202de887b0SJonathan Cameron #include <linux/property.h> 21cf35ad61SPeter Meerwald 22cf35ad61SPeter Meerwald #include <linux/iio/iio.h> 23cf35ad61SPeter Meerwald #include <linux/iio/sysfs.h> 24cf35ad61SPeter Meerwald 25cf35ad61SPeter Meerwald #include <linux/iio/dac/mcp4725.h> 26cf35ad61SPeter Meerwald 27cf35ad61SPeter Meerwald #define MCP4725_DRV_NAME "mcp4725" 28cf35ad61SPeter Meerwald 2929157c6dSTomas Novotny #define MCP472X_REF_VDD 0x00 3029157c6dSTomas Novotny #define MCP472X_REF_VREF_UNBUFFERED 0x02 3129157c6dSTomas Novotny #define MCP472X_REF_VREF_BUFFERED 0x03 3229157c6dSTomas Novotny 3318bdc686SBiju Das struct mcp4725_chip_info { 3418bdc686SBiju Das const struct iio_chan_spec *chan_spec; 35*c377e2feSBiju Das u8 dac_reg_offset; 36155da070SBiju Das bool use_ext_ref_voltage; 3718bdc686SBiju Das }; 3818bdc686SBiju Das 39cf35ad61SPeter Meerwald struct mcp4725_data { 40cf35ad61SPeter Meerwald struct i2c_client *client; 4129157c6dSTomas Novotny unsigned ref_mode; 4229157c6dSTomas Novotny bool vref_buffered; 43cf35ad61SPeter Meerwald u16 dac_value; 44155f1b41SPeter Meerwald bool powerdown; 45155f1b41SPeter Meerwald unsigned powerdown_mode; 46b440f1d9STomas Novotny struct regulator *vdd_reg; 4729157c6dSTomas Novotny struct regulator *vref_reg; 48cf35ad61SPeter Meerwald }; 49cf35ad61SPeter Meerwald 50bf19b235SJonathan Cameron static int mcp4725_suspend(struct device *dev) 51cf35ad61SPeter Meerwald { 52a97dd069SPeter Meerwald struct mcp4725_data *data = iio_priv(i2c_get_clientdata( 53a97dd069SPeter Meerwald to_i2c_client(dev))); 54cf35ad61SPeter Meerwald u8 outbuf[2]; 5509d3bec7SMarek Vasut int ret; 56cf35ad61SPeter Meerwald 57155f1b41SPeter Meerwald outbuf[0] = (data->powerdown_mode + 1) << 4; 58cf35ad61SPeter Meerwald outbuf[1] = 0; 59155f1b41SPeter Meerwald data->powerdown = true; 60cf35ad61SPeter Meerwald 6109d3bec7SMarek Vasut ret = i2c_master_send(data->client, outbuf, 2); 6209d3bec7SMarek Vasut if (ret < 0) 6309d3bec7SMarek Vasut return ret; 6409d3bec7SMarek Vasut else if (ret != 2) 6509d3bec7SMarek Vasut return -EIO; 6609d3bec7SMarek Vasut return 0; 67cf35ad61SPeter Meerwald } 68cf35ad61SPeter Meerwald 69bf19b235SJonathan Cameron static int mcp4725_resume(struct device *dev) 70cf35ad61SPeter Meerwald { 71a97dd069SPeter Meerwald struct mcp4725_data *data = iio_priv(i2c_get_clientdata( 72a97dd069SPeter Meerwald to_i2c_client(dev))); 73cf35ad61SPeter Meerwald u8 outbuf[2]; 7409d3bec7SMarek Vasut int ret; 75cf35ad61SPeter Meerwald 76cf35ad61SPeter Meerwald /* restore previous DAC value */ 77cf35ad61SPeter Meerwald outbuf[0] = (data->dac_value >> 8) & 0xf; 78cf35ad61SPeter Meerwald outbuf[1] = data->dac_value & 0xff; 79155f1b41SPeter Meerwald data->powerdown = false; 80cf35ad61SPeter Meerwald 8109d3bec7SMarek Vasut ret = i2c_master_send(data->client, outbuf, 2); 8209d3bec7SMarek Vasut if (ret < 0) 8309d3bec7SMarek Vasut return ret; 8409d3bec7SMarek Vasut else if (ret != 2) 8509d3bec7SMarek Vasut return -EIO; 8609d3bec7SMarek Vasut return 0; 87cf35ad61SPeter Meerwald } 88bf19b235SJonathan Cameron static DEFINE_SIMPLE_DEV_PM_OPS(mcp4725_pm_ops, mcp4725_suspend, 89bf19b235SJonathan Cameron mcp4725_resume); 90cf35ad61SPeter Meerwald 914fd313daSJonathan Cameron static ssize_t mcp4725_store_eeprom(struct device *dev, 92f17b77d6SPeter Meerwald struct device_attribute *attr, const char *buf, size_t len) 93f17b77d6SPeter Meerwald { 94f17b77d6SPeter Meerwald struct iio_dev *indio_dev = dev_to_iio_dev(dev); 95f17b77d6SPeter Meerwald struct mcp4725_data *data = iio_priv(indio_dev); 96f17b77d6SPeter Meerwald int tries = 20; 97f17b77d6SPeter Meerwald u8 inoutbuf[3]; 98f17b77d6SPeter Meerwald bool state; 99f17b77d6SPeter Meerwald int ret; 100f17b77d6SPeter Meerwald 10174f582ecSLars-Peter Clausen ret = kstrtobool(buf, &state); 102f17b77d6SPeter Meerwald if (ret < 0) 103f17b77d6SPeter Meerwald return ret; 104f17b77d6SPeter Meerwald 105f17b77d6SPeter Meerwald if (!state) 106f17b77d6SPeter Meerwald return 0; 107f17b77d6SPeter Meerwald 108f17b77d6SPeter Meerwald inoutbuf[0] = 0x60; /* write EEPROM */ 10929157c6dSTomas Novotny inoutbuf[0] |= data->ref_mode << 3; 11006003531SJean-Francois Dagenais inoutbuf[0] |= data->powerdown ? ((data->powerdown_mode + 1) << 1) : 0; 111f17b77d6SPeter Meerwald inoutbuf[1] = data->dac_value >> 4; 112f17b77d6SPeter Meerwald inoutbuf[2] = (data->dac_value & 0xf) << 4; 113f17b77d6SPeter Meerwald 114f17b77d6SPeter Meerwald ret = i2c_master_send(data->client, inoutbuf, 3); 115f17b77d6SPeter Meerwald if (ret < 0) 116f17b77d6SPeter Meerwald return ret; 117f17b77d6SPeter Meerwald else if (ret != 3) 118f17b77d6SPeter Meerwald return -EIO; 119f17b77d6SPeter Meerwald 120f17b77d6SPeter Meerwald /* wait for write complete, takes up to 50ms */ 121f17b77d6SPeter Meerwald while (tries--) { 122f17b77d6SPeter Meerwald msleep(20); 123f17b77d6SPeter Meerwald ret = i2c_master_recv(data->client, inoutbuf, 3); 124f17b77d6SPeter Meerwald if (ret < 0) 125f17b77d6SPeter Meerwald return ret; 126f17b77d6SPeter Meerwald else if (ret != 3) 127f17b77d6SPeter Meerwald return -EIO; 128f17b77d6SPeter Meerwald 129f17b77d6SPeter Meerwald if (inoutbuf[0] & 0x80) 130f17b77d6SPeter Meerwald break; 131f17b77d6SPeter Meerwald } 132f17b77d6SPeter Meerwald 133f17b77d6SPeter Meerwald if (tries < 0) { 134f17b77d6SPeter Meerwald dev_err(&data->client->dev, 135f17b77d6SPeter Meerwald "mcp4725_store_eeprom() failed, incomplete\n"); 136f17b77d6SPeter Meerwald return -EIO; 137f17b77d6SPeter Meerwald } 138f17b77d6SPeter Meerwald 139f17b77d6SPeter Meerwald return len; 140f17b77d6SPeter Meerwald } 141f17b77d6SPeter Meerwald 142f17b77d6SPeter Meerwald static IIO_DEVICE_ATTR(store_eeprom, S_IWUSR, NULL, mcp4725_store_eeprom, 0); 143f17b77d6SPeter Meerwald 144f17b77d6SPeter Meerwald static struct attribute *mcp4725_attributes[] = { 145f17b77d6SPeter Meerwald &iio_dev_attr_store_eeprom.dev_attr.attr, 146f17b77d6SPeter Meerwald NULL, 147f17b77d6SPeter Meerwald }; 148f17b77d6SPeter Meerwald 149f17b77d6SPeter Meerwald static const struct attribute_group mcp4725_attribute_group = { 150f17b77d6SPeter Meerwald .attrs = mcp4725_attributes, 151f17b77d6SPeter Meerwald }; 152f17b77d6SPeter Meerwald 153155f1b41SPeter Meerwald static const char * const mcp4725_powerdown_modes[] = { 154155f1b41SPeter Meerwald "1kohm_to_gnd", 155155f1b41SPeter Meerwald "100kohm_to_gnd", 156155f1b41SPeter Meerwald "500kohm_to_gnd" 157155f1b41SPeter Meerwald }; 158155f1b41SPeter Meerwald 15935f73967SAkinobu Mita static const char * const mcp4726_powerdown_modes[] = { 16035f73967SAkinobu Mita "1kohm_to_gnd", 16135f73967SAkinobu Mita "125kohm_to_gnd", 16235f73967SAkinobu Mita "640kohm_to_gnd" 16335f73967SAkinobu Mita }; 16435f73967SAkinobu Mita 165155f1b41SPeter Meerwald static int mcp4725_get_powerdown_mode(struct iio_dev *indio_dev, 166155f1b41SPeter Meerwald const struct iio_chan_spec *chan) 167155f1b41SPeter Meerwald { 168155f1b41SPeter Meerwald struct mcp4725_data *data = iio_priv(indio_dev); 169155f1b41SPeter Meerwald 170155f1b41SPeter Meerwald return data->powerdown_mode; 171155f1b41SPeter Meerwald } 172155f1b41SPeter Meerwald 173155f1b41SPeter Meerwald static int mcp4725_set_powerdown_mode(struct iio_dev *indio_dev, 174155f1b41SPeter Meerwald const struct iio_chan_spec *chan, unsigned mode) 175155f1b41SPeter Meerwald { 176155f1b41SPeter Meerwald struct mcp4725_data *data = iio_priv(indio_dev); 177155f1b41SPeter Meerwald 178155f1b41SPeter Meerwald data->powerdown_mode = mode; 179155f1b41SPeter Meerwald 180155f1b41SPeter Meerwald return 0; 181155f1b41SPeter Meerwald } 182155f1b41SPeter Meerwald 183155f1b41SPeter Meerwald static ssize_t mcp4725_read_powerdown(struct iio_dev *indio_dev, 184155f1b41SPeter Meerwald uintptr_t private, const struct iio_chan_spec *chan, char *buf) 185155f1b41SPeter Meerwald { 186155f1b41SPeter Meerwald struct mcp4725_data *data = iio_priv(indio_dev); 187155f1b41SPeter Meerwald 188f46ac009SLars-Peter Clausen return sysfs_emit(buf, "%d\n", data->powerdown); 189155f1b41SPeter Meerwald } 190155f1b41SPeter Meerwald 191155f1b41SPeter Meerwald static ssize_t mcp4725_write_powerdown(struct iio_dev *indio_dev, 192155f1b41SPeter Meerwald uintptr_t private, const struct iio_chan_spec *chan, 193155f1b41SPeter Meerwald const char *buf, size_t len) 194155f1b41SPeter Meerwald { 195155f1b41SPeter Meerwald struct mcp4725_data *data = iio_priv(indio_dev); 196155f1b41SPeter Meerwald bool state; 197155f1b41SPeter Meerwald int ret; 198155f1b41SPeter Meerwald 19974f582ecSLars-Peter Clausen ret = kstrtobool(buf, &state); 200155f1b41SPeter Meerwald if (ret) 201155f1b41SPeter Meerwald return ret; 202155f1b41SPeter Meerwald 203155f1b41SPeter Meerwald if (state) 204155f1b41SPeter Meerwald ret = mcp4725_suspend(&data->client->dev); 205155f1b41SPeter Meerwald else 206155f1b41SPeter Meerwald ret = mcp4725_resume(&data->client->dev); 207155f1b41SPeter Meerwald if (ret < 0) 208155f1b41SPeter Meerwald return ret; 209155f1b41SPeter Meerwald 210155f1b41SPeter Meerwald return len; 211155f1b41SPeter Meerwald } 212155f1b41SPeter Meerwald 2138414af1eSJavier Martinez Canillas enum chip_id { 21435f73967SAkinobu Mita MCP4725, 21535f73967SAkinobu Mita MCP4726, 21635f73967SAkinobu Mita }; 21735f73967SAkinobu Mita 21835f73967SAkinobu Mita static const struct iio_enum mcp472x_powerdown_mode_enum[] = { 21935f73967SAkinobu Mita [MCP4725] = { 220155f1b41SPeter Meerwald .items = mcp4725_powerdown_modes, 221155f1b41SPeter Meerwald .num_items = ARRAY_SIZE(mcp4725_powerdown_modes), 222155f1b41SPeter Meerwald .get = mcp4725_get_powerdown_mode, 223155f1b41SPeter Meerwald .set = mcp4725_set_powerdown_mode, 22435f73967SAkinobu Mita }, 22535f73967SAkinobu Mita [MCP4726] = { 22635f73967SAkinobu Mita .items = mcp4726_powerdown_modes, 22735f73967SAkinobu Mita .num_items = ARRAY_SIZE(mcp4726_powerdown_modes), 22835f73967SAkinobu Mita .get = mcp4725_get_powerdown_mode, 22935f73967SAkinobu Mita .set = mcp4725_set_powerdown_mode, 23035f73967SAkinobu Mita }, 231155f1b41SPeter Meerwald }; 232155f1b41SPeter Meerwald 233155f1b41SPeter Meerwald static const struct iio_chan_spec_ext_info mcp4725_ext_info[] = { 234155f1b41SPeter Meerwald { 235155f1b41SPeter Meerwald .name = "powerdown", 236155f1b41SPeter Meerwald .read = mcp4725_read_powerdown, 237155f1b41SPeter Meerwald .write = mcp4725_write_powerdown, 2383704432fSJonathan Cameron .shared = IIO_SEPARATE, 239155f1b41SPeter Meerwald }, 24035f73967SAkinobu Mita IIO_ENUM("powerdown_mode", IIO_SEPARATE, 24135f73967SAkinobu Mita &mcp472x_powerdown_mode_enum[MCP4725]), 242ffc7c517SAntoniu Miclaus IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, 24335f73967SAkinobu Mita &mcp472x_powerdown_mode_enum[MCP4725]), 244155f1b41SPeter Meerwald { }, 245155f1b41SPeter Meerwald }; 246155f1b41SPeter Meerwald 24735f73967SAkinobu Mita static const struct iio_chan_spec_ext_info mcp4726_ext_info[] = { 24835f73967SAkinobu Mita { 24935f73967SAkinobu Mita .name = "powerdown", 25035f73967SAkinobu Mita .read = mcp4725_read_powerdown, 25135f73967SAkinobu Mita .write = mcp4725_write_powerdown, 25235f73967SAkinobu Mita .shared = IIO_SEPARATE, 25335f73967SAkinobu Mita }, 25435f73967SAkinobu Mita IIO_ENUM("powerdown_mode", IIO_SEPARATE, 25535f73967SAkinobu Mita &mcp472x_powerdown_mode_enum[MCP4726]), 256ffc7c517SAntoniu Miclaus IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, 25735f73967SAkinobu Mita &mcp472x_powerdown_mode_enum[MCP4726]), 25835f73967SAkinobu Mita { }, 25935f73967SAkinobu Mita }; 26035f73967SAkinobu Mita 26135f73967SAkinobu Mita static const struct iio_chan_spec mcp472x_channel[] = { 26235f73967SAkinobu Mita [MCP4725] = { 263cf35ad61SPeter Meerwald .type = IIO_VOLTAGE, 264cf35ad61SPeter Meerwald .indexed = 1, 265cf35ad61SPeter Meerwald .output = 1, 266cf35ad61SPeter Meerwald .channel = 0, 26790b46374SJonathan Cameron .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 26890b46374SJonathan Cameron .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), 269155f1b41SPeter Meerwald .ext_info = mcp4725_ext_info, 27035f73967SAkinobu Mita }, 27135f73967SAkinobu Mita [MCP4726] = { 27235f73967SAkinobu Mita .type = IIO_VOLTAGE, 27335f73967SAkinobu Mita .indexed = 1, 27435f73967SAkinobu Mita .output = 1, 27535f73967SAkinobu Mita .channel = 0, 27635f73967SAkinobu Mita .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 27735f73967SAkinobu Mita .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), 27835f73967SAkinobu Mita .ext_info = mcp4726_ext_info, 27935f73967SAkinobu Mita }, 280cf35ad61SPeter Meerwald }; 281cf35ad61SPeter Meerwald 282cf35ad61SPeter Meerwald static int mcp4725_set_value(struct iio_dev *indio_dev, int val) 283cf35ad61SPeter Meerwald { 284cf35ad61SPeter Meerwald struct mcp4725_data *data = iio_priv(indio_dev); 285cf35ad61SPeter Meerwald u8 outbuf[2]; 286cf35ad61SPeter Meerwald int ret; 287cf35ad61SPeter Meerwald 288cf35ad61SPeter Meerwald if (val >= (1 << 12) || val < 0) 289cf35ad61SPeter Meerwald return -EINVAL; 290cf35ad61SPeter Meerwald 291cf35ad61SPeter Meerwald outbuf[0] = (val >> 8) & 0xf; 292cf35ad61SPeter Meerwald outbuf[1] = val & 0xff; 293cf35ad61SPeter Meerwald 294cf35ad61SPeter Meerwald ret = i2c_master_send(data->client, outbuf, 2); 295cf35ad61SPeter Meerwald if (ret < 0) 296cf35ad61SPeter Meerwald return ret; 297cf35ad61SPeter Meerwald else if (ret != 2) 298cf35ad61SPeter Meerwald return -EIO; 299cf35ad61SPeter Meerwald else 300cf35ad61SPeter Meerwald return 0; 301cf35ad61SPeter Meerwald } 302cf35ad61SPeter Meerwald 30329157c6dSTomas Novotny static int mcp4726_set_cfg(struct iio_dev *indio_dev) 30429157c6dSTomas Novotny { 30529157c6dSTomas Novotny struct mcp4725_data *data = iio_priv(indio_dev); 30629157c6dSTomas Novotny u8 outbuf[3]; 30729157c6dSTomas Novotny int ret; 30829157c6dSTomas Novotny 30929157c6dSTomas Novotny outbuf[0] = 0x40; 31029157c6dSTomas Novotny outbuf[0] |= data->ref_mode << 3; 31129157c6dSTomas Novotny if (data->powerdown) 31229157c6dSTomas Novotny outbuf[0] |= data->powerdown << 1; 31329157c6dSTomas Novotny outbuf[1] = data->dac_value >> 4; 31429157c6dSTomas Novotny outbuf[2] = (data->dac_value & 0xf) << 4; 31529157c6dSTomas Novotny 31629157c6dSTomas Novotny ret = i2c_master_send(data->client, outbuf, 3); 31729157c6dSTomas Novotny if (ret < 0) 31829157c6dSTomas Novotny return ret; 31929157c6dSTomas Novotny else if (ret != 3) 32029157c6dSTomas Novotny return -EIO; 32129157c6dSTomas Novotny else 32229157c6dSTomas Novotny return 0; 32329157c6dSTomas Novotny } 32429157c6dSTomas Novotny 325cf35ad61SPeter Meerwald static int mcp4725_read_raw(struct iio_dev *indio_dev, 326cf35ad61SPeter Meerwald struct iio_chan_spec const *chan, 327cf35ad61SPeter Meerwald int *val, int *val2, long mask) 328cf35ad61SPeter Meerwald { 329cf35ad61SPeter Meerwald struct mcp4725_data *data = iio_priv(indio_dev); 330b440f1d9STomas Novotny int ret; 331cf35ad61SPeter Meerwald 332cf35ad61SPeter Meerwald switch (mask) { 333cf35ad61SPeter Meerwald case IIO_CHAN_INFO_RAW: 334cf35ad61SPeter Meerwald *val = data->dac_value; 335cf35ad61SPeter Meerwald return IIO_VAL_INT; 336cf35ad61SPeter Meerwald case IIO_CHAN_INFO_SCALE: 33729157c6dSTomas Novotny if (data->ref_mode == MCP472X_REF_VDD) 338b440f1d9STomas Novotny ret = regulator_get_voltage(data->vdd_reg); 33929157c6dSTomas Novotny else 34029157c6dSTomas Novotny ret = regulator_get_voltage(data->vref_reg); 34129157c6dSTomas Novotny 342b440f1d9STomas Novotny if (ret < 0) 343b440f1d9STomas Novotny return ret; 344b440f1d9STomas Novotny 345b440f1d9STomas Novotny *val = ret / 1000; 346b117f96fSLars-Peter Clausen *val2 = 12; 347b117f96fSLars-Peter Clausen return IIO_VAL_FRACTIONAL_LOG2; 348cf35ad61SPeter Meerwald } 349cf35ad61SPeter Meerwald return -EINVAL; 350cf35ad61SPeter Meerwald } 351cf35ad61SPeter Meerwald 352cf35ad61SPeter Meerwald static int mcp4725_write_raw(struct iio_dev *indio_dev, 353cf35ad61SPeter Meerwald struct iio_chan_spec const *chan, 354cf35ad61SPeter Meerwald int val, int val2, long mask) 355cf35ad61SPeter Meerwald { 356cf35ad61SPeter Meerwald struct mcp4725_data *data = iio_priv(indio_dev); 357cf35ad61SPeter Meerwald int ret; 358cf35ad61SPeter Meerwald 359cf35ad61SPeter Meerwald switch (mask) { 360cf35ad61SPeter Meerwald case IIO_CHAN_INFO_RAW: 361cf35ad61SPeter Meerwald ret = mcp4725_set_value(indio_dev, val); 362cf35ad61SPeter Meerwald data->dac_value = val; 363cf35ad61SPeter Meerwald break; 364cf35ad61SPeter Meerwald default: 365cf35ad61SPeter Meerwald ret = -EINVAL; 366cf35ad61SPeter Meerwald break; 367cf35ad61SPeter Meerwald } 368cf35ad61SPeter Meerwald 369cf35ad61SPeter Meerwald return ret; 370cf35ad61SPeter Meerwald } 371cf35ad61SPeter Meerwald 372cf35ad61SPeter Meerwald static const struct iio_info mcp4725_info = { 373cf35ad61SPeter Meerwald .read_raw = mcp4725_read_raw, 374cf35ad61SPeter Meerwald .write_raw = mcp4725_write_raw, 375f17b77d6SPeter Meerwald .attrs = &mcp4725_attribute_group, 376cf35ad61SPeter Meerwald }; 377cf35ad61SPeter Meerwald 37888e39a88STomas Novotny static int mcp4725_probe_dt(struct device *dev, 37988e39a88STomas Novotny struct mcp4725_platform_data *pdata) 38088e39a88STomas Novotny { 38188e39a88STomas Novotny /* check if is the vref-supply defined */ 3822de887b0SJonathan Cameron pdata->use_vref = device_property_read_bool(dev, "vref-supply"); 38388e39a88STomas Novotny pdata->vref_buffered = 3842de887b0SJonathan Cameron device_property_read_bool(dev, "microchip,vref-buffered"); 38588e39a88STomas Novotny 38688e39a88STomas Novotny return 0; 38788e39a88STomas Novotny } 38888e39a88STomas Novotny 389818fe454SUwe Kleine-König static int mcp4725_probe(struct i2c_client *client) 390cf35ad61SPeter Meerwald { 391818fe454SUwe Kleine-König const struct i2c_device_id *id = i2c_client_get_device_id(client); 39218bdc686SBiju Das const struct mcp4725_chip_info *info; 393cf35ad61SPeter Meerwald struct mcp4725_data *data; 394cf35ad61SPeter Meerwald struct iio_dev *indio_dev; 39588e39a88STomas Novotny struct mcp4725_platform_data *pdata, pdata_dt; 39629157c6dSTomas Novotny u8 inbuf[4]; 397155f1b41SPeter Meerwald u8 pd; 39829157c6dSTomas Novotny u8 ref; 399cf35ad61SPeter Meerwald int err; 400cf35ad61SPeter Meerwald 401b6ff86f3SPeter Meerwald indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 402b6ff86f3SPeter Meerwald if (indio_dev == NULL) 403b6ff86f3SPeter Meerwald return -ENOMEM; 404cf35ad61SPeter Meerwald data = iio_priv(indio_dev); 405cf35ad61SPeter Meerwald i2c_set_clientdata(client, indio_dev); 406cf35ad61SPeter Meerwald data->client = client; 40718bdc686SBiju Das info = i2c_get_match_data(client); 40888e39a88STomas Novotny pdata = dev_get_platdata(&client->dev); 40988e39a88STomas Novotny 41088e39a88STomas Novotny if (!pdata) { 41188e39a88STomas Novotny err = mcp4725_probe_dt(&client->dev, &pdata_dt); 41288e39a88STomas Novotny if (err) { 41388e39a88STomas Novotny dev_err(&client->dev, 41488e39a88STomas Novotny "invalid platform or devicetree data"); 41588e39a88STomas Novotny return err; 41688e39a88STomas Novotny } 41788e39a88STomas Novotny pdata = &pdata_dt; 41888e39a88STomas Novotny } 41929157c6dSTomas Novotny 420155da070SBiju Das if (info->use_ext_ref_voltage && pdata->use_vref) { 42129157c6dSTomas Novotny dev_err(&client->dev, 42229157c6dSTomas Novotny "external reference is unavailable on MCP4725"); 42329157c6dSTomas Novotny return -EINVAL; 42429157c6dSTomas Novotny } 42529157c6dSTomas Novotny 42629157c6dSTomas Novotny if (!pdata->use_vref && pdata->vref_buffered) { 42729157c6dSTomas Novotny dev_err(&client->dev, 42829157c6dSTomas Novotny "buffering is unavailable on the internal reference"); 42929157c6dSTomas Novotny return -EINVAL; 43029157c6dSTomas Novotny } 43129157c6dSTomas Novotny 43229157c6dSTomas Novotny if (!pdata->use_vref) 43329157c6dSTomas Novotny data->ref_mode = MCP472X_REF_VDD; 43429157c6dSTomas Novotny else 43529157c6dSTomas Novotny data->ref_mode = pdata->vref_buffered ? 43629157c6dSTomas Novotny MCP472X_REF_VREF_BUFFERED : 43729157c6dSTomas Novotny MCP472X_REF_VREF_UNBUFFERED; 438cf35ad61SPeter Meerwald 439b440f1d9STomas Novotny data->vdd_reg = devm_regulator_get(&client->dev, "vdd"); 440b440f1d9STomas Novotny if (IS_ERR(data->vdd_reg)) 441b440f1d9STomas Novotny return PTR_ERR(data->vdd_reg); 442b440f1d9STomas Novotny 443b440f1d9STomas Novotny err = regulator_enable(data->vdd_reg); 444b440f1d9STomas Novotny if (err) 445b440f1d9STomas Novotny return err; 446b440f1d9STomas Novotny 44729157c6dSTomas Novotny if (pdata->use_vref) { 44829157c6dSTomas Novotny data->vref_reg = devm_regulator_get(&client->dev, "vref"); 44929157c6dSTomas Novotny if (IS_ERR(data->vref_reg)) { 45030df2d18SJulia Lawall err = PTR_ERR(data->vref_reg); 45129157c6dSTomas Novotny goto err_disable_vdd_reg; 45229157c6dSTomas Novotny } 45329157c6dSTomas Novotny 45429157c6dSTomas Novotny err = regulator_enable(data->vref_reg); 45529157c6dSTomas Novotny if (err) 45629157c6dSTomas Novotny goto err_disable_vdd_reg; 45729157c6dSTomas Novotny } 45829157c6dSTomas Novotny 45997a249e9SYong Li indio_dev->name = id->name; 460cf35ad61SPeter Meerwald indio_dev->info = &mcp4725_info; 46118bdc686SBiju Das indio_dev->channels = info->chan_spec; 462cf35ad61SPeter Meerwald indio_dev->num_channels = 1; 463cf35ad61SPeter Meerwald indio_dev->modes = INDIO_DIRECT_MODE; 464cf35ad61SPeter Meerwald 46529157c6dSTomas Novotny /* read current DAC value and settings */ 466*c377e2feSBiju Das err = i2c_master_recv(client, inbuf, info->dac_reg_offset); 46729157c6dSTomas Novotny 468cf35ad61SPeter Meerwald if (err < 0) { 469cf35ad61SPeter Meerwald dev_err(&client->dev, "failed to read DAC value"); 47029157c6dSTomas Novotny goto err_disable_vref_reg; 471cf35ad61SPeter Meerwald } 472155f1b41SPeter Meerwald pd = (inbuf[0] >> 1) & 0x3; 473f272f19cSAndrew F. Davis data->powerdown = pd > 0; 4746a31c225STomas Novotny data->powerdown_mode = pd ? pd - 1 : 2; /* largest resistor to gnd */ 475cf35ad61SPeter Meerwald data->dac_value = (inbuf[1] << 4) | (inbuf[2] >> 4); 476155da070SBiju Das if (!info->use_ext_ref_voltage) 47729157c6dSTomas Novotny ref = (inbuf[3] >> 3) & 0x3; 47829157c6dSTomas Novotny 479155da070SBiju Das if (!info->use_ext_ref_voltage && ref != data->ref_mode) { 48029157c6dSTomas Novotny dev_info(&client->dev, 48129157c6dSTomas Novotny "voltage reference mode differs (conf: %u, eeprom: %u), setting %u", 48229157c6dSTomas Novotny data->ref_mode, ref, data->ref_mode); 48329157c6dSTomas Novotny err = mcp4726_set_cfg(indio_dev); 48429157c6dSTomas Novotny if (err < 0) 48529157c6dSTomas Novotny goto err_disable_vref_reg; 48629157c6dSTomas Novotny } 487cf35ad61SPeter Meerwald 488b440f1d9STomas Novotny err = iio_device_register(indio_dev); 489b440f1d9STomas Novotny if (err) 49029157c6dSTomas Novotny goto err_disable_vref_reg; 491b440f1d9STomas Novotny 492b440f1d9STomas Novotny return 0; 493b440f1d9STomas Novotny 49429157c6dSTomas Novotny err_disable_vref_reg: 49529157c6dSTomas Novotny if (data->vref_reg) 49629157c6dSTomas Novotny regulator_disable(data->vref_reg); 497b440f1d9STomas Novotny 498b440f1d9STomas Novotny err_disable_vdd_reg: 499b440f1d9STomas Novotny regulator_disable(data->vdd_reg); 500b440f1d9STomas Novotny 501b440f1d9STomas Novotny return err; 502cf35ad61SPeter Meerwald } 503cf35ad61SPeter Meerwald 504ed5c2f5fSUwe Kleine-König static void mcp4725_remove(struct i2c_client *client) 505cf35ad61SPeter Meerwald { 506b440f1d9STomas Novotny struct iio_dev *indio_dev = i2c_get_clientdata(client); 507b440f1d9STomas Novotny struct mcp4725_data *data = iio_priv(indio_dev); 508b440f1d9STomas Novotny 509b440f1d9STomas Novotny iio_device_unregister(indio_dev); 510b440f1d9STomas Novotny 51129157c6dSTomas Novotny if (data->vref_reg) 51229157c6dSTomas Novotny regulator_disable(data->vref_reg); 513b440f1d9STomas Novotny regulator_disable(data->vdd_reg); 514cf35ad61SPeter Meerwald } 515cf35ad61SPeter Meerwald 51618bdc686SBiju Das static const struct mcp4725_chip_info mcp4725 = { 51718bdc686SBiju Das .chan_spec = &mcp472x_channel[MCP4725], 518*c377e2feSBiju Das .dac_reg_offset = 3, 519155da070SBiju Das .use_ext_ref_voltage = true, 52018bdc686SBiju Das }; 52118bdc686SBiju Das 52218bdc686SBiju Das static const struct mcp4725_chip_info mcp4726 = { 52318bdc686SBiju Das .chan_spec = &mcp472x_channel[MCP4726], 524*c377e2feSBiju Das .dac_reg_offset = 4, 52518bdc686SBiju Das }; 52618bdc686SBiju Das 527cf35ad61SPeter Meerwald static const struct i2c_device_id mcp4725_id[] = { 52818bdc686SBiju Das { "mcp4725", (kernel_ulong_t)&mcp4725 }, 52918bdc686SBiju Das { "mcp4726", (kernel_ulong_t)&mcp4726 }, 530cf35ad61SPeter Meerwald { } 531cf35ad61SPeter Meerwald }; 532cf35ad61SPeter Meerwald MODULE_DEVICE_TABLE(i2c, mcp4725_id); 533cf35ad61SPeter Meerwald 5348414af1eSJavier Martinez Canillas static const struct of_device_id mcp4725_of_match[] = { 5358414af1eSJavier Martinez Canillas { 5368414af1eSJavier Martinez Canillas .compatible = "microchip,mcp4725", 53718bdc686SBiju Das .data = &mcp4725 5388414af1eSJavier Martinez Canillas }, 5398414af1eSJavier Martinez Canillas { 5408414af1eSJavier Martinez Canillas .compatible = "microchip,mcp4726", 54118bdc686SBiju Das .data = &mcp4726 5428414af1eSJavier Martinez Canillas }, 5438414af1eSJavier Martinez Canillas { } 5448414af1eSJavier Martinez Canillas }; 5458414af1eSJavier Martinez Canillas MODULE_DEVICE_TABLE(of, mcp4725_of_match); 5468414af1eSJavier Martinez Canillas 547cf35ad61SPeter Meerwald static struct i2c_driver mcp4725_driver = { 548cf35ad61SPeter Meerwald .driver = { 549cf35ad61SPeter Meerwald .name = MCP4725_DRV_NAME, 5502de887b0SJonathan Cameron .of_match_table = mcp4725_of_match, 551bf19b235SJonathan Cameron .pm = pm_sleep_ptr(&mcp4725_pm_ops), 552cf35ad61SPeter Meerwald }, 5537cf15f42SUwe Kleine-König .probe = mcp4725_probe, 554fc52692cSGreg Kroah-Hartman .remove = mcp4725_remove, 555cf35ad61SPeter Meerwald .id_table = mcp4725_id, 556cf35ad61SPeter Meerwald }; 557cf35ad61SPeter Meerwald module_i2c_driver(mcp4725_driver); 558cf35ad61SPeter Meerwald 559cf35ad61SPeter Meerwald MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>"); 56035f73967SAkinobu Mita MODULE_DESCRIPTION("MCP4725/6 12-bit DAC"); 561cf35ad61SPeter Meerwald MODULE_LICENSE("GPL"); 562