250 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * m62332.c - Support for Mitsubishi m62332 DAC4 *5 * Copyright (c) 2014 Dmitry Eremin-Solenikov6 *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 222 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{181 struct m62332_data *data;182 struct iio_dev *indio_dev;183 int ret;184 185 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));186 if (!indio_dev)187 return -ENOMEM;188 189 data = iio_priv(indio_dev);190 i2c_set_clientdata(client, indio_dev);191 data->client = client;192 193 mutex_init(&data->mutex);194 195 data->vcc = devm_regulator_get(&client->dev, "VCC");196 if (IS_ERR(data->vcc))197 return PTR_ERR(data->vcc);198 199 indio_dev->num_channels = ARRAY_SIZE(m62332_channels);200 indio_dev->channels = m62332_channels;201 indio_dev->modes = INDIO_DIRECT_MODE;202 indio_dev->info = &m62332_info;203 204 ret = iio_map_array_register(indio_dev, client->dev.platform_data);205 if (ret < 0)206 return ret;207 208 ret = iio_device_register(indio_dev);209 if (ret < 0)210 goto err;211 212 return 0;213 214err:215 iio_map_array_unregister(indio_dev);216 217 return ret;218}219 220static void m62332_remove(struct i2c_client *client)221{222 struct iio_dev *indio_dev = i2c_get_clientdata(client);223 224 iio_device_unregister(indio_dev);225 iio_map_array_unregister(indio_dev);226 m62332_set_value(indio_dev, 0, 0);227 m62332_set_value(indio_dev, 0, 1);228}229 230static const struct i2c_device_id m62332_id[] = {231 { "m62332", },232 { }233};234MODULE_DEVICE_TABLE(i2c, m62332_id);235 236static struct i2c_driver m62332_driver = {237 .driver = {238 .name = "m62332",239 .pm = pm_sleep_ptr(&m62332_pm_ops),240 },241 .probe = m62332_probe,242 .remove = m62332_remove,243 .id_table = m62332_id,244};245module_i2c_driver(m62332_driver);246 247MODULE_AUTHOR("Dmitry Eremin-Solenikov");248MODULE_DESCRIPTION("M62332 8-bit DAC");249MODULE_LICENSE("GPL v2");250