2 * Copyright (C) 2014-2015 Pengutronix, Markus Pargmann <mpa@pengutronix.de>
4 * This program is free software; you can redistribute it and/or modify it under
5 * the terms of the GNU General Public License version 2 as published by the
6 * Free Software Foundation.
8 * This is the driver for the imx25 GCQ (Generic Conversion Queue)
9 * connected to the imx25 ADC.
12 #include <dt-bindings/iio/adc/fsl-imx25-gcq.h>
13 #include <linux/clk.h>
14 #include <linux/iio/iio.h>
15 #include <linux/interrupt.h>
16 #include <linux/mfd/imx25-tsadc.h>
17 #include <linux/module.h>
19 #include <linux/platform_device.h>
20 #include <linux/regmap.h>
21 #include <linux/regulator/consumer.h>
23 #define MX25_GCQ_TIMEOUT (msecs_to_jiffies(2000))
25 static const char * const driver_name
= "mx25-gcq";
39 struct mx25_gcq_priv
{
41 struct completion completed
;
44 struct regulator
*vref
[4];
45 u32 channel_vref_mv
[MX25_NUM_CFGS
];
48 #define MX25_CQG_CHAN(chan, id) {\
52 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
53 BIT(IIO_CHAN_INFO_SCALE),\
54 .datasheet_name = id,\
57 static const struct iio_chan_spec mx25_gcq_channels
[MX25_NUM_CFGS
] = {
58 MX25_CQG_CHAN(MX25_CFG_XP
, "xp"),
59 MX25_CQG_CHAN(MX25_CFG_YP
, "yp"),
60 MX25_CQG_CHAN(MX25_CFG_XN
, "xn"),
61 MX25_CQG_CHAN(MX25_CFG_YN
, "yn"),
62 MX25_CQG_CHAN(MX25_CFG_WIPER
, "wiper"),
63 MX25_CQG_CHAN(MX25_CFG_INAUX0
, "inaux0"),
64 MX25_CQG_CHAN(MX25_CFG_INAUX1
, "inaux1"),
65 MX25_CQG_CHAN(MX25_CFG_INAUX2
, "inaux2"),
68 static const char * const mx25_gcq_refp_names
[] = {
69 [MX25_ADC_REFP_YP
] = "yp",
70 [MX25_ADC_REFP_XP
] = "xp",
71 [MX25_ADC_REFP_INT
] = "int",
72 [MX25_ADC_REFP_EXT
] = "ext",
75 static irqreturn_t
mx25_gcq_irq(int irq
, void *data
)
77 struct mx25_gcq_priv
*priv
= data
;
80 regmap_read(priv
->regs
, MX25_ADCQ_SR
, &stats
);
82 if (stats
& MX25_ADCQ_SR_EOQ
) {
83 regmap_update_bits(priv
->regs
, MX25_ADCQ_MR
,
84 MX25_ADCQ_MR_EOQ_IRQ
, MX25_ADCQ_MR_EOQ_IRQ
);
85 complete(&priv
->completed
);
88 /* Disable conversion queue run */
89 regmap_update_bits(priv
->regs
, MX25_ADCQ_CR
, MX25_ADCQ_CR_FQS
, 0);
91 /* Acknowledge all possible irqs */
92 regmap_write(priv
->regs
, MX25_ADCQ_SR
, MX25_ADCQ_SR_FRR
|
93 MX25_ADCQ_SR_FUR
| MX25_ADCQ_SR_FOR
|
94 MX25_ADCQ_SR_EOQ
| MX25_ADCQ_SR_PD
);
99 static int mx25_gcq_get_raw_value(struct device
*dev
,
100 struct iio_chan_spec
const *chan
,
101 struct mx25_gcq_priv
*priv
,
107 /* Setup the configuration we want to use */
108 regmap_write(priv
->regs
, MX25_ADCQ_ITEM_7_0
,
109 MX25_ADCQ_ITEM(0, chan
->channel
));
111 regmap_update_bits(priv
->regs
, MX25_ADCQ_MR
, MX25_ADCQ_MR_EOQ_IRQ
, 0);
113 /* Trigger queue for one run */
114 regmap_update_bits(priv
->regs
, MX25_ADCQ_CR
, MX25_ADCQ_CR_FQS
,
117 timeout
= wait_for_completion_interruptible_timeout(
118 &priv
->completed
, MX25_GCQ_TIMEOUT
);
120 dev_err(dev
, "ADC wait for measurement failed\n");
122 } else if (timeout
== 0) {
123 dev_err(dev
, "ADC timed out\n");
127 regmap_read(priv
->regs
, MX25_ADCQ_FIFO
, &data
);
129 *val
= MX25_ADCQ_FIFO_DATA(data
);
134 static int mx25_gcq_read_raw(struct iio_dev
*indio_dev
,
135 struct iio_chan_spec
const *chan
, int *val
,
136 int *val2
, long mask
)
138 struct mx25_gcq_priv
*priv
= iio_priv(indio_dev
);
142 case IIO_CHAN_INFO_RAW
:
143 mutex_lock(&indio_dev
->mlock
);
144 ret
= mx25_gcq_get_raw_value(&indio_dev
->dev
, chan
, priv
, val
);
145 mutex_unlock(&indio_dev
->mlock
);
148 case IIO_CHAN_INFO_SCALE
:
149 *val
= priv
->channel_vref_mv
[chan
->channel
];
151 return IIO_VAL_FRACTIONAL_LOG2
;
158 static const struct iio_info mx25_gcq_iio_info
= {
159 .read_raw
= mx25_gcq_read_raw
,
162 static const struct regmap_config mx25_gcq_regconfig
= {
163 .max_register
= 0x5c,
169 static int mx25_gcq_setup_cfgs(struct platform_device
*pdev
,
170 struct mx25_gcq_priv
*priv
)
172 struct device_node
*np
= pdev
->dev
.of_node
;
173 struct device_node
*child
;
174 struct device
*dev
= &pdev
->dev
;
175 unsigned int refp_used
[4] = {};
179 * Setup all configurations registers with a default conversion
180 * configuration for each input
182 for (i
= 0; i
< MX25_NUM_CFGS
; ++i
)
183 regmap_write(priv
->regs
, MX25_ADCQ_CFG(i
),
184 MX25_ADCQ_CFG_YPLL_OFF
|
185 MX25_ADCQ_CFG_XNUR_OFF
|
186 MX25_ADCQ_CFG_XPUL_OFF
|
187 MX25_ADCQ_CFG_REFP_INT
|
188 MX25_ADCQ_CFG_IN(i
) |
189 MX25_ADCQ_CFG_REFN_NGND2
);
192 * First get all regulators to store them in channel_vref_mv if
193 * necessary. Later we use that information for proper IIO scale
196 priv
->vref
[MX25_ADC_REFP_INT
] = NULL
;
197 priv
->vref
[MX25_ADC_REFP_EXT
] =
198 devm_regulator_get_optional(&pdev
->dev
, "vref-ext");
199 priv
->vref
[MX25_ADC_REFP_XP
] =
200 devm_regulator_get_optional(&pdev
->dev
, "vref-xp");
201 priv
->vref
[MX25_ADC_REFP_YP
] =
202 devm_regulator_get_optional(&pdev
->dev
, "vref-yp");
204 for_each_child_of_node(np
, child
) {
206 u32 refp
= MX25_ADCQ_CFG_REFP_INT
;
207 u32 refn
= MX25_ADCQ_CFG_REFN_NGND2
;
209 ret
= of_property_read_u32(child
, "reg", ®
);
211 dev_err(dev
, "Failed to get reg property\n");
215 if (reg
>= MX25_NUM_CFGS
) {
217 "reg value is greater than the number of available configuration registers\n");
221 of_property_read_u32(child
, "fsl,adc-refp", &refp
);
222 of_property_read_u32(child
, "fsl,adc-refn", &refn
);
225 case MX25_ADC_REFP_EXT
:
226 case MX25_ADC_REFP_XP
:
227 case MX25_ADC_REFP_YP
:
228 if (IS_ERR(priv
->vref
[refp
])) {
229 dev_err(dev
, "Error, trying to use external voltage reference without a vref-%s regulator.",
230 mx25_gcq_refp_names
[refp
]);
231 return PTR_ERR(priv
->vref
[refp
]);
233 priv
->channel_vref_mv
[reg
] =
234 regulator_get_voltage(priv
->vref
[refp
]);
235 /* Conversion from uV to mV */
236 priv
->channel_vref_mv
[reg
] /= 1000;
238 case MX25_ADC_REFP_INT
:
239 priv
->channel_vref_mv
[reg
] = 2500;
242 dev_err(dev
, "Invalid positive reference %d\n", refp
);
249 * Shift the read values to the correct positions within the
252 refp
= MX25_ADCQ_CFG_REFP(refp
);
253 refn
= MX25_ADCQ_CFG_REFN(refn
);
255 if ((refp
& MX25_ADCQ_CFG_REFP_MASK
) != refp
) {
256 dev_err(dev
, "Invalid fsl,adc-refp property value\n");
259 if ((refn
& MX25_ADCQ_CFG_REFN_MASK
) != refn
) {
260 dev_err(dev
, "Invalid fsl,adc-refn property value\n");
264 regmap_update_bits(priv
->regs
, MX25_ADCQ_CFG(reg
),
265 MX25_ADCQ_CFG_REFP_MASK
|
266 MX25_ADCQ_CFG_REFN_MASK
,
269 regmap_update_bits(priv
->regs
, MX25_ADCQ_CR
,
270 MX25_ADCQ_CR_FRST
| MX25_ADCQ_CR_QRST
,
271 MX25_ADCQ_CR_FRST
| MX25_ADCQ_CR_QRST
);
273 regmap_write(priv
->regs
, MX25_ADCQ_CR
,
274 MX25_ADCQ_CR_PDMSK
| MX25_ADCQ_CR_QSM_FQS
);
276 /* Remove unused regulators */
277 for (i
= 0; i
!= 4; ++i
) {
279 if (!IS_ERR_OR_NULL(priv
->vref
[i
]))
280 devm_regulator_put(priv
->vref
[i
]);
281 priv
->vref
[i
] = NULL
;
288 static int mx25_gcq_probe(struct platform_device
*pdev
)
290 struct iio_dev
*indio_dev
;
291 struct mx25_gcq_priv
*priv
;
292 struct mx25_tsadc
*tsadc
= dev_get_drvdata(pdev
->dev
.parent
);
293 struct device
*dev
= &pdev
->dev
;
294 struct resource
*res
;
299 indio_dev
= devm_iio_device_alloc(&pdev
->dev
, sizeof(*priv
));
303 priv
= iio_priv(indio_dev
);
305 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
306 mem
= devm_ioremap_resource(dev
, res
);
310 priv
->regs
= devm_regmap_init_mmio(dev
, mem
, &mx25_gcq_regconfig
);
311 if (IS_ERR(priv
->regs
)) {
312 dev_err(dev
, "Failed to initialize regmap\n");
313 return PTR_ERR(priv
->regs
);
316 init_completion(&priv
->completed
);
318 ret
= mx25_gcq_setup_cfgs(pdev
, priv
);
322 for (i
= 0; i
!= 4; ++i
) {
326 ret
= regulator_enable(priv
->vref
[i
]);
328 goto err_regulator_disable
;
331 priv
->clk
= tsadc
->clk
;
332 ret
= clk_prepare_enable(priv
->clk
);
334 dev_err(dev
, "Failed to enable clock\n");
335 goto err_vref_disable
;
338 priv
->irq
= platform_get_irq(pdev
, 0);
339 if (priv
->irq
<= 0) {
340 dev_err(dev
, "Failed to get IRQ\n");
344 goto err_clk_unprepare
;
347 ret
= request_irq(priv
->irq
, mx25_gcq_irq
, 0, pdev
->name
, priv
);
349 dev_err(dev
, "Failed requesting IRQ\n");
350 goto err_clk_unprepare
;
353 indio_dev
->dev
.parent
= &pdev
->dev
;
354 indio_dev
->channels
= mx25_gcq_channels
;
355 indio_dev
->num_channels
= ARRAY_SIZE(mx25_gcq_channels
);
356 indio_dev
->info
= &mx25_gcq_iio_info
;
357 indio_dev
->name
= driver_name
;
359 ret
= iio_device_register(indio_dev
);
361 dev_err(dev
, "Failed to register iio device\n");
365 platform_set_drvdata(pdev
, indio_dev
);
370 free_irq(priv
->irq
, priv
);
372 clk_disable_unprepare(priv
->clk
);
375 err_regulator_disable
:
378 regulator_disable(priv
->vref
[i
]);
383 static int mx25_gcq_remove(struct platform_device
*pdev
)
385 struct iio_dev
*indio_dev
= platform_get_drvdata(pdev
);
386 struct mx25_gcq_priv
*priv
= iio_priv(indio_dev
);
389 iio_device_unregister(indio_dev
);
390 free_irq(priv
->irq
, priv
);
391 clk_disable_unprepare(priv
->clk
);
392 for (i
= 4; i
-- > 0;) {
394 regulator_disable(priv
->vref
[i
]);
400 static const struct of_device_id mx25_gcq_ids
[] = {
401 { .compatible
= "fsl,imx25-gcq", },
404 MODULE_DEVICE_TABLE(of
, mx25_gcq_ids
);
406 static struct platform_driver mx25_gcq_driver
= {
409 .of_match_table
= mx25_gcq_ids
,
411 .probe
= mx25_gcq_probe
,
412 .remove
= mx25_gcq_remove
,
414 module_platform_driver(mx25_gcq_driver
);
416 MODULE_DESCRIPTION("ADC driver for Freescale mx25");
417 MODULE_AUTHOR("Markus Pargmann <mpa@pengutronix.de>");
418 MODULE_LICENSE("GPL v2");