xref: /openbmc/linux/drivers/iio/adc/ingenic-adc.c (revision 82b5d164)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * ADC driver for the Ingenic JZ47xx SoCs
4  * Copyright (c) 2019 Artur Rojek <contact@artur-rojek.eu>
5  *
6  * based on drivers/mfd/jz4740-adc.c
7  */
8 
9 #include <dt-bindings/iio/adc/ingenic,adc.h>
10 #include <linux/clk.h>
11 #include <linux/iio/iio.h>
12 #include <linux/io.h>
13 #include <linux/iopoll.h>
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/mutex.h>
17 #include <linux/platform_device.h>
18 
19 #define JZ_ADC_REG_ENABLE		0x00
20 #define JZ_ADC_REG_CFG			0x04
21 #define JZ_ADC_REG_CTRL			0x08
22 #define JZ_ADC_REG_STATUS		0x0c
23 #define JZ_ADC_REG_ADTCH		0x18
24 #define JZ_ADC_REG_ADBDAT		0x1c
25 #define JZ_ADC_REG_ADSDAT		0x20
26 #define JZ_ADC_REG_ADCLK		0x28
27 
28 #define JZ_ADC_REG_CFG_BAT_MD		BIT(4)
29 #define JZ_ADC_REG_ADCLK_CLKDIV_LSB	0
30 #define JZ_ADC_REG_ADCLK_CLKDIV10US_LSB	16
31 
32 #define JZ_ADC_AUX_VREF				3300
33 #define JZ_ADC_AUX_VREF_BITS			12
34 #define JZ_ADC_BATTERY_LOW_VREF			2500
35 #define JZ_ADC_BATTERY_LOW_VREF_BITS		12
36 #define JZ4725B_ADC_BATTERY_HIGH_VREF		7500
37 #define JZ4725B_ADC_BATTERY_HIGH_VREF_BITS	10
38 #define JZ4740_ADC_BATTERY_HIGH_VREF		(7500 * 0.986)
39 #define JZ4740_ADC_BATTERY_HIGH_VREF_BITS	12
40 
41 struct ingenic_adc;
42 
43 struct ingenic_adc_soc_data {
44 	unsigned int battery_high_vref;
45 	unsigned int battery_high_vref_bits;
46 	const int *battery_raw_avail;
47 	size_t battery_raw_avail_size;
48 	const int *battery_scale_avail;
49 	size_t battery_scale_avail_size;
50 	int (*init_clk_div)(struct device *dev, struct ingenic_adc *adc);
51 };
52 
53 struct ingenic_adc {
54 	void __iomem *base;
55 	struct clk *clk;
56 	struct mutex lock;
57 	const struct ingenic_adc_soc_data *soc_data;
58 	bool low_vref_mode;
59 };
60 
61 static void ingenic_adc_set_config(struct ingenic_adc *adc,
62 				   uint32_t mask,
63 				   uint32_t val)
64 {
65 	uint32_t cfg;
66 
67 	clk_enable(adc->clk);
68 	mutex_lock(&adc->lock);
69 
70 	cfg = readl(adc->base + JZ_ADC_REG_CFG) & ~mask;
71 	cfg |= val;
72 	writel(cfg, adc->base + JZ_ADC_REG_CFG);
73 
74 	mutex_unlock(&adc->lock);
75 	clk_disable(adc->clk);
76 }
77 
78 static void ingenic_adc_enable(struct ingenic_adc *adc,
79 			       int engine,
80 			       bool enabled)
81 {
82 	u8 val;
83 
84 	mutex_lock(&adc->lock);
85 	val = readb(adc->base + JZ_ADC_REG_ENABLE);
86 
87 	if (enabled)
88 		val |= BIT(engine);
89 	else
90 		val &= ~BIT(engine);
91 
92 	writeb(val, adc->base + JZ_ADC_REG_ENABLE);
93 	mutex_unlock(&adc->lock);
94 }
95 
96 static int ingenic_adc_capture(struct ingenic_adc *adc,
97 			       int engine)
98 {
99 	u8 val;
100 	int ret;
101 
102 	ingenic_adc_enable(adc, engine, true);
103 	ret = readb_poll_timeout(adc->base + JZ_ADC_REG_ENABLE, val,
104 				 !(val & BIT(engine)), 250, 1000);
105 	if (ret)
106 		ingenic_adc_enable(adc, engine, false);
107 
108 	return ret;
109 }
110 
111 static int ingenic_adc_write_raw(struct iio_dev *iio_dev,
112 				 struct iio_chan_spec const *chan,
113 				 int val,
114 				 int val2,
115 				 long m)
116 {
117 	struct ingenic_adc *adc = iio_priv(iio_dev);
118 
119 	switch (m) {
120 	case IIO_CHAN_INFO_SCALE:
121 		switch (chan->channel) {
122 		case INGENIC_ADC_BATTERY:
123 			if (val > JZ_ADC_BATTERY_LOW_VREF) {
124 				ingenic_adc_set_config(adc,
125 						       JZ_ADC_REG_CFG_BAT_MD,
126 						       0);
127 				adc->low_vref_mode = false;
128 			} else {
129 				ingenic_adc_set_config(adc,
130 						       JZ_ADC_REG_CFG_BAT_MD,
131 						       JZ_ADC_REG_CFG_BAT_MD);
132 				adc->low_vref_mode = true;
133 			}
134 			return 0;
135 		default:
136 			return -EINVAL;
137 		}
138 	default:
139 		return -EINVAL;
140 	}
141 }
142 
143 static const int jz4725b_adc_battery_raw_avail[] = {
144 	0, 1, (1 << JZ_ADC_BATTERY_LOW_VREF_BITS) - 1,
145 };
146 
147 static const int jz4725b_adc_battery_scale_avail[] = {
148 	JZ4725B_ADC_BATTERY_HIGH_VREF, JZ4725B_ADC_BATTERY_HIGH_VREF_BITS,
149 	JZ_ADC_BATTERY_LOW_VREF, JZ_ADC_BATTERY_LOW_VREF_BITS,
150 };
151 
152 static const int jz4740_adc_battery_raw_avail[] = {
153 	0, 1, (1 << JZ_ADC_BATTERY_LOW_VREF_BITS) - 1,
154 };
155 
156 static const int jz4740_adc_battery_scale_avail[] = {
157 	JZ4740_ADC_BATTERY_HIGH_VREF, JZ4740_ADC_BATTERY_HIGH_VREF_BITS,
158 	JZ_ADC_BATTERY_LOW_VREF, JZ_ADC_BATTERY_LOW_VREF_BITS,
159 };
160 
161 static int jz4725b_adc_init_clk_div(struct device *dev, struct ingenic_adc *adc)
162 {
163 	struct clk *parent_clk;
164 	unsigned long parent_rate, rate;
165 	unsigned int div_main, div_10us;
166 
167 	parent_clk = clk_get_parent(adc->clk);
168 	if (!parent_clk) {
169 		dev_err(dev, "ADC clock has no parent\n");
170 		return -ENODEV;
171 	}
172 	parent_rate = clk_get_rate(parent_clk);
173 
174 	/*
175 	 * The JZ4725B ADC works at 500 kHz to 8 MHz.
176 	 * We pick the highest rate possible.
177 	 * In practice we typically get 6 MHz, half of the 12 MHz EXT clock.
178 	 */
179 	div_main = DIV_ROUND_UP(parent_rate, 8000000);
180 	div_main = clamp(div_main, 1u, 64u);
181 	rate = parent_rate / div_main;
182 	if (rate < 500000 || rate > 8000000) {
183 		dev_err(dev, "No valid divider for ADC main clock\n");
184 		return -EINVAL;
185 	}
186 
187 	/* We also need a divider that produces a 10us clock. */
188 	div_10us = DIV_ROUND_UP(rate, 100000);
189 
190 	writel(((div_10us - 1) << JZ_ADC_REG_ADCLK_CLKDIV10US_LSB) |
191 	       (div_main - 1) << JZ_ADC_REG_ADCLK_CLKDIV_LSB,
192 	       adc->base + JZ_ADC_REG_ADCLK);
193 
194 	return 0;
195 }
196 
197 static const struct ingenic_adc_soc_data jz4725b_adc_soc_data = {
198 	.battery_high_vref = JZ4725B_ADC_BATTERY_HIGH_VREF,
199 	.battery_high_vref_bits = JZ4725B_ADC_BATTERY_HIGH_VREF_BITS,
200 	.battery_raw_avail = jz4725b_adc_battery_raw_avail,
201 	.battery_raw_avail_size = ARRAY_SIZE(jz4725b_adc_battery_raw_avail),
202 	.battery_scale_avail = jz4725b_adc_battery_scale_avail,
203 	.battery_scale_avail_size = ARRAY_SIZE(jz4725b_adc_battery_scale_avail),
204 	.init_clk_div = jz4725b_adc_init_clk_div,
205 };
206 
207 static const struct ingenic_adc_soc_data jz4740_adc_soc_data = {
208 	.battery_high_vref = JZ4740_ADC_BATTERY_HIGH_VREF,
209 	.battery_high_vref_bits = JZ4740_ADC_BATTERY_HIGH_VREF_BITS,
210 	.battery_raw_avail = jz4740_adc_battery_raw_avail,
211 	.battery_raw_avail_size = ARRAY_SIZE(jz4740_adc_battery_raw_avail),
212 	.battery_scale_avail = jz4740_adc_battery_scale_avail,
213 	.battery_scale_avail_size = ARRAY_SIZE(jz4740_adc_battery_scale_avail),
214 	.init_clk_div = NULL, /* no ADCLK register on JZ4740 */
215 };
216 
217 static int ingenic_adc_read_avail(struct iio_dev *iio_dev,
218 				  struct iio_chan_spec const *chan,
219 				  const int **vals,
220 				  int *type,
221 				  int *length,
222 				  long m)
223 {
224 	struct ingenic_adc *adc = iio_priv(iio_dev);
225 
226 	switch (m) {
227 	case IIO_CHAN_INFO_RAW:
228 		*type = IIO_VAL_INT;
229 		*length = adc->soc_data->battery_raw_avail_size;
230 		*vals = adc->soc_data->battery_raw_avail;
231 		return IIO_AVAIL_RANGE;
232 	case IIO_CHAN_INFO_SCALE:
233 		*type = IIO_VAL_FRACTIONAL_LOG2;
234 		*length = adc->soc_data->battery_scale_avail_size;
235 		*vals = adc->soc_data->battery_scale_avail;
236 		return IIO_AVAIL_LIST;
237 	default:
238 		return -EINVAL;
239 	};
240 }
241 
242 static int ingenic_adc_read_raw(struct iio_dev *iio_dev,
243 				struct iio_chan_spec const *chan,
244 				int *val,
245 				int *val2,
246 				long m)
247 {
248 	struct ingenic_adc *adc = iio_priv(iio_dev);
249 	int ret;
250 
251 	switch (m) {
252 	case IIO_CHAN_INFO_RAW:
253 		clk_enable(adc->clk);
254 		ret = ingenic_adc_capture(adc, chan->channel);
255 		if (ret) {
256 			clk_disable(adc->clk);
257 			return ret;
258 		}
259 
260 		switch (chan->channel) {
261 		case INGENIC_ADC_AUX:
262 			*val = readw(adc->base + JZ_ADC_REG_ADSDAT);
263 			break;
264 		case INGENIC_ADC_BATTERY:
265 			*val = readw(adc->base + JZ_ADC_REG_ADBDAT);
266 			break;
267 		}
268 
269 		clk_disable(adc->clk);
270 
271 		return IIO_VAL_INT;
272 	case IIO_CHAN_INFO_SCALE:
273 		switch (chan->channel) {
274 		case INGENIC_ADC_AUX:
275 			*val = JZ_ADC_AUX_VREF;
276 			*val2 = JZ_ADC_AUX_VREF_BITS;
277 			break;
278 		case INGENIC_ADC_BATTERY:
279 			if (adc->low_vref_mode) {
280 				*val = JZ_ADC_BATTERY_LOW_VREF;
281 				*val2 = JZ_ADC_BATTERY_LOW_VREF_BITS;
282 			} else {
283 				*val = adc->soc_data->battery_high_vref;
284 				*val2 = adc->soc_data->battery_high_vref_bits;
285 			}
286 			break;
287 		}
288 
289 		return IIO_VAL_FRACTIONAL_LOG2;
290 	default:
291 		return -EINVAL;
292 	}
293 }
294 
295 static void ingenic_adc_clk_cleanup(void *data)
296 {
297 	clk_unprepare(data);
298 }
299 
300 static const struct iio_info ingenic_adc_info = {
301 	.write_raw = ingenic_adc_write_raw,
302 	.read_raw = ingenic_adc_read_raw,
303 	.read_avail = ingenic_adc_read_avail,
304 };
305 
306 static const struct iio_chan_spec ingenic_channels[] = {
307 	{
308 		.extend_name = "aux",
309 		.type = IIO_VOLTAGE,
310 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
311 				      BIT(IIO_CHAN_INFO_SCALE),
312 		.indexed = 1,
313 		.channel = INGENIC_ADC_AUX,
314 	},
315 	{
316 		.extend_name = "battery",
317 		.type = IIO_VOLTAGE,
318 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
319 				      BIT(IIO_CHAN_INFO_SCALE),
320 		.info_mask_separate_available = BIT(IIO_CHAN_INFO_RAW) |
321 						BIT(IIO_CHAN_INFO_SCALE),
322 		.indexed = 1,
323 		.channel = INGENIC_ADC_BATTERY,
324 	},
325 };
326 
327 static int ingenic_adc_probe(struct platform_device *pdev)
328 {
329 	struct device *dev = &pdev->dev;
330 	struct iio_dev *iio_dev;
331 	struct ingenic_adc *adc;
332 	struct resource *mem_base;
333 	const struct ingenic_adc_soc_data *soc_data;
334 	int ret;
335 
336 	soc_data = device_get_match_data(dev);
337 	if (!soc_data)
338 		return -EINVAL;
339 
340 	iio_dev = devm_iio_device_alloc(dev, sizeof(*adc));
341 	if (!iio_dev)
342 		return -ENOMEM;
343 
344 	adc = iio_priv(iio_dev);
345 	mutex_init(&adc->lock);
346 	adc->soc_data = soc_data;
347 
348 	mem_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
349 	adc->base = devm_ioremap_resource(dev, mem_base);
350 	if (IS_ERR(adc->base))
351 		return PTR_ERR(adc->base);
352 
353 	adc->clk = devm_clk_get(dev, "adc");
354 	if (IS_ERR(adc->clk)) {
355 		dev_err(dev, "Unable to get clock\n");
356 		return PTR_ERR(adc->clk);
357 	}
358 
359 	ret = clk_prepare_enable(adc->clk);
360 	if (ret) {
361 		dev_err(dev, "Failed to enable clock\n");
362 		return ret;
363 	}
364 
365 	/* Set clock dividers. */
366 	if (soc_data->init_clk_div) {
367 		ret = soc_data->init_clk_div(dev, adc);
368 		if (ret) {
369 			clk_disable_unprepare(adc->clk);
370 			return ret;
371 		}
372 	}
373 
374 	/* Put hardware in a known passive state. */
375 	writeb(0x00, adc->base + JZ_ADC_REG_ENABLE);
376 	writeb(0xff, adc->base + JZ_ADC_REG_CTRL);
377 	clk_disable(adc->clk);
378 
379 	ret = devm_add_action_or_reset(dev, ingenic_adc_clk_cleanup, adc->clk);
380 	if (ret) {
381 		dev_err(dev, "Unable to add action\n");
382 		return ret;
383 	}
384 
385 	iio_dev->dev.parent = dev;
386 	iio_dev->name = "jz-adc";
387 	iio_dev->modes = INDIO_DIRECT_MODE;
388 	iio_dev->channels = ingenic_channels;
389 	iio_dev->num_channels = ARRAY_SIZE(ingenic_channels);
390 	iio_dev->info = &ingenic_adc_info;
391 
392 	ret = devm_iio_device_register(dev, iio_dev);
393 	if (ret)
394 		dev_err(dev, "Unable to register IIO device\n");
395 
396 	return ret;
397 }
398 
399 #ifdef CONFIG_OF
400 static const struct of_device_id ingenic_adc_of_match[] = {
401 	{ .compatible = "ingenic,jz4725b-adc", .data = &jz4725b_adc_soc_data, },
402 	{ .compatible = "ingenic,jz4740-adc", .data = &jz4740_adc_soc_data, },
403 	{ },
404 };
405 MODULE_DEVICE_TABLE(of, ingenic_adc_of_match);
406 #endif
407 
408 static struct platform_driver ingenic_adc_driver = {
409 	.driver = {
410 		.name = "ingenic-adc",
411 		.of_match_table = of_match_ptr(ingenic_adc_of_match),
412 	},
413 	.probe = ingenic_adc_probe,
414 };
415 module_platform_driver(ingenic_adc_driver);
416 MODULE_LICENSE("GPL v2");
417