aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Thomson <Adam.Thomson.Opensource@diasemi.com>2015-02-18 09:08:28 -0500
committerSebastian Reichel <sre@kernel.org>2015-02-25 15:05:26 -0500
commited5f07b3d3d4344f917658a7f62cf62ccb19cb07 (patch)
tree17513f51cf270f1f210a988b01f4eb8aec3e7fc9
parentc517d838eb7d07bbe9507871fab3931deccff539 (diff)
iio: Add support for DA9150 GPADC
This patch adds support for DA9150 Charger & Fuel-Gauge IC GPADC. Signed-off-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com> Reviewed-by: Hartmut Knaack <knaack.h@gmx.de> Acked-by: Jonathan Cameron <jic23@kernel.org> Signed-off-by: Sebastian Reichel <sre@kernel.org>
-rw-r--r--drivers/iio/adc/Kconfig9
-rw-r--r--drivers/iio/adc/Makefile1
-rw-r--r--drivers/iio/adc/da9150-gpadc.c407
3 files changed, 417 insertions, 0 deletions
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 202daf889be2..fc6f90614218 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -135,6 +135,15 @@ config AXP288_ADC
135 device. Depending on platform configuration, this general purpose ADC can 135 device. Depending on platform configuration, this general purpose ADC can
136 be used for sampling sensors such as thermal resistors. 136 be used for sampling sensors such as thermal resistors.
137 137
138config DA9150_GPADC
139 tristate "Dialog DA9150 GPADC driver support"
140 depends on MFD_DA9150
141 help
142 Say yes here to build support for Dialog DA9150 GPADC.
143
144 This driver can also be built as a module. If chosen, the module name
145 will be da9150-gpadc.
146
138config CC10001_ADC 147config CC10001_ADC
139 tristate "Cosmic Circuits 10001 ADC driver" 148 tristate "Cosmic Circuits 10001 ADC driver"
140 depends on HAS_IOMEM || HAVE_CLK || REGULATOR 149 depends on HAS_IOMEM || HAVE_CLK || REGULATOR
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 0315af640866..3930e63e84bc 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_AD7887) += ad7887.o
15obj-$(CONFIG_AD799X) += ad799x.o 15obj-$(CONFIG_AD799X) += ad799x.o
16obj-$(CONFIG_AT91_ADC) += at91_adc.o 16obj-$(CONFIG_AT91_ADC) += at91_adc.o
17obj-$(CONFIG_AXP288_ADC) += axp288_adc.o 17obj-$(CONFIG_AXP288_ADC) += axp288_adc.o
18obj-$(CONFIG_DA9150_GPADC) += da9150-gpadc.o
18obj-$(CONFIG_CC10001_ADC) += cc10001_adc.o 19obj-$(CONFIG_CC10001_ADC) += cc10001_adc.o
19obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o 20obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o
20obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o 21obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
diff --git a/drivers/iio/adc/da9150-gpadc.c b/drivers/iio/adc/da9150-gpadc.c
new file mode 100644
index 000000000000..3445107e10b7
--- /dev/null
+++ b/drivers/iio/adc/da9150-gpadc.c
@@ -0,0 +1,407 @@
1/*
2 * DA9150 GPADC Driver
3 *
4 * Copyright (c) 2014 Dialog Semiconductor
5 *
6 * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 */
13
14#include <linux/kernel.h>
15#include <linux/slab.h>
16#include <linux/module.h>
17#include <linux/platform_device.h>
18#include <linux/interrupt.h>
19#include <linux/mutex.h>
20#include <linux/completion.h>
21#include <linux/iio/iio.h>
22#include <linux/iio/machine.h>
23#include <linux/iio/driver.h>
24#include <linux/mfd/da9150/core.h>
25#include <linux/mfd/da9150/registers.h>
26
27/* Channels */
28enum da9150_gpadc_hw_channel {
29 DA9150_GPADC_HW_CHAN_GPIOA_2V = 0,
30 DA9150_GPADC_HW_CHAN_GPIOA_2V_,
31 DA9150_GPADC_HW_CHAN_GPIOB_2V,
32 DA9150_GPADC_HW_CHAN_GPIOB_2V_,
33 DA9150_GPADC_HW_CHAN_GPIOC_2V,
34 DA9150_GPADC_HW_CHAN_GPIOC_2V_,
35 DA9150_GPADC_HW_CHAN_GPIOD_2V,
36 DA9150_GPADC_HW_CHAN_GPIOD_2V_,
37 DA9150_GPADC_HW_CHAN_IBUS_SENSE,
38 DA9150_GPADC_HW_CHAN_IBUS_SENSE_,
39 DA9150_GPADC_HW_CHAN_VBUS_DIV,
40 DA9150_GPADC_HW_CHAN_VBUS_DIV_,
41 DA9150_GPADC_HW_CHAN_ID,
42 DA9150_GPADC_HW_CHAN_ID_,
43 DA9150_GPADC_HW_CHAN_VSYS,
44 DA9150_GPADC_HW_CHAN_VSYS_,
45 DA9150_GPADC_HW_CHAN_GPIOA_6V,
46 DA9150_GPADC_HW_CHAN_GPIOA_6V_,
47 DA9150_GPADC_HW_CHAN_GPIOB_6V,
48 DA9150_GPADC_HW_CHAN_GPIOB_6V_,
49 DA9150_GPADC_HW_CHAN_GPIOC_6V,
50 DA9150_GPADC_HW_CHAN_GPIOC_6V_,
51 DA9150_GPADC_HW_CHAN_GPIOD_6V,
52 DA9150_GPADC_HW_CHAN_GPIOD_6V_,
53 DA9150_GPADC_HW_CHAN_VBAT,
54 DA9150_GPADC_HW_CHAN_VBAT_,
55 DA9150_GPADC_HW_CHAN_TBAT,
56 DA9150_GPADC_HW_CHAN_TBAT_,
57 DA9150_GPADC_HW_CHAN_TJUNC_CORE,
58 DA9150_GPADC_HW_CHAN_TJUNC_CORE_,
59 DA9150_GPADC_HW_CHAN_TJUNC_OVP,
60 DA9150_GPADC_HW_CHAN_TJUNC_OVP_,
61};
62
63enum da9150_gpadc_channel {
64 DA9150_GPADC_CHAN_GPIOA = 0,
65 DA9150_GPADC_CHAN_GPIOB,
66 DA9150_GPADC_CHAN_GPIOC,
67 DA9150_GPADC_CHAN_GPIOD,
68 DA9150_GPADC_CHAN_IBUS,
69 DA9150_GPADC_CHAN_VBUS,
70 DA9150_GPADC_CHAN_VSYS,
71 DA9150_GPADC_CHAN_VBAT,
72 DA9150_GPADC_CHAN_TBAT,
73 DA9150_GPADC_CHAN_TJUNC_CORE,
74 DA9150_GPADC_CHAN_TJUNC_OVP,
75};
76
77/* Private data */
78struct da9150_gpadc {
79 struct da9150 *da9150;
80 struct device *dev;
81
82 struct mutex lock;
83 struct completion complete;
84};
85
86
87static irqreturn_t da9150_gpadc_irq(int irq, void *data)
88{
89
90 struct da9150_gpadc *gpadc = data;
91
92 complete(&gpadc->complete);
93
94 return IRQ_HANDLED;
95}
96
97static int da9150_gpadc_read_adc(struct da9150_gpadc *gpadc, int hw_chan)
98{
99 u8 result_regs[2];
100 int result;
101
102 mutex_lock(&gpadc->lock);
103
104 /* Set channel & enable measurement */
105 da9150_reg_write(gpadc->da9150, DA9150_GPADC_MAN,
106 (DA9150_GPADC_EN_MASK |
107 hw_chan << DA9150_GPADC_MUX_SHIFT));
108
109 /* Consume left-over completion from a previous timeout */
110 try_wait_for_completion(&gpadc->complete);
111
112 /* Check for actual completion */
113 wait_for_completion_timeout(&gpadc->complete, msecs_to_jiffies(5));
114
115 /* Read result and status from device */
116 da9150_bulk_read(gpadc->da9150, DA9150_GPADC_RES_A, 2, result_regs);
117
118 mutex_unlock(&gpadc->lock);
119
120 /* Check to make sure device really has completed reading */
121 if (result_regs[1] & DA9150_GPADC_RUN_MASK) {
122 dev_err(gpadc->dev, "Timeout on channel %d of GPADC\n",
123 hw_chan);
124 return -ETIMEDOUT;
125 }
126
127 /* LSBs - 2 bits */
128 result = (result_regs[1] & DA9150_GPADC_RES_L_MASK) >>
129 DA9150_GPADC_RES_L_SHIFT;
130 /* MSBs - 8 bits */
131 result |= result_regs[0] << DA9150_GPADC_RES_L_BITS;
132
133 return result;
134}
135
136static inline int da9150_gpadc_gpio_6v_voltage_now(int raw_val)
137{
138 /* Convert to mV */
139 return (6 * ((raw_val * 1000) + 500)) / 1024;
140}
141
142static inline int da9150_gpadc_ibus_current_avg(int raw_val)
143{
144 /* Convert to mA */
145 return (4 * ((raw_val * 1000) + 500)) / 2048;
146}
147
148static inline int da9150_gpadc_vbus_21v_voltage_now(int raw_val)
149{
150 /* Convert to mV */
151 return (21 * ((raw_val * 1000) + 500)) / 1024;
152}
153
154static inline int da9150_gpadc_vsys_6v_voltage_now(int raw_val)
155{
156 /* Convert to mV */
157 return (3 * ((raw_val * 1000) + 500)) / 512;
158}
159
160static int da9150_gpadc_read_processed(struct da9150_gpadc *gpadc, int channel,
161 int hw_chan, int *val)
162{
163 int raw_val;
164
165 raw_val = da9150_gpadc_read_adc(gpadc, hw_chan);
166 if (raw_val < 0)
167 return raw_val;
168
169 switch (channel) {
170 case DA9150_GPADC_CHAN_GPIOA:
171 case DA9150_GPADC_CHAN_GPIOB:
172 case DA9150_GPADC_CHAN_GPIOC:
173 case DA9150_GPADC_CHAN_GPIOD:
174 *val = da9150_gpadc_gpio_6v_voltage_now(raw_val);
175 break;
176 case DA9150_GPADC_CHAN_IBUS:
177 *val = da9150_gpadc_ibus_current_avg(raw_val);
178 break;
179 case DA9150_GPADC_CHAN_VBUS:
180 *val = da9150_gpadc_vbus_21v_voltage_now(raw_val);
181 break;
182 case DA9150_GPADC_CHAN_VSYS:
183 *val = da9150_gpadc_vsys_6v_voltage_now(raw_val);
184 break;
185 default:
186 /* No processing for other channels so return raw value */
187 *val = raw_val;
188 break;
189 }
190
191 return IIO_VAL_INT;
192}
193
194static int da9150_gpadc_read_scale(int channel, int *val, int *val2)
195{
196 switch (channel) {
197 case DA9150_GPADC_CHAN_VBAT:
198 *val = 2932;
199 *val2 = 1000;
200 return IIO_VAL_FRACTIONAL;
201 case DA9150_GPADC_CHAN_TJUNC_CORE:
202 case DA9150_GPADC_CHAN_TJUNC_OVP:
203 *val = 1000000;
204 *val2 = 4420;
205 return IIO_VAL_FRACTIONAL;
206 default:
207 return -EINVAL;
208 }
209}
210
211static int da9150_gpadc_read_offset(int channel, int *val)
212{
213 switch (channel) {
214 case DA9150_GPADC_CHAN_VBAT:
215 *val = 1500000 / 2932;
216 return IIO_VAL_INT;
217 case DA9150_GPADC_CHAN_TJUNC_CORE:
218 case DA9150_GPADC_CHAN_TJUNC_OVP:
219 *val = -144;
220 return IIO_VAL_INT;
221 default:
222 return -EINVAL;
223 }
224}
225
226static int da9150_gpadc_read_raw(struct iio_dev *indio_dev,
227 struct iio_chan_spec const *chan,
228 int *val, int *val2, long mask)
229{
230 struct da9150_gpadc *gpadc = iio_priv(indio_dev);
231
232 if ((chan->channel < DA9150_GPADC_CHAN_GPIOA) ||
233 (chan->channel > DA9150_GPADC_CHAN_TJUNC_OVP))
234 return -EINVAL;
235
236 switch (mask) {
237 case IIO_CHAN_INFO_RAW:
238 case IIO_CHAN_INFO_PROCESSED:
239 return da9150_gpadc_read_processed(gpadc, chan->channel,
240 chan->address, val);
241 case IIO_CHAN_INFO_SCALE:
242 return da9150_gpadc_read_scale(chan->channel, val, val2);
243 case IIO_CHAN_INFO_OFFSET:
244 return da9150_gpadc_read_offset(chan->channel, val);
245 default:
246 return -EINVAL;
247 }
248}
249
250static const struct iio_info da9150_gpadc_info = {
251 .read_raw = &da9150_gpadc_read_raw,
252 .driver_module = THIS_MODULE,
253};
254
255#define DA9150_GPADC_CHANNEL(_id, _hw_id, _type, chan_info, \
256 _ext_name) { \
257 .type = _type, \
258 .indexed = 1, \
259 .channel = DA9150_GPADC_CHAN_##_id, \
260 .address = DA9150_GPADC_HW_CHAN_##_hw_id, \
261 .info_mask_separate = chan_info, \
262 .extend_name = _ext_name, \
263 .datasheet_name = #_id, \
264}
265
266#define DA9150_GPADC_CHANNEL_RAW(_id, _hw_id, _type, _ext_name) \
267 DA9150_GPADC_CHANNEL(_id, _hw_id, _type, \
268 BIT(IIO_CHAN_INFO_RAW), _ext_name)
269
270#define DA9150_GPADC_CHANNEL_SCALED(_id, _hw_id, _type, _ext_name) \
271 DA9150_GPADC_CHANNEL(_id, _hw_id, _type, \
272 BIT(IIO_CHAN_INFO_RAW) | \
273 BIT(IIO_CHAN_INFO_SCALE) | \
274 BIT(IIO_CHAN_INFO_OFFSET), \
275 _ext_name)
276
277#define DA9150_GPADC_CHANNEL_PROCESSED(_id, _hw_id, _type, _ext_name) \
278 DA9150_GPADC_CHANNEL(_id, _hw_id, _type, \
279 BIT(IIO_CHAN_INFO_PROCESSED), _ext_name)
280
281/* Supported channels */
282static const struct iio_chan_spec da9150_gpadc_channels[] = {
283 DA9150_GPADC_CHANNEL_PROCESSED(GPIOA, GPIOA_6V, IIO_VOLTAGE, NULL),
284 DA9150_GPADC_CHANNEL_PROCESSED(GPIOB, GPIOB_6V, IIO_VOLTAGE, NULL),
285 DA9150_GPADC_CHANNEL_PROCESSED(GPIOC, GPIOC_6V, IIO_VOLTAGE, NULL),
286 DA9150_GPADC_CHANNEL_PROCESSED(GPIOD, GPIOD_6V, IIO_VOLTAGE, NULL),
287 DA9150_GPADC_CHANNEL_PROCESSED(IBUS, IBUS_SENSE, IIO_CURRENT, "ibus"),
288 DA9150_GPADC_CHANNEL_PROCESSED(VBUS, VBUS_DIV_, IIO_VOLTAGE, "vbus"),
289 DA9150_GPADC_CHANNEL_PROCESSED(VSYS, VSYS, IIO_VOLTAGE, "vsys"),
290 DA9150_GPADC_CHANNEL_SCALED(VBAT, VBAT, IIO_VOLTAGE, "vbat"),
291 DA9150_GPADC_CHANNEL_RAW(TBAT, TBAT, IIO_VOLTAGE, "tbat"),
292 DA9150_GPADC_CHANNEL_SCALED(TJUNC_CORE, TJUNC_CORE, IIO_TEMP,
293 "tjunc_core"),
294 DA9150_GPADC_CHANNEL_SCALED(TJUNC_OVP, TJUNC_OVP, IIO_TEMP,
295 "tjunc_ovp"),
296};
297
298/* Default maps used by da9150-charger */
299static struct iio_map da9150_gpadc_default_maps[] = {
300 {
301 .consumer_dev_name = "da9150-charger",
302 .consumer_channel = "CHAN_IBUS",
303 .adc_channel_label = "IBUS",
304 },
305 {
306 .consumer_dev_name = "da9150-charger",
307 .consumer_channel = "CHAN_VBUS",
308 .adc_channel_label = "VBUS",
309 },
310 {
311 .consumer_dev_name = "da9150-charger",
312 .consumer_channel = "CHAN_TJUNC",
313 .adc_channel_label = "TJUNC_CORE",
314 },
315 {
316 .consumer_dev_name = "da9150-charger",
317 .consumer_channel = "CHAN_VBAT",
318 .adc_channel_label = "VBAT",
319 },
320 {},
321};
322
323static int da9150_gpadc_probe(struct platform_device *pdev)
324{
325 struct device *dev = &pdev->dev;
326 struct da9150 *da9150 = dev_get_drvdata(dev->parent);
327 struct da9150_gpadc *gpadc;
328 struct iio_dev *indio_dev;
329 int irq, ret;
330
331 indio_dev = devm_iio_device_alloc(dev, sizeof(*gpadc));
332 if (!indio_dev) {
333 dev_err(&pdev->dev, "Failed to allocate IIO device\n");
334 return -ENOMEM;
335 }
336 gpadc = iio_priv(indio_dev);
337
338 platform_set_drvdata(pdev, indio_dev);
339 gpadc->da9150 = da9150;
340 gpadc->dev = dev;
341 mutex_init(&gpadc->lock);
342 init_completion(&gpadc->complete);
343
344 irq = platform_get_irq_byname(pdev, "GPADC");
345 if (irq < 0) {
346 dev_err(dev, "Failed to get IRQ: %d\n", irq);
347 return irq;
348 }
349
350 ret = devm_request_threaded_irq(dev, irq, NULL, da9150_gpadc_irq,
351 IRQF_ONESHOT, "GPADC", gpadc);
352 if (ret) {
353 dev_err(dev, "Failed to request IRQ %d: %d\n", irq, ret);
354 return ret;
355 }
356
357 ret = iio_map_array_register(indio_dev, da9150_gpadc_default_maps);
358 if (ret) {
359 dev_err(dev, "Failed to register IIO maps: %d\n", ret);
360 return ret;
361 }
362
363 indio_dev->name = dev_name(dev);
364 indio_dev->dev.parent = dev;
365 indio_dev->dev.of_node = pdev->dev.of_node;
366 indio_dev->info = &da9150_gpadc_info;
367 indio_dev->modes = INDIO_DIRECT_MODE;
368 indio_dev->channels = da9150_gpadc_channels;
369 indio_dev->num_channels = ARRAY_SIZE(da9150_gpadc_channels);
370
371 ret = iio_device_register(indio_dev);
372 if (ret) {
373 dev_err(dev, "Failed to register IIO device: %d\n", ret);
374 goto iio_map_unreg;
375 }
376
377 return 0;
378
379iio_map_unreg:
380 iio_map_array_unregister(indio_dev);
381
382 return ret;
383}
384
385static int da9150_gpadc_remove(struct platform_device *pdev)
386{
387 struct iio_dev *indio_dev = platform_get_drvdata(pdev);
388
389 iio_device_unregister(indio_dev);
390 iio_map_array_unregister(indio_dev);
391
392 return 0;
393}
394
395static struct platform_driver da9150_gpadc_driver = {
396 .driver = {
397 .name = "da9150-gpadc",
398 },
399 .probe = da9150_gpadc_probe,
400 .remove = da9150_gpadc_remove,
401};
402
403module_platform_driver(da9150_gpadc_driver);
404
405MODULE_DESCRIPTION("GPADC Driver for DA9150");
406MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com>");
407MODULE_LICENSE("GPL");