File Index
Files and directories
Sign in
FILE

imx8qxp-adc.c

File preview with syntax highlighting.

linux-6.19.14/drivers/iio/adc/imx8qxp-adc.c C
  1// SPDX-License-Identifier: GPL-2.0+
  2/*
  3 * NXP i.MX8QXP ADC driver
  4 *
  5 * Based on the work of Haibo Chen <haibo.chen@nxp.com>
  6 * The initial developer of the original code is Haibo Chen.
  7 * Portions created by Haibo Chen are Copyright (C) 2018 NXP.
  8 * All Rights Reserved.
  9 *
 10 * Copyright (C) 2018 NXP
 11 * Copyright (C) 2021 Cai Huoqing
 12 */
 13#include <linux/bitfield.h>
 14#include <linux/bits.h>
 15#include <linux/clk.h>
 16#include <linux/completion.h>
 17#include <linux/delay.h>
 18#include <linux/err.h>
 19#include <linux/interrupt.h>
 20#include <linux/io.h>
 21#include <linux/kernel.h>
 22#include <linux/mod_devicetable.h>
 23#include <linux/module.h>
 24#include <linux/platform_device.h>
 25#include <linux/pm_runtime.h>
 26#include <linux/regulator/consumer.h>
 27
 28#include <linux/iio/iio.h>
 29
 30#define ADC_DRIVER_NAME		"imx8qxp-adc"
 31
 32/* Register map definition */
 33#define IMX8QXP_ADR_ADC_CTRL		0x10
 34#define IMX8QXP_ADR_ADC_STAT		0x14
 35#define IMX8QXP_ADR_ADC_IE		0x18
 36#define IMX8QXP_ADR_ADC_DE		0x1c
 37#define IMX8QXP_ADR_ADC_CFG		0x20
 38#define IMX8QXP_ADR_ADC_FCTRL		0x30
 39#define IMX8QXP_ADR_ADC_SWTRIG		0x34
 40#define IMX8QXP_ADR_ADC_TCTRL(tid)	(0xc0 + (tid) * 4)
 41#define IMX8QXP_ADR_ADC_CMDL(cid)	(0x100 + (cid) * 8)
 42#define IMX8QXP_ADR_ADC_CMDH(cid)	(0x104 + (cid) * 8)
 43#define IMX8QXP_ADR_ADC_RESFIFO		0x300
 44#define IMX8QXP_ADR_ADC_TST		0xffc
 45
 46/* ADC bit shift */
 47#define IMX8QXP_ADC_IE_FWMIE_MASK		GENMASK(1, 0)
 48#define IMX8QXP_ADC_CTRL_FIFO_RESET_MASK	BIT(8)
 49#define IMX8QXP_ADC_CTRL_SOFTWARE_RESET_MASK	BIT(1)
 50#define IMX8QXP_ADC_CTRL_ADC_EN_MASK		BIT(0)
 51#define IMX8QXP_ADC_TCTRL_TCMD_MASK		GENMASK(31, 24)
 52#define IMX8QXP_ADC_TCTRL_TDLY_MASK		GENMASK(23, 16)
 53#define IMX8QXP_ADC_TCTRL_TPRI_MASK		GENMASK(15, 8)
 54#define IMX8QXP_ADC_TCTRL_HTEN_MASK		GENMASK(7, 0)
 55#define IMX8QXP_ADC_CMDL_CSCALE_MASK		GENMASK(13, 8)
 56#define IMX8QXP_ADC_CMDL_MODE_MASK		BIT(7)
 57#define IMX8QXP_ADC_CMDL_DIFF_MASK		BIT(6)
 58#define IMX8QXP_ADC_CMDL_ABSEL_MASK		BIT(5)
 59#define IMX8QXP_ADC_CMDL_ADCH_MASK		GENMASK(2, 0)
 60#define IMX8QXP_ADC_CMDH_NEXT_MASK		GENMASK(31, 24)
 61#define IMX8QXP_ADC_CMDH_LOOP_MASK		GENMASK(23, 16)
 62#define IMX8QXP_ADC_CMDH_AVGS_MASK		GENMASK(15, 12)
 63#define IMX8QXP_ADC_CMDH_STS_MASK		BIT(8)
 64#define IMX8QXP_ADC_CMDH_LWI_MASK		GENMASK(7, 7)
 65#define IMX8QXP_ADC_CMDH_CMPEN_MASK		GENMASK(0, 0)
 66#define IMX8QXP_ADC_CFG_PWREN_MASK		BIT(28)
 67#define IMX8QXP_ADC_CFG_PUDLY_MASK		GENMASK(23, 16)
 68#define IMX8QXP_ADC_CFG_REFSEL_MASK		GENMASK(7, 6)
 69#define IMX8QXP_ADC_CFG_PWRSEL_MASK		GENMASK(5, 4)
 70#define IMX8QXP_ADC_CFG_TPRICTRL_MASK		GENMASK(3, 0)
 71#define IMX8QXP_ADC_FCTRL_FWMARK_MASK		GENMASK(20, 16)
 72#define IMX8QXP_ADC_FCTRL_FCOUNT_MASK		GENMASK(4, 0)
 73#define IMX8QXP_ADC_RESFIFO_VAL_MASK		GENMASK(18, 3)
 74
 75/* ADC PARAMETER*/
 76#define IMX8QXP_ADC_CMDL_CHANNEL_SCALE_FULL		GENMASK(5, 0)
 77#define IMX8QXP_ADC_CMDL_SEL_A_A_B_CHANNEL		0
 78#define IMX8QXP_ADC_CMDL_STANDARD_RESOLUTION		0
 79#define IMX8QXP_ADC_CMDL_MODE_SINGLE			0
 80#define IMX8QXP_ADC_CMDH_LWI_INCREMENT_DIS		0
 81#define IMX8QXP_ADC_CMDH_CMPEN_DIS			0
 82#define IMX8QXP_ADC_PAUSE_EN				BIT(31)
 83#define IMX8QXP_ADC_TCTRL_TPRI_PRIORITY_HIGH		0
 84
 85#define IMX8QXP_ADC_TCTRL_HTEN_HW_TIRG_DIS		0
 86
 87#define IMX8QXP_ADC_TIMEOUT		msecs_to_jiffies(100)
 88
 89#define IMX8QXP_ADC_MAX_FIFO_SIZE		16
 90
 91struct imx8qxp_adc {
 92	struct device *dev;
 93	void __iomem *regs;
 94	struct clk *clk;
 95	struct clk *ipg_clk;
 96	struct regulator *vref;
 97	/* Serialise ADC channel reads */
 98	struct mutex lock;
 99	struct completion completion;
100	u32 fifo[IMX8QXP_ADC_MAX_FIFO_SIZE];
101};
102
103#define IMX8QXP_ADC_CHAN(_idx) {				\
104	.type = IIO_VOLTAGE,					\
105	.indexed = 1,						\
106	.channel = (_idx),					\
107	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
108	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |	\
109				BIT(IIO_CHAN_INFO_SAMP_FREQ),	\
110}
111
112static const struct iio_chan_spec imx8qxp_adc_iio_channels[] = {
113	IMX8QXP_ADC_CHAN(0),
114	IMX8QXP_ADC_CHAN(1),
115	IMX8QXP_ADC_CHAN(2),
116	IMX8QXP_ADC_CHAN(3),
117	IMX8QXP_ADC_CHAN(4),
118	IMX8QXP_ADC_CHAN(5),
119	IMX8QXP_ADC_CHAN(6),
120	IMX8QXP_ADC_CHAN(7),
121};
122
123static void imx8qxp_adc_reset(struct imx8qxp_adc *adc)
124{
125	u32 ctrl;
126
127	/*software reset, need to clear the set bit*/
128	ctrl = readl(adc->regs + IMX8QXP_ADR_ADC_CTRL);
129	ctrl |= FIELD_PREP(IMX8QXP_ADC_CTRL_SOFTWARE_RESET_MASK, 1);
130	writel(ctrl, adc->regs + IMX8QXP_ADR_ADC_CTRL);
131	udelay(10);
132	ctrl &= ~FIELD_PREP(IMX8QXP_ADC_CTRL_SOFTWARE_RESET_MASK, 1);
133	writel(ctrl, adc->regs + IMX8QXP_ADR_ADC_CTRL);
134
135	/* reset the fifo */
136	ctrl |= FIELD_PREP(IMX8QXP_ADC_CTRL_FIFO_RESET_MASK, 1);
137	writel(ctrl, adc->regs + IMX8QXP_ADR_ADC_CTRL);
138}
139
140static void imx8qxp_adc_reg_config(struct imx8qxp_adc *adc, int channel)
141{
142	u32 adc_cfg, adc_tctrl, adc_cmdl, adc_cmdh;
143
144	/* ADC configuration */
145	adc_cfg = FIELD_PREP(IMX8QXP_ADC_CFG_PWREN_MASK, 1) |
146		  FIELD_PREP(IMX8QXP_ADC_CFG_PUDLY_MASK, 0x80)|
147		  FIELD_PREP(IMX8QXP_ADC_CFG_REFSEL_MASK, 0) |
148		  FIELD_PREP(IMX8QXP_ADC_CFG_PWRSEL_MASK, 3) |
149		  FIELD_PREP(IMX8QXP_ADC_CFG_TPRICTRL_MASK, 0);
150	writel(adc_cfg, adc->regs + IMX8QXP_ADR_ADC_CFG);
151
152	/* config the trigger control */
153	adc_tctrl = FIELD_PREP(IMX8QXP_ADC_TCTRL_TCMD_MASK, 1) |
154		    FIELD_PREP(IMX8QXP_ADC_TCTRL_TDLY_MASK, 0) |
155		    FIELD_PREP(IMX8QXP_ADC_TCTRL_TPRI_MASK, IMX8QXP_ADC_TCTRL_TPRI_PRIORITY_HIGH) |
156		    FIELD_PREP(IMX8QXP_ADC_TCTRL_HTEN_MASK, IMX8QXP_ADC_TCTRL_HTEN_HW_TIRG_DIS);
157	writel(adc_tctrl, adc->regs + IMX8QXP_ADR_ADC_TCTRL(0));
158
159	/* config the cmd */
160	adc_cmdl = FIELD_PREP(IMX8QXP_ADC_CMDL_CSCALE_MASK, IMX8QXP_ADC_CMDL_CHANNEL_SCALE_FULL) |
161		   FIELD_PREP(IMX8QXP_ADC_CMDL_MODE_MASK, IMX8QXP_ADC_CMDL_STANDARD_RESOLUTION) |
162		   FIELD_PREP(IMX8QXP_ADC_CMDL_DIFF_MASK, IMX8QXP_ADC_CMDL_MODE_SINGLE) |
163		   FIELD_PREP(IMX8QXP_ADC_CMDL_ABSEL_MASK, IMX8QXP_ADC_CMDL_SEL_A_A_B_CHANNEL) |
164		   FIELD_PREP(IMX8QXP_ADC_CMDL_ADCH_MASK, channel);
165	writel(adc_cmdl, adc->regs + IMX8QXP_ADR_ADC_CMDL(0));
166
167	adc_cmdh = FIELD_PREP(IMX8QXP_ADC_CMDH_NEXT_MASK, 0) |
168		   FIELD_PREP(IMX8QXP_ADC_CMDH_LOOP_MASK, 0) |
169		   FIELD_PREP(IMX8QXP_ADC_CMDH_AVGS_MASK, 7) |
170		   FIELD_PREP(IMX8QXP_ADC_CMDH_STS_MASK, 0) |
171		   FIELD_PREP(IMX8QXP_ADC_CMDH_LWI_MASK, IMX8QXP_ADC_CMDH_LWI_INCREMENT_DIS) |
172		   FIELD_PREP(IMX8QXP_ADC_CMDH_CMPEN_MASK, IMX8QXP_ADC_CMDH_CMPEN_DIS);
173	writel(adc_cmdh, adc->regs + IMX8QXP_ADR_ADC_CMDH(0));
174}
175
176static void imx8qxp_adc_fifo_config(struct imx8qxp_adc *adc)
177{
178	u32 fifo_ctrl, interrupt_en;
179
180	fifo_ctrl = readl(adc->regs + IMX8QXP_ADR_ADC_FCTRL);
181	fifo_ctrl &= ~IMX8QXP_ADC_FCTRL_FWMARK_MASK;
182	/* set the watermark level to 1 */
183	fifo_ctrl |= FIELD_PREP(IMX8QXP_ADC_FCTRL_FWMARK_MASK, 0);
184	writel(fifo_ctrl, adc->regs + IMX8QXP_ADR_ADC_FCTRL);
185
186	/* FIFO Watermark Interrupt Enable */
187	interrupt_en = readl(adc->regs + IMX8QXP_ADR_ADC_IE);
188	interrupt_en |= FIELD_PREP(IMX8QXP_ADC_IE_FWMIE_MASK, 1);
189	writel(interrupt_en, adc->regs + IMX8QXP_ADR_ADC_IE);
190}
191
192static void imx8qxp_adc_disable(struct imx8qxp_adc *adc)
193{
194	u32 ctrl;
195
196	ctrl = readl(adc->regs + IMX8QXP_ADR_ADC_CTRL);
197	ctrl &= ~FIELD_PREP(IMX8QXP_ADC_CTRL_ADC_EN_MASK, 1);
198	writel(ctrl, adc->regs + IMX8QXP_ADR_ADC_CTRL);
199}
200
201static int imx8qxp_adc_read_raw(struct iio_dev *indio_dev,
202				struct iio_chan_spec const *chan,
203				int *val, int *val2, long mask)
204{
205	struct imx8qxp_adc *adc = iio_priv(indio_dev);
206	struct device *dev = adc->dev;
207
208	u32 ctrl;
209	long ret;
210
211	switch (mask) {
212	case IIO_CHAN_INFO_RAW:
213		pm_runtime_get_sync(dev);
214
215		mutex_lock(&adc->lock);
216		reinit_completion(&adc->completion);
217
218		imx8qxp_adc_reg_config(adc, chan->channel);
219
220		imx8qxp_adc_fifo_config(adc);
221
222		/* adc enable */
223		ctrl = readl(adc->regs + IMX8QXP_ADR_ADC_CTRL);
224		ctrl |= FIELD_PREP(IMX8QXP_ADC_CTRL_ADC_EN_MASK, 1);
225		writel(ctrl, adc->regs + IMX8QXP_ADR_ADC_CTRL);
226		/* adc start */
227		writel(1, adc->regs + IMX8QXP_ADR_ADC_SWTRIG);
228
229		ret = wait_for_completion_interruptible_timeout(&adc->completion,
230								IMX8QXP_ADC_TIMEOUT);
231
232		pm_runtime_put_sync_autosuspend(dev);
233
234		if (ret == 0) {
235			mutex_unlock(&adc->lock);
236			return -ETIMEDOUT;
237		}
238		if (ret < 0) {
239			mutex_unlock(&adc->lock);
240			return ret;
241		}
242
243		*val = adc->fifo[0];
244
245		mutex_unlock(&adc->lock);
246		return IIO_VAL_INT;
247
248	case IIO_CHAN_INFO_SCALE:
249		ret = regulator_get_voltage(adc->vref);
250		if (ret < 0)
251			return ret;
252		*val = ret / 1000;
253		*val2 = 12;
254		return IIO_VAL_FRACTIONAL_LOG2;
255
256	case IIO_CHAN_INFO_SAMP_FREQ:
257		*val = clk_get_rate(adc->clk) / 3;
258		return IIO_VAL_INT;
259
260	default:
261		return -EINVAL;
262	}
263}
264
265static irqreturn_t imx8qxp_adc_isr(int irq, void *dev_id)
266{
267	struct imx8qxp_adc *adc = dev_id;
268	u32 fifo_count;
269	int i;
270
271	fifo_count = FIELD_GET(IMX8QXP_ADC_FCTRL_FCOUNT_MASK,
272			       readl(adc->regs + IMX8QXP_ADR_ADC_FCTRL));
273
274	for (i = 0; i < fifo_count; i++)
275		adc->fifo[i] = FIELD_GET(IMX8QXP_ADC_RESFIFO_VAL_MASK,
276				readl_relaxed(adc->regs + IMX8QXP_ADR_ADC_RESFIFO));
277
278	if (fifo_count)
279		complete(&adc->completion);
280
281	return IRQ_HANDLED;
282}
283
284static int imx8qxp_adc_reg_access(struct iio_dev *indio_dev, unsigned int reg,
285				  unsigned int writeval, unsigned int *readval)
286{
287	struct imx8qxp_adc *adc = iio_priv(indio_dev);
288	struct device *dev = adc->dev;
289
290	if (!readval || reg % 4 || reg > IMX8QXP_ADR_ADC_TST)
291		return -EINVAL;
292
293	pm_runtime_get_sync(dev);
294
295	*readval = readl(adc->regs + reg);
296
297	pm_runtime_put_sync_autosuspend(dev);
298
299	return 0;
300}
301
302static const struct iio_info imx8qxp_adc_iio_info = {
303	.read_raw = &imx8qxp_adc_read_raw,
304	.debugfs_reg_access = &imx8qxp_adc_reg_access,
305};
306
307static int imx8qxp_adc_probe(struct platform_device *pdev)
308{
309	struct imx8qxp_adc *adc;
310	struct iio_dev *indio_dev;
311	struct device *dev = &pdev->dev;
312	int irq;
313	int ret;
314
315	indio_dev = devm_iio_device_alloc(dev, sizeof(*adc));
316	if (!indio_dev)
317		return -ENOMEM;
318
319	adc = iio_priv(indio_dev);
320	adc->dev = dev;
321
322	mutex_init(&adc->lock);
323	adc->regs = devm_platform_ioremap_resource(pdev, 0);
324	if (IS_ERR(adc->regs))
325		return PTR_ERR(adc->regs);
326
327	irq = platform_get_irq(pdev, 0);
328	if (irq < 0)
329		return irq;
330
331	adc->clk = devm_clk_get(dev, "per");
332	if (IS_ERR(adc->clk))
333		return dev_err_probe(dev, PTR_ERR(adc->clk), "Failed getting clock\n");
334
335	adc->ipg_clk = devm_clk_get(dev, "ipg");
336	if (IS_ERR(adc->ipg_clk))
337		return dev_err_probe(dev, PTR_ERR(adc->ipg_clk), "Failed getting clock\n");
338
339	adc->vref = devm_regulator_get(dev, "vref");
340	if (IS_ERR(adc->vref))
341		return dev_err_probe(dev, PTR_ERR(adc->vref), "Failed getting reference voltage\n");
342
343	ret = regulator_enable(adc->vref);
344	if (ret) {
345		dev_err(dev, "Can't enable adc reference top voltage\n");
346		return ret;
347	}
348
349	platform_set_drvdata(pdev, indio_dev);
350
351	init_completion(&adc->completion);
352
353	indio_dev->name = ADC_DRIVER_NAME;
354	indio_dev->info = &imx8qxp_adc_iio_info;
355	indio_dev->modes = INDIO_DIRECT_MODE;
356	indio_dev->channels = imx8qxp_adc_iio_channels;
357	indio_dev->num_channels = ARRAY_SIZE(imx8qxp_adc_iio_channels);
358
359	ret = clk_prepare_enable(adc->clk);
360	if (ret) {
361		dev_err(&pdev->dev, "Could not prepare or enable the clock.\n");
362		goto error_regulator_disable;
363	}
364
365	ret = clk_prepare_enable(adc->ipg_clk);
366	if (ret) {
367		dev_err(&pdev->dev, "Could not prepare or enable the clock.\n");
368		goto error_adc_clk_disable;
369	}
370
371	ret = devm_request_irq(dev, irq, imx8qxp_adc_isr, 0, ADC_DRIVER_NAME, adc);
372	if (ret < 0) {
373		dev_err(dev, "Failed requesting irq, irq = %d\n", irq);
374		goto error_ipg_clk_disable;
375	}
376
377	imx8qxp_adc_reset(adc);
378
379	ret = iio_device_register(indio_dev);
380	if (ret) {
381		imx8qxp_adc_disable(adc);
382		dev_err(dev, "Couldn't register the device.\n");
383		goto error_ipg_clk_disable;
384	}
385
386	pm_runtime_set_active(dev);
387	pm_runtime_set_autosuspend_delay(dev, 50);
388	pm_runtime_use_autosuspend(dev);
389	pm_runtime_enable(dev);
390
391	return 0;
392
393error_ipg_clk_disable:
394	clk_disable_unprepare(adc->ipg_clk);
395error_adc_clk_disable:
396	clk_disable_unprepare(adc->clk);
397error_regulator_disable:
398	regulator_disable(adc->vref);
399
400	return ret;
401}
402
403static void imx8qxp_adc_remove(struct platform_device *pdev)
404{
405	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
406	struct imx8qxp_adc *adc = iio_priv(indio_dev);
407	struct device *dev = adc->dev;
408
409	pm_runtime_get_sync(dev);
410
411	iio_device_unregister(indio_dev);
412
413	imx8qxp_adc_disable(adc);
414
415	clk_disable_unprepare(adc->clk);
416	clk_disable_unprepare(adc->ipg_clk);
417	regulator_disable(adc->vref);
418
419	pm_runtime_disable(dev);
420	pm_runtime_put_noidle(dev);
421}
422
423static int imx8qxp_adc_runtime_suspend(struct device *dev)
424{
425	struct iio_dev *indio_dev = dev_get_drvdata(dev);
426	struct imx8qxp_adc *adc = iio_priv(indio_dev);
427
428	imx8qxp_adc_disable(adc);
429
430	clk_disable_unprepare(adc->clk);
431	clk_disable_unprepare(adc->ipg_clk);
432	regulator_disable(adc->vref);
433
434	return 0;
435}
436
437static int imx8qxp_adc_runtime_resume(struct device *dev)
438{
439	struct iio_dev *indio_dev = dev_get_drvdata(dev);
440	struct imx8qxp_adc *adc = iio_priv(indio_dev);
441	int ret;
442
443	ret = regulator_enable(adc->vref);
444	if (ret) {
445		dev_err(dev, "Can't enable adc reference top voltage, err = %d\n", ret);
446		return ret;
447	}
448
449	ret = clk_prepare_enable(adc->clk);
450	if (ret) {
451		dev_err(dev, "Could not prepare or enable clock.\n");
452		goto err_disable_reg;
453	}
454
455	ret = clk_prepare_enable(adc->ipg_clk);
456	if (ret) {
457		dev_err(dev, "Could not prepare or enable clock.\n");
458		goto err_unprepare_clk;
459	}
460
461	imx8qxp_adc_reset(adc);
462
463	return 0;
464
465err_unprepare_clk:
466	clk_disable_unprepare(adc->clk);
467
468err_disable_reg:
469	regulator_disable(adc->vref);
470
471	return ret;
472}
473
474static DEFINE_RUNTIME_DEV_PM_OPS(imx8qxp_adc_pm_ops,
475				 imx8qxp_adc_runtime_suspend,
476				 imx8qxp_adc_runtime_resume, NULL);
477
478static const struct of_device_id imx8qxp_adc_match[] = {
479	{ .compatible = "nxp,imx8qxp-adc", },
480	{ }
481};
482MODULE_DEVICE_TABLE(of, imx8qxp_adc_match);
483
484static struct platform_driver imx8qxp_adc_driver = {
485	.probe		= imx8qxp_adc_probe,
486	.remove		= imx8qxp_adc_remove,
487	.driver		= {
488		.name	= ADC_DRIVER_NAME,
489		.of_match_table = imx8qxp_adc_match,
490		.pm	= pm_ptr(&imx8qxp_adc_pm_ops),
491	},
492};
493
494module_platform_driver(imx8qxp_adc_driver);
495
496MODULE_DESCRIPTION("i.MX8QuadXPlus ADC driver");
497MODULE_LICENSE("GPL v2");
~/ Read-only file preview.