1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * ST SPEAr ADC driver |
4 | * |
5 | * Copyright 2012 Stefan Roese <sr@denx.de> |
6 | */ |
7 | |
8 | #include <linux/module.h> |
9 | #include <linux/platform_device.h> |
10 | #include <linux/interrupt.h> |
11 | #include <linux/device.h> |
12 | #include <linux/kernel.h> |
13 | #include <linux/slab.h> |
14 | #include <linux/io.h> |
15 | #include <linux/clk.h> |
16 | #include <linux/err.h> |
17 | #include <linux/completion.h> |
18 | #include <linux/of.h> |
19 | #include <linux/of_address.h> |
20 | |
21 | #include <linux/iio/iio.h> |
22 | #include <linux/iio/sysfs.h> |
23 | |
24 | /* SPEAR registers definitions */ |
25 | #define SPEAR600_ADC_SCAN_RATE_LO(x) ((x) & 0xFFFF) |
26 | #define SPEAR600_ADC_SCAN_RATE_HI(x) (((x) >> 0x10) & 0xFFFF) |
27 | #define SPEAR_ADC_CLK_LOW(x) (((x) & 0xf) << 0) |
28 | #define SPEAR_ADC_CLK_HIGH(x) (((x) & 0xf) << 4) |
29 | |
30 | /* Bit definitions for SPEAR_ADC_STATUS */ |
31 | #define SPEAR_ADC_STATUS_START_CONVERSION BIT(0) |
32 | #define SPEAR_ADC_STATUS_CHANNEL_NUM(x) ((x) << 1) |
33 | #define SPEAR_ADC_STATUS_ADC_ENABLE BIT(4) |
34 | #define SPEAR_ADC_STATUS_AVG_SAMPLE(x) ((x) << 5) |
35 | #define SPEAR_ADC_STATUS_VREF_INTERNAL BIT(9) |
36 | |
37 | #define SPEAR_ADC_DATA_MASK 0x03ff |
38 | #define SPEAR_ADC_DATA_BITS 10 |
39 | |
40 | #define SPEAR_ADC_MOD_NAME "spear-adc" |
41 | |
42 | #define SPEAR_ADC_CHANNEL_NUM 8 |
43 | |
44 | #define SPEAR_ADC_CLK_MIN 2500000 |
45 | #define SPEAR_ADC_CLK_MAX 20000000 |
46 | |
47 | struct adc_regs_spear3xx { |
48 | u32 status; |
49 | u32 average; |
50 | u32 scan_rate; |
51 | u32 clk; /* Not avail for 1340 & 1310 */ |
52 | u32 ch_ctrl[SPEAR_ADC_CHANNEL_NUM]; |
53 | u32 ch_data[SPEAR_ADC_CHANNEL_NUM]; |
54 | }; |
55 | |
56 | struct chan_data { |
57 | u32 lsb; |
58 | u32 msb; |
59 | }; |
60 | |
61 | struct adc_regs_spear6xx { |
62 | u32 status; |
63 | u32 pad[2]; |
64 | u32 clk; |
65 | u32 ch_ctrl[SPEAR_ADC_CHANNEL_NUM]; |
66 | struct chan_data ch_data[SPEAR_ADC_CHANNEL_NUM]; |
67 | u32 scan_rate_lo; |
68 | u32 scan_rate_hi; |
69 | struct chan_data average; |
70 | }; |
71 | |
72 | struct spear_adc_state { |
73 | struct device_node *np; |
74 | struct adc_regs_spear3xx __iomem *adc_base_spear3xx; |
75 | struct adc_regs_spear6xx __iomem *adc_base_spear6xx; |
76 | struct clk *clk; |
77 | struct completion completion; |
78 | /* |
79 | * Lock to protect the device state during a potential concurrent |
80 | * read access from userspace. Reading a raw value requires a sequence |
81 | * of register writes, then a wait for a completion callback, |
82 | * and finally a register read, during which userspace could issue |
83 | * another read request. This lock protects a read access from |
84 | * ocurring before another one has finished. |
85 | */ |
86 | struct mutex lock; |
87 | u32 current_clk; |
88 | u32 sampling_freq; |
89 | u32 avg_samples; |
90 | u32 vref_external; |
91 | u32 value; |
92 | }; |
93 | |
94 | /* |
95 | * Functions to access some SPEAr ADC register. Abstracted into |
96 | * static inline functions, because of different register offsets |
97 | * on different SoC variants (SPEAr300 vs SPEAr600 etc). |
98 | */ |
99 | static void spear_adc_set_status(struct spear_adc_state *st, u32 val) |
100 | { |
101 | __raw_writel(val, addr: &st->adc_base_spear6xx->status); |
102 | } |
103 | |
104 | static void spear_adc_set_clk(struct spear_adc_state *st, u32 val) |
105 | { |
106 | u32 clk_high, clk_low, count; |
107 | u32 apb_clk = clk_get_rate(clk: st->clk); |
108 | |
109 | count = DIV_ROUND_UP(apb_clk, val); |
110 | clk_low = count / 2; |
111 | clk_high = count - clk_low; |
112 | st->current_clk = apb_clk / count; |
113 | |
114 | __raw_writel(SPEAR_ADC_CLK_LOW(clk_low) | SPEAR_ADC_CLK_HIGH(clk_high), |
115 | addr: &st->adc_base_spear6xx->clk); |
116 | } |
117 | |
118 | static void spear_adc_set_ctrl(struct spear_adc_state *st, int n, |
119 | u32 val) |
120 | { |
121 | __raw_writel(val, addr: &st->adc_base_spear6xx->ch_ctrl[n]); |
122 | } |
123 | |
124 | static u32 spear_adc_get_average(struct spear_adc_state *st) |
125 | { |
126 | if (of_device_is_compatible(device: st->np, "st,spear600-adc" )) { |
127 | return __raw_readl(addr: &st->adc_base_spear6xx->average.msb) & |
128 | SPEAR_ADC_DATA_MASK; |
129 | } else { |
130 | return __raw_readl(addr: &st->adc_base_spear3xx->average) & |
131 | SPEAR_ADC_DATA_MASK; |
132 | } |
133 | } |
134 | |
135 | static void spear_adc_set_scanrate(struct spear_adc_state *st, u32 rate) |
136 | { |
137 | if (of_device_is_compatible(device: st->np, "st,spear600-adc" )) { |
138 | __raw_writel(SPEAR600_ADC_SCAN_RATE_LO(rate), |
139 | addr: &st->adc_base_spear6xx->scan_rate_lo); |
140 | __raw_writel(SPEAR600_ADC_SCAN_RATE_HI(rate), |
141 | addr: &st->adc_base_spear6xx->scan_rate_hi); |
142 | } else { |
143 | __raw_writel(val: rate, addr: &st->adc_base_spear3xx->scan_rate); |
144 | } |
145 | } |
146 | |
147 | static int spear_adc_read_raw(struct iio_dev *indio_dev, |
148 | struct iio_chan_spec const *chan, |
149 | int *val, |
150 | int *val2, |
151 | long mask) |
152 | { |
153 | struct spear_adc_state *st = iio_priv(indio_dev); |
154 | u32 status; |
155 | |
156 | switch (mask) { |
157 | case IIO_CHAN_INFO_RAW: |
158 | mutex_lock(&st->lock); |
159 | |
160 | status = SPEAR_ADC_STATUS_CHANNEL_NUM(chan->channel) | |
161 | SPEAR_ADC_STATUS_AVG_SAMPLE(st->avg_samples) | |
162 | SPEAR_ADC_STATUS_START_CONVERSION | |
163 | SPEAR_ADC_STATUS_ADC_ENABLE; |
164 | if (st->vref_external == 0) |
165 | status |= SPEAR_ADC_STATUS_VREF_INTERNAL; |
166 | |
167 | spear_adc_set_status(st, val: status); |
168 | wait_for_completion(&st->completion); /* set by ISR */ |
169 | *val = st->value; |
170 | |
171 | mutex_unlock(lock: &st->lock); |
172 | |
173 | return IIO_VAL_INT; |
174 | |
175 | case IIO_CHAN_INFO_SCALE: |
176 | *val = st->vref_external; |
177 | *val2 = SPEAR_ADC_DATA_BITS; |
178 | return IIO_VAL_FRACTIONAL_LOG2; |
179 | case IIO_CHAN_INFO_SAMP_FREQ: |
180 | *val = st->current_clk; |
181 | return IIO_VAL_INT; |
182 | } |
183 | |
184 | return -EINVAL; |
185 | } |
186 | |
187 | static int spear_adc_write_raw(struct iio_dev *indio_dev, |
188 | struct iio_chan_spec const *chan, |
189 | int val, |
190 | int val2, |
191 | long mask) |
192 | { |
193 | struct spear_adc_state *st = iio_priv(indio_dev); |
194 | int ret = 0; |
195 | |
196 | if (mask != IIO_CHAN_INFO_SAMP_FREQ) |
197 | return -EINVAL; |
198 | |
199 | mutex_lock(&st->lock); |
200 | |
201 | if ((val < SPEAR_ADC_CLK_MIN) || |
202 | (val > SPEAR_ADC_CLK_MAX) || |
203 | (val2 != 0)) { |
204 | ret = -EINVAL; |
205 | goto out; |
206 | } |
207 | |
208 | spear_adc_set_clk(st, val); |
209 | |
210 | out: |
211 | mutex_unlock(lock: &st->lock); |
212 | return ret; |
213 | } |
214 | |
215 | #define SPEAR_ADC_CHAN(idx) { \ |
216 | .type = IIO_VOLTAGE, \ |
217 | .indexed = 1, \ |
218 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ |
219 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ |
220 | .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\ |
221 | .channel = idx, \ |
222 | } |
223 | |
224 | static const struct iio_chan_spec spear_adc_iio_channels[] = { |
225 | SPEAR_ADC_CHAN(0), |
226 | SPEAR_ADC_CHAN(1), |
227 | SPEAR_ADC_CHAN(2), |
228 | SPEAR_ADC_CHAN(3), |
229 | SPEAR_ADC_CHAN(4), |
230 | SPEAR_ADC_CHAN(5), |
231 | SPEAR_ADC_CHAN(6), |
232 | SPEAR_ADC_CHAN(7), |
233 | }; |
234 | |
235 | static irqreturn_t spear_adc_isr(int irq, void *dev_id) |
236 | { |
237 | struct spear_adc_state *st = dev_id; |
238 | |
239 | /* Read value to clear IRQ */ |
240 | st->value = spear_adc_get_average(st); |
241 | complete(&st->completion); |
242 | |
243 | return IRQ_HANDLED; |
244 | } |
245 | |
246 | static int spear_adc_configure(struct spear_adc_state *st) |
247 | { |
248 | int i; |
249 | |
250 | /* Reset ADC core */ |
251 | spear_adc_set_status(st, val: 0); |
252 | __raw_writel(val: 0, addr: &st->adc_base_spear6xx->clk); |
253 | for (i = 0; i < 8; i++) |
254 | spear_adc_set_ctrl(st, n: i, val: 0); |
255 | spear_adc_set_scanrate(st, rate: 0); |
256 | |
257 | spear_adc_set_clk(st, val: st->sampling_freq); |
258 | |
259 | return 0; |
260 | } |
261 | |
262 | static const struct iio_info spear_adc_info = { |
263 | .read_raw = &spear_adc_read_raw, |
264 | .write_raw = &spear_adc_write_raw, |
265 | }; |
266 | |
267 | static int spear_adc_probe(struct platform_device *pdev) |
268 | { |
269 | struct device_node *np = pdev->dev.of_node; |
270 | struct device *dev = &pdev->dev; |
271 | struct spear_adc_state *st; |
272 | struct iio_dev *indio_dev = NULL; |
273 | int ret = -ENODEV; |
274 | int irq; |
275 | |
276 | indio_dev = devm_iio_device_alloc(parent: dev, sizeof_priv: sizeof(struct spear_adc_state)); |
277 | if (!indio_dev) |
278 | return dev_err_probe(dev, err: -ENOMEM, |
279 | fmt: "failed allocating iio device\n" ); |
280 | |
281 | st = iio_priv(indio_dev); |
282 | |
283 | mutex_init(&st->lock); |
284 | |
285 | st->np = np; |
286 | |
287 | /* |
288 | * SPEAr600 has a different register layout than other SPEAr SoC's |
289 | * (e.g. SPEAr3xx). Let's provide two register base addresses |
290 | * to support multi-arch kernels. |
291 | */ |
292 | st->adc_base_spear6xx = devm_platform_ioremap_resource(pdev, index: 0); |
293 | if (IS_ERR(ptr: st->adc_base_spear6xx)) |
294 | return PTR_ERR(ptr: st->adc_base_spear6xx); |
295 | |
296 | st->adc_base_spear3xx = |
297 | (struct adc_regs_spear3xx __iomem *)st->adc_base_spear6xx; |
298 | |
299 | st->clk = devm_clk_get_enabled(dev, NULL); |
300 | if (IS_ERR(ptr: st->clk)) |
301 | return dev_err_probe(dev, err: PTR_ERR(ptr: st->clk), |
302 | fmt: "failed enabling clock\n" ); |
303 | |
304 | irq = platform_get_irq(pdev, 0); |
305 | if (irq < 0) |
306 | return irq; |
307 | |
308 | ret = devm_request_irq(dev, irq, handler: spear_adc_isr, irqflags: 0, SPEAR_ADC_MOD_NAME, |
309 | dev_id: st); |
310 | if (ret < 0) |
311 | return dev_err_probe(dev, err: ret, fmt: "failed requesting interrupt\n" ); |
312 | |
313 | if (of_property_read_u32(np, propname: "sampling-frequency" , |
314 | out_value: &st->sampling_freq)) |
315 | return dev_err_probe(dev, err: -EINVAL, |
316 | fmt: "sampling-frequency missing in DT\n" ); |
317 | |
318 | /* |
319 | * Optional avg_samples defaults to 0, resulting in single data |
320 | * conversion |
321 | */ |
322 | of_property_read_u32(np, propname: "average-samples" , out_value: &st->avg_samples); |
323 | |
324 | /* |
325 | * Optional vref_external defaults to 0, resulting in internal vref |
326 | * selection |
327 | */ |
328 | of_property_read_u32(np, propname: "vref-external" , out_value: &st->vref_external); |
329 | |
330 | spear_adc_configure(st); |
331 | |
332 | init_completion(x: &st->completion); |
333 | |
334 | indio_dev->name = SPEAR_ADC_MOD_NAME; |
335 | indio_dev->info = &spear_adc_info; |
336 | indio_dev->modes = INDIO_DIRECT_MODE; |
337 | indio_dev->channels = spear_adc_iio_channels; |
338 | indio_dev->num_channels = ARRAY_SIZE(spear_adc_iio_channels); |
339 | |
340 | ret = devm_iio_device_register(dev, indio_dev); |
341 | if (ret) |
342 | return ret; |
343 | |
344 | dev_info(dev, "SPEAR ADC driver loaded, IRQ %d\n" , irq); |
345 | |
346 | return 0; |
347 | } |
348 | |
349 | #ifdef CONFIG_OF |
350 | static const struct of_device_id spear_adc_dt_ids[] = { |
351 | { .compatible = "st,spear600-adc" , }, |
352 | { /* sentinel */ } |
353 | }; |
354 | MODULE_DEVICE_TABLE(of, spear_adc_dt_ids); |
355 | #endif |
356 | |
357 | static struct platform_driver spear_adc_driver = { |
358 | .probe = spear_adc_probe, |
359 | .driver = { |
360 | .name = SPEAR_ADC_MOD_NAME, |
361 | .of_match_table = of_match_ptr(spear_adc_dt_ids), |
362 | }, |
363 | }; |
364 | |
365 | module_platform_driver(spear_adc_driver); |
366 | |
367 | MODULE_AUTHOR("Stefan Roese <sr@denx.de>" ); |
368 | MODULE_DESCRIPTION("SPEAr ADC driver" ); |
369 | MODULE_LICENSE("GPL" ); |
370 | |