blob: 19339bc439ca9a650a88daa35ca4eabd590ca67b [file] [log] [blame]
Arun Murthydae2db32011-02-22 10:11:13 +01001/*
2 * Copyright (C) ST-Ericsson SA 2010
3 *
4 * License Terms: GNU General Public License v2
5 * Author: Arun R Murthy <arun.murthy@stericsson.com>
6 */
7#include <linux/init.h>
8#include <linux/module.h>
9#include <linux/device.h>
10#include <linux/interrupt.h>
11#include <linux/spinlock.h>
12#include <linux/delay.h>
13#include <linux/platform_device.h>
14#include <linux/completion.h>
15#include <linux/regulator/consumer.h>
16#include <linux/err.h>
17#include <linux/slab.h>
18#include <linux/mfd/ab8500.h>
19#include <linux/mfd/abx500.h>
20#include <linux/mfd/ab8500-gpadc.h>
21
22/*
23 * GPADC register offsets
24 * Bank : 0x0A
25 */
26#define AB8500_GPADC_CTRL1_REG 0x00
27#define AB8500_GPADC_CTRL2_REG 0x01
28#define AB8500_GPADC_CTRL3_REG 0x02
29#define AB8500_GPADC_AUTO_TIMER_REG 0x03
30#define AB8500_GPADC_STAT_REG 0x04
31#define AB8500_GPADC_MANDATAL_REG 0x05
32#define AB8500_GPADC_MANDATAH_REG 0x06
33#define AB8500_GPADC_AUTODATAL_REG 0x07
34#define AB8500_GPADC_AUTODATAH_REG 0x08
35#define AB8500_GPADC_MUX_CTRL_REG 0x09
36
37/* gpadc constants */
38#define EN_VINTCORE12 0x04
39#define EN_VTVOUT 0x02
40#define EN_GPADC 0x01
41#define DIS_GPADC 0x00
42#define SW_AVG_16 0x60
43#define ADC_SW_CONV 0x04
44#define EN_BUF 0x40
45#define DIS_ZERO 0x00
46#define GPADC_BUSY 0x01
47
48/**
49 * struct ab8500_gpadc - ab8500 GPADC device information
50 * @dev: pointer to the struct device
51 * @parent: pointer to the parent device structure ab8500
52 * @ab8500_gpadc_complete: pointer to the struct completion, to indicate
53 * the completion of gpadc conversion
54 * @ab8500_gpadc_lock: structure of type mutex
55 * @regu: pointer to the struct regulator
56 * @irq: interrupt number that is used by gpadc
57 */
58static struct ab8500_gpadc {
59 struct device *dev;
60 struct ab8500 *parent;
61 struct completion ab8500_gpadc_complete;
62 struct mutex ab8500_gpadc_lock;
63 struct regulator *regu;
64 int irq;
65} *di;
66
67/**
68 * ab8500_gpadc_convert() - gpadc conversion
69 * @input: analog input to be converted to digital data
70 *
71 * This function converts the selected analog i/p to digital
72 * data. Thereafter calibration has to be made to obtain the
73 * data in the required quantity measurement.
74 */
75int ab8500_gpadc_convert(u8 input)
76{
77 int ret;
78 u16 data = 0;
79 int looplimit = 0;
80 u8 val, low_data, high_data;
81
82 if (!di)
83 return -ENODEV;
84
85 mutex_lock(&di->ab8500_gpadc_lock);
86 /* Enable VTVout LDO this is required for GPADC */
87 regulator_enable(di->regu);
88
89 /* Check if ADC is not busy, lock and proceed */
90 do {
91 ret = abx500_get_register_interruptible(di->dev, AB8500_GPADC,
92 AB8500_GPADC_STAT_REG, &val);
93 if (ret < 0)
94 goto out;
95 if (!(val & GPADC_BUSY))
96 break;
97 msleep(10);
98 } while (++looplimit < 10);
99 if (looplimit >= 10 && (val & GPADC_BUSY)) {
100 dev_err(di->dev, "gpadc_conversion: GPADC busy");
101 ret = -EINVAL;
102 goto out;
103 }
104
105 /* Enable GPADC */
106 ret = abx500_mask_and_set_register_interruptible(di->dev, AB8500_GPADC,
107 AB8500_GPADC_CTRL1_REG, EN_GPADC, EN_GPADC);
108 if (ret < 0) {
109 dev_err(di->dev, "gpadc_conversion: enable gpadc failed\n");
110 goto out;
111 }
112 /* Select the input source and set average samples to 16 */
113 ret = abx500_set_register_interruptible(di->dev, AB8500_GPADC,
114 AB8500_GPADC_CTRL2_REG, (input | SW_AVG_16));
115 if (ret < 0) {
116 dev_err(di->dev,
117 "gpadc_conversion: set avg samples failed\n");
118 goto out;
119 }
120 /* Enable ADC, Buffering and select rising edge, start Conversion */
121 ret = abx500_mask_and_set_register_interruptible(di->dev, AB8500_GPADC,
122 AB8500_GPADC_CTRL1_REG, EN_BUF, EN_BUF);
123 if (ret < 0) {
124 dev_err(di->dev,
125 "gpadc_conversion: select falling edge failed\n");
126 goto out;
127 }
128 ret = abx500_mask_and_set_register_interruptible(di->dev, AB8500_GPADC,
129 AB8500_GPADC_CTRL1_REG, ADC_SW_CONV, ADC_SW_CONV);
130 if (ret < 0) {
131 dev_err(di->dev,
132 "gpadc_conversion: start s/w conversion failed\n");
133 goto out;
134 }
135 /* wait for completion of conversion */
136 if (!wait_for_completion_timeout(&di->ab8500_gpadc_complete, 2*HZ)) {
137 dev_err(di->dev,
138 "timeout: didnt recieve GPADC conversion interrupt\n");
139 ret = -EINVAL;
140 goto out;
141 }
142
143 /* Read the converted RAW data */
144 ret = abx500_get_register_interruptible(di->dev, AB8500_GPADC,
145 AB8500_GPADC_MANDATAL_REG, &low_data);
146 if (ret < 0) {
147 dev_err(di->dev, "gpadc_conversion: read low data failed\n");
148 goto out;
149 }
150
151 ret = abx500_get_register_interruptible(di->dev, AB8500_GPADC,
152 AB8500_GPADC_MANDATAH_REG, &high_data);
153 if (ret < 0) {
154 dev_err(di->dev, "gpadc_conversion: read high data failed\n");
155 goto out;
156 }
157
158 data = (high_data << 8) | low_data;
159 /* Disable GPADC */
160 ret = abx500_set_register_interruptible(di->dev, AB8500_GPADC,
161 AB8500_GPADC_CTRL1_REG, DIS_GPADC);
162 if (ret < 0) {
163 dev_err(di->dev, "gpadc_conversion: disable gpadc failed\n");
164 goto out;
165 }
166 /* Disable VTVout LDO this is required for GPADC */
167 regulator_disable(di->regu);
168 mutex_unlock(&di->ab8500_gpadc_lock);
169 return data;
170
171out:
172 /*
173 * It has shown to be needed to turn off the GPADC if an error occurs,
174 * otherwise we might have problem when waiting for the busy bit in the
175 * GPADC status register to go low. In V1.1 there wait_for_completion
176 * seems to timeout when waiting for an interrupt.. Not seen in V2.0
177 */
178 (void) abx500_set_register_interruptible(di->dev, AB8500_GPADC,
179 AB8500_GPADC_CTRL1_REG, DIS_GPADC);
180 regulator_disable(di->regu);
181 mutex_unlock(&di->ab8500_gpadc_lock);
182 dev_err(di->dev, "gpadc_conversion: Failed to AD convert channel %d\n",
183 input);
184 return ret;
185}
186EXPORT_SYMBOL(ab8500_gpadc_convert);
187
188/**
189 * ab8500_bm_gpswadcconvend_handler() - isr for s/w gpadc conversion completion
190 * @irq: irq number
191 * @data: pointer to the data passed during request irq
192 *
193 * This is a interrupt service routine for s/w gpadc conversion completion.
194 * Notifies the gpadc completion is completed and the converted raw value
195 * can be read from the registers.
196 * Returns IRQ status(IRQ_HANDLED)
197 */
198static irqreturn_t ab8500_bm_gpswadcconvend_handler(int irq, void *_di)
199{
200 struct ab8500_gpadc *gpadc = _di;
201
202 complete(&gpadc->ab8500_gpadc_complete);
203
204 return IRQ_HANDLED;
205}
206
207static int __devinit ab8500_gpadc_probe(struct platform_device *pdev)
208{
209 int ret = 0;
210 struct ab8500_gpadc *gpadc;
211
212 gpadc = kzalloc(sizeof(struct ab8500_gpadc), GFP_KERNEL);
213 if (!gpadc) {
214 dev_err(&pdev->dev, "Error: No memory\n");
215 return -ENOMEM;
216 }
217
218 gpadc->parent = dev_get_drvdata(pdev->dev.parent);
219 gpadc->irq = platform_get_irq_byname(pdev, "SW_CONV_END");
220 if (gpadc->irq < 0) {
221 dev_err(gpadc->dev, "failed to get platform irq-%d\n", di->irq);
222 ret = gpadc->irq;
223 goto fail;
224 }
225
226 gpadc->dev = &pdev->dev;
227 mutex_init(&di->ab8500_gpadc_lock);
228
229 /* Initialize completion used to notify completion of conversion */
230 init_completion(&gpadc->ab8500_gpadc_complete);
231
232 /* Register interrupt - SwAdcComplete */
233 ret = request_threaded_irq(gpadc->irq, NULL,
234 ab8500_bm_gpswadcconvend_handler,
235 IRQF_NO_SUSPEND | IRQF_SHARED, "ab8500-gpadc", gpadc);
236 if (ret < 0) {
237 dev_err(gpadc->dev, "Failed to register interrupt, irq: %d\n",
238 gpadc->irq);
239 goto fail;
240 }
241
242 /* VTVout LDO used to power up ab8500-GPADC */
243 gpadc->regu = regulator_get(&pdev->dev, "vddadc");
244 if (IS_ERR(gpadc->regu)) {
245 ret = PTR_ERR(gpadc->regu);
246 dev_err(gpadc->dev, "failed to get vtvout LDO\n");
247 goto fail;
248 }
249 di = gpadc;
250 dev_dbg(gpadc->dev, "probe success\n");
251 return 0;
252fail:
253 kfree(gpadc);
254 gpadc = NULL;
255 return ret;
256}
257
258static int __devexit ab8500_gpadc_remove(struct platform_device *pdev)
259{
260 struct ab8500_gpadc *gpadc = platform_get_drvdata(pdev);
261
262 /* remove interrupt - completion of Sw ADC conversion */
263 free_irq(gpadc->irq, di);
264 /* disable VTVout LDO that is being used by GPADC */
265 regulator_put(gpadc->regu);
266 kfree(gpadc);
267 gpadc = NULL;
268 return 0;
269}
270
271static struct platform_driver ab8500_gpadc_driver = {
272 .probe = ab8500_gpadc_probe,
273 .remove = __devexit_p(ab8500_gpadc_remove),
274 .driver = {
275 .name = "ab8500-gpadc",
276 .owner = THIS_MODULE,
277 },
278};
279
280static int __init ab8500_gpadc_init(void)
281{
282 return platform_driver_register(&ab8500_gpadc_driver);
283}
284
285static void __exit ab8500_gpadc_exit(void)
286{
287 platform_driver_unregister(&ab8500_gpadc_driver);
288}
289
290subsys_initcall_sync(ab8500_gpadc_init);
291module_exit(ab8500_gpadc_exit);
292
293MODULE_LICENSE("GPL v2");
294MODULE_AUTHOR("Arun R Murthy");
295MODULE_ALIAS("platform:ab8500_gpadc");
296MODULE_DESCRIPTION("AB8500 GPADC driver");