This source file includes following definitions.
- ingenic_adc_set_config
- ingenic_adc_enable
- ingenic_adc_capture
- ingenic_adc_write_raw
- jz4725b_adc_init_clk_div
- ingenic_adc_read_avail
- ingenic_adc_read_raw
- ingenic_adc_clk_cleanup
- ingenic_adc_probe
1
2
3
4
5
6
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
176
177
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
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,
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
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
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");