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