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.
Signed-off-by: MyungJoo Ham <[email protected]>
Signed-off-by: Kyungmin Park <[email protected]>
---
arch/arm/plat-samsung/adc.c | 20 +++++++++++++++++++-
1 files changed, 19 insertions(+), 1 deletions(-)
diff --git a/arch/arm/plat-samsung/adc.c b/arch/arm/plat-samsung/adc.c
index e8f2be2..a8499d8 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>
@@ -59,6 +60,8 @@ struct s3c_adc_client {
unsigned *samples_left);
};
+#define S3C_ADC_REGULATOR_NAME "vdd"
+
struct adc_device {
struct platform_device *pdev;
struct platform_device *owner;
@@ -71,6 +74,7 @@ struct adc_device {
unsigned int prescale;
int irq;
+ struct regulator *vdd;
};
static struct adc_device *adc_dev;
@@ -338,6 +342,12 @@ static int s3c_adc_probe(struct platform_device *pdev)
adc->pdev = pdev;
adc->prescale = S3C2410_ADCCON_PRSCVL(49);
+ adc->vdd = regulator_get(dev, S3C_ADC_REGULATOR_NAME);
+ 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 */
+ }
+
adc->irq = platform_get_irq(pdev, 1);
if (adc->irq <= 0) {
dev_err(dev, "failed to get adc irq\n");
@@ -372,6 +382,8 @@ static int s3c_adc_probe(struct platform_device *pdev)
goto err_clk;
}
+ if (adc->vdd)
+ regulator_enable(adc->vdd);
clk_enable(adc->clk);
tmp = adc->prescale | S3C2410_ADCCON_PRSCEN;
@@ -406,6 +418,8 @@ static int __devexit s3c_adc_remove(struct platform_device *pdev)
iounmap(adc->regs);
free_irq(adc->irq, adc);
clk_disable(adc->clk);
+ if (adc->vdd)
+ regulator_disable(adc->vdd);
clk_put(adc->clk);
kfree(adc);
@@ -428,6 +442,8 @@ 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);
+ if (adc->vdd)
+ regulator_disable(adc->vdd);
return 0;
}
@@ -436,6 +452,8 @@ static int s3c_adc_resume(struct platform_device *pdev)
{
struct adc_device *adc = platform_get_drvdata(pdev);
+ if (adc->vdd)
+ regulator_enable(adc->vdd);
clk_enable(adc->clk);
enable_irq(adc->irq);
@@ -485,4 +503,4 @@ static int __init adc_init(void)
return ret;
}
-arch_initcall(adc_init);
+module_init(adc_init);
--
1.7.4.1
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]>
---
arch/arm/plat-samsung/adc.c | 24 +++++++++++++++++-------
1 files changed, 17 insertions(+), 7 deletions(-)
diff --git a/arch/arm/plat-samsung/adc.c b/arch/arm/plat-samsung/adc.c
index a8499d8..7895819 100644
--- a/arch/arm/plat-samsung/adc.c
+++ b/arch/arm/plat-samsung/adc.c
@@ -41,8 +41,10 @@
enum s3c_cpu_type {
TYPE_S3C24XX,
- TYPE_S3C64XX
+ TYPE_S3C64XX,
+ TYPE_S5P,
};
+#define S3C64XX_OR_LATER(type) ((type) == TYPE_S3C64XX || (type) == TYPE_S5P)
struct s3c_adc_client {
struct platform_device *pdev;
@@ -95,6 +97,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);
@@ -102,8 +105,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_S5P)
+ writel(client->channel & 0xf, adc->regs + S5P_ADCMUX);
+ else
+ con |= S3C2410_ADCCON_SELMUX(client->channel);
+ }
writel(con, adc->regs + S3C2410_ADCCON);
}
@@ -289,8 +296,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 (S3C64XX_OR_LATER(cpu)) {
+ /* S3C64XX/S5P ADC resolution is 12-bit */
data0 &= 0xfff;
data1 &= 0xfff;
} else {
@@ -316,7 +323,7 @@ static irqreturn_t s3c_adc_irq(int irq, void *pw)
}
exit:
- if (cpu == TYPE_S3C64XX) {
+ if (S3C64XX_OR_LATER(cpu)) {
/* Clear ADC interrupt */
writel(0, adc->regs + S3C64XX_ADCCLRINT);
}
@@ -387,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 (S3C64XX_OR_LATER(platform_get_device_id(pdev)->driver_data)) {
/* Enable 12-bit ADC resolution */
tmp |= S3C64XX_ADCCON_RESSEL;
}
@@ -475,6 +482,9 @@ static struct platform_device_id s3c_adc_driver_ids[] = {
}, {
.name = "s3c64xx-adc",
.driver_data = TYPE_S3C64XX,
+ }, {
+ .name = "s5p-adc",
+ .driver_data = TYPE_S5P,
},
{ }
};
--
1.7.4.1
ADCMUX register is added.
Signed-off-by: MyungJoo Ham <[email protected]>
Signed-off-by: Kyungmin Park <[email protected]>
---
arch/arm/plat-samsung/include/plat/regs-adc.h | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
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
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
On Thu, Jun 16, 2011 at 05:30:02PM +0900, MyungJoo Ham wrote:
> + adc->vdd = regulator_get(dev, S3C_ADC_REGULATOR_NAME);
I'm not convinced that the #define for the name is terribly good style
here, especially given that you actually call it vdd in the code.
> + 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.
> + if (adc->vdd)
> + regulator_enable(adc->vdd);
You're not checking the return value here or anywhere else after the
inital get().
Hello,
On Sun, Jun 19, 2011 at 12:06 AM, Mark Brown
<[email protected]> wrote:
> On Thu, Jun 16, 2011 at 05:30:02PM +0900, MyungJoo Ham wrote:
>
>> + adc->vdd = regulator_get(dev, S3C_ADC_REGULATOR_NAME);
>
> I'm not convinced that the #define for the name is terribly good style
> here, especially given that you actually call it vdd in the code.
Then, would it be fine to use as [ regulator_get(dev, "vdd"); ] ?
>
>> + 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.
This ADC driver is for every ADC from S3C24xx series to Exynos4 (and
its successors as well).
The regulator (VDD for ADC) is essential for the recent chips
(S5PC110, S5PV210, and Exynos4).
I was just worried about the old boards using the same ADC driver
(mach-s3c2410/mach-*.c, mach-s3c6410/mach-*.c, and so on) without
ADC-VDD regulators defined.
However, no s3c compliance defconfigs have ever used CONFIG_REGULATOR.
Thus, it seems that it's safe to enforce using "vdd" with regulators
in plat-samsung's ADC driver.
I'll proceed as you have commented.
>
>> + if (adc->vdd)
>> + regulator_enable(adc->vdd);
>
> You're not checking the return value here or anywhere else after the
> inital get().
>
Ok. I'll let it handle errors from regulator_enable.
Thank you!
- MyungJoo.
--
MyungJoo Ham (함명주), Ph.D.
Mobile Software Platform Lab,
Digital Media and Communications (DMC) Business
Samsung Electronics
cell: 82-10-6714-2858
On Mon, Jun 20, 2011 at 02:16:59PM +0900, MyungJoo Ham wrote:
> On Sun, Jun 19, 2011 at 12:06 AM, Mark Brown
> > On Thu, Jun 16, 2011 at 05:30:02PM +0900, MyungJoo Ham wrote:
> >> + ? ? adc->vdd = regulator_get(dev, S3C_ADC_REGULATOR_NAME);
> > I'm not convinced that the #define for the name is terribly good style
> > here, especially given that you actually call it vdd in the code.
> Then, would it be fine to use as [ regulator_get(dev, "vdd"); ] ?
Yes.
> >> + ? ? 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.
> This ADC driver is for every ADC from S3C24xx series to Exynos4 (and
> its successors as well).
> The regulator (VDD for ADC) is essential for the recent chips
> (S5PC110, S5PV210, and Exynos4).
> I was just worried about the old boards using the same ADC driver
> (mach-s3c2410/mach-*.c, mach-s3c6410/mach-*.c, and so on) without
> ADC-VDD regulators defined.
If the regulator API is in use on a system it is reasonable to expect it
to be set up correctly for the system.
> However, no s3c compliance defconfigs have ever used CONFIG_REGULATOR.
> Thus, it seems that it's safe to enforce using "vdd" with regulators
> in plat-samsung's ADC driver.
> I'll proceed as you have commented.
Note that SMDK6410 and Cragganmore are both using regulators fairly
extensively.
Patch 1/5: 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/5: 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/5: Support ADC at Exynos4
Define register addresses and device name for Exynos4
Patch 4/5: Support ADC at S5PC110/S5PV210
Correct ADC device name for S5PC110/S5PV210
Patch 5/5: 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 (5):
Samsung SoC ADC: use regulator (VDD for ADC).
Samsung SoC ADC: Channel selection for S5PV210, S5PC110, and Exynos4
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 | 8 ++++
arch/arm/mach-exynos4/include/mach/map.h | 5 ++
arch/arm/mach-s5pv210/cpu.c | 2 +-
arch/arm/plat-samsung/adc.c | 55 +++++++++++++++++++-----
arch/arm/plat-samsung/include/plat/devs.h | 5 ++
arch/arm/plat-samsung/include/plat/regs-adc.h | 1 +
8 files changed, 68 insertions(+), 13 deletions(-)
--
1.7.4.1
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]>
--
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, 26 insertions(+), 5 deletions(-)
diff --git a/arch/arm/plat-samsung/adc.c b/arch/arm/plat-samsung/adc.c
index e8f2be2..938f6e9 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,14 +454,16 @@ 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);
clk_enable(adc->clk);
enable_irq(adc->irq);
writel(adc->prescale | S3C2410_ADCCON_PRSCEN,
adc->regs + S3C2410_ADCCON);
- return 0;
+ return ret;
}
#else
@@ -485,4 +506,4 @@ static int __init adc_init(void)
return ret;
}
-arch_initcall(adc_init);
+module_init(adc_init);
--
1.7.4.1
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]>
--
v2: No changes from v1. Resubmitted as a series of patches
---
arch/arm/plat-samsung/adc.c | 24 +++++++++++++++++-------
arch/arm/plat-samsung/include/plat/regs-adc.h | 1 +
2 files changed, 18 insertions(+), 7 deletions(-)
diff --git a/arch/arm/plat-samsung/adc.c b/arch/arm/plat-samsung/adc.c
index 938f6e9..0233c69 100644
--- a/arch/arm/plat-samsung/adc.c
+++ b/arch/arm/plat-samsung/adc.c
@@ -41,8 +41,10 @@
enum s3c_cpu_type {
TYPE_S3C24XX,
- TYPE_S3C64XX
+ TYPE_S3C64XX,
+ TYPE_S5P,
};
+#define S3C64XX_OR_LATER(type) ((type) == TYPE_S3C64XX || (type) == TYPE_S5P)
struct s3c_adc_client {
struct platform_device *pdev;
@@ -93,6 +95,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 +103,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_S5P)
+ writel(client->channel & 0xf, adc->regs + S5P_ADCMUX);
+ else
+ con |= S3C2410_ADCCON_SELMUX(client->channel);
+ }
writel(con, adc->regs + S3C2410_ADCCON);
}
@@ -287,8 +294,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 (S3C64XX_OR_LATER(cpu)) {
+ /* S3C64XX/S5P ADC resolution is 12-bit */
data0 &= 0xfff;
data1 &= 0xfff;
} else {
@@ -314,7 +321,7 @@ static irqreturn_t s3c_adc_irq(int irq, void *pw)
}
exit:
- if (cpu == TYPE_S3C64XX) {
+ if (S3C64XX_OR_LATER(cpu)) {
/* Clear ADC interrupt */
writel(0, adc->regs + S3C64XX_ADCCLRINT);
}
@@ -388,7 +395,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 (S3C64XX_OR_LATER(platform_get_device_id(pdev)->driver_data)) {
/* Enable 12-bit ADC resolution */
tmp |= S3C64XX_ADCCON_RESSEL;
}
@@ -478,6 +485,9 @@ static struct platform_device_id s3c_adc_driver_ids[] = {
}, {
.name = "s3c64xx-adc",
.driver_data = TYPE_S3C64XX,
+ }, {
+ .name = "s5p-adc",
+ .driver_data = TYPE_S5P,
},
{ }
};
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
Signed-off-by: MyungJoo Ham <[email protected]>
Signed-off-by: Kyungmin Park <[email protected]>
--
v2: No changes from v1. Resubmitted as a series of patches
---
arch/arm/mach-exynos4/Kconfig | 1 +
arch/arm/mach-exynos4/cpu.c | 4 ++++
arch/arm/mach-exynos4/include/mach/irqs.h | 8 ++++++++
arch/arm/mach-exynos4/include/mach/map.h | 5 +++++
4 files changed, 18 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-exynos4/Kconfig b/arch/arm/mach-exynos4/Kconfig
index 1435fc3..61fdf68 100644
--- a/arch/arm/mach-exynos4/Kconfig
+++ b/arch/arm/mach-exynos4/Kconfig
@@ -183,6 +183,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 9babe44..c9af2f9 100644
--- a/arch/arm/mach-exynos4/cpu.c
+++ b/arch/arm/mach-exynos4/cpu.c
@@ -19,7 +19,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>
@@ -128,6 +130,8 @@ void __init exynos4_map_io(void)
exynos4_default_sdhci2();
exynos4_default_sdhci3();
+ s3c_adc_setname("s5p-adc");
+
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 5d03730..aa62d3f 100644
--- a/arch/arm/mach-exynos4/include/mach/irqs.h
+++ b/arch/arm/mach-exynos4/include/mach/irqs.h
@@ -73,6 +73,11 @@
#define IRQ_SYSMMU_MFC_M1_0 COMBINER_IRQ(5, 6)
#define IRQ_SYSMMU_PCIE_0 COMBINER_IRQ(5, 7)
+#define IRQ_ADC0 COMBINER_IRQ(19, 0)
+#define IRQ_PEN0 COMBINER_IRQ(19, 1)
+#define IRQ_ADC1 COMBINER_IRQ(19, 2)
+#define IRQ_PEN1 COMBINER_IRQ(19, 3)
+
#define IRQ_PDMA0 COMBINER_IRQ(21, 0)
#define IRQ_PDMA1 COMBINER_IRQ(21, 1)
@@ -143,6 +148,9 @@
#define MAX_COMBINER_NR 54
+#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 0009e77..d5ba95b 100644
--- a/arch/arm/mach-exynos4/include/mach/map.h
+++ b/arch/arm/mach-exynos4/include/mach/map.h
@@ -108,6 +108,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
@@ -130,6 +133,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
Signed-off-by: MyungJoo Ham <[email protected]>
Signed-off-by: Kyungmin Park <[email protected]>
--
v2: No changes from v1. Resubmitted as a series of patches
---
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..8b68e30 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("s5p-adc");
s3c_cfcon_setname("s5pv210-pata");
--
1.7.4.1
There has been no #ifndef - #define - #endif protection for this header
file.
To compile EXYNOS4 with adc support without compiler errors, this patch is essential.
Signed-off-by: MyungJoo Ham <[email protected]>
Signed-off-by: Kyungmin Park <[email protected]>
--
v2: No changes from v1. Resubmitted as a series of patches
---
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
On Tue, Jun 21, 2011 at 10:58:43AM +0900, MyungJoo Ham wrote:
> + ret = regulator_enable(adc->vdd);
> + if (!ret)
> + goto err_ioremap;
> +
This test looks the wrong way round? regulator_enable() should return 0
on success but this will treat that as an error.
> static int s3c_adc_resume(struct platform_device *pdev)
> {
> struct adc_device *adc = platform_get_drvdata(pdev);
> + int ret;
>
> + ret = regulator_enable(adc->vdd);
> clk_enable(adc->clk);
> enable_irq(adc->irq);
>
> writel(adc->prescale | S3C2410_ADCCON_PRSCEN,
> adc->regs + S3C2410_ADCCON);
>
> - return 0;
> + return ret;
Seems better to return as soon as we notice the error, no point in
starting anything else up if we don't have power.
On Tue, Jun 21, 2011 at 7:43 PM, Mark Brown
<[email protected]> wrote:
> On Tue, Jun 21, 2011 at 10:58:43AM +0900, MyungJoo Ham wrote:
>
>> + ret = regulator_enable(adc->vdd);
>> + if (!ret)
>> + goto err_ioremap;
>> +
>
> This test looks the wrong way round? regulator_enable() should return 0
> on success but this will treat that as an error.
Whoops.. thanks for pointing that out!
>
>> static int s3c_adc_resume(struct platform_device *pdev)
>> {
>> struct adc_device *adc = platform_get_drvdata(pdev);
>> + int ret;
>>
>> + ret = regulator_enable(adc->vdd);
>> clk_enable(adc->clk);
>> enable_irq(adc->irq);
>>
>> writel(adc->prescale | S3C2410_ADCCON_PRSCEN,
>> adc->regs + S3C2410_ADCCON);
>>
>> - return 0;
>> + return ret;
>
> Seems better to return as soon as we notice the error, no point in
> starting anything else up if we don't have power.
>
Ok. I see.
--
MyungJoo Ham (함명주), Ph.D.
Mobile Software Platform Lab,
Digital Media and Communications (DMC) Business
Samsung Electronics
cell: 82-10-6714-2858
MyungJoo Ham wrote:
>
> 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
OK, applied.
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <[email protected]>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
MyungJoo Ham wrote:
>
> 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]>
> --
> v2: No changes from v1. Resubmitted as a series of patches
> ---
> arch/arm/plat-samsung/adc.c | 24
> +++++++++++++++++-------
> arch/arm/plat-samsung/include/plat/regs-adc.h | 1 +
> 2 files changed, 18 insertions(+), 7 deletions(-)
>
> diff --git a/arch/arm/plat-samsung/adc.c b/arch/arm/plat-samsung/adc.c
> index 938f6e9..0233c69 100644
> --- a/arch/arm/plat-samsung/adc.c
> +++ b/arch/arm/plat-samsung/adc.c
> @@ -41,8 +41,10 @@
>
> enum s3c_cpu_type {
> TYPE_S3C24XX,
> - TYPE_S3C64XX
> + TYPE_S3C64XX,
> + TYPE_S5P,
> };
How about S5PC100? Following is better for next if we cannot distinguish it
by CPU.
-enum s3c_cpu_type {
- TYPE_S3C24XX,
- TYPE_S3C64XX
+enum samsung_adc_type {
+ TYPE_ADC24, /* S3C24XX */
+ TYPE_ADC64, /* S3C64XX, S5P64X0, S5PC100 */
+ TYPE_ADCV3 /* S5PV210, EXYNOS4210 */
};
...
TYPE_ADCV1 and V2?...
Of course, the name can be changed...
> +#define S3C64XX_OR_LATER(type) ((type) == TYPE_S3C64XX || (type) ==
> TYPE_S5P)
>
> struct s3c_adc_client {
> struct platform_device *pdev;
> @@ -93,6 +95,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 +103,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_S5P)
> + writel(client->channel & 0xf, adc->regs +
> S5P_ADCMUX);
> + else
> + con |= S3C2410_ADCCON_SELMUX(client->channel);
> + }
>
> writel(con, adc->regs + S3C2410_ADCCON);
> }
> @@ -287,8 +294,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 (S3C64XX_OR_LATER(cpu)) {
> + /* S3C64XX/S5P ADC resolution is 12-bit */
> data0 &= 0xfff;
> data1 &= 0xfff;
> } else {
> @@ -314,7 +321,7 @@ static irqreturn_t s3c_adc_irq(int irq, void *pw)
> }
>
> exit:
> - if (cpu == TYPE_S3C64XX) {
Or (if we use s3c_cpu_type)
+ if (cpu != TYPE_S3C24XX) {
> + if (S3C64XX_OR_LATER(cpu)) {
> /* Clear ADC interrupt */
> writel(0, adc->regs + S3C64XX_ADCCLRINT);
> }
> @@ -388,7 +395,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 (S3C64XX_OR_LATER(platform_get_device_id(pdev)->driver_data)) {
> /* Enable 12-bit ADC resolution */
> tmp |= S3C64XX_ADCCON_RESSEL;
> }
> @@ -478,6 +485,9 @@ static struct platform_device_id s3c_adc_driver_ids[]
= {
> }, {
> .name = "s3c64xx-adc",
> .driver_data = TYPE_S3C64XX,
> + }, {
> + .name = "s5p-adc",
> + .driver_data = TYPE_S5P,
> },
> { }
> };
> 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
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <[email protected]>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
MyungJoo Ham wrote:
>
> Signed-off-by: MyungJoo Ham <[email protected]>
> Signed-off-by: Kyungmin Park <[email protected]>
> --
> v2: No changes from v1. Resubmitted as a series of patches
> ---
> arch/arm/mach-exynos4/Kconfig | 1 +
> arch/arm/mach-exynos4/cpu.c | 4 ++++
> arch/arm/mach-exynos4/include/mach/irqs.h | 8 ++++++++
> arch/arm/mach-exynos4/include/mach/map.h | 5 +++++
> 4 files changed, 18 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-exynos4/Kconfig b/arch/arm/mach-exynos4/Kconfig
> index 1435fc3..61fdf68 100644
> --- a/arch/arm/mach-exynos4/Kconfig
> +++ b/arch/arm/mach-exynos4/Kconfig
> @@ -183,6 +183,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 9babe44..c9af2f9 100644
(snip)
>
> +#define IRQ_ADC0 COMBINER_IRQ(19, 0)
> +#define IRQ_PEN0 COMBINER_IRQ(19, 1)
> +#define IRQ_ADC1 COMBINER_IRQ(19, 2)
> +#define IRQ_PEN1 COMBINER_IRQ(19, 3)
> +
As you know, we need to use external GIC instead of current internal on
EXYNOS4210.
So could you please re-make this based on that?
I will make some branch or will apply external GIC patches into for-next
soon.
(snip)
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <[email protected]>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
On Wed, Jun 29, 2011 at 10:42 PM, Kukjin Kim <[email protected]> wrote:
> MyungJoo Ham wrote:
>>
>> 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]>
>> --
>> v2: No changes from v1. Resubmitted as a series of patches
>> ---
[]
>>
>> enum s3c_cpu_type {
>> TYPE_S3C24XX,
>> - TYPE_S3C64XX
>> + TYPE_S3C64XX,
>> + TYPE_S5P,
>> };
>
> How about S5PC100? Following is better for next if we cannot distinguish it
> by CPU.
>
> -enum s3c_cpu_type {
> - TYPE_S3C24XX,
> - TYPE_S3C64XX
> +enum samsung_adc_type {
> + TYPE_ADC24, /* S3C24XX */
> + TYPE_ADC64, /* S3C64XX, S5P64X0, S5PC100 */
> + TYPE_ADCV3 /* S5PV210, EXYNOS4210 */
> };
> ...
>
> TYPE_ADCV1 and V2?...
> Of course, the name can be changed...
I don't mind about these names as they are just internal values of adc.c.
Anyway, I prefer the last suggestion and I'll use TYPE_ADCV1/V2/V3.
Thanks.
--
MyungJoo Ham (함명주), Ph.D.
Mobile Software Platform Lab,
Digital Media and Communications (DMC) Business
Samsung Electronics
cell: 82-10-6714-2858