Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
adc.c
Go to the documentation of this file.
1 /* arch/arm/plat-samsung/adc.c
2  *
3  * Copyright (c) 2008 Simtec Electronics
4  * http://armlinux.simtec.co.uk/
6  *
7  * Samsung ADC device core
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License.
12 */
13 
14 #include <linux/module.h>
15 #include <linux/kernel.h>
16 #include <linux/platform_device.h>
17 #include <linux/sched.h>
18 #include <linux/list.h>
19 #include <linux/slab.h>
20 #include <linux/err.h>
21 #include <linux/clk.h>
22 #include <linux/interrupt.h>
23 #include <linux/io.h>
25 
26 #include <plat/regs-adc.h>
27 #include <plat/adc.h>
28 
29 /* This driver is designed to control the usage of the ADC block between
30  * the touchscreen and any other drivers that may need to use it, such as
31  * the hwmon driver.
32  *
33  * Priority will be given to the touchscreen driver, but as this itself is
34  * rate limited it should not starve other requests which are processed in
35  * order that they are received.
36  *
37  * Each user registers to get a client block which uniquely identifies it
38  * and stores information such as the necessary functions to callback when
39  * action is required.
40  */
41 
43  TYPE_ADCV1, /* S3C24XX */
44  TYPE_ADCV11, /* S3C2443 */
45  TYPE_ADCV12, /* S3C2416, S3C2450 */
46  TYPE_ADCV2, /* S3C64XX, S5P64X0, S5PC100 */
47  TYPE_ADCV3, /* S5PV210, S5PC110, EXYNOS4210 */
48 };
49 
52  struct list_head pend;
54 
55  unsigned int nr_samples;
56  int result;
57  unsigned char is_ts;
58  unsigned char channel;
59 
60  void (*select_cb)(struct s3c_adc_client *c, unsigned selected);
62  unsigned val1, unsigned val2,
63  unsigned *samples_left);
64 };
65 
66 struct adc_device {
69  struct clk *clk;
72  void __iomem *regs;
74 
75  unsigned int prescale;
76 
77  int irq;
78  struct regulator *vdd;
79 };
80 
81 static struct adc_device *adc_dev;
82 
83 static LIST_HEAD(adc_pending); /* protected by adc_device.lock */
84 
85 #define adc_dbg(_adc, msg...) dev_dbg(&(_adc)->pdev->dev, msg)
86 
87 static inline void s3c_adc_convert(struct adc_device *adc)
88 {
89  unsigned con = readl(adc->regs + S3C2410_ADCCON);
90 
92  writel(con, adc->regs + S3C2410_ADCCON);
93 }
94 
95 static inline void s3c_adc_select(struct adc_device *adc,
96  struct s3c_adc_client *client)
97 {
98  unsigned con = readl(adc->regs + S3C2410_ADCCON);
99  enum s3c_cpu_type cpu = platform_get_device_id(adc->pdev)->driver_data;
100 
101  client->select_cb(client, 1);
102 
103  if (cpu == TYPE_ADCV1 || cpu == TYPE_ADCV2)
104  con &= ~S3C2410_ADCCON_MUXMASK;
105  con &= ~S3C2410_ADCCON_STDBM;
106  con &= ~S3C2410_ADCCON_STARTMASK;
107 
108  if (!client->is_ts) {
109  if (cpu == TYPE_ADCV3)
110  writel(client->channel & 0xf, adc->regs + S5P_ADCMUX);
111  else if (cpu == TYPE_ADCV11 || cpu == TYPE_ADCV12)
112  writel(client->channel & 0xf,
113  adc->regs + S3C2443_ADCMUX);
114  else
115  con |= S3C2410_ADCCON_SELMUX(client->channel);
116  }
117 
118  writel(con, adc->regs + S3C2410_ADCCON);
119 }
120 
121 static void s3c_adc_dbgshow(struct adc_device *adc)
122 {
123  adc_dbg(adc, "CON=%08x, TSC=%08x, DLY=%08x\n",
124  readl(adc->regs + S3C2410_ADCCON),
125  readl(adc->regs + S3C2410_ADCTSC),
126  readl(adc->regs + S3C2410_ADCDLY));
127 }
128 
129 static void s3c_adc_try(struct adc_device *adc)
130 {
131  struct s3c_adc_client *next = adc->ts_pend;
132 
133  if (!next && !list_empty(&adc_pending)) {
134  next = list_first_entry(&adc_pending,
135  struct s3c_adc_client, pend);
136  list_del(&next->pend);
137  } else
138  adc->ts_pend = NULL;
139 
140  if (next) {
141  adc_dbg(adc, "new client is %p\n", next);
142  adc->cur = next;
143  s3c_adc_select(adc, next);
144  s3c_adc_convert(adc);
145  s3c_adc_dbgshow(adc);
146  }
147 }
148 
149 int s3c_adc_start(struct s3c_adc_client *client,
150  unsigned int channel, unsigned int nr_samples)
151 {
152  struct adc_device *adc = adc_dev;
153  unsigned long flags;
154 
155  if (!adc) {
156  printk(KERN_ERR "%s: failed to find adc\n", __func__);
157  return -EINVAL;
158  }
159 
160  spin_lock_irqsave(&adc->lock, flags);
161 
162  if (client->is_ts && adc->ts_pend) {
163  spin_unlock_irqrestore(&adc->lock, flags);
164  return -EAGAIN;
165  }
166 
167  client->channel = channel;
168  client->nr_samples = nr_samples;
169 
170  if (client->is_ts)
171  adc->ts_pend = client;
172  else
173  list_add_tail(&client->pend, &adc_pending);
174 
175  if (!adc->cur)
176  s3c_adc_try(adc);
177 
178  spin_unlock_irqrestore(&adc->lock, flags);
179 
180  return 0;
181 }
183 
184 static void s3c_convert_done(struct s3c_adc_client *client,
185  unsigned v, unsigned u, unsigned *left)
186 {
187  client->result = v;
188  wake_up(client->wait);
189 }
190 
191 int s3c_adc_read(struct s3c_adc_client *client, unsigned int ch)
192 {
194  int ret;
195 
196  client->convert_cb = s3c_convert_done;
197  client->wait = &wake;
198  client->result = -1;
199 
200  ret = s3c_adc_start(client, ch, 1);
201  if (ret < 0)
202  goto err;
203 
204  ret = wait_event_timeout(wake, client->result >= 0, HZ / 2);
205  if (client->result < 0) {
206  ret = -ETIMEDOUT;
207  goto err;
208  }
209 
210  client->convert_cb = NULL;
211  return client->result;
212 
213 err:
214  return ret;
215 }
217 
218 static void s3c_adc_default_select(struct s3c_adc_client *client,
219  unsigned select)
220 {
221 }
222 
224  void (*select)(struct s3c_adc_client *client,
225  unsigned int selected),
226  void (*conv)(struct s3c_adc_client *client,
227  unsigned d0, unsigned d1,
228  unsigned *samples_left),
229  unsigned int is_ts)
230 {
231  struct s3c_adc_client *client;
232 
233  WARN_ON(!pdev);
234 
235  if (!select)
236  select = s3c_adc_default_select;
237 
238  if (!pdev)
239  return ERR_PTR(-EINVAL);
240 
241  client = kzalloc(sizeof(struct s3c_adc_client), GFP_KERNEL);
242  if (!client) {
243  dev_err(&pdev->dev, "no memory for adc client\n");
244  return ERR_PTR(-ENOMEM);
245  }
246 
247  client->pdev = pdev;
248  client->is_ts = is_ts;
249  client->select_cb = select;
250  client->convert_cb = conv;
251 
252  return client;
253 }
255 
256 void s3c_adc_release(struct s3c_adc_client *client)
257 {
258  unsigned long flags;
259 
260  spin_lock_irqsave(&adc_dev->lock, flags);
261 
262  /* We should really check that nothing is in progress. */
263  if (adc_dev->cur == client)
264  adc_dev->cur = NULL;
265  if (adc_dev->ts_pend == client)
266  adc_dev->ts_pend = NULL;
267  else {
268  struct list_head *p, *n;
269  struct s3c_adc_client *tmp;
270 
271  list_for_each_safe(p, n, &adc_pending) {
272  tmp = list_entry(p, struct s3c_adc_client, pend);
273  if (tmp == client)
274  list_del(&tmp->pend);
275  }
276  }
277 
278  if (adc_dev->cur == NULL)
279  s3c_adc_try(adc_dev);
280 
281  spin_unlock_irqrestore(&adc_dev->lock, flags);
282  kfree(client);
283 }
285 
286 static irqreturn_t s3c_adc_irq(int irq, void *pw)
287 {
288  struct adc_device *adc = pw;
289  struct s3c_adc_client *client = adc->cur;
290  enum s3c_cpu_type cpu = platform_get_device_id(adc->pdev)->driver_data;
291  unsigned data0, data1;
292 
293  if (!client) {
294  dev_warn(&adc->pdev->dev, "%s: no adc pending\n", __func__);
295  goto exit;
296  }
297 
298  data0 = readl(adc->regs + S3C2410_ADCDAT0);
299  data1 = readl(adc->regs + S3C2410_ADCDAT1);
300  adc_dbg(adc, "read %d: 0x%04x, 0x%04x\n", client->nr_samples, data0, data1);
301 
302  client->nr_samples--;
303 
304  if (cpu == TYPE_ADCV1 || cpu == TYPE_ADCV11) {
305  data0 &= 0x3ff;
306  data1 &= 0x3ff;
307  } else {
308  /* S3C2416/S3C64XX/S5P ADC resolution is 12-bit */
309  data0 &= 0xfff;
310  data1 &= 0xfff;
311  }
312 
313  if (client->convert_cb)
314  (client->convert_cb)(client, data0, data1, &client->nr_samples);
315 
316  if (client->nr_samples > 0) {
317  /* fire another conversion for this */
318 
319  client->select_cb(client, 1);
320  s3c_adc_convert(adc);
321  } else {
322  spin_lock(&adc->lock);
323  (client->select_cb)(client, 0);
324  adc->cur = NULL;
325 
326  s3c_adc_try(adc);
327  spin_unlock(&adc->lock);
328  }
329 
330 exit:
331  if (cpu == TYPE_ADCV2 || cpu == TYPE_ADCV3) {
332  /* Clear ADC interrupt */
333  writel(0, adc->regs + S3C64XX_ADCCLRINT);
334  }
335  return IRQ_HANDLED;
336 }
337 
338 static int s3c_adc_probe(struct platform_device *pdev)
339 {
340  struct device *dev = &pdev->dev;
341  struct adc_device *adc;
342  struct resource *regs;
343  enum s3c_cpu_type cpu = platform_get_device_id(pdev)->driver_data;
344  int ret;
345  unsigned tmp;
346 
347  adc = kzalloc(sizeof(struct adc_device), GFP_KERNEL);
348  if (adc == NULL) {
349  dev_err(dev, "failed to allocate adc_device\n");
350  return -ENOMEM;
351  }
352 
353  spin_lock_init(&adc->lock);
354 
355  adc->pdev = pdev;
356  adc->prescale = S3C2410_ADCCON_PRSCVL(49);
357 
358  adc->vdd = regulator_get(dev, "vdd");
359  if (IS_ERR(adc->vdd)) {
360  dev_err(dev, "operating without regulator \"vdd\" .\n");
361  ret = PTR_ERR(adc->vdd);
362  goto err_alloc;
363  }
364 
365  adc->irq = platform_get_irq(pdev, 1);
366  if (adc->irq <= 0) {
367  dev_err(dev, "failed to get adc irq\n");
368  ret = -ENOENT;
369  goto err_reg;
370  }
371 
372  ret = request_irq(adc->irq, s3c_adc_irq, 0, dev_name(dev), adc);
373  if (ret < 0) {
374  dev_err(dev, "failed to attach adc irq\n");
375  goto err_reg;
376  }
377 
378  adc->clk = clk_get(dev, "adc");
379  if (IS_ERR(adc->clk)) {
380  dev_err(dev, "failed to get adc clock\n");
381  ret = PTR_ERR(adc->clk);
382  goto err_irq;
383  }
384 
385  regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
386  if (!regs) {
387  dev_err(dev, "failed to find registers\n");
388  ret = -ENXIO;
389  goto err_clk;
390  }
391 
392  adc->regs = ioremap(regs->start, resource_size(regs));
393  if (!adc->regs) {
394  dev_err(dev, "failed to map registers\n");
395  ret = -ENXIO;
396  goto err_clk;
397  }
398 
399  ret = regulator_enable(adc->vdd);
400  if (ret)
401  goto err_ioremap;
402 
403  clk_enable(adc->clk);
404 
405  tmp = adc->prescale | S3C2410_ADCCON_PRSCEN;
406 
407  /* Enable 12-bit ADC resolution */
408  if (cpu == TYPE_ADCV12)
409  tmp |= S3C2416_ADCCON_RESSEL;
410  if (cpu == TYPE_ADCV2 || cpu == TYPE_ADCV3)
411  tmp |= S3C64XX_ADCCON_RESSEL;
412 
413  writel(tmp, adc->regs + S3C2410_ADCCON);
414 
415  dev_info(dev, "attached adc driver\n");
416 
417  platform_set_drvdata(pdev, adc);
418  adc_dev = adc;
419 
420  return 0;
421 
422  err_ioremap:
423  iounmap(adc->regs);
424  err_clk:
425  clk_put(adc->clk);
426 
427  err_irq:
428  free_irq(adc->irq, adc);
429  err_reg:
430  regulator_put(adc->vdd);
431  err_alloc:
432  kfree(adc);
433  return ret;
434 }
435 
436 static int __devexit s3c_adc_remove(struct platform_device *pdev)
437 {
438  struct adc_device *adc = platform_get_drvdata(pdev);
439 
440  iounmap(adc->regs);
441  free_irq(adc->irq, adc);
442  clk_disable(adc->clk);
443  regulator_disable(adc->vdd);
444  regulator_put(adc->vdd);
445  clk_put(adc->clk);
446  kfree(adc);
447 
448  return 0;
449 }
450 
451 #ifdef CONFIG_PM
452 static int s3c_adc_suspend(struct device *dev)
453 {
454  struct platform_device *pdev = container_of(dev,
455  struct platform_device, dev);
456  struct adc_device *adc = platform_get_drvdata(pdev);
457  unsigned long flags;
458  u32 con;
459 
460  spin_lock_irqsave(&adc->lock, flags);
461 
462  con = readl(adc->regs + S3C2410_ADCCON);
463  con |= S3C2410_ADCCON_STDBM;
464  writel(con, adc->regs + S3C2410_ADCCON);
465 
466  disable_irq(adc->irq);
467  spin_unlock_irqrestore(&adc->lock, flags);
468  clk_disable(adc->clk);
469  regulator_disable(adc->vdd);
470 
471  return 0;
472 }
473 
474 static int s3c_adc_resume(struct device *dev)
475 {
476  struct platform_device *pdev = container_of(dev,
477  struct platform_device, dev);
478  struct adc_device *adc = platform_get_drvdata(pdev);
479  enum s3c_cpu_type cpu = platform_get_device_id(pdev)->driver_data;
480  int ret;
481  unsigned long tmp;
482 
483  ret = regulator_enable(adc->vdd);
484  if (ret)
485  return ret;
486  clk_enable(adc->clk);
487  enable_irq(adc->irq);
488 
489  tmp = adc->prescale | S3C2410_ADCCON_PRSCEN;
490 
491  /* Enable 12-bit ADC resolution */
492  if (cpu == TYPE_ADCV12)
493  tmp |= S3C2416_ADCCON_RESSEL;
494  if (cpu == TYPE_ADCV2 || cpu == TYPE_ADCV3)
495  tmp |= S3C64XX_ADCCON_RESSEL;
496 
497  writel(tmp, adc->regs + S3C2410_ADCCON);
498 
499  return 0;
500 }
501 
502 #else
503 #define s3c_adc_suspend NULL
504 #define s3c_adc_resume NULL
505 #endif
506 
507 static struct platform_device_id s3c_adc_driver_ids[] = {
508  {
509  .name = "s3c24xx-adc",
510  .driver_data = TYPE_ADCV1,
511  }, {
512  .name = "s3c2443-adc",
513  .driver_data = TYPE_ADCV11,
514  }, {
515  .name = "s3c2416-adc",
516  .driver_data = TYPE_ADCV12,
517  }, {
518  .name = "s3c64xx-adc",
519  .driver_data = TYPE_ADCV2,
520  }, {
521  .name = "samsung-adc-v3",
522  .driver_data = TYPE_ADCV3,
523  },
524  { }
525 };
526 MODULE_DEVICE_TABLE(platform, s3c_adc_driver_ids);
527 
528 static const struct dev_pm_ops adc_pm_ops = {
529  .suspend = s3c_adc_suspend,
530  .resume = s3c_adc_resume,
531 };
532 
533 static struct platform_driver s3c_adc_driver = {
534  .id_table = s3c_adc_driver_ids,
535  .driver = {
536  .name = "s3c-adc",
537  .owner = THIS_MODULE,
538  .pm = &adc_pm_ops,
539  },
540  .probe = s3c_adc_probe,
541  .remove = __devexit_p(s3c_adc_remove),
542 };
543 
544 static int __init adc_init(void)
545 {
546  int ret;
547 
548  ret = platform_driver_register(&s3c_adc_driver);
549  if (ret)
550  printk(KERN_ERR "%s: failed to add adc driver\n", __func__);
551 
552  return ret;
553 }
554 
555 module_init(adc_init);