1 /* 2 * Maxim Integrated 3 * 7-bit, Multi-Channel Sink/Source Current DAC Driver 4 * Copyright (C) 2017 Maxim Integrated 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 */ 10 11 #include <linux/kernel.h> 12 #include <linux/module.h> 13 #include <linux/i2c.h> 14 #include <linux/regulator/consumer.h> 15 #include <linux/err.h> 16 #include <linux/delay.h> 17 #include <linux/iio/iio.h> 18 #include <linux/iio/driver.h> 19 #include <linux/iio/machine.h> 20 #include <linux/iio/consumer.h> 21 22 #define DS4422_MAX_DAC_CHANNELS 2 23 #define DS4424_MAX_DAC_CHANNELS 4 24 25 #define DS4424_DAC_ADDR(chan) ((chan) + 0xf8) 26 #define DS4424_SOURCE_I 1 27 #define DS4424_SINK_I 0 28 29 #define DS4424_CHANNEL(chan) { \ 30 .type = IIO_CURRENT, \ 31 .indexed = 1, \ 32 .output = 1, \ 33 .channel = chan, \ 34 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 35 } 36 37 /* 38 * DS4424 DAC control register 8 bits 39 * [7] 0: to sink; 1: to source 40 * [6:0] steps to sink/source 41 * bit[7] looks like a sign bit, but the value of the register is 42 * not a two's complement code considering the bit[6:0] is a absolute 43 * distance from the zero point. 44 */ 45 union ds4424_raw_data { 46 struct { 47 u8 dx:7; 48 u8 source_bit:1; 49 }; 50 u8 bits; 51 }; 52 53 enum ds4424_device_ids { 54 ID_DS4422, 55 ID_DS4424, 56 }; 57 58 struct ds4424_data { 59 struct i2c_client *client; 60 struct mutex lock; 61 uint8_t save[DS4424_MAX_DAC_CHANNELS]; 62 struct regulator *vcc_reg; 63 uint8_t raw[DS4424_MAX_DAC_CHANNELS]; 64 }; 65 66 static const struct iio_chan_spec ds4424_channels[] = { 67 DS4424_CHANNEL(0), 68 DS4424_CHANNEL(1), 69 DS4424_CHANNEL(2), 70 DS4424_CHANNEL(3), 71 }; 72 73 static int ds4424_get_value(struct iio_dev *indio_dev, 74 int *val, int channel) 75 { 76 struct ds4424_data *data = iio_priv(indio_dev); 77 int ret; 78 79 mutex_lock(&data->lock); 80 ret = i2c_smbus_read_byte_data(data->client, DS4424_DAC_ADDR(channel)); 81 if (ret < 0) 82 goto fail; 83 84 *val = ret; 85 86 fail: 87 mutex_unlock(&data->lock); 88 return ret; 89 } 90 91 static int ds4424_set_value(struct iio_dev *indio_dev, 92 int val, struct iio_chan_spec const *chan) 93 { 94 struct ds4424_data *data = iio_priv(indio_dev); 95 int ret; 96 97 mutex_lock(&data->lock); 98 ret = i2c_smbus_write_byte_data(data->client, 99 DS4424_DAC_ADDR(chan->channel), val); 100 if (ret < 0) 101 goto fail; 102 103 data->raw[chan->channel] = val; 104 105 fail: 106 mutex_unlock(&data->lock); 107 return ret; 108 } 109 110 static int ds4424_read_raw(struct iio_dev *indio_dev, 111 struct iio_chan_spec const *chan, 112 int *val, int *val2, long mask) 113 { 114 union ds4424_raw_data raw; 115 int ret; 116 117 switch (mask) { 118 case IIO_CHAN_INFO_RAW: 119 ret = ds4424_get_value(indio_dev, val, chan->channel); 120 if (ret < 0) { 121 pr_err("%s : ds4424_get_value returned %d\n", 122 __func__, ret); 123 return ret; 124 } 125 raw.bits = *val; 126 *val = raw.dx; 127 if (raw.source_bit == DS4424_SINK_I) 128 *val = -*val; 129 return IIO_VAL_INT; 130 131 default: 132 return -EINVAL; 133 } 134 } 135 136 static int ds4424_write_raw(struct iio_dev *indio_dev, 137 struct iio_chan_spec const *chan, 138 int val, int val2, long mask) 139 { 140 union ds4424_raw_data raw; 141 142 if (val2 != 0) 143 return -EINVAL; 144 145 switch (mask) { 146 case IIO_CHAN_INFO_RAW: 147 if (val < S8_MIN || val > S8_MAX) 148 return -EINVAL; 149 150 if (val > 0) { 151 raw.source_bit = DS4424_SOURCE_I; 152 raw.dx = val; 153 } else { 154 raw.source_bit = DS4424_SINK_I; 155 raw.dx = -val; 156 } 157 158 return ds4424_set_value(indio_dev, raw.bits, chan); 159 160 default: 161 return -EINVAL; 162 } 163 } 164 165 static int ds4424_verify_chip(struct iio_dev *indio_dev) 166 { 167 int ret, val; 168 169 ret = ds4424_get_value(indio_dev, &val, 0); 170 if (ret < 0) 171 dev_err(&indio_dev->dev, 172 "%s failed. ret: %d\n", __func__, ret); 173 174 return ret; 175 } 176 177 static int __maybe_unused ds4424_suspend(struct device *dev) 178 { 179 struct i2c_client *client = to_i2c_client(dev); 180 struct iio_dev *indio_dev = i2c_get_clientdata(client); 181 struct ds4424_data *data = iio_priv(indio_dev); 182 int ret = 0; 183 int i; 184 185 for (i = 0; i < indio_dev->num_channels; i++) { 186 data->save[i] = data->raw[i]; 187 ret = ds4424_set_value(indio_dev, 0, 188 &indio_dev->channels[i]); 189 if (ret < 0) 190 return ret; 191 } 192 return ret; 193 } 194 195 static int __maybe_unused ds4424_resume(struct device *dev) 196 { 197 struct i2c_client *client = to_i2c_client(dev); 198 struct iio_dev *indio_dev = i2c_get_clientdata(client); 199 struct ds4424_data *data = iio_priv(indio_dev); 200 int ret = 0; 201 int i; 202 203 for (i = 0; i < indio_dev->num_channels; i++) { 204 ret = ds4424_set_value(indio_dev, data->save[i], 205 &indio_dev->channels[i]); 206 if (ret < 0) 207 return ret; 208 } 209 return ret; 210 } 211 212 static SIMPLE_DEV_PM_OPS(ds4424_pm_ops, ds4424_suspend, ds4424_resume); 213 214 static const struct iio_info ds4424_info = { 215 .read_raw = ds4424_read_raw, 216 .write_raw = ds4424_write_raw, 217 }; 218 219 static int ds4424_probe(struct i2c_client *client, 220 const struct i2c_device_id *id) 221 { 222 struct ds4424_data *data; 223 struct iio_dev *indio_dev; 224 int ret; 225 226 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 227 if (!indio_dev) { 228 dev_err(&client->dev, "iio dev alloc failed.\n"); 229 return -ENOMEM; 230 } 231 232 data = iio_priv(indio_dev); 233 i2c_set_clientdata(client, indio_dev); 234 data->client = client; 235 indio_dev->name = id->name; 236 indio_dev->dev.of_node = client->dev.of_node; 237 indio_dev->dev.parent = &client->dev; 238 239 data->vcc_reg = devm_regulator_get(&client->dev, "vcc"); 240 if (IS_ERR(data->vcc_reg)) { 241 dev_err(&client->dev, 242 "Failed to get vcc-supply regulator. err: %ld\n", 243 PTR_ERR(data->vcc_reg)); 244 return PTR_ERR(data->vcc_reg); 245 } 246 247 mutex_init(&data->lock); 248 ret = regulator_enable(data->vcc_reg); 249 if (ret < 0) { 250 dev_err(&client->dev, 251 "Unable to enable the regulator.\n"); 252 return ret; 253 } 254 255 usleep_range(1000, 1200); 256 ret = ds4424_verify_chip(indio_dev); 257 if (ret < 0) 258 goto fail; 259 260 switch (id->driver_data) { 261 case ID_DS4422: 262 indio_dev->num_channels = DS4422_MAX_DAC_CHANNELS; 263 break; 264 case ID_DS4424: 265 indio_dev->num_channels = DS4424_MAX_DAC_CHANNELS; 266 break; 267 default: 268 dev_err(&client->dev, 269 "ds4424: Invalid chip id.\n"); 270 ret = -ENXIO; 271 goto fail; 272 } 273 274 indio_dev->channels = ds4424_channels; 275 indio_dev->modes = INDIO_DIRECT_MODE; 276 indio_dev->info = &ds4424_info; 277 278 ret = iio_device_register(indio_dev); 279 if (ret < 0) { 280 dev_err(&client->dev, 281 "iio_device_register failed. ret: %d\n", ret); 282 goto fail; 283 } 284 285 return ret; 286 287 fail: 288 regulator_disable(data->vcc_reg); 289 return ret; 290 } 291 292 static int ds4424_remove(struct i2c_client *client) 293 { 294 struct iio_dev *indio_dev = i2c_get_clientdata(client); 295 struct ds4424_data *data = iio_priv(indio_dev); 296 297 iio_device_unregister(indio_dev); 298 regulator_disable(data->vcc_reg); 299 300 return 0; 301 } 302 303 static const struct i2c_device_id ds4424_id[] = { 304 { "ds4422", ID_DS4422 }, 305 { "ds4424", ID_DS4424 }, 306 { } 307 }; 308 309 MODULE_DEVICE_TABLE(i2c, ds4424_id); 310 311 static const struct of_device_id ds4424_of_match[] = { 312 { .compatible = "maxim,ds4422" }, 313 { .compatible = "maxim,ds4424" }, 314 { }, 315 }; 316 317 MODULE_DEVICE_TABLE(of, ds4424_of_match); 318 319 static struct i2c_driver ds4424_driver = { 320 .driver = { 321 .name = "ds4424", 322 .of_match_table = ds4424_of_match, 323 .pm = &ds4424_pm_ops, 324 }, 325 .probe = ds4424_probe, 326 .remove = ds4424_remove, 327 .id_table = ds4424_id, 328 }; 329 module_i2c_driver(ds4424_driver); 330 331 MODULE_DESCRIPTION("Maxim DS4424 DAC Driver"); 332 MODULE_AUTHOR("Ismail H. Kose <ismail.kose@maximintegrated.com>"); 333 MODULE_AUTHOR("Vishal Sood <vishal.sood@maximintegrated.com>"); 334 MODULE_AUTHOR("David Jung <david.jung@maximintegrated.com>"); 335 MODULE_LICENSE("GPL v2"); 336