2 * Copyright (C) 2013 Oskar Andero <oskar.andero@gmail.com>
4 * Driver for Microchip Technology's MCP3204 and MCP3208 ADC chips.
5 * Datasheet can be found here:
6 * http://ww1.microchip.com/downloads/en/devicedoc/21298c.pdf
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
13 #include <linux/err.h>
14 #include <linux/spi/spi.h>
15 #include <linux/module.h>
16 #include <linux/iio/iio.h>
17 #include <linux/regulator/consumer.h>
19 #define MCP_SINGLE_ENDED (1 << 3)
20 #define MCP_START_BIT (1 << 4)
28 struct spi_device
*spi
;
29 struct spi_message msg
;
30 struct spi_transfer transfer
[2];
35 struct regulator
*reg
;
39 static int mcp320x_adc_conversion(struct mcp320x
*adc
, u8 msg
)
44 ret
= spi_sync(adc
->spi
, &adc
->msg
);
48 return ((adc
->rx_buf
[0] & 0x3f) << 6) |
49 (adc
->rx_buf
[1] >> 2);
52 static int mcp320x_read_raw(struct iio_dev
*indio_dev
,
53 struct iio_chan_spec
const *channel
, int *val
,
56 struct mcp320x
*adc
= iio_priv(indio_dev
);
59 mutex_lock(&adc
->lock
);
62 case IIO_CHAN_INFO_RAW
:
63 if (channel
->differential
)
64 ret
= mcp320x_adc_conversion(adc
,
65 MCP_START_BIT
| channel
->address
);
67 ret
= mcp320x_adc_conversion(adc
,
68 MCP_START_BIT
| MCP_SINGLE_ENDED
|
77 case IIO_CHAN_INFO_SCALE
:
78 /* Digital output code = (4096 * Vin) / Vref */
79 ret
= regulator_get_voltage(adc
->reg
);
85 ret
= IIO_VAL_FRACTIONAL_LOG2
;
93 mutex_unlock(&adc
->lock
);
98 #define MCP320X_VOLTAGE_CHANNEL(num) \
100 .type = IIO_VOLTAGE, \
104 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
105 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \
108 #define MCP320X_VOLTAGE_CHANNEL_DIFF(num) \
110 .type = IIO_VOLTAGE, \
112 .channel = (num * 2), \
113 .channel2 = (num * 2 + 1), \
114 .address = (num * 2), \
116 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
117 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \
120 static const struct iio_chan_spec mcp3204_channels
[] = {
121 MCP320X_VOLTAGE_CHANNEL(0),
122 MCP320X_VOLTAGE_CHANNEL(1),
123 MCP320X_VOLTAGE_CHANNEL(2),
124 MCP320X_VOLTAGE_CHANNEL(3),
125 MCP320X_VOLTAGE_CHANNEL_DIFF(0),
126 MCP320X_VOLTAGE_CHANNEL_DIFF(1),
129 static const struct iio_chan_spec mcp3208_channels
[] = {
130 MCP320X_VOLTAGE_CHANNEL(0),
131 MCP320X_VOLTAGE_CHANNEL(1),
132 MCP320X_VOLTAGE_CHANNEL(2),
133 MCP320X_VOLTAGE_CHANNEL(3),
134 MCP320X_VOLTAGE_CHANNEL(4),
135 MCP320X_VOLTAGE_CHANNEL(5),
136 MCP320X_VOLTAGE_CHANNEL(6),
137 MCP320X_VOLTAGE_CHANNEL(7),
138 MCP320X_VOLTAGE_CHANNEL_DIFF(0),
139 MCP320X_VOLTAGE_CHANNEL_DIFF(1),
140 MCP320X_VOLTAGE_CHANNEL_DIFF(2),
141 MCP320X_VOLTAGE_CHANNEL_DIFF(3),
144 static const struct iio_info mcp320x_info
= {
145 .read_raw
= mcp320x_read_raw
,
146 .driver_module
= THIS_MODULE
,
149 struct mcp3208_chip_info
{
150 const struct iio_chan_spec
*channels
;
151 unsigned int num_channels
;
154 static const struct mcp3208_chip_info mcp3208_chip_infos
[] = {
156 .channels
= mcp3204_channels
,
157 .num_channels
= ARRAY_SIZE(mcp3204_channels
)
160 .channels
= mcp3208_channels
,
161 .num_channels
= ARRAY_SIZE(mcp3208_channels
)
165 static int mcp320x_probe(struct spi_device
*spi
)
167 struct iio_dev
*indio_dev
;
169 const struct mcp3208_chip_info
*chip_info
;
172 indio_dev
= devm_iio_device_alloc(&spi
->dev
, sizeof(*adc
));
176 adc
= iio_priv(indio_dev
);
179 indio_dev
->dev
.parent
= &spi
->dev
;
180 indio_dev
->name
= spi_get_device_id(spi
)->name
;
181 indio_dev
->modes
= INDIO_DIRECT_MODE
;
182 indio_dev
->info
= &mcp320x_info
;
184 chip_info
= &mcp3208_chip_infos
[spi_get_device_id(spi
)->driver_data
];
185 indio_dev
->channels
= chip_info
->channels
;
186 indio_dev
->num_channels
= chip_info
->num_channels
;
188 adc
->transfer
[0].tx_buf
= &adc
->tx_buf
;
189 adc
->transfer
[0].len
= sizeof(adc
->tx_buf
);
190 adc
->transfer
[1].rx_buf
= adc
->rx_buf
;
191 adc
->transfer
[1].len
= sizeof(adc
->rx_buf
);
193 spi_message_init_with_transfers(&adc
->msg
, adc
->transfer
,
194 ARRAY_SIZE(adc
->transfer
));
196 adc
->reg
= devm_regulator_get(&spi
->dev
, "vref");
197 if (IS_ERR(adc
->reg
))
198 return PTR_ERR(adc
->reg
);
200 ret
= regulator_enable(adc
->reg
);
204 mutex_init(&adc
->lock
);
206 ret
= iio_device_register(indio_dev
);
213 regulator_disable(adc
->reg
);
218 static int mcp320x_remove(struct spi_device
*spi
)
220 struct iio_dev
*indio_dev
= spi_get_drvdata(spi
);
221 struct mcp320x
*adc
= iio_priv(indio_dev
);
223 iio_device_unregister(indio_dev
);
224 regulator_disable(adc
->reg
);
229 static const struct spi_device_id mcp320x_id
[] = {
230 { "mcp3204", mcp3204
},
231 { "mcp3208", mcp3208
},
234 MODULE_DEVICE_TABLE(spi
, mcp320x_id
);
236 static struct spi_driver mcp320x_driver
= {
239 .owner
= THIS_MODULE
,
241 .probe
= mcp320x_probe
,
242 .remove
= mcp320x_remove
,
243 .id_table
= mcp320x_id
,
245 module_spi_driver(mcp320x_driver
);
247 MODULE_AUTHOR("Oskar Andero <oskar.andero@gmail.com>");
248 MODULE_DESCRIPTION("Microchip Technology MCP3204/08");
249 MODULE_LICENSE("GPL v2");