aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-samsung/adc.c
diff options
context:
space:
mode:
authorMyungJoo Ham <myungjoo.ham@samsung.com>2011-07-20 08:08:17 -0400
committerKukjin Kim <kgene.kim@samsung.com>2011-07-20 10:38:50 -0400
commitf462904ef1508c0a2cc22c65478a7be0cd89f47a (patch)
tree4e2181469a87c4ed89c6c2b95124a5592e4fd37f /arch/arm/plat-samsung/adc.c
parent56c03d91f7f44991870f3f79b3067d40249b7bb9 (diff)
ARM: SAMSUNG: use regulator VDD for ADC
This patch allows the Samsung ADC driver to enable VDD regulator at probe and resume and to disable at exit and suspend. In a platform where ADC's VDD regulator is not "always-on", this control is required although this patch does not provide fine-grained power control (turning on the regulator only when being accessed). However, if VDD regulator ("vdd" for the adc device) is not provided, the regulator control will not be activated because there are platforms that do not provide regulator for ADC device. arch_initcall has been modified to module_init in order to allow regulators to be available at probe. Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
Diffstat (limited to 'arch/arm/plat-samsung/adc.c')
-rw-r--r--arch/arm/plat-samsung/adc.c31
1 files changed, 27 insertions, 4 deletions
diff --git a/arch/arm/plat-samsung/adc.c b/arch/arm/plat-samsung/adc.c
index e8f2be2d67f2..2224128cc603 100644
--- a/arch/arm/plat-samsung/adc.c
+++ b/arch/arm/plat-samsung/adc.c
@@ -21,6 +21,7 @@
21#include <linux/clk.h> 21#include <linux/clk.h>
22#include <linux/interrupt.h> 22#include <linux/interrupt.h>
23#include <linux/io.h> 23#include <linux/io.h>
24#include <linux/regulator/consumer.h>
24 25
25#include <plat/regs-adc.h> 26#include <plat/regs-adc.h>
26#include <plat/adc.h> 27#include <plat/adc.h>
@@ -71,6 +72,7 @@ struct adc_device {
71 unsigned int prescale; 72 unsigned int prescale;
72 73
73 int irq; 74 int irq;
75 struct regulator *vdd;
74}; 76};
75 77
76static struct adc_device *adc_dev; 78static struct adc_device *adc_dev;
@@ -338,17 +340,24 @@ static int s3c_adc_probe(struct platform_device *pdev)
338 adc->pdev = pdev; 340 adc->pdev = pdev;
339 adc->prescale = S3C2410_ADCCON_PRSCVL(49); 341 adc->prescale = S3C2410_ADCCON_PRSCVL(49);
340 342
343 adc->vdd = regulator_get(dev, "vdd");
344 if (IS_ERR(adc->vdd)) {
345 dev_err(dev, "operating without regulator \"vdd\" .\n");
346 ret = PTR_ERR(adc->vdd);
347 goto err_alloc;
348 }
349
341 adc->irq = platform_get_irq(pdev, 1); 350 adc->irq = platform_get_irq(pdev, 1);
342 if (adc->irq <= 0) { 351 if (adc->irq <= 0) {
343 dev_err(dev, "failed to get adc irq\n"); 352 dev_err(dev, "failed to get adc irq\n");
344 ret = -ENOENT; 353 ret = -ENOENT;
345 goto err_alloc; 354 goto err_reg;
346 } 355 }
347 356
348 ret = request_irq(adc->irq, s3c_adc_irq, 0, dev_name(dev), adc); 357 ret = request_irq(adc->irq, s3c_adc_irq, 0, dev_name(dev), adc);
349 if (ret < 0) { 358 if (ret < 0) {
350 dev_err(dev, "failed to attach adc irq\n"); 359 dev_err(dev, "failed to attach adc irq\n");
351 goto err_alloc; 360 goto err_reg;
352 } 361 }
353 362
354 adc->clk = clk_get(dev, "adc"); 363 adc->clk = clk_get(dev, "adc");
@@ -372,6 +381,10 @@ static int s3c_adc_probe(struct platform_device *pdev)
372 goto err_clk; 381 goto err_clk;
373 } 382 }
374 383
384 ret = regulator_enable(adc->vdd);
385 if (ret)
386 goto err_ioremap;
387
375 clk_enable(adc->clk); 388 clk_enable(adc->clk);
376 389
377 tmp = adc->prescale | S3C2410_ADCCON_PRSCEN; 390 tmp = adc->prescale | S3C2410_ADCCON_PRSCEN;
@@ -388,12 +401,15 @@ static int s3c_adc_probe(struct platform_device *pdev)
388 401
389 return 0; 402 return 0;
390 403
404 err_ioremap:
405 iounmap(adc->regs);
391 err_clk: 406 err_clk:
392 clk_put(adc->clk); 407 clk_put(adc->clk);
393 408
394 err_irq: 409 err_irq:
395 free_irq(adc->irq, adc); 410 free_irq(adc->irq, adc);
396 411 err_reg:
412 regulator_put(adc->vdd);
397 err_alloc: 413 err_alloc:
398 kfree(adc); 414 kfree(adc);
399 return ret; 415 return ret;
@@ -406,6 +422,8 @@ static int __devexit s3c_adc_remove(struct platform_device *pdev)
406 iounmap(adc->regs); 422 iounmap(adc->regs);
407 free_irq(adc->irq, adc); 423 free_irq(adc->irq, adc);
408 clk_disable(adc->clk); 424 clk_disable(adc->clk);
425 regulator_disable(adc->vdd);
426 regulator_put(adc->vdd);
409 clk_put(adc->clk); 427 clk_put(adc->clk);
410 kfree(adc); 428 kfree(adc);
411 429
@@ -428,6 +446,7 @@ static int s3c_adc_suspend(struct platform_device *pdev, pm_message_t state)
428 disable_irq(adc->irq); 446 disable_irq(adc->irq);
429 spin_unlock_irqrestore(&adc->lock, flags); 447 spin_unlock_irqrestore(&adc->lock, flags);
430 clk_disable(adc->clk); 448 clk_disable(adc->clk);
449 regulator_disable(adc->vdd);
431 450
432 return 0; 451 return 0;
433} 452}
@@ -435,7 +454,11 @@ static int s3c_adc_suspend(struct platform_device *pdev, pm_message_t state)
435static int s3c_adc_resume(struct platform_device *pdev) 454static int s3c_adc_resume(struct platform_device *pdev)
436{ 455{
437 struct adc_device *adc = platform_get_drvdata(pdev); 456 struct adc_device *adc = platform_get_drvdata(pdev);
457 int ret;
438 458
459 ret = regulator_enable(adc->vdd);
460 if (ret)
461 return ret;
439 clk_enable(adc->clk); 462 clk_enable(adc->clk);
440 enable_irq(adc->irq); 463 enable_irq(adc->irq);
441 464
@@ -485,4 +508,4 @@ static int __init adc_init(void)
485 return ret; 508 return ret;
486} 509}
487 510
488arch_initcall(adc_init); 511module_init(adc_init);