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, DS4424_DAC_ADDR(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 if (!client->dev.of_node) { 240 dev_err(&client->dev, 241 "Not found DT.\n"); 242 return -ENODEV; 243 } 244 245 data->vcc_reg = devm_regulator_get(&client->dev, "vcc"); 246 if (IS_ERR(data->vcc_reg)) { 247 dev_err(&client->dev, 248 "Failed to get vcc-supply regulator. err: %ld\n", 249 PTR_ERR(data->vcc_reg)); 250 return PTR_ERR(data->vcc_reg); 251 } 252 253 mutex_init(&data->lock); 254 ret = regulator_enable(data->vcc_reg); 255 if (ret < 0) { 256 dev_err(&client->dev, 257 "Unable to enable the regulator.\n"); 258 return ret; 259 } 260 261 usleep_range(1000, 1200); 262 ret = ds4424_verify_chip(indio_dev); 263 if (ret < 0) 264 goto fail; 265 266 switch (id->driver_data) { 267 case ID_DS4422: 268 indio_dev->num_channels = DS4422_MAX_DAC_CHANNELS; 269 break; 270 case ID_DS4424: 271 indio_dev->num_channels = DS4424_MAX_DAC_CHANNELS; 272 break; 273 default: 274 dev_err(&client->dev, 275 "ds4424: Invalid chip id.\n"); 276 ret = -ENXIO; 277 goto fail; 278 } 279 280 indio_dev->channels = ds4424_channels; 281 indio_dev->modes = INDIO_DIRECT_MODE; 282 indio_dev->info = &ds4424_info; 283 284 ret = iio_device_register(indio_dev); 285 if (ret < 0) { 286 dev_err(&client->dev, 287 "iio_device_register failed. ret: %d\n", ret); 288 goto fail; 289 } 290 291 return ret; 292 293 fail: 294 regulator_disable(data->vcc_reg); 295 return ret; 296 } 297 298 static int ds4424_remove(struct i2c_client *client) 299 { 300 struct iio_dev *indio_dev = i2c_get_clientdata(client); 301 struct ds4424_data *data = iio_priv(indio_dev); 302 303 iio_device_unregister(indio_dev); 304 regulator_disable(data->vcc_reg); 305 306 return 0; 307 } 308 309 static const struct i2c_device_id ds4424_id[] = { 310 { "ds4422", ID_DS4422 }, 311 { "ds4424", ID_DS4424 }, 312 { } 313 }; 314 315 MODULE_DEVICE_TABLE(i2c, ds4424_id); 316 317 static const struct of_device_id ds4424_of_match[] = { 318 { .compatible = "maxim,ds4422" }, 319 { .compatible = "maxim,ds4424" }, 320 { }, 321 }; 322 323 MODULE_DEVICE_TABLE(of, ds4424_of_match); 324 325 static struct i2c_driver ds4424_driver = { 326 .driver = { 327 .name = "ds4424", 328 .of_match_table = ds4424_of_match, 329 .pm = &ds4424_pm_ops, 330 }, 331 .probe = ds4424_probe, 332 .remove = ds4424_remove, 333 .id_table = ds4424_id, 334 }; 335 module_i2c_driver(ds4424_driver); 336 337 MODULE_DESCRIPTION("Maxim DS4424 DAC Driver"); 338 MODULE_AUTHOR("Ismail H. Kose <ismail.kose@maximintegrated.com>"); 339 MODULE_AUTHOR("Vishal Sood <vishal.sood@maximintegrated.com>"); 340 MODULE_AUTHOR("David Jung <david.jung@maximintegrated.com>"); 341 MODULE_LICENSE("GPL v2"); 342