2014-04-30 05:02:33

by Pankaj Dubey

[permalink] [raw]
Subject: [PATCH v3 00/12] ARM: Exynos: PMU cleanup and refactoring for using DT

This patch series, does some minor cleanup of exynos machine files.
It also modifies Exynos Power Management Unit (PMU) related code for
converting it into a platform_driver.
This is also preparation for moving PMU related code out of machine
folder into a either "drivers/mfd", or "drivers/power" or some other
suitable place so that ARM64 based SoC can utilize common piece of code.
These patches require change in Exynos SoC dtsi files, which has been
posted as separate patch series [2]

These patches are created on top of Kukjin Kim's for-next (v3.15-rc1 tag)
branch and on top of Daniel Lezcano's Exynos cpuidle refactor patches [3].

These patches depends on following three patch series:
[1] mfd: syscon: Support early initialization
https://lkml.org/lkml/2014/4/8/239
[2] Add PMU node for Exynos SoCs
http://www.mail-archive.com/[email protected]/msg29329.html
[3] http://thread.gmane.org/gmane.linux.kernel.samsung-soc/29085

We have tested these patches on SMDK5250 board for System boot and
Arndale (Exynos5250) board for System boot and PMU initialization and S2R.

For testing on Arndale (Exynos5250) board:
Tested-by: Pankaj Dubey <[email protected]>

Changes Since v2:
- Rebased on top of Daniel Lezcano's Exynos cpuidle refactor patches.
- Removed exynos_cpuidle_init and exynos_cpufreq_init code as suggested
by Tomasz Figa.
- Removed early mapping of PMU base address from exynos.c and removed
"get_exynos_pmuaddr" function. Instead of this added code in platsmp.c
to get PMU base address using of_iomap as suggested by Tomasz Figa.
- Converted PMU implementation into platform_driver by using static
platform_device method.

Changes Since v1:
- Rebased on latest for-next of Kukjin Kim's tree.
- Added patch: "Make exynos machine_ops as static".
For making more cleanup in "mach-exynos/common.h"
as suggested by Tomasz Figa.
- Addressed comments of Tomasz Figa for cleaning "mach-exynos/common.h".
- Updated patch: Remove file path from comment section
As suggested by Michel Simek, instead of updating file path
lets remove them from each file under "mach-exynos".
Even though Kukjin pointed out that there is similar patch pending from
Sachin/Tushar but since I could not find I have included this here. If
I have missed something please point to any existing such patch.
- Updated patch: Add support for mapping PMU base address via DT
- Removed __initdata from declaration of "exynos_pmu_base", as it caused
kernel crash as pointed out by Vikas Sajjan.
- Added support for Syscon initialization and getting PMU regmap handle
as suggested by Sylwester. Since current implementation of early
intialization [1] has limitation that "early_syscon_init" requires
DT to be unflattened and system should be able to allocate memory,
we can't use regmap handles for platsmp.c file as "smp_secondary_init"
will be called before DT unflattening. So I have kept both method for
accessing PMU base address. platsmp.c will use ioremmaped address where
as rest other files can use regmap handle.
- Added patch: Remove "linux/bug.h" from pmu.c.
- Updated patch: Refactored code for PMU register mapping via DT
- Modified to use regmap_read/write when using regmap handle.
- Added patch: Move "mach/map.h" inclusion from regs-pmu.h to platsmp.c
- Added patch: Add device tree based initialization support for PMU.
- Convert existing PMU implementation to be a device tree based
before moving it to "drivers/mfd" folder. As suggested by Bartlomiej.
- Dropped making a platform_driver for PMU, as currently PMU binding
has two compatibility strings as "samsung, exynosxxx-pmu", "syscon",
once we enable MFD_SYSCON config option, current "syscon" driver probe
gets called and PMU probe never gets called. So modified PMU
initialization code to scan DT and match against supported compatiblity
string in driver code, and once we get matching node use that for
accessing PMU regmap handle using "syscon_early_regmap_lookup_by_phandle".
If there is any better solution please suggest.

Pankaj Dubey (8):
ARM: EXYNOS: Make exynos machine_ops as static
ARM: EXYNOS: Move cpufreq and cpuidle device registration to
init_machine
ARM: EXYNOS: Cleanup "mach-exynos/common.h" file
ARM: EXYNOS: Remove file path from comment section
ARM: EXYNOS: Remove "linux/bug.h" from pmu.c
ARM: EXYNOS: Refactored code for using PMU address via DT
ARM: EXYNOS: Move "mach/map.h" inclusion from regs-pmu.h to platsmp.c
ARM: EXYNOS: Add platform driver support for Exynos PMU.

Young-Gun Jang (4):
ARM: EXYNOS: Move SYSREG definition into sys-reg specific file.
ARM: EXYNOS: Remove regs-pmu.h header dependency from pm_domain
ARM: EXYNOS: Add support for mapping PMU base address via DT
ARM: EXYNOS: Move PMU specific definitions from common.h

arch/arm/mach-exynos/Kconfig | 2 +
arch/arm/mach-exynos/common.h | 28 +-
arch/arm/mach-exynos/exynos-pmu.h | 31 ++
arch/arm/mach-exynos/exynos.c | 84 +++--
arch/arm/mach-exynos/headsmp.S | 2 -
arch/arm/mach-exynos/hotplug.c | 7 +-
arch/arm/mach-exynos/include/mach/map.h | 3 -
arch/arm/mach-exynos/include/mach/memory.h | 3 +-
arch/arm/mach-exynos/platsmp.c | 42 ++-
arch/arm/mach-exynos/pm.c | 79 ++--
arch/arm/mach-exynos/pm_domains.c | 8 +-
arch/arm/mach-exynos/pmu.c | 285 +++++++++++---
arch/arm/mach-exynos/regs-pmu.h | 512 +++++++++++++-------------
arch/arm/mach-exynos/regs-sys.h | 22 ++
arch/arm/plat-samsung/include/plat/map-s5p.h | 1 -
15 files changed, 680 insertions(+), 429 deletions(-)
create mode 100644 arch/arm/mach-exynos/exynos-pmu.h
create mode 100644 arch/arm/mach-exynos/regs-sys.h

--
1.7.10.4


2014-04-30 04:59:42

by Pankaj Dubey

[permalink] [raw]
Subject: [PATCH v3 01/12] ARM: EXYNOS: Make exynos machine_ops as static

As machine function ops are used only in this file let's make
them static.

Signed-off-by: Pankaj Dubey <[email protected]>
---
arch/arm/mach-exynos/exynos.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c
index 3d69e8d..06dcce5 100644
--- a/arch/arm/mach-exynos/exynos.c
+++ b/arch/arm/mach-exynos/exynos.c
@@ -198,7 +198,7 @@ static struct map_desc exynos5_iodesc[] __initdata = {
},
};

-void exynos_restart(enum reboot_mode mode, const char *cmd)
+static void exynos_restart(enum reboot_mode mode, const char *cmd)
{
struct device_node *np;
u32 val = 0x1;
@@ -239,7 +239,7 @@ void __init exynos_cpufreq_init(void)
platform_device_register_simple("exynos-cpufreq", -1, NULL, 0);
}

-void __init exynos_init_late(void)
+static void __init exynos_init_late(void)
{
if (of_machine_is_compatible("samsung,exynos5440"))
/* to be supported later */
@@ -300,7 +300,7 @@ static void __init exynos_map_io(void)
iotable_init(exynos5250_iodesc, ARRAY_SIZE(exynos5250_iodesc));
}

-void __init exynos_init_io(void)
+static void __init exynos_init_io(void)
{
debug_ll_io_init();

--
1.7.10.4

2014-04-30 04:59:51

by Pankaj Dubey

[permalink] [raw]
Subject: [PATCH v3 04/12] ARM: EXYNOS: Move SYSREG definition into sys-reg specific file.

From: Young-Gun Jang <[email protected]>

While making PMU implementation to be device tree based, there are
few register offsets related with SYSREG present in regs-pmu.h, so
let's make a new header file "regs-sys.h" to keep all such SYSREG
related register offsets and remove them from "regs-pmu.h"

Signed-off-by: Young-Gun Jang <[email protected]>
Signed-off-by: Pankaj Dubey <[email protected]>
Reviewed-by: Tomasz Figa <[email protected]>
---
arch/arm/mach-exynos/exynos.c | 1 +
arch/arm/mach-exynos/pm.c | 1 +
arch/arm/mach-exynos/regs-pmu.h | 3 ---
arch/arm/mach-exynos/regs-sys.h | 22 ++++++++++++++++++++++
4 files changed, 24 insertions(+), 3 deletions(-)
create mode 100644 arch/arm/mach-exynos/regs-sys.h

diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c
index 9315bd8..a7b45db 100644
--- a/arch/arm/mach-exynos/exynos.c
+++ b/arch/arm/mach-exynos/exynos.c
@@ -31,6 +31,7 @@
#include "common.h"
#include "mfc.h"
#include "regs-pmu.h"
+#include "regs-sys.h"

#define L2_AUX_VAL 0x7C470001
#define L2_AUX_MASK 0xC200ffff
diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c
index b380d48..f445c49 100644
--- a/arch/arm/mach-exynos/pm.c
+++ b/arch/arm/mach-exynos/pm.c
@@ -36,6 +36,7 @@

#include "common.h"
#include "regs-pmu.h"
+#include "regs-sys.h"

/**
* struct exynos_wkup_irq - Exynos GIC to PMU IRQ mapping
diff --git a/arch/arm/mach-exynos/regs-pmu.h b/arch/arm/mach-exynos/regs-pmu.h
index 6c1d2db..b68b5cc 100644
--- a/arch/arm/mach-exynos/regs-pmu.h
+++ b/arch/arm/mach-exynos/regs-pmu.h
@@ -15,7 +15,6 @@
#include <mach/map.h>

#define S5P_PMUREG(x) (S5P_VA_PMU + (x))
-#define S5P_SYSREG(x) (S3C_VA_SYS + (x))

#define S5P_CENTRAL_SEQ_CONFIGURATION S5P_PMUREG(0x0200)

@@ -178,8 +177,6 @@

/* For EXYNOS5 */

-#define EXYNOS5_SYS_I2C_CFG S5P_SYSREG(0x0234)
-
#define EXYNOS5_AUTO_WDTRESET_DISABLE S5P_PMUREG(0x0408)
#define EXYNOS5_MASK_WDTRESET_REQUEST S5P_PMUREG(0x040C)

diff --git a/arch/arm/mach-exynos/regs-sys.h b/arch/arm/mach-exynos/regs-sys.h
new file mode 100644
index 0000000..84332b0
--- /dev/null
+++ b/arch/arm/mach-exynos/regs-sys.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * EXYNOS - system register definition
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_REGS_SYS_H
+#define __ASM_ARCH_REGS_SYS_H __FILE__
+
+#include <mach/map.h>
+
+#define S5P_SYSREG(x) (S3C_VA_SYS + (x))
+
+/* For EXYNOS5 */
+#define EXYNOS5_SYS_I2C_CFG S5P_SYSREG(0x0234)
+
+#endif /* __ASM_ARCH_REGS_SYS_H */
--
1.7.10.4

2014-04-30 04:59:56

by Pankaj Dubey

[permalink] [raw]
Subject: [PATCH v3 08/12] ARM: EXYNOS: Remove "linux/bug.h" from pmu.c

This patch removes unnecessary header file inclusion from pmu.c.

Signed-off-by: Young-Gun Jang <[email protected]>
Reviewed-by: Tomasz Figa <[email protected]>
---
arch/arm/mach-exynos/pmu.c | 1 -
1 file changed, 1 deletion(-)

diff --git a/arch/arm/mach-exynos/pmu.c b/arch/arm/mach-exynos/pmu.c
index 05c7ce1..4c3453a 100644
--- a/arch/arm/mach-exynos/pmu.c
+++ b/arch/arm/mach-exynos/pmu.c
@@ -11,7 +11,6 @@

#include <linux/io.h>
#include <linux/kernel.h>
-#include <linux/bug.h>

#include <plat/cpu.h>

--
1.7.10.4

2014-04-30 05:00:16

by Pankaj Dubey

[permalink] [raw]
Subject: [PATCH v3 12/12] ARM: EXYNOS: Move PMU specific definitions from common.h

From: Young-Gun Jang <[email protected]>

This patch moves PMU specific definitions into a new file
as exynos-pmu.h. This will help in making PMU implementation
independent of common.h header.

Signed-off-by: Young-Gun Jang <[email protected]>
Signed-off-by: Pankaj Dubey <[email protected]>
---
arch/arm/mach-exynos/common.h | 17 -----------------
arch/arm/mach-exynos/exynos-pmu.h | 31 +++++++++++++++++++++++++++++++
arch/arm/mach-exynos/pm.c | 1 +
arch/arm/mach-exynos/pmu.c | 2 +-
4 files changed, 33 insertions(+), 18 deletions(-)
create mode 100644 arch/arm/mach-exynos/exynos-pmu.h

diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h
index 2922f20..8f45a35 100644
--- a/arch/arm/mach-exynos/common.h
+++ b/arch/arm/mach-exynos/common.h
@@ -35,24 +35,7 @@ extern struct smp_operations exynos_smp_ops;

extern void exynos_cpu_die(unsigned int cpu);

-/* PMU(Power Management Unit) support */
-
-#define PMU_TABLE_END (-1U)
-
-enum sys_powerdown {
- SYS_AFTR,
- SYS_LPA,
- SYS_SLEEP,
- NUM_SYS_POWERDOWN,
-};
-
extern unsigned long l2x0_regs_phys;
-struct exynos_pmu_conf {
- unsigned int offset;
- unsigned int val[NUM_SYS_POWERDOWN];
-};
-
-extern void exynos_sys_powerdown_conf(enum sys_powerdown mode);
extern void exynos_enter_aftr(void);

extern struct regmap *get_exynos_pmuregmap(void);
diff --git a/arch/arm/mach-exynos/exynos-pmu.h b/arch/arm/mach-exynos/exynos-pmu.h
new file mode 100644
index 0000000..16ff036
--- /dev/null
+++ b/arch/arm/mach-exynos/exynos-pmu.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Header for EXYNOS PMU Driver support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __EXYNOS_PMU_H
+#define __EXYNOS_PMU_H
+
+#define PMU_TABLE_END (-1U)
+
+enum sys_powerdown {
+ SYS_AFTR,
+ SYS_LPA,
+ SYS_SLEEP,
+ NUM_SYS_POWERDOWN,
+};
+
+struct exynos_pmu_conf {
+ unsigned int offset;
+ unsigned int val[NUM_SYS_POWERDOWN];
+};
+
+extern void exynos_sys_powerdown_conf(enum sys_powerdown mode);
+
+#endif /* __EXYNOS_PMU_H */
diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c
index ee427d7..a7a1b7f 100644
--- a/arch/arm/mach-exynos/pm.c
+++ b/arch/arm/mach-exynos/pm.c
@@ -38,6 +38,7 @@
#include "common.h"
#include "regs-pmu.h"
#include "regs-sys.h"
+#include "exynos-pmu.h"

static struct regmap *pmu_regmap;

diff --git a/arch/arm/mach-exynos/pmu.c b/arch/arm/mach-exynos/pmu.c
index 030df96..1570761 100644
--- a/arch/arm/mach-exynos/pmu.c
+++ b/arch/arm/mach-exynos/pmu.c
@@ -16,7 +16,7 @@
#include <linux/slab.h>
#include <linux/mfd/syscon.h>

-#include "common.h"
+#include "exynos-pmu.h"
#include "regs-pmu.h"

struct exynos_pmu_data {
--
1.7.10.4

2014-04-30 04:59:47

by Pankaj Dubey

[permalink] [raw]
Subject: [PATCH v3 05/12] ARM: EXYNOS: Remove file path from comment section

Many files under "arm/mach-exynos" are having file path in file
comment section which is invalid now.
So for better code maintainability let's remove them.

Signed-off-by: Pankaj Dubey <[email protected]>
Reviewed-by: Tomasz Figa <[email protected]>
---
arch/arm/mach-exynos/headsmp.S | 2 --
arch/arm/mach-exynos/hotplug.c | 3 +--
arch/arm/mach-exynos/include/mach/memory.h | 3 +--
arch/arm/mach-exynos/platsmp.c | 3 +--
4 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/arch/arm/mach-exynos/headsmp.S b/arch/arm/mach-exynos/headsmp.S
index cdd9d91..698c57f 100644
--- a/arch/arm/mach-exynos/headsmp.S
+++ b/arch/arm/mach-exynos/headsmp.S
@@ -1,6 +1,4 @@
/*
- * linux/arch/arm/mach-exynos4/headsmp.S
- *
* Cloned from linux/arch/arm/mach-realview/headsmp.S
*
* Copyright (c) 2003 ARM Limited
diff --git a/arch/arm/mach-exynos/hotplug.c b/arch/arm/mach-exynos/hotplug.c
index 5eead53..73b0b5c 100644
--- a/arch/arm/mach-exynos/hotplug.c
+++ b/arch/arm/mach-exynos/hotplug.c
@@ -1,5 +1,4 @@
-/* linux arch/arm/mach-exynos4/hotplug.c
- *
+/*
* Cloned from linux/arch/arm/mach-realview/hotplug.c
*
* Copyright (C) 2002 ARM Ltd.
diff --git a/arch/arm/mach-exynos/include/mach/memory.h b/arch/arm/mach-exynos/include/mach/memory.h
index 2a4cdb7..e19df1f 100644
--- a/arch/arm/mach-exynos/include/mach/memory.h
+++ b/arch/arm/mach-exynos/include/mach/memory.h
@@ -1,5 +1,4 @@
-/* linux/arch/arm/mach-exynos4/include/mach/memory.h
- *
+/*
* Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c
index 03e5e9f..29c2286 100644
--- a/arch/arm/mach-exynos/platsmp.c
+++ b/arch/arm/mach-exynos/platsmp.c
@@ -1,5 +1,4 @@
-/* linux/arch/arm/mach-exynos4/platsmp.c
- *
+/*
* Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
--
1.7.10.4

2014-04-30 05:00:49

by Pankaj Dubey

[permalink] [raw]
Subject: [PATCH v3 02/12] ARM: EXYNOS: Move cpufreq and cpuidle device registration to init_machine

As exynos_cpuidle_init and exynos_cpufreq_init function have just one lines
of code for registering platform devices. We can move these lines to
exynos_dt_machine_init and delete exynos_cpuidle_init and exynos_cpufreq_init
function. This will help in reducing lines of code in exynos.c, making it
more cleaner.

Suggested-by: Tomasz Figa <[email protected]>
Signed-off-by: Pankaj Dubey <[email protected]>
---
arch/arm/mach-exynos/exynos.c | 19 ++++---------------
1 file changed, 4 insertions(+), 15 deletions(-)

diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c
index 06dcce5..9315bd8 100644
--- a/arch/arm/mach-exynos/exynos.c
+++ b/arch/arm/mach-exynos/exynos.c
@@ -226,19 +226,6 @@ static struct platform_device exynos_cpuidle = {
.id = -1,
};

-void __init exynos_cpuidle_init(void)
-{
- if (soc_is_exynos5440())
- return;
-
- platform_device_register(&exynos_cpuidle);
-}
-
-void __init exynos_cpufreq_init(void)
-{
- platform_device_register_simple("exynos-cpufreq", -1, NULL, 0);
-}
-
static void __init exynos_init_late(void)
{
if (of_machine_is_compatible("samsung,exynos5440"))
@@ -367,8 +354,10 @@ static void __init exynos_dt_machine_init(void)
}
}

- exynos_cpuidle_init();
- exynos_cpufreq_init();
+ if (!soc_is_exynos5440())
+ platform_device_register(&exynos_cpuidle);
+
+ platform_device_register_simple("exynos-cpufreq", -1, NULL, 0);

of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
}
--
1.7.10.4

2014-04-30 05:00:55

by Pankaj Dubey

[permalink] [raw]
Subject: [PATCH v3 09/12] ARM: EXYNOS: Refactored code for using PMU address via DT

Under "arm/mach-exynos" many files are using PMU register offsets.
Since we have added support for accessing PMU base address via DT,
now we can remove PMU mapping from exynosX_iodesc. Let's convert
all these access using either of iomapped address or regmap handle.
This will help us in removing static mapping of PMU base address
as well as help in reducing dependency over machine header files.
Thus helping for migration of PMU implementation from machine to
driver folder which can be reused for ARM64 bsed SoC.

CC: Ben Dooks <[email protected]>
CC: Kyungmin Park <[email protected]>
CC: Arnd Bergmann <[email protected]>
Signed-off-by: Pankaj Dubey <[email protected]>
---
arch/arm/mach-exynos/common.h | 4 +-
arch/arm/mach-exynos/exynos.c | 19 +-
arch/arm/mach-exynos/hotplug.c | 4 +-
arch/arm/mach-exynos/include/mach/map.h | 3 -
arch/arm/mach-exynos/platsmp.c | 38 +-
arch/arm/mach-exynos/pm.c | 77 ++--
arch/arm/mach-exynos/pmu.c | 40 +-
arch/arm/mach-exynos/regs-pmu.h | 506 +++++++++++++-------------
arch/arm/plat-samsung/include/plat/map-s5p.h | 1 -
9 files changed, 362 insertions(+), 330 deletions(-)

diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h
index 33a2bee..2922f20 100644
--- a/arch/arm/mach-exynos/common.h
+++ b/arch/arm/mach-exynos/common.h
@@ -37,7 +37,7 @@ extern void exynos_cpu_die(unsigned int cpu);

/* PMU(Power Management Unit) support */

-#define PMU_TABLE_END NULL
+#define PMU_TABLE_END (-1U)

enum sys_powerdown {
SYS_AFTR,
@@ -48,7 +48,7 @@ enum sys_powerdown {

extern unsigned long l2x0_regs_phys;
struct exynos_pmu_conf {
- void __iomem *reg;
+ unsigned int offset;
unsigned int val[NUM_SYS_POWERDOWN];
};

diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c
index 9045fd6..a59b122 100644
--- a/arch/arm/mach-exynos/exynos.c
+++ b/arch/arm/mach-exynos/exynos.c
@@ -20,6 +20,7 @@
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>

#include <asm/cacheflush.h>
#include <asm/hardware/cache-l2x0.h>
@@ -66,11 +67,6 @@ static struct map_desc exynos4_iodesc[] __initdata = {
.length = SZ_4K,
.type = MT_DEVICE,
}, {
- .virtual = (unsigned long)S5P_VA_PMU,
- .pfn = __phys_to_pfn(EXYNOS4_PA_PMU),
- .length = SZ_64K,
- .type = MT_DEVICE,
- }, {
.virtual = (unsigned long)S5P_VA_COMBINER_BASE,
.pfn = __phys_to_pfn(EXYNOS4_PA_COMBINER),
.length = SZ_4K,
@@ -194,11 +190,6 @@ static struct map_desc exynos5_iodesc[] __initdata = {
.pfn = __phys_to_pfn(EXYNOS5_PA_CMU),
.length = 144 * SZ_1K,
.type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)S5P_VA_PMU,
- .pfn = __phys_to_pfn(EXYNOS5_PA_PMU),
- .length = SZ_64K,
- .type = MT_DEVICE,
},
};

@@ -206,7 +197,7 @@ static void exynos_restart(enum reboot_mode mode, const char *cmd)
{
struct device_node *np;
u32 val = 0x1;
- void __iomem *addr = EXYNOS_SWRESET;
+ void __iomem *addr = NULL;

if (of_machine_is_compatible("samsung,exynos5440")) {
u32 status;
@@ -219,9 +210,9 @@ static void exynos_restart(enum reboot_mode mode, const char *cmd)
val = __raw_readl(addr);

val = (val & 0xffff0000) | (status & 0xffff);
- }
-
- __raw_writel(val, addr);
+ __raw_writel(val, addr);
+ } else
+ regmap_write(exynos_pmu_regmap, EXYNOS_SWRESET, val);
}

static struct platform_device exynos_cpuidle = {
diff --git a/arch/arm/mach-exynos/hotplug.c b/arch/arm/mach-exynos/hotplug.c
index 73b0b5c..0243ef3 100644
--- a/arch/arm/mach-exynos/hotplug.c
+++ b/arch/arm/mach-exynos/hotplug.c
@@ -13,6 +13,7 @@
#include <linux/errno.h>
#include <linux/smp.h>
#include <linux/io.h>
+#include <linux/regmap.h>

#include <asm/cacheflush.h>
#include <asm/cp15.h>
@@ -91,11 +92,12 @@ static inline void cpu_leave_lowpower(void)

static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
{
+ struct regmap *pmu_regmap = get_exynos_pmuregmap();
for (;;) {

/* make cpu1 to be turned off at next WFI command */
if (cpu == 1)
- __raw_writel(0, S5P_ARM_CORE1_CONFIGURATION);
+ regmap_write(pmu_regmap, S5P_ARM_CORE1_CONFIGURATION, 0);

/*
* here's the WFI
diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h
index 7b046b5..1ba7fb5 100644
--- a/arch/arm/mach-exynos/include/mach/map.h
+++ b/arch/arm/mach-exynos/include/mach/map.h
@@ -35,9 +35,6 @@
#define EXYNOS4_PA_SYSCON 0x10010000
#define EXYNOS5_PA_SYSCON 0x10050100

-#define EXYNOS4_PA_PMU 0x10020000
-#define EXYNOS5_PA_PMU 0x10040000
-
#define EXYNOS4_PA_CMU 0x10030000
#define EXYNOS5_PA_CMU 0x10010000

diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c
index 29c2286..375ea4e 100644
--- a/arch/arm/mach-exynos/platsmp.c
+++ b/arch/arm/mach-exynos/platsmp.c
@@ -19,6 +19,7 @@
#include <linux/jiffies.h>
#include <linux/smp.h>
#include <linux/io.h>
+#include <linux/of_address.h>

#include <asm/cacheflush.h>
#include <asm/smp_plat.h>
@@ -31,11 +32,12 @@
#include "regs-pmu.h"

extern void exynos4_secondary_startup(void);
+static void __iomem *pmu_base;

static inline void __iomem *cpu_boot_reg_base(void)
{
if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_1_1)
- return S5P_INFORM5;
+ return pmu_base + S5P_INFORM5;
return S5P_VA_SYSRAM;
}

@@ -68,6 +70,30 @@ static void __iomem *scu_base_addr(void)
return (void __iomem *)(S5P_VA_SCU);
}

+static const struct of_device_id exynos_dt_pmu_match[] = {
+ { .compatible = "samsung,exynos4210-pmu" },
+ { .compatible = "samsung,exynos4212-pmu" },
+ { .compatible = "samsung,exynos4412-pmu" },
+ { .compatible = "samsung,exynos5250-pmu" },
+ {},
+};
+
+static void __iomem *pmu_base_addr(void)
+{
+ struct device_node *np = NULL;
+ if (!pmu_base) {
+ np = of_find_matching_node(NULL, exynos_dt_pmu_match);
+
+ if (!np)
+ panic("%s, failed to find PMU node\n", __func__);
+ else
+ pmu_base = of_iomap(np, 0);
+
+ if (!pmu_base)
+ panic("%s: failed to map registers\n", __func__);
+ }
+ return pmu_base;
+}
static DEFINE_SPINLOCK(boot_lock);

static void exynos_secondary_init(unsigned int cpu)
@@ -106,14 +132,14 @@ static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle)
*/
write_pen_release(phys_cpu);

- if (!(__raw_readl(S5P_ARM_CORE1_STATUS) & S5P_CORE_LOCAL_PWR_EN)) {
+ if (!(__raw_readl(pmu_base + S5P_ARM_CORE1_STATUS)
+ & S5P_CORE_LOCAL_PWR_EN)) {
__raw_writel(S5P_CORE_LOCAL_PWR_EN,
- S5P_ARM_CORE1_CONFIGURATION);
-
+ pmu_base + S5P_ARM_CORE1_CONFIGURATION);
timeout = 10;

/* wait max 10 ms until cpu1 is on */
- while ((__raw_readl(S5P_ARM_CORE1_STATUS)
+ while ((__raw_readl(pmu_base + S5P_ARM_CORE1_STATUS)
& S5P_CORE_LOCAL_PWR_EN) != S5P_CORE_LOCAL_PWR_EN) {
if (timeout-- == 0)
break;
@@ -201,6 +227,8 @@ static void __init exynos_smp_prepare_cpus(unsigned int max_cpus)
{
int i;

+ pmu_base = pmu_base_addr();
+
if (read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A9)
scu_enable(scu_base_addr());

diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c
index f445c49..ee427d7 100644
--- a/arch/arm/mach-exynos/pm.c
+++ b/arch/arm/mach-exynos/pm.c
@@ -21,6 +21,7 @@
#include <linux/irqchip/arm-gic.h>
#include <linux/err.h>
#include <linux/clk.h>
+#include <linux/regmap.h>

#include <asm/cacheflush.h>
#include <asm/hardware/cache-l2x0.h>
@@ -38,6 +39,8 @@
#include "regs-pmu.h"
#include "regs-sys.h"

+static struct regmap *pmu_regmap;
+
/**
* struct exynos_wkup_irq - Exynos GIC to PMU IRQ mapping
* @hwirq: Hardware IRQ signal of the GIC
@@ -104,10 +107,10 @@ static int exynos_irq_set_wake(struct irq_data *data, unsigned int state)

#define EXYNOS_BOOT_VECTOR_ADDR (samsung_rev() == EXYNOS4210_REV_1_1 ? \
S5P_INFORM7 : (samsung_rev() == EXYNOS4210_REV_1_0 ? \
- (S5P_VA_SYSRAM + 0x24) : S5P_INFORM0))
+ 0x24 : S5P_INFORM0))
#define EXYNOS_BOOT_VECTOR_FLAG (samsung_rev() == EXYNOS4210_REV_1_1 ? \
S5P_INFORM6 : (samsung_rev() == EXYNOS4210_REV_1_0 ? \
- (S5P_VA_SYSRAM + 0x20) : S5P_INFORM1))
+ 0x20 : S5P_INFORM1))

#define S5P_CHECK_AFTR 0xFCBA0D10
#define S5P_CHECK_SLEEP 0x00000BAD
@@ -115,13 +118,20 @@ static int exynos_irq_set_wake(struct irq_data *data, unsigned int state)
/* Ext-GIC nIRQ/nFIQ is the only wakeup source in AFTR */
static void exynos_set_wakeupmask(long mask)
{
- __raw_writel(mask, S5P_WAKEUP_MASK);
+ regmap_write(pmu_regmap, S5P_WAKEUP_MASK, mask);
}

static void exynos_cpu_set_boot_vector(long flags)
{
- __raw_writel(virt_to_phys(exynos_cpu_resume), EXYNOS_BOOT_VECTOR_ADDR);
- __raw_writel(flags, EXYNOS_BOOT_VECTOR_FLAG);
+ if (samsung_rev() == EXYNOS4210_REV_1_0) {
+ __raw_writel(virt_to_phys(exynos_cpu_resume),
+ S5P_VA_SYSRAM + EXYNOS_BOOT_VECTOR_ADDR);
+ __raw_writel(flags, S5P_VA_SYSRAM + EXYNOS_BOOT_VECTOR_FLAG);
+ } else {
+ regmap_write(pmu_regmap, EXYNOS_BOOT_VECTOR_ADDR,
+ virt_to_phys(exynos_cpu_resume));
+ regmap_write(pmu_regmap, EXYNOS_BOOT_VECTOR_FLAG, flags);
+ }
}

void exynos_enter_aftr(void)
@@ -192,49 +202,51 @@ static void exynos_pm_prepare(void)
unsigned int tmp;

/* Set wake-up mask registers */
- __raw_writel(exynos_get_eint_wake_mask(), S5P_EINT_WAKEUP_MASK);
- __raw_writel(exynos_irqwake_intmask & ~(1 << 31), S5P_WAKEUP_MASK);
+ regmap_write(pmu_regmap, S5P_EINT_WAKEUP_MASK,
+ exynos_get_eint_wake_mask());
+ regmap_write(pmu_regmap, S5P_WAKEUP_MASK,
+ exynos_irqwake_intmask & ~(1 << 31));

s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save));

if (soc_is_exynos5250()) {
s3c_pm_do_save(exynos5_sys_save, ARRAY_SIZE(exynos5_sys_save));
/* Disable USE_RETENTION of JPEG_MEM_OPTION */
- tmp = __raw_readl(EXYNOS5_JPEG_MEM_OPTION);
+ regmap_read(pmu_regmap, EXYNOS5_JPEG_MEM_OPTION, &tmp);
tmp &= ~EXYNOS5_OPTION_USE_RETENTION;
- __raw_writel(tmp, EXYNOS5_JPEG_MEM_OPTION);
+ regmap_write(pmu_regmap, EXYNOS5_JPEG_MEM_OPTION, tmp);
}

/* Set value of power down register for sleep mode */

exynos_sys_powerdown_conf(SYS_SLEEP);
- __raw_writel(S5P_CHECK_SLEEP, S5P_INFORM1);
+ regmap_write(pmu_regmap, S5P_INFORM1, S5P_CHECK_SLEEP);

/* ensure at least INFORM0 has the resume address */

- __raw_writel(virt_to_phys(exynos_cpu_resume), S5P_INFORM0);
+ regmap_write(pmu_regmap, S5P_INFORM0, virt_to_phys(exynos_cpu_resume));
}

static void exynos_pm_central_suspend(void)
{
- unsigned long tmp;
+ unsigned int tmp;

/* Setting Central Sequence Register for power down mode */
- tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
+ regmap_read(pmu_regmap, S5P_CENTRAL_SEQ_CONFIGURATION, &tmp);
tmp &= ~S5P_CENTRAL_LOWPWR_CFG;
- __raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
+ regmap_write(pmu_regmap, S5P_CENTRAL_SEQ_CONFIGURATION, tmp);
}

static int exynos_pm_suspend(void)
{
- unsigned long tmp;
+ unsigned int tmp;

exynos_pm_central_suspend();

/* Setting SEQ_OPTION register */

tmp = (S5P_USE_STANDBY_WFI0 | S5P_USE_STANDBY_WFE0);
- __raw_writel(tmp, S5P_CENTRAL_SEQ_OPTION);
+ regmap_write(pmu_regmap, S5P_CENTRAL_SEQ_OPTION, tmp);

if (!soc_is_exynos5250())
exynos_cpu_save_register();
@@ -244,7 +256,7 @@ static int exynos_pm_suspend(void)

static int exynos_pm_central_resume(void)
{
- unsigned long tmp;
+ unsigned int tmp;

/*
* If PMU failed while entering sleep mode, WFI will be
@@ -252,12 +264,12 @@ static int exynos_pm_central_resume(void)
* S5P_CENTRAL_LOWPWR_CFG bit will not be set automatically
* in this situation.
*/
- tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
+ regmap_read(pmu_regmap, S5P_CENTRAL_SEQ_CONFIGURATION, &tmp);
if (!(tmp & S5P_CENTRAL_LOWPWR_CFG)) {
tmp |= S5P_CENTRAL_LOWPWR_CFG;
- __raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
+ regmap_write(pmu_regmap, S5P_CENTRAL_SEQ_CONFIGURATION, tmp);
/* clear the wakeup state register */
- __raw_writel(0x0, S5P_WAKEUP_STAT);
+ regmap_write(pmu_regmap, S5P_WAKEUP_STAT, 0x0);
/* No need to perform below restore code */
return -1;
}
@@ -275,13 +287,13 @@ static void exynos_pm_resume(void)

/* For release retention */

- __raw_writel((1 << 28), S5P_PAD_RET_MAUDIO_OPTION);
- __raw_writel((1 << 28), S5P_PAD_RET_GPIO_OPTION);
- __raw_writel((1 << 28), S5P_PAD_RET_UART_OPTION);
- __raw_writel((1 << 28), S5P_PAD_RET_MMCA_OPTION);
- __raw_writel((1 << 28), S5P_PAD_RET_MMCB_OPTION);
- __raw_writel((1 << 28), S5P_PAD_RET_EBIA_OPTION);
- __raw_writel((1 << 28), S5P_PAD_RET_EBIB_OPTION);
+ regmap_write(pmu_regmap, S5P_PAD_RET_MAUDIO_OPTION, (1 << 28));
+ regmap_write(pmu_regmap, S5P_PAD_RET_GPIO_OPTION, (1 << 28));
+ regmap_write(pmu_regmap, S5P_PAD_RET_UART_OPTION, (1 << 28));
+ regmap_write(pmu_regmap, S5P_PAD_RET_MMCA_OPTION, (1 << 28));
+ regmap_write(pmu_regmap, S5P_PAD_RET_MMCB_OPTION, (1 << 28));
+ regmap_write(pmu_regmap, S5P_PAD_RET_EBIA_OPTION, (1 << 28));
+ regmap_write(pmu_regmap, S5P_PAD_RET_EBIB_OPTION, (1 << 28));

if (soc_is_exynos5250())
s3c_pm_do_restore(exynos5_sys_save,
@@ -295,7 +307,7 @@ static void exynos_pm_resume(void)
early_wakeup:

/* Clear SLEEP mode set in INFORM1 */
- __raw_writel(0x0, S5P_INFORM1);
+ regmap_write(pmu_regmap, S5P_INFORM1, 0x0);

return;
}
@@ -338,8 +350,8 @@ static int exynos_suspend_enter(suspend_state_t state)

s3c_pm_restore_uarts();

- S3C_PMDBG("%s: wakeup stat: %08x\n", __func__,
- __raw_readl(S5P_WAKEUP_STAT));
+ regmap_read(pmu_regmap, S5P_WAKEUP_STAT, &ret);
+ S3C_PMDBG("%s: wakeup stat: %08x\n", __func__, ret);

s3c_pm_check_restore();

@@ -401,15 +413,16 @@ void __init exynos_pm_init(void)
{
u32 tmp;

+ pmu_regmap = get_exynos_pmuregmap();
cpu_pm_register_notifier(&exynos_cpu_pm_notifier_block);

/* Platform-specific GIC callback */
gic_arch_extn.irq_set_wake = exynos_irq_set_wake;

/* All wakeup disable */
- tmp = __raw_readl(S5P_WAKEUP_MASK);
+ regmap_read(pmu_regmap, S5P_WAKEUP_MASK, &tmp);
tmp |= ((0xFF << 8) | (0x1F << 1));
- __raw_writel(tmp, S5P_WAKEUP_MASK);
+ regmap_write(pmu_regmap, S5P_WAKEUP_MASK, tmp);

register_syscore_ops(&exynos_pm_syscore_ops);
suspend_set_ops(&exynos_suspend_ops);
diff --git a/arch/arm/mach-exynos/pmu.c b/arch/arm/mach-exynos/pmu.c
index 4c3453a..67116a5 100644
--- a/arch/arm/mach-exynos/pmu.c
+++ b/arch/arm/mach-exynos/pmu.c
@@ -11,6 +11,7 @@

#include <linux/io.h>
#include <linux/kernel.h>
+#include <linux/regmap.h>

#include <plat/cpu.h>

@@ -18,6 +19,7 @@
#include "regs-pmu.h"

static const struct exynos_pmu_conf *exynos_pmu_config;
+static struct regmap *pmu_regmap;

static const struct exynos_pmu_conf exynos4210_pmu_config[] = {
/* { .reg = address, .val = { AFTR, LPA, SLEEP } */
@@ -317,7 +319,7 @@ static const struct exynos_pmu_conf exynos5250_pmu_config[] = {
{ PMU_TABLE_END,},
};

-static void __iomem * const exynos5_list_both_cnt_feed[] = {
+static unsigned int const exynos5_list_both_cnt_feed[] = {
EXYNOS5_ARM_CORE0_OPTION,
EXYNOS5_ARM_CORE1_OPTION,
EXYNOS5_ARM_COMMON_OPTION,
@@ -331,7 +333,7 @@ static void __iomem * const exynos5_list_both_cnt_feed[] = {
EXYNOS5_TOP_PWR_SYSMEM_OPTION,
};

-static void __iomem * const exynos5_list_diable_wfi_wfe[] = {
+static unsigned int const exynos5_list_diable_wfi_wfe[] = {
EXYNOS5_ARM_CORE1_OPTION,
EXYNOS5_FSYS_ARM_OPTION,
EXYNOS5_ISP_ARM_OPTION,
@@ -346,27 +348,28 @@ static void exynos5_init_pmu(void)
* Enable both SC_FEEDBACK and SC_COUNTER
*/
for (i = 0 ; i < ARRAY_SIZE(exynos5_list_both_cnt_feed) ; i++) {
- tmp = __raw_readl(exynos5_list_both_cnt_feed[i]);
+ regmap_read(pmu_regmap, exynos5_list_both_cnt_feed[i], &tmp);
tmp |= (EXYNOS5_USE_SC_FEEDBACK |
EXYNOS5_USE_SC_COUNTER);
- __raw_writel(tmp, exynos5_list_both_cnt_feed[i]);
+ regmap_write(pmu_regmap, exynos5_list_both_cnt_feed[i], tmp);
}

/*
* SKIP_DEACTIVATE_ACEACP_IN_PWDN_BITFIELD Enable
*/
- tmp = __raw_readl(EXYNOS5_ARM_COMMON_OPTION);
+ regmap_read(pmu_regmap, EXYNOS5_ARM_COMMON_OPTION, &tmp);
tmp |= EXYNOS5_SKIP_DEACTIVATE_ACEACP_IN_PWDN;
- __raw_writel(tmp, EXYNOS5_ARM_COMMON_OPTION);
+ regmap_write(pmu_regmap, EXYNOS5_ARM_COMMON_OPTION, tmp);

/*
* Disable WFI/WFE on XXX_OPTION
*/
for (i = 0 ; i < ARRAY_SIZE(exynos5_list_diable_wfi_wfe) ; i++) {
- tmp = __raw_readl(exynos5_list_diable_wfi_wfe[i]);
+ tmp = regmap_read(pmu_regmap, exynos5_list_diable_wfi_wfe[i],
+ &tmp);
tmp &= ~(EXYNOS5_OPTION_USE_STANDBYWFE |
EXYNOS5_OPTION_USE_STANDBYWFI);
- __raw_writel(tmp, exynos5_list_diable_wfi_wfe[i]);
+ regmap_write(pmu_regmap, exynos5_list_diable_wfi_wfe[i], tmp);
}
}

@@ -377,14 +380,14 @@ void exynos_sys_powerdown_conf(enum sys_powerdown mode)
if (soc_is_exynos5250())
exynos5_init_pmu();

- for (i = 0; (exynos_pmu_config[i].reg != PMU_TABLE_END) ; i++)
- __raw_writel(exynos_pmu_config[i].val[mode],
- exynos_pmu_config[i].reg);
+ for (i = 0; (exynos_pmu_config[i].offset != PMU_TABLE_END) ; i++)
+ regmap_write(pmu_regmap, exynos_pmu_config[i].offset,
+ exynos_pmu_config[i].val[mode]);

if (soc_is_exynos4412()) {
- for (i = 0; exynos4412_pmu_config[i].reg != PMU_TABLE_END ; i++)
- __raw_writel(exynos4412_pmu_config[i].val[mode],
- exynos4412_pmu_config[i].reg);
+ for (i = 0; exynos4412_pmu_config[i].offset != PMU_TABLE_END; i++)
+ regmap_write(pmu_regmap, exynos4412_pmu_config[i].offset,
+ exynos4412_pmu_config[i].val[mode]);
}
}

@@ -393,6 +396,7 @@ static int __init exynos_pmu_init(void)
unsigned int value;

exynos_pmu_config = exynos4210_pmu_config;
+ pmu_regmap = get_exynos_pmuregmap();

if (soc_is_exynos4210()) {
exynos_pmu_config = exynos4210_pmu_config;
@@ -405,13 +409,13 @@ static int __init exynos_pmu_init(void)
* When SYS_WDTRESET is set, watchdog timer reset request
* is ignored by power management unit.
*/
- value = __raw_readl(EXYNOS5_AUTO_WDTRESET_DISABLE);
+ regmap_read(pmu_regmap, EXYNOS5_AUTO_WDTRESET_DISABLE, &value);
value &= ~EXYNOS5_SYS_WDTRESET;
- __raw_writel(value, EXYNOS5_AUTO_WDTRESET_DISABLE);
+ regmap_write(pmu_regmap, EXYNOS5_AUTO_WDTRESET_DISABLE, value);

- value = __raw_readl(EXYNOS5_MASK_WDTRESET_REQUEST);
+ regmap_read(pmu_regmap, EXYNOS5_MASK_WDTRESET_REQUEST, &value);
value &= ~EXYNOS5_SYS_WDTRESET;
- __raw_writel(value, EXYNOS5_MASK_WDTRESET_REQUEST);
+ regmap_write(pmu_regmap, EXYNOS5_MASK_WDTRESET_REQUEST, value);

exynos_pmu_config = exynos5250_pmu_config;
pr_info("EXYNOS5250 PMU Initialize\n");
diff --git a/arch/arm/mach-exynos/regs-pmu.h b/arch/arm/mach-exynos/regs-pmu.h
index fd8a19d..a72b1bc 100644
--- a/arch/arm/mach-exynos/regs-pmu.h
+++ b/arch/arm/mach-exynos/regs-pmu.h
@@ -14,288 +14,286 @@

#include <mach/map.h>

-#define S5P_PMUREG(x) (S5P_VA_PMU + (x))
-
-#define S5P_CENTRAL_SEQ_CONFIGURATION S5P_PMUREG(0x0200)
+#define S5P_CENTRAL_SEQ_CONFIGURATION 0x0200

#define S5P_CENTRAL_LOWPWR_CFG (1 << 16)

-#define S5P_CENTRAL_SEQ_OPTION S5P_PMUREG(0x0208)
+#define S5P_CENTRAL_SEQ_OPTION 0x0208

#define S5P_USE_STANDBY_WFI0 (1 << 16)
#define S5P_USE_STANDBY_WFE0 (1 << 24)

-#define EXYNOS_SWRESET S5P_PMUREG(0x0400)
-#define EXYNOS5440_SWRESET S5P_PMUREG(0x00C4)
+#define EXYNOS_SWRESET 0x0400
+#define EXYNOS5440_SWRESET 0x00C4

-#define S5P_WAKEUP_STAT S5P_PMUREG(0x0600)
-#define S5P_EINT_WAKEUP_MASK S5P_PMUREG(0x0604)
-#define S5P_WAKEUP_MASK S5P_PMUREG(0x0608)
+#define S5P_WAKEUP_STAT 0x0600
+#define S5P_EINT_WAKEUP_MASK 0x0604
+#define S5P_WAKEUP_MASK 0x0608

-#define S5P_INFORM0 S5P_PMUREG(0x0800)
-#define S5P_INFORM1 S5P_PMUREG(0x0804)
-#define S5P_INFORM5 S5P_PMUREG(0x0814)
-#define S5P_INFORM6 S5P_PMUREG(0x0818)
-#define S5P_INFORM7 S5P_PMUREG(0x081C)
+#define S5P_INFORM0 0x0800
+#define S5P_INFORM1 0x0804
+#define S5P_INFORM5 0x0814
+#define S5P_INFORM6 0x0818
+#define S5P_INFORM7 0x081C

-#define S5P_ARM_CORE0_LOWPWR S5P_PMUREG(0x1000)
-#define S5P_DIS_IRQ_CORE0 S5P_PMUREG(0x1004)
-#define S5P_DIS_IRQ_CENTRAL0 S5P_PMUREG(0x1008)
-#define S5P_ARM_CORE1_LOWPWR S5P_PMUREG(0x1010)
-#define S5P_DIS_IRQ_CORE1 S5P_PMUREG(0x1014)
-#define S5P_DIS_IRQ_CENTRAL1 S5P_PMUREG(0x1018)
-#define S5P_ARM_COMMON_LOWPWR S5P_PMUREG(0x1080)
-#define S5P_L2_0_LOWPWR S5P_PMUREG(0x10C0)
-#define S5P_L2_1_LOWPWR S5P_PMUREG(0x10C4)
-#define S5P_CMU_ACLKSTOP_LOWPWR S5P_PMUREG(0x1100)
-#define S5P_CMU_SCLKSTOP_LOWPWR S5P_PMUREG(0x1104)
-#define S5P_CMU_RESET_LOWPWR S5P_PMUREG(0x110C)
-#define S5P_APLL_SYSCLK_LOWPWR S5P_PMUREG(0x1120)
-#define S5P_MPLL_SYSCLK_LOWPWR S5P_PMUREG(0x1124)
-#define S5P_VPLL_SYSCLK_LOWPWR S5P_PMUREG(0x1128)
-#define S5P_EPLL_SYSCLK_LOWPWR S5P_PMUREG(0x112C)
-#define S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR S5P_PMUREG(0x1138)
-#define S5P_CMU_RESET_GPSALIVE_LOWPWR S5P_PMUREG(0x113C)
-#define S5P_CMU_CLKSTOP_CAM_LOWPWR S5P_PMUREG(0x1140)
-#define S5P_CMU_CLKSTOP_TV_LOWPWR S5P_PMUREG(0x1144)
-#define S5P_CMU_CLKSTOP_MFC_LOWPWR S5P_PMUREG(0x1148)
-#define S5P_CMU_CLKSTOP_G3D_LOWPWR S5P_PMUREG(0x114C)
-#define S5P_CMU_CLKSTOP_LCD0_LOWPWR S5P_PMUREG(0x1150)
-#define S5P_CMU_CLKSTOP_MAUDIO_LOWPWR S5P_PMUREG(0x1158)
-#define S5P_CMU_CLKSTOP_GPS_LOWPWR S5P_PMUREG(0x115C)
-#define S5P_CMU_RESET_CAM_LOWPWR S5P_PMUREG(0x1160)
-#define S5P_CMU_RESET_TV_LOWPWR S5P_PMUREG(0x1164)
-#define S5P_CMU_RESET_MFC_LOWPWR S5P_PMUREG(0x1168)
-#define S5P_CMU_RESET_G3D_LOWPWR S5P_PMUREG(0x116C)
-#define S5P_CMU_RESET_LCD0_LOWPWR S5P_PMUREG(0x1170)
-#define S5P_CMU_RESET_MAUDIO_LOWPWR S5P_PMUREG(0x1178)
-#define S5P_CMU_RESET_GPS_LOWPWR S5P_PMUREG(0x117C)
-#define S5P_TOP_BUS_LOWPWR S5P_PMUREG(0x1180)
-#define S5P_TOP_RETENTION_LOWPWR S5P_PMUREG(0x1184)
-#define S5P_TOP_PWR_LOWPWR S5P_PMUREG(0x1188)
-#define S5P_LOGIC_RESET_LOWPWR S5P_PMUREG(0x11A0)
-#define S5P_ONENAND_MEM_LOWPWR S5P_PMUREG(0x11C0)
-#define S5P_G2D_ACP_MEM_LOWPWR S5P_PMUREG(0x11C8)
-#define S5P_USBOTG_MEM_LOWPWR S5P_PMUREG(0x11CC)
-#define S5P_HSMMC_MEM_LOWPWR S5P_PMUREG(0x11D0)
-#define S5P_CSSYS_MEM_LOWPWR S5P_PMUREG(0x11D4)
-#define S5P_SECSS_MEM_LOWPWR S5P_PMUREG(0x11D8)
-#define S5P_PAD_RETENTION_DRAM_LOWPWR S5P_PMUREG(0x1200)
-#define S5P_PAD_RETENTION_MAUDIO_LOWPWR S5P_PMUREG(0x1204)
-#define S5P_PAD_RETENTION_GPIO_LOWPWR S5P_PMUREG(0x1220)
-#define S5P_PAD_RETENTION_UART_LOWPWR S5P_PMUREG(0x1224)
-#define S5P_PAD_RETENTION_MMCA_LOWPWR S5P_PMUREG(0x1228)
-#define S5P_PAD_RETENTION_MMCB_LOWPWR S5P_PMUREG(0x122C)
-#define S5P_PAD_RETENTION_EBIA_LOWPWR S5P_PMUREG(0x1230)
-#define S5P_PAD_RETENTION_EBIB_LOWPWR S5P_PMUREG(0x1234)
-#define S5P_PAD_RETENTION_ISOLATION_LOWPWR S5P_PMUREG(0x1240)
-#define S5P_PAD_RETENTION_ALV_SEL_LOWPWR S5P_PMUREG(0x1260)
-#define S5P_XUSBXTI_LOWPWR S5P_PMUREG(0x1280)
-#define S5P_XXTI_LOWPWR S5P_PMUREG(0x1284)
-#define S5P_EXT_REGULATOR_LOWPWR S5P_PMUREG(0x12C0)
-#define S5P_GPIO_MODE_LOWPWR S5P_PMUREG(0x1300)
-#define S5P_GPIO_MODE_MAUDIO_LOWPWR S5P_PMUREG(0x1340)
-#define S5P_CAM_LOWPWR S5P_PMUREG(0x1380)
-#define S5P_TV_LOWPWR S5P_PMUREG(0x1384)
-#define S5P_MFC_LOWPWR S5P_PMUREG(0x1388)
-#define S5P_G3D_LOWPWR S5P_PMUREG(0x138C)
-#define S5P_LCD0_LOWPWR S5P_PMUREG(0x1390)
-#define S5P_MAUDIO_LOWPWR S5P_PMUREG(0x1398)
-#define S5P_GPS_LOWPWR S5P_PMUREG(0x139C)
-#define S5P_GPS_ALIVE_LOWPWR S5P_PMUREG(0x13A0)
+#define S5P_ARM_CORE0_LOWPWR 0x1000
+#define S5P_DIS_IRQ_CORE0 0x1004
+#define S5P_DIS_IRQ_CENTRAL0 0x1008
+#define S5P_ARM_CORE1_LOWPWR 0x1010
+#define S5P_DIS_IRQ_CORE1 0x1014
+#define S5P_DIS_IRQ_CENTRAL1 0x1018
+#define S5P_ARM_COMMON_LOWPWR 0x1080
+#define S5P_L2_0_LOWPWR 0x10C0
+#define S5P_L2_1_LOWPWR 0x10C4
+#define S5P_CMU_ACLKSTOP_LOWPWR 0x1100
+#define S5P_CMU_SCLKSTOP_LOWPWR 0x1104
+#define S5P_CMU_RESET_LOWPWR 0x110C
+#define S5P_APLL_SYSCLK_LOWPWR 0x1120
+#define S5P_MPLL_SYSCLK_LOWPWR 0x1124
+#define S5P_VPLL_SYSCLK_LOWPWR 0x1128
+#define S5P_EPLL_SYSCLK_LOWPWR 0x112C
+#define S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR 0x1138
+#define S5P_CMU_RESET_GPSALIVE_LOWPWR 0x113C
+#define S5P_CMU_CLKSTOP_CAM_LOWPWR 0x1140
+#define S5P_CMU_CLKSTOP_TV_LOWPWR 0x1144
+#define S5P_CMU_CLKSTOP_MFC_LOWPWR 0x1148
+#define S5P_CMU_CLKSTOP_G3D_LOWPWR 0x114C
+#define S5P_CMU_CLKSTOP_LCD0_LOWPWR 0x1150
+#define S5P_CMU_CLKSTOP_MAUDIO_LOWPWR 0x1158
+#define S5P_CMU_CLKSTOP_GPS_LOWPWR 0x115C
+#define S5P_CMU_RESET_CAM_LOWPWR 0x1160
+#define S5P_CMU_RESET_TV_LOWPWR 0x1164
+#define S5P_CMU_RESET_MFC_LOWPWR 0x1168
+#define S5P_CMU_RESET_G3D_LOWPWR 0x116C
+#define S5P_CMU_RESET_LCD0_LOWPWR 0x1170
+#define S5P_CMU_RESET_MAUDIO_LOWPWR 0x1178
+#define S5P_CMU_RESET_GPS_LOWPWR 0x117C
+#define S5P_TOP_BUS_LOWPWR 0x1180
+#define S5P_TOP_RETENTION_LOWPWR 0x1184
+#define S5P_TOP_PWR_LOWPWR 0x1188
+#define S5P_LOGIC_RESET_LOWPWR 0x11A0
+#define S5P_ONENAND_MEM_LOWPWR 0x11C0
+#define S5P_G2D_ACP_MEM_LOWPWR 0x11C8
+#define S5P_USBOTG_MEM_LOWPWR 0x11CC
+#define S5P_HSMMC_MEM_LOWPWR 0x11D0
+#define S5P_CSSYS_MEM_LOWPWR 0x11D4
+#define S5P_SECSS_MEM_LOWPWR 0x11D8
+#define S5P_PAD_RETENTION_DRAM_LOWPWR 0x1200
+#define S5P_PAD_RETENTION_MAUDIO_LOWPWR 0x1204
+#define S5P_PAD_RETENTION_GPIO_LOWPWR 0x1220
+#define S5P_PAD_RETENTION_UART_LOWPWR 0x1224
+#define S5P_PAD_RETENTION_MMCA_LOWPWR 0x1228
+#define S5P_PAD_RETENTION_MMCB_LOWPWR 0x122C
+#define S5P_PAD_RETENTION_EBIA_LOWPWR 0x1230
+#define S5P_PAD_RETENTION_EBIB_LOWPWR 0x1234
+#define S5P_PAD_RETENTION_ISOLATION_LOWPWR 0x1240
+#define S5P_PAD_RETENTION_ALV_SEL_LOWPWR 0x1260
+#define S5P_XUSBXTI_LOWPWR 0x1280
+#define S5P_XXTI_LOWPWR 0x1284
+#define S5P_EXT_REGULATOR_LOWPWR 0x12C0
+#define S5P_GPIO_MODE_LOWPWR 0x1300
+#define S5P_GPIO_MODE_MAUDIO_LOWPWR 0x1340
+#define S5P_CAM_LOWPWR 0x1380
+#define S5P_TV_LOWPWR 0x1384
+#define S5P_MFC_LOWPWR 0x1388
+#define S5P_G3D_LOWPWR 0x138C
+#define S5P_LCD0_LOWPWR 0x1390
+#define S5P_MAUDIO_LOWPWR 0x1398
+#define S5P_GPS_LOWPWR 0x139C
+#define S5P_GPS_ALIVE_LOWPWR 0x13A0

-#define S5P_ARM_CORE1_CONFIGURATION S5P_PMUREG(0x2080)
-#define S5P_ARM_CORE1_STATUS S5P_PMUREG(0x2084)
+#define S5P_ARM_CORE1_CONFIGURATION 0x2080
+#define S5P_ARM_CORE1_STATUS 0x2084

-#define S5P_PAD_RET_MAUDIO_OPTION S5P_PMUREG(0x3028)
-#define S5P_PAD_RET_GPIO_OPTION S5P_PMUREG(0x3108)
-#define S5P_PAD_RET_UART_OPTION S5P_PMUREG(0x3128)
-#define S5P_PAD_RET_MMCA_OPTION S5P_PMUREG(0x3148)
-#define S5P_PAD_RET_MMCB_OPTION S5P_PMUREG(0x3168)
-#define S5P_PAD_RET_EBIA_OPTION S5P_PMUREG(0x3188)
-#define S5P_PAD_RET_EBIB_OPTION S5P_PMUREG(0x31A8)
+#define S5P_PAD_RET_MAUDIO_OPTION 0x3028
+#define S5P_PAD_RET_GPIO_OPTION 0x3108
+#define S5P_PAD_RET_UART_OPTION 0x3128
+#define S5P_PAD_RET_MMCA_OPTION 0x3148
+#define S5P_PAD_RET_MMCB_OPTION 0x3168
+#define S5P_PAD_RET_EBIA_OPTION 0x3188
+#define S5P_PAD_RET_EBIB_OPTION 0x31A8

#define S5P_CORE_LOCAL_PWR_EN 0x3

/* Only for EXYNOS4210 */
-#define S5P_CMU_CLKSTOP_LCD1_LOWPWR S5P_PMUREG(0x1154)
-#define S5P_CMU_RESET_LCD1_LOWPWR S5P_PMUREG(0x1174)
-#define S5P_MODIMIF_MEM_LOWPWR S5P_PMUREG(0x11C4)
-#define S5P_PCIE_MEM_LOWPWR S5P_PMUREG(0x11E0)
-#define S5P_SATA_MEM_LOWPWR S5P_PMUREG(0x11E4)
-#define S5P_LCD1_LOWPWR S5P_PMUREG(0x1394)
+#define S5P_CMU_CLKSTOP_LCD1_LOWPWR 0x1154
+#define S5P_CMU_RESET_LCD1_LOWPWR 0x1174
+#define S5P_MODIMIF_MEM_LOWPWR 0x11C4
+#define S5P_PCIE_MEM_LOWPWR 0x11E0
+#define S5P_SATA_MEM_LOWPWR 0x11E4
+#define S5P_LCD1_LOWPWR 0x1394

/* Only for EXYNOS4x12 */
-#define S5P_ISP_ARM_LOWPWR S5P_PMUREG(0x1050)
-#define S5P_DIS_IRQ_ISP_ARM_LOCAL_LOWPWR S5P_PMUREG(0x1054)
-#define S5P_DIS_IRQ_ISP_ARM_CENTRAL_LOWPWR S5P_PMUREG(0x1058)
-#define S5P_CMU_ACLKSTOP_COREBLK_LOWPWR S5P_PMUREG(0x1110)
-#define S5P_CMU_SCLKSTOP_COREBLK_LOWPWR S5P_PMUREG(0x1114)
-#define S5P_CMU_RESET_COREBLK_LOWPWR S5P_PMUREG(0x111C)
-#define S5P_MPLLUSER_SYSCLK_LOWPWR S5P_PMUREG(0x1130)
-#define S5P_CMU_CLKSTOP_ISP_LOWPWR S5P_PMUREG(0x1154)
-#define S5P_CMU_RESET_ISP_LOWPWR S5P_PMUREG(0x1174)
-#define S5P_TOP_BUS_COREBLK_LOWPWR S5P_PMUREG(0x1190)
-#define S5P_TOP_RETENTION_COREBLK_LOWPWR S5P_PMUREG(0x1194)
-#define S5P_TOP_PWR_COREBLK_LOWPWR S5P_PMUREG(0x1198)
-#define S5P_OSCCLK_GATE_LOWPWR S5P_PMUREG(0x11A4)
-#define S5P_LOGIC_RESET_COREBLK_LOWPWR S5P_PMUREG(0x11B0)
-#define S5P_OSCCLK_GATE_COREBLK_LOWPWR S5P_PMUREG(0x11B4)
-#define S5P_HSI_MEM_LOWPWR S5P_PMUREG(0x11C4)
-#define S5P_ROTATOR_MEM_LOWPWR S5P_PMUREG(0x11DC)
-#define S5P_PAD_RETENTION_GPIO_COREBLK_LOWPWR S5P_PMUREG(0x123C)
-#define S5P_PAD_ISOLATION_COREBLK_LOWPWR S5P_PMUREG(0x1250)
-#define S5P_GPIO_MODE_COREBLK_LOWPWR S5P_PMUREG(0x1320)
-#define S5P_TOP_ASB_RESET_LOWPWR S5P_PMUREG(0x1344)
-#define S5P_TOP_ASB_ISOLATION_LOWPWR S5P_PMUREG(0x1348)
-#define S5P_ISP_LOWPWR S5P_PMUREG(0x1394)
-#define S5P_DRAM_FREQ_DOWN_LOWPWR S5P_PMUREG(0x13B0)
-#define S5P_DDRPHY_DLLOFF_LOWPWR S5P_PMUREG(0x13B4)
-#define S5P_CMU_SYSCLK_ISP_LOWPWR S5P_PMUREG(0x13B8)
-#define S5P_CMU_SYSCLK_GPS_LOWPWR S5P_PMUREG(0x13BC)
-#define S5P_LPDDR_PHY_DLL_LOCK_LOWPWR S5P_PMUREG(0x13C0)
+#define S5P_ISP_ARM_LOWPWR 0x1050
+#define S5P_DIS_IRQ_ISP_ARM_LOCAL_LOWPWR 0x1054
+#define S5P_DIS_IRQ_ISP_ARM_CENTRAL_LOWPWR 0x1058
+#define S5P_CMU_ACLKSTOP_COREBLK_LOWPWR 0x1110
+#define S5P_CMU_SCLKSTOP_COREBLK_LOWPWR 0x1114
+#define S5P_CMU_RESET_COREBLK_LOWPWR 0x111C
+#define S5P_MPLLUSER_SYSCLK_LOWPWR 0x1130
+#define S5P_CMU_CLKSTOP_ISP_LOWPWR 0x1154
+#define S5P_CMU_RESET_ISP_LOWPWR 0x1174
+#define S5P_TOP_BUS_COREBLK_LOWPWR 0x1190
+#define S5P_TOP_RETENTION_COREBLK_LOWPWR 0x1194
+#define S5P_TOP_PWR_COREBLK_LOWPWR 0x1198
+#define S5P_OSCCLK_GATE_LOWPWR 0x11A4
+#define S5P_LOGIC_RESET_COREBLK_LOWPWR 0x11B0
+#define S5P_OSCCLK_GATE_COREBLK_LOWPWR 0x11B4
+#define S5P_HSI_MEM_LOWPWR 0x11C4
+#define S5P_ROTATOR_MEM_LOWPWR 0x11DC
+#define S5P_PAD_RETENTION_GPIO_COREBLK_LOWPWR 0x123C
+#define S5P_PAD_ISOLATION_COREBLK_LOWPWR 0x1250
+#define S5P_GPIO_MODE_COREBLK_LOWPWR 0x1320
+#define S5P_TOP_ASB_RESET_LOWPWR 0x1344
+#define S5P_TOP_ASB_ISOLATION_LOWPWR 0x1348
+#define S5P_ISP_LOWPWR 0x1394
+#define S5P_DRAM_FREQ_DOWN_LOWPWR 0x13B0
+#define S5P_DDRPHY_DLLOFF_LOWPWR 0x13B4
+#define S5P_CMU_SYSCLK_ISP_LOWPWR 0x13B8
+#define S5P_CMU_SYSCLK_GPS_LOWPWR 0x13BC
+#define S5P_LPDDR_PHY_DLL_LOCK_LOWPWR 0x13C0

-#define S5P_ARM_L2_0_OPTION S5P_PMUREG(0x2608)
-#define S5P_ARM_L2_1_OPTION S5P_PMUREG(0x2628)
-#define S5P_ONENAND_MEM_OPTION S5P_PMUREG(0x2E08)
-#define S5P_HSI_MEM_OPTION S5P_PMUREG(0x2E28)
-#define S5P_G2D_ACP_MEM_OPTION S5P_PMUREG(0x2E48)
-#define S5P_USBOTG_MEM_OPTION S5P_PMUREG(0x2E68)
-#define S5P_HSMMC_MEM_OPTION S5P_PMUREG(0x2E88)
-#define S5P_CSSYS_MEM_OPTION S5P_PMUREG(0x2EA8)
-#define S5P_SECSS_MEM_OPTION S5P_PMUREG(0x2EC8)
-#define S5P_ROTATOR_MEM_OPTION S5P_PMUREG(0x2F48)
+#define S5P_ARM_L2_0_OPTION 0x2608
+#define S5P_ARM_L2_1_OPTION 0x2628
+#define S5P_ONENAND_MEM_OPTION 0x2E08
+#define S5P_HSI_MEM_OPTION 0x2E28
+#define S5P_G2D_ACP_MEM_OPTION 0x2E48
+#define S5P_USBOTG_MEM_OPTION 0x2E68
+#define S5P_HSMMC_MEM_OPTION 0x2E88
+#define S5P_CSSYS_MEM_OPTION 0x2EA8
+#define S5P_SECSS_MEM_OPTION 0x2EC8
+#define S5P_ROTATOR_MEM_OPTION 0x2F48

/* Only for EXYNOS4412 */
-#define S5P_ARM_CORE2_LOWPWR S5P_PMUREG(0x1020)
-#define S5P_DIS_IRQ_CORE2 S5P_PMUREG(0x1024)
-#define S5P_DIS_IRQ_CENTRAL2 S5P_PMUREG(0x1028)
-#define S5P_ARM_CORE3_LOWPWR S5P_PMUREG(0x1030)
-#define S5P_DIS_IRQ_CORE3 S5P_PMUREG(0x1034)
-#define S5P_DIS_IRQ_CENTRAL3 S5P_PMUREG(0x1038)
+#define S5P_ARM_CORE2_LOWPWR 0x1020
+#define S5P_DIS_IRQ_CORE2 0x1024
+#define S5P_DIS_IRQ_CENTRAL2 0x1028
+#define S5P_ARM_CORE3_LOWPWR 0x1030
+#define S5P_DIS_IRQ_CORE3 0x1034
+#define S5P_DIS_IRQ_CENTRAL3 0x1038

/* For EXYNOS5 */

-#define EXYNOS5_AUTO_WDTRESET_DISABLE S5P_PMUREG(0x0408)
-#define EXYNOS5_MASK_WDTRESET_REQUEST S5P_PMUREG(0x040C)
+#define EXYNOS5_AUTO_WDTRESET_DISABLE 0x0408
+#define EXYNOS5_MASK_WDTRESET_REQUEST 0x040C

#define EXYNOS5_SYS_WDTRESET (1 << 20)

-#define EXYNOS5_ARM_CORE0_SYS_PWR_REG S5P_PMUREG(0x1000)
-#define EXYNOS5_DIS_IRQ_ARM_CORE0_LOCAL_SYS_PWR_REG S5P_PMUREG(0x1004)
-#define EXYNOS5_DIS_IRQ_ARM_CORE0_CENTRAL_SYS_PWR_REG S5P_PMUREG(0x1008)
-#define EXYNOS5_ARM_CORE1_SYS_PWR_REG S5P_PMUREG(0x1010)
-#define EXYNOS5_DIS_IRQ_ARM_CORE1_LOCAL_SYS_PWR_REG S5P_PMUREG(0x1014)
-#define EXYNOS5_DIS_IRQ_ARM_CORE1_CENTRAL_SYS_PWR_REG S5P_PMUREG(0x1018)
-#define EXYNOS5_FSYS_ARM_SYS_PWR_REG S5P_PMUREG(0x1040)
-#define EXYNOS5_DIS_IRQ_FSYS_ARM_CENTRAL_SYS_PWR_REG S5P_PMUREG(0x1048)
-#define EXYNOS5_ISP_ARM_SYS_PWR_REG S5P_PMUREG(0x1050)
-#define EXYNOS5_DIS_IRQ_ISP_ARM_LOCAL_SYS_PWR_REG S5P_PMUREG(0x1054)
-#define EXYNOS5_DIS_IRQ_ISP_ARM_CENTRAL_SYS_PWR_REG S5P_PMUREG(0x1058)
-#define EXYNOS5_ARM_COMMON_SYS_PWR_REG S5P_PMUREG(0x1080)
-#define EXYNOS5_ARM_L2_SYS_PWR_REG S5P_PMUREG(0x10C0)
-#define EXYNOS5_CMU_ACLKSTOP_SYS_PWR_REG S5P_PMUREG(0x1100)
-#define EXYNOS5_CMU_SCLKSTOP_SYS_PWR_REG S5P_PMUREG(0x1104)
-#define EXYNOS5_CMU_RESET_SYS_PWR_REG S5P_PMUREG(0x110C)
-#define EXYNOS5_CMU_ACLKSTOP_SYSMEM_SYS_PWR_REG S5P_PMUREG(0x1120)
-#define EXYNOS5_CMU_SCLKSTOP_SYSMEM_SYS_PWR_REG S5P_PMUREG(0x1124)
-#define EXYNOS5_CMU_RESET_SYSMEM_SYS_PWR_REG S5P_PMUREG(0x112C)
-#define EXYNOS5_DRAM_FREQ_DOWN_SYS_PWR_REG S5P_PMUREG(0x1130)
-#define EXYNOS5_DDRPHY_DLLOFF_SYS_PWR_REG S5P_PMUREG(0x1134)
-#define EXYNOS5_DDRPHY_DLLLOCK_SYS_PWR_REG S5P_PMUREG(0x1138)
-#define EXYNOS5_APLL_SYSCLK_SYS_PWR_REG S5P_PMUREG(0x1140)
-#define EXYNOS5_MPLL_SYSCLK_SYS_PWR_REG S5P_PMUREG(0x1144)
-#define EXYNOS5_VPLL_SYSCLK_SYS_PWR_REG S5P_PMUREG(0x1148)
-#define EXYNOS5_EPLL_SYSCLK_SYS_PWR_REG S5P_PMUREG(0x114C)
-#define EXYNOS5_BPLL_SYSCLK_SYS_PWR_REG S5P_PMUREG(0x1150)
-#define EXYNOS5_CPLL_SYSCLK_SYS_PWR_REG S5P_PMUREG(0x1154)
-#define EXYNOS5_MPLLUSER_SYSCLK_SYS_PWR_REG S5P_PMUREG(0x1164)
-#define EXYNOS5_BPLLUSER_SYSCLK_SYS_PWR_REG S5P_PMUREG(0x1170)
-#define EXYNOS5_TOP_BUS_SYS_PWR_REG S5P_PMUREG(0x1180)
-#define EXYNOS5_TOP_RETENTION_SYS_PWR_REG S5P_PMUREG(0x1184)
-#define EXYNOS5_TOP_PWR_SYS_PWR_REG S5P_PMUREG(0x1188)
-#define EXYNOS5_TOP_BUS_SYSMEM_SYS_PWR_REG S5P_PMUREG(0x1190)
-#define EXYNOS5_TOP_RETENTION_SYSMEM_SYS_PWR_REG S5P_PMUREG(0x1194)
-#define EXYNOS5_TOP_PWR_SYSMEM_SYS_PWR_REG S5P_PMUREG(0x1198)
-#define EXYNOS5_LOGIC_RESET_SYS_PWR_REG S5P_PMUREG(0x11A0)
-#define EXYNOS5_OSCCLK_GATE_SYS_PWR_REG S5P_PMUREG(0x11A4)
-#define EXYNOS5_LOGIC_RESET_SYSMEM_SYS_PWR_REG S5P_PMUREG(0x11B0)
-#define EXYNOS5_OSCCLK_GATE_SYSMEM_SYS_PWR_REG S5P_PMUREG(0x11B4)
-#define EXYNOS5_USBOTG_MEM_SYS_PWR_REG S5P_PMUREG(0x11C0)
-#define EXYNOS5_G2D_MEM_SYS_PWR_REG S5P_PMUREG(0x11C8)
-#define EXYNOS5_USBDRD_MEM_SYS_PWR_REG S5P_PMUREG(0x11CC)
-#define EXYNOS5_SDMMC_MEM_SYS_PWR_REG S5P_PMUREG(0x11D0)
-#define EXYNOS5_CSSYS_MEM_SYS_PWR_REG S5P_PMUREG(0x11D4)
-#define EXYNOS5_SECSS_MEM_SYS_PWR_REG S5P_PMUREG(0x11D8)
-#define EXYNOS5_ROTATOR_MEM_SYS_PWR_REG S5P_PMUREG(0x11DC)
-#define EXYNOS5_INTRAM_MEM_SYS_PWR_REG S5P_PMUREG(0x11E0)
-#define EXYNOS5_INTROM_MEM_SYS_PWR_REG S5P_PMUREG(0x11E4)
-#define EXYNOS5_JPEG_MEM_SYS_PWR_REG S5P_PMUREG(0x11E8)
-#define EXYNOS5_HSI_MEM_SYS_PWR_REG S5P_PMUREG(0x11EC)
-#define EXYNOS5_MCUIOP_MEM_SYS_PWR_REG S5P_PMUREG(0x11F4)
-#define EXYNOS5_SATA_MEM_SYS_PWR_REG S5P_PMUREG(0x11FC)
-#define EXYNOS5_PAD_RETENTION_DRAM_SYS_PWR_REG S5P_PMUREG(0x1200)
-#define EXYNOS5_PAD_RETENTION_MAU_SYS_PWR_REG S5P_PMUREG(0x1204)
-#define EXYNOS5_PAD_RETENTION_EFNAND_SYS_PWR_REG S5P_PMUREG(0x1208)
-#define EXYNOS5_PAD_RETENTION_GPIO_SYS_PWR_REG S5P_PMUREG(0x1220)
-#define EXYNOS5_PAD_RETENTION_UART_SYS_PWR_REG S5P_PMUREG(0x1224)
-#define EXYNOS5_PAD_RETENTION_MMCA_SYS_PWR_REG S5P_PMUREG(0x1228)
-#define EXYNOS5_PAD_RETENTION_MMCB_SYS_PWR_REG S5P_PMUREG(0x122C)
-#define EXYNOS5_PAD_RETENTION_EBIA_SYS_PWR_REG S5P_PMUREG(0x1230)
-#define EXYNOS5_PAD_RETENTION_EBIB_SYS_PWR_REG S5P_PMUREG(0x1234)
-#define EXYNOS5_PAD_RETENTION_SPI_SYS_PWR_REG S5P_PMUREG(0x1238)
-#define EXYNOS5_PAD_RETENTION_GPIO_SYSMEM_SYS_PWR_REG S5P_PMUREG(0x123C)
-#define EXYNOS5_PAD_ISOLATION_SYS_PWR_REG S5P_PMUREG(0x1240)
-#define EXYNOS5_PAD_ISOLATION_SYSMEM_SYS_PWR_REG S5P_PMUREG(0x1250)
-#define EXYNOS5_PAD_ALV_SEL_SYS_PWR_REG S5P_PMUREG(0x1260)
-#define EXYNOS5_XUSBXTI_SYS_PWR_REG S5P_PMUREG(0x1280)
-#define EXYNOS5_XXTI_SYS_PWR_REG S5P_PMUREG(0x1284)
-#define EXYNOS5_EXT_REGULATOR_SYS_PWR_REG S5P_PMUREG(0x12C0)
-#define EXYNOS5_GPIO_MODE_SYS_PWR_REG S5P_PMUREG(0x1300)
-#define EXYNOS5_GPIO_MODE_SYSMEM_SYS_PWR_REG S5P_PMUREG(0x1320)
-#define EXYNOS5_GPIO_MODE_MAU_SYS_PWR_REG S5P_PMUREG(0x1340)
-#define EXYNOS5_TOP_ASB_RESET_SYS_PWR_REG S5P_PMUREG(0x1344)
-#define EXYNOS5_TOP_ASB_ISOLATION_SYS_PWR_REG S5P_PMUREG(0x1348)
-#define EXYNOS5_GSCL_SYS_PWR_REG S5P_PMUREG(0x1400)
-#define EXYNOS5_ISP_SYS_PWR_REG S5P_PMUREG(0x1404)
-#define EXYNOS5_MFC_SYS_PWR_REG S5P_PMUREG(0x1408)
-#define EXYNOS5_G3D_SYS_PWR_REG S5P_PMUREG(0x140C)
-#define EXYNOS5_DISP1_SYS_PWR_REG S5P_PMUREG(0x1414)
-#define EXYNOS5_MAU_SYS_PWR_REG S5P_PMUREG(0x1418)
-#define EXYNOS5_CMU_CLKSTOP_GSCL_SYS_PWR_REG S5P_PMUREG(0x1480)
-#define EXYNOS5_CMU_CLKSTOP_ISP_SYS_PWR_REG S5P_PMUREG(0x1484)
-#define EXYNOS5_CMU_CLKSTOP_MFC_SYS_PWR_REG S5P_PMUREG(0x1488)
-#define EXYNOS5_CMU_CLKSTOP_G3D_SYS_PWR_REG S5P_PMUREG(0x148C)
-#define EXYNOS5_CMU_CLKSTOP_DISP1_SYS_PWR_REG S5P_PMUREG(0x1494)
-#define EXYNOS5_CMU_CLKSTOP_MAU_SYS_PWR_REG S5P_PMUREG(0x1498)
-#define EXYNOS5_CMU_SYSCLK_GSCL_SYS_PWR_REG S5P_PMUREG(0x14C0)
-#define EXYNOS5_CMU_SYSCLK_ISP_SYS_PWR_REG S5P_PMUREG(0x14C4)
-#define EXYNOS5_CMU_SYSCLK_MFC_SYS_PWR_REG S5P_PMUREG(0x14C8)
-#define EXYNOS5_CMU_SYSCLK_G3D_SYS_PWR_REG S5P_PMUREG(0x14CC)
-#define EXYNOS5_CMU_SYSCLK_DISP1_SYS_PWR_REG S5P_PMUREG(0x14D4)
-#define EXYNOS5_CMU_SYSCLK_MAU_SYS_PWR_REG S5P_PMUREG(0x14D8)
-#define EXYNOS5_CMU_RESET_GSCL_SYS_PWR_REG S5P_PMUREG(0x1580)
-#define EXYNOS5_CMU_RESET_ISP_SYS_PWR_REG S5P_PMUREG(0x1584)
-#define EXYNOS5_CMU_RESET_MFC_SYS_PWR_REG S5P_PMUREG(0x1588)
-#define EXYNOS5_CMU_RESET_G3D_SYS_PWR_REG S5P_PMUREG(0x158C)
-#define EXYNOS5_CMU_RESET_DISP1_SYS_PWR_REG S5P_PMUREG(0x1594)
-#define EXYNOS5_CMU_RESET_MAU_SYS_PWR_REG S5P_PMUREG(0x1598)
+#define EXYNOS5_ARM_CORE0_SYS_PWR_REG 0x1000
+#define EXYNOS5_DIS_IRQ_ARM_CORE0_LOCAL_SYS_PWR_REG 0x1004
+#define EXYNOS5_DIS_IRQ_ARM_CORE0_CENTRAL_SYS_PWR_REG 0x1008
+#define EXYNOS5_ARM_CORE1_SYS_PWR_REG 0x1010
+#define EXYNOS5_DIS_IRQ_ARM_CORE1_LOCAL_SYS_PWR_REG 0x1014
+#define EXYNOS5_DIS_IRQ_ARM_CORE1_CENTRAL_SYS_PWR_REG 0x1018
+#define EXYNOS5_FSYS_ARM_SYS_PWR_REG 0x1040
+#define EXYNOS5_DIS_IRQ_FSYS_ARM_CENTRAL_SYS_PWR_REG 0x1048
+#define EXYNOS5_ISP_ARM_SYS_PWR_REG 0x1050
+#define EXYNOS5_DIS_IRQ_ISP_ARM_LOCAL_SYS_PWR_REG 0x1054
+#define EXYNOS5_DIS_IRQ_ISP_ARM_CENTRAL_SYS_PWR_REG 0x1058
+#define EXYNOS5_ARM_COMMON_SYS_PWR_REG 0x1080
+#define EXYNOS5_ARM_L2_SYS_PWR_REG 0x10C0
+#define EXYNOS5_CMU_ACLKSTOP_SYS_PWR_REG 0x1100
+#define EXYNOS5_CMU_SCLKSTOP_SYS_PWR_REG 0x1104
+#define EXYNOS5_CMU_RESET_SYS_PWR_REG 0x110C
+#define EXYNOS5_CMU_ACLKSTOP_SYSMEM_SYS_PWR_REG 0x1120
+#define EXYNOS5_CMU_SCLKSTOP_SYSMEM_SYS_PWR_REG 0x1124
+#define EXYNOS5_CMU_RESET_SYSMEM_SYS_PWR_REG 0x112C
+#define EXYNOS5_DRAM_FREQ_DOWN_SYS_PWR_REG 0x1130
+#define EXYNOS5_DDRPHY_DLLOFF_SYS_PWR_REG 0x1134
+#define EXYNOS5_DDRPHY_DLLLOCK_SYS_PWR_REG 0x1138
+#define EXYNOS5_APLL_SYSCLK_SYS_PWR_REG 0x1140
+#define EXYNOS5_MPLL_SYSCLK_SYS_PWR_REG 0x1144
+#define EXYNOS5_VPLL_SYSCLK_SYS_PWR_REG 0x1148
+#define EXYNOS5_EPLL_SYSCLK_SYS_PWR_REG 0x114C
+#define EXYNOS5_BPLL_SYSCLK_SYS_PWR_REG 0x1150
+#define EXYNOS5_CPLL_SYSCLK_SYS_PWR_REG 0x1154
+#define EXYNOS5_MPLLUSER_SYSCLK_SYS_PWR_REG 0x1164
+#define EXYNOS5_BPLLUSER_SYSCLK_SYS_PWR_REG 0x1170
+#define EXYNOS5_TOP_BUS_SYS_PWR_REG 0x1180
+#define EXYNOS5_TOP_RETENTION_SYS_PWR_REG 0x1184
+#define EXYNOS5_TOP_PWR_SYS_PWR_REG 0x1188
+#define EXYNOS5_TOP_BUS_SYSMEM_SYS_PWR_REG 0x1190
+#define EXYNOS5_TOP_RETENTION_SYSMEM_SYS_PWR_REG 0x1194
+#define EXYNOS5_TOP_PWR_SYSMEM_SYS_PWR_REG 0x1198
+#define EXYNOS5_LOGIC_RESET_SYS_PWR_REG 0x11A0
+#define EXYNOS5_OSCCLK_GATE_SYS_PWR_REG 0x11A4
+#define EXYNOS5_LOGIC_RESET_SYSMEM_SYS_PWR_REG 0x11B0
+#define EXYNOS5_OSCCLK_GATE_SYSMEM_SYS_PWR_REG 0x11B4
+#define EXYNOS5_USBOTG_MEM_SYS_PWR_REG 0x11C0
+#define EXYNOS5_G2D_MEM_SYS_PWR_REG 0x11C8
+#define EXYNOS5_USBDRD_MEM_SYS_PWR_REG 0x11CC
+#define EXYNOS5_SDMMC_MEM_SYS_PWR_REG 0x11D0
+#define EXYNOS5_CSSYS_MEM_SYS_PWR_REG 0x11D4
+#define EXYNOS5_SECSS_MEM_SYS_PWR_REG 0x11D8
+#define EXYNOS5_ROTATOR_MEM_SYS_PWR_REG 0x11DC
+#define EXYNOS5_INTRAM_MEM_SYS_PWR_REG 0x11E0
+#define EXYNOS5_INTROM_MEM_SYS_PWR_REG 0x11E4
+#define EXYNOS5_JPEG_MEM_SYS_PWR_REG 0x11E8
+#define EXYNOS5_HSI_MEM_SYS_PWR_REG 0x11EC
+#define EXYNOS5_MCUIOP_MEM_SYS_PWR_REG 0x11F4
+#define EXYNOS5_SATA_MEM_SYS_PWR_REG 0x11FC
+#define EXYNOS5_PAD_RETENTION_DRAM_SYS_PWR_REG 0x1200
+#define EXYNOS5_PAD_RETENTION_MAU_SYS_PWR_REG 0x1204
+#define EXYNOS5_PAD_RETENTION_EFNAND_SYS_PWR_REG 0x1208
+#define EXYNOS5_PAD_RETENTION_GPIO_SYS_PWR_REG 0x1220
+#define EXYNOS5_PAD_RETENTION_UART_SYS_PWR_REG 0x1224
+#define EXYNOS5_PAD_RETENTION_MMCA_SYS_PWR_REG 0x1228
+#define EXYNOS5_PAD_RETENTION_MMCB_SYS_PWR_REG 0x122C
+#define EXYNOS5_PAD_RETENTION_EBIA_SYS_PWR_REG 0x1230
+#define EXYNOS5_PAD_RETENTION_EBIB_SYS_PWR_REG 0x1234
+#define EXYNOS5_PAD_RETENTION_SPI_SYS_PWR_REG 0x1238
+#define EXYNOS5_PAD_RETENTION_GPIO_SYSMEM_SYS_PWR_REG 0x123C
+#define EXYNOS5_PAD_ISOLATION_SYS_PWR_REG 0x1240
+#define EXYNOS5_PAD_ISOLATION_SYSMEM_SYS_PWR_REG 0x1250
+#define EXYNOS5_PAD_ALV_SEL_SYS_PWR_REG 0x1260
+#define EXYNOS5_XUSBXTI_SYS_PWR_REG 0x1280
+#define EXYNOS5_XXTI_SYS_PWR_REG 0x1284
+#define EXYNOS5_EXT_REGULATOR_SYS_PWR_REG 0x12C0
+#define EXYNOS5_GPIO_MODE_SYS_PWR_REG 0x1300
+#define EXYNOS5_GPIO_MODE_SYSMEM_SYS_PWR_REG 0x1320
+#define EXYNOS5_GPIO_MODE_MAU_SYS_PWR_REG 0x1340
+#define EXYNOS5_TOP_ASB_RESET_SYS_PWR_REG 0x1344
+#define EXYNOS5_TOP_ASB_ISOLATION_SYS_PWR_REG 0x1348
+#define EXYNOS5_GSCL_SYS_PWR_REG 0x1400
+#define EXYNOS5_ISP_SYS_PWR_REG 0x1404
+#define EXYNOS5_MFC_SYS_PWR_REG 0x1408
+#define EXYNOS5_G3D_SYS_PWR_REG 0x140C
+#define EXYNOS5_DISP1_SYS_PWR_REG 0x1414
+#define EXYNOS5_MAU_SYS_PWR_REG 0x1418
+#define EXYNOS5_CMU_CLKSTOP_GSCL_SYS_PWR_REG 0x1480
+#define EXYNOS5_CMU_CLKSTOP_ISP_SYS_PWR_REG 0x1484
+#define EXYNOS5_CMU_CLKSTOP_MFC_SYS_PWR_REG 0x1488
+#define EXYNOS5_CMU_CLKSTOP_G3D_SYS_PWR_REG 0x148C
+#define EXYNOS5_CMU_CLKSTOP_DISP1_SYS_PWR_REG 0x1494
+#define EXYNOS5_CMU_CLKSTOP_MAU_SYS_PWR_REG 0x1498
+#define EXYNOS5_CMU_SYSCLK_GSCL_SYS_PWR_REG 0x14C0
+#define EXYNOS5_CMU_SYSCLK_ISP_SYS_PWR_REG 0x14C4
+#define EXYNOS5_CMU_SYSCLK_MFC_SYS_PWR_REG 0x14C8
+#define EXYNOS5_CMU_SYSCLK_G3D_SYS_PWR_REG 0x14CC
+#define EXYNOS5_CMU_SYSCLK_DISP1_SYS_PWR_REG 0x14D4
+#define EXYNOS5_CMU_SYSCLK_MAU_SYS_PWR_REG 0x14D8
+#define EXYNOS5_CMU_RESET_GSCL_SYS_PWR_REG 0x1580
+#define EXYNOS5_CMU_RESET_ISP_SYS_PWR_REG 0x1584
+#define EXYNOS5_CMU_RESET_MFC_SYS_PWR_REG 0x1588
+#define EXYNOS5_CMU_RESET_G3D_SYS_PWR_REG 0x158C
+#define EXYNOS5_CMU_RESET_DISP1_SYS_PWR_REG 0x1594
+#define EXYNOS5_CMU_RESET_MAU_SYS_PWR_REG 0x1598

-#define EXYNOS5_ARM_CORE0_OPTION S5P_PMUREG(0x2008)
-#define EXYNOS5_ARM_CORE1_OPTION S5P_PMUREG(0x2088)
-#define EXYNOS5_FSYS_ARM_OPTION S5P_PMUREG(0x2208)
-#define EXYNOS5_ISP_ARM_OPTION S5P_PMUREG(0x2288)
-#define EXYNOS5_ARM_COMMON_OPTION S5P_PMUREG(0x2408)
-#define EXYNOS5_ARM_L2_OPTION S5P_PMUREG(0x2608)
-#define EXYNOS5_TOP_PWR_OPTION S5P_PMUREG(0x2C48)
-#define EXYNOS5_TOP_PWR_SYSMEM_OPTION S5P_PMUREG(0x2CC8)
-#define EXYNOS5_JPEG_MEM_OPTION S5P_PMUREG(0x2F48)
-#define EXYNOS5_GSCL_OPTION S5P_PMUREG(0x4008)
-#define EXYNOS5_ISP_OPTION S5P_PMUREG(0x4028)
-#define EXYNOS5_MFC_OPTION S5P_PMUREG(0x4048)
-#define EXYNOS5_G3D_OPTION S5P_PMUREG(0x4068)
-#define EXYNOS5_DISP1_OPTION S5P_PMUREG(0x40A8)
-#define EXYNOS5_MAU_OPTION S5P_PMUREG(0x40C8)
+#define EXYNOS5_ARM_CORE0_OPTION 0x2008
+#define EXYNOS5_ARM_CORE1_OPTION 0x2088
+#define EXYNOS5_FSYS_ARM_OPTION 0x2208
+#define EXYNOS5_ISP_ARM_OPTION 0x2288
+#define EXYNOS5_ARM_COMMON_OPTION 0x2408
+#define EXYNOS5_ARM_L2_OPTION 0x2608
+#define EXYNOS5_TOP_PWR_OPTION 0x2C48
+#define EXYNOS5_TOP_PWR_SYSMEM_OPTION 0x2CC8
+#define EXYNOS5_JPEG_MEM_OPTION 0x2F48
+#define EXYNOS5_GSCL_OPTION 0x4008
+#define EXYNOS5_ISP_OPTION 0x4028
+#define EXYNOS5_MFC_OPTION 0x4048
+#define EXYNOS5_G3D_OPTION 0x4068
+#define EXYNOS5_DISP1_OPTION 0x40A8
+#define EXYNOS5_MAU_OPTION 0x40C8

#define EXYNOS5_USE_SC_FEEDBACK (1 << 1)
#define EXYNOS5_USE_SC_COUNTER (1 << 0)
diff --git a/arch/arm/plat-samsung/include/plat/map-s5p.h b/arch/arm/plat-samsung/include/plat/map-s5p.h
index c186786..f5b9d3f 100644
--- a/arch/arm/plat-samsung/include/plat/map-s5p.h
+++ b/arch/arm/plat-samsung/include/plat/map-s5p.h
@@ -15,7 +15,6 @@

#define S5P_VA_CHIPID S3C_ADDR(0x02000000)
#define S5P_VA_CMU S3C_ADDR(0x02100000)
-#define S5P_VA_PMU S3C_ADDR(0x02180000)
#define S5P_VA_GPIO S3C_ADDR(0x02200000)
#define S5P_VA_GPIO1 S5P_VA_GPIO
#define S5P_VA_GPIO2 S3C_ADDR(0x02240000)
--
1.7.10.4

2014-04-30 05:01:01

by Pankaj Dubey

[permalink] [raw]
Subject: [PATCH v3 11/12] ARM: EXYNOS: Add platform driver support for Exynos PMU.

This patch modifies Exynos Power Management Unit (PMU) initialization
implementation in following way:

- Added platform_device support by registering static platform device.
- Added platform struct exynos_pmu_data to hold platform specific data.
- For each SoC's PMU support now we can add platform data and statically
bind PMU configuration and SoC specific initialization function.
- Probe function will scan DT and based on matching PMU compatibility
string initialize pmu_context which will be platform_data for driver.
- Obtain PMU regmap handle using "syscon_regmap_lookup_by_phandle" so
that we can reduce dependency over machine header files.
- Separate each SoC's PMU initialization function and make it as part of
platform data.
- It also removes uses of soc_is_exynosXXXX() thus making PMU implementation
independent of "plat/cpu.h".

Signed-off-by: Pankaj Dubey <[email protected]>
Signed-off-by: Young-Gun Jang <[email protected]>
---
arch/arm/mach-exynos/pmu.c | 280 +++++++++++++++++++++++++++++++++++---------
1 file changed, 224 insertions(+), 56 deletions(-)

diff --git a/arch/arm/mach-exynos/pmu.c b/arch/arm/mach-exynos/pmu.c
index 67116a5..030df96 100644
--- a/arch/arm/mach-exynos/pmu.c
+++ b/arch/arm/mach-exynos/pmu.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
* EXYNOS - CPU PMU(Power Management Unit) support
@@ -9,20 +9,33 @@
* published by the Free Software Foundation.
*/

-#include <linux/io.h>
-#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/regmap.h>
-
-#include <plat/cpu.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/mfd/syscon.h>

#include "common.h"
#include "regs-pmu.h"

-static const struct exynos_pmu_conf *exynos_pmu_config;
-static struct regmap *pmu_regmap;
+struct exynos_pmu_data {
+ const struct exynos_pmu_conf *pmu_config;
+ const struct exynos_pmu_conf *pmu_config_extra;
+ void (*pmu_init)(void);
+ void (*powerdown_conf)(enum sys_powerdown);
+};
+
+struct exynos_pmu_context {
+ struct device *dev;
+ struct exynos_pmu_data *pmu_data;
+ struct regmap *pmu_regmap;
+};
+
+static struct exynos_pmu_context *pmu_context;

static const struct exynos_pmu_conf exynos4210_pmu_config[] = {
- /* { .reg = address, .val = { AFTR, LPA, SLEEP } */
+ /* { .offset = address, .val = { AFTR, LPA, SLEEP } */
{ S5P_ARM_CORE0_LOWPWR, { 0x0, 0x0, 0x2 } },
{ S5P_DIS_IRQ_CORE0, { 0x0, 0x0, 0x0 } },
{ S5P_DIS_IRQ_CENTRAL0, { 0x0, 0x0, 0x0 } },
@@ -216,7 +229,7 @@ static const struct exynos_pmu_conf exynos4412_pmu_config[] = {
};

static const struct exynos_pmu_conf exynos5250_pmu_config[] = {
- /* { .reg = address, .val = { AFTR, LPA, SLEEP } */
+ /* { .offset = address, .val = { AFTR, LPA, SLEEP } */
{ EXYNOS5_ARM_CORE0_SYS_PWR_REG, { 0x0, 0x0, 0x2} },
{ EXYNOS5_DIS_IRQ_ARM_CORE0_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5_DIS_IRQ_ARM_CORE0_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
@@ -339,7 +352,7 @@ static unsigned int const exynos5_list_diable_wfi_wfe[] = {
EXYNOS5_ISP_ARM_OPTION,
};

-static void exynos5_init_pmu(void)
+void exynos5_powerdown_conf(enum sys_powerdown mode)
{
unsigned int i;
unsigned int tmp;
@@ -348,81 +361,236 @@ static void exynos5_init_pmu(void)
* Enable both SC_FEEDBACK and SC_COUNTER
*/
for (i = 0 ; i < ARRAY_SIZE(exynos5_list_both_cnt_feed) ; i++) {
- regmap_read(pmu_regmap, exynos5_list_both_cnt_feed[i], &tmp);
+ regmap_read(pmu_context->pmu_regmap,
+ exynos5_list_both_cnt_feed[i], &tmp);
tmp |= (EXYNOS5_USE_SC_FEEDBACK |
EXYNOS5_USE_SC_COUNTER);
- regmap_write(pmu_regmap, exynos5_list_both_cnt_feed[i], tmp);
+ regmap_write(pmu_context->pmu_regmap,
+ exynos5_list_both_cnt_feed[i], tmp);
}

/*
* SKIP_DEACTIVATE_ACEACP_IN_PWDN_BITFIELD Enable
*/
- regmap_read(pmu_regmap, EXYNOS5_ARM_COMMON_OPTION, &tmp);
+ regmap_read(pmu_context->pmu_regmap, EXYNOS5_ARM_COMMON_OPTION, &tmp);
tmp |= EXYNOS5_SKIP_DEACTIVATE_ACEACP_IN_PWDN;
- regmap_write(pmu_regmap, EXYNOS5_ARM_COMMON_OPTION, tmp);
+ regmap_write(pmu_context->pmu_regmap, EXYNOS5_ARM_COMMON_OPTION, tmp);

/*
* Disable WFI/WFE on XXX_OPTION
*/
for (i = 0 ; i < ARRAY_SIZE(exynos5_list_diable_wfi_wfe) ; i++) {
- tmp = regmap_read(pmu_regmap, exynos5_list_diable_wfi_wfe[i],
- &tmp);
+ tmp = regmap_read(pmu_context->pmu_regmap,
+ exynos5_list_diable_wfi_wfe[i], &tmp);
tmp &= ~(EXYNOS5_OPTION_USE_STANDBYWFE |
EXYNOS5_OPTION_USE_STANDBYWFI);
- regmap_write(pmu_regmap, exynos5_list_diable_wfi_wfe[i], tmp);
+ regmap_write(pmu_context->pmu_regmap,
+ exynos5_list_diable_wfi_wfe[i], tmp);
}
}

void exynos_sys_powerdown_conf(enum sys_powerdown mode)
{
unsigned int i;
+ struct exynos_pmu_data *pmu_data = pmu_context->pmu_data;

- if (soc_is_exynos5250())
- exynos5_init_pmu();
+ if (pmu_data->powerdown_conf)
+ pmu_data->powerdown_conf(mode);

- for (i = 0; (exynos_pmu_config[i].offset != PMU_TABLE_END) ; i++)
- regmap_write(pmu_regmap, exynos_pmu_config[i].offset,
- exynos_pmu_config[i].val[mode]);
+ if (pmu_data->pmu_config) {
+ for (i = 0; (pmu_data->pmu_config[i].offset != PMU_TABLE_END) ; i++)
+ regmap_write(pmu_context->pmu_regmap,
+ pmu_data->pmu_config[i].offset,
+ pmu_data->pmu_config[i].val[mode]);
+ }

- if (soc_is_exynos4412()) {
- for (i = 0; exynos4412_pmu_config[i].offset != PMU_TABLE_END; i++)
- regmap_write(pmu_regmap, exynos4412_pmu_config[i].offset,
- exynos4412_pmu_config[i].val[mode]);
+ if (pmu_data->pmu_config_extra) {
+ for (i = 0; pmu_data->pmu_config_extra[i].offset != PMU_TABLE_END; i++)
+ regmap_write(pmu_context->pmu_regmap,
+ pmu_data->pmu_config_extra[i].offset,
+ pmu_data->pmu_config_extra[i].val[mode]);
}
}

-static int __init exynos_pmu_init(void)
+static void exynos5250_pmu_init(void)
+{
+ unsigned int tmp;
+ struct regmap *pmu_regmap = pmu_context->pmu_regmap;
+ /*
+ * When SYS_WDTRESET is set, watchdog timer reset request
+ * is ignored by power management unit.
+ */
+ regmap_read(pmu_regmap, EXYNOS5_AUTO_WDTRESET_DISABLE, &tmp);
+ tmp &= ~EXYNOS5_SYS_WDTRESET;
+ regmap_write(pmu_regmap, EXYNOS5_AUTO_WDTRESET_DISABLE, tmp);
+
+ regmap_read(pmu_regmap, EXYNOS5_MASK_WDTRESET_REQUEST, &tmp);
+ tmp &= ~EXYNOS5_SYS_WDTRESET;
+ regmap_write(pmu_regmap, EXYNOS5_MASK_WDTRESET_REQUEST, tmp);
+}
+
+static struct exynos_pmu_data exynos4210_pmu_data = {
+ .pmu_config = exynos4210_pmu_config,
+};
+
+static struct exynos_pmu_data exynos4x12_pmu_data = {
+ .pmu_config = exynos4x12_pmu_config,
+};
+
+static struct exynos_pmu_data exynos4412_pmu_data = {
+ .pmu_config = exynos4x12_pmu_config,
+ .pmu_config_extra = exynos4412_pmu_config,
+};
+
+static struct exynos_pmu_data exynos5250_pmu_data = {
+ .pmu_config = exynos5250_pmu_config,
+ .pmu_init = exynos5250_pmu_init,
+ .powerdown_conf = exynos5_powerdown_conf,
+};
+
+/*
+ * PMU platform driver and devicetree bindings.
+ */
+static struct of_device_id exynos_pmu_of_device_ids[] = {
+ {
+ .compatible = "samsung,exynos4210-pmu",
+ .data = (void *)&exynos4210_pmu_data,
+ },
+ {
+ .compatible = "samsung,exynos4212-pmu",
+ .data = (void *)&exynos4x12_pmu_data,
+ },
+ {
+ .compatible = "samsung,exynos4412-pmu",
+ .data = (void *)&exynos4412_pmu_data,
+ },
+ {
+ .compatible = "samsung,exynos5250-pmu",
+ .data = (void *)&exynos5250_pmu_data,
+ },
+ {},
+};
+
+static int exynos_pmu_data_init(struct device_node *np)
{
- unsigned int value;
-
- exynos_pmu_config = exynos4210_pmu_config;
- pmu_regmap = get_exynos_pmuregmap();
-
- if (soc_is_exynos4210()) {
- exynos_pmu_config = exynos4210_pmu_config;
- pr_info("EXYNOS4210 PMU Initialize\n");
- } else if (soc_is_exynos4212() || soc_is_exynos4412()) {
- exynos_pmu_config = exynos4x12_pmu_config;
- pr_info("EXYNOS4x12 PMU Initialize\n");
- } else if (soc_is_exynos5250()) {
- /*
- * When SYS_WDTRESET is set, watchdog timer reset request
- * is ignored by power management unit.
- */
- regmap_read(pmu_regmap, EXYNOS5_AUTO_WDTRESET_DISABLE, &value);
- value &= ~EXYNOS5_SYS_WDTRESET;
- regmap_write(pmu_regmap, EXYNOS5_AUTO_WDTRESET_DISABLE, value);
-
- regmap_read(pmu_regmap, EXYNOS5_MASK_WDTRESET_REQUEST, &value);
- value &= ~EXYNOS5_SYS_WDTRESET;
- regmap_write(pmu_regmap, EXYNOS5_MASK_WDTRESET_REQUEST, value);
-
- exynos_pmu_config = exynos5250_pmu_config;
- pr_info("EXYNOS5250 PMU Initialize\n");
- } else {
- pr_info("EXYNOS: PMU not supported\n");
+ const struct of_device_id *match;
+
+ match = of_match_node(exynos_pmu_of_device_ids, np);
+ if (!match) {
+ pr_err("fail to get matching of_match struct\n");
+ return -EINVAL;
+ }
+
+ pmu_context->pmu_data = (struct exynos_pmu_data *) match->data;
+ pmu_context->pmu_regmap = syscon_regmap_lookup_by_phandle(np,
+ "samsung,syscon-phandle");
+
+ if (IS_ERR(pmu_context->pmu_regmap)) {
+ pr_err("failed to find exynos_pmu_regmap\n");
+ return PTR_ERR(pmu_context->pmu_regmap);
}

+ if (pmu_context->pmu_data->pmu_init)
+ pmu_context->pmu_data->pmu_init();
+
+ return 0;
+};
+
+static int exynos_pmu_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct device_node *np;
+ struct device *dev = &pdev->dev;
+
+ pmu_context = devm_kzalloc(&pdev->dev,
+ sizeof(struct exynos_pmu_context),
+ GFP_KERNEL);
+ if (pmu_context == NULL) {
+ dev_err(dev, "Cannot allocate memory.\n");
+ return -ENOMEM;
+ }
+
+ for_each_matching_node_and_match(np, exynos_pmu_of_device_ids, NULL) {
+ ret = exynos_pmu_data_init(np);
+ if (ret < 0)
+ return ret;
+ break;
+ }
+
+ pmu_context->dev = dev;
+
+ platform_set_drvdata(pdev, pmu_context);
+
+ pr_info("Exynos PMU Driver probe done!!!\n");
+ return 0;
+}
+
+static int exynos_pmu_suspend(struct device *dev)
+{
+ /* ToDo: */
return 0;
}
-arch_initcall(exynos_pmu_init);
+
+static int exynos_pmu_resume(struct device *dev)
+{
+ /* ToDo: */
+ return 0;
+}
+
+static const struct dev_pm_ops exynos_pmu_pm = {
+ .suspend = exynos_pmu_suspend,
+ .resume = exynos_pmu_resume,
+};
+
+static int exynos_pmu_remove(struct platform_device *pdev)
+{
+ /* nothing to do here */
+ return 0;
+}
+
+static struct platform_device *exynos_pmu_pdev;
+
+static struct platform_driver exynos_pmu_driver = {
+ .driver = {
+ .name = "exynos-pmu",
+ .owner = THIS_MODULE,
+ .pm = &exynos_pmu_pm,
+ },
+ .probe = exynos_pmu_probe,
+ .remove = exynos_pmu_remove,
+};
+
+static int __init exynos_pmu_of_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&exynos_pmu_driver);
+ if (ret < 0)
+ goto out;
+
+ exynos_pmu_pdev = platform_device_register_simple("exynos-pmu", -1,
+ NULL, 0);
+
+ if (IS_ERR(exynos_pmu_pdev)) {
+ ret = PTR_ERR(exynos_pmu_pdev);
+ goto out1;
+ }
+
+ return 0;
+out1:
+ platform_driver_unregister(&exynos_pmu_driver);
+out:
+ return ret;
+}
+arch_initcall(exynos_pmu_of_init);
+
+static void __exit exynos_pmu_exit(void)
+{
+ platform_device_unregister(exynos_pmu_pdev);
+ platform_driver_unregister(&exynos_pmu_driver);
+}
+module_exit(exynos_pmu_exit);
+
+MODULE_AUTHOR("Pankaj Dubey <[email protected]");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("EXYNOS Power Management Unit Driver");
--
1.7.10.4

2014-04-30 05:01:39

by Pankaj Dubey

[permalink] [raw]
Subject: [PATCH v3 03/12] ARM: EXYNOS: Cleanup "mach-exynos/common.h" file

Remove unused and unwanted declarations from "mach-exynos/common.h"

Signed-off-by: Pankaj Dubey <[email protected]>
---
arch/arm/mach-exynos/common.h | 9 ---------
1 file changed, 9 deletions(-)

diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h
index 30123a0..8a4aa0b 100644
--- a/arch/arm/mach-exynos/common.h
+++ b/arch/arm/mach-exynos/common.h
@@ -15,15 +15,6 @@
#include <linux/reboot.h>
#include <linux/of.h>

-void mct_init(void __iomem *base, int irq_g0, int irq_l0, int irq_l1);
-
-struct map_desc;
-void exynos_init_io(void);
-void exynos_restart(enum reboot_mode mode, const char *cmd);
-void exynos_cpuidle_init(void);
-void exynos_cpufreq_init(void);
-void exynos_init_late(void);
-
void exynos_firmware_init(void);

#ifdef CONFIG_PINCTRL_EXYNOS
--
1.7.10.4

2014-04-30 05:02:00

by Pankaj Dubey

[permalink] [raw]
Subject: [PATCH v3 06/12] ARM: EXYNOS: Remove regs-pmu.h header dependency from pm_domain

From: Young-Gun Jang <[email protected]>

Current "pm_domain.c" file uses "S5P_INT_LOCAL_PWR_EN" definition from
"regs-pmu.h" and hence needs to include this header file. As there is
no other user of "S5P_INT_LOCAL_PWR_EN" definition other than pm_domain,
to remove "regs-pmu.h" header file dependency from "pm_domain.c" it's
better we define this definition in "pm_domain.c" file itself and thus it
will help in removing header file inclusion from "pm_domain.c".
Also removing "S5P_" prefix from macro.

Signed-off-by: Young-Gun Jang <[email protected]>
Signed-off-by: Pankaj Dubey <[email protected]>
Reviewed-by: Tomasz Figa <[email protected]>
---
arch/arm/mach-exynos/pm_domains.c | 8 ++++----
arch/arm/mach-exynos/regs-pmu.h | 1 -
2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-exynos/pm_domains.c b/arch/arm/mach-exynos/pm_domains.c
index fe6570e..e45d288 100644
--- a/arch/arm/mach-exynos/pm_domains.c
+++ b/arch/arm/mach-exynos/pm_domains.c
@@ -22,7 +22,7 @@
#include <linux/of_platform.h>
#include <linux/sched.h>

-#include "regs-pmu.h"
+#define INT_LOCAL_PWR_EN 0x7

/*
* Exynos specific wrapper around the generic power domain
@@ -44,13 +44,13 @@ static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on)
pd = container_of(domain, struct exynos_pm_domain, pd);
base = pd->base;

- pwr = power_on ? S5P_INT_LOCAL_PWR_EN : 0;
+ pwr = power_on ? INT_LOCAL_PWR_EN : 0;
__raw_writel(pwr, base);

/* Wait max 1ms */
timeout = 10;

- while ((__raw_readl(base + 0x4) & S5P_INT_LOCAL_PWR_EN) != pwr) {
+ while ((__raw_readl(base + 0x4) & INT_LOCAL_PWR_EN) != pwr) {
if (!timeout) {
op = (power_on) ? "enable" : "disable";
pr_err("Power domain %s %s failed\n", domain->name, op);
@@ -172,7 +172,7 @@ static __init int exynos4_pm_init_power_domain(void)

platform_set_drvdata(pdev, pd);

- on = __raw_readl(pd->base + 0x4) & S5P_INT_LOCAL_PWR_EN;
+ on = __raw_readl(pd->base + 0x4) & INT_LOCAL_PWR_EN;

pm_genpd_init(&pd->pd, NULL, !on);
}
diff --git a/arch/arm/mach-exynos/regs-pmu.h b/arch/arm/mach-exynos/regs-pmu.h
index b68b5cc..fd8a19d 100644
--- a/arch/arm/mach-exynos/regs-pmu.h
+++ b/arch/arm/mach-exynos/regs-pmu.h
@@ -116,7 +116,6 @@
#define S5P_PAD_RET_EBIB_OPTION S5P_PMUREG(0x31A8)

#define S5P_CORE_LOCAL_PWR_EN 0x3
-#define S5P_INT_LOCAL_PWR_EN 0x7

/* Only for EXYNOS4210 */
#define S5P_CMU_CLKSTOP_LCD1_LOWPWR S5P_PMUREG(0x1154)
--
1.7.10.4

2014-04-30 05:01:56

by Pankaj Dubey

[permalink] [raw]
Subject: [PATCH v3 10/12] ARM: EXYNOS: Move "mach/map.h" inclusion from regs-pmu.h to platsmp.c

As we have removed static mappings from "regs-pmu.h" it does not
need map.h anymore. But "platsmp.c" needed this and till now it
got included indirectly. So lets move header inclusion of
"mach/map.h" from "regs-pmu.h" to "platsmp.c".

Signed-off-by: Pankaj Dubey <[email protected]>
---
arch/arm/mach-exynos/platsmp.c | 1 +
arch/arm/mach-exynos/regs-pmu.h | 2 --
2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c
index 375ea4e..8f3b866 100644
--- a/arch/arm/mach-exynos/platsmp.c
+++ b/arch/arm/mach-exynos/platsmp.c
@@ -27,6 +27,7 @@
#include <asm/firmware.h>

#include <plat/cpu.h>
+#include <mach/map.h>

#include "common.h"
#include "regs-pmu.h"
diff --git a/arch/arm/mach-exynos/regs-pmu.h b/arch/arm/mach-exynos/regs-pmu.h
index a72b1bc..1d83c7e 100644
--- a/arch/arm/mach-exynos/regs-pmu.h
+++ b/arch/arm/mach-exynos/regs-pmu.h
@@ -12,8 +12,6 @@
#ifndef __ASM_ARCH_REGS_PMU_H
#define __ASM_ARCH_REGS_PMU_H __FILE__

-#include <mach/map.h>
-
#define S5P_CENTRAL_SEQ_CONFIGURATION 0x0200

#define S5P_CENTRAL_LOWPWR_CFG (1 << 16)
--
1.7.10.4

2014-04-30 05:02:30

by Pankaj Dubey

[permalink] [raw]
Subject: [PATCH v3 07/12] ARM: EXYNOS: Add support for mapping PMU base address via DT

From: Young-Gun Jang <[email protected]>

Add support for mapping Samsung Power Management Unit (PMU)
base address from device tree. This patch also adds helper
function as "get_exynos_pmuregmap". This function can be used
by other machine files such as "pm.c", "hotplug.c" for accessing
PMU regmap handle.

Signed-off-by: Young-Gun Jang <[email protected]>
Signed-off-by: Pankaj Dubey <[email protected]>
---
arch/arm/mach-exynos/Kconfig | 2 ++
arch/arm/mach-exynos/common.h | 2 ++
arch/arm/mach-exynos/exynos.c | 39 +++++++++++++++++++++++++++++++++++++++
3 files changed, 43 insertions(+)

diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index fc8bf18..2f60c90 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -26,6 +26,7 @@ config ARCH_EXYNOS4
select PINCTRL
select PM_GENERIC_DOMAINS if PM_RUNTIME
select S5P_DEV_MFC
+ select MFD_SYSCON
help
Samsung EXYNOS4 SoCs based systems

@@ -36,6 +37,7 @@ config ARCH_EXYNOS5
select HAVE_ARM_SCU if SMP
select HAVE_SMP
select PINCTRL
+ select MFD_SYSCON
help
Samsung EXYNOS5 (Cortex-A15) SoC based systems

diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h
index 8a4aa0b..33a2bee 100644
--- a/arch/arm/mach-exynos/common.h
+++ b/arch/arm/mach-exynos/common.h
@@ -55,4 +55,6 @@ struct exynos_pmu_conf {
extern void exynos_sys_powerdown_conf(enum sys_powerdown mode);
extern void exynos_enter_aftr(void);

+extern struct regmap *get_exynos_pmuregmap(void);
+
#endif /* __ARCH_ARM_MACH_EXYNOS_COMMON_H */
diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c
index a7b45db..9045fd6 100644
--- a/arch/arm/mach-exynos/exynos.c
+++ b/arch/arm/mach-exynos/exynos.c
@@ -19,6 +19,7 @@
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
+#include <linux/mfd/syscon.h>

#include <asm/cacheflush.h>
#include <asm/hardware/cache-l2x0.h>
@@ -36,6 +37,8 @@
#define L2_AUX_VAL 0x7C470001
#define L2_AUX_MASK 0xC200ffff

+static struct regmap *exynos_pmu_regmap;
+
static struct map_desc exynos4_iodesc[] __initdata = {
{
.virtual = (unsigned long)S3C_VA_SYS,
@@ -260,6 +263,14 @@ static int __init exynos_fdt_map_chipid(unsigned long node, const char *uname,
return 1;
}

+static const struct of_device_id exynos_dt_pmu_match[] = {
+ { .compatible = "samsung,exynos4210-pmu" },
+ { .compatible = "samsung,exynos4212-pmu" },
+ { .compatible = "samsung,exynos4412-pmu" },
+ { .compatible = "samsung,exynos5250-pmu" },
+ {},
+};
+
/*
* exynos_map_io
*
@@ -327,6 +338,32 @@ static int __init exynos4_l2x0_cache_init(void)
}
early_initcall(exynos4_l2x0_cache_init);

+
+struct regmap *get_exynos_pmuregmap()
+{
+ return exynos_pmu_regmap;
+}
+
+void __init exynos_map_pmu(void)
+{
+ struct device_node *np = NULL;
+
+ early_syscon_init();
+
+ np = of_find_matching_node(NULL, exynos_dt_pmu_match);
+
+ if (!np) {
+ pr_err("Failed to find PMU node\n");
+ return;
+ } else {
+ exynos_pmu_regmap = syscon_early_regmap_lookup_by_phandle(np,
+ "samsung,syscon-phandle");
+ }
+
+ if (IS_ERR(exynos_pmu_regmap))
+ pr_err("failed to find exynos_pmu_regmap\n");
+}
+
static void __init exynos_dt_machine_init(void)
{
struct device_node *i2c_np;
@@ -355,6 +392,8 @@ static void __init exynos_dt_machine_init(void)
}
}

+ exynos_map_pmu();
+
if (!soc_is_exynos5440())
platform_device_register(&exynos_cpuidle);

--
1.7.10.4

2014-04-30 06:01:04

by Sachin Kamat

[permalink] [raw]
Subject: Re: [PATCH v3 01/12] ARM: EXYNOS: Make exynos machine_ops as static

Hi Pankaj,

On 30 April 2014 10:47, Pankaj Dubey <[email protected]> wrote:
> As machine function ops are used only in this file let's make
> them static.
>
> Signed-off-by: Pankaj Dubey <[email protected]>
> ---
> arch/arm/mach-exynos/exynos.c | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c
> index 3d69e8d..06dcce5 100644
> --- a/arch/arm/mach-exynos/exynos.c
> +++ b/arch/arm/mach-exynos/exynos.c
> @@ -198,7 +198,7 @@ static struct map_desc exynos5_iodesc[] __initdata = {
> },
> };
>
> -void exynos_restart(enum reboot_mode mode, const char *cmd)
> +static void exynos_restart(enum reboot_mode mode, const char *cmd)
> {
> struct device_node *np;
> u32 val = 0x1;
> @@ -239,7 +239,7 @@ void __init exynos_cpufreq_init(void)
> platform_device_register_simple("exynos-cpufreq", -1, NULL, 0);
> }
>
> -void __init exynos_init_late(void)
> +static void __init exynos_init_late(void)
> {
> if (of_machine_is_compatible("samsung,exynos5440"))
> /* to be supported later */
> @@ -300,7 +300,7 @@ static void __init exynos_map_io(void)
> iotable_init(exynos5250_iodesc, ARRAY_SIZE(exynos5250_iodesc));
> }
>
> -void __init exynos_init_io(void)
> +static void __init exynos_init_io(void)
> {
> debug_ll_io_init();


The declarations from common.h should also be removed in this patch to
avoid the below
build errors:

arch/arm/mach-exynos/exynos.c:198:13: error: static declaration of
‘exynos_restart’ follows non-static declaration
static void exynos_restart(enum reboot_mode mode, const char *cmd)
^
In file included from arch/arm/mach-exynos/exynos.c:31:0:
arch/arm/mach-exynos/common.h:22:6: note: previous declaration of
‘exynos_restart’ was here
void exynos_restart(enum reboot_mode mode, const char *cmd);
^
arch/arm/mach-exynos/exynos.c:235:20: error: static declaration of
‘exynos_init_late’ follows non-static declaration
static void __init exynos_init_late(void)
^
In file included from arch/arm/mach-exynos/exynos.c:31:0:
arch/arm/mach-exynos/common.h:25:6: note: previous declaration of
‘exynos_init_late’ was here
void exynos_init_late(void);
^
arch/arm/mach-exynos/exynos.c:296:20: error: static declaration of
‘exynos_init_io’ follows non-static declaration
static void __init exynos_init_io(void)
^
In file included from arch/arm/mach-exynos/exynos.c:31:0:
arch/arm/mach-exynos/common.h:21:6: note: previous declaration of
‘exynos_init_io’ was here
void exynos_init_io(void);


--
With warm regards,
Sachin

2014-04-30 06:05:53

by Vikas Sajjan

[permalink] [raw]
Subject: Re: [PATCH v3 11/12] ARM: EXYNOS: Add platform driver support for Exynos PMU.

Hi Pankaj,

On Wed, Apr 30, 2014 at 10:47 AM, Pankaj Dubey <[email protected]> wrote:
> This patch modifies Exynos Power Management Unit (PMU) initialization
> implementation in following way:
>
> - Added platform_device support by registering static platform device.
> - Added platform struct exynos_pmu_data to hold platform specific data.
> - For each SoC's PMU support now we can add platform data and statically
> bind PMU configuration and SoC specific initialization function.
> - Probe function will scan DT and based on matching PMU compatibility
> string initialize pmu_context which will be platform_data for driver.
> - Obtain PMU regmap handle using "syscon_regmap_lookup_by_phandle" so
> that we can reduce dependency over machine header files.
> - Separate each SoC's PMU initialization function and make it as part of
> platform data.
> - It also removes uses of soc_is_exynosXXXX() thus making PMU implementation
> independent of "plat/cpu.h".
>
> Signed-off-by: Pankaj Dubey <[email protected]>
> Signed-off-by: Young-Gun Jang <[email protected]>
> ---
> arch/arm/mach-exynos/pmu.c | 280 +++++++++++++++++++++++++++++++++++---------
> 1 file changed, 224 insertions(+), 56 deletions(-)
>
> diff --git a/arch/arm/mach-exynos/pmu.c b/arch/arm/mach-exynos/pmu.c
> index 67116a5..030df96 100644
> --- a/arch/arm/mach-exynos/pmu.c
> +++ b/arch/arm/mach-exynos/pmu.c
> @@ -1,5 +1,5 @@
> /*
> - * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd.
> + * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd.
> * http://www.samsung.com/
> *
> * EXYNOS - CPU PMU(Power Management Unit) support
> @@ -9,20 +9,33 @@
> * published by the Free Software Foundation.
> */
>
> -#include <linux/io.h>
> -#include <linux/kernel.h>
> +#include <linux/module.h>
> #include <linux/regmap.h>
> -
> -#include <plat/cpu.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +#include <linux/mfd/syscon.h>
>
> #include "common.h"
> #include "regs-pmu.h"
>
> -static const struct exynos_pmu_conf *exynos_pmu_config;
> -static struct regmap *pmu_regmap;
> +struct exynos_pmu_data {
> + const struct exynos_pmu_conf *pmu_config;
> + const struct exynos_pmu_conf *pmu_config_extra;
> + void (*pmu_init)(void);
> + void (*powerdown_conf)(enum sys_powerdown);
> +};
> +
> +struct exynos_pmu_context {
> + struct device *dev;
> + struct exynos_pmu_data *pmu_data;
> + struct regmap *pmu_regmap;
> +};
> +
> +static struct exynos_pmu_context *pmu_context;
>
> static const struct exynos_pmu_conf exynos4210_pmu_config[] = {
> - /* { .reg = address, .val = { AFTR, LPA, SLEEP } */
> + /* { .offset = address, .val = { AFTR, LPA, SLEEP } */
> { S5P_ARM_CORE0_LOWPWR, { 0x0, 0x0, 0x2 } },
> { S5P_DIS_IRQ_CORE0, { 0x0, 0x0, 0x0 } },
> { S5P_DIS_IRQ_CENTRAL0, { 0x0, 0x0, 0x0 } },
> @@ -216,7 +229,7 @@ static const struct exynos_pmu_conf exynos4412_pmu_config[] = {
> };
>
> static const struct exynos_pmu_conf exynos5250_pmu_config[] = {
> - /* { .reg = address, .val = { AFTR, LPA, SLEEP } */
> + /* { .offset = address, .val = { AFTR, LPA, SLEEP } */
> { EXYNOS5_ARM_CORE0_SYS_PWR_REG, { 0x0, 0x0, 0x2} },
> { EXYNOS5_DIS_IRQ_ARM_CORE0_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
> { EXYNOS5_DIS_IRQ_ARM_CORE0_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
> @@ -339,7 +352,7 @@ static unsigned int const exynos5_list_diable_wfi_wfe[] = {
> EXYNOS5_ISP_ARM_OPTION,
> };
>
> -static void exynos5_init_pmu(void)
> +void exynos5_powerdown_conf(enum sys_powerdown mode)
> {
> unsigned int i;
> unsigned int tmp;
> @@ -348,81 +361,236 @@ static void exynos5_init_pmu(void)
> * Enable both SC_FEEDBACK and SC_COUNTER
> */
> for (i = 0 ; i < ARRAY_SIZE(exynos5_list_both_cnt_feed) ; i++) {
> - regmap_read(pmu_regmap, exynos5_list_both_cnt_feed[i], &tmp);
> + regmap_read(pmu_context->pmu_regmap,
> + exynos5_list_both_cnt_feed[i], &tmp);
> tmp |= (EXYNOS5_USE_SC_FEEDBACK |
> EXYNOS5_USE_SC_COUNTER);
> - regmap_write(pmu_regmap, exynos5_list_both_cnt_feed[i], tmp);
> + regmap_write(pmu_context->pmu_regmap,
> + exynos5_list_both_cnt_feed[i], tmp);
> }
>
> /*
> * SKIP_DEACTIVATE_ACEACP_IN_PWDN_BITFIELD Enable
> */
> - regmap_read(pmu_regmap, EXYNOS5_ARM_COMMON_OPTION, &tmp);
> + regmap_read(pmu_context->pmu_regmap, EXYNOS5_ARM_COMMON_OPTION, &tmp);
> tmp |= EXYNOS5_SKIP_DEACTIVATE_ACEACP_IN_PWDN;
> - regmap_write(pmu_regmap, EXYNOS5_ARM_COMMON_OPTION, tmp);
> + regmap_write(pmu_context->pmu_regmap, EXYNOS5_ARM_COMMON_OPTION, tmp);
>
> /*
> * Disable WFI/WFE on XXX_OPTION
> */
> for (i = 0 ; i < ARRAY_SIZE(exynos5_list_diable_wfi_wfe) ; i++) {
> - tmp = regmap_read(pmu_regmap, exynos5_list_diable_wfi_wfe[i],
> - &tmp);
> + tmp = regmap_read(pmu_context->pmu_regmap,
> + exynos5_list_diable_wfi_wfe[i], &tmp);
> tmp &= ~(EXYNOS5_OPTION_USE_STANDBYWFE |
> EXYNOS5_OPTION_USE_STANDBYWFI);
> - regmap_write(pmu_regmap, exynos5_list_diable_wfi_wfe[i], tmp);
> + regmap_write(pmu_context->pmu_regmap,
> + exynos5_list_diable_wfi_wfe[i], tmp);
> }
> }
>
> void exynos_sys_powerdown_conf(enum sys_powerdown mode)
> {
> unsigned int i;
> + struct exynos_pmu_data *pmu_data = pmu_context->pmu_data;
>
> - if (soc_is_exynos5250())
> - exynos5_init_pmu();
> + if (pmu_data->powerdown_conf)
> + pmu_data->powerdown_conf(mode);
>
> - for (i = 0; (exynos_pmu_config[i].offset != PMU_TABLE_END) ; i++)
> - regmap_write(pmu_regmap, exynos_pmu_config[i].offset,
> - exynos_pmu_config[i].val[mode]);
> + if (pmu_data->pmu_config) {
> + for (i = 0; (pmu_data->pmu_config[i].offset != PMU_TABLE_END) ; i++)
> + regmap_write(pmu_context->pmu_regmap,
> + pmu_data->pmu_config[i].offset,
> + pmu_data->pmu_config[i].val[mode]);
> + }
>
> - if (soc_is_exynos4412()) {
> - for (i = 0; exynos4412_pmu_config[i].offset != PMU_TABLE_END; i++)
> - regmap_write(pmu_regmap, exynos4412_pmu_config[i].offset,
> - exynos4412_pmu_config[i].val[mode]);
> + if (pmu_data->pmu_config_extra) {
> + for (i = 0; pmu_data->pmu_config_extra[i].offset != PMU_TABLE_END; i++)
> + regmap_write(pmu_context->pmu_regmap,
> + pmu_data->pmu_config_extra[i].offset,
> + pmu_data->pmu_config_extra[i].val[mode]);
> }
> }
>
> -static int __init exynos_pmu_init(void)
> +static void exynos5250_pmu_init(void)
> +{
> + unsigned int tmp;
> + struct regmap *pmu_regmap = pmu_context->pmu_regmap;
> + /*
> + * When SYS_WDTRESET is set, watchdog timer reset request
> + * is ignored by power management unit.
> + */
> + regmap_read(pmu_regmap, EXYNOS5_AUTO_WDTRESET_DISABLE, &tmp);
> + tmp &= ~EXYNOS5_SYS_WDTRESET;
> + regmap_write(pmu_regmap, EXYNOS5_AUTO_WDTRESET_DISABLE, tmp);
> +
> + regmap_read(pmu_regmap, EXYNOS5_MASK_WDTRESET_REQUEST, &tmp);
> + tmp &= ~EXYNOS5_SYS_WDTRESET;
> + regmap_write(pmu_regmap, EXYNOS5_MASK_WDTRESET_REQUEST, tmp);
> +}
> +
> +static struct exynos_pmu_data exynos4210_pmu_data = {
> + .pmu_config = exynos4210_pmu_config,
> +};
> +
> +static struct exynos_pmu_data exynos4x12_pmu_data = {
> + .pmu_config = exynos4x12_pmu_config,
> +};
> +
> +static struct exynos_pmu_data exynos4412_pmu_data = {
> + .pmu_config = exynos4x12_pmu_config,
> + .pmu_config_extra = exynos4412_pmu_config,
> +};
> +
> +static struct exynos_pmu_data exynos5250_pmu_data = {
> + .pmu_config = exynos5250_pmu_config,
> + .pmu_init = exynos5250_pmu_init,
> + .powerdown_conf = exynos5_powerdown_conf,
> +};
> +
> +/*
> + * PMU platform driver and devicetree bindings.
> + */
> +static struct of_device_id exynos_pmu_of_device_ids[] = {
> + {
> + .compatible = "samsung,exynos4210-pmu",
> + .data = (void *)&exynos4210_pmu_data,
> + },
> + {
> + .compatible = "samsung,exynos4212-pmu",
> + .data = (void *)&exynos4x12_pmu_data,
> + },
> + {
> + .compatible = "samsung,exynos4412-pmu",
> + .data = (void *)&exynos4412_pmu_data,
> + },
> + {
> + .compatible = "samsung,exynos5250-pmu",
> + .data = (void *)&exynos5250_pmu_data,
> + },
> + {},
> +};
> +
> +static int exynos_pmu_data_init(struct device_node *np)
> {
> - unsigned int value;
> -
> - exynos_pmu_config = exynos4210_pmu_config;
> - pmu_regmap = get_exynos_pmuregmap();
> -
> - if (soc_is_exynos4210()) {
> - exynos_pmu_config = exynos4210_pmu_config;
> - pr_info("EXYNOS4210 PMU Initialize\n");
> - } else if (soc_is_exynos4212() || soc_is_exynos4412()) {
> - exynos_pmu_config = exynos4x12_pmu_config;
> - pr_info("EXYNOS4x12 PMU Initialize\n");
> - } else if (soc_is_exynos5250()) {
> - /*
> - * When SYS_WDTRESET is set, watchdog timer reset request
> - * is ignored by power management unit.
> - */
> - regmap_read(pmu_regmap, EXYNOS5_AUTO_WDTRESET_DISABLE, &value);
> - value &= ~EXYNOS5_SYS_WDTRESET;
> - regmap_write(pmu_regmap, EXYNOS5_AUTO_WDTRESET_DISABLE, value);
> -
> - regmap_read(pmu_regmap, EXYNOS5_MASK_WDTRESET_REQUEST, &value);
> - value &= ~EXYNOS5_SYS_WDTRESET;
> - regmap_write(pmu_regmap, EXYNOS5_MASK_WDTRESET_REQUEST, value);
> -
> - exynos_pmu_config = exynos5250_pmu_config;
> - pr_info("EXYNOS5250 PMU Initialize\n");
> - } else {
> - pr_info("EXYNOS: PMU not supported\n");
> + const struct of_device_id *match;
> +
> + match = of_match_node(exynos_pmu_of_device_ids, np);
> + if (!match) {
> + pr_err("fail to get matching of_match struct\n");
> + return -EINVAL;
> + }
> +
> + pmu_context->pmu_data = (struct exynos_pmu_data *) match->data;
> + pmu_context->pmu_regmap = syscon_regmap_lookup_by_phandle(np,
> + "samsung,syscon-phandle");
> +
> + if (IS_ERR(pmu_context->pmu_regmap)) {
> + pr_err("failed to find exynos_pmu_regmap\n");
> + return PTR_ERR(pmu_context->pmu_regmap);
> }
>
> + if (pmu_context->pmu_data->pmu_init)
> + pmu_context->pmu_data->pmu_init();
> +
> + return 0;
> +};
> +
> +static int exynos_pmu_probe(struct platform_device *pdev)
> +{
> + int ret;
> + struct device_node *np;
> + struct device *dev = &pdev->dev;
> +
> + pmu_context = devm_kzalloc(&pdev->dev,
> + sizeof(struct exynos_pmu_context),
> + GFP_KERNEL);
> + if (pmu_context == NULL) {
> + dev_err(dev, "Cannot allocate memory.\n");
> + return -ENOMEM;
> + }
> +
> + for_each_matching_node_and_match(np, exynos_pmu_of_device_ids, NULL) {
> + ret = exynos_pmu_data_init(np);
> + if (ret < 0)
> + return ret;
> + break;
> + }

Ca we optmize further as below, there by avoiding one more call to
exynos_pmu_data_init()

=============================================================
const struct of_device_id *match;
for_each_matching_node_and_match(np, exynos_pmu_of_device_ids, &match) {

pmu_context->pmu_data = (struct exynos_pmu_data *) match->data;
pmu_context->pmu_regmap = syscon_regmap_lookup_by_phandle(np,
"samsung,syscon-phandle");

if (IS_ERR(pmu_context->pmu_regmap)) {
pr_err("failed to find exynos_pmu_regmap\n");
return PTR_ERR(pmu_context->pmu_regmap);
}

if (pmu_context->pmu_data->pmu_init)
pmu_context->pmu_data->pmu_init();

break;
}
============================================================

> +
> + pmu_context->dev = dev;
> +
> + platform_set_drvdata(pdev, pmu_context);
> +
> + pr_info("Exynos PMU Driver probe done!!!\n");
> + return 0;
> +}
> +
> +static int exynos_pmu_suspend(struct device *dev)
> +{
> + /* ToDo: */
> return 0;
> }
> -arch_initcall(exynos_pmu_init);
> +
> +static int exynos_pmu_resume(struct device *dev)
> +{
> + /* ToDo: */
> + return 0;
> +}
> +
> +static const struct dev_pm_ops exynos_pmu_pm = {
> + .suspend = exynos_pmu_suspend,
> + .resume = exynos_pmu_resume,
> +};
> +
> +static int exynos_pmu_remove(struct platform_device *pdev)
> +{
> + /* nothing to do here */
> + return 0;
> +}
> +
> +static struct platform_device *exynos_pmu_pdev;
> +
> +static struct platform_driver exynos_pmu_driver = {
> + .driver = {
> + .name = "exynos-pmu",
> + .owner = THIS_MODULE,
> + .pm = &exynos_pmu_pm,
> + },
> + .probe = exynos_pmu_probe,
> + .remove = exynos_pmu_remove,
> +};
> +
> +static int __init exynos_pmu_of_init(void)
> +{
> + int ret;
> +
> + ret = platform_driver_register(&exynos_pmu_driver);
> + if (ret < 0)
> + goto out;
> +
> + exynos_pmu_pdev = platform_device_register_simple("exynos-pmu", -1,
> + NULL, 0);
> +
> + if (IS_ERR(exynos_pmu_pdev)) {
> + ret = PTR_ERR(exynos_pmu_pdev);
> + goto out1;
> + }
> +
> + return 0;
> +out1:
> + platform_driver_unregister(&exynos_pmu_driver);
> +out:
> + return ret;
> +}
> +arch_initcall(exynos_pmu_of_init);
> +
> +static void __exit exynos_pmu_exit(void)
> +{
> + platform_device_unregister(exynos_pmu_pdev);
> + platform_driver_unregister(&exynos_pmu_driver);
> +}
> +module_exit(exynos_pmu_exit);
> +
> +MODULE_AUTHOR("Pankaj Dubey <[email protected]");
> +MODULE_LICENSE("GPL v2");
> +MODULE_DESCRIPTION("EXYNOS Power Management Unit Driver");
> --
> 1.7.10.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html

2014-04-30 07:17:36

by Pankaj Dubey

[permalink] [raw]
Subject: Re: [PATCH v3 01/12] ARM: EXYNOS: Make exynos machine_ops as static

Hi Sachin,

On 04/30/2014 03:00 PM, Sachin Kamat wrote:
> Hi Pankaj,
>
> On 30 April 2014 10:47, Pankaj Dubey <[email protected]> wrote:
>> As machine function ops are used only in this file let's make
>> them static.
>>
>> Signed-off-by: Pankaj Dubey <[email protected]>
>> ---
>> arch/arm/mach-exynos/exynos.c | 6 +++---
>> 1 file changed, 3 insertions(+), 3 deletions(-)
>>
>> diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c
>> index 3d69e8d..06dcce5 100644
>> --- a/arch/arm/mach-exynos/exynos.c
>> +++ b/arch/arm/mach-exynos/exynos.c
>> @@ -198,7 +198,7 @@ static struct map_desc exynos5_iodesc[] __initdata = {
>> },
>> };
>>
>> -void exynos_restart(enum reboot_mode mode, const char *cmd)
>> +static void exynos_restart(enum reboot_mode mode, const char *cmd)
>> {
>> struct device_node *np;
>> u32 val = 0x1;
>> @@ -239,7 +239,7 @@ void __init exynos_cpufreq_init(void)
>> platform_device_register_simple("exynos-cpufreq", -1, NULL, 0);
>> }
>>
>> -void __init exynos_init_late(void)
>> +static void __init exynos_init_late(void)
>> {
>> if (of_machine_is_compatible("samsung,exynos5440"))
>> /* to be supported later */
>> @@ -300,7 +300,7 @@ static void __init exynos_map_io(void)
>> iotable_init(exynos5250_iodesc, ARRAY_SIZE(exynos5250_iodesc));
>> }
>>
>> -void __init exynos_init_io(void)
>> +static void __init exynos_init_io(void)
>> {
>> debug_ll_io_init();
>
> The declarations from common.h should also be removed in this patch to
> avoid the below
> build errors:

Thanks. I will merge changes in common.h in this patch itself.

>
> arch/arm/mach-exynos/exynos.c:198:13: error: static declaration of
> ‘exynos_restart’ follows non-static declaration
> static void exynos_restart(enum reboot_mode mode, const char *cmd)
> ^
> In file included from arch/arm/mach-exynos/exynos.c:31:0:
> arch/arm/mach-exynos/common.h:22:6: note: previous declaration of
> ‘exynos_restart’ was here
> void exynos_restart(enum reboot_mode mode, const char *cmd);
> ^
> arch/arm/mach-exynos/exynos.c:235:20: error: static declaration of
> ‘exynos_init_late’ follows non-static declaration
> static void __init exynos_init_late(void)
> ^
> In file included from arch/arm/mach-exynos/exynos.c:31:0:
> arch/arm/mach-exynos/common.h:25:6: note: previous declaration of
> ‘exynos_init_late’ was here
> void exynos_init_late(void);
> ^
> arch/arm/mach-exynos/exynos.c:296:20: error: static declaration of
> ‘exynos_init_io’ follows non-static declaration
> static void __init exynos_init_io(void)
> ^
> In file included from arch/arm/mach-exynos/exynos.c:31:0:
> arch/arm/mach-exynos/common.h:21:6: note: previous declaration of
> ‘exynos_init_io’ was here
> void exynos_init_io(void);
>
>


--
Best Regards,
Pankaj Dubey

2014-04-30 08:41:47

by Sachin Kamat

[permalink] [raw]
Subject: Re: [PATCH v3 05/12] ARM: EXYNOS: Remove file path from comment section

Hi Pankaj,

On 30 April 2014 10:47, Pankaj Dubey <[email protected]> wrote:
> Many files under "arm/mach-exynos" are having file path in file
> comment section which is invalid now.
> So for better code maintainability let's remove them.
>
> Signed-off-by: Pankaj Dubey <[email protected]>
> Reviewed-by: Tomasz Figa <[email protected]>
> ---

The change is sensible. However Kukjin had refused to accept such patches
when I had submitted patches doing such cleanup for all Samsung platform files.

Anyway, FWIW
Reviewed-by: Sachin Kamat <[email protected]>

--
With warm regards,
Sachin

2014-05-01 03:40:15

by Pankaj Dubey

[permalink] [raw]
Subject: Re: [PATCH v3 11/12] ARM: EXYNOS: Add platform driver support for Exynos PMU.

On 04/30/2014 03:05 PM, Vikas Sajjan wrote:
> Hi Pankaj,
>
> On Wed, Apr 30, 2014 at 10:47 AM, Pankaj Dubey <[email protected]> wrote:
>> This patch modifies Exynos Power Management Unit (PMU) initialization
>> implementation in following way:
>>
>> - Added platform_device support by registering static platform device.
>> - Added platform struct exynos_pmu_data to hold platform specific data.
>> - For each SoC's PMU support now we can add platform data and statically
>> bind PMU configuration and SoC specific initialization function.
>> - Probe function will scan DT and based on matching PMU compatibility
>> string initialize pmu_context which will be platform_data for driver.
>> - Obtain PMU regmap handle using "syscon_regmap_lookup_by_phandle" so
>> that we can reduce dependency over machine header files.
>> - Separate each SoC's PMU initialization function and make it as part of
>> platform data.
>> - It also removes uses of soc_is_exynosXXXX() thus making PMU implementation
>> independent of "plat/cpu.h".
>>
>> Signed-off-by: Pankaj Dubey <[email protected]>
>> Signed-off-by: Young-Gun Jang <[email protected]>
>> ---
>> arch/arm/mach-exynos/pmu.c | 280 +++++++++++++++++++++++++++++++++++---------
>> 1 file changed, 224 insertions(+), 56 deletions(-)
>>
>> diff --git a/arch/arm/mach-exynos/pmu.c b/arch/arm/mach-exynos/pmu.c
>> index 67116a5..030df96 100644
>> --- a/arch/arm/mach-exynos/pmu.c
>> +++ b/arch/arm/mach-exynos/pmu.c
>> @@ -1,5 +1,5 @@
>> /*
>> - * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd.
>> + * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd.
>> * http://www.samsung.com/
>> *
>> * EXYNOS - CPU PMU(Power Management Unit) support
>> @@ -9,20 +9,33 @@
>> * published by the Free Software Foundation.
>> */
>>
>> -#include <linux/io.h>
>> -#include <linux/kernel.h>
>> +#include <linux/module.h>
>> #include <linux/regmap.h>
>> -
>> -#include <plat/cpu.h>
>> +#include <linux/of.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/slab.h>
>> +#include <linux/mfd/syscon.h>
>>
>> #include "common.h"
>> #include "regs-pmu.h"
>>
>> -static const struct exynos_pmu_conf *exynos_pmu_config;
>> -static struct regmap *pmu_regmap;
>> +struct exynos_pmu_data {
>> + const struct exynos_pmu_conf *pmu_config;
>> + const struct exynos_pmu_conf *pmu_config_extra;
>> + void (*pmu_init)(void);
>> + void (*powerdown_conf)(enum sys_powerdown);
>> +};
>> +
>> +struct exynos_pmu_context {
>> + struct device *dev;
>> + struct exynos_pmu_data *pmu_data;
>> + struct regmap *pmu_regmap;
>> +};
>> +
>> +static struct exynos_pmu_context *pmu_context;
>>
>> static const struct exynos_pmu_conf exynos4210_pmu_config[] = {
>> - /* { .reg = address, .val = { AFTR, LPA, SLEEP } */
>> + /* { .offset = address, .val = { AFTR, LPA, SLEEP } */
>> { S5P_ARM_CORE0_LOWPWR, { 0x0, 0x0, 0x2 } },
>> { S5P_DIS_IRQ_CORE0, { 0x0, 0x0, 0x0 } },
>> { S5P_DIS_IRQ_CENTRAL0, { 0x0, 0x0, 0x0 } },
>> @@ -216,7 +229,7 @@ static const struct exynos_pmu_conf exynos4412_pmu_config[] = {
>> };
>>
>> static const struct exynos_pmu_conf exynos5250_pmu_config[] = {
>> - /* { .reg = address, .val = { AFTR, LPA, SLEEP } */
>> + /* { .offset = address, .val = { AFTR, LPA, SLEEP } */
>> { EXYNOS5_ARM_CORE0_SYS_PWR_REG, { 0x0, 0x0, 0x2} },
>> { EXYNOS5_DIS_IRQ_ARM_CORE0_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
>> { EXYNOS5_DIS_IRQ_ARM_CORE0_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
>> @@ -339,7 +352,7 @@ static unsigned int const exynos5_list_diable_wfi_wfe[] = {
>> EXYNOS5_ISP_ARM_OPTION,
>> };
>>
>> -static void exynos5_init_pmu(void)
>> +void exynos5_powerdown_conf(enum sys_powerdown mode)
>> {
>> unsigned int i;
>> unsigned int tmp;
>> @@ -348,81 +361,236 @@ static void exynos5_init_pmu(void)
>> * Enable both SC_FEEDBACK and SC_COUNTER
>> */
>> for (i = 0 ; i < ARRAY_SIZE(exynos5_list_both_cnt_feed) ; i++) {
>> - regmap_read(pmu_regmap, exynos5_list_both_cnt_feed[i], &tmp);
>> + regmap_read(pmu_context->pmu_regmap,
>> + exynos5_list_both_cnt_feed[i], &tmp);
>> tmp |= (EXYNOS5_USE_SC_FEEDBACK |
>> EXYNOS5_USE_SC_COUNTER);
>> - regmap_write(pmu_regmap, exynos5_list_both_cnt_feed[i], tmp);
>> + regmap_write(pmu_context->pmu_regmap,
>> + exynos5_list_both_cnt_feed[i], tmp);
>> }
>>
>> /*
>> * SKIP_DEACTIVATE_ACEACP_IN_PWDN_BITFIELD Enable
>> */
>> - regmap_read(pmu_regmap, EXYNOS5_ARM_COMMON_OPTION, &tmp);
>> + regmap_read(pmu_context->pmu_regmap, EXYNOS5_ARM_COMMON_OPTION, &tmp);
>> tmp |= EXYNOS5_SKIP_DEACTIVATE_ACEACP_IN_PWDN;
>> - regmap_write(pmu_regmap, EXYNOS5_ARM_COMMON_OPTION, tmp);
>> + regmap_write(pmu_context->pmu_regmap, EXYNOS5_ARM_COMMON_OPTION, tmp);
>>
>> /*
>> * Disable WFI/WFE on XXX_OPTION
>> */
>> for (i = 0 ; i < ARRAY_SIZE(exynos5_list_diable_wfi_wfe) ; i++) {
>> - tmp = regmap_read(pmu_regmap, exynos5_list_diable_wfi_wfe[i],
>> - &tmp);
>> + tmp = regmap_read(pmu_context->pmu_regmap,
>> + exynos5_list_diable_wfi_wfe[i], &tmp);
>> tmp &= ~(EXYNOS5_OPTION_USE_STANDBYWFE |
>> EXYNOS5_OPTION_USE_STANDBYWFI);
>> - regmap_write(pmu_regmap, exynos5_list_diable_wfi_wfe[i], tmp);
>> + regmap_write(pmu_context->pmu_regmap,
>> + exynos5_list_diable_wfi_wfe[i], tmp);
>> }
>> }
>>
>> void exynos_sys_powerdown_conf(enum sys_powerdown mode)
>> {
>> unsigned int i;
>> + struct exynos_pmu_data *pmu_data = pmu_context->pmu_data;
>>
>> - if (soc_is_exynos5250())
>> - exynos5_init_pmu();
>> + if (pmu_data->powerdown_conf)
>> + pmu_data->powerdown_conf(mode);
>>
>> - for (i = 0; (exynos_pmu_config[i].offset != PMU_TABLE_END) ; i++)
>> - regmap_write(pmu_regmap, exynos_pmu_config[i].offset,
>> - exynos_pmu_config[i].val[mode]);
>> + if (pmu_data->pmu_config) {
>> + for (i = 0; (pmu_data->pmu_config[i].offset != PMU_TABLE_END) ; i++)
>> + regmap_write(pmu_context->pmu_regmap,
>> + pmu_data->pmu_config[i].offset,
>> + pmu_data->pmu_config[i].val[mode]);
>> + }
>>
>> - if (soc_is_exynos4412()) {
>> - for (i = 0; exynos4412_pmu_config[i].offset != PMU_TABLE_END; i++)
>> - regmap_write(pmu_regmap, exynos4412_pmu_config[i].offset,
>> - exynos4412_pmu_config[i].val[mode]);
>> + if (pmu_data->pmu_config_extra) {
>> + for (i = 0; pmu_data->pmu_config_extra[i].offset != PMU_TABLE_END; i++)
>> + regmap_write(pmu_context->pmu_regmap,
>> + pmu_data->pmu_config_extra[i].offset,
>> + pmu_data->pmu_config_extra[i].val[mode]);
>> }
>> }
>>
>> -static int __init exynos_pmu_init(void)
>> +static void exynos5250_pmu_init(void)
>> +{
>> + unsigned int tmp;
>> + struct regmap *pmu_regmap = pmu_context->pmu_regmap;
>> + /*
>> + * When SYS_WDTRESET is set, watchdog timer reset request
>> + * is ignored by power management unit.
>> + */
>> + regmap_read(pmu_regmap, EXYNOS5_AUTO_WDTRESET_DISABLE, &tmp);
>> + tmp &= ~EXYNOS5_SYS_WDTRESET;
>> + regmap_write(pmu_regmap, EXYNOS5_AUTO_WDTRESET_DISABLE, tmp);
>> +
>> + regmap_read(pmu_regmap, EXYNOS5_MASK_WDTRESET_REQUEST, &tmp);
>> + tmp &= ~EXYNOS5_SYS_WDTRESET;
>> + regmap_write(pmu_regmap, EXYNOS5_MASK_WDTRESET_REQUEST, tmp);
>> +}
>> +
>> +static struct exynos_pmu_data exynos4210_pmu_data = {
>> + .pmu_config = exynos4210_pmu_config,
>> +};
>> +
>> +static struct exynos_pmu_data exynos4x12_pmu_data = {
>> + .pmu_config = exynos4x12_pmu_config,
>> +};
>> +
>> +static struct exynos_pmu_data exynos4412_pmu_data = {
>> + .pmu_config = exynos4x12_pmu_config,
>> + .pmu_config_extra = exynos4412_pmu_config,
>> +};
>> +
>> +static struct exynos_pmu_data exynos5250_pmu_data = {
>> + .pmu_config = exynos5250_pmu_config,
>> + .pmu_init = exynos5250_pmu_init,
>> + .powerdown_conf = exynos5_powerdown_conf,
>> +};
>> +
>> +/*
>> + * PMU platform driver and devicetree bindings.
>> + */
>> +static struct of_device_id exynos_pmu_of_device_ids[] = {
>> + {
>> + .compatible = "samsung,exynos4210-pmu",
>> + .data = (void *)&exynos4210_pmu_data,
>> + },
>> + {
>> + .compatible = "samsung,exynos4212-pmu",
>> + .data = (void *)&exynos4x12_pmu_data,
>> + },
>> + {
>> + .compatible = "samsung,exynos4412-pmu",
>> + .data = (void *)&exynos4412_pmu_data,
>> + },
>> + {
>> + .compatible = "samsung,exynos5250-pmu",
>> + .data = (void *)&exynos5250_pmu_data,
>> + },
>> + {},
>> +};
>> +
>> +static int exynos_pmu_data_init(struct device_node *np)
>> {
>> - unsigned int value;
>> -
>> - exynos_pmu_config = exynos4210_pmu_config;
>> - pmu_regmap = get_exynos_pmuregmap();
>> -
>> - if (soc_is_exynos4210()) {
>> - exynos_pmu_config = exynos4210_pmu_config;
>> - pr_info("EXYNOS4210 PMU Initialize\n");
>> - } else if (soc_is_exynos4212() || soc_is_exynos4412()) {
>> - exynos_pmu_config = exynos4x12_pmu_config;
>> - pr_info("EXYNOS4x12 PMU Initialize\n");
>> - } else if (soc_is_exynos5250()) {
>> - /*
>> - * When SYS_WDTRESET is set, watchdog timer reset request
>> - * is ignored by power management unit.
>> - */
>> - regmap_read(pmu_regmap, EXYNOS5_AUTO_WDTRESET_DISABLE, &value);
>> - value &= ~EXYNOS5_SYS_WDTRESET;
>> - regmap_write(pmu_regmap, EXYNOS5_AUTO_WDTRESET_DISABLE, value);
>> -
>> - regmap_read(pmu_regmap, EXYNOS5_MASK_WDTRESET_REQUEST, &value);
>> - value &= ~EXYNOS5_SYS_WDTRESET;
>> - regmap_write(pmu_regmap, EXYNOS5_MASK_WDTRESET_REQUEST, value);
>> -
>> - exynos_pmu_config = exynos5250_pmu_config;
>> - pr_info("EXYNOS5250 PMU Initialize\n");
>> - } else {
>> - pr_info("EXYNOS: PMU not supported\n");
>> + const struct of_device_id *match;
>> +
>> + match = of_match_node(exynos_pmu_of_device_ids, np);
>> + if (!match) {
>> + pr_err("fail to get matching of_match struct\n");
>> + return -EINVAL;
>> + }
>> +
>> + pmu_context->pmu_data = (struct exynos_pmu_data *) match->data;
>> + pmu_context->pmu_regmap = syscon_regmap_lookup_by_phandle(np,
>> + "samsung,syscon-phandle");
>> +
>> + if (IS_ERR(pmu_context->pmu_regmap)) {
>> + pr_err("failed to find exynos_pmu_regmap\n");
>> + return PTR_ERR(pmu_context->pmu_regmap);
>> }
>>
>> + if (pmu_context->pmu_data->pmu_init)
>> + pmu_context->pmu_data->pmu_init();
>> +
>> + return 0;
>> +};
>> +
>> +static int exynos_pmu_probe(struct platform_device *pdev)
>> +{
>> + int ret;
>> + struct device_node *np;
>> + struct device *dev = &pdev->dev;
>> +
>> + pmu_context = devm_kzalloc(&pdev->dev,
>> + sizeof(struct exynos_pmu_context),
>> + GFP_KERNEL);
>> + if (pmu_context == NULL) {
>> + dev_err(dev, "Cannot allocate memory.\n");
>> + return -ENOMEM;
>> + }
>> +
>> + for_each_matching_node_and_match(np, exynos_pmu_of_device_ids, NULL) {
>> + ret = exynos_pmu_data_init(np);
>> + if (ret < 0)
>> + return ret;
>> + break;
>> + }
> Ca we optmize further as below, there by avoiding one more call to
> exynos_pmu_data_init()
>
> =============================================================
> const struct of_device_id *match;
> for_each_matching_node_and_match(np, exynos_pmu_of_device_ids, &match) {
>
> pmu_context->pmu_data = (struct exynos_pmu_data *) match->data;
> pmu_context->pmu_regmap = syscon_regmap_lookup_by_phandle(np,
> "samsung,syscon-phandle");
>
> if (IS_ERR(pmu_context->pmu_regmap)) {
> pr_err("failed to find exynos_pmu_regmap\n");
> return PTR_ERR(pmu_context->pmu_regmap);
> }
>
> if (pmu_context->pmu_data->pmu_init)
> pmu_context->pmu_data->pmu_init();
>
> break;
> }
> ============================================================

Okay. Let me wait for one or two more days for more review on this,
then in next version I will improve/optimize it further.

In addition to above, since my syscon change has been accepted [1],
I will change function call "syscon_regmap_lookup_by_phandle
passing second parameter as NULL, this will also help us not to add
a property in PMU device node which is pointing back to itself. So I will
also update DT patch series, along with next revision of this patch series.

[1]: https://lkml.org/lkml/2014/4/30/349


>> +
>> + pmu_context->dev = dev;
>> +
>> + platform_set_drvdata(pdev, pmu_context);
>> +
>> + pr_info("Exynos PMU Driver probe done!!!\n");
>> + return 0;
>> +}
>> +
>> +static int exynos_pmu_suspend(struct device *dev)
>> +{
>> + /* ToDo: */
>> return 0;
>> }
>> -arch_initcall(exynos_pmu_init);
>> +
>> +static int exynos_pmu_resume(struct device *dev)
>> +{
>> + /* ToDo: */
>> + return 0;
>> +}
>> +
>> +static const struct dev_pm_ops exynos_pmu_pm = {
>> + .suspend = exynos_pmu_suspend,
>> + .resume = exynos_pmu_resume,
>> +};
>> +
>> +static int exynos_pmu_remove(struct platform_device *pdev)
>> +{
>> + /* nothing to do here */
>> + return 0;
>> +}
>> +
>> +static struct platform_device *exynos_pmu_pdev;
>> +
>> +static struct platform_driver exynos_pmu_driver = {
>> + .driver = {
>> + .name = "exynos-pmu",
>> + .owner = THIS_MODULE,
>> + .pm = &exynos_pmu_pm,
>> + },
>> + .probe = exynos_pmu_probe,
>> + .remove = exynos_pmu_remove,
>> +};
>> +
>> +static int __init exynos_pmu_of_init(void)
>> +{
>> + int ret;
>> +
>> + ret = platform_driver_register(&exynos_pmu_driver);
>> + if (ret < 0)
>> + goto out;
>> +
>> + exynos_pmu_pdev = platform_device_register_simple("exynos-pmu", -1,
>> + NULL, 0);
>> +
>> + if (IS_ERR(exynos_pmu_pdev)) {
>> + ret = PTR_ERR(exynos_pmu_pdev);
>> + goto out1;
>> + }
>> +
>> + return 0;
>> +out1:
>> + platform_driver_unregister(&exynos_pmu_driver);
>> +out:
>> + return ret;
>> +}
>> +arch_initcall(exynos_pmu_of_init);
>> +
>> +static void __exit exynos_pmu_exit(void)
>> +{
>> + platform_device_unregister(exynos_pmu_pdev);
>> + platform_driver_unregister(&exynos_pmu_driver);
>> +}
>> +module_exit(exynos_pmu_exit);
>> +
>> +MODULE_AUTHOR("Pankaj Dubey <[email protected]");
>> +MODULE_LICENSE("GPL v2");
>> +MODULE_DESCRIPTION("EXYNOS Power Management Unit Driver");
>> --
>> 1.7.10.4
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
>> the body of a message to [email protected]
>> More majordomo info at http://vger.kernel.org/majordomo-info.html


--
Best Regards,
Pankaj Dubey