diff options
author | Raveendra Padasalagi <raveendra.padasalagi@broadcom.com> | 2016-06-28 03:40:35 -0400 |
---|---|---|
committer | Jonathan Cameron <jic23@kernel.org> | 2016-07-03 06:32:30 -0400 |
commit | 4324c97ecedcba8a548bcff9d620880e11359425 (patch) | |
tree | 1f561278c9ccffb3f58316d11df32d5abadc935b /drivers/iio | |
parent | d3c4d0ab3b4e7cdfe5a209ba4d58bf5787e7c47f (diff) |
iio: Add driver for Broadcom iproc-static-adc
This patch adds basic driver implementation for Broadcom's
static adc controller used in iProc SoC's family.
Signed-off-by: Raveendra Padasalagi <raveendra.padasalagi@broadcom.com>
Reviewed-by: Ray Jui <ray.jui@broadcom.com>
Reviewed-by: Scott Branden <scott.branden@broadcom.com>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Diffstat (limited to 'drivers/iio')
-rw-r--r-- | drivers/iio/adc/Kconfig | 12 | ||||
-rw-r--r-- | drivers/iio/adc/Makefile | 1 | ||||
-rw-r--r-- | drivers/iio/adc/bcm_iproc_adc.c | 644 |
3 files changed, 657 insertions, 0 deletions
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 25378c5882e2..1de31bdd4ce4 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig | |||
@@ -153,6 +153,18 @@ config AXP288_ADC | |||
153 | To compile this driver as a module, choose M here: the module will be | 153 | To compile this driver as a module, choose M here: the module will be |
154 | called axp288_adc. | 154 | called axp288_adc. |
155 | 155 | ||
156 | config BCM_IPROC_ADC | ||
157 | tristate "Broadcom IPROC ADC driver" | ||
158 | depends on ARCH_BCM_IPROC || COMPILE_TEST | ||
159 | depends on MFD_SYSCON | ||
160 | default ARCH_BCM_CYGNUS | ||
161 | help | ||
162 | Say Y here if you want to add support for the Broadcom static | ||
163 | ADC driver. | ||
164 | |||
165 | Broadcom iProc ADC driver. Broadcom iProc ADC controller has 8 | ||
166 | channels. The driver allows the user to read voltage values. | ||
167 | |||
156 | config BERLIN2_ADC | 168 | config BERLIN2_ADC |
157 | tristate "Marvell Berlin2 ADC driver" | 169 | tristate "Marvell Berlin2 ADC driver" |
158 | depends on ARCH_BERLIN | 170 | depends on ARCH_BERLIN |
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 38638d46f972..0ba0d500eedb 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile | |||
@@ -16,6 +16,7 @@ obj-$(CONFIG_AD799X) += ad799x.o | |||
16 | obj-$(CONFIG_AT91_ADC) += at91_adc.o | 16 | obj-$(CONFIG_AT91_ADC) += at91_adc.o |
17 | obj-$(CONFIG_AT91_SAMA5D2_ADC) += at91-sama5d2_adc.o | 17 | obj-$(CONFIG_AT91_SAMA5D2_ADC) += at91-sama5d2_adc.o |
18 | obj-$(CONFIG_AXP288_ADC) += axp288_adc.o | 18 | obj-$(CONFIG_AXP288_ADC) += axp288_adc.o |
19 | obj-$(CONFIG_BCM_IPROC_ADC) += bcm_iproc_adc.o | ||
19 | obj-$(CONFIG_BERLIN2_ADC) += berlin2-adc.o | 20 | obj-$(CONFIG_BERLIN2_ADC) += berlin2-adc.o |
20 | obj-$(CONFIG_CC10001_ADC) += cc10001_adc.o | 21 | obj-$(CONFIG_CC10001_ADC) += cc10001_adc.o |
21 | obj-$(CONFIG_DA9150_GPADC) += da9150-gpadc.o | 22 | obj-$(CONFIG_DA9150_GPADC) += da9150-gpadc.o |
diff --git a/drivers/iio/adc/bcm_iproc_adc.c b/drivers/iio/adc/bcm_iproc_adc.c new file mode 100644 index 000000000000..21d38c8af21e --- /dev/null +++ b/drivers/iio/adc/bcm_iproc_adc.c | |||
@@ -0,0 +1,644 @@ | |||
1 | /* | ||
2 | * Copyright 2016 Broadcom | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License, version 2, as | ||
6 | * published by the Free Software Foundation (the "GPL"). | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, but | ||
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
11 | * General Public License version 2 (GPLv2) for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * version 2 (GPLv2) along with this source code. | ||
15 | */ | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/of.h> | ||
19 | #include <linux/io.h> | ||
20 | #include <linux/clk.h> | ||
21 | #include <linux/mfd/syscon.h> | ||
22 | #include <linux/regmap.h> | ||
23 | #include <linux/delay.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | |||
27 | #include <linux/iio/iio.h> | ||
28 | |||
29 | /* Below Register's are common to IPROC ADC and Touchscreen IP */ | ||
30 | #define IPROC_REGCTL1 0x00 | ||
31 | #define IPROC_REGCTL2 0x04 | ||
32 | #define IPROC_INTERRUPT_THRES 0x08 | ||
33 | #define IPROC_INTERRUPT_MASK 0x0c | ||
34 | #define IPROC_INTERRUPT_STATUS 0x10 | ||
35 | #define IPROC_ANALOG_CONTROL 0x1c | ||
36 | #define IPROC_CONTROLLER_STATUS 0x14 | ||
37 | #define IPROC_AUX_DATA 0x20 | ||
38 | #define IPROC_SOFT_BYPASS_CONTROL 0x38 | ||
39 | #define IPROC_SOFT_BYPASS_DATA 0x3C | ||
40 | |||
41 | /* IPROC ADC Channel register offsets */ | ||
42 | #define IPROC_ADC_CHANNEL_REGCTL1 0x800 | ||
43 | #define IPROC_ADC_CHANNEL_REGCTL2 0x804 | ||
44 | #define IPROC_ADC_CHANNEL_STATUS 0x808 | ||
45 | #define IPROC_ADC_CHANNEL_INTERRUPT_STATUS 0x80c | ||
46 | #define IPROC_ADC_CHANNEL_INTERRUPT_MASK 0x810 | ||
47 | #define IPROC_ADC_CHANNEL_DATA 0x814 | ||
48 | #define IPROC_ADC_CHANNEL_OFFSET 0x20 | ||
49 | |||
50 | /* Bit definitions for IPROC_REGCTL2 */ | ||
51 | #define IPROC_ADC_AUXIN_SCAN_ENA BIT(0) | ||
52 | #define IPROC_ADC_PWR_LDO BIT(5) | ||
53 | #define IPROC_ADC_PWR_ADC BIT(4) | ||
54 | #define IPROC_ADC_PWR_BG BIT(3) | ||
55 | #define IPROC_ADC_CONTROLLER_EN BIT(17) | ||
56 | |||
57 | /* Bit definitions for IPROC_INTERRUPT_MASK and IPROC_INTERRUPT_STATUS */ | ||
58 | #define IPROC_ADC_AUXDATA_RDY_INTR BIT(3) | ||
59 | #define IPROC_ADC_INTR 9 | ||
60 | #define IPROC_ADC_INTR_MASK (0xFF << IPROC_ADC_INTR) | ||
61 | |||
62 | /* Bit definitions for IPROC_ANALOG_CONTROL */ | ||
63 | #define IPROC_ADC_CHANNEL_SEL 11 | ||
64 | #define IPROC_ADC_CHANNEL_SEL_MASK (0x7 << IPROC_ADC_CHANNEL_SEL) | ||
65 | |||
66 | /* Bit definitions for IPROC_ADC_CHANNEL_REGCTL1 */ | ||
67 | #define IPROC_ADC_CHANNEL_ROUNDS 0x2 | ||
68 | #define IPROC_ADC_CHANNEL_ROUNDS_MASK (0x3F << IPROC_ADC_CHANNEL_ROUNDS) | ||
69 | #define IPROC_ADC_CHANNEL_MODE 0x1 | ||
70 | #define IPROC_ADC_CHANNEL_MODE_MASK (0x1 << IPROC_ADC_CHANNEL_MODE) | ||
71 | #define IPROC_ADC_CHANNEL_MODE_TDM 0x1 | ||
72 | #define IPROC_ADC_CHANNEL_MODE_SNAPSHOT 0x0 | ||
73 | #define IPROC_ADC_CHANNEL_ENABLE 0x0 | ||
74 | #define IPROC_ADC_CHANNEL_ENABLE_MASK 0x1 | ||
75 | |||
76 | /* Bit definitions for IPROC_ADC_CHANNEL_REGCTL2 */ | ||
77 | #define IPROC_ADC_CHANNEL_WATERMARK 0x0 | ||
78 | #define IPROC_ADC_CHANNEL_WATERMARK_MASK \ | ||
79 | (0x3F << IPROC_ADC_CHANNEL_WATERMARK) | ||
80 | |||
81 | #define IPROC_ADC_WATER_MARK_LEVEL 0x1 | ||
82 | |||
83 | /* Bit definitions for IPROC_ADC_CHANNEL_STATUS */ | ||
84 | #define IPROC_ADC_CHANNEL_DATA_LOST 0x0 | ||
85 | #define IPROC_ADC_CHANNEL_DATA_LOST_MASK \ | ||
86 | (0x0 << IPROC_ADC_CHANNEL_DATA_LOST) | ||
87 | #define IPROC_ADC_CHANNEL_VALID_ENTERIES 0x1 | ||
88 | #define IPROC_ADC_CHANNEL_VALID_ENTERIES_MASK \ | ||
89 | (0xFF << IPROC_ADC_CHANNEL_VALID_ENTERIES) | ||
90 | #define IPROC_ADC_CHANNEL_TOTAL_ENTERIES 0x9 | ||
91 | #define IPROC_ADC_CHANNEL_TOTAL_ENTERIES_MASK \ | ||
92 | (0xFF << IPROC_ADC_CHANNEL_TOTAL_ENTERIES) | ||
93 | |||
94 | /* Bit definitions for IPROC_ADC_CHANNEL_INTERRUPT_MASK */ | ||
95 | #define IPROC_ADC_CHANNEL_WTRMRK_INTR 0x0 | ||
96 | #define IPROC_ADC_CHANNEL_WTRMRK_INTR_MASK \ | ||
97 | (0x1 << IPROC_ADC_CHANNEL_WTRMRK_INTR) | ||
98 | #define IPROC_ADC_CHANNEL_FULL_INTR 0x1 | ||
99 | #define IPROC_ADC_CHANNEL_FULL_INTR_MASK \ | ||
100 | (0x1 << IPROC_ADC_IPROC_ADC_CHANNEL_FULL_INTR) | ||
101 | #define IPROC_ADC_CHANNEL_EMPTY_INTR 0x2 | ||
102 | #define IPROC_ADC_CHANNEL_EMPTY_INTR_MASK \ | ||
103 | (0x1 << IPROC_ADC_CHANNEL_EMPTY_INTR) | ||
104 | |||
105 | #define IPROC_ADC_WATER_MARK_INTR_ENABLE 0x1 | ||
106 | |||
107 | /* Number of time to retry a set of the interrupt mask reg */ | ||
108 | #define IPROC_ADC_INTMASK_RETRY_ATTEMPTS 10 | ||
109 | |||
110 | #define IPROC_ADC_READ_TIMEOUT (HZ*2) | ||
111 | |||
112 | #define iproc_adc_dbg_reg(dev, priv, reg) \ | ||
113 | do { \ | ||
114 | u32 val; \ | ||
115 | regmap_read(priv->regmap, reg, &val); \ | ||
116 | dev_dbg(dev, "%20s= 0x%08x\n", #reg, val); \ | ||
117 | } while (0) | ||
118 | |||
119 | struct iproc_adc_priv { | ||
120 | struct regmap *regmap; | ||
121 | struct clk *adc_clk; | ||
122 | struct mutex mutex; | ||
123 | int irqno; | ||
124 | int chan_val; | ||
125 | int chan_id; | ||
126 | struct completion completion; | ||
127 | }; | ||
128 | |||
129 | static void iproc_adc_reg_dump(struct iio_dev *indio_dev) | ||
130 | { | ||
131 | struct device *dev = &indio_dev->dev; | ||
132 | struct iproc_adc_priv *adc_priv = iio_priv(indio_dev); | ||
133 | |||
134 | iproc_adc_dbg_reg(dev, adc_priv, IPROC_REGCTL1); | ||
135 | iproc_adc_dbg_reg(dev, adc_priv, IPROC_REGCTL2); | ||
136 | iproc_adc_dbg_reg(dev, adc_priv, IPROC_INTERRUPT_THRES); | ||
137 | iproc_adc_dbg_reg(dev, adc_priv, IPROC_INTERRUPT_MASK); | ||
138 | iproc_adc_dbg_reg(dev, adc_priv, IPROC_INTERRUPT_STATUS); | ||
139 | iproc_adc_dbg_reg(dev, adc_priv, IPROC_CONTROLLER_STATUS); | ||
140 | iproc_adc_dbg_reg(dev, adc_priv, IPROC_ANALOG_CONTROL); | ||
141 | iproc_adc_dbg_reg(dev, adc_priv, IPROC_AUX_DATA); | ||
142 | iproc_adc_dbg_reg(dev, adc_priv, IPROC_SOFT_BYPASS_CONTROL); | ||
143 | iproc_adc_dbg_reg(dev, adc_priv, IPROC_SOFT_BYPASS_DATA); | ||
144 | } | ||
145 | |||
146 | static irqreturn_t iproc_adc_interrupt_handler(int irq, void *data) | ||
147 | { | ||
148 | u32 channel_intr_status; | ||
149 | u32 intr_status; | ||
150 | u32 intr_mask; | ||
151 | struct iio_dev *indio_dev = data; | ||
152 | struct iproc_adc_priv *adc_priv = iio_priv(indio_dev); | ||
153 | |||
154 | /* | ||
155 | * This interrupt is shared with the touchscreen driver. | ||
156 | * Make sure this interrupt is intended for us. | ||
157 | * Handle only ADC channel specific interrupts. | ||
158 | */ | ||
159 | regmap_read(adc_priv->regmap, IPROC_INTERRUPT_STATUS, &intr_status); | ||
160 | regmap_read(adc_priv->regmap, IPROC_INTERRUPT_MASK, &intr_mask); | ||
161 | intr_status = intr_status & intr_mask; | ||
162 | channel_intr_status = (intr_status & IPROC_ADC_INTR_MASK) >> | ||
163 | IPROC_ADC_INTR; | ||
164 | if (channel_intr_status) | ||
165 | return IRQ_WAKE_THREAD; | ||
166 | |||
167 | return IRQ_NONE; | ||
168 | } | ||
169 | |||
170 | static irqreturn_t iproc_adc_interrupt_thread(int irq, void *data) | ||
171 | { | ||
172 | irqreturn_t retval = IRQ_NONE; | ||
173 | struct iproc_adc_priv *adc_priv; | ||
174 | struct iio_dev *indio_dev = data; | ||
175 | unsigned int valid_entries; | ||
176 | u32 intr_status; | ||
177 | u32 intr_channels; | ||
178 | u32 channel_status; | ||
179 | u32 ch_intr_status; | ||
180 | |||
181 | adc_priv = iio_priv(indio_dev); | ||
182 | |||
183 | regmap_read(adc_priv->regmap, IPROC_INTERRUPT_STATUS, &intr_status); | ||
184 | dev_dbg(&indio_dev->dev, "iproc_adc_interrupt_thread(),INTRPT_STS:%x\n", | ||
185 | intr_status); | ||
186 | |||
187 | intr_channels = (intr_status & IPROC_ADC_INTR_MASK) >> IPROC_ADC_INTR; | ||
188 | if (intr_channels) { | ||
189 | regmap_read(adc_priv->regmap, | ||
190 | IPROC_ADC_CHANNEL_INTERRUPT_STATUS + | ||
191 | IPROC_ADC_CHANNEL_OFFSET * adc_priv->chan_id, | ||
192 | &ch_intr_status); | ||
193 | |||
194 | if (ch_intr_status & IPROC_ADC_CHANNEL_WTRMRK_INTR_MASK) { | ||
195 | regmap_read(adc_priv->regmap, | ||
196 | IPROC_ADC_CHANNEL_STATUS + | ||
197 | IPROC_ADC_CHANNEL_OFFSET * | ||
198 | adc_priv->chan_id, | ||
199 | &channel_status); | ||
200 | |||
201 | valid_entries = ((channel_status & | ||
202 | IPROC_ADC_CHANNEL_VALID_ENTERIES_MASK) >> | ||
203 | IPROC_ADC_CHANNEL_VALID_ENTERIES); | ||
204 | if (valid_entries >= 1) { | ||
205 | regmap_read(adc_priv->regmap, | ||
206 | IPROC_ADC_CHANNEL_DATA + | ||
207 | IPROC_ADC_CHANNEL_OFFSET * | ||
208 | adc_priv->chan_id, | ||
209 | &adc_priv->chan_val); | ||
210 | complete(&adc_priv->completion); | ||
211 | } else { | ||
212 | dev_err(&indio_dev->dev, | ||
213 | "No data rcvd on channel %d\n", | ||
214 | adc_priv->chan_id); | ||
215 | } | ||
216 | regmap_write(adc_priv->regmap, | ||
217 | IPROC_ADC_CHANNEL_INTERRUPT_MASK + | ||
218 | IPROC_ADC_CHANNEL_OFFSET * | ||
219 | adc_priv->chan_id, | ||
220 | (ch_intr_status & | ||
221 | ~(IPROC_ADC_CHANNEL_WTRMRK_INTR_MASK))); | ||
222 | } | ||
223 | regmap_write(adc_priv->regmap, | ||
224 | IPROC_ADC_CHANNEL_INTERRUPT_STATUS + | ||
225 | IPROC_ADC_CHANNEL_OFFSET * adc_priv->chan_id, | ||
226 | ch_intr_status); | ||
227 | regmap_write(adc_priv->regmap, IPROC_INTERRUPT_STATUS, | ||
228 | intr_channels); | ||
229 | retval = IRQ_HANDLED; | ||
230 | } | ||
231 | |||
232 | return retval; | ||
233 | } | ||
234 | |||
235 | static int iproc_adc_do_read(struct iio_dev *indio_dev, | ||
236 | int channel, | ||
237 | u16 *p_adc_data) | ||
238 | { | ||
239 | int read_len = 0; | ||
240 | u32 val; | ||
241 | u32 mask; | ||
242 | u32 val_check; | ||
243 | int failed_cnt = 0; | ||
244 | struct iproc_adc_priv *adc_priv = iio_priv(indio_dev); | ||
245 | |||
246 | mutex_lock(&adc_priv->mutex); | ||
247 | |||
248 | /* | ||
249 | * After a read is complete the ADC interrupts will be disabled so | ||
250 | * we can assume this section of code is safe from interrupts. | ||
251 | */ | ||
252 | adc_priv->chan_val = -1; | ||
253 | adc_priv->chan_id = channel; | ||
254 | |||
255 | reinit_completion(&adc_priv->completion); | ||
256 | /* Clear any pending interrupt */ | ||
257 | regmap_update_bits(adc_priv->regmap, IPROC_INTERRUPT_STATUS, | ||
258 | IPROC_ADC_INTR_MASK | IPROC_ADC_AUXDATA_RDY_INTR, | ||
259 | ((0x0 << channel) << IPROC_ADC_INTR) | | ||
260 | IPROC_ADC_AUXDATA_RDY_INTR); | ||
261 | |||
262 | /* Configure channel for snapshot mode and enable */ | ||
263 | val = (BIT(IPROC_ADC_CHANNEL_ROUNDS) | | ||
264 | (IPROC_ADC_CHANNEL_MODE_SNAPSHOT << IPROC_ADC_CHANNEL_MODE) | | ||
265 | (0x1 << IPROC_ADC_CHANNEL_ENABLE)); | ||
266 | |||
267 | mask = IPROC_ADC_CHANNEL_ROUNDS_MASK | IPROC_ADC_CHANNEL_MODE_MASK | | ||
268 | IPROC_ADC_CHANNEL_ENABLE_MASK; | ||
269 | regmap_update_bits(adc_priv->regmap, (IPROC_ADC_CHANNEL_REGCTL1 + | ||
270 | IPROC_ADC_CHANNEL_OFFSET * channel), | ||
271 | mask, val); | ||
272 | |||
273 | /* Set the Watermark for a channel */ | ||
274 | regmap_update_bits(adc_priv->regmap, (IPROC_ADC_CHANNEL_REGCTL2 + | ||
275 | IPROC_ADC_CHANNEL_OFFSET * channel), | ||
276 | IPROC_ADC_CHANNEL_WATERMARK_MASK, | ||
277 | 0x1); | ||
278 | |||
279 | /* Enable water mark interrupt */ | ||
280 | regmap_update_bits(adc_priv->regmap, (IPROC_ADC_CHANNEL_INTERRUPT_MASK + | ||
281 | IPROC_ADC_CHANNEL_OFFSET * | ||
282 | channel), | ||
283 | IPROC_ADC_CHANNEL_WTRMRK_INTR_MASK, | ||
284 | IPROC_ADC_WATER_MARK_INTR_ENABLE); | ||
285 | regmap_read(adc_priv->regmap, IPROC_INTERRUPT_MASK, &val); | ||
286 | |||
287 | /* Enable ADC interrupt for a channel */ | ||
288 | val |= (BIT(channel) << IPROC_ADC_INTR); | ||
289 | regmap_write(adc_priv->regmap, IPROC_INTERRUPT_MASK, val); | ||
290 | |||
291 | /* | ||
292 | * There seems to be a very rare issue where writing to this register | ||
293 | * does not take effect. To work around the issue we will try multiple | ||
294 | * writes. In total we will spend about 10*10 = 100 us attempting this. | ||
295 | * Testing has shown that this may loop a few time, but we have never | ||
296 | * hit the full count. | ||
297 | */ | ||
298 | regmap_read(adc_priv->regmap, IPROC_INTERRUPT_MASK, &val_check); | ||
299 | while (val_check != val) { | ||
300 | failed_cnt++; | ||
301 | |||
302 | if (failed_cnt > IPROC_ADC_INTMASK_RETRY_ATTEMPTS) | ||
303 | break; | ||
304 | |||
305 | udelay(10); | ||
306 | regmap_update_bits(adc_priv->regmap, IPROC_INTERRUPT_MASK, | ||
307 | IPROC_ADC_INTR_MASK, | ||
308 | ((0x1 << channel) << | ||
309 | IPROC_ADC_INTR)); | ||
310 | |||
311 | regmap_read(adc_priv->regmap, IPROC_INTERRUPT_MASK, &val_check); | ||
312 | } | ||
313 | |||
314 | if (failed_cnt) { | ||
315 | dev_dbg(&indio_dev->dev, | ||
316 | "IntMask failed (%d times)", failed_cnt); | ||
317 | if (failed_cnt > IPROC_ADC_INTMASK_RETRY_ATTEMPTS) { | ||
318 | dev_err(&indio_dev->dev, | ||
319 | "IntMask set failed. Read will likely fail."); | ||
320 | read_len = -EIO; | ||
321 | goto adc_err; | ||
322 | }; | ||
323 | } | ||
324 | regmap_read(adc_priv->regmap, IPROC_INTERRUPT_MASK, &val_check); | ||
325 | |||
326 | if (wait_for_completion_timeout(&adc_priv->completion, | ||
327 | IPROC_ADC_READ_TIMEOUT) > 0) { | ||
328 | |||
329 | /* Only the lower 16 bits are relevant */ | ||
330 | *p_adc_data = adc_priv->chan_val & 0xFFFF; | ||
331 | read_len = sizeof(*p_adc_data); | ||
332 | |||
333 | } else { | ||
334 | /* | ||
335 | * We never got the interrupt, something went wrong. | ||
336 | * Perhaps the interrupt may still be coming, we do not want | ||
337 | * that now. Lets disable the ADC interrupt, and clear the | ||
338 | * status to put it back in to normal state. | ||
339 | */ | ||
340 | read_len = -ETIMEDOUT; | ||
341 | goto adc_err; | ||
342 | } | ||
343 | mutex_unlock(&adc_priv->mutex); | ||
344 | |||
345 | return read_len; | ||
346 | |||
347 | adc_err: | ||
348 | regmap_update_bits(adc_priv->regmap, IPROC_INTERRUPT_MASK, | ||
349 | IPROC_ADC_INTR_MASK, | ||
350 | ((0x0 << channel) << IPROC_ADC_INTR)); | ||
351 | |||
352 | regmap_update_bits(adc_priv->regmap, IPROC_INTERRUPT_STATUS, | ||
353 | IPROC_ADC_INTR_MASK, | ||
354 | ((0x0 << channel) << IPROC_ADC_INTR)); | ||
355 | |||
356 | dev_err(&indio_dev->dev, "Timed out waiting for ADC data!\n"); | ||
357 | iproc_adc_reg_dump(indio_dev); | ||
358 | mutex_unlock(&adc_priv->mutex); | ||
359 | |||
360 | return read_len; | ||
361 | } | ||
362 | |||
363 | static int iproc_adc_enable(struct iio_dev *indio_dev) | ||
364 | { | ||
365 | u32 val; | ||
366 | u32 channel_id; | ||
367 | struct iproc_adc_priv *adc_priv = iio_priv(indio_dev); | ||
368 | int ret; | ||
369 | |||
370 | /* Set i_amux = 3b'000, select channel 0 */ | ||
371 | ret = regmap_update_bits(adc_priv->regmap, IPROC_ANALOG_CONTROL, | ||
372 | IPROC_ADC_CHANNEL_SEL_MASK, 0); | ||
373 | if (ret) { | ||
374 | dev_err(&indio_dev->dev, | ||
375 | "failed to write IPROC_ANALOG_CONTROL %d\n", ret); | ||
376 | return ret; | ||
377 | } | ||
378 | adc_priv->chan_val = -1; | ||
379 | |||
380 | /* | ||
381 | * PWR up LDO, ADC, and Band Gap (0 to enable) | ||
382 | * Also enable ADC controller (set high) | ||
383 | */ | ||
384 | ret = regmap_read(adc_priv->regmap, IPROC_REGCTL2, &val); | ||
385 | if (ret) { | ||
386 | dev_err(&indio_dev->dev, | ||
387 | "failed to read IPROC_REGCTL2 %d\n", ret); | ||
388 | return ret; | ||
389 | } | ||
390 | |||
391 | val &= ~(IPROC_ADC_PWR_LDO | IPROC_ADC_PWR_ADC | IPROC_ADC_PWR_BG); | ||
392 | |||
393 | ret = regmap_write(adc_priv->regmap, IPROC_REGCTL2, val); | ||
394 | if (ret) { | ||
395 | dev_err(&indio_dev->dev, | ||
396 | "failed to write IPROC_REGCTL2 %d\n", ret); | ||
397 | return ret; | ||
398 | } | ||
399 | |||
400 | ret = regmap_read(adc_priv->regmap, IPROC_REGCTL2, &val); | ||
401 | if (ret) { | ||
402 | dev_err(&indio_dev->dev, | ||
403 | "failed to read IPROC_REGCTL2 %d\n", ret); | ||
404 | return ret; | ||
405 | } | ||
406 | |||
407 | val |= IPROC_ADC_CONTROLLER_EN; | ||
408 | ret = regmap_write(adc_priv->regmap, IPROC_REGCTL2, val); | ||
409 | if (ret) { | ||
410 | dev_err(&indio_dev->dev, | ||
411 | "failed to write IPROC_REGCTL2 %d\n", ret); | ||
412 | return ret; | ||
413 | } | ||
414 | |||
415 | for (channel_id = 0; channel_id < indio_dev->num_channels; | ||
416 | channel_id++) { | ||
417 | ret = regmap_write(adc_priv->regmap, | ||
418 | IPROC_ADC_CHANNEL_INTERRUPT_MASK + | ||
419 | IPROC_ADC_CHANNEL_OFFSET * channel_id, 0); | ||
420 | if (ret) { | ||
421 | dev_err(&indio_dev->dev, | ||
422 | "failed to write ADC_CHANNEL_INTERRUPT_MASK %d\n", | ||
423 | ret); | ||
424 | return ret; | ||
425 | } | ||
426 | |||
427 | ret = regmap_write(adc_priv->regmap, | ||
428 | IPROC_ADC_CHANNEL_INTERRUPT_STATUS + | ||
429 | IPROC_ADC_CHANNEL_OFFSET * channel_id, 0); | ||
430 | if (ret) { | ||
431 | dev_err(&indio_dev->dev, | ||
432 | "failed to write ADC_CHANNEL_INTERRUPT_STATUS %d\n", | ||
433 | ret); | ||
434 | return ret; | ||
435 | } | ||
436 | } | ||
437 | |||
438 | return 0; | ||
439 | } | ||
440 | |||
441 | static void iproc_adc_disable(struct iio_dev *indio_dev) | ||
442 | { | ||
443 | u32 val; | ||
444 | int ret; | ||
445 | struct iproc_adc_priv *adc_priv = iio_priv(indio_dev); | ||
446 | |||
447 | ret = regmap_read(adc_priv->regmap, IPROC_REGCTL2, &val); | ||
448 | if (ret) { | ||
449 | dev_err(&indio_dev->dev, | ||
450 | "failed to read IPROC_REGCTL2 %d\n", ret); | ||
451 | return; | ||
452 | } | ||
453 | |||
454 | val &= ~IPROC_ADC_CONTROLLER_EN; | ||
455 | ret = regmap_write(adc_priv->regmap, IPROC_REGCTL2, val); | ||
456 | if (ret) { | ||
457 | dev_err(&indio_dev->dev, | ||
458 | "failed to write IPROC_REGCTL2 %d\n", ret); | ||
459 | return; | ||
460 | } | ||
461 | } | ||
462 | |||
463 | static int iproc_adc_read_raw(struct iio_dev *indio_dev, | ||
464 | struct iio_chan_spec const *chan, | ||
465 | int *val, | ||
466 | int *val2, | ||
467 | long mask) | ||
468 | { | ||
469 | u16 adc_data; | ||
470 | int err; | ||
471 | |||
472 | switch (mask) { | ||
473 | case IIO_CHAN_INFO_RAW: | ||
474 | err = iproc_adc_do_read(indio_dev, chan->channel, &adc_data); | ||
475 | if (err < 0) | ||
476 | return err; | ||
477 | *val = adc_data; | ||
478 | return IIO_VAL_INT; | ||
479 | case IIO_CHAN_INFO_SCALE: | ||
480 | switch (chan->type) { | ||
481 | case IIO_VOLTAGE: | ||
482 | *val = 1800; | ||
483 | *val2 = 10; | ||
484 | return IIO_VAL_FRACTIONAL_LOG2; | ||
485 | default: | ||
486 | return -EINVAL; | ||
487 | } | ||
488 | default: | ||
489 | return -EINVAL; | ||
490 | } | ||
491 | } | ||
492 | |||
493 | static const struct iio_info iproc_adc_iio_info = { | ||
494 | .read_raw = &iproc_adc_read_raw, | ||
495 | .driver_module = THIS_MODULE, | ||
496 | }; | ||
497 | |||
498 | #define IPROC_ADC_CHANNEL(_index, _id) { \ | ||
499 | .type = IIO_VOLTAGE, \ | ||
500 | .indexed = 1, \ | ||
501 | .channel = _index, \ | ||
502 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | ||
503 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ | ||
504 | .datasheet_name = _id, \ | ||
505 | } | ||
506 | |||
507 | static const struct iio_chan_spec iproc_adc_iio_channels[] = { | ||
508 | IPROC_ADC_CHANNEL(0, "adc0"), | ||
509 | IPROC_ADC_CHANNEL(1, "adc1"), | ||
510 | IPROC_ADC_CHANNEL(2, "adc2"), | ||
511 | IPROC_ADC_CHANNEL(3, "adc3"), | ||
512 | IPROC_ADC_CHANNEL(4, "adc4"), | ||
513 | IPROC_ADC_CHANNEL(5, "adc5"), | ||
514 | IPROC_ADC_CHANNEL(6, "adc6"), | ||
515 | IPROC_ADC_CHANNEL(7, "adc7"), | ||
516 | }; | ||
517 | |||
518 | static int iproc_adc_probe(struct platform_device *pdev) | ||
519 | { | ||
520 | struct iproc_adc_priv *adc_priv; | ||
521 | struct iio_dev *indio_dev = NULL; | ||
522 | int ret; | ||
523 | |||
524 | indio_dev = devm_iio_device_alloc(&pdev->dev, | ||
525 | sizeof(*adc_priv)); | ||
526 | if (!indio_dev) { | ||
527 | dev_err(&pdev->dev, "failed to allocate iio device\n"); | ||
528 | return -ENOMEM; | ||
529 | } | ||
530 | |||
531 | adc_priv = iio_priv(indio_dev); | ||
532 | platform_set_drvdata(pdev, indio_dev); | ||
533 | |||
534 | mutex_init(&adc_priv->mutex); | ||
535 | |||
536 | init_completion(&adc_priv->completion); | ||
537 | |||
538 | adc_priv->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, | ||
539 | "adc-syscon"); | ||
540 | if (IS_ERR(adc_priv->regmap)) { | ||
541 | dev_err(&pdev->dev, "failed to get handle for tsc syscon\n"); | ||
542 | ret = PTR_ERR(adc_priv->regmap); | ||
543 | return ret; | ||
544 | } | ||
545 | |||
546 | adc_priv->adc_clk = devm_clk_get(&pdev->dev, "tsc_clk"); | ||
547 | if (IS_ERR(adc_priv->adc_clk)) { | ||
548 | dev_err(&pdev->dev, | ||
549 | "failed getting clock tsc_clk\n"); | ||
550 | ret = PTR_ERR(adc_priv->adc_clk); | ||
551 | return ret; | ||
552 | } | ||
553 | |||
554 | adc_priv->irqno = platform_get_irq(pdev, 0); | ||
555 | if (adc_priv->irqno <= 0) { | ||
556 | dev_err(&pdev->dev, "platform_get_irq failed\n"); | ||
557 | ret = -ENODEV; | ||
558 | return ret; | ||
559 | } | ||
560 | |||
561 | ret = regmap_update_bits(adc_priv->regmap, IPROC_REGCTL2, | ||
562 | IPROC_ADC_AUXIN_SCAN_ENA, 0); | ||
563 | if (ret) { | ||
564 | dev_err(&pdev->dev, "failed to write IPROC_REGCTL2 %d\n", ret); | ||
565 | return ret; | ||
566 | } | ||
567 | |||
568 | ret = devm_request_threaded_irq(&pdev->dev, adc_priv->irqno, | ||
569 | iproc_adc_interrupt_thread, | ||
570 | iproc_adc_interrupt_handler, | ||
571 | IRQF_SHARED, "iproc-adc", indio_dev); | ||
572 | if (ret) { | ||
573 | dev_err(&pdev->dev, "request_irq error %d\n", ret); | ||
574 | return ret; | ||
575 | } | ||
576 | |||
577 | ret = clk_prepare_enable(adc_priv->adc_clk); | ||
578 | if (ret) { | ||
579 | dev_err(&pdev->dev, | ||
580 | "clk_prepare_enable failed %d\n", ret); | ||
581 | return ret; | ||
582 | } | ||
583 | |||
584 | ret = iproc_adc_enable(indio_dev); | ||
585 | if (ret) { | ||
586 | dev_err(&pdev->dev, "failed to enable adc %d\n", ret); | ||
587 | goto err_adc_enable; | ||
588 | } | ||
589 | |||
590 | indio_dev->name = "iproc-static-adc"; | ||
591 | indio_dev->dev.parent = &pdev->dev; | ||
592 | indio_dev->dev.of_node = pdev->dev.of_node; | ||
593 | indio_dev->info = &iproc_adc_iio_info; | ||
594 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
595 | indio_dev->channels = iproc_adc_iio_channels; | ||
596 | indio_dev->num_channels = ARRAY_SIZE(iproc_adc_iio_channels); | ||
597 | |||
598 | ret = iio_device_register(indio_dev); | ||
599 | if (ret) { | ||
600 | dev_err(&pdev->dev, "iio_device_register failed:err %d\n", ret); | ||
601 | goto err_clk; | ||
602 | } | ||
603 | |||
604 | return 0; | ||
605 | |||
606 | err_clk: | ||
607 | iproc_adc_disable(indio_dev); | ||
608 | err_adc_enable: | ||
609 | clk_disable_unprepare(adc_priv->adc_clk); | ||
610 | |||
611 | return ret; | ||
612 | } | ||
613 | |||
614 | static int iproc_adc_remove(struct platform_device *pdev) | ||
615 | { | ||
616 | struct iio_dev *indio_dev = platform_get_drvdata(pdev); | ||
617 | struct iproc_adc_priv *adc_priv = iio_priv(indio_dev); | ||
618 | |||
619 | iio_device_unregister(indio_dev); | ||
620 | iproc_adc_disable(indio_dev); | ||
621 | clk_disable_unprepare(adc_priv->adc_clk); | ||
622 | |||
623 | return 0; | ||
624 | } | ||
625 | |||
626 | static const struct of_device_id iproc_adc_of_match[] = { | ||
627 | {.compatible = "brcm,iproc-static-adc", }, | ||
628 | { }, | ||
629 | }; | ||
630 | MODULE_DEVICE_TABLE(of, iproc_adc_of_match); | ||
631 | |||
632 | static struct platform_driver iproc_adc_driver = { | ||
633 | .probe = iproc_adc_probe, | ||
634 | .remove = iproc_adc_remove, | ||
635 | .driver = { | ||
636 | .name = "iproc-static-adc", | ||
637 | .of_match_table = of_match_ptr(iproc_adc_of_match), | ||
638 | }, | ||
639 | }; | ||
640 | module_platform_driver(iproc_adc_driver); | ||
641 | |||
642 | MODULE_DESCRIPTION("Broadcom iProc ADC controller driver"); | ||
643 | MODULE_AUTHOR("Raveendra Padasalagi <raveendra.padasalagi@broadcom.com>"); | ||
644 | MODULE_LICENSE("GPL v2"); | ||