1*dbdc025bSLars-Peter Clausen /* 2*dbdc025bSLars-Peter Clausen * max517.c - Support for Maxim MAX517, MAX518 and MAX519 3*dbdc025bSLars-Peter Clausen * 4*dbdc025bSLars-Peter Clausen * Copyright (C) 2010, 2011 Roland Stigge <stigge@antcom.de> 5*dbdc025bSLars-Peter Clausen * 6*dbdc025bSLars-Peter Clausen * This program is free software; you can redistribute it and/or modify 7*dbdc025bSLars-Peter Clausen * it under the terms of the GNU General Public License as published by 8*dbdc025bSLars-Peter Clausen * the Free Software Foundation; either version 2 of the License, or 9*dbdc025bSLars-Peter Clausen * (at your option) any later version. 10*dbdc025bSLars-Peter Clausen * 11*dbdc025bSLars-Peter Clausen * This program is distributed in the hope that it will be useful, 12*dbdc025bSLars-Peter Clausen * but WITHOUT ANY WARRANTY; without even the implied warranty of 13*dbdc025bSLars-Peter Clausen * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14*dbdc025bSLars-Peter Clausen * GNU General Public License for more details. 15*dbdc025bSLars-Peter Clausen * 16*dbdc025bSLars-Peter Clausen * You should have received a copy of the GNU General Public License 17*dbdc025bSLars-Peter Clausen * along with this program; if not, write to the Free Software 18*dbdc025bSLars-Peter Clausen * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19*dbdc025bSLars-Peter Clausen */ 20*dbdc025bSLars-Peter Clausen 21*dbdc025bSLars-Peter Clausen #include <linux/module.h> 22*dbdc025bSLars-Peter Clausen #include <linux/init.h> 23*dbdc025bSLars-Peter Clausen #include <linux/slab.h> 24*dbdc025bSLars-Peter Clausen #include <linux/jiffies.h> 25*dbdc025bSLars-Peter Clausen #include <linux/i2c.h> 26*dbdc025bSLars-Peter Clausen #include <linux/err.h> 27*dbdc025bSLars-Peter Clausen 28*dbdc025bSLars-Peter Clausen #include <linux/iio/iio.h> 29*dbdc025bSLars-Peter Clausen #include <linux/iio/sysfs.h> 30*dbdc025bSLars-Peter Clausen #include <linux/iio/dac/max517.h> 31*dbdc025bSLars-Peter Clausen 32*dbdc025bSLars-Peter Clausen #define MAX517_DRV_NAME "max517" 33*dbdc025bSLars-Peter Clausen 34*dbdc025bSLars-Peter Clausen /* Commands */ 35*dbdc025bSLars-Peter Clausen #define COMMAND_CHANNEL0 0x00 36*dbdc025bSLars-Peter Clausen #define COMMAND_CHANNEL1 0x01 /* for MAX518 and MAX519 */ 37*dbdc025bSLars-Peter Clausen #define COMMAND_PD 0x08 /* Power Down */ 38*dbdc025bSLars-Peter Clausen 39*dbdc025bSLars-Peter Clausen enum max517_device_ids { 40*dbdc025bSLars-Peter Clausen ID_MAX517, 41*dbdc025bSLars-Peter Clausen ID_MAX518, 42*dbdc025bSLars-Peter Clausen ID_MAX519, 43*dbdc025bSLars-Peter Clausen }; 44*dbdc025bSLars-Peter Clausen 45*dbdc025bSLars-Peter Clausen struct max517_data { 46*dbdc025bSLars-Peter Clausen struct iio_dev *indio_dev; 47*dbdc025bSLars-Peter Clausen struct i2c_client *client; 48*dbdc025bSLars-Peter Clausen unsigned short vref_mv[2]; 49*dbdc025bSLars-Peter Clausen }; 50*dbdc025bSLars-Peter Clausen 51*dbdc025bSLars-Peter Clausen /* 52*dbdc025bSLars-Peter Clausen * channel: bit 0: channel 1 53*dbdc025bSLars-Peter Clausen * bit 1: channel 2 54*dbdc025bSLars-Peter Clausen * (this way, it's possible to set both channels at once) 55*dbdc025bSLars-Peter Clausen */ 56*dbdc025bSLars-Peter Clausen static int max517_set_value(struct iio_dev *indio_dev, 57*dbdc025bSLars-Peter Clausen long val, int channel) 58*dbdc025bSLars-Peter Clausen { 59*dbdc025bSLars-Peter Clausen struct max517_data *data = iio_priv(indio_dev); 60*dbdc025bSLars-Peter Clausen struct i2c_client *client = data->client; 61*dbdc025bSLars-Peter Clausen u8 outbuf[2]; 62*dbdc025bSLars-Peter Clausen int res; 63*dbdc025bSLars-Peter Clausen 64*dbdc025bSLars-Peter Clausen if (val < 0 || val > 255) 65*dbdc025bSLars-Peter Clausen return -EINVAL; 66*dbdc025bSLars-Peter Clausen 67*dbdc025bSLars-Peter Clausen outbuf[0] = channel; 68*dbdc025bSLars-Peter Clausen outbuf[1] = val; 69*dbdc025bSLars-Peter Clausen 70*dbdc025bSLars-Peter Clausen res = i2c_master_send(client, outbuf, 2); 71*dbdc025bSLars-Peter Clausen if (res < 0) 72*dbdc025bSLars-Peter Clausen return res; 73*dbdc025bSLars-Peter Clausen else if (res != 2) 74*dbdc025bSLars-Peter Clausen return -EIO; 75*dbdc025bSLars-Peter Clausen else 76*dbdc025bSLars-Peter Clausen return 0; 77*dbdc025bSLars-Peter Clausen } 78*dbdc025bSLars-Peter Clausen 79*dbdc025bSLars-Peter Clausen static int max517_read_raw(struct iio_dev *indio_dev, 80*dbdc025bSLars-Peter Clausen struct iio_chan_spec const *chan, 81*dbdc025bSLars-Peter Clausen int *val, 82*dbdc025bSLars-Peter Clausen int *val2, 83*dbdc025bSLars-Peter Clausen long m) 84*dbdc025bSLars-Peter Clausen { 85*dbdc025bSLars-Peter Clausen struct max517_data *data = iio_priv(indio_dev); 86*dbdc025bSLars-Peter Clausen unsigned int scale_uv; 87*dbdc025bSLars-Peter Clausen 88*dbdc025bSLars-Peter Clausen switch (m) { 89*dbdc025bSLars-Peter Clausen case IIO_CHAN_INFO_SCALE: 90*dbdc025bSLars-Peter Clausen /* Corresponds to Vref / 2^(bits) */ 91*dbdc025bSLars-Peter Clausen scale_uv = (data->vref_mv[chan->channel] * 1000) >> 8; 92*dbdc025bSLars-Peter Clausen *val = scale_uv / 1000000; 93*dbdc025bSLars-Peter Clausen *val2 = scale_uv % 1000000; 94*dbdc025bSLars-Peter Clausen return IIO_VAL_INT_PLUS_MICRO; 95*dbdc025bSLars-Peter Clausen default: 96*dbdc025bSLars-Peter Clausen break; 97*dbdc025bSLars-Peter Clausen } 98*dbdc025bSLars-Peter Clausen return -EINVAL; 99*dbdc025bSLars-Peter Clausen } 100*dbdc025bSLars-Peter Clausen 101*dbdc025bSLars-Peter Clausen static int max517_write_raw(struct iio_dev *indio_dev, 102*dbdc025bSLars-Peter Clausen struct iio_chan_spec const *chan, int val, int val2, long mask) 103*dbdc025bSLars-Peter Clausen { 104*dbdc025bSLars-Peter Clausen int ret; 105*dbdc025bSLars-Peter Clausen 106*dbdc025bSLars-Peter Clausen switch (mask) { 107*dbdc025bSLars-Peter Clausen case IIO_CHAN_INFO_RAW: 108*dbdc025bSLars-Peter Clausen ret = max517_set_value(indio_dev, val, chan->channel); 109*dbdc025bSLars-Peter Clausen break; 110*dbdc025bSLars-Peter Clausen default: 111*dbdc025bSLars-Peter Clausen ret = -EINVAL; 112*dbdc025bSLars-Peter Clausen break; 113*dbdc025bSLars-Peter Clausen } 114*dbdc025bSLars-Peter Clausen 115*dbdc025bSLars-Peter Clausen return ret; 116*dbdc025bSLars-Peter Clausen } 117*dbdc025bSLars-Peter Clausen 118*dbdc025bSLars-Peter Clausen #ifdef CONFIG_PM_SLEEP 119*dbdc025bSLars-Peter Clausen static int max517_suspend(struct device *dev) 120*dbdc025bSLars-Peter Clausen { 121*dbdc025bSLars-Peter Clausen u8 outbuf = COMMAND_PD; 122*dbdc025bSLars-Peter Clausen 123*dbdc025bSLars-Peter Clausen return i2c_master_send(to_i2c_client(dev), &outbuf, 1); 124*dbdc025bSLars-Peter Clausen } 125*dbdc025bSLars-Peter Clausen 126*dbdc025bSLars-Peter Clausen static int max517_resume(struct device *dev) 127*dbdc025bSLars-Peter Clausen { 128*dbdc025bSLars-Peter Clausen u8 outbuf = 0; 129*dbdc025bSLars-Peter Clausen 130*dbdc025bSLars-Peter Clausen return i2c_master_send(to_i2c_client(dev), &outbuf, 1); 131*dbdc025bSLars-Peter Clausen } 132*dbdc025bSLars-Peter Clausen 133*dbdc025bSLars-Peter Clausen static SIMPLE_DEV_PM_OPS(max517_pm_ops, max517_suspend, max517_resume); 134*dbdc025bSLars-Peter Clausen #define MAX517_PM_OPS (&max517_pm_ops) 135*dbdc025bSLars-Peter Clausen #else 136*dbdc025bSLars-Peter Clausen #define MAX517_PM_OPS NULL 137*dbdc025bSLars-Peter Clausen #endif 138*dbdc025bSLars-Peter Clausen 139*dbdc025bSLars-Peter Clausen static const struct iio_info max517_info = { 140*dbdc025bSLars-Peter Clausen .read_raw = max517_read_raw, 141*dbdc025bSLars-Peter Clausen .write_raw = max517_write_raw, 142*dbdc025bSLars-Peter Clausen .driver_module = THIS_MODULE, 143*dbdc025bSLars-Peter Clausen }; 144*dbdc025bSLars-Peter Clausen 145*dbdc025bSLars-Peter Clausen #define MAX517_CHANNEL(chan) { \ 146*dbdc025bSLars-Peter Clausen .type = IIO_VOLTAGE, \ 147*dbdc025bSLars-Peter Clausen .indexed = 1, \ 148*dbdc025bSLars-Peter Clausen .output = 1, \ 149*dbdc025bSLars-Peter Clausen .channel = (chan), \ 150*dbdc025bSLars-Peter Clausen .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ 151*dbdc025bSLars-Peter Clausen IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ 152*dbdc025bSLars-Peter Clausen .scan_type = IIO_ST('u', 8, 8, 0), \ 153*dbdc025bSLars-Peter Clausen } 154*dbdc025bSLars-Peter Clausen 155*dbdc025bSLars-Peter Clausen static const struct iio_chan_spec max517_channels[] = { 156*dbdc025bSLars-Peter Clausen MAX517_CHANNEL(0), 157*dbdc025bSLars-Peter Clausen MAX517_CHANNEL(1) 158*dbdc025bSLars-Peter Clausen }; 159*dbdc025bSLars-Peter Clausen 160*dbdc025bSLars-Peter Clausen static int max517_probe(struct i2c_client *client, 161*dbdc025bSLars-Peter Clausen const struct i2c_device_id *id) 162*dbdc025bSLars-Peter Clausen { 163*dbdc025bSLars-Peter Clausen struct max517_data *data; 164*dbdc025bSLars-Peter Clausen struct iio_dev *indio_dev; 165*dbdc025bSLars-Peter Clausen struct max517_platform_data *platform_data = client->dev.platform_data; 166*dbdc025bSLars-Peter Clausen int err; 167*dbdc025bSLars-Peter Clausen 168*dbdc025bSLars-Peter Clausen indio_dev = iio_device_alloc(sizeof(*data)); 169*dbdc025bSLars-Peter Clausen if (indio_dev == NULL) { 170*dbdc025bSLars-Peter Clausen err = -ENOMEM; 171*dbdc025bSLars-Peter Clausen goto exit; 172*dbdc025bSLars-Peter Clausen } 173*dbdc025bSLars-Peter Clausen data = iio_priv(indio_dev); 174*dbdc025bSLars-Peter Clausen i2c_set_clientdata(client, indio_dev); 175*dbdc025bSLars-Peter Clausen data->client = client; 176*dbdc025bSLars-Peter Clausen 177*dbdc025bSLars-Peter Clausen /* establish that the iio_dev is a child of the i2c device */ 178*dbdc025bSLars-Peter Clausen indio_dev->dev.parent = &client->dev; 179*dbdc025bSLars-Peter Clausen 180*dbdc025bSLars-Peter Clausen /* reduced channel set for MAX517 */ 181*dbdc025bSLars-Peter Clausen if (id->driver_data == ID_MAX517) 182*dbdc025bSLars-Peter Clausen indio_dev->num_channels = 1; 183*dbdc025bSLars-Peter Clausen else 184*dbdc025bSLars-Peter Clausen indio_dev->num_channels = 2; 185*dbdc025bSLars-Peter Clausen indio_dev->channels = max517_channels; 186*dbdc025bSLars-Peter Clausen indio_dev->modes = INDIO_DIRECT_MODE; 187*dbdc025bSLars-Peter Clausen indio_dev->info = &max517_info; 188*dbdc025bSLars-Peter Clausen 189*dbdc025bSLars-Peter Clausen /* 190*dbdc025bSLars-Peter Clausen * Reference voltage on MAX518 and default is 5V, else take vref_mv 191*dbdc025bSLars-Peter Clausen * from platform_data 192*dbdc025bSLars-Peter Clausen */ 193*dbdc025bSLars-Peter Clausen if (id->driver_data == ID_MAX518 || !platform_data) { 194*dbdc025bSLars-Peter Clausen data->vref_mv[0] = data->vref_mv[1] = 5000; /* mV */ 195*dbdc025bSLars-Peter Clausen } else { 196*dbdc025bSLars-Peter Clausen data->vref_mv[0] = platform_data->vref_mv[0]; 197*dbdc025bSLars-Peter Clausen data->vref_mv[1] = platform_data->vref_mv[1]; 198*dbdc025bSLars-Peter Clausen } 199*dbdc025bSLars-Peter Clausen 200*dbdc025bSLars-Peter Clausen err = iio_device_register(indio_dev); 201*dbdc025bSLars-Peter Clausen if (err) 202*dbdc025bSLars-Peter Clausen goto exit_free_device; 203*dbdc025bSLars-Peter Clausen 204*dbdc025bSLars-Peter Clausen dev_info(&client->dev, "DAC registered\n"); 205*dbdc025bSLars-Peter Clausen 206*dbdc025bSLars-Peter Clausen return 0; 207*dbdc025bSLars-Peter Clausen 208*dbdc025bSLars-Peter Clausen exit_free_device: 209*dbdc025bSLars-Peter Clausen iio_device_free(indio_dev); 210*dbdc025bSLars-Peter Clausen exit: 211*dbdc025bSLars-Peter Clausen return err; 212*dbdc025bSLars-Peter Clausen } 213*dbdc025bSLars-Peter Clausen 214*dbdc025bSLars-Peter Clausen static int max517_remove(struct i2c_client *client) 215*dbdc025bSLars-Peter Clausen { 216*dbdc025bSLars-Peter Clausen iio_device_unregister(i2c_get_clientdata(client)); 217*dbdc025bSLars-Peter Clausen iio_device_free(i2c_get_clientdata(client)); 218*dbdc025bSLars-Peter Clausen 219*dbdc025bSLars-Peter Clausen return 0; 220*dbdc025bSLars-Peter Clausen } 221*dbdc025bSLars-Peter Clausen 222*dbdc025bSLars-Peter Clausen static const struct i2c_device_id max517_id[] = { 223*dbdc025bSLars-Peter Clausen { "max517", ID_MAX517 }, 224*dbdc025bSLars-Peter Clausen { "max518", ID_MAX518 }, 225*dbdc025bSLars-Peter Clausen { "max519", ID_MAX519 }, 226*dbdc025bSLars-Peter Clausen { } 227*dbdc025bSLars-Peter Clausen }; 228*dbdc025bSLars-Peter Clausen MODULE_DEVICE_TABLE(i2c, max517_id); 229*dbdc025bSLars-Peter Clausen 230*dbdc025bSLars-Peter Clausen static struct i2c_driver max517_driver = { 231*dbdc025bSLars-Peter Clausen .driver = { 232*dbdc025bSLars-Peter Clausen .name = MAX517_DRV_NAME, 233*dbdc025bSLars-Peter Clausen .pm = MAX517_PM_OPS, 234*dbdc025bSLars-Peter Clausen }, 235*dbdc025bSLars-Peter Clausen .probe = max517_probe, 236*dbdc025bSLars-Peter Clausen .remove = max517_remove, 237*dbdc025bSLars-Peter Clausen .id_table = max517_id, 238*dbdc025bSLars-Peter Clausen }; 239*dbdc025bSLars-Peter Clausen module_i2c_driver(max517_driver); 240*dbdc025bSLars-Peter Clausen 241*dbdc025bSLars-Peter Clausen MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>"); 242*dbdc025bSLars-Peter Clausen MODULE_DESCRIPTION("MAX517/MAX518/MAX519 8-bit DAC"); 243*dbdc025bSLars-Peter Clausen MODULE_LICENSE("GPL"); 244