summaryrefslogtreecommitdiff
path: root/drivers/iio/adc/rzn1-adc.c
blob: 93b0feef8ea0b762853dff7168ef13e387f0680e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
// SPDX-License-Identifier: GPL-2.0
/*
 * Renesas RZ/N1 ADC driver
 *
 * Copyright (C) 2025 Schneider-Electric
 *
 * Author: Herve Codina <herve.codina@bootlin.com>
 *
 * The RZ/N1 ADC controller can handle channels from its internal ADC1 and/or
 * ADC2 cores. The driver use ADC1 and/or ADC2 cores depending on the presence
 * of the related power supplies (AVDD and VREF) description in the device-tree.
 */

#include <linux/array_size.h>
#include <linux/bitfield.h>
#include <linux/bits.h>
#include <linux/cleanup.h>
#include <linux/clk.h>
#include <linux/dev_printk.h>
#include <linux/err.h>
#include <linux/iio/iio.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
#include <linux/types.h>

#define RZN1_ADC_CONTROL_REG			0x02c
#define RZN1_ADC_CONTROL_ADC_BUSY		BIT(6)

#define RZN1_ADC_FORCE_REG			0x030
#define RZN1_ADC_SET_FORCE_REG			0x034
#define RZN1_ADC_CLEAR_FORCE_REG		0x038
#define RZN1_ADC_FORCE_VC(_n)			BIT(_n)

#define RZN1_ADC_CONFIG_REG			0x040
#define RZN1_ADC_CONFIG_ADC_POWER_DOWN		BIT(3)

#define RZN1_ADC_VC_REG(_n)			(0x0c0 + 4 * (_n))
#define RZN1_ADC_VC_ADC2_ENABLE			BIT(16)
#define RZN1_ADC_VC_ADC1_ENABLE			BIT(15)
#define RZN1_ADC_VC_ADC2_CHANNEL_SEL_MASK	GENMASK(5, 3)
#define RZN1_ADC_VC_ADC1_CHANNEL_SEL_MASK	GENMASK(2, 0)

#define RZN1_ADC_ADC1_DATA_REG(_n)		(0x100 + 4 * (_n))
#define RZN1_ADC_ADC2_DATA_REG(_n)		(0x140 + 4 * (_n))
#define RZN1_ADC_ADCX_DATA_DATA_MASK		GENMASK(11, 0)

#define RZN1_ADC_NO_CHANNEL	-1

#define RZN1_ADC_CHANNEL_SHARED_SCALE(_ch, _ds_name) {		\
	.type = IIO_VOLTAGE,					\
	.indexed = 1,						\
	.channel = (_ch),					\
	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),   \
	.datasheet_name = (_ds_name),				\
}

#define RZN1_ADC_CHANNEL_SEPARATED_SCALE(_ch, _ds_name) {	\
	.type = IIO_VOLTAGE,					\
	.indexed = 1,						\
	.channel = (_ch),					\
	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |		\
			      BIT(IIO_CHAN_INFO_SCALE),		\
	.datasheet_name = (_ds_name),				\
}

/*
 * 8 ADC1_IN signals existed numbered 0..4, 6..8
 * ADCx_IN5 doesn't exist in RZ/N1 datasheet
 */
static struct iio_chan_spec rzn1_adc1_channels[] = {
	RZN1_ADC_CHANNEL_SHARED_SCALE(0, "ADC1_IN0"),
	RZN1_ADC_CHANNEL_SHARED_SCALE(1, "ADC1_IN1"),
	RZN1_ADC_CHANNEL_SHARED_SCALE(2, "ADC1_IN2"),
	RZN1_ADC_CHANNEL_SHARED_SCALE(3, "ADC1_IN3"),
	RZN1_ADC_CHANNEL_SHARED_SCALE(4, "ADC1_IN4"),
	RZN1_ADC_CHANNEL_SHARED_SCALE(5, "ADC1_IN6"),
	RZN1_ADC_CHANNEL_SHARED_SCALE(6, "ADC1_IN7"),
	RZN1_ADC_CHANNEL_SHARED_SCALE(7, "ADC1_IN8"),
};

static struct iio_chan_spec rzn1_adc2_channels[] = {
	RZN1_ADC_CHANNEL_SHARED_SCALE(8,  "ADC2_IN0"),
	RZN1_ADC_CHANNEL_SHARED_SCALE(9,  "ADC2_IN1"),
	RZN1_ADC_CHANNEL_SHARED_SCALE(10, "ADC2_IN2"),
	RZN1_ADC_CHANNEL_SHARED_SCALE(11, "ADC2_IN3"),
	RZN1_ADC_CHANNEL_SHARED_SCALE(12, "ADC2_IN4"),
	RZN1_ADC_CHANNEL_SHARED_SCALE(13, "ADC2_IN6"),
	RZN1_ADC_CHANNEL_SHARED_SCALE(14, "ADC2_IN7"),
	RZN1_ADC_CHANNEL_SHARED_SCALE(15, "ADC2_IN8"),
};

/*
 * If both ADCs core are used, scale cannot be common. Indeed, scale is
 * based on Vref connected on each ADC core.
 */
static struct iio_chan_spec rzn1_adc1_adc2_channels[] = {
	RZN1_ADC_CHANNEL_SEPARATED_SCALE(0, "ADC1_IN0"),
	RZN1_ADC_CHANNEL_SEPARATED_SCALE(1, "ADC1_IN1"),
	RZN1_ADC_CHANNEL_SEPARATED_SCALE(2, "ADC1_IN2"),
	RZN1_ADC_CHANNEL_SEPARATED_SCALE(3, "ADC1_IN3"),
	RZN1_ADC_CHANNEL_SEPARATED_SCALE(4, "ADC1_IN4"),
	RZN1_ADC_CHANNEL_SEPARATED_SCALE(5, "ADC1_IN6"),
	RZN1_ADC_CHANNEL_SEPARATED_SCALE(6, "ADC1_IN7"),
	RZN1_ADC_CHANNEL_SEPARATED_SCALE(7, "ADC1_IN8"),
	RZN1_ADC_CHANNEL_SEPARATED_SCALE(8,  "ADC2_IN0"),
	RZN1_ADC_CHANNEL_SEPARATED_SCALE(9,  "ADC2_IN1"),
	RZN1_ADC_CHANNEL_SEPARATED_SCALE(10, "ADC2_IN2"),
	RZN1_ADC_CHANNEL_SEPARATED_SCALE(11, "ADC2_IN3"),
	RZN1_ADC_CHANNEL_SEPARATED_SCALE(12, "ADC2_IN4"),
	RZN1_ADC_CHANNEL_SEPARATED_SCALE(13, "ADC2_IN6"),
	RZN1_ADC_CHANNEL_SEPARATED_SCALE(14, "ADC2_IN7"),
	RZN1_ADC_CHANNEL_SEPARATED_SCALE(15, "ADC2_IN8"),
};

struct rzn1_adc {
	struct device *dev;
	void __iomem *regs;
	struct mutex lock; /* ADC lock */
	int adc1_vref_mV; /* ADC1 Vref in mV. Negative if ADC1 is not used */
	int adc2_vref_mV; /* ADC2 Vref in mV. Negative if ADC2 is not used */
};

static int rzn1_adc_power(struct rzn1_adc *rzn1_adc, bool power)
{
	u32 v;

	writel(power ? 0 : RZN1_ADC_CONFIG_ADC_POWER_DOWN,
	       rzn1_adc->regs + RZN1_ADC_CONFIG_REG);

	/* Wait for the ADC_BUSY to clear */
	return readl_poll_timeout_atomic(rzn1_adc->regs + RZN1_ADC_CONTROL_REG,
					 v, !(v & RZN1_ADC_CONTROL_ADC_BUSY),
					 0, 500);
}

static void rzn1_adc_vc_setup_conversion(struct rzn1_adc *rzn1_adc, u32 ch,
					 int adc1_ch, int adc2_ch)
{
	u32 vc = 0;

	if (adc1_ch != RZN1_ADC_NO_CHANNEL)
		vc |= RZN1_ADC_VC_ADC1_ENABLE |
		      FIELD_PREP(RZN1_ADC_VC_ADC1_CHANNEL_SEL_MASK, adc1_ch);

	if (adc2_ch != RZN1_ADC_NO_CHANNEL)
		vc |= RZN1_ADC_VC_ADC2_ENABLE |
		      FIELD_PREP(RZN1_ADC_VC_ADC2_CHANNEL_SEL_MASK, adc2_ch);

	writel(vc, rzn1_adc->regs + RZN1_ADC_VC_REG(ch));
}

static int rzn1_adc_vc_start_conversion(struct rzn1_adc *rzn1_adc, u32 ch)
{
	u32 val;

	val = readl(rzn1_adc->regs + RZN1_ADC_FORCE_REG);
	if (val & RZN1_ADC_FORCE_VC(ch))
		return -EBUSY;

	writel(RZN1_ADC_FORCE_VC(ch), rzn1_adc->regs + RZN1_ADC_SET_FORCE_REG);

	return 0;
}

static void rzn1_adc_vc_stop_conversion(struct rzn1_adc *rzn1_adc, u32 ch)
{
	writel(RZN1_ADC_FORCE_VC(ch), rzn1_adc->regs + RZN1_ADC_CLEAR_FORCE_REG);
}

static int rzn1_adc_vc_wait_conversion(struct rzn1_adc *rzn1_adc, u32 ch,
				       u32 *adc1_data, u32 *adc2_data)
{
	u32 data_reg;
	int ret;
	u32 v;

	/*
	 * When a VC is selected, it needs 20 ADC clocks to perform the
	 * conversion.
	 *
	 * The worst case is when the 16 VCs need to perform a conversion and
	 * our VC is the lowest in term of priority.
	 *
	 * In that case, the conversion is performed in 16 * 20 ADC clocks.
	 *
	 * The ADC clock can be set from 4MHz to 20MHz. This leads to a worst
	 * case of  16 * 20 * 1/4Mhz = 80us.
	 *
	 * Round it up to 100us.
	 */

	/* Wait for the ADC_FORCE_VC(n) to clear */
	ret = readl_poll_timeout_atomic(rzn1_adc->regs + RZN1_ADC_FORCE_REG,
					v, !(v & RZN1_ADC_FORCE_VC(ch)),
					0, 100);
	if (ret)
		return ret;

	if (adc1_data) {
		data_reg = readl(rzn1_adc->regs + RZN1_ADC_ADC1_DATA_REG(ch));
		*adc1_data = FIELD_GET(RZN1_ADC_ADCX_DATA_DATA_MASK, data_reg);
	}

	if (adc2_data) {
		data_reg = readl(rzn1_adc->regs + RZN1_ADC_ADC2_DATA_REG(ch));
		*adc2_data = FIELD_GET(RZN1_ADC_ADCX_DATA_DATA_MASK, data_reg);
	}

	return 0;
}

static int rzn1_adc_read_raw_ch(struct rzn1_adc *rzn1_adc, unsigned int chan, int *val)
{
	u32 *adc1_data, *adc2_data;
	int adc1_ch, adc2_ch;
	u32 adc_data;
	int ret;

	/*
	 * IIO chan are decoupled from chans used in rzn1_adc_vc_*() functions.
	 * The RZ/N1 ADC VC controller can handle on a single VC chan one
	 * channel from the ADC1 core and one channel from the ADC2 core.
	 *
	 * Even if IIO chans are mapped 1:1 to ADC core chans and so uses only
	 * a chan from ADC1 or a chan from ADC2, future improvements can define
	 * an IIO chan that uses one chan from ADC1 and one chan from ADC2.
	 */

	if (chan < 8) {
		/* chan 0..7 used to get ADC1 ch 0..7 */
		adc1_ch = chan;
		adc1_data = &adc_data;
		adc2_ch = RZN1_ADC_NO_CHANNEL;
		adc2_data = NULL;
	} else if (chan < 16) {
		/* chan 8..15 used to get ADC2 ch 0..7 */
		adc1_ch = RZN1_ADC_NO_CHANNEL;
		adc1_data = NULL;
		adc2_ch = chan - 8;
		adc2_data = &adc_data;
	} else {
		return -EINVAL;
	}

	ACQUIRE(pm_runtime_active_auto_try_enabled, pm)(rzn1_adc->dev);
	ret = ACQUIRE_ERR(pm_runtime_active_auto_try_enabled, &pm);
	if (ret < 0)
		return ret;

	scoped_guard(mutex, &rzn1_adc->lock) {
		rzn1_adc_vc_setup_conversion(rzn1_adc, chan, adc1_ch, adc2_ch);

		ret = rzn1_adc_vc_start_conversion(rzn1_adc, chan);
		if (ret)
			return ret;

		ret = rzn1_adc_vc_wait_conversion(rzn1_adc, chan, adc1_data, adc2_data);
		if (ret) {
			rzn1_adc_vc_stop_conversion(rzn1_adc, chan);
			return ret;
		}
	}

	*val = adc_data;
	ret = IIO_VAL_INT;

	return 0;
}

static int rzn1_adc_get_vref_mV(struct rzn1_adc *rzn1_adc, unsigned int chan)
{
	/* chan 0..7 use ADC1 ch 0..7. Vref related to ADC1 core */
	if (chan < 8)
		return rzn1_adc->adc1_vref_mV;

	/* chan 8..15 use ADC2 ch 0..7. Vref related to ADC2 core */
	if (chan < 16)
		return rzn1_adc->adc2_vref_mV;

	return -EINVAL;
}

static int rzn1_adc_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
			     int *val, int *val2, long mask)
{
	struct rzn1_adc *rzn1_adc = iio_priv(indio_dev);
	int ret;

	switch (mask) {
	case IIO_CHAN_INFO_RAW:
		ret = rzn1_adc_read_raw_ch(rzn1_adc, chan->channel, val);
		if (ret)
			return ret;
		return IIO_VAL_INT;

	case IIO_CHAN_INFO_SCALE:
		ret = rzn1_adc_get_vref_mV(rzn1_adc, chan->channel);
		if (ret < 0)
			return ret;
		*val = ret;
		*val2 = 12;
		return IIO_VAL_FRACTIONAL_LOG2;

	default:
		return -EINVAL;
	}
}

static const struct iio_info rzn1_adc_info = {
	.read_raw = &rzn1_adc_read_raw,
};

static int rzn1_adc_set_iio_dev_channels(struct rzn1_adc *rzn1_adc,
					 struct iio_dev *indio_dev)
{
	/*
	 * When an ADC core is not used, its related vref_mV is set to a
	 * negative error code. Use the correct IIO channels table based on
	 * those vref_mV values.
	 */
	if (rzn1_adc->adc1_vref_mV >= 0) {
		if (rzn1_adc->adc2_vref_mV >= 0) {
			indio_dev->channels = rzn1_adc1_adc2_channels;
			indio_dev->num_channels = ARRAY_SIZE(rzn1_adc1_adc2_channels);
		} else {
			indio_dev->channels = rzn1_adc1_channels;
			indio_dev->num_channels = ARRAY_SIZE(rzn1_adc1_channels);
		}
		return 0;
	}

	if (rzn1_adc->adc2_vref_mV >= 0) {
		indio_dev->channels = rzn1_adc2_channels;
		indio_dev->num_channels = ARRAY_SIZE(rzn1_adc2_channels);
		return 0;
	}

	return dev_err_probe(rzn1_adc->dev, -ENODEV,
			     "Failed to set IIO channels, no ADC core used\n");
}

static int rzn1_adc_core_get_regulators(struct rzn1_adc *rzn1_adc,
					int *adc_vref_mV,
					const char *avdd_name, const char *vref_name)
{
	struct device *dev = rzn1_adc->dev;
	int ret;

	/*
	 * For a given ADC core (ADC1 or ADC2), both regulators (AVDD and VREF)
	 * must be available in order to have the ADC core used.
	 *
	 * We use the regulators presence to check the usage of the related
	 * ADC core. If both regulators are available, the ADC core is used.
	 * Otherwise, the ADC core is not used.
	 *
	 * The adc_vref_mV value is set to a negative error code (-ENODEV) when
	 * the ADC core is not used. Otherwise it is set to the VRef mV value.
	 */

	*adc_vref_mV = -ENODEV;

	ret = devm_regulator_get_enable_optional(dev, avdd_name);
	if (ret == -ENODEV)
		return 0;
	if (ret < 0)
		return dev_err_probe(dev, ret, "Failed to get '%s' regulator\n",
				     avdd_name);

	ret = devm_regulator_get_enable_read_voltage(dev, vref_name);
	if (ret == -ENODEV)
		return 0;
	if (ret < 0)
		return dev_err_probe(dev, ret, "Failed to get '%s' regulator\n",
				     vref_name);

	/*
	 * Both regulators are available.
	 * Set adc_vref_mV to the Vref value in mV. This, as the value set is
	 * positive, also signals that the ADC is used.
	 */
	*adc_vref_mV = ret / 1000;

	return 0;
}

static int rzn1_adc_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct iio_dev *indio_dev;
	struct rzn1_adc *rzn1_adc;
	struct clk *clk;
	int ret;

	indio_dev = devm_iio_device_alloc(dev, sizeof(*rzn1_adc));
	if (!indio_dev)
		return -ENOMEM;

	rzn1_adc = iio_priv(indio_dev);
	rzn1_adc->dev = dev;

	ret = devm_mutex_init(dev, &rzn1_adc->lock);
	if (ret)
		return ret;

	rzn1_adc->regs = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(rzn1_adc->regs))
		return PTR_ERR(rzn1_adc->regs);

	clk = devm_clk_get_enabled(dev, "pclk");
	if (IS_ERR(clk))
		return dev_err_probe(dev, PTR_ERR(clk), "Failed to get pclk\n");

	clk = devm_clk_get_enabled(dev, "adc");
	if (IS_ERR(clk))
		return dev_err_probe(dev, PTR_ERR(clk), "Failed to get adc clk\n");

	ret = rzn1_adc_core_get_regulators(rzn1_adc, &rzn1_adc->adc1_vref_mV,
					   "adc1-avdd", "adc1-vref");
	if (ret)
		return ret;

	ret = rzn1_adc_core_get_regulators(rzn1_adc, &rzn1_adc->adc2_vref_mV,
					   "adc2-avdd", "adc2-vref");
	if (ret)
		return ret;

	platform_set_drvdata(pdev, rzn1_adc);

	indio_dev->name = "rzn1-adc";
	indio_dev->info = &rzn1_adc_info;
	indio_dev->modes = INDIO_DIRECT_MODE;
	ret = rzn1_adc_set_iio_dev_channels(rzn1_adc, indio_dev);
	if (ret)
		return ret;

	pm_runtime_set_autosuspend_delay(dev, 500);
	pm_runtime_use_autosuspend(dev);
	ret = devm_pm_runtime_enable(dev);
	if (ret)
		return dev_err_probe(dev, ret, "Failed to enable runtime PM\n");

	return devm_iio_device_register(dev, indio_dev);
}

static int rzn1_adc_pm_runtime_suspend(struct device *dev)
{
	struct rzn1_adc *rzn1_adc = dev_get_drvdata(dev);

	return rzn1_adc_power(rzn1_adc, false);
}

static int rzn1_adc_pm_runtime_resume(struct device *dev)
{
	struct rzn1_adc *rzn1_adc = dev_get_drvdata(dev);

	return rzn1_adc_power(rzn1_adc, true);
}

static DEFINE_RUNTIME_DEV_PM_OPS(rzn1_adc_pm_ops,
				 rzn1_adc_pm_runtime_suspend,
				 rzn1_adc_pm_runtime_resume,
				 NULL);

static const struct of_device_id rzn1_adc_of_match[] = {
	{ .compatible = "renesas,rzn1-adc" },
	{ }
};
MODULE_DEVICE_TABLE(of, rzn1_adc_of_match);

static struct platform_driver rzn1_adc_driver = {
	.probe = rzn1_adc_probe,
	.driver = {
		.name = "rzn1-adc",
		.of_match_table = rzn1_adc_of_match,
		.pm = pm_ptr(&rzn1_adc_pm_ops),
	},
};
module_platform_driver(rzn1_adc_driver);

MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>");
MODULE_DESCRIPTION("Renesas RZ/N1 ADC Driver");
MODULE_LICENSE("GPL");