1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2023 ASEM Srl
6 * Originally based on NXP linux-imx kernel v5.15 drivers/iio/adc/imx93_adc.c
12 #include <linux/bitfield.h>
13 #include <linux/iopoll.h>
17 #define IMX93_ADC_MCR 0x00
18 #define IMX93_ADC_MSR 0x04
19 #define IMX93_ADC_ISR 0x10
20 #define IMX93_ADC_IMR 0x20
21 #define IMX93_ADC_CIMR0 0x24
22 #define IMX93_ADC_CTR0 0x94
23 #define IMX93_ADC_NCMR0 0xA4
24 #define IMX93_ADC_PCDR0 0x100
25 #define IMX93_ADC_PCDR1 0x104
26 #define IMX93_ADC_PCDR2 0x108
27 #define IMX93_ADC_PCDR3 0x10c
28 #define IMX93_ADC_PCDR4 0x110
29 #define IMX93_ADC_PCDR5 0x114
30 #define IMX93_ADC_PCDR6 0x118
31 #define IMX93_ADC_PCDR7 0x11c
32 #define IMX93_ADC_CALSTAT 0x39C
34 #define IMX93_ADC_MCR_MODE_MASK BIT(29)
35 #define IMX93_ADC_MCR_NSTART_MASK BIT(24)
36 #define IMX93_ADC_MCR_CALSTART_MASK BIT(14)
37 #define IMX93_ADC_MCR_ADCLKSE_MASK BIT(8)
38 #define IMX93_ADC_MCR_PWDN_MASK BIT(0)
40 #define IMX93_ADC_MSR_CALFAIL_MASK BIT(30)
41 #define IMX93_ADC_MSR_CALBUSY_MASK BIT(29)
42 #define IMX93_ADC_MSR_ADCSTATUS_MASK GENMASK(2, 0)
44 #define IMX93_ADC_ISR_EOC_MASK BIT(1)
46 #define IMX93_ADC_IMR_EOC_MASK BIT(1)
47 #define IMX93_ADC_IMR_ECH_MASK BIT(0)
49 #define IMX93_ADC_PCDR_CDATA_MASK GENMASK(11, 0)
54 #define BUSY_IN_CALIBRATION 3
58 #define IMX93_ADC_MAX_CHANNEL 3
59 #define IMX93_ADC_DAT_MASK 0xfff
60 #define IMX93_ADC_TIMEOUT 100000
62 struct imx93_adc_priv {
68 static void imx93_adc_power_down(struct imx93_adc_priv *adc)
73 mcr = readl(adc->regs + IMX93_ADC_MCR);
74 mcr |= FIELD_PREP(IMX93_ADC_MCR_PWDN_MASK, 1);
75 writel(mcr, adc->regs + IMX93_ADC_MCR);
77 ret = readl_poll_timeout(adc->regs + IMX93_ADC_MSR, msr,
78 ((msr & IMX93_ADC_MSR_ADCSTATUS_MASK) == POWER_DOWN), 50);
79 if (ret == -ETIMEDOUT)
80 pr_warn("ADC not in power down mode, current MSR: %x\n", msr);
83 static void imx93_adc_power_up(struct imx93_adc_priv *adc)
87 /* bring ADC out of power down state, in idle state */
88 mcr = readl(adc->regs + IMX93_ADC_MCR);
89 mcr &= ~FIELD_PREP(IMX93_ADC_MCR_PWDN_MASK, 1);
90 writel(mcr, adc->regs + IMX93_ADC_MCR);
93 static void imx93_adc_config_ad_clk(struct imx93_adc_priv *adc)
97 /* put adc in power down mode */
98 imx93_adc_power_down(adc);
100 /* config the AD_CLK equal to bus clock */
101 mcr = readl(adc->regs + IMX93_ADC_MCR);
102 mcr |= FIELD_PREP(IMX93_ADC_MCR_ADCLKSE_MASK, 1);
103 writel(mcr, adc->regs + IMX93_ADC_MCR);
105 /* bring ADC out of power down state, in idle state */
106 imx93_adc_power_up(adc);
109 static int imx93_adc_calibration(struct imx93_adc_priv *adc)
114 /* make sure ADC is in power down mode */
115 imx93_adc_power_down(adc);
117 /* config SAR controller operating clock */
118 mcr = readl(adc->regs + IMX93_ADC_MCR);
119 mcr &= ~FIELD_PREP(IMX93_ADC_MCR_ADCLKSE_MASK, 1);
120 writel(mcr, adc->regs + IMX93_ADC_MCR);
122 /* bring ADC out of power down state */
123 imx93_adc_power_up(adc);
126 * we use the default TSAMP/NRSMPL/AVGEN in MCR,
127 * can add the setting of these bit if need
130 /* run calibration */
131 mcr = readl(adc->regs + IMX93_ADC_MCR);
132 mcr |= FIELD_PREP(IMX93_ADC_MCR_CALSTART_MASK, 1);
133 writel(mcr, adc->regs + IMX93_ADC_MCR);
135 /* wait calibration to be finished */
136 ret = readl_poll_timeout(adc->regs + IMX93_ADC_MSR, msr,
137 !(msr & IMX93_ADC_MSR_CALBUSY_MASK), 2000000);
138 if (ret == -ETIMEDOUT) {
139 pr_warn("ADC calibration timeout\n");
143 /* check whether calbration is successful or not */
144 msr = readl(adc->regs + IMX93_ADC_MSR);
145 if (msr & IMX93_ADC_MSR_CALFAIL_MASK) {
146 pr_warn("ADC calibration failed!\n");
153 static int imx93_adc_channel_data(struct udevice *dev, int channel,
156 struct imx93_adc_priv *adc = dev_get_priv(dev);
160 if (channel != adc->active_channel) {
161 pr_err("Requested channel is not active!\n");
165 ret = readl_poll_timeout(adc->regs + IMX93_ADC_ISR, isr,
166 (isr & IMX93_ADC_ISR_EOC_MASK), IMX93_ADC_TIMEOUT);
168 /* clear interrupts */
169 writel(isr, adc->regs + IMX93_ADC_ISR);
171 if (ret == -ETIMEDOUT) {
172 pr_warn("ADC conversion timeout!\n");
176 pcda = readl(adc->regs + IMX93_ADC_PCDR0 + channel * 4);
178 *data = FIELD_GET(IMX93_ADC_PCDR_CDATA_MASK, pcda);
183 static int imx93_adc_start_channel(struct udevice *dev, int channel)
185 struct imx93_adc_priv *adc = dev_get_priv(dev);
188 /* config channel mask register */
189 writel(1 << channel, adc->regs + IMX93_ADC_NCMR0);
191 /* config interrupt mask */
192 imr = FIELD_PREP(IMX93_ADC_IMR_EOC_MASK, 1);
193 writel(imr, adc->regs + IMX93_ADC_IMR);
194 writel(1 << channel, adc->regs + IMX93_ADC_CIMR0);
196 /* config one-shot mode */
197 mcr = readl(adc->regs + IMX93_ADC_MCR);
198 mcr &= ~FIELD_PREP(IMX93_ADC_MCR_MODE_MASK, 1);
199 writel(mcr, adc->regs + IMX93_ADC_MCR);
201 /* start normal conversion */
202 mcr = readl(adc->regs + IMX93_ADC_MCR);
203 mcr |= FIELD_PREP(IMX93_ADC_MCR_NSTART_MASK, 1);
204 writel(mcr, adc->regs + IMX93_ADC_MCR);
206 adc->active_channel = channel;
211 static int imx93_adc_stop(struct udevice *dev)
213 struct imx93_adc_priv *adc = dev_get_priv(dev);
215 imx93_adc_power_down(adc);
217 adc->active_channel = -1;
222 static int imx93_adc_probe(struct udevice *dev)
224 struct imx93_adc_priv *adc = dev_get_priv(dev);
227 ret = imx93_adc_calibration(adc);
231 imx93_adc_config_ad_clk(adc);
233 adc->active_channel = -1;
238 static int imx93_adc_of_to_plat(struct udevice *dev)
240 struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev);
241 struct imx93_adc_priv *adc = dev_get_priv(dev);
244 adc->regs = dev_read_addr_ptr(dev);
245 if (adc->regs == (struct imx93_adc *)FDT_ADDR_T_NONE) {
246 pr_err("Dev: %s - can't get address!", dev->name);
250 ret = clk_get_by_name(dev, "ipg", &adc->ipg_clk);
252 pr_err("Can't get ADC ipg clk: %d\n", ret);
255 ret = clk_enable(&adc->ipg_clk);
257 pr_err("Can't enable ADC ipg clk: %d\n", ret);
261 uc_pdata->data_mask = IMX93_ADC_DAT_MASK;
262 uc_pdata->data_format = ADC_DATA_FORMAT_BIN;
263 uc_pdata->data_timeout_us = IMX93_ADC_TIMEOUT;
265 /* Mask available channel bits: [0:3] */
266 uc_pdata->channel_mask = (2 << IMX93_ADC_MAX_CHANNEL) - 1;
271 static const struct adc_ops imx93_adc_ops = {
272 .start_channel = imx93_adc_start_channel,
273 .channel_data = imx93_adc_channel_data,
274 .stop = imx93_adc_stop,
277 static const struct udevice_id imx93_adc_ids[] = {
278 { .compatible = "nxp,imx93-adc" },
282 U_BOOT_DRIVER(imx93_adc) = {
285 .of_match = imx93_adc_ids,
286 .ops = &imx93_adc_ops,
287 .probe = imx93_adc_probe,
288 .of_to_plat = imx93_adc_of_to_plat,
289 .priv_auto = sizeof(struct imx93_adc_priv),