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 33cf35ad61SPeter Meerwald struct mcp4725_data { 34cf35ad61SPeter Meerwald struct i2c_client *client; 3529157c6dSTomas Novotny int id; 3629157c6dSTomas Novotny unsigned ref_mode; 3729157c6dSTomas Novotny bool vref_buffered; 38cf35ad61SPeter Meerwald u16 dac_value; 39155f1b41SPeter Meerwald bool powerdown; 40155f1b41SPeter Meerwald unsigned powerdown_mode; 41b440f1d9STomas Novotny struct regulator *vdd_reg; 4229157c6dSTomas Novotny struct regulator *vref_reg; 43cf35ad61SPeter Meerwald }; 44cf35ad61SPeter Meerwald 451a5bc41aSMarcus Folkesson static int __maybe_unused mcp4725_suspend(struct device *dev) 46cf35ad61SPeter Meerwald { 47a97dd069SPeter Meerwald struct mcp4725_data *data = iio_priv(i2c_get_clientdata( 48a97dd069SPeter Meerwald to_i2c_client(dev))); 49cf35ad61SPeter Meerwald u8 outbuf[2]; 50cf35ad61SPeter Meerwald 51155f1b41SPeter Meerwald outbuf[0] = (data->powerdown_mode + 1) << 4; 52cf35ad61SPeter Meerwald outbuf[1] = 0; 53155f1b41SPeter Meerwald data->powerdown = true; 54cf35ad61SPeter Meerwald 55a97dd069SPeter Meerwald return i2c_master_send(data->client, outbuf, 2); 56cf35ad61SPeter Meerwald } 57cf35ad61SPeter Meerwald 581a5bc41aSMarcus Folkesson static int __maybe_unused mcp4725_resume(struct device *dev) 59cf35ad61SPeter Meerwald { 60a97dd069SPeter Meerwald struct mcp4725_data *data = iio_priv(i2c_get_clientdata( 61a97dd069SPeter Meerwald to_i2c_client(dev))); 62cf35ad61SPeter Meerwald u8 outbuf[2]; 63cf35ad61SPeter Meerwald 64cf35ad61SPeter Meerwald /* restore previous DAC value */ 65cf35ad61SPeter Meerwald outbuf[0] = (data->dac_value >> 8) & 0xf; 66cf35ad61SPeter Meerwald outbuf[1] = data->dac_value & 0xff; 67155f1b41SPeter Meerwald data->powerdown = false; 68cf35ad61SPeter Meerwald 69a97dd069SPeter Meerwald return i2c_master_send(data->client, outbuf, 2); 70cf35ad61SPeter Meerwald } 71cf35ad61SPeter Meerwald static SIMPLE_DEV_PM_OPS(mcp4725_pm_ops, mcp4725_suspend, mcp4725_resume); 72cf35ad61SPeter Meerwald 734fd313daSJonathan Cameron static ssize_t mcp4725_store_eeprom(struct device *dev, 74f17b77d6SPeter Meerwald struct device_attribute *attr, const char *buf, size_t len) 75f17b77d6SPeter Meerwald { 76f17b77d6SPeter Meerwald struct iio_dev *indio_dev = dev_to_iio_dev(dev); 77f17b77d6SPeter Meerwald struct mcp4725_data *data = iio_priv(indio_dev); 78f17b77d6SPeter Meerwald int tries = 20; 79f17b77d6SPeter Meerwald u8 inoutbuf[3]; 80f17b77d6SPeter Meerwald bool state; 81f17b77d6SPeter Meerwald int ret; 82f17b77d6SPeter Meerwald 83f17b77d6SPeter Meerwald ret = strtobool(buf, &state); 84f17b77d6SPeter Meerwald if (ret < 0) 85f17b77d6SPeter Meerwald return ret; 86f17b77d6SPeter Meerwald 87f17b77d6SPeter Meerwald if (!state) 88f17b77d6SPeter Meerwald return 0; 89f17b77d6SPeter Meerwald 90f17b77d6SPeter Meerwald inoutbuf[0] = 0x60; /* write EEPROM */ 9129157c6dSTomas Novotny inoutbuf[0] |= data->ref_mode << 3; 9206003531SJean-Francois Dagenais inoutbuf[0] |= data->powerdown ? ((data->powerdown_mode + 1) << 1) : 0; 93f17b77d6SPeter Meerwald inoutbuf[1] = data->dac_value >> 4; 94f17b77d6SPeter Meerwald inoutbuf[2] = (data->dac_value & 0xf) << 4; 95f17b77d6SPeter Meerwald 96f17b77d6SPeter Meerwald ret = i2c_master_send(data->client, inoutbuf, 3); 97f17b77d6SPeter Meerwald if (ret < 0) 98f17b77d6SPeter Meerwald return ret; 99f17b77d6SPeter Meerwald else if (ret != 3) 100f17b77d6SPeter Meerwald return -EIO; 101f17b77d6SPeter Meerwald 102f17b77d6SPeter Meerwald /* wait for write complete, takes up to 50ms */ 103f17b77d6SPeter Meerwald while (tries--) { 104f17b77d6SPeter Meerwald msleep(20); 105f17b77d6SPeter Meerwald ret = i2c_master_recv(data->client, inoutbuf, 3); 106f17b77d6SPeter Meerwald if (ret < 0) 107f17b77d6SPeter Meerwald return ret; 108f17b77d6SPeter Meerwald else if (ret != 3) 109f17b77d6SPeter Meerwald return -EIO; 110f17b77d6SPeter Meerwald 111f17b77d6SPeter Meerwald if (inoutbuf[0] & 0x80) 112f17b77d6SPeter Meerwald break; 113f17b77d6SPeter Meerwald } 114f17b77d6SPeter Meerwald 115f17b77d6SPeter Meerwald if (tries < 0) { 116f17b77d6SPeter Meerwald dev_err(&data->client->dev, 117f17b77d6SPeter Meerwald "mcp4725_store_eeprom() failed, incomplete\n"); 118f17b77d6SPeter Meerwald return -EIO; 119f17b77d6SPeter Meerwald } 120f17b77d6SPeter Meerwald 121f17b77d6SPeter Meerwald return len; 122f17b77d6SPeter Meerwald } 123f17b77d6SPeter Meerwald 124f17b77d6SPeter Meerwald static IIO_DEVICE_ATTR(store_eeprom, S_IWUSR, NULL, mcp4725_store_eeprom, 0); 125f17b77d6SPeter Meerwald 126f17b77d6SPeter Meerwald static struct attribute *mcp4725_attributes[] = { 127f17b77d6SPeter Meerwald &iio_dev_attr_store_eeprom.dev_attr.attr, 128f17b77d6SPeter Meerwald NULL, 129f17b77d6SPeter Meerwald }; 130f17b77d6SPeter Meerwald 131f17b77d6SPeter Meerwald static const struct attribute_group mcp4725_attribute_group = { 132f17b77d6SPeter Meerwald .attrs = mcp4725_attributes, 133f17b77d6SPeter Meerwald }; 134f17b77d6SPeter Meerwald 135155f1b41SPeter Meerwald static const char * const mcp4725_powerdown_modes[] = { 136155f1b41SPeter Meerwald "1kohm_to_gnd", 137155f1b41SPeter Meerwald "100kohm_to_gnd", 138155f1b41SPeter Meerwald "500kohm_to_gnd" 139155f1b41SPeter Meerwald }; 140155f1b41SPeter Meerwald 14135f73967SAkinobu Mita static const char * const mcp4726_powerdown_modes[] = { 14235f73967SAkinobu Mita "1kohm_to_gnd", 14335f73967SAkinobu Mita "125kohm_to_gnd", 14435f73967SAkinobu Mita "640kohm_to_gnd" 14535f73967SAkinobu Mita }; 14635f73967SAkinobu Mita 147155f1b41SPeter Meerwald static int mcp4725_get_powerdown_mode(struct iio_dev *indio_dev, 148155f1b41SPeter Meerwald const struct iio_chan_spec *chan) 149155f1b41SPeter Meerwald { 150155f1b41SPeter Meerwald struct mcp4725_data *data = iio_priv(indio_dev); 151155f1b41SPeter Meerwald 152155f1b41SPeter Meerwald return data->powerdown_mode; 153155f1b41SPeter Meerwald } 154155f1b41SPeter Meerwald 155155f1b41SPeter Meerwald static int mcp4725_set_powerdown_mode(struct iio_dev *indio_dev, 156155f1b41SPeter Meerwald const struct iio_chan_spec *chan, unsigned mode) 157155f1b41SPeter Meerwald { 158155f1b41SPeter Meerwald struct mcp4725_data *data = iio_priv(indio_dev); 159155f1b41SPeter Meerwald 160155f1b41SPeter Meerwald data->powerdown_mode = mode; 161155f1b41SPeter Meerwald 162155f1b41SPeter Meerwald return 0; 163155f1b41SPeter Meerwald } 164155f1b41SPeter Meerwald 165155f1b41SPeter Meerwald static ssize_t mcp4725_read_powerdown(struct iio_dev *indio_dev, 166155f1b41SPeter Meerwald uintptr_t private, const struct iio_chan_spec *chan, char *buf) 167155f1b41SPeter Meerwald { 168155f1b41SPeter Meerwald struct mcp4725_data *data = iio_priv(indio_dev); 169155f1b41SPeter Meerwald 170f46ac009SLars-Peter Clausen return sysfs_emit(buf, "%d\n", data->powerdown); 171155f1b41SPeter Meerwald } 172155f1b41SPeter Meerwald 173155f1b41SPeter Meerwald static ssize_t mcp4725_write_powerdown(struct iio_dev *indio_dev, 174155f1b41SPeter Meerwald uintptr_t private, const struct iio_chan_spec *chan, 175155f1b41SPeter Meerwald const char *buf, size_t len) 176155f1b41SPeter Meerwald { 177155f1b41SPeter Meerwald struct mcp4725_data *data = iio_priv(indio_dev); 178155f1b41SPeter Meerwald bool state; 179155f1b41SPeter Meerwald int ret; 180155f1b41SPeter Meerwald 181155f1b41SPeter Meerwald ret = strtobool(buf, &state); 182155f1b41SPeter Meerwald if (ret) 183155f1b41SPeter Meerwald return ret; 184155f1b41SPeter Meerwald 185155f1b41SPeter Meerwald if (state) 186155f1b41SPeter Meerwald ret = mcp4725_suspend(&data->client->dev); 187155f1b41SPeter Meerwald else 188155f1b41SPeter Meerwald ret = mcp4725_resume(&data->client->dev); 189155f1b41SPeter Meerwald if (ret < 0) 190155f1b41SPeter Meerwald return ret; 191155f1b41SPeter Meerwald 192155f1b41SPeter Meerwald return len; 193155f1b41SPeter Meerwald } 194155f1b41SPeter Meerwald 1958414af1eSJavier Martinez Canillas enum chip_id { 19635f73967SAkinobu Mita MCP4725, 19735f73967SAkinobu Mita MCP4726, 19835f73967SAkinobu Mita }; 19935f73967SAkinobu Mita 20035f73967SAkinobu Mita static const struct iio_enum mcp472x_powerdown_mode_enum[] = { 20135f73967SAkinobu Mita [MCP4725] = { 202155f1b41SPeter Meerwald .items = mcp4725_powerdown_modes, 203155f1b41SPeter Meerwald .num_items = ARRAY_SIZE(mcp4725_powerdown_modes), 204155f1b41SPeter Meerwald .get = mcp4725_get_powerdown_mode, 205155f1b41SPeter Meerwald .set = mcp4725_set_powerdown_mode, 20635f73967SAkinobu Mita }, 20735f73967SAkinobu Mita [MCP4726] = { 20835f73967SAkinobu Mita .items = mcp4726_powerdown_modes, 20935f73967SAkinobu Mita .num_items = ARRAY_SIZE(mcp4726_powerdown_modes), 21035f73967SAkinobu Mita .get = mcp4725_get_powerdown_mode, 21135f73967SAkinobu Mita .set = mcp4725_set_powerdown_mode, 21235f73967SAkinobu Mita }, 213155f1b41SPeter Meerwald }; 214155f1b41SPeter Meerwald 215155f1b41SPeter Meerwald static const struct iio_chan_spec_ext_info mcp4725_ext_info[] = { 216155f1b41SPeter Meerwald { 217155f1b41SPeter Meerwald .name = "powerdown", 218155f1b41SPeter Meerwald .read = mcp4725_read_powerdown, 219155f1b41SPeter Meerwald .write = mcp4725_write_powerdown, 2203704432fSJonathan Cameron .shared = IIO_SEPARATE, 221155f1b41SPeter Meerwald }, 22235f73967SAkinobu Mita IIO_ENUM("powerdown_mode", IIO_SEPARATE, 22335f73967SAkinobu Mita &mcp472x_powerdown_mode_enum[MCP4725]), 224*ffc7c517SAntoniu Miclaus IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, 22535f73967SAkinobu Mita &mcp472x_powerdown_mode_enum[MCP4725]), 226155f1b41SPeter Meerwald { }, 227155f1b41SPeter Meerwald }; 228155f1b41SPeter Meerwald 22935f73967SAkinobu Mita static const struct iio_chan_spec_ext_info mcp4726_ext_info[] = { 23035f73967SAkinobu Mita { 23135f73967SAkinobu Mita .name = "powerdown", 23235f73967SAkinobu Mita .read = mcp4725_read_powerdown, 23335f73967SAkinobu Mita .write = mcp4725_write_powerdown, 23435f73967SAkinobu Mita .shared = IIO_SEPARATE, 23535f73967SAkinobu Mita }, 23635f73967SAkinobu Mita IIO_ENUM("powerdown_mode", IIO_SEPARATE, 23735f73967SAkinobu Mita &mcp472x_powerdown_mode_enum[MCP4726]), 238*ffc7c517SAntoniu Miclaus IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, 23935f73967SAkinobu Mita &mcp472x_powerdown_mode_enum[MCP4726]), 24035f73967SAkinobu Mita { }, 24135f73967SAkinobu Mita }; 24235f73967SAkinobu Mita 24335f73967SAkinobu Mita static const struct iio_chan_spec mcp472x_channel[] = { 24435f73967SAkinobu Mita [MCP4725] = { 245cf35ad61SPeter Meerwald .type = IIO_VOLTAGE, 246cf35ad61SPeter Meerwald .indexed = 1, 247cf35ad61SPeter Meerwald .output = 1, 248cf35ad61SPeter Meerwald .channel = 0, 24990b46374SJonathan Cameron .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 25090b46374SJonathan Cameron .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), 251155f1b41SPeter Meerwald .ext_info = mcp4725_ext_info, 25235f73967SAkinobu Mita }, 25335f73967SAkinobu Mita [MCP4726] = { 25435f73967SAkinobu Mita .type = IIO_VOLTAGE, 25535f73967SAkinobu Mita .indexed = 1, 25635f73967SAkinobu Mita .output = 1, 25735f73967SAkinobu Mita .channel = 0, 25835f73967SAkinobu Mita .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 25935f73967SAkinobu Mita .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), 26035f73967SAkinobu Mita .ext_info = mcp4726_ext_info, 26135f73967SAkinobu Mita }, 262cf35ad61SPeter Meerwald }; 263cf35ad61SPeter Meerwald 264cf35ad61SPeter Meerwald static int mcp4725_set_value(struct iio_dev *indio_dev, int val) 265cf35ad61SPeter Meerwald { 266cf35ad61SPeter Meerwald struct mcp4725_data *data = iio_priv(indio_dev); 267cf35ad61SPeter Meerwald u8 outbuf[2]; 268cf35ad61SPeter Meerwald int ret; 269cf35ad61SPeter Meerwald 270cf35ad61SPeter Meerwald if (val >= (1 << 12) || val < 0) 271cf35ad61SPeter Meerwald return -EINVAL; 272cf35ad61SPeter Meerwald 273cf35ad61SPeter Meerwald outbuf[0] = (val >> 8) & 0xf; 274cf35ad61SPeter Meerwald outbuf[1] = val & 0xff; 275cf35ad61SPeter Meerwald 276cf35ad61SPeter Meerwald ret = i2c_master_send(data->client, outbuf, 2); 277cf35ad61SPeter Meerwald if (ret < 0) 278cf35ad61SPeter Meerwald return ret; 279cf35ad61SPeter Meerwald else if (ret != 2) 280cf35ad61SPeter Meerwald return -EIO; 281cf35ad61SPeter Meerwald else 282cf35ad61SPeter Meerwald return 0; 283cf35ad61SPeter Meerwald } 284cf35ad61SPeter Meerwald 28529157c6dSTomas Novotny static int mcp4726_set_cfg(struct iio_dev *indio_dev) 28629157c6dSTomas Novotny { 28729157c6dSTomas Novotny struct mcp4725_data *data = iio_priv(indio_dev); 28829157c6dSTomas Novotny u8 outbuf[3]; 28929157c6dSTomas Novotny int ret; 29029157c6dSTomas Novotny 29129157c6dSTomas Novotny outbuf[0] = 0x40; 29229157c6dSTomas Novotny outbuf[0] |= data->ref_mode << 3; 29329157c6dSTomas Novotny if (data->powerdown) 29429157c6dSTomas Novotny outbuf[0] |= data->powerdown << 1; 29529157c6dSTomas Novotny outbuf[1] = data->dac_value >> 4; 29629157c6dSTomas Novotny outbuf[2] = (data->dac_value & 0xf) << 4; 29729157c6dSTomas Novotny 29829157c6dSTomas Novotny ret = i2c_master_send(data->client, outbuf, 3); 29929157c6dSTomas Novotny if (ret < 0) 30029157c6dSTomas Novotny return ret; 30129157c6dSTomas Novotny else if (ret != 3) 30229157c6dSTomas Novotny return -EIO; 30329157c6dSTomas Novotny else 30429157c6dSTomas Novotny return 0; 30529157c6dSTomas Novotny } 30629157c6dSTomas Novotny 307cf35ad61SPeter Meerwald static int mcp4725_read_raw(struct iio_dev *indio_dev, 308cf35ad61SPeter Meerwald struct iio_chan_spec const *chan, 309cf35ad61SPeter Meerwald int *val, int *val2, long mask) 310cf35ad61SPeter Meerwald { 311cf35ad61SPeter Meerwald struct mcp4725_data *data = iio_priv(indio_dev); 312b440f1d9STomas Novotny int ret; 313cf35ad61SPeter Meerwald 314cf35ad61SPeter Meerwald switch (mask) { 315cf35ad61SPeter Meerwald case IIO_CHAN_INFO_RAW: 316cf35ad61SPeter Meerwald *val = data->dac_value; 317cf35ad61SPeter Meerwald return IIO_VAL_INT; 318cf35ad61SPeter Meerwald case IIO_CHAN_INFO_SCALE: 31929157c6dSTomas Novotny if (data->ref_mode == MCP472X_REF_VDD) 320b440f1d9STomas Novotny ret = regulator_get_voltage(data->vdd_reg); 32129157c6dSTomas Novotny else 32229157c6dSTomas Novotny ret = regulator_get_voltage(data->vref_reg); 32329157c6dSTomas Novotny 324b440f1d9STomas Novotny if (ret < 0) 325b440f1d9STomas Novotny return ret; 326b440f1d9STomas Novotny 327b440f1d9STomas Novotny *val = ret / 1000; 328b117f96fSLars-Peter Clausen *val2 = 12; 329b117f96fSLars-Peter Clausen return IIO_VAL_FRACTIONAL_LOG2; 330cf35ad61SPeter Meerwald } 331cf35ad61SPeter Meerwald return -EINVAL; 332cf35ad61SPeter Meerwald } 333cf35ad61SPeter Meerwald 334cf35ad61SPeter Meerwald static int mcp4725_write_raw(struct iio_dev *indio_dev, 335cf35ad61SPeter Meerwald struct iio_chan_spec const *chan, 336cf35ad61SPeter Meerwald int val, int val2, long mask) 337cf35ad61SPeter Meerwald { 338cf35ad61SPeter Meerwald struct mcp4725_data *data = iio_priv(indio_dev); 339cf35ad61SPeter Meerwald int ret; 340cf35ad61SPeter Meerwald 341cf35ad61SPeter Meerwald switch (mask) { 342cf35ad61SPeter Meerwald case IIO_CHAN_INFO_RAW: 343cf35ad61SPeter Meerwald ret = mcp4725_set_value(indio_dev, val); 344cf35ad61SPeter Meerwald data->dac_value = val; 345cf35ad61SPeter Meerwald break; 346cf35ad61SPeter Meerwald default: 347cf35ad61SPeter Meerwald ret = -EINVAL; 348cf35ad61SPeter Meerwald break; 349cf35ad61SPeter Meerwald } 350cf35ad61SPeter Meerwald 351cf35ad61SPeter Meerwald return ret; 352cf35ad61SPeter Meerwald } 353cf35ad61SPeter Meerwald 354cf35ad61SPeter Meerwald static const struct iio_info mcp4725_info = { 355cf35ad61SPeter Meerwald .read_raw = mcp4725_read_raw, 356cf35ad61SPeter Meerwald .write_raw = mcp4725_write_raw, 357f17b77d6SPeter Meerwald .attrs = &mcp4725_attribute_group, 358cf35ad61SPeter Meerwald }; 359cf35ad61SPeter Meerwald 36088e39a88STomas Novotny static int mcp4725_probe_dt(struct device *dev, 36188e39a88STomas Novotny struct mcp4725_platform_data *pdata) 36288e39a88STomas Novotny { 36388e39a88STomas Novotny /* check if is the vref-supply defined */ 3642de887b0SJonathan Cameron pdata->use_vref = device_property_read_bool(dev, "vref-supply"); 36588e39a88STomas Novotny pdata->vref_buffered = 3662de887b0SJonathan Cameron device_property_read_bool(dev, "microchip,vref-buffered"); 36788e39a88STomas Novotny 36888e39a88STomas Novotny return 0; 36988e39a88STomas Novotny } 37088e39a88STomas Novotny 371fc52692cSGreg Kroah-Hartman static int mcp4725_probe(struct i2c_client *client, 372cf35ad61SPeter Meerwald const struct i2c_device_id *id) 373cf35ad61SPeter Meerwald { 374cf35ad61SPeter Meerwald struct mcp4725_data *data; 375cf35ad61SPeter Meerwald struct iio_dev *indio_dev; 37688e39a88STomas Novotny struct mcp4725_platform_data *pdata, pdata_dt; 37729157c6dSTomas Novotny u8 inbuf[4]; 378155f1b41SPeter Meerwald u8 pd; 37929157c6dSTomas Novotny u8 ref; 380cf35ad61SPeter Meerwald int err; 381cf35ad61SPeter Meerwald 382b6ff86f3SPeter Meerwald indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 383b6ff86f3SPeter Meerwald if (indio_dev == NULL) 384b6ff86f3SPeter Meerwald return -ENOMEM; 385cf35ad61SPeter Meerwald data = iio_priv(indio_dev); 386cf35ad61SPeter Meerwald i2c_set_clientdata(client, indio_dev); 387cf35ad61SPeter Meerwald data->client = client; 3882de887b0SJonathan Cameron if (dev_fwnode(&client->dev)) 3892de887b0SJonathan Cameron data->id = (enum chip_id)device_get_match_data(&client->dev); 3908414af1eSJavier Martinez Canillas else 39129157c6dSTomas Novotny data->id = id->driver_data; 39288e39a88STomas Novotny pdata = dev_get_platdata(&client->dev); 39388e39a88STomas Novotny 39488e39a88STomas Novotny if (!pdata) { 39588e39a88STomas Novotny err = mcp4725_probe_dt(&client->dev, &pdata_dt); 39688e39a88STomas Novotny if (err) { 39788e39a88STomas Novotny dev_err(&client->dev, 39888e39a88STomas Novotny "invalid platform or devicetree data"); 39988e39a88STomas Novotny return err; 40088e39a88STomas Novotny } 40188e39a88STomas Novotny pdata = &pdata_dt; 40288e39a88STomas Novotny } 40329157c6dSTomas Novotny 40429157c6dSTomas Novotny if (data->id == MCP4725 && pdata->use_vref) { 40529157c6dSTomas Novotny dev_err(&client->dev, 40629157c6dSTomas Novotny "external reference is unavailable on MCP4725"); 40729157c6dSTomas Novotny return -EINVAL; 40829157c6dSTomas Novotny } 40929157c6dSTomas Novotny 41029157c6dSTomas Novotny if (!pdata->use_vref && pdata->vref_buffered) { 41129157c6dSTomas Novotny dev_err(&client->dev, 41229157c6dSTomas Novotny "buffering is unavailable on the internal reference"); 41329157c6dSTomas Novotny return -EINVAL; 41429157c6dSTomas Novotny } 41529157c6dSTomas Novotny 41629157c6dSTomas Novotny if (!pdata->use_vref) 41729157c6dSTomas Novotny data->ref_mode = MCP472X_REF_VDD; 41829157c6dSTomas Novotny else 41929157c6dSTomas Novotny data->ref_mode = pdata->vref_buffered ? 42029157c6dSTomas Novotny MCP472X_REF_VREF_BUFFERED : 42129157c6dSTomas Novotny MCP472X_REF_VREF_UNBUFFERED; 422cf35ad61SPeter Meerwald 423b440f1d9STomas Novotny data->vdd_reg = devm_regulator_get(&client->dev, "vdd"); 424b440f1d9STomas Novotny if (IS_ERR(data->vdd_reg)) 425b440f1d9STomas Novotny return PTR_ERR(data->vdd_reg); 426b440f1d9STomas Novotny 427b440f1d9STomas Novotny err = regulator_enable(data->vdd_reg); 428b440f1d9STomas Novotny if (err) 429b440f1d9STomas Novotny return err; 430b440f1d9STomas Novotny 43129157c6dSTomas Novotny if (pdata->use_vref) { 43229157c6dSTomas Novotny data->vref_reg = devm_regulator_get(&client->dev, "vref"); 43329157c6dSTomas Novotny if (IS_ERR(data->vref_reg)) { 43430df2d18SJulia Lawall err = PTR_ERR(data->vref_reg); 43529157c6dSTomas Novotny goto err_disable_vdd_reg; 43629157c6dSTomas Novotny } 43729157c6dSTomas Novotny 43829157c6dSTomas Novotny err = regulator_enable(data->vref_reg); 43929157c6dSTomas Novotny if (err) 44029157c6dSTomas Novotny goto err_disable_vdd_reg; 44129157c6dSTomas Novotny } 44229157c6dSTomas Novotny 44397a249e9SYong Li indio_dev->name = id->name; 444cf35ad61SPeter Meerwald indio_dev->info = &mcp4725_info; 44535f73967SAkinobu Mita indio_dev->channels = &mcp472x_channel[id->driver_data]; 446cf35ad61SPeter Meerwald indio_dev->num_channels = 1; 447cf35ad61SPeter Meerwald indio_dev->modes = INDIO_DIRECT_MODE; 448cf35ad61SPeter Meerwald 44929157c6dSTomas Novotny /* read current DAC value and settings */ 45029157c6dSTomas Novotny err = i2c_master_recv(client, inbuf, data->id == MCP4725 ? 3 : 4); 45129157c6dSTomas Novotny 452cf35ad61SPeter Meerwald if (err < 0) { 453cf35ad61SPeter Meerwald dev_err(&client->dev, "failed to read DAC value"); 45429157c6dSTomas Novotny goto err_disable_vref_reg; 455cf35ad61SPeter Meerwald } 456155f1b41SPeter Meerwald pd = (inbuf[0] >> 1) & 0x3; 457f272f19cSAndrew F. Davis data->powerdown = pd > 0; 4586a31c225STomas Novotny data->powerdown_mode = pd ? pd - 1 : 2; /* largest resistor to gnd */ 459cf35ad61SPeter Meerwald data->dac_value = (inbuf[1] << 4) | (inbuf[2] >> 4); 46029157c6dSTomas Novotny if (data->id == MCP4726) 46129157c6dSTomas Novotny ref = (inbuf[3] >> 3) & 0x3; 46229157c6dSTomas Novotny 46329157c6dSTomas Novotny if (data->id == MCP4726 && ref != data->ref_mode) { 46429157c6dSTomas Novotny dev_info(&client->dev, 46529157c6dSTomas Novotny "voltage reference mode differs (conf: %u, eeprom: %u), setting %u", 46629157c6dSTomas Novotny data->ref_mode, ref, data->ref_mode); 46729157c6dSTomas Novotny err = mcp4726_set_cfg(indio_dev); 46829157c6dSTomas Novotny if (err < 0) 46929157c6dSTomas Novotny goto err_disable_vref_reg; 47029157c6dSTomas Novotny } 471cf35ad61SPeter Meerwald 472b440f1d9STomas Novotny err = iio_device_register(indio_dev); 473b440f1d9STomas Novotny if (err) 47429157c6dSTomas Novotny goto err_disable_vref_reg; 475b440f1d9STomas Novotny 476b440f1d9STomas Novotny return 0; 477b440f1d9STomas Novotny 47829157c6dSTomas Novotny err_disable_vref_reg: 47929157c6dSTomas Novotny if (data->vref_reg) 48029157c6dSTomas Novotny regulator_disable(data->vref_reg); 481b440f1d9STomas Novotny 482b440f1d9STomas Novotny err_disable_vdd_reg: 483b440f1d9STomas Novotny regulator_disable(data->vdd_reg); 484b440f1d9STomas Novotny 485b440f1d9STomas Novotny return err; 486cf35ad61SPeter Meerwald } 487cf35ad61SPeter Meerwald 488fc52692cSGreg Kroah-Hartman static int mcp4725_remove(struct i2c_client *client) 489cf35ad61SPeter Meerwald { 490b440f1d9STomas Novotny struct iio_dev *indio_dev = i2c_get_clientdata(client); 491b440f1d9STomas Novotny struct mcp4725_data *data = iio_priv(indio_dev); 492b440f1d9STomas Novotny 493b440f1d9STomas Novotny iio_device_unregister(indio_dev); 494b440f1d9STomas Novotny 49529157c6dSTomas Novotny if (data->vref_reg) 49629157c6dSTomas Novotny regulator_disable(data->vref_reg); 497b440f1d9STomas Novotny regulator_disable(data->vdd_reg); 498b440f1d9STomas Novotny 499cf35ad61SPeter Meerwald return 0; 500cf35ad61SPeter Meerwald } 501cf35ad61SPeter Meerwald 502cf35ad61SPeter Meerwald static const struct i2c_device_id mcp4725_id[] = { 50335f73967SAkinobu Mita { "mcp4725", MCP4725 }, 50435f73967SAkinobu Mita { "mcp4726", MCP4726 }, 505cf35ad61SPeter Meerwald { } 506cf35ad61SPeter Meerwald }; 507cf35ad61SPeter Meerwald MODULE_DEVICE_TABLE(i2c, mcp4725_id); 508cf35ad61SPeter Meerwald 5098414af1eSJavier Martinez Canillas static const struct of_device_id mcp4725_of_match[] = { 5108414af1eSJavier Martinez Canillas { 5118414af1eSJavier Martinez Canillas .compatible = "microchip,mcp4725", 5128414af1eSJavier Martinez Canillas .data = (void *)MCP4725 5138414af1eSJavier Martinez Canillas }, 5148414af1eSJavier Martinez Canillas { 5158414af1eSJavier Martinez Canillas .compatible = "microchip,mcp4726", 5168414af1eSJavier Martinez Canillas .data = (void *)MCP4726 5178414af1eSJavier Martinez Canillas }, 5188414af1eSJavier Martinez Canillas { } 5198414af1eSJavier Martinez Canillas }; 5208414af1eSJavier Martinez Canillas MODULE_DEVICE_TABLE(of, mcp4725_of_match); 5218414af1eSJavier Martinez Canillas 522cf35ad61SPeter Meerwald static struct i2c_driver mcp4725_driver = { 523cf35ad61SPeter Meerwald .driver = { 524cf35ad61SPeter Meerwald .name = MCP4725_DRV_NAME, 5252de887b0SJonathan Cameron .of_match_table = mcp4725_of_match, 5261a5bc41aSMarcus Folkesson .pm = &mcp4725_pm_ops, 527cf35ad61SPeter Meerwald }, 528cf35ad61SPeter Meerwald .probe = mcp4725_probe, 529fc52692cSGreg Kroah-Hartman .remove = mcp4725_remove, 530cf35ad61SPeter Meerwald .id_table = mcp4725_id, 531cf35ad61SPeter Meerwald }; 532cf35ad61SPeter Meerwald module_i2c_driver(mcp4725_driver); 533cf35ad61SPeter Meerwald 534cf35ad61SPeter Meerwald MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>"); 53535f73967SAkinobu Mita MODULE_DESCRIPTION("MCP4725/6 12-bit DAC"); 536cf35ad61SPeter Meerwald MODULE_LICENSE("GPL"); 537