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");
216 if (reg
>= MX25_NUM_CFGS
) {
218 "reg value is greater than the number of available configuration registers\n");
223 of_property_read_u32(child
, "fsl,adc-refp", &refp
);
224 of_property_read_u32(child
, "fsl,adc-refn", &refn
);
227 case MX25_ADC_REFP_EXT
:
228 case MX25_ADC_REFP_XP
:
229 case MX25_ADC_REFP_YP
:
230 if (IS_ERR(priv
->vref
[refp
])) {
231 dev_err(dev
, "Error, trying to use external voltage reference without a vref-%s regulator.",
232 mx25_gcq_refp_names
[refp
]);
234 return PTR_ERR(priv
->vref
[refp
]);
236 priv
->channel_vref_mv
[reg
] =
237 regulator_get_voltage(priv
->vref
[refp
]);
238 /* Conversion from uV to mV */
239 priv
->channel_vref_mv
[reg
] /= 1000;
241 case MX25_ADC_REFP_INT
:
242 priv
->channel_vref_mv
[reg
] = 2500;
245 dev_err(dev
, "Invalid positive reference %d\n", refp
);
253 * Shift the read values to the correct positions within the
256 refp
= MX25_ADCQ_CFG_REFP(refp
);
257 refn
= MX25_ADCQ_CFG_REFN(refn
);
259 if ((refp
& MX25_ADCQ_CFG_REFP_MASK
) != refp
) {
260 dev_err(dev
, "Invalid fsl,adc-refp property value\n");
264 if ((refn
& MX25_ADCQ_CFG_REFN_MASK
) != refn
) {
265 dev_err(dev
, "Invalid fsl,adc-refn property value\n");
270 regmap_update_bits(priv
->regs
, MX25_ADCQ_CFG(reg
),
271 MX25_ADCQ_CFG_REFP_MASK
|
272 MX25_ADCQ_CFG_REFN_MASK
,
275 regmap_update_bits(priv
->regs
, MX25_ADCQ_CR
,
276 MX25_ADCQ_CR_FRST
| MX25_ADCQ_CR_QRST
,
277 MX25_ADCQ_CR_FRST
| MX25_ADCQ_CR_QRST
);
279 regmap_write(priv
->regs
, MX25_ADCQ_CR
,
280 MX25_ADCQ_CR_PDMSK
| MX25_ADCQ_CR_QSM_FQS
);
282 /* Remove unused regulators */
283 for (i
= 0; i
!= 4; ++i
) {
285 if (!IS_ERR_OR_NULL(priv
->vref
[i
]))
286 devm_regulator_put(priv
->vref
[i
]);
287 priv
->vref
[i
] = NULL
;
294 static int mx25_gcq_probe(struct platform_device
*pdev
)
296 struct iio_dev
*indio_dev
;
297 struct mx25_gcq_priv
*priv
;
298 struct mx25_tsadc
*tsadc
= dev_get_drvdata(pdev
->dev
.parent
);
299 struct device
*dev
= &pdev
->dev
;
300 struct resource
*res
;
305 indio_dev
= devm_iio_device_alloc(&pdev
->dev
, sizeof(*priv
));
309 priv
= iio_priv(indio_dev
);
311 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
312 mem
= devm_ioremap_resource(dev
, res
);
316 priv
->regs
= devm_regmap_init_mmio(dev
, mem
, &mx25_gcq_regconfig
);
317 if (IS_ERR(priv
->regs
)) {
318 dev_err(dev
, "Failed to initialize regmap\n");
319 return PTR_ERR(priv
->regs
);
322 init_completion(&priv
->completed
);
324 ret
= mx25_gcq_setup_cfgs(pdev
, priv
);
328 for (i
= 0; i
!= 4; ++i
) {
332 ret
= regulator_enable(priv
->vref
[i
]);
334 goto err_regulator_disable
;
337 priv
->clk
= tsadc
->clk
;
338 ret
= clk_prepare_enable(priv
->clk
);
340 dev_err(dev
, "Failed to enable clock\n");
341 goto err_vref_disable
;
344 priv
->irq
= platform_get_irq(pdev
, 0);
345 if (priv
->irq
<= 0) {
346 dev_err(dev
, "Failed to get IRQ\n");
350 goto err_clk_unprepare
;
353 ret
= request_irq(priv
->irq
, mx25_gcq_irq
, 0, pdev
->name
, priv
);
355 dev_err(dev
, "Failed requesting IRQ\n");
356 goto err_clk_unprepare
;
359 indio_dev
->dev
.parent
= &pdev
->dev
;
360 indio_dev
->channels
= mx25_gcq_channels
;
361 indio_dev
->num_channels
= ARRAY_SIZE(mx25_gcq_channels
);
362 indio_dev
->info
= &mx25_gcq_iio_info
;
363 indio_dev
->name
= driver_name
;
365 ret
= iio_device_register(indio_dev
);
367 dev_err(dev
, "Failed to register iio device\n");
371 platform_set_drvdata(pdev
, indio_dev
);
376 free_irq(priv
->irq
, priv
);
378 clk_disable_unprepare(priv
->clk
);
381 err_regulator_disable
:
384 regulator_disable(priv
->vref
[i
]);
389 static int mx25_gcq_remove(struct platform_device
*pdev
)
391 struct iio_dev
*indio_dev
= platform_get_drvdata(pdev
);
392 struct mx25_gcq_priv
*priv
= iio_priv(indio_dev
);
395 iio_device_unregister(indio_dev
);
396 free_irq(priv
->irq
, priv
);
397 clk_disable_unprepare(priv
->clk
);
398 for (i
= 4; i
-- > 0;) {
400 regulator_disable(priv
->vref
[i
]);
406 static const struct of_device_id mx25_gcq_ids
[] = {
407 { .compatible
= "fsl,imx25-gcq", },
410 MODULE_DEVICE_TABLE(of
, mx25_gcq_ids
);
412 static struct platform_driver mx25_gcq_driver
= {
415 .of_match_table
= mx25_gcq_ids
,
417 .probe
= mx25_gcq_probe
,
418 .remove
= mx25_gcq_remove
,
420 module_platform_driver(mx25_gcq_driver
);
422 MODULE_DESCRIPTION("ADC driver for Freescale mx25");
423 MODULE_AUTHOR("Markus Pargmann <mpa@pengutronix.de>");
424 MODULE_LICENSE("GPL v2");