PM / sleep: Asynchronous threads for suspend_noirq
[linux/fpc-iii.git] / drivers / iio / adc / mcp320x.c
blob28a086e48776255b3ba8889111dbb73203b5005e
1 /*
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)
22 enum {
23 mcp3204,
24 mcp3208,
27 struct mcp320x {
28 struct spi_device *spi;
29 struct spi_message msg;
30 struct spi_transfer transfer[2];
32 u8 tx_buf;
33 u8 rx_buf[2];
35 struct regulator *reg;
36 struct mutex lock;
39 static int mcp320x_adc_conversion(struct mcp320x *adc, u8 msg)
41 int ret;
43 adc->tx_buf = msg;
44 ret = spi_sync(adc->spi, &adc->msg);
45 if (ret < 0)
46 return ret;
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,
54 int *val2, long mask)
56 struct mcp320x *adc = iio_priv(indio_dev);
57 int ret = -EINVAL;
59 mutex_lock(&adc->lock);
61 switch (mask) {
62 case IIO_CHAN_INFO_RAW:
63 if (channel->differential)
64 ret = mcp320x_adc_conversion(adc,
65 MCP_START_BIT | channel->address);
66 else
67 ret = mcp320x_adc_conversion(adc,
68 MCP_START_BIT | MCP_SINGLE_ENDED |
69 channel->address);
70 if (ret < 0)
71 goto out;
73 *val = ret;
74 ret = IIO_VAL_INT;
75 break;
77 case IIO_CHAN_INFO_SCALE:
78 /* Digital output code = (4096 * Vin) / Vref */
79 ret = regulator_get_voltage(adc->reg);
80 if (ret < 0)
81 goto out;
83 *val = ret / 1000;
84 *val2 = 12;
85 ret = IIO_VAL_FRACTIONAL_LOG2;
86 break;
88 default:
89 break;
92 out:
93 mutex_unlock(&adc->lock);
95 return ret;
98 #define MCP320X_VOLTAGE_CHANNEL(num) \
99 { \
100 .type = IIO_VOLTAGE, \
101 .indexed = 1, \
102 .channel = (num), \
103 .address = (num), \
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, \
111 .indexed = 1, \
112 .channel = (num * 2), \
113 .channel2 = (num * 2 + 1), \
114 .address = (num * 2), \
115 .differential = 1, \
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[] = {
155 [mcp3204] = {
156 .channels = mcp3204_channels,
157 .num_channels = ARRAY_SIZE(mcp3204_channels)
159 [mcp3208] = {
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;
168 struct mcp320x *adc;
169 const struct mcp3208_chip_info *chip_info;
170 int ret;
172 indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adc));
173 if (!indio_dev)
174 return -ENOMEM;
176 adc = iio_priv(indio_dev);
177 adc->spi = spi;
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);
201 if (ret < 0)
202 return ret;
204 mutex_init(&adc->lock);
206 ret = iio_device_register(indio_dev);
207 if (ret < 0)
208 goto reg_disable;
210 return 0;
212 reg_disable:
213 regulator_disable(adc->reg);
215 return ret;
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);
226 return 0;
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 = {
237 .driver = {
238 .name = "mcp320x",
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");