1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2fbbc5e70SSlawomir Stepien /* 3fbbc5e70SSlawomir Stepien * Maxim Integrated DS1803 digital potentiometer driver 4fbbc5e70SSlawomir Stepien * Copyright (c) 2016 Slawomir Stepien 5fbbc5e70SSlawomir Stepien * 6fbbc5e70SSlawomir Stepien * Datasheet: https://datasheets.maximintegrated.com/en/ds/DS1803.pdf 7fbbc5e70SSlawomir Stepien * 8fbbc5e70SSlawomir Stepien * DEVID #Wipers #Positions Resistor Opts (kOhm) i2c address 9fbbc5e70SSlawomir Stepien * ds1803 2 256 10, 50, 100 0101xxx 10fbbc5e70SSlawomir Stepien */ 11fbbc5e70SSlawomir Stepien 12fbbc5e70SSlawomir Stepien #include <linux/err.h> 13fbbc5e70SSlawomir Stepien #include <linux/export.h> 14fbbc5e70SSlawomir Stepien #include <linux/i2c.h> 15fbbc5e70SSlawomir Stepien #include <linux/iio/iio.h> 16fbbc5e70SSlawomir Stepien #include <linux/module.h> 17*c34bed92SJonathan Cameron #include <linux/mod_devicetable.h> 18fbbc5e70SSlawomir Stepien 19fbbc5e70SSlawomir Stepien #define DS1803_MAX_POS 255 20fbbc5e70SSlawomir Stepien #define DS1803_WRITE(chan) (0xa8 | ((chan) + 1)) 21fbbc5e70SSlawomir Stepien 22fbbc5e70SSlawomir Stepien enum ds1803_type { 23fbbc5e70SSlawomir Stepien DS1803_010, 24fbbc5e70SSlawomir Stepien DS1803_050, 25fbbc5e70SSlawomir Stepien DS1803_100, 26fbbc5e70SSlawomir Stepien }; 27fbbc5e70SSlawomir Stepien 28fbbc5e70SSlawomir Stepien struct ds1803_cfg { 29fbbc5e70SSlawomir Stepien int kohms; 30fbbc5e70SSlawomir Stepien }; 31fbbc5e70SSlawomir Stepien 32fbbc5e70SSlawomir Stepien static const struct ds1803_cfg ds1803_cfg[] = { 33fbbc5e70SSlawomir Stepien [DS1803_010] = { .kohms = 10, }, 34fbbc5e70SSlawomir Stepien [DS1803_050] = { .kohms = 50, }, 35fbbc5e70SSlawomir Stepien [DS1803_100] = { .kohms = 100, }, 36fbbc5e70SSlawomir Stepien }; 37fbbc5e70SSlawomir Stepien 38fbbc5e70SSlawomir Stepien struct ds1803_data { 39fbbc5e70SSlawomir Stepien struct i2c_client *client; 40fbbc5e70SSlawomir Stepien const struct ds1803_cfg *cfg; 41fbbc5e70SSlawomir Stepien }; 42fbbc5e70SSlawomir Stepien 43fbbc5e70SSlawomir Stepien #define DS1803_CHANNEL(ch) { \ 44fbbc5e70SSlawomir Stepien .type = IIO_RESISTANCE, \ 45fbbc5e70SSlawomir Stepien .indexed = 1, \ 46fbbc5e70SSlawomir Stepien .output = 1, \ 47fbbc5e70SSlawomir Stepien .channel = (ch), \ 48fbbc5e70SSlawomir Stepien .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 49fbbc5e70SSlawomir Stepien .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 50fbbc5e70SSlawomir Stepien } 51fbbc5e70SSlawomir Stepien 52fbbc5e70SSlawomir Stepien static const struct iio_chan_spec ds1803_channels[] = { 53fbbc5e70SSlawomir Stepien DS1803_CHANNEL(0), 54fbbc5e70SSlawomir Stepien DS1803_CHANNEL(1), 55fbbc5e70SSlawomir Stepien }; 56fbbc5e70SSlawomir Stepien 57fbbc5e70SSlawomir Stepien static int ds1803_read_raw(struct iio_dev *indio_dev, 58fbbc5e70SSlawomir Stepien struct iio_chan_spec const *chan, 59fbbc5e70SSlawomir Stepien int *val, int *val2, long mask) 60fbbc5e70SSlawomir Stepien { 61fbbc5e70SSlawomir Stepien struct ds1803_data *data = iio_priv(indio_dev); 62fbbc5e70SSlawomir Stepien int pot = chan->channel; 63fbbc5e70SSlawomir Stepien int ret; 64a937729cSHimanshu Jha u8 result[ARRAY_SIZE(ds1803_channels)]; 65fbbc5e70SSlawomir Stepien 66fbbc5e70SSlawomir Stepien switch (mask) { 67fbbc5e70SSlawomir Stepien case IIO_CHAN_INFO_RAW: 68fbbc5e70SSlawomir Stepien ret = i2c_master_recv(data->client, result, 69fbbc5e70SSlawomir Stepien indio_dev->num_channels); 70fbbc5e70SSlawomir Stepien if (ret < 0) 71fbbc5e70SSlawomir Stepien return ret; 72fbbc5e70SSlawomir Stepien 73fbbc5e70SSlawomir Stepien *val = result[pot]; 74fbbc5e70SSlawomir Stepien return IIO_VAL_INT; 75fbbc5e70SSlawomir Stepien 76fbbc5e70SSlawomir Stepien case IIO_CHAN_INFO_SCALE: 77fbbc5e70SSlawomir Stepien *val = 1000 * data->cfg->kohms; 78fbbc5e70SSlawomir Stepien *val2 = DS1803_MAX_POS; 79fbbc5e70SSlawomir Stepien return IIO_VAL_FRACTIONAL; 80fbbc5e70SSlawomir Stepien } 81fbbc5e70SSlawomir Stepien 82fbbc5e70SSlawomir Stepien return -EINVAL; 83fbbc5e70SSlawomir Stepien } 84fbbc5e70SSlawomir Stepien 85fbbc5e70SSlawomir Stepien static int ds1803_write_raw(struct iio_dev *indio_dev, 86fbbc5e70SSlawomir Stepien struct iio_chan_spec const *chan, 87fbbc5e70SSlawomir Stepien int val, int val2, long mask) 88fbbc5e70SSlawomir Stepien { 89fbbc5e70SSlawomir Stepien struct ds1803_data *data = iio_priv(indio_dev); 90fbbc5e70SSlawomir Stepien int pot = chan->channel; 91fbbc5e70SSlawomir Stepien 92fbbc5e70SSlawomir Stepien if (val2 != 0) 93fbbc5e70SSlawomir Stepien return -EINVAL; 94fbbc5e70SSlawomir Stepien 95fbbc5e70SSlawomir Stepien switch (mask) { 96fbbc5e70SSlawomir Stepien case IIO_CHAN_INFO_RAW: 97fbbc5e70SSlawomir Stepien if (val > DS1803_MAX_POS || val < 0) 98fbbc5e70SSlawomir Stepien return -EINVAL; 99fbbc5e70SSlawomir Stepien break; 100fbbc5e70SSlawomir Stepien default: 101fbbc5e70SSlawomir Stepien return -EINVAL; 102fbbc5e70SSlawomir Stepien } 103fbbc5e70SSlawomir Stepien 104fbbc5e70SSlawomir Stepien return i2c_smbus_write_byte_data(data->client, DS1803_WRITE(pot), val); 105fbbc5e70SSlawomir Stepien } 106fbbc5e70SSlawomir Stepien 107fbbc5e70SSlawomir Stepien static const struct iio_info ds1803_info = { 108fbbc5e70SSlawomir Stepien .read_raw = ds1803_read_raw, 109fbbc5e70SSlawomir Stepien .write_raw = ds1803_write_raw, 110fbbc5e70SSlawomir Stepien }; 111fbbc5e70SSlawomir Stepien 112fbbc5e70SSlawomir Stepien static int ds1803_probe(struct i2c_client *client, 113fbbc5e70SSlawomir Stepien const struct i2c_device_id *id) 114fbbc5e70SSlawomir Stepien { 115fbbc5e70SSlawomir Stepien struct device *dev = &client->dev; 116fbbc5e70SSlawomir Stepien struct ds1803_data *data; 117fbbc5e70SSlawomir Stepien struct iio_dev *indio_dev; 118fbbc5e70SSlawomir Stepien 119fbbc5e70SSlawomir Stepien indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); 120fbbc5e70SSlawomir Stepien if (!indio_dev) 121fbbc5e70SSlawomir Stepien return -ENOMEM; 122fbbc5e70SSlawomir Stepien 123fbbc5e70SSlawomir Stepien i2c_set_clientdata(client, indio_dev); 124fbbc5e70SSlawomir Stepien 125fbbc5e70SSlawomir Stepien data = iio_priv(indio_dev); 126fbbc5e70SSlawomir Stepien data->client = client; 127fbbc5e70SSlawomir Stepien data->cfg = &ds1803_cfg[id->driver_data]; 128fbbc5e70SSlawomir Stepien 129fbbc5e70SSlawomir Stepien indio_dev->info = &ds1803_info; 130fbbc5e70SSlawomir Stepien indio_dev->channels = ds1803_channels; 131fbbc5e70SSlawomir Stepien indio_dev->num_channels = ARRAY_SIZE(ds1803_channels); 132fbbc5e70SSlawomir Stepien indio_dev->name = client->name; 133fbbc5e70SSlawomir Stepien 134fbbc5e70SSlawomir Stepien return devm_iio_device_register(dev, indio_dev); 135fbbc5e70SSlawomir Stepien } 136fbbc5e70SSlawomir Stepien 137fbbc5e70SSlawomir Stepien static const struct of_device_id ds1803_dt_ids[] = { 138fbbc5e70SSlawomir Stepien { .compatible = "maxim,ds1803-010", .data = &ds1803_cfg[DS1803_010] }, 139fbbc5e70SSlawomir Stepien { .compatible = "maxim,ds1803-050", .data = &ds1803_cfg[DS1803_050] }, 140fbbc5e70SSlawomir Stepien { .compatible = "maxim,ds1803-100", .data = &ds1803_cfg[DS1803_100] }, 141fbbc5e70SSlawomir Stepien {} 142fbbc5e70SSlawomir Stepien }; 143fbbc5e70SSlawomir Stepien MODULE_DEVICE_TABLE(of, ds1803_dt_ids); 144fbbc5e70SSlawomir Stepien 145fbbc5e70SSlawomir Stepien static const struct i2c_device_id ds1803_id[] = { 146fbbc5e70SSlawomir Stepien { "ds1803-010", DS1803_010 }, 147fbbc5e70SSlawomir Stepien { "ds1803-050", DS1803_050 }, 148fbbc5e70SSlawomir Stepien { "ds1803-100", DS1803_100 }, 149fbbc5e70SSlawomir Stepien {} 150fbbc5e70SSlawomir Stepien }; 151fbbc5e70SSlawomir Stepien MODULE_DEVICE_TABLE(i2c, ds1803_id); 152fbbc5e70SSlawomir Stepien 153fbbc5e70SSlawomir Stepien static struct i2c_driver ds1803_driver = { 154fbbc5e70SSlawomir Stepien .driver = { 155fbbc5e70SSlawomir Stepien .name = "ds1803", 156*c34bed92SJonathan Cameron .of_match_table = ds1803_dt_ids, 157fbbc5e70SSlawomir Stepien }, 158fbbc5e70SSlawomir Stepien .probe = ds1803_probe, 159fbbc5e70SSlawomir Stepien .id_table = ds1803_id, 160fbbc5e70SSlawomir Stepien }; 161fbbc5e70SSlawomir Stepien 162fbbc5e70SSlawomir Stepien module_i2c_driver(ds1803_driver); 163fbbc5e70SSlawomir Stepien 164fbbc5e70SSlawomir Stepien MODULE_AUTHOR("Slawomir Stepien <sst@poczta.fm>"); 165fbbc5e70SSlawomir Stepien MODULE_DESCRIPTION("DS1803 digital potentiometer"); 166fbbc5e70SSlawomir Stepien MODULE_LICENSE("GPL v2"); 167