Commit | Line | Data |
---|---|---|
70f19379 AT |
1 | /* |
2 | * Marvell Berlin2 ADC driver | |
3 | * | |
4 | * Copyright (C) 2015 Marvell Technology Group Ltd. | |
5 | * | |
6 | * Antoine Tenart <antoine.tenart@free-electrons.com> | |
7 | * | |
8 | * This file is licensed under the terms of the GNU General Public | |
9 | * License version 2. This program is licensed "as is" without any | |
10 | * warranty of any kind, whether express or implied. | |
11 | */ | |
12 | ||
13 | #include <linux/iio/iio.h> | |
14 | #include <linux/iio/driver.h> | |
15 | #include <linux/iio/machine.h> | |
16 | #include <linux/interrupt.h> | |
17 | #include <linux/kernel.h> | |
18 | #include <linux/module.h> | |
19 | #include <linux/platform_device.h> | |
20 | #include <linux/slab.h> | |
21 | #include <linux/mfd/syscon.h> | |
22 | #include <linux/regmap.h> | |
23 | #include <linux/sched.h> | |
24 | #include <linux/wait.h> | |
25 | ||
26 | #define BERLIN2_SM_CTRL 0x14 | |
27 | #define BERLIN2_SM_CTRL_SM_SOC_INT BIT(1) | |
28 | #define BERLIN2_SM_CTRL_SOC_SM_INT BIT(2) | |
57cb0676 | 29 | #define BERLIN2_SM_CTRL_ADC_SEL(x) ((x) << 5) /* 0-15 */ |
4b308e8c | 30 | #define BERLIN2_SM_CTRL_ADC_SEL_MASK GENMASK(8, 5) |
70f19379 AT |
31 | #define BERLIN2_SM_CTRL_ADC_POWER BIT(9) |
32 | #define BERLIN2_SM_CTRL_ADC_CLKSEL_DIV2 (0x0 << 10) | |
33 | #define BERLIN2_SM_CTRL_ADC_CLKSEL_DIV3 (0x1 << 10) | |
34 | #define BERLIN2_SM_CTRL_ADC_CLKSEL_DIV4 (0x2 << 10) | |
35 | #define BERLIN2_SM_CTRL_ADC_CLKSEL_DIV8 (0x3 << 10) | |
4b308e8c | 36 | #define BERLIN2_SM_CTRL_ADC_CLKSEL_MASK GENMASK(11, 10) |
70f19379 AT |
37 | #define BERLIN2_SM_CTRL_ADC_START BIT(12) |
38 | #define BERLIN2_SM_CTRL_ADC_RESET BIT(13) | |
39 | #define BERLIN2_SM_CTRL_ADC_BANDGAP_RDY BIT(14) | |
40 | #define BERLIN2_SM_CTRL_ADC_CONT_SINGLE (0x0 << 15) | |
41 | #define BERLIN2_SM_CTRL_ADC_CONT_CONTINUOUS (0x1 << 15) | |
42 | #define BERLIN2_SM_CTRL_ADC_BUFFER_EN BIT(16) | |
43 | #define BERLIN2_SM_CTRL_ADC_VREF_EXT (0x0 << 17) | |
44 | #define BERLIN2_SM_CTRL_ADC_VREF_INT (0x1 << 17) | |
45 | #define BERLIN2_SM_CTRL_ADC_ROTATE BIT(19) | |
46 | #define BERLIN2_SM_CTRL_TSEN_EN BIT(20) | |
47 | #define BERLIN2_SM_CTRL_TSEN_CLK_SEL_125 (0x0 << 21) /* 1.25 MHz */ | |
48 | #define BERLIN2_SM_CTRL_TSEN_CLK_SEL_250 (0x1 << 21) /* 2.5 MHz */ | |
49 | #define BERLIN2_SM_CTRL_TSEN_MODE_0_125 (0x0 << 22) /* 0-125 C */ | |
50 | #define BERLIN2_SM_CTRL_TSEN_MODE_10_50 (0x1 << 22) /* 10-50 C */ | |
51 | #define BERLIN2_SM_CTRL_TSEN_RESET BIT(29) | |
52 | #define BERLIN2_SM_ADC_DATA 0x20 | |
4b308e8c | 53 | #define BERLIN2_SM_ADC_MASK GENMASK(9, 0) |
70f19379 AT |
54 | #define BERLIN2_SM_ADC_STATUS 0x1c |
55 | #define BERLIN2_SM_ADC_STATUS_DATA_RDY(x) BIT(x) /* 0-15 */ | |
57cb0676 | 56 | #define BERLIN2_SM_ADC_STATUS_DATA_RDY_MASK GENMASK(15, 0) |
70f19379 | 57 | #define BERLIN2_SM_ADC_STATUS_INT_EN(x) (BIT(x) << 16) /* 0-15 */ |
57cb0676 | 58 | #define BERLIN2_SM_ADC_STATUS_INT_EN_MASK GENMASK(31, 16) |
70f19379 AT |
59 | #define BERLIN2_SM_TSEN_STATUS 0x24 |
60 | #define BERLIN2_SM_TSEN_STATUS_DATA_RDY BIT(0) | |
61 | #define BERLIN2_SM_TSEN_STATUS_INT_EN BIT(1) | |
62 | #define BERLIN2_SM_TSEN_DATA 0x28 | |
57cb0676 | 63 | #define BERLIN2_SM_TSEN_MASK GENMASK(9, 0) |
70f19379 AT |
64 | #define BERLIN2_SM_TSEN_CTRL 0x74 |
65 | #define BERLIN2_SM_TSEN_CTRL_START BIT(8) | |
66 | #define BERLIN2_SM_TSEN_CTRL_SETTLING_4 (0x0 << 21) /* 4 us */ | |
67 | #define BERLIN2_SM_TSEN_CTRL_SETTLING_12 (0x1 << 21) /* 12 us */ | |
4b308e8c | 68 | #define BERLIN2_SM_TSEN_CTRL_SETTLING_MASK BIT(21) |
70f19379 | 69 | #define BERLIN2_SM_TSEN_CTRL_TRIM(x) ((x) << 22) |
4b308e8c | 70 | #define BERLIN2_SM_TSEN_CTRL_TRIM_MASK GENMASK(25, 22) |
70f19379 AT |
71 | |
72 | struct berlin2_adc_priv { | |
73 | struct regmap *regmap; | |
74 | struct mutex lock; | |
75 | wait_queue_head_t wq; | |
76 | bool data_available; | |
77 | int data; | |
78 | }; | |
79 | ||
80 | #define BERLIN2_ADC_CHANNEL(n, t) \ | |
81 | { \ | |
82 | .channel = n, \ | |
83 | .datasheet_name = "channel"#n, \ | |
84 | .type = t, \ | |
85 | .indexed = 1, \ | |
86 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | |
87 | } | |
88 | ||
688febbd | 89 | static const struct iio_chan_spec berlin2_adc_channels[] = { |
70f19379 AT |
90 | BERLIN2_ADC_CHANNEL(0, IIO_VOLTAGE), /* external input */ |
91 | BERLIN2_ADC_CHANNEL(1, IIO_VOLTAGE), /* external input */ | |
92 | BERLIN2_ADC_CHANNEL(2, IIO_VOLTAGE), /* external input */ | |
93 | BERLIN2_ADC_CHANNEL(3, IIO_VOLTAGE), /* external input */ | |
94 | BERLIN2_ADC_CHANNEL(4, IIO_VOLTAGE), /* reserved */ | |
95 | BERLIN2_ADC_CHANNEL(5, IIO_VOLTAGE), /* reserved */ | |
96 | { /* temperature sensor */ | |
97 | .channel = 6, | |
98 | .datasheet_name = "channel6", | |
99 | .type = IIO_TEMP, | |
100 | .indexed = 0, | |
101 | .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), | |
102 | }, | |
103 | BERLIN2_ADC_CHANNEL(7, IIO_VOLTAGE), /* reserved */ | |
104 | IIO_CHAN_SOFT_TIMESTAMP(8), /* timestamp */ | |
105 | }; | |
70f19379 AT |
106 | |
107 | static int berlin2_adc_read(struct iio_dev *indio_dev, int channel) | |
108 | { | |
109 | struct berlin2_adc_priv *priv = iio_priv(indio_dev); | |
110 | int data, ret; | |
111 | ||
112 | mutex_lock(&priv->lock); | |
113 | ||
114 | /* Configure the ADC */ | |
115 | regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL, | |
116 | BERLIN2_SM_CTRL_ADC_RESET | BERLIN2_SM_CTRL_ADC_SEL_MASK | |
117 | | BERLIN2_SM_CTRL_ADC_START, | |
118 | BERLIN2_SM_CTRL_ADC_SEL(channel) | BERLIN2_SM_CTRL_ADC_START); | |
119 | ||
120 | ret = wait_event_interruptible_timeout(priv->wq, priv->data_available, | |
121 | msecs_to_jiffies(1000)); | |
122 | ||
123 | /* Disable the interrupts */ | |
124 | regmap_update_bits(priv->regmap, BERLIN2_SM_ADC_STATUS, | |
125 | BERLIN2_SM_ADC_STATUS_INT_EN(channel), 0); | |
126 | ||
127 | if (ret == 0) | |
128 | ret = -ETIMEDOUT; | |
129 | if (ret < 0) { | |
130 | mutex_unlock(&priv->lock); | |
131 | return ret; | |
132 | } | |
133 | ||
134 | regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL, | |
135 | BERLIN2_SM_CTRL_ADC_START, 0); | |
136 | ||
137 | data = priv->data; | |
138 | priv->data_available = false; | |
139 | ||
140 | mutex_unlock(&priv->lock); | |
141 | ||
142 | return data; | |
143 | } | |
144 | ||
145 | static int berlin2_adc_tsen_read(struct iio_dev *indio_dev) | |
146 | { | |
147 | struct berlin2_adc_priv *priv = iio_priv(indio_dev); | |
148 | int data, ret; | |
149 | ||
150 | mutex_lock(&priv->lock); | |
151 | ||
152 | /* Configure the ADC */ | |
153 | regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL, | |
154 | BERLIN2_SM_CTRL_TSEN_RESET | BERLIN2_SM_CTRL_ADC_ROTATE, | |
155 | BERLIN2_SM_CTRL_ADC_ROTATE); | |
156 | ||
157 | /* Configure the temperature sensor */ | |
158 | regmap_update_bits(priv->regmap, BERLIN2_SM_TSEN_CTRL, | |
159 | BERLIN2_SM_TSEN_CTRL_TRIM_MASK | BERLIN2_SM_TSEN_CTRL_SETTLING_MASK | |
160 | | BERLIN2_SM_TSEN_CTRL_START, | |
161 | BERLIN2_SM_TSEN_CTRL_TRIM(3) | BERLIN2_SM_TSEN_CTRL_SETTLING_12 | |
162 | | BERLIN2_SM_TSEN_CTRL_START); | |
163 | ||
164 | ret = wait_event_interruptible_timeout(priv->wq, priv->data_available, | |
165 | msecs_to_jiffies(1000)); | |
166 | ||
167 | /* Disable interrupts */ | |
168 | regmap_update_bits(priv->regmap, BERLIN2_SM_TSEN_STATUS, | |
169 | BERLIN2_SM_TSEN_STATUS_INT_EN, 0); | |
170 | ||
171 | if (ret == 0) | |
172 | ret = -ETIMEDOUT; | |
173 | if (ret < 0) { | |
174 | mutex_unlock(&priv->lock); | |
175 | return ret; | |
176 | } | |
177 | ||
178 | regmap_update_bits(priv->regmap, BERLIN2_SM_TSEN_CTRL, | |
179 | BERLIN2_SM_TSEN_CTRL_START, 0); | |
180 | ||
181 | data = priv->data; | |
182 | priv->data_available = false; | |
183 | ||
184 | mutex_unlock(&priv->lock); | |
185 | ||
186 | return data; | |
187 | } | |
188 | ||
189 | static int berlin2_adc_read_raw(struct iio_dev *indio_dev, | |
190 | struct iio_chan_spec const *chan, int *val, int *val2, | |
191 | long mask) | |
192 | { | |
193 | struct berlin2_adc_priv *priv = iio_priv(indio_dev); | |
194 | int temp; | |
195 | ||
196 | switch (mask) { | |
197 | case IIO_CHAN_INFO_RAW: | |
198 | if (chan->type != IIO_VOLTAGE) | |
199 | return -EINVAL; | |
200 | ||
201 | /* Enable the interrupts */ | |
202 | regmap_write(priv->regmap, BERLIN2_SM_ADC_STATUS, | |
203 | BERLIN2_SM_ADC_STATUS_INT_EN(chan->channel)); | |
204 | ||
205 | *val = berlin2_adc_read(indio_dev, chan->channel); | |
206 | if (*val < 0) | |
207 | return *val; | |
208 | ||
209 | return IIO_VAL_INT; | |
210 | case IIO_CHAN_INFO_PROCESSED: | |
211 | if (chan->type != IIO_TEMP) | |
212 | return -EINVAL; | |
213 | ||
214 | /* Enable interrupts */ | |
215 | regmap_write(priv->regmap, BERLIN2_SM_TSEN_STATUS, | |
216 | BERLIN2_SM_TSEN_STATUS_INT_EN); | |
217 | ||
218 | temp = berlin2_adc_tsen_read(indio_dev); | |
219 | if (temp < 0) | |
220 | return temp; | |
221 | ||
222 | if (temp > 2047) | |
609e9d88 | 223 | temp -= 4096; |
70f19379 AT |
224 | |
225 | /* Convert to milli Celsius */ | |
226 | *val = ((temp * 100000) / 264 - 270000); | |
227 | return IIO_VAL_INT; | |
228 | default: | |
229 | break; | |
230 | } | |
231 | ||
232 | return -EINVAL; | |
233 | } | |
234 | ||
235 | static irqreturn_t berlin2_adc_irq(int irq, void *private) | |
236 | { | |
237 | struct berlin2_adc_priv *priv = iio_priv(private); | |
238 | unsigned val; | |
239 | ||
240 | regmap_read(priv->regmap, BERLIN2_SM_ADC_STATUS, &val); | |
241 | if (val & BERLIN2_SM_ADC_STATUS_DATA_RDY_MASK) { | |
242 | regmap_read(priv->regmap, BERLIN2_SM_ADC_DATA, &priv->data); | |
243 | priv->data &= BERLIN2_SM_ADC_MASK; | |
244 | ||
245 | val &= ~BERLIN2_SM_ADC_STATUS_DATA_RDY_MASK; | |
246 | regmap_write(priv->regmap, BERLIN2_SM_ADC_STATUS, val); | |
247 | ||
248 | priv->data_available = true; | |
249 | wake_up_interruptible(&priv->wq); | |
250 | } | |
251 | ||
252 | return IRQ_HANDLED; | |
253 | } | |
254 | ||
255 | static irqreturn_t berlin2_adc_tsen_irq(int irq, void *private) | |
256 | { | |
257 | struct berlin2_adc_priv *priv = iio_priv(private); | |
258 | unsigned val; | |
259 | ||
260 | regmap_read(priv->regmap, BERLIN2_SM_TSEN_STATUS, &val); | |
261 | if (val & BERLIN2_SM_TSEN_STATUS_DATA_RDY) { | |
262 | regmap_read(priv->regmap, BERLIN2_SM_TSEN_DATA, &priv->data); | |
263 | priv->data &= BERLIN2_SM_TSEN_MASK; | |
264 | ||
265 | val &= ~BERLIN2_SM_TSEN_STATUS_DATA_RDY; | |
266 | regmap_write(priv->regmap, BERLIN2_SM_TSEN_STATUS, val); | |
267 | ||
268 | priv->data_available = true; | |
269 | wake_up_interruptible(&priv->wq); | |
270 | } | |
271 | ||
272 | return IRQ_HANDLED; | |
273 | } | |
274 | ||
275 | static const struct iio_info berlin2_adc_info = { | |
276 | .driver_module = THIS_MODULE, | |
277 | .read_raw = berlin2_adc_read_raw, | |
278 | }; | |
279 | ||
280 | static int berlin2_adc_probe(struct platform_device *pdev) | |
281 | { | |
282 | struct iio_dev *indio_dev; | |
283 | struct berlin2_adc_priv *priv; | |
284 | struct device_node *parent_np = of_get_parent(pdev->dev.of_node); | |
285 | int irq, tsen_irq; | |
286 | int ret; | |
287 | ||
609e9d88 | 288 | indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv)); |
70f19379 AT |
289 | if (!indio_dev) |
290 | return -ENOMEM; | |
291 | ||
292 | priv = iio_priv(indio_dev); | |
293 | platform_set_drvdata(pdev, indio_dev); | |
294 | ||
295 | priv->regmap = syscon_node_to_regmap(parent_np); | |
296 | of_node_put(parent_np); | |
297 | if (IS_ERR(priv->regmap)) | |
298 | return PTR_ERR(priv->regmap); | |
299 | ||
300 | irq = platform_get_irq_byname(pdev, "adc"); | |
301 | if (irq < 0) | |
19d56642 | 302 | return irq; |
70f19379 AT |
303 | |
304 | tsen_irq = platform_get_irq_byname(pdev, "tsen"); | |
305 | if (tsen_irq < 0) | |
19d56642 | 306 | return tsen_irq; |
70f19379 AT |
307 | |
308 | ret = devm_request_irq(&pdev->dev, irq, berlin2_adc_irq, 0, | |
309 | pdev->dev.driver->name, indio_dev); | |
310 | if (ret) | |
311 | return ret; | |
312 | ||
313 | ret = devm_request_irq(&pdev->dev, tsen_irq, berlin2_adc_tsen_irq, | |
314 | 0, pdev->dev.driver->name, indio_dev); | |
315 | if (ret) | |
316 | return ret; | |
317 | ||
318 | init_waitqueue_head(&priv->wq); | |
319 | mutex_init(&priv->lock); | |
320 | ||
321 | indio_dev->dev.parent = &pdev->dev; | |
322 | indio_dev->name = dev_name(&pdev->dev); | |
323 | indio_dev->modes = INDIO_DIRECT_MODE; | |
324 | indio_dev->info = &berlin2_adc_info; | |
325 | ||
70f19379 | 326 | indio_dev->channels = berlin2_adc_channels; |
546384c9 | 327 | indio_dev->num_channels = ARRAY_SIZE(berlin2_adc_channels); |
70f19379 AT |
328 | |
329 | /* Power up the ADC */ | |
330 | regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL, | |
331 | BERLIN2_SM_CTRL_ADC_POWER, BERLIN2_SM_CTRL_ADC_POWER); | |
332 | ||
333 | ret = iio_device_register(indio_dev); | |
334 | if (ret) { | |
335 | /* Power down the ADC */ | |
336 | regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL, | |
337 | BERLIN2_SM_CTRL_ADC_POWER, 0); | |
338 | return ret; | |
339 | } | |
340 | ||
341 | return 0; | |
342 | } | |
343 | ||
344 | static int berlin2_adc_remove(struct platform_device *pdev) | |
345 | { | |
346 | struct iio_dev *indio_dev = platform_get_drvdata(pdev); | |
347 | struct berlin2_adc_priv *priv = iio_priv(indio_dev); | |
348 | ||
349 | iio_device_unregister(indio_dev); | |
350 | ||
351 | /* Power down the ADC */ | |
352 | regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL, | |
353 | BERLIN2_SM_CTRL_ADC_POWER, 0); | |
354 | ||
355 | return 0; | |
356 | } | |
357 | ||
358 | static const struct of_device_id berlin2_adc_match[] = { | |
359 | { .compatible = "marvell,berlin2-adc", }, | |
360 | { }, | |
361 | }; | |
362 | MODULE_DEVICE_TABLE(of, berlin2_adc_match); | |
363 | ||
364 | static struct platform_driver berlin2_adc_driver = { | |
365 | .driver = { | |
366 | .name = "berlin2-adc", | |
367 | .of_match_table = berlin2_adc_match, | |
368 | }, | |
369 | .probe = berlin2_adc_probe, | |
370 | .remove = berlin2_adc_remove, | |
371 | }; | |
372 | module_platform_driver(berlin2_adc_driver); | |
373 | ||
374 | MODULE_AUTHOR("Antoine Tenart <antoine.tenart@free-electrons.com>"); | |
375 | MODULE_DESCRIPTION("Marvell Berlin2 ADC driver"); | |
376 | MODULE_LICENSE("GPL v2"); |