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