1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * m62332.c - Support for Mitsubishi m62332 DAC 4 * 5 * Copyright (c) 2014 Dmitry Eremin-Solenikov 6 * 7 * Based on max517 driver: 8 * Copyright (C) 2010, 2011 Roland Stigge <stigge@antcom.de> 9 */ 10 11#include <linux/module.h> 12#include <linux/slab.h> 13#include <linux/i2c.h> 14#include <linux/err.h> 15 16#include <linux/iio/iio.h> 17#include <linux/iio/driver.h> 18 19#include <linux/regulator/consumer.h> 20 21#define M62332_CHANNELS 2 22 23struct m62332_data { 24 struct i2c_client *client; 25 struct regulator *vcc; 26 struct mutex mutex; 27 u8 raw[M62332_CHANNELS]; 28#ifdef CONFIG_PM_SLEEP 29 u8 save[M62332_CHANNELS]; 30#endif 31}; 32 33static int m62332_set_value(struct iio_dev *indio_dev, u8 val, int channel) 34{ 35 struct m62332_data *data = iio_priv(indio_dev); 36 struct i2c_client *client = data->client; 37 u8 outbuf[2]; 38 int res; 39 40 if (val == data->raw[channel]) 41 return 0; 42 43 outbuf[0] = channel; 44 outbuf[1] = val; 45 46 mutex_lock(&data->mutex); 47 48 if (val) { 49 res = regulator_enable(data->vcc); 50 if (res) 51 goto out; 52 } 53 54 res = i2c_master_send(client, outbuf, ARRAY_SIZE(outbuf)); 55 if (res >= 0 && res != ARRAY_SIZE(outbuf)) 56 res = -EIO; 57 if (res < 0) 58 goto out; 59 60 data->raw[channel] = val; 61 62 if (!val) 63 regulator_disable(data->vcc); 64 65 mutex_unlock(&data->mutex); 66 67 return 0; 68 69out: 70 mutex_unlock(&data->mutex); 71 72 return res; 73} 74 75static int m62332_read_raw(struct iio_dev *indio_dev, 76 struct iio_chan_spec const *chan, 77 int *val, 78 int *val2, 79 long mask) 80{ 81 struct m62332_data *data = iio_priv(indio_dev); 82 int ret; 83 84 switch (mask) { 85 case IIO_CHAN_INFO_SCALE: 86 /* Corresponds to Vref / 2^(bits) */ 87 ret = regulator_get_voltage(data->vcc); 88 if (ret < 0) 89 return ret; 90 91 *val = ret / 1000; /* mV */ 92 *val2 = 8; 93 94 return IIO_VAL_FRACTIONAL_LOG2; 95 case IIO_CHAN_INFO_RAW: 96 *val = data->raw[chan->channel]; 97 98 return IIO_VAL_INT; 99 case IIO_CHAN_INFO_OFFSET: 100 *val = 1; 101 102 return IIO_VAL_INT; 103 default: 104 break; 105 } 106 107 return -EINVAL; 108} 109 110static int m62332_write_raw(struct iio_dev *indio_dev, 111 struct iio_chan_spec const *chan, int val, int val2, 112 long mask) 113{ 114 switch (mask) { 115 case IIO_CHAN_INFO_RAW: 116 if (val < 0 || val > 255) 117 return -EINVAL; 118 119 return m62332_set_value(indio_dev, val, chan->channel); 120 default: 121 break; 122 } 123 124 return -EINVAL; 125} 126 127#ifdef CONFIG_PM_SLEEP 128static int m62332_suspend(struct device *dev) 129{ 130 struct i2c_client *client = to_i2c_client(dev); 131 struct iio_dev *indio_dev = i2c_get_clientdata(client); 132 struct m62332_data *data = iio_priv(indio_dev); 133 int ret; 134 135 data->save[0] = data->raw[0]; 136 data->save[1] = data->raw[1]; 137 138 ret = m62332_set_value(indio_dev, 0, 0); 139 if (ret < 0) 140 return ret; 141 142 return m62332_set_value(indio_dev, 0, 1); 143} 144 145static int m62332_resume(struct device *dev) 146{ 147 struct i2c_client *client = to_i2c_client(dev); 148 struct iio_dev *indio_dev = i2c_get_clientdata(client); 149 struct m62332_data *data = iio_priv(indio_dev); 150 int ret; 151 152 ret = m62332_set_value(indio_dev, data->save[0], 0); 153 if (ret < 0) 154 return ret; 155 156 return m62332_set_value(indio_dev, data->save[1], 1); 157} 158 159static SIMPLE_DEV_PM_OPS(m62332_pm_ops, m62332_suspend, m62332_resume); 160#define M62332_PM_OPS (&m62332_pm_ops) 161#else 162#define M62332_PM_OPS NULL 163#endif 164 165static const struct iio_info m62332_info = { 166 .read_raw = m62332_read_raw, 167 .write_raw = m62332_write_raw, 168}; 169 170#define M62332_CHANNEL(chan) { \ 171 .type = IIO_VOLTAGE, \ 172 .indexed = 1, \ 173 .output = 1, \ 174 .channel = (chan), \ 175 .datasheet_name = "CH" #chan, \ 176 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 177 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ 178 BIT(IIO_CHAN_INFO_OFFSET), \ 179} 180 181static const struct iio_chan_spec m62332_channels[M62332_CHANNELS] = { 182 M62332_CHANNEL(0), 183 M62332_CHANNEL(1) 184}; 185 186static int m62332_probe(struct i2c_client *client, 187 const struct i2c_device_id *id) 188{ 189 struct m62332_data *data; 190 struct iio_dev *indio_dev; 191 int ret; 192 193 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 194 if (!indio_dev) 195 return -ENOMEM; 196 197 data = iio_priv(indio_dev); 198 i2c_set_clientdata(client, indio_dev); 199 data->client = client; 200 201 mutex_init(&data->mutex); 202 203 data->vcc = devm_regulator_get(&client->dev, "VCC"); 204 if (IS_ERR(data->vcc)) 205 return PTR_ERR(data->vcc); 206 207 indio_dev->num_channels = ARRAY_SIZE(m62332_channels); 208 indio_dev->channels = m62332_channels; 209 indio_dev->modes = INDIO_DIRECT_MODE; 210 indio_dev->info = &m62332_info; 211 212 ret = iio_map_array_register(indio_dev, client->dev.platform_data); 213 if (ret < 0) 214 return ret; 215 216 ret = iio_device_register(indio_dev); 217 if (ret < 0) 218 goto err; 219 220 return 0; 221 222err: 223 iio_map_array_unregister(indio_dev); 224 225 return ret; 226} 227 228static int m62332_remove(struct i2c_client *client) 229{ 230 struct iio_dev *indio_dev = i2c_get_clientdata(client); 231 232 iio_device_unregister(indio_dev); 233 iio_map_array_unregister(indio_dev); 234 m62332_set_value(indio_dev, 0, 0); 235 m62332_set_value(indio_dev, 0, 1); 236 237 return 0; 238} 239 240static const struct i2c_device_id m62332_id[] = { 241 { "m62332", }, 242 { } 243}; 244MODULE_DEVICE_TABLE(i2c, m62332_id); 245 246static struct i2c_driver m62332_driver = { 247 .driver = { 248 .name = "m62332", 249 .pm = M62332_PM_OPS, 250 }, 251 .probe = m62332_probe, 252 .remove = m62332_remove, 253 .id_table = m62332_id, 254}; 255module_i2c_driver(m62332_driver); 256 257MODULE_AUTHOR("Dmitry Eremin-Solenikov"); 258MODULE_DESCRIPTION("M62332 8-bit DAC"); 259MODULE_LICENSE("GPL v2"); 260