2011-06-30 07:49:46

by MyungJoo Ham

[permalink] [raw]
Subject: [PATCH v3 0/6] Update Samsung-SoC ADC to support recent CPUs

Patch 1/6: Add regulator support in ADC driver.
If CONFIG_REGULATOR is enabled, "vdd" regulator for the ADC driver
(e.g., "s5p-adc") should exist for the adc driver.

Patch 2/6: Channel selection method for S5PC110 and Exynos4
Recent Samsung SoCs have different register addresses for
channel selection. Use "s5p-adc" to support such chips.

Patch 3/6: Bugfix for suspend/resume of ADC driver.

Patch 4/6: Support ADC at Exynos4
Define register addresses and device name for Exynos4

Patch 5/6: Support ADC at S5PC110/S5PV210
Correct ADC device name for S5PC110/S5PV210

Patch 6/6: Header file correction (plat/devs.h)
The long-overdue bugfix for compiler errors. ADC for Exynos4 fails to
be compiled without this patch.


MyungJoo Ham (6):
Samsung SoC ADC: use regulator (VDD for ADC).
Samsung SoC ADC: Channel selection for S5PV210, S5PC110, and Exynos4
Samsung SoC ADC: Revise PM for 12-bit ADC operations
ARM: EXYNOS4: Support ADC
ARM: S5PC110/S5PV210: Support ADC
Samsung SoC: header file revised to prevent declaring duplicated.

arch/arm/mach-exynos4/Kconfig | 1 +
arch/arm/mach-exynos4/cpu.c | 4 +
arch/arm/mach-exynos4/include/mach/irqs.h | 3 +
arch/arm/mach-exynos4/include/mach/map.h | 5 ++
arch/arm/mach-s5pv210/cpu.c | 2 +-
arch/arm/plat-samsung/adc.c | 84 +++++++++++++++++++------
arch/arm/plat-samsung/include/plat/devs.h | 5 ++
arch/arm/plat-samsung/include/plat/regs-adc.h | 1 +
8 files changed, 84 insertions(+), 21 deletions(-)

--
1.7.4.1


2011-06-30 07:50:04

by MyungJoo Ham

[permalink] [raw]
Subject: [PATCH v3 1/6] Samsung SoC ADC: 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 <[email protected]>
Signed-off-by: Kyungmin Park <[email protected]>

--
changed from v2 with valuable comments from Mark Brown.
- Bugfix on error handling
- Faster escape when error at resume function
changes from v1
- Removed macro defining the name of regulator.
- Handle error from regulator_enable.
- Do not allow not to have the regulator if CONFIG_REGULATOR.
- Seperate a patch dealing with "arch_initcall->module_init"
---
arch/arm/plat-samsung/adc.c | 31 +++++++++++++++++++++++++++----
1 files changed, 27 insertions(+), 4 deletions(-)

diff --git a/arch/arm/plat-samsung/adc.c b/arch/arm/plat-samsung/adc.c
index e8f2be2..2224128 100644
--- a/arch/arm/plat-samsung/adc.c
+++ b/arch/arm/plat-samsung/adc.c
@@ -21,6 +21,7 @@
#include <linux/clk.h>
#include <linux/interrupt.h>
#include <linux/io.h>
+#include <linux/regulator/consumer.h>

#include <plat/regs-adc.h>
#include <plat/adc.h>
@@ -71,6 +72,7 @@ struct adc_device {
unsigned int prescale;

int irq;
+ struct regulator *vdd;
};

static struct adc_device *adc_dev;
@@ -338,17 +340,24 @@ static int s3c_adc_probe(struct platform_device *pdev)
adc->pdev = pdev;
adc->prescale = S3C2410_ADCCON_PRSCVL(49);

+ adc->vdd = regulator_get(dev, "vdd");
+ if (IS_ERR(adc->vdd)) {
+ dev_err(dev, "operating without regulator \"vdd\" .\n");
+ ret = PTR_ERR(adc->vdd);
+ goto err_alloc;
+ }
+
adc->irq = platform_get_irq(pdev, 1);
if (adc->irq <= 0) {
dev_err(dev, "failed to get adc irq\n");
ret = -ENOENT;
- goto err_alloc;
+ goto err_reg;
}

ret = request_irq(adc->irq, s3c_adc_irq, 0, dev_name(dev), adc);
if (ret < 0) {
dev_err(dev, "failed to attach adc irq\n");
- goto err_alloc;
+ goto err_reg;
}

adc->clk = clk_get(dev, "adc");
@@ -372,6 +381,10 @@ static int s3c_adc_probe(struct platform_device *pdev)
goto err_clk;
}

+ ret = regulator_enable(adc->vdd);
+ if (ret)
+ goto err_ioremap;
+
clk_enable(adc->clk);

tmp = adc->prescale | S3C2410_ADCCON_PRSCEN;
@@ -388,12 +401,15 @@ static int s3c_adc_probe(struct platform_device *pdev)

return 0;

+ err_ioremap:
+ iounmap(adc->regs);
err_clk:
clk_put(adc->clk);

err_irq:
free_irq(adc->irq, adc);
-
+ err_reg:
+ regulator_put(adc->vdd);
err_alloc:
kfree(adc);
return ret;
@@ -406,6 +422,8 @@ static int __devexit s3c_adc_remove(struct platform_device *pdev)
iounmap(adc->regs);
free_irq(adc->irq, adc);
clk_disable(adc->clk);
+ regulator_disable(adc->vdd);
+ regulator_put(adc->vdd);
clk_put(adc->clk);
kfree(adc);

@@ -428,6 +446,7 @@ static int s3c_adc_suspend(struct platform_device *pdev, pm_message_t state)
disable_irq(adc->irq);
spin_unlock_irqrestore(&adc->lock, flags);
clk_disable(adc->clk);
+ regulator_disable(adc->vdd);

return 0;
}
@@ -435,7 +454,11 @@ static int s3c_adc_suspend(struct platform_device *pdev, pm_message_t state)
static int s3c_adc_resume(struct platform_device *pdev)
{
struct adc_device *adc = platform_get_drvdata(pdev);
+ int ret;

+ ret = regulator_enable(adc->vdd);
+ if (ret)
+ return ret;
clk_enable(adc->clk);
enable_irq(adc->irq);

@@ -485,4 +508,4 @@ static int __init adc_init(void)
return ret;
}

-arch_initcall(adc_init);
+module_init(adc_init);
--
1.7.4.1

2011-06-30 07:49:56

by MyungJoo Ham

[permalink] [raw]
Subject: [PATCH v3 2/6] Samsung SoC ADC: Channel selection for S5PV210, S5PC110, and Exynos4

In S5PV210/S5PC110/Exynos4, ADCMUX channel selection uses ADCMUX
register, not ADCCON register. This patch corrects the behavior of
Samsung-ADC for such cpus.

Signed-off-by: MyungJoo Ham <[email protected]>
Signed-off-by: Kyungmin Park <[email protected]>
--
updates from v2
- Renamed internal device names.
---
arch/arm/plat-samsung/adc.c | 29 ++++++++++++++++--------
arch/arm/plat-samsung/include/plat/regs-adc.h | 1 +
2 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/arch/arm/plat-samsung/adc.c b/arch/arm/plat-samsung/adc.c
index 2224128..45cc7e6 100644
--- a/arch/arm/plat-samsung/adc.c
+++ b/arch/arm/plat-samsung/adc.c
@@ -40,8 +40,9 @@
*/

enum s3c_cpu_type {
- TYPE_S3C24XX,
- TYPE_S3C64XX
+ TYPE_ADCV1, /* S3C24XX */
+ TYPE_ADCV2, /* S3C64XX, S5P64X0, S5PC100 */
+ TYPE_ADCV3, /* S5PV210, S5PC110, EXYNOS4210 */
};

struct s3c_adc_client {
@@ -93,6 +94,7 @@ static inline void s3c_adc_select(struct adc_device *adc,
struct s3c_adc_client *client)
{
unsigned con = readl(adc->regs + S3C2410_ADCCON);
+ enum s3c_cpu_type cpu = platform_get_device_id(adc->pdev)->driver_data;

client->select_cb(client, 1);

@@ -100,8 +102,12 @@ static inline void s3c_adc_select(struct adc_device *adc,
con &= ~S3C2410_ADCCON_STDBM;
con &= ~S3C2410_ADCCON_STARTMASK;

- if (!client->is_ts)
- con |= S3C2410_ADCCON_SELMUX(client->channel);
+ if (!client->is_ts) {
+ if (cpu == TYPE_ADCV3)
+ writel(client->channel & 0xf, adc->regs + S5P_ADCMUX);
+ else
+ con |= S3C2410_ADCCON_SELMUX(client->channel);
+ }

writel(con, adc->regs + S3C2410_ADCCON);
}
@@ -287,8 +293,8 @@ static irqreturn_t s3c_adc_irq(int irq, void *pw)

client->nr_samples--;

- if (cpu == TYPE_S3C64XX) {
- /* S3C64XX ADC resolution is 12-bit */
+ if (cpu != TYPE_ADCV1) {
+ /* S3C64XX/S5P ADC resolution is 12-bit */
data0 &= 0xfff;
data1 &= 0xfff;
} else {
@@ -314,7 +320,7 @@ static irqreturn_t s3c_adc_irq(int irq, void *pw)
}

exit:
- if (cpu == TYPE_S3C64XX) {
+ if (cpu != TYPE_ADCV1) {
/* Clear ADC interrupt */
writel(0, adc->regs + S3C64XX_ADCCLRINT);
}
@@ -388,7 +394,7 @@ static int s3c_adc_probe(struct platform_device *pdev)
clk_enable(adc->clk);

tmp = adc->prescale | S3C2410_ADCCON_PRSCEN;
- if (platform_get_device_id(pdev)->driver_data == TYPE_S3C64XX) {
+ if (platform_get_device_id(pdev)->driver_data != TYPE_ADCV1) {
/* Enable 12-bit ADC resolution */
tmp |= S3C64XX_ADCCON_RESSEL;
}
@@ -476,10 +482,13 @@ static int s3c_adc_resume(struct platform_device *pdev)
static struct platform_device_id s3c_adc_driver_ids[] = {
{
.name = "s3c24xx-adc",
- .driver_data = TYPE_S3C24XX,
+ .driver_data = TYPE_ADCV1,
}, {
.name = "s3c64xx-adc",
- .driver_data = TYPE_S3C64XX,
+ .driver_data = TYPE_ADCV2,
+ }, {
+ .name = "samsung-adc-v3",
+ .driver_data = TYPE_ADCV3,
},
{ }
};
diff --git a/arch/arm/plat-samsung/include/plat/regs-adc.h b/arch/arm/plat-samsung/include/plat/regs-adc.h
index 7554c4f..035e8c3 100644
--- a/arch/arm/plat-samsung/include/plat/regs-adc.h
+++ b/arch/arm/plat-samsung/include/plat/regs-adc.h
@@ -21,6 +21,7 @@
#define S3C2410_ADCDAT1 S3C2410_ADCREG(0x10)
#define S3C64XX_ADCUPDN S3C2410_ADCREG(0x14)
#define S3C64XX_ADCCLRINT S3C2410_ADCREG(0x18)
+#define S5P_ADCMUX S3C2410_ADCREG(0x1C)
#define S3C64XX_ADCCLRINTPNDNUP S3C2410_ADCREG(0x20)


--
1.7.4.1

2011-06-30 07:50:17

by MyungJoo Ham

[permalink] [raw]
Subject: [PATCH v3 3/6] Samsung SoC ADC: Revise PM for 12-bit ADC operations

- Fixed: 12bit precision is lost at suspend/resume
- Updated: use pm_dev_ops

Signed-off-by: MyungJoo Ham <[email protected]>
Signed-off-by: Kyungmin Park <[email protected]>
---
arch/arm/plat-samsung/adc.c | 24 ++++++++++++++++++------
1 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/arch/arm/plat-samsung/adc.c b/arch/arm/plat-samsung/adc.c
index 45cc7e6..ee8deef 100644
--- a/arch/arm/plat-samsung/adc.c
+++ b/arch/arm/plat-samsung/adc.c
@@ -437,8 +437,10 @@ static int __devexit s3c_adc_remove(struct platform_device *pdev)
}

#ifdef CONFIG_PM
-static int s3c_adc_suspend(struct platform_device *pdev, pm_message_t state)
+static int s3c_adc_suspend(struct device *dev)
{
+ struct platform_device *pdev = container_of(dev,
+ struct platform_device, dev);
struct adc_device *adc = platform_get_drvdata(pdev);
unsigned long flags;
u32 con;
@@ -457,10 +459,13 @@ static int s3c_adc_suspend(struct platform_device *pdev, pm_message_t state)
return 0;
}

-static int s3c_adc_resume(struct platform_device *pdev)
+static int s3c_adc_resume(struct device *dev)
{
+ struct platform_device *pdev = container_of(dev,
+ struct platform_device, dev);
struct adc_device *adc = platform_get_drvdata(pdev);
int ret;
+ unsigned long tmp;

ret = regulator_enable(adc->vdd);
if (ret)
@@ -468,8 +473,11 @@ static int s3c_adc_resume(struct platform_device *pdev)
clk_enable(adc->clk);
enable_irq(adc->irq);

- writel(adc->prescale | S3C2410_ADCCON_PRSCEN,
- adc->regs + S3C2410_ADCCON);
+ tmp = adc->prescale | S3C2410_ADCCON_PRSCEN;
+ /* Enable 12-bit ADC resolution */
+ if (platform_get_device_id(pdev)->driver_data != TYPE_ADCV1)
+ tmp |= S3C64XX_ADCCON_RESSEL;
+ writel(tmp, adc->regs + S3C2410_ADCCON);

return 0;
}
@@ -494,16 +502,20 @@ static struct platform_device_id s3c_adc_driver_ids[] = {
};
MODULE_DEVICE_TABLE(platform, s3c_adc_driver_ids);

+static const struct dev_pm_ops adc_pm_ops = {
+ .suspend = s3c_adc_suspend,
+ .resume = s3c_adc_resume,
+};
+
static struct platform_driver s3c_adc_driver = {
.id_table = s3c_adc_driver_ids,
.driver = {
.name = "s3c-adc",
.owner = THIS_MODULE,
+ .pm = &adc_pm_ops,
},
.probe = s3c_adc_probe,
.remove = __devexit_p(s3c_adc_remove),
- .suspend = s3c_adc_suspend,
- .resume = s3c_adc_resume,
};

static int __init adc_init(void)
--
1.7.4.1

2011-06-30 07:50:10

by MyungJoo Ham

[permalink] [raw]
Subject: [PATCH v3 4/6] ARM: EXYNOS4: Support ADC

Signed-off-by: MyungJoo Ham <[email protected]>
Signed-off-by: Kyungmin Park <[email protected]>
--
Updates from v2
- Based on EXT_GIC patches from Changhwan Youn (ARM: EXYNOS4: Adds
External GIC)
---
arch/arm/mach-exynos4/Kconfig | 1 +
arch/arm/mach-exynos4/cpu.c | 4 ++++
arch/arm/mach-exynos4/include/mach/irqs.h | 3 +++
arch/arm/mach-exynos4/include/mach/map.h | 5 +++++
4 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-exynos4/Kconfig b/arch/arm/mach-exynos4/Kconfig
index 0aca083..80f4fbe 100644
--- a/arch/arm/mach-exynos4/Kconfig
+++ b/arch/arm/mach-exynos4/Kconfig
@@ -184,6 +184,7 @@ config MACH_NURI
select EXYNOS4_SETUP_SDHCI
select EXYNOS4_SETUP_USB_PHY
select SAMSUNG_DEV_PWM
+ select SAMSUNG_DEV_ADC
help
Machine support for Samsung Mobile NURI Board.

diff --git a/arch/arm/mach-exynos4/cpu.c b/arch/arm/mach-exynos4/cpu.c
index 5423ed8..7ffa81d 100644
--- a/arch/arm/mach-exynos4/cpu.c
+++ b/arch/arm/mach-exynos4/cpu.c
@@ -21,7 +21,9 @@

#include <plat/cpu.h>
#include <plat/clock.h>
+#include <plat/devs.h>
#include <plat/exynos4.h>
+#include <plat/adc-core.h>
#include <plat/sdhci.h>
#include <plat/devs.h>
#include <plat/fimc-core.h>
@@ -141,6 +143,8 @@ void __init exynos4_map_io(void)
exynos4_default_sdhci2();
exynos4_default_sdhci3();

+ s3c_adc_setname("samsung-adc-v3");
+
s3c_fimc_setname(0, "exynos4-fimc");
s3c_fimc_setname(1, "exynos4-fimc");
s3c_fimc_setname(2, "exynos4-fimc");
diff --git a/arch/arm/mach-exynos4/include/mach/irqs.h b/arch/arm/mach-exynos4/include/mach/irqs.h
index 250427f..31f6bed 100644
--- a/arch/arm/mach-exynos4/include/mach/irqs.h
+++ b/arch/arm/mach-exynos4/include/mach/irqs.h
@@ -139,6 +139,9 @@

#define MAX_COMBINER_NR 16

+#define IRQ_ADC IRQ_ADC0
+#define IRQ_TC IRQ_PEN0
+
#define S5P_IRQ_EINT_BASE COMBINER_IRQ(MAX_COMBINER_NR, 0)

#define S5P_EINT_BASE1 (S5P_IRQ_EINT_BASE + 0)
diff --git a/arch/arm/mach-exynos4/include/mach/map.h b/arch/arm/mach-exynos4/include/mach/map.h
index e4b5c79..e03e820 100644
--- a/arch/arm/mach-exynos4/include/mach/map.h
+++ b/arch/arm/mach-exynos4/include/mach/map.h
@@ -110,6 +110,9 @@

#define EXYNOS4_PA_IIC(x) (0x13860000 + ((x) * 0x10000))

+#define EXYNOS4_PA_ADC 0x13910000
+#define EXYNOS4_PA_ADC1 0x13911000
+
#define EXYNOS4_PA_AC97 0x139A0000

#define EXYNOS4_PA_SPDIF 0x139B0000
@@ -132,6 +135,8 @@
#define S3C_PA_IIC5 EXYNOS4_PA_IIC(5)
#define S3C_PA_IIC6 EXYNOS4_PA_IIC(6)
#define S3C_PA_IIC7 EXYNOS4_PA_IIC(7)
+#define SAMSUNG_PA_ADC EXYNOS4_PA_ADC
+#define SAMSUNG_PA_ADC1 EXYNOS4_PA_ADC1
#define S3C_PA_RTC EXYNOS4_PA_RTC
#define S3C_PA_WDT EXYNOS4_PA_WATCHDOG

--
1.7.4.1

2011-06-30 07:50:21

by MyungJoo Ham

[permalink] [raw]
Subject: [PATCH v3 5/6] ARM: S5PC110/S5PV210: Support ADC

Signed-off-by: MyungJoo Ham <[email protected]>
Signed-off-by: Kyungmin Park <[email protected]>
---
arch/arm/mach-s5pv210/cpu.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-s5pv210/cpu.c b/arch/arm/mach-s5pv210/cpu.c
index 61e6c24..79907ec 100644
--- a/arch/arm/mach-s5pv210/cpu.c
+++ b/arch/arm/mach-s5pv210/cpu.c
@@ -126,7 +126,7 @@ void __init s5pv210_map_io(void)
s5pv210_default_sdhci2();
s5pv210_default_sdhci3();

- s3c_adc_setname("s3c64xx-adc");
+ s3c_adc_setname("samsung-adc-v3");

s3c_cfcon_setname("s5pv210-pata");

--
1.7.4.1

2011-06-30 07:50:26

by MyungJoo Ham

[permalink] [raw]
Subject: [PATCH v3 6/6] Samsung SoC: header file revised to prevent declaring duplicated.

There has been no #ifndef - #define - #endif protection for this header
file. The patch adds it for Exynos4-ADC support

Signed-off-by: MyungJoo Ham <[email protected]>
---
arch/arm/plat-samsung/include/plat/devs.h | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h
index 4af108f..3c87779 100644
--- a/arch/arm/plat-samsung/include/plat/devs.h
+++ b/arch/arm/plat-samsung/include/plat/devs.h
@@ -12,6 +12,9 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
+#ifndef __PLAT_DEVS_H
+#define __PLAT_DEVS_H __FILE__
+
#include <linux/platform_device.h>

struct s3c24xx_uart_resources {
@@ -159,3 +162,5 @@ extern struct platform_device s3c_device_ac97;
*/
extern void *s3c_set_platdata(void *pd, size_t pdsize,
struct platform_device *pdev);
+
+#endif /* __PLAT_DEVS_H */
--
1.7.4.1

2011-06-30 08:24:10

by Vasily Khoruzhick

[permalink] [raw]
Subject: Re: [PATCH v3 1/6] Samsung SoC ADC: use regulator (VDD for ADC).

On Thursday 30 June 2011 10:49:30 MyungJoo Ham wrote:
> 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 <[email protected]>
> Signed-off-by: Kyungmin Park <[email protected]>


> --
> changed from v2 with valuable comments from Mark Brown.
> - Bugfix on error handling
> - Faster escape when error at resume function
> changes from v1
> - Removed macro defining the name of regulator.
> - Handle error from regulator_enable.
> - Do not allow not to have the regulator if CONFIG_REGULATOR.
> - Seperate a patch dealing with "arch_initcall->module_init"
> ---
> arch/arm/plat-samsung/adc.c | 31 +++++++++++++++++++++++++++----
> 1 files changed, 27 insertions(+), 4 deletions(-)
>
> diff --git a/arch/arm/plat-samsung/adc.c b/arch/arm/plat-samsung/adc.c
> index e8f2be2..2224128 100644
> --- a/arch/arm/plat-samsung/adc.c
> +++ b/arch/arm/plat-samsung/adc.c
> @@ -21,6 +21,7 @@
> #include <linux/clk.h>
> #include <linux/interrupt.h>
> #include <linux/io.h>
> +#include <linux/regulator/consumer.h>
>
> #include <plat/regs-adc.h>
> #include <plat/adc.h>
> @@ -71,6 +72,7 @@ struct adc_device {
> unsigned int prescale;
>
> int irq;
> + struct regulator *vdd;
> };
>
> static struct adc_device *adc_dev;
> @@ -338,17 +340,24 @@ static int s3c_adc_probe(struct platform_device
> *pdev) adc->pdev = pdev;
> adc->prescale = S3C2410_ADCCON_PRSCVL(49);
>
> + adc->vdd = regulator_get(dev, "vdd");
> + if (IS_ERR(adc->vdd)) {
> + dev_err(dev, "operating without regulator \"vdd\" .\n");
> + ret = PTR_ERR(adc->vdd);
> + goto err_alloc;
> + }
> +

NACK. Make it optional, otherwise it breaks s3c24xx.

> adc->irq = platform_get_irq(pdev, 1);
> if (adc->irq <= 0) {
> dev_err(dev, "failed to get adc irq\n");
> ret = -ENOENT;
> - goto err_alloc;
> + goto err_reg;
> }
>
> ret = request_irq(adc->irq, s3c_adc_irq, 0, dev_name(dev), adc);
> if (ret < 0) {
> dev_err(dev, "failed to attach adc irq\n");
> - goto err_alloc;
> + goto err_reg;
> }
>
> adc->clk = clk_get(dev, "adc");
> @@ -372,6 +381,10 @@ static int s3c_adc_probe(struct platform_device *pdev)
> goto err_clk;
> }
>
> + ret = regulator_enable(adc->vdd);
> + if (ret)
> + goto err_ioremap;
> +
> clk_enable(adc->clk);
>
> tmp = adc->prescale | S3C2410_ADCCON_PRSCEN;
> @@ -388,12 +401,15 @@ static int s3c_adc_probe(struct platform_device
> *pdev)
>
> return 0;
>
> + err_ioremap:
> + iounmap(adc->regs);
> err_clk:
> clk_put(adc->clk);
>
> err_irq:
> free_irq(adc->irq, adc);
> -
> + err_reg:
> + regulator_put(adc->vdd);
> err_alloc:
> kfree(adc);
> return ret;
> @@ -406,6 +422,8 @@ static int __devexit s3c_adc_remove(struct
> platform_device *pdev) iounmap(adc->regs);
> free_irq(adc->irq, adc);
> clk_disable(adc->clk);
> + regulator_disable(adc->vdd);
> + regulator_put(adc->vdd);
> clk_put(adc->clk);
> kfree(adc);
>
> @@ -428,6 +446,7 @@ static int s3c_adc_suspend(struct platform_device
> *pdev, pm_message_t state) disable_irq(adc->irq);
> spin_unlock_irqrestore(&adc->lock, flags);
> clk_disable(adc->clk);
> + regulator_disable(adc->vdd);
>
> return 0;
> }
> @@ -435,7 +454,11 @@ static int s3c_adc_suspend(struct platform_device
> *pdev, pm_message_t state) static int s3c_adc_resume(struct
> platform_device *pdev)
> {
> struct adc_device *adc = platform_get_drvdata(pdev);
> + int ret;
>
> + ret = regulator_enable(adc->vdd);
> + if (ret)
> + return ret;
> clk_enable(adc->clk);
> enable_irq(adc->irq);
>
> @@ -485,4 +508,4 @@ static int __init adc_init(void)
> return ret;
> }
>
> -arch_initcall(adc_init);
> +module_init(adc_init);

2011-06-30 09:03:16

by MyungJoo Ham

[permalink] [raw]
Subject: Re: [PATCH v3 1/6] Samsung SoC ADC: use regulator (VDD for ADC).

On Thu, Jun 30, 2011 at 5:22 PM, Vasily Khoruzhick <[email protected]> wrote:
> On Thursday 30 June 2011 10:49:30 MyungJoo Ham wrote:
>> 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 <[email protected]>
>> Signed-off-by: Kyungmin Park <[email protected]>
[]
>> + ? ? adc->vdd = regulator_get(dev, "vdd");
>> + ? ? if (IS_ERR(adc->vdd)) {
>> + ? ? ? ? ? ? dev_err(dev, "operating without regulator \"vdd\" .\n");
>> + ? ? ? ? ? ? ret = PTR_ERR(adc->vdd);
>> + ? ? ? ? ? ? goto err_alloc;
>> + ? ? }
>> +
>
> NACK. Make it optional, otherwise it breaks s3c24xx.
>

Ok. Now, I've got the issue I've worried in the previous patch revision.

Anyway, Mark once stated:
--- quote starts ---
On Sun, Jun 19, 2011 at 12:06 AM, Mark Brown
<[email protected]> wrote:
>> + if (IS_ERR_OR_NULL(adc->vdd)) {
>> + dev_dbg(dev, "operating without regulator %s.\n", S3C_ADC_REGULATOR_NAME);
>> + adc->vdd = NULL; /* Do not control regulator */
>> + }
>> +
>
> No, don't do this. Just unconditionally assume the regulator is present
> if power is essential for use of the device. The regulator API will
> stub out correctly if it's not in use to allow things to proceed and if
> vdd is genuinely not hooked up then the driver can't function.
--- quote ends ---

Then, how about unconditionally using ADC VDD for TYPE_ADCV3
(S5PC110/S5PV210/Exynos4210) and forget VDD for older ADC types?


Thanks.

- MyungJoo
--
MyungJoo Ham, Ph.D.
Mobile Software Platform Lab,
Digital Media and Communications (DMC) Business
Samsung Electronics
cell: 82-10-6714-2858

2011-06-30 16:05:09

by Mark Brown

[permalink] [raw]
Subject: Re: [PATCH v3 1/6] Samsung SoC ADC: use regulator (VDD for ADC).

On Thu, Jun 30, 2011 at 11:22:50AM +0300, Vasily Khoruzhick wrote:
> On Thursday 30 June 2011 10:49:30 MyungJoo Ham wrote:

> > + adc->vdd = regulator_get(dev, "vdd");
> > + if (IS_ERR(adc->vdd)) {
> > + dev_err(dev, "operating without regulator \"vdd\" .\n");
> > + ret = PTR_ERR(adc->vdd);
> > + goto err_alloc;
> > + }
> > +

> NACK. Make it optional, otherwise it breaks s3c24xx.

No, the above code is how the regulator API should be used. The API
will stub itself out if not in use so unless the s3c24xx platforms are
using regulators and there's a couple of options in the regulator API
for handling partially defined hookups of regulators on the board.

If there isn't a separate supply for the regulators on S3C24xx devices
then I guess the best option is to provide that supply as a dummy
regulator in the s3c24xx core code.