Samsung exynos updates in arch/arm/mach-exynos/ for v3.19
- add SOC_EXYNOS4415 config to be used in audio driver - add support platform driver for exynos PMU - move PMU specific definitions from common.h to exynos-pmu.h - for exynos5420, add support PMU and Suspend-to-RAM use MCPM call backs and call regulator core suspend prepare and finish functions NOTE: including v3.19-next/non-critical-fixes, v3.19-next/cleanup-samsung and v3.19-next/pm-samsung-2 branches -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJUb0TrAAoJEA0Cl+kVi2xqJDEQAKwcA/2h1PftCpwP720wXZE/ yG3JTnFLU3zbRa/ZhKiye6l227k60PAEn1lJU1OBtNvjYyEjOiso3BsWaxdBflxT URw9IXp6tr6efDUhx1YYb5akSzPLm5dsR1PuyIPYlfdpU2Gqtwizcs8W7pLSKOP8 fzR5WgZoFq+XaqiKZKhl9NEKV5itNgJpr2UcIAw+p0zeEJ4eyX+fuXtObpBSsdfn +WE2jqNhLhpO1TcXZzguqw0tCiYc8pSMnqIPmdj+326dMQ6SyjNnigEvFRgDZBbj pXRG6aA/AtUmbd9WD9g9klfFANyz8XJQ7YYCZMFsmGuXzQKeuodeKbIsilo+bdtK 4Tz5X3xrI4eK1MXcKpzm7bQTlX/5j4O0zDdynhT3t9wuEX8Ed+aVFz850EKIUdWE Ln7ktbR7Ae84KfZGCO5fHk6qCxgU/vWzP5fCf80lQqd9cwKK7Lv3sqJmyfAWgqKD pcqN86NFtTlVdR/Rytv8dzqNeb3oE/xwTdb/ZXG2rc5qhXdZtEfIqembwy+pXHfN ZCJJNGKOP2yr/N3xdx3QtYi7JFQ2pDYTIKRCE82e6/MnNRL3YFxmlGG1mFZMgLbE 10fY2VWy90/yZt/wQxAtPh2C/T3/SoIEmZ+Z12GyD9T8ppEEFEFkn2Z5vTLytPug O3nw14OGrj0tbSdaJ7Iy =FzS8 -----END PGP SIGNATURE----- Merge tag 'samsung-exynos-v3.19' of git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung into next/soc Pull "Samsung exynos updates in arch/arm/mach-exynos/ for v3.19" from Kukjin Kim: - add SOC_EXYNOS4415 config to be used in audio driver - add support platform driver for exynos PMU - move PMU specific definitions from common.h to exynos-pmu.h - for exynos5420, add support PMU and Suspend-to-RAM use MCPM call backs and call regulator core suspend prepare and finish functions NOTE: including v3.19-next/non-critical-fixes, v3.19-next/cleanup-samsung and v3.19-next/pm-samsung-2 branches * tag 'samsung-exynos-v3.19' of git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung: ARM: EXYNOS: Call regulator core suspend prepare and finish functions ARM: EXYNOS: Use MCPM call-backs to support S2R on exynos5420 ARM: EXYNOS: Add Suspend-to-RAM support for exynos5420 ARM: EXYNOS: Add PMU support for exynos5420 ARM: EXYNOS: Move PMU specific definitions from common.h ARM: EXYNOS: Add platform driver support for Exynos PMU ARM: EXYNOS: Add support for exynos4415 SoC ARM: EXYNOS: fix typo in static struct name "exynos5_list_diable_wfi_wfe" ARM: EXYNOS: Fix CPU idle clock down after CPU off ARM: EXYNOS: Remove unneeded __ref annotation for cpu_die function ARM: EXYNOS: Move code from hotplug.c to platsmp.c Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
commit
5c5ee5e7c1
|
@ -24,6 +24,7 @@ menuconfig ARCH_EXYNOS
|
|||
select PM_GENERIC_DOMAINS if PM_RUNTIME
|
||||
select S5P_DEV_MFC
|
||||
select SRAM
|
||||
select MFD_SYSCON
|
||||
help
|
||||
Support for SAMSUNG EXYNOS SoCs (EXYNOS4/5)
|
||||
|
||||
|
@ -75,6 +76,11 @@ config SOC_EXYNOS4412
|
|||
default y
|
||||
depends on ARCH_EXYNOS4
|
||||
|
||||
config SOC_EXYNOS4415
|
||||
bool "SAMSUNG EXYNOS4415"
|
||||
default y
|
||||
depends on ARCH_EXYNOS4
|
||||
|
||||
config SOC_EXYNOS5250
|
||||
bool "SAMSUNG EXYNOS5250"
|
||||
default y
|
||||
|
|
|
@ -17,9 +17,6 @@ obj-$(CONFIG_PM_GENERIC_DOMAINS) += pm_domains.o
|
|||
|
||||
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
|
||||
|
||||
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
|
||||
CFLAGS_hotplug.o += -march=armv7-a
|
||||
|
||||
plus_sec := $(call as-instr,.arch_extension sec,+sec)
|
||||
AFLAGS_exynos-smc.o :=-Wa,-march=armv7-a$(plus_sec)
|
||||
AFLAGS_sleep.o :=-Wa,-march=armv7-a$(plus_sec)
|
||||
|
|
|
@ -139,25 +139,6 @@ extern void exynos_cpu_resume_ns(void);
|
|||
|
||||
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,
|
||||
};
|
||||
|
||||
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_cpu_power_down(int cpu);
|
||||
extern void exynos_cpu_power_up(int cpu);
|
||||
extern int exynos_cpu_power_state(int cpu);
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* 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
|
||||
|
||||
enum sys_powerdown {
|
||||
SYS_AFTR,
|
||||
SYS_LPA,
|
||||
SYS_SLEEP,
|
||||
NUM_SYS_POWERDOWN,
|
||||
};
|
||||
|
||||
extern void exynos_sys_powerdown_conf(enum sys_powerdown mode);
|
||||
|
||||
#endif /* __EXYNOS_PMU_H */
|
|
@ -252,6 +252,7 @@ static const struct of_device_id exynos_dt_pmu_match[] = {
|
|||
{ .compatible = "samsung,exynos4210-pmu" },
|
||||
{ .compatible = "samsung,exynos4212-pmu" },
|
||||
{ .compatible = "samsung,exynos4412-pmu" },
|
||||
{ .compatible = "samsung,exynos4415-pmu" },
|
||||
{ .compatible = "samsung,exynos5250-pmu" },
|
||||
{ .compatible = "samsung,exynos5260-pmu" },
|
||||
{ .compatible = "samsung,exynos5410-pmu" },
|
||||
|
@ -336,6 +337,7 @@ static char const *exynos_dt_compat[] __initconst = {
|
|||
"samsung,exynos4210",
|
||||
"samsung,exynos4212",
|
||||
"samsung,exynos4412",
|
||||
"samsung,exynos4415",
|
||||
"samsung,exynos5",
|
||||
"samsung,exynos5250",
|
||||
"samsung,exynos5260",
|
||||
|
|
|
@ -1,91 +0,0 @@
|
|||
/*
|
||||
* Cloned from linux/arch/arm/mach-realview/hotplug.c
|
||||
*
|
||||
* Copyright (C) 2002 ARM Ltd.
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/cp15.h>
|
||||
#include <asm/smp_plat.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "regs-pmu.h"
|
||||
|
||||
static inline void cpu_leave_lowpower(void)
|
||||
{
|
||||
unsigned int v;
|
||||
|
||||
asm volatile(
|
||||
"mrc p15, 0, %0, c1, c0, 0\n"
|
||||
" orr %0, %0, %1\n"
|
||||
" mcr p15, 0, %0, c1, c0, 0\n"
|
||||
" mrc p15, 0, %0, c1, c0, 1\n"
|
||||
" orr %0, %0, %2\n"
|
||||
" mcr p15, 0, %0, c1, c0, 1\n"
|
||||
: "=&r" (v)
|
||||
: "Ir" (CR_C), "Ir" (0x40)
|
||||
: "cc");
|
||||
}
|
||||
|
||||
static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
|
||||
{
|
||||
u32 mpidr = cpu_logical_map(cpu);
|
||||
u32 core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
|
||||
|
||||
for (;;) {
|
||||
|
||||
/* Turn the CPU off on next WFI instruction. */
|
||||
exynos_cpu_power_down(core_id);
|
||||
|
||||
wfi();
|
||||
|
||||
if (pen_release == core_id) {
|
||||
/*
|
||||
* OK, proper wakeup, we're done
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Getting here, means that we have come out of WFI without
|
||||
* having been woken up - this shouldn't happen
|
||||
*
|
||||
* Just note it happening - when we're woken, we can report
|
||||
* its occurrence.
|
||||
*/
|
||||
(*spurious)++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* platform-specific code to shutdown a CPU
|
||||
*
|
||||
* Called with IRQs disabled
|
||||
*/
|
||||
void __ref exynos_cpu_die(unsigned int cpu)
|
||||
{
|
||||
int spurious = 0;
|
||||
|
||||
v7_exit_coherency_flush(louis);
|
||||
|
||||
platform_do_lowpower(cpu, &spurious);
|
||||
|
||||
/*
|
||||
* bring this CPU back into the world of cache
|
||||
* coherency, and then restore interrupts
|
||||
*/
|
||||
cpu_leave_lowpower();
|
||||
|
||||
if (spurious)
|
||||
pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
|
||||
}
|
|
@ -15,6 +15,7 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/syscore_ops.h>
|
||||
|
||||
#include <asm/cputype.h>
|
||||
#include <asm/cp15.h>
|
||||
|
@ -30,6 +31,8 @@
|
|||
#define EXYNOS5420_USE_ARM_CORE_DOWN_STATE BIT(29)
|
||||
#define EXYNOS5420_USE_L2_COMMON_UP_STATE BIT(30)
|
||||
|
||||
static void __iomem *ns_sram_base_addr;
|
||||
|
||||
/*
|
||||
* The common v7_exit_coherency_flush API could not be used because of the
|
||||
* Erratum 799270 workaround. This macro is the same as the common one (in
|
||||
|
@ -318,10 +321,26 @@ static const struct of_device_id exynos_dt_mcpm_match[] = {
|
|||
{},
|
||||
};
|
||||
|
||||
static void exynos_mcpm_setup_entry_point(void)
|
||||
{
|
||||
/*
|
||||
* U-Boot SPL is hardcoded to jump to the start of ns_sram_base_addr
|
||||
* as part of secondary_cpu_start(). Let's redirect it to the
|
||||
* mcpm_entry_point(). This is done during both secondary boot-up as
|
||||
* well as system resume.
|
||||
*/
|
||||
__raw_writel(0xe59f0000, ns_sram_base_addr); /* ldr r0, [pc, #0] */
|
||||
__raw_writel(0xe12fff10, ns_sram_base_addr + 4); /* bx r0 */
|
||||
__raw_writel(virt_to_phys(mcpm_entry_point), ns_sram_base_addr + 8);
|
||||
}
|
||||
|
||||
static struct syscore_ops exynos_mcpm_syscore_ops = {
|
||||
.resume = exynos_mcpm_setup_entry_point,
|
||||
};
|
||||
|
||||
static int __init exynos_mcpm_init(void)
|
||||
{
|
||||
struct device_node *node;
|
||||
void __iomem *ns_sram_base_addr;
|
||||
unsigned int value, i;
|
||||
int ret;
|
||||
|
||||
|
@ -387,16 +406,9 @@ static int __init exynos_mcpm_init(void)
|
|||
pmu_raw_writel(value, EXYNOS_COMMON_OPTION(i));
|
||||
}
|
||||
|
||||
/*
|
||||
* U-Boot SPL is hardcoded to jump to the start of ns_sram_base_addr
|
||||
* as part of secondary_cpu_start(). Let's redirect it to the
|
||||
* mcpm_entry_point().
|
||||
*/
|
||||
__raw_writel(0xe59f0000, ns_sram_base_addr); /* ldr r0, [pc, #0] */
|
||||
__raw_writel(0xe12fff10, ns_sram_base_addr + 4); /* bx r0 */
|
||||
__raw_writel(virt_to_phys(mcpm_entry_point), ns_sram_base_addr + 8);
|
||||
exynos_mcpm_setup_entry_point();
|
||||
|
||||
iounmap(ns_sram_base_addr);
|
||||
register_syscore_ops(&exynos_mcpm_syscore_ops);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <linux/of_address.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/cp15.h>
|
||||
#include <asm/smp_plat.h>
|
||||
#include <asm/smp_scu.h>
|
||||
#include <asm/firmware.h>
|
||||
|
@ -33,6 +34,88 @@
|
|||
|
||||
extern void exynos4_secondary_startup(void);
|
||||
|
||||
/*
|
||||
* Set or clear the USE_DELAYED_RESET_ASSERTION option, set on Exynos4 SoCs
|
||||
* during hot-(un)plugging CPUx.
|
||||
*
|
||||
* The feature can be cleared safely during first boot of secondary CPU.
|
||||
*
|
||||
* Exynos4 SoCs require setting USE_DELAYED_RESET_ASSERTION during powering
|
||||
* down a CPU so the CPU idle clock down feature could properly detect global
|
||||
* idle state when CPUx is off.
|
||||
*/
|
||||
static void exynos_set_delayed_reset_assertion(u32 core_id, bool enable)
|
||||
{
|
||||
if (soc_is_exynos4()) {
|
||||
unsigned int tmp;
|
||||
|
||||
tmp = pmu_raw_readl(EXYNOS_ARM_CORE_OPTION(core_id));
|
||||
if (enable)
|
||||
tmp |= S5P_USE_DELAYED_RESET_ASSERTION;
|
||||
else
|
||||
tmp &= ~(S5P_USE_DELAYED_RESET_ASSERTION);
|
||||
pmu_raw_writel(tmp, EXYNOS_ARM_CORE_OPTION(core_id));
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
static inline void cpu_leave_lowpower(u32 core_id)
|
||||
{
|
||||
unsigned int v;
|
||||
|
||||
asm volatile(
|
||||
"mrc p15, 0, %0, c1, c0, 0\n"
|
||||
" orr %0, %0, %1\n"
|
||||
" mcr p15, 0, %0, c1, c0, 0\n"
|
||||
" mrc p15, 0, %0, c1, c0, 1\n"
|
||||
" orr %0, %0, %2\n"
|
||||
" mcr p15, 0, %0, c1, c0, 1\n"
|
||||
: "=&r" (v)
|
||||
: "Ir" (CR_C), "Ir" (0x40)
|
||||
: "cc");
|
||||
|
||||
exynos_set_delayed_reset_assertion(core_id, false);
|
||||
}
|
||||
|
||||
static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
|
||||
{
|
||||
u32 mpidr = cpu_logical_map(cpu);
|
||||
u32 core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
|
||||
|
||||
for (;;) {
|
||||
|
||||
/* Turn the CPU off on next WFI instruction. */
|
||||
exynos_cpu_power_down(core_id);
|
||||
|
||||
/*
|
||||
* Exynos4 SoCs require setting
|
||||
* USE_DELAYED_RESET_ASSERTION so the CPU idle
|
||||
* clock down feature could properly detect
|
||||
* global idle state when CPUx is off.
|
||||
*/
|
||||
exynos_set_delayed_reset_assertion(core_id, true);
|
||||
|
||||
wfi();
|
||||
|
||||
if (pen_release == core_id) {
|
||||
/*
|
||||
* OK, proper wakeup, we're done
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Getting here, means that we have come out of WFI without
|
||||
* having been woken up - this shouldn't happen
|
||||
*
|
||||
* Just note it happening - when we're woken, we can report
|
||||
* its occurrence.
|
||||
*/
|
||||
(*spurious)++;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_HOTPLUG_CPU */
|
||||
|
||||
/**
|
||||
* exynos_core_power_down : power down the specified cpu
|
||||
* @cpu : the cpu to power down
|
||||
|
@ -43,6 +126,18 @@ extern void exynos4_secondary_startup(void);
|
|||
*/
|
||||
void exynos_cpu_power_down(int cpu)
|
||||
{
|
||||
if (cpu == 0 && (of_machine_is_compatible("samsung,exynos5420") ||
|
||||
of_machine_is_compatible("samsung,exynos5800"))) {
|
||||
/*
|
||||
* Bypass power down for CPU0 during suspend. Check for
|
||||
* the SYS_PWR_REG value to decide if we are suspending
|
||||
* the system.
|
||||
*/
|
||||
int val = pmu_raw_readl(EXYNOS5_ARM_CORE0_SYS_PWR_REG);
|
||||
|
||||
if (!(val & S5P_CORE_LOCAL_PWR_EN))
|
||||
return;
|
||||
}
|
||||
pmu_raw_writel(0, EXYNOS_ARM_CORE_CONFIGURATION(cpu));
|
||||
}
|
||||
|
||||
|
@ -260,6 +355,9 @@ static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
|||
udelay(10);
|
||||
}
|
||||
|
||||
/* No harm if this is called during first boot of secondary CPU */
|
||||
exynos_set_delayed_reset_assertion(core_id, false);
|
||||
|
||||
/*
|
||||
* now the secondary core is starting up let it run its
|
||||
* calibrations, then wait for it to finish
|
||||
|
@ -341,6 +439,33 @@ static void __init exynos_smp_prepare_cpus(unsigned int max_cpus)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
/*
|
||||
* platform-specific code to shutdown a CPU
|
||||
*
|
||||
* Called with IRQs disabled
|
||||
*/
|
||||
static void exynos_cpu_die(unsigned int cpu)
|
||||
{
|
||||
int spurious = 0;
|
||||
u32 mpidr = cpu_logical_map(cpu);
|
||||
u32 core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
|
||||
|
||||
v7_exit_coherency_flush(louis);
|
||||
|
||||
platform_do_lowpower(cpu, &spurious);
|
||||
|
||||
/*
|
||||
* bring this CPU back into the world of cache
|
||||
* coherency, and then restore interrupts
|
||||
*/
|
||||
cpu_leave_lowpower(core_id);
|
||||
|
||||
if (spurious)
|
||||
pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
|
||||
}
|
||||
#endif /* CONFIG_HOTPLUG_CPU */
|
||||
|
||||
struct smp_operations exynos_smp_ops __initdata = {
|
||||
.smp_init_cpus = exynos_smp_init_cpus,
|
||||
.smp_prepare_cpus = exynos_smp_prepare_cpus,
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <plat/pm-common.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "exynos-pmu.h"
|
||||
#include "regs-pmu.h"
|
||||
#include "regs-sys.h"
|
||||
|
||||
|
|
|
@ -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
|
||||
|
@ -10,12 +10,46 @@
|
|||
*/
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include "exynos-pmu.h"
|
||||
#include "regs-pmu.h"
|
||||
|
||||
static const struct exynos_pmu_conf *exynos_pmu_config;
|
||||
#define PMU_TABLE_END (-1U)
|
||||
|
||||
struct exynos_pmu_conf {
|
||||
unsigned int offset;
|
||||
unsigned int val[NUM_SYS_POWERDOWN];
|
||||
};
|
||||
|
||||
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;
|
||||
const struct exynos_pmu_data *pmu_data;
|
||||
};
|
||||
|
||||
static void __iomem *pmu_base_addr;
|
||||
static struct exynos_pmu_context *pmu_context;
|
||||
|
||||
static inline void pmu_raw_writel(u32 val, u32 offset)
|
||||
{
|
||||
writel_relaxed(val, pmu_base_addr + offset);
|
||||
}
|
||||
|
||||
static inline u32 pmu_raw_readl(u32 offset)
|
||||
{
|
||||
return readl_relaxed(pmu_base_addr + offset);
|
||||
}
|
||||
|
||||
static const struct exynos_pmu_conf exynos4210_pmu_config[] = {
|
||||
/* { .offset = offset, .val = { AFTR, LPA, SLEEP } */
|
||||
|
@ -316,6 +350,151 @@ static const struct exynos_pmu_conf exynos5250_pmu_config[] = {
|
|||
{ PMU_TABLE_END,},
|
||||
};
|
||||
|
||||
static struct exynos_pmu_conf exynos5420_pmu_config[] = {
|
||||
/* { .offset = offset, .val = { AFTR, LPA, SLEEP } */
|
||||
{ EXYNOS5_ARM_CORE0_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5_DIS_IRQ_ARM_CORE0_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5_DIS_IRQ_ARM_CORE0_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5_ARM_CORE1_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5_DIS_IRQ_ARM_CORE1_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5_DIS_IRQ_ARM_CORE1_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_ARM_CORE2_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_DIS_IRQ_ARM_CORE2_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_DIS_IRQ_ARM_CORE2_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_ARM_CORE3_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_DIS_IRQ_ARM_CORE3_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_DIS_IRQ_ARM_CORE3_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_KFC_CORE0_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_DIS_IRQ_KFC_CORE0_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_DIS_IRQ_KFC_CORE0_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_KFC_CORE1_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_DIS_IRQ_KFC_CORE1_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_DIS_IRQ_KFC_CORE1_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_KFC_CORE2_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_DIS_IRQ_KFC_CORE2_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_DIS_IRQ_KFC_CORE2_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_KFC_CORE3_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_DIS_IRQ_KFC_CORE3_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_DIS_IRQ_KFC_CORE3_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5_ISP_ARM_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_DIS_IRQ_ISP_ARM_LOCAL_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_DIS_IRQ_ISP_ARM_CENTRAL_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5420_ARM_COMMON_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_KFC_COMMON_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5_ARM_L2_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_KFC_L2_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5_CMU_ACLKSTOP_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_CMU_SCLKSTOP_SYS_PWR_REG, { 0x1, 0x0, 0x1} },
|
||||
{ EXYNOS5_CMU_RESET_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
|
||||
{ EXYNOS5_CMU_ACLKSTOP_SYSMEM_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_CMU_SCLKSTOP_SYSMEM_SYS_PWR_REG, { 0x1, 0x0, 0x1} },
|
||||
{ EXYNOS5_CMU_RESET_SYSMEM_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
|
||||
{ EXYNOS5_DRAM_FREQ_DOWN_SYS_PWR_REG, { 0x1, 0x0, 0x1} },
|
||||
{ EXYNOS5_DDRPHY_DLLOFF_SYS_PWR_REG, { 0x1, 0x1, 0x1} },
|
||||
{ EXYNOS5_DDRPHY_DLLLOCK_SYS_PWR_REG, { 0x1, 0x0, 0x1} },
|
||||
{ EXYNOS5_APLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_MPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_VPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_EPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
|
||||
{ EXYNOS5_BPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_CPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5420_DPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5420_IPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5420_KPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_MPLLUSER_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_BPLLUSER_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5420_RPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5420_SPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_TOP_BUS_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
|
||||
{ EXYNOS5_TOP_RETENTION_SYS_PWR_REG, { 0x1, 0x1, 0x1} },
|
||||
{ EXYNOS5_TOP_PWR_SYS_PWR_REG, { 0x3, 0x3, 0x0} },
|
||||
{ EXYNOS5_TOP_BUS_SYSMEM_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
|
||||
{ EXYNOS5_TOP_RETENTION_SYSMEM_SYS_PWR_REG, { 0x1, 0x0, 0x1} },
|
||||
{ EXYNOS5_TOP_PWR_SYSMEM_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
|
||||
{ EXYNOS5_LOGIC_RESET_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
|
||||
{ EXYNOS5_OSCCLK_GATE_SYS_PWR_REG, { 0x1, 0x0, 0x1} },
|
||||
{ EXYNOS5_LOGIC_RESET_SYSMEM_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_OSCCLK_GATE_SYSMEM_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5420_INTRAM_MEM_SYS_PWR_REG, { 0x3, 0x0, 0x3} },
|
||||
{ EXYNOS5420_INTROM_MEM_SYS_PWR_REG, { 0x3, 0x0, 0x3} },
|
||||
{ EXYNOS5_PAD_RETENTION_DRAM_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_PAD_RETENTION_MAU_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
|
||||
{ EXYNOS5420_PAD_RETENTION_JTAG_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
|
||||
{ EXYNOS5420_PAD_RETENTION_DRAM_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5420_PAD_RETENTION_UART_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5420_PAD_RETENTION_MMC0_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5420_PAD_RETENTION_MMC1_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5420_PAD_RETENTION_MMC2_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5420_PAD_RETENTION_HSI_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5420_PAD_RETENTION_EBIA_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5420_PAD_RETENTION_EBIB_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5420_PAD_RETENTION_SPI_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5420_PAD_RETENTION_DRAM_COREBLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_PAD_ISOLATION_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
|
||||
{ EXYNOS5_PAD_ISOLATION_SYSMEM_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_PAD_ALV_SEL_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_XUSBXTI_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
|
||||
{ EXYNOS5_XXTI_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
|
||||
{ EXYNOS5_EXT_REGULATOR_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
|
||||
{ EXYNOS5_GPIO_MODE_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_GPIO_MODE_SYSMEM_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
|
||||
{ EXYNOS5_GPIO_MODE_MAU_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
|
||||
{ EXYNOS5_TOP_ASB_RESET_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
|
||||
{ EXYNOS5_TOP_ASB_ISOLATION_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_GSCL_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
|
||||
{ EXYNOS5_ISP_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
|
||||
{ EXYNOS5_MFC_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
|
||||
{ EXYNOS5_G3D_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
|
||||
{ EXYNOS5420_DISP1_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
|
||||
{ EXYNOS5420_MAU_SYS_PWR_REG, { 0x7, 0x7, 0x0} },
|
||||
{ EXYNOS5420_G2D_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
|
||||
{ EXYNOS5420_MSC_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
|
||||
{ EXYNOS5420_FSYS_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
|
||||
{ EXYNOS5420_FSYS2_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
|
||||
{ EXYNOS5420_PSGEN_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
|
||||
{ EXYNOS5420_PERIC_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
|
||||
{ EXYNOS5420_WCORE_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
|
||||
{ EXYNOS5_CMU_CLKSTOP_GSCL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5_CMU_CLKSTOP_ISP_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5_CMU_CLKSTOP_MFC_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5_CMU_CLKSTOP_G3D_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_CMU_CLKSTOP_DISP1_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_CMU_CLKSTOP_MAU_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_CMU_CLKSTOP_G2D_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_CMU_CLKSTOP_MSC_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_CMU_CLKSTOP_FSYS_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_CMU_CLKSTOP_PSGEN_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_CMU_CLKSTOP_PERIC_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_CMU_CLKSTOP_WCORE_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5_CMU_SYSCLK_GSCL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5_CMU_SYSCLK_ISP_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5_CMU_SYSCLK_MFC_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5_CMU_SYSCLK_G3D_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_CMU_SYSCLK_DISP1_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_CMU_SYSCLK_MAU_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_CMU_SYSCLK_G2D_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_CMU_SYSCLK_MSC_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_CMU_SYSCLK_FSYS_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_CMU_SYSCLK_FSYS2_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_CMU_SYSCLK_PSGEN_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_CMU_SYSCLK_PERIC_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_CMU_SYSCLK_WCORE_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_CMU_RESET_FSYS2_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_CMU_RESET_PSGEN_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_CMU_RESET_PERIC_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_CMU_RESET_WCORE_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5_CMU_RESET_GSCL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5_CMU_RESET_ISP_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5_CMU_RESET_MFC_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5_CMU_RESET_G3D_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_CMU_RESET_DISP1_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_CMU_RESET_MAU_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_CMU_RESET_G2D_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_CMU_RESET_MSC_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5420_CMU_RESET_FSYS_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ PMU_TABLE_END,},
|
||||
};
|
||||
|
||||
static unsigned int const exynos5_list_both_cnt_feed[] = {
|
||||
EXYNOS5_ARM_CORE0_OPTION,
|
||||
EXYNOS5_ARM_CORE1_OPTION,
|
||||
|
@ -330,13 +509,82 @@ static unsigned int const exynos5_list_both_cnt_feed[] = {
|
|||
EXYNOS5_TOP_PWR_SYSMEM_OPTION,
|
||||
};
|
||||
|
||||
static unsigned int const exynos5_list_diable_wfi_wfe[] = {
|
||||
static unsigned int const exynos5_list_disable_wfi_wfe[] = {
|
||||
EXYNOS5_ARM_CORE1_OPTION,
|
||||
EXYNOS5_FSYS_ARM_OPTION,
|
||||
EXYNOS5_ISP_ARM_OPTION,
|
||||
};
|
||||
|
||||
static void exynos5_init_pmu(void)
|
||||
static unsigned int const exynos5420_list_disable_pmu_reg[] = {
|
||||
EXYNOS5_CMU_CLKSTOP_GSCL_SYS_PWR_REG,
|
||||
EXYNOS5_CMU_CLKSTOP_ISP_SYS_PWR_REG,
|
||||
EXYNOS5_CMU_CLKSTOP_G3D_SYS_PWR_REG,
|
||||
EXYNOS5420_CMU_CLKSTOP_DISP1_SYS_PWR_REG,
|
||||
EXYNOS5420_CMU_CLKSTOP_MAU_SYS_PWR_REG,
|
||||
EXYNOS5420_CMU_CLKSTOP_G2D_SYS_PWR_REG,
|
||||
EXYNOS5420_CMU_CLKSTOP_MSC_SYS_PWR_REG,
|
||||
EXYNOS5420_CMU_CLKSTOP_FSYS_SYS_PWR_REG,
|
||||
EXYNOS5420_CMU_CLKSTOP_PSGEN_SYS_PWR_REG,
|
||||
EXYNOS5420_CMU_CLKSTOP_PERIC_SYS_PWR_REG,
|
||||
EXYNOS5420_CMU_CLKSTOP_WCORE_SYS_PWR_REG,
|
||||
EXYNOS5_CMU_SYSCLK_GSCL_SYS_PWR_REG,
|
||||
EXYNOS5_CMU_SYSCLK_ISP_SYS_PWR_REG,
|
||||
EXYNOS5_CMU_SYSCLK_G3D_SYS_PWR_REG,
|
||||
EXYNOS5420_CMU_SYSCLK_DISP1_SYS_PWR_REG,
|
||||
EXYNOS5420_CMU_SYSCLK_MAU_SYS_PWR_REG,
|
||||
EXYNOS5420_CMU_SYSCLK_G2D_SYS_PWR_REG,
|
||||
EXYNOS5420_CMU_SYSCLK_MSC_SYS_PWR_REG,
|
||||
EXYNOS5420_CMU_SYSCLK_FSYS_SYS_PWR_REG,
|
||||
EXYNOS5420_CMU_SYSCLK_FSYS2_SYS_PWR_REG,
|
||||
EXYNOS5420_CMU_SYSCLK_PSGEN_SYS_PWR_REG,
|
||||
EXYNOS5420_CMU_SYSCLK_PERIC_SYS_PWR_REG,
|
||||
EXYNOS5420_CMU_SYSCLK_WCORE_SYS_PWR_REG,
|
||||
EXYNOS5420_CMU_RESET_FSYS2_SYS_PWR_REG,
|
||||
EXYNOS5420_CMU_RESET_PSGEN_SYS_PWR_REG,
|
||||
EXYNOS5420_CMU_RESET_PERIC_SYS_PWR_REG,
|
||||
EXYNOS5420_CMU_RESET_WCORE_SYS_PWR_REG,
|
||||
EXYNOS5_CMU_RESET_GSCL_SYS_PWR_REG,
|
||||
EXYNOS5_CMU_RESET_ISP_SYS_PWR_REG,
|
||||
EXYNOS5_CMU_RESET_G3D_SYS_PWR_REG,
|
||||
EXYNOS5420_CMU_RESET_DISP1_SYS_PWR_REG,
|
||||
EXYNOS5420_CMU_RESET_MAU_SYS_PWR_REG,
|
||||
EXYNOS5420_CMU_RESET_G2D_SYS_PWR_REG,
|
||||
EXYNOS5420_CMU_RESET_MSC_SYS_PWR_REG,
|
||||
EXYNOS5420_CMU_RESET_FSYS_SYS_PWR_REG,
|
||||
};
|
||||
|
||||
static void exynos5_power_off(void)
|
||||
{
|
||||
unsigned int tmp;
|
||||
|
||||
pr_info("Power down.\n");
|
||||
tmp = pmu_raw_readl(EXYNOS_PS_HOLD_CONTROL);
|
||||
tmp ^= (1 << 8);
|
||||
pmu_raw_writel(tmp, EXYNOS_PS_HOLD_CONTROL);
|
||||
|
||||
/* Wait a little so we don't give a false warning below */
|
||||
mdelay(100);
|
||||
|
||||
pr_err("Power down failed, please power off system manually.\n");
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
void exynos5420_powerdown_conf(enum sys_powerdown mode)
|
||||
{
|
||||
u32 this_cluster;
|
||||
|
||||
this_cluster = MPIDR_AFFINITY_LEVEL(read_cpuid_mpidr(), 1);
|
||||
|
||||
/*
|
||||
* set the cluster id to IROM register to ensure that we wake
|
||||
* up with the current cluster.
|
||||
*/
|
||||
pmu_raw_writel(this_cluster, EXYNOS_IROM_DATA2);
|
||||
}
|
||||
|
||||
|
||||
static void exynos5_powerdown_conf(enum sys_powerdown mode)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int tmp;
|
||||
|
@ -344,7 +592,7 @@ 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++) {
|
||||
for (i = 0; i < ARRAY_SIZE(exynos5_list_both_cnt_feed); i++) {
|
||||
tmp = pmu_raw_readl(exynos5_list_both_cnt_feed[i]);
|
||||
tmp |= (EXYNOS5_USE_SC_FEEDBACK |
|
||||
EXYNOS5_USE_SC_COUNTER);
|
||||
|
@ -361,11 +609,11 @@ static void exynos5_init_pmu(void)
|
|||
/*
|
||||
* Disable WFI/WFE on XXX_OPTION
|
||||
*/
|
||||
for (i = 0 ; i < ARRAY_SIZE(exynos5_list_diable_wfi_wfe) ; i++) {
|
||||
tmp = pmu_raw_readl(exynos5_list_diable_wfi_wfe[i]);
|
||||
for (i = 0; i < ARRAY_SIZE(exynos5_list_disable_wfi_wfe); i++) {
|
||||
tmp = pmu_raw_readl(exynos5_list_disable_wfi_wfe[i]);
|
||||
tmp &= ~(EXYNOS5_OPTION_USE_STANDBYWFE |
|
||||
EXYNOS5_OPTION_USE_STANDBYWFI);
|
||||
pmu_raw_writel(tmp, exynos5_list_diable_wfi_wfe[i]);
|
||||
pmu_raw_writel(tmp, exynos5_list_disable_wfi_wfe[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -373,51 +621,195 @@ void exynos_sys_powerdown_conf(enum sys_powerdown mode)
|
|||
{
|
||||
unsigned int i;
|
||||
|
||||
if (soc_is_exynos5250())
|
||||
exynos5_init_pmu();
|
||||
const struct exynos_pmu_data *pmu_data = pmu_context->pmu_data;
|
||||
|
||||
for (i = 0; (exynos_pmu_config[i].offset != PMU_TABLE_END) ; i++)
|
||||
pmu_raw_writel(exynos_pmu_config[i].val[mode],
|
||||
exynos_pmu_config[i].offset);
|
||||
if (pmu_data->powerdown_conf)
|
||||
pmu_data->powerdown_conf(mode);
|
||||
|
||||
if (soc_is_exynos4412()) {
|
||||
for (i = 0; exynos4412_pmu_config[i].offset != PMU_TABLE_END ; i++)
|
||||
pmu_raw_writel(exynos4412_pmu_config[i].val[mode],
|
||||
exynos4412_pmu_config[i].offset);
|
||||
if (pmu_data->pmu_config) {
|
||||
for (i = 0; (pmu_data->pmu_config[i].offset != PMU_TABLE_END); i++)
|
||||
pmu_raw_writel(pmu_data->pmu_config[i].val[mode],
|
||||
pmu_data->pmu_config[i].offset);
|
||||
}
|
||||
|
||||
if (pmu_data->pmu_config_extra) {
|
||||
for (i = 0; pmu_data->pmu_config_extra[i].offset != PMU_TABLE_END; i++)
|
||||
pmu_raw_writel(pmu_data->pmu_config_extra[i].val[mode],
|
||||
pmu_data->pmu_config_extra[i].offset);
|
||||
}
|
||||
}
|
||||
|
||||
static void exynos5250_pmu_init(void)
|
||||
{
|
||||
unsigned int value;
|
||||
/*
|
||||
* When SYS_WDTRESET is set, watchdog timer reset request
|
||||
* is ignored by power management unit.
|
||||
*/
|
||||
value = pmu_raw_readl(EXYNOS5_AUTO_WDTRESET_DISABLE);
|
||||
value &= ~EXYNOS5_SYS_WDTRESET;
|
||||
pmu_raw_writel(value, EXYNOS5_AUTO_WDTRESET_DISABLE);
|
||||
|
||||
value = pmu_raw_readl(EXYNOS5_MASK_WDTRESET_REQUEST);
|
||||
value &= ~EXYNOS5_SYS_WDTRESET;
|
||||
pmu_raw_writel(value, EXYNOS5_MASK_WDTRESET_REQUEST);
|
||||
}
|
||||
|
||||
static void exynos5420_pmu_init(void)
|
||||
{
|
||||
unsigned int value;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Set the CMU_RESET, CMU_SYSCLK and CMU_CLKSTOP registers
|
||||
* for local power blocks to Low initially as per Table 8-4:
|
||||
* "System-Level Power-Down Configuration Registers".
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(exynos5420_list_disable_pmu_reg); i++)
|
||||
pmu_raw_writel(0, exynos5420_list_disable_pmu_reg[i]);
|
||||
|
||||
/* Enable USE_STANDBY_WFI for all CORE */
|
||||
pmu_raw_writel(EXYNOS5420_USE_STANDBY_WFI_ALL, S5P_CENTRAL_SEQ_OPTION);
|
||||
|
||||
value = pmu_raw_readl(EXYNOS_L2_OPTION(0));
|
||||
value &= ~EXYNOS5_USE_RETENTION;
|
||||
pmu_raw_writel(value, EXYNOS_L2_OPTION(0));
|
||||
|
||||
value = pmu_raw_readl(EXYNOS_L2_OPTION(1));
|
||||
value &= ~EXYNOS5_USE_RETENTION;
|
||||
pmu_raw_writel(value, EXYNOS_L2_OPTION(1));
|
||||
|
||||
/*
|
||||
* If L2_COMMON is turned off, clocks related to ATB async
|
||||
* bridge are gated. Thus, when ISP power is gated, LPI
|
||||
* may get stuck.
|
||||
*/
|
||||
value = pmu_raw_readl(EXYNOS5420_LPI_MASK);
|
||||
value |= EXYNOS5420_ATB_ISP_ARM;
|
||||
pmu_raw_writel(value, EXYNOS5420_LPI_MASK);
|
||||
|
||||
value = pmu_raw_readl(EXYNOS5420_LPI_MASK1);
|
||||
value |= EXYNOS5420_ATB_KFC;
|
||||
pmu_raw_writel(value, EXYNOS5420_LPI_MASK1);
|
||||
|
||||
/* Prevent issue of new bus request from L2 memory */
|
||||
value = pmu_raw_readl(EXYNOS5420_ARM_COMMON_OPTION);
|
||||
value |= EXYNOS5_SKIP_DEACTIVATE_ACEACP_IN_PWDN;
|
||||
pmu_raw_writel(value, EXYNOS5420_ARM_COMMON_OPTION);
|
||||
|
||||
value = pmu_raw_readl(EXYNOS5420_KFC_COMMON_OPTION);
|
||||
value |= EXYNOS5_SKIP_DEACTIVATE_ACEACP_IN_PWDN;
|
||||
pmu_raw_writel(value, EXYNOS5420_KFC_COMMON_OPTION);
|
||||
|
||||
/* This setting is to reduce suspend/resume time */
|
||||
pmu_raw_writel(DUR_WAIT_RESET, EXYNOS5420_LOGIC_RESET_DURATION3);
|
||||
|
||||
/* Serialized CPU wakeup of Eagle */
|
||||
pmu_raw_writel(SPREAD_ENABLE, EXYNOS5420_ARM_INTR_SPREAD_ENABLE);
|
||||
|
||||
pmu_raw_writel(SPREAD_USE_STANDWFI,
|
||||
EXYNOS5420_ARM_INTR_SPREAD_USE_STANDBYWFI);
|
||||
|
||||
pmu_raw_writel(0x1, EXYNOS5420_UP_SCHEDULER);
|
||||
|
||||
pm_power_off = exynos5_power_off;
|
||||
pr_info("EXYNOS5420 PMU initialized\n");
|
||||
}
|
||||
|
||||
|
||||
static const struct exynos_pmu_data exynos4210_pmu_data = {
|
||||
.pmu_config = exynos4210_pmu_config,
|
||||
};
|
||||
|
||||
static const struct exynos_pmu_data exynos4212_pmu_data = {
|
||||
.pmu_config = exynos4x12_pmu_config,
|
||||
};
|
||||
|
||||
static const struct exynos_pmu_data exynos4412_pmu_data = {
|
||||
.pmu_config = exynos4x12_pmu_config,
|
||||
.pmu_config_extra = exynos4412_pmu_config,
|
||||
};
|
||||
|
||||
static const struct exynos_pmu_data exynos5250_pmu_data = {
|
||||
.pmu_config = exynos5250_pmu_config,
|
||||
.pmu_init = exynos5250_pmu_init,
|
||||
.powerdown_conf = exynos5_powerdown_conf,
|
||||
};
|
||||
|
||||
static struct exynos_pmu_data exynos5420_pmu_data = {
|
||||
.pmu_config = exynos5420_pmu_config,
|
||||
.pmu_init = exynos5420_pmu_init,
|
||||
.powerdown_conf = exynos5420_powerdown_conf,
|
||||
};
|
||||
|
||||
/*
|
||||
* PMU platform driver and devicetree bindings.
|
||||
*/
|
||||
static const struct of_device_id exynos_pmu_of_device_ids[] = {
|
||||
{
|
||||
.compatible = "samsung,exynos4210-pmu",
|
||||
.data = &exynos4210_pmu_data,
|
||||
}, {
|
||||
.compatible = "samsung,exynos4212-pmu",
|
||||
.data = &exynos4212_pmu_data,
|
||||
}, {
|
||||
.compatible = "samsung,exynos4412-pmu",
|
||||
.data = &exynos4412_pmu_data,
|
||||
}, {
|
||||
.compatible = "samsung,exynos5250-pmu",
|
||||
.data = &exynos5250_pmu_data,
|
||||
}, {
|
||||
.compatible = "samsung,exynos5420-pmu",
|
||||
.data = &exynos5420_pmu_data,
|
||||
},
|
||||
{ /*sentinel*/ },
|
||||
};
|
||||
|
||||
static int exynos_pmu_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct of_device_id *match;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct resource *res;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
pmu_base_addr = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(pmu_base_addr))
|
||||
return PTR_ERR(pmu_base_addr);
|
||||
|
||||
pmu_context = devm_kzalloc(&pdev->dev,
|
||||
sizeof(struct exynos_pmu_context),
|
||||
GFP_KERNEL);
|
||||
if (!pmu_context) {
|
||||
dev_err(dev, "Cannot allocate memory.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
pmu_context->dev = dev;
|
||||
|
||||
match = of_match_node(exynos_pmu_of_device_ids, dev->of_node);
|
||||
|
||||
pmu_context->pmu_data = match->data;
|
||||
|
||||
if (pmu_context->pmu_data->pmu_init)
|
||||
pmu_context->pmu_data->pmu_init();
|
||||
|
||||
platform_set_drvdata(pdev, pmu_context);
|
||||
|
||||
dev_dbg(dev, "Exynos PMU Driver probe done\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver exynos_pmu_driver = {
|
||||
.driver = {
|
||||
.name = "exynos-pmu",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = exynos_pmu_of_device_ids,
|
||||
},
|
||||
.probe = exynos_pmu_probe,
|
||||
};
|
||||
|
||||
static int __init exynos_pmu_init(void)
|
||||
{
|
||||
unsigned int value;
|
||||
return platform_driver_register(&exynos_pmu_driver);
|
||||
|
||||
exynos_pmu_config = exynos4210_pmu_config;
|
||||
|
||||
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.
|
||||
*/
|
||||
value = pmu_raw_readl(EXYNOS5_AUTO_WDTRESET_DISABLE);
|
||||
value &= ~EXYNOS5_SYS_WDTRESET;
|
||||
pmu_raw_writel(value, EXYNOS5_AUTO_WDTRESET_DISABLE);
|
||||
|
||||
value = pmu_raw_readl(EXYNOS5_MASK_WDTRESET_REQUEST);
|
||||
value &= ~EXYNOS5_SYS_WDTRESET;
|
||||
pmu_raw_writel(value, EXYNOS5_MASK_WDTRESET_REQUEST);
|
||||
|
||||
exynos_pmu_config = exynos5250_pmu_config;
|
||||
pr_info("EXYNOS5250 PMU Initialize\n");
|
||||
} else {
|
||||
pr_info("EXYNOS: PMU not supported\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(exynos_pmu_init);
|
||||
postcore_initcall(exynos_pmu_init);
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#define S5P_USE_STANDBY_WFI0 (1 << 16)
|
||||
#define S5P_USE_STANDBY_WFE0 (1 << 24)
|
||||
#define S5P_USE_DELAYED_RESET_ASSERTION BIT(12)
|
||||
|
||||
#define EXYNOS_CORE_PO_RESET(n) ((1 << 4) << n)
|
||||
#define EXYNOS_WAKEUP_FROM_LOWPWR (1 << 28)
|
||||
|
@ -37,6 +38,7 @@
|
|||
#define S5P_INFORM7 0x081C
|
||||
#define S5P_PMU_SPARE3 0x090C
|
||||
|
||||
#define EXYNOS_IROM_DATA2 0x0988
|
||||
#define S5P_ARM_CORE0_LOWPWR 0x1000
|
||||
#define S5P_DIS_IRQ_CORE0 0x1004
|
||||
#define S5P_DIS_IRQ_CENTRAL0 0x1008
|
||||
|
@ -108,6 +110,8 @@
|
|||
(EXYNOS_ARM_CORE0_CONFIGURATION + (0x80 * (_nr)))
|
||||
#define EXYNOS_ARM_CORE_STATUS(_nr) \
|
||||
(EXYNOS_ARM_CORE_CONFIGURATION(_nr) + 0x4)
|
||||
#define EXYNOS_ARM_CORE_OPTION(_nr) \
|
||||
(EXYNOS_ARM_CORE_CONFIGURATION(_nr) + 0x8)
|
||||
|
||||
#define EXYNOS_ARM_COMMON_CONFIGURATION 0x2500
|
||||
#define EXYNOS_COMMON_CONFIGURATION(_nr) \
|
||||
|
@ -117,6 +121,31 @@
|
|||
#define EXYNOS_COMMON_OPTION(_nr) \
|
||||
(EXYNOS_COMMON_CONFIGURATION(_nr) + 0x8)
|
||||
|
||||
#define EXYNOS_CORE_LOCAL_PWR_EN 0x3
|
||||
|
||||
#define EXYNOS_ARM_COMMON_STATUS 0x2504
|
||||
#define EXYNOS_COMMON_OPTION(_nr) \
|
||||
(EXYNOS_COMMON_CONFIGURATION(_nr) + 0x8)
|
||||
|
||||
#define EXYNOS_ARM_L2_CONFIGURATION 0x2600
|
||||
#define EXYNOS_L2_CONFIGURATION(_nr) \
|
||||
(EXYNOS_ARM_L2_CONFIGURATION + ((_nr) * 0x80))
|
||||
#define EXYNOS_L2_STATUS(_nr) \
|
||||
(EXYNOS_L2_CONFIGURATION(_nr) + 0x4)
|
||||
#define EXYNOS_L2_OPTION(_nr) \
|
||||
(EXYNOS_L2_CONFIGURATION(_nr) + 0x8)
|
||||
#define EXYNOS_L2_COMMON_PWR_EN 0x3
|
||||
|
||||
#define EXYNOS_ARM_CORE_X_STATUS_OFFSET 0x4
|
||||
|
||||
#define EXYNOS5_APLL_SYSCLK_CONFIGURATION 0x2A00
|
||||
#define EXYNOS5_APLL_SYSCLK_STATUS 0x2A04
|
||||
|
||||
#define EXYNOS5_ARM_L2_OPTION 0x2608
|
||||
#define EXYNOS5_USE_RETENTION BIT(4)
|
||||
|
||||
#define EXYNOS5_L2RSTDISABLE_VALUE BIT(3)
|
||||
|
||||
#define S5P_PAD_RET_MAUDIO_OPTION 0x3028
|
||||
#define S5P_PAD_RET_GPIO_OPTION 0x3108
|
||||
#define S5P_PAD_RET_UART_OPTION 0x3128
|
||||
|
@ -190,6 +219,7 @@
|
|||
#define EXYNOS5_AUTO_WDTRESET_DISABLE 0x0408
|
||||
#define EXYNOS5_MASK_WDTRESET_REQUEST 0x040C
|
||||
|
||||
#define EXYNOS5_USE_RETENTION BIT(4)
|
||||
#define EXYNOS5_SYS_WDTRESET (1 << 20)
|
||||
|
||||
#define EXYNOS5_ARM_CORE0_SYS_PWR_REG 0x1000
|
||||
|
@ -329,4 +359,204 @@ static inline unsigned int exynos_pmu_cpunr(unsigned int mpidr)
|
|||
+ MPIDR_AFFINITY_LEVEL(mpidr, 0));
|
||||
}
|
||||
|
||||
/* Only for EXYNOS5420 */
|
||||
#define EXYNOS5420_ISP_ARM_OPTION 0x2488
|
||||
#define EXYNOS5420_L2RSTDISABLE_VALUE BIT(3)
|
||||
|
||||
#define EXYNOS5420_LPI_MASK 0x0004
|
||||
#define EXYNOS5420_LPI_MASK1 0x0008
|
||||
#define EXYNOS5420_UFS BIT(8)
|
||||
#define EXYNOS5420_ATB_KFC BIT(13)
|
||||
#define EXYNOS5420_ATB_ISP_ARM BIT(19)
|
||||
#define EXYNOS5420_EMULATION BIT(31)
|
||||
#define ATB_ISP_ARM BIT(12)
|
||||
#define ATB_KFC BIT(13)
|
||||
#define ATB_NOC BIT(14)
|
||||
|
||||
#define EXYNOS5420_ARM_INTR_SPREAD_ENABLE 0x0100
|
||||
#define EXYNOS5420_ARM_INTR_SPREAD_USE_STANDBYWFI 0x0104
|
||||
#define EXYNOS5420_UP_SCHEDULER 0x0120
|
||||
#define SPREAD_ENABLE 0xF
|
||||
#define SPREAD_USE_STANDWFI 0xF
|
||||
|
||||
#define EXYNOS5420_BB_CON1 0x0784
|
||||
#define EXYNOS5420_BB_SEL_EN BIT(31)
|
||||
#define EXYNOS5420_BB_PMOS_EN BIT(7)
|
||||
#define EXYNOS5420_BB_1300X 0XF
|
||||
|
||||
#define EXYNOS5420_ARM_CORE2_SYS_PWR_REG 0x1020
|
||||
#define EXYNOS5420_DIS_IRQ_ARM_CORE2_LOCAL_SYS_PWR_REG 0x1024
|
||||
#define EXYNOS5420_DIS_IRQ_ARM_CORE2_CENTRAL_SYS_PWR_REG 0x1028
|
||||
#define EXYNOS5420_ARM_CORE3_SYS_PWR_REG 0x1030
|
||||
#define EXYNOS5420_DIS_IRQ_ARM_CORE3_LOCAL_SYS_PWR_REG 0x1034
|
||||
#define EXYNOS5420_DIS_IRQ_ARM_CORE3_CENTRAL_SYS_PWR_REG 0x1038
|
||||
#define EXYNOS5420_KFC_CORE0_SYS_PWR_REG 0x1040
|
||||
#define EXYNOS5420_DIS_IRQ_KFC_CORE0_LOCAL_SYS_PWR_REG 0x1044
|
||||
#define EXYNOS5420_DIS_IRQ_KFC_CORE0_CENTRAL_SYS_PWR_REG 0x1048
|
||||
#define EXYNOS5420_KFC_CORE1_SYS_PWR_REG 0x1050
|
||||
#define EXYNOS5420_DIS_IRQ_KFC_CORE1_LOCAL_SYS_PWR_REG 0x1054
|
||||
#define EXYNOS5420_DIS_IRQ_KFC_CORE1_CENTRAL_SYS_PWR_REG 0x1058
|
||||
#define EXYNOS5420_KFC_CORE2_SYS_PWR_REG 0x1060
|
||||
#define EXYNOS5420_DIS_IRQ_KFC_CORE2_LOCAL_SYS_PWR_REG 0x1064
|
||||
#define EXYNOS5420_DIS_IRQ_KFC_CORE2_CENTRAL_SYS_PWR_REG 0x1068
|
||||
#define EXYNOS5420_KFC_CORE3_SYS_PWR_REG 0x1070
|
||||
#define EXYNOS5420_DIS_IRQ_KFC_CORE3_LOCAL_SYS_PWR_REG 0x1074
|
||||
#define EXYNOS5420_DIS_IRQ_KFC_CORE3_CENTRAL_SYS_PWR_REG 0x1078
|
||||
#define EXYNOS5420_ISP_ARM_SYS_PWR_REG 0x1090
|
||||
#define EXYNOS5420_DIS_IRQ_ISP_ARM_LOCAL_SYS_PWR_REG 0x1094
|
||||
#define EXYNOS5420_DIS_IRQ_ISP_ARM_CENTRAL_SYS_PWR_REG 0x1098
|
||||
#define EXYNOS5420_ARM_COMMON_SYS_PWR_REG 0x10A0
|
||||
#define EXYNOS5420_KFC_COMMON_SYS_PWR_REG 0x10B0
|
||||
#define EXYNOS5420_KFC_L2_SYS_PWR_REG 0x10D0
|
||||
#define EXYNOS5420_DPLL_SYSCLK_SYS_PWR_REG 0x1158
|
||||
#define EXYNOS5420_IPLL_SYSCLK_SYS_PWR_REG 0x115C
|
||||
#define EXYNOS5420_KPLL_SYSCLK_SYS_PWR_REG 0x1160
|
||||
#define EXYNOS5420_RPLL_SYSCLK_SYS_PWR_REG 0x1174
|
||||
#define EXYNOS5420_SPLL_SYSCLK_SYS_PWR_REG 0x1178
|
||||
#define EXYNOS5420_INTRAM_MEM_SYS_PWR_REG 0x11B8
|
||||
#define EXYNOS5420_INTROM_MEM_SYS_PWR_REG 0x11BC
|
||||
#define EXYNOS5420_ONENANDXL_MEM_SYS_PWR 0x11C0
|
||||
#define EXYNOS5420_USBDEV_MEM_SYS_PWR 0x11CC
|
||||
#define EXYNOS5420_USBDEV1_MEM_SYS_PWR 0x11D0
|
||||
#define EXYNOS5420_SDMMC_MEM_SYS_PWR 0x11D4
|
||||
#define EXYNOS5420_CSSYS_MEM_SYS_PWR 0x11D8
|
||||
#define EXYNOS5420_SECSS_MEM_SYS_PWR 0x11DC
|
||||
#define EXYNOS5420_ROTATOR_MEM_SYS_PWR 0x11E0
|
||||
#define EXYNOS5420_INTRAM_MEM_SYS_PWR 0x11E4
|
||||
#define EXYNOS5420_INTROM_MEM_SYS_PWR 0x11E8
|
||||
#define EXYNOS5420_PAD_RETENTION_JTAG_SYS_PWR_REG 0x1208
|
||||
#define EXYNOS5420_PAD_RETENTION_DRAM_SYS_PWR_REG 0x1210
|
||||
#define EXYNOS5420_PAD_RETENTION_UART_SYS_PWR_REG 0x1214
|
||||
#define EXYNOS5420_PAD_RETENTION_MMC0_SYS_PWR_REG 0x1218
|
||||
#define EXYNOS5420_PAD_RETENTION_MMC1_SYS_PWR_REG 0x121C
|
||||
#define EXYNOS5420_PAD_RETENTION_MMC2_SYS_PWR_REG 0x1220
|
||||
#define EXYNOS5420_PAD_RETENTION_HSI_SYS_PWR_REG 0x1224
|
||||
#define EXYNOS5420_PAD_RETENTION_EBIA_SYS_PWR_REG 0x1228
|
||||
#define EXYNOS5420_PAD_RETENTION_EBIB_SYS_PWR_REG 0x122C
|
||||
#define EXYNOS5420_PAD_RETENTION_SPI_SYS_PWR_REG 0x1230
|
||||
#define EXYNOS5420_PAD_RETENTION_DRAM_COREBLK_SYS_PWR_REG 0x1234
|
||||
#define EXYNOS5420_DISP1_SYS_PWR_REG 0x1410
|
||||
#define EXYNOS5420_MAU_SYS_PWR_REG 0x1414
|
||||
#define EXYNOS5420_G2D_SYS_PWR_REG 0x1418
|
||||
#define EXYNOS5420_MSC_SYS_PWR_REG 0x141C
|
||||
#define EXYNOS5420_FSYS_SYS_PWR_REG 0x1420
|
||||
#define EXYNOS5420_FSYS2_SYS_PWR_REG 0x1424
|
||||
#define EXYNOS5420_PSGEN_SYS_PWR_REG 0x1428
|
||||
#define EXYNOS5420_PERIC_SYS_PWR_REG 0x142C
|
||||
#define EXYNOS5420_WCORE_SYS_PWR_REG 0x1430
|
||||
#define EXYNOS5420_CMU_CLKSTOP_DISP1_SYS_PWR_REG 0x1490
|
||||
#define EXYNOS5420_CMU_CLKSTOP_MAU_SYS_PWR_REG 0x1494
|
||||
#define EXYNOS5420_CMU_CLKSTOP_G2D_SYS_PWR_REG 0x1498
|
||||
#define EXYNOS5420_CMU_CLKSTOP_MSC_SYS_PWR_REG 0x149C
|
||||
#define EXYNOS5420_CMU_CLKSTOP_FSYS_SYS_PWR_REG 0x14A0
|
||||
#define EXYNOS5420_CMU_CLKSTOP_FSYS2_SYS_PWR_REG 0x14A4
|
||||
#define EXYNOS5420_CMU_CLKSTOP_PSGEN_SYS_PWR_REG 0x14A8
|
||||
#define EXYNOS5420_CMU_CLKSTOP_PERIC_SYS_PWR_REG 0x14AC
|
||||
#define EXYNOS5420_CMU_CLKSTOP_WCORE_SYS_PWR_REG 0x14B0
|
||||
#define EXYNOS5420_CMU_SYSCLK_TOPPWR_SYS_PWR_REG 0x14BC
|
||||
#define EXYNOS5420_CMU_SYSCLK_DISP1_SYS_PWR_REG 0x14D0
|
||||
#define EXYNOS5420_CMU_SYSCLK_MAU_SYS_PWR_REG 0x14D4
|
||||
#define EXYNOS5420_CMU_SYSCLK_G2D_SYS_PWR_REG 0x14D8
|
||||
#define EXYNOS5420_CMU_SYSCLK_MSC_SYS_PWR_REG 0x14DC
|
||||
#define EXYNOS5420_CMU_SYSCLK_FSYS_SYS_PWR_REG 0x14E0
|
||||
#define EXYNOS5420_CMU_SYSCLK_FSYS2_SYS_PWR_REG 0x14E4
|
||||
#define EXYNOS5420_CMU_SYSCLK_PSGEN_SYS_PWR_REG 0x14E8
|
||||
#define EXYNOS5420_CMU_SYSCLK_PERIC_SYS_PWR_REG 0x14EC
|
||||
#define EXYNOS5420_CMU_SYSCLK_WCORE_SYS_PWR_REG 0x14F0
|
||||
#define EXYNOS5420_CMU_SYSCLK_SYSMEM_TOPPWR_SYS_PWR_REG 0x14F4
|
||||
#define EXYNOS5420_CMU_RESET_FSYS2_SYS_PWR_REG 0x1570
|
||||
#define EXYNOS5420_CMU_RESET_PSGEN_SYS_PWR_REG 0x1574
|
||||
#define EXYNOS5420_CMU_RESET_PERIC_SYS_PWR_REG 0x1578
|
||||
#define EXYNOS5420_CMU_RESET_WCORE_SYS_PWR_REG 0x157C
|
||||
#define EXYNOS5420_CMU_RESET_DISP1_SYS_PWR_REG 0x1590
|
||||
#define EXYNOS5420_CMU_RESET_MAU_SYS_PWR_REG 0x1594
|
||||
#define EXYNOS5420_CMU_RESET_G2D_SYS_PWR_REG 0x1598
|
||||
#define EXYNOS5420_CMU_RESET_MSC_SYS_PWR_REG 0x159C
|
||||
#define EXYNOS5420_CMU_RESET_FSYS_SYS_PWR_REG 0x15A0
|
||||
#define EXYNOS5420_SFR_AXI_CGDIS1 0x15E4
|
||||
#define EXYNOS_ARM_CORE2_CONFIGURATION 0x2100
|
||||
#define EXYNOS5420_ARM_CORE2_OPTION 0x2108
|
||||
#define EXYNOS_ARM_CORE3_CONFIGURATION 0x2180
|
||||
#define EXYNOS5420_ARM_CORE3_OPTION 0x2188
|
||||
#define EXYNOS5420_ARM_COMMON_STATUS 0x2504
|
||||
#define EXYNOS5420_ARM_COMMON_OPTION 0x2508
|
||||
#define EXYNOS5420_KFC_COMMON_STATUS 0x2584
|
||||
#define EXYNOS5420_KFC_COMMON_OPTION 0x2588
|
||||
#define EXYNOS5420_LOGIC_RESET_DURATION3 0x2D1C
|
||||
|
||||
#define EXYNOS5420_PAD_RET_GPIO_OPTION 0x30C8
|
||||
#define EXYNOS5420_PAD_RET_UART_OPTION 0x30E8
|
||||
#define EXYNOS5420_PAD_RET_MMCA_OPTION 0x3108
|
||||
#define EXYNOS5420_PAD_RET_MMCB_OPTION 0x3128
|
||||
#define EXYNOS5420_PAD_RET_MMCC_OPTION 0x3148
|
||||
#define EXYNOS5420_PAD_RET_HSI_OPTION 0x3168
|
||||
#define EXYNOS5420_PAD_RET_SPI_OPTION 0x31C8
|
||||
#define EXYNOS5420_PAD_RET_DRAM_COREBLK_OPTION 0x31E8
|
||||
#define EXYNOS_PAD_RET_DRAM_OPTION 0x3008
|
||||
#define EXYNOS_PAD_RET_MAUDIO_OPTION 0x3028
|
||||
#define EXYNOS_PAD_RET_JTAG_OPTION 0x3048
|
||||
#define EXYNOS_PAD_RET_GPIO_OPTION 0x3108
|
||||
#define EXYNOS_PAD_RET_UART_OPTION 0x3128
|
||||
#define EXYNOS_PAD_RET_MMCA_OPTION 0x3148
|
||||
#define EXYNOS_PAD_RET_MMCB_OPTION 0x3168
|
||||
#define EXYNOS_PAD_RET_EBIA_OPTION 0x3188
|
||||
#define EXYNOS_PAD_RET_EBIB_OPTION 0x31A8
|
||||
|
||||
#define EXYNOS_PS_HOLD_CONTROL 0x330C
|
||||
|
||||
/* For SYS_PWR_REG */
|
||||
#define EXYNOS_SYS_PWR_CFG BIT(0)
|
||||
|
||||
#define EXYNOS5420_MFC_CONFIGURATION 0x4060
|
||||
#define EXYNOS5420_MFC_STATUS 0x4064
|
||||
#define EXYNOS5420_MFC_OPTION 0x4068
|
||||
#define EXYNOS5420_G3D_CONFIGURATION 0x4080
|
||||
#define EXYNOS5420_G3D_STATUS 0x4084
|
||||
#define EXYNOS5420_G3D_OPTION 0x4088
|
||||
#define EXYNOS5420_DISP0_CONFIGURATION 0x40A0
|
||||
#define EXYNOS5420_DISP0_STATUS 0x40A4
|
||||
#define EXYNOS5420_DISP0_OPTION 0x40A8
|
||||
#define EXYNOS5420_DISP1_CONFIGURATION 0x40C0
|
||||
#define EXYNOS5420_DISP1_STATUS 0x40C4
|
||||
#define EXYNOS5420_DISP1_OPTION 0x40C8
|
||||
#define EXYNOS5420_MAU_CONFIGURATION 0x40E0
|
||||
#define EXYNOS5420_MAU_STATUS 0x40E4
|
||||
#define EXYNOS5420_MAU_OPTION 0x40E8
|
||||
#define EXYNOS5420_FSYS2_OPTION 0x4168
|
||||
#define EXYNOS5420_PSGEN_OPTION 0x4188
|
||||
|
||||
/* For EXYNOS_CENTRAL_SEQ_OPTION */
|
||||
#define EXYNOS5_USE_STANDBYWFI_ARM_CORE0 BIT(16)
|
||||
#define EXYNOS5_USE_STANDBYWFI_ARM_CORE1 BUT(17)
|
||||
#define EXYNOS5_USE_STANDBYWFE_ARM_CORE0 BIT(24)
|
||||
#define EXYNOS5_USE_STANDBYWFE_ARM_CORE1 BIT(25)
|
||||
|
||||
#define EXYNOS5420_ARM_USE_STANDBY_WFI0 BIT(4)
|
||||
#define EXYNOS5420_ARM_USE_STANDBY_WFI1 BIT(5)
|
||||
#define EXYNOS5420_ARM_USE_STANDBY_WFI2 BIT(6)
|
||||
#define EXYNOS5420_ARM_USE_STANDBY_WFI3 BIT(7)
|
||||
#define EXYNOS5420_KFC_USE_STANDBY_WFI0 BIT(8)
|
||||
#define EXYNOS5420_KFC_USE_STANDBY_WFI1 BIT(9)
|
||||
#define EXYNOS5420_KFC_USE_STANDBY_WFI2 BIT(10)
|
||||
#define EXYNOS5420_KFC_USE_STANDBY_WFI3 BIT(11)
|
||||
#define EXYNOS5420_ARM_USE_STANDBY_WFE0 BIT(16)
|
||||
#define EXYNOS5420_ARM_USE_STANDBY_WFE1 BIT(17)
|
||||
#define EXYNOS5420_ARM_USE_STANDBY_WFE2 BIT(18)
|
||||
#define EXYNOS5420_ARM_USE_STANDBY_WFE3 BIT(19)
|
||||
#define EXYNOS5420_KFC_USE_STANDBY_WFE0 BIT(20)
|
||||
#define EXYNOS5420_KFC_USE_STANDBY_WFE1 BIT(21)
|
||||
#define EXYNOS5420_KFC_USE_STANDBY_WFE2 BIT(22)
|
||||
#define EXYNOS5420_KFC_USE_STANDBY_WFE3 BIT(23)
|
||||
|
||||
#define DUR_WAIT_RESET 0xF
|
||||
|
||||
#define EXYNOS5420_USE_STANDBY_WFI_ALL (EXYNOS5420_ARM_USE_STANDBY_WFI0 \
|
||||
| EXYNOS5420_ARM_USE_STANDBY_WFI1 \
|
||||
| EXYNOS5420_ARM_USE_STANDBY_WFI2 \
|
||||
| EXYNOS5420_ARM_USE_STANDBY_WFI3 \
|
||||
| EXYNOS5420_KFC_USE_STANDBY_WFI0 \
|
||||
| EXYNOS5420_KFC_USE_STANDBY_WFI1 \
|
||||
| EXYNOS5420_KFC_USE_STANDBY_WFI2 \
|
||||
| EXYNOS5420_KFC_USE_STANDBY_WFI3)
|
||||
|
||||
#endif /* __ASM_ARCH_REGS_PMU_H */
|
||||
|
|
|
@ -20,10 +20,12 @@
|
|||
#include <linux/io.h>
|
||||
#include <linux/irqchip/arm-gic.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/hardware/cache-l2x0.h>
|
||||
#include <asm/firmware.h>
|
||||
#include <asm/mcpm.h>
|
||||
#include <asm/smp_scu.h>
|
||||
#include <asm/suspend.h>
|
||||
|
||||
|
@ -33,11 +35,14 @@
|
|||
#include "common.h"
|
||||
#include "regs-pmu.h"
|
||||
#include "regs-sys.h"
|
||||
#include "exynos-pmu.h"
|
||||
|
||||
#define S5P_CHECK_SLEEP 0x00000BAD
|
||||
|
||||
#define REG_TABLE_END (-1U)
|
||||
|
||||
#define EXYNOS5420_CPU_STATE 0x28
|
||||
|
||||
/**
|
||||
* struct exynos_wkup_irq - Exynos GIC to PMU IRQ mapping
|
||||
* @hwirq: Hardware IRQ signal of the GIC
|
||||
|
@ -69,6 +74,7 @@ struct exynos_pm_data {
|
|||
unsigned int *release_ret_regs;
|
||||
|
||||
void (*pm_prepare)(void);
|
||||
void (*pm_resume_prepare)(void);
|
||||
void (*pm_resume)(void);
|
||||
int (*pm_suspend)(void);
|
||||
int (*cpu_suspend)(unsigned long);
|
||||
|
@ -76,6 +82,9 @@ struct exynos_pm_data {
|
|||
|
||||
struct exynos_pm_data *pm_data;
|
||||
|
||||
static int exynos5420_cpu_state;
|
||||
static unsigned int exynos_pmu_spare3;
|
||||
|
||||
/*
|
||||
* GIC wake-up support
|
||||
*/
|
||||
|
@ -105,6 +114,23 @@ unsigned int exynos_release_ret_regs[] = {
|
|||
REG_TABLE_END,
|
||||
};
|
||||
|
||||
unsigned int exynos5420_release_ret_regs[] = {
|
||||
EXYNOS_PAD_RET_DRAM_OPTION,
|
||||
EXYNOS_PAD_RET_MAUDIO_OPTION,
|
||||
EXYNOS_PAD_RET_JTAG_OPTION,
|
||||
EXYNOS5420_PAD_RET_GPIO_OPTION,
|
||||
EXYNOS5420_PAD_RET_UART_OPTION,
|
||||
EXYNOS5420_PAD_RET_MMCA_OPTION,
|
||||
EXYNOS5420_PAD_RET_MMCB_OPTION,
|
||||
EXYNOS5420_PAD_RET_MMCC_OPTION,
|
||||
EXYNOS5420_PAD_RET_HSI_OPTION,
|
||||
EXYNOS_PAD_RET_EBIA_OPTION,
|
||||
EXYNOS_PAD_RET_EBIB_OPTION,
|
||||
EXYNOS5420_PAD_RET_SPI_OPTION,
|
||||
EXYNOS5420_PAD_RET_DRAM_COREBLK_OPTION,
|
||||
REG_TABLE_END,
|
||||
};
|
||||
|
||||
static int exynos_irq_set_wake(struct irq_data *data, unsigned int state)
|
||||
{
|
||||
const struct exynos_wkup_irq *wkup_irq;
|
||||
|
@ -135,14 +161,44 @@ static int exynos_cpu_do_idle(void)
|
|||
pr_info("Failed to suspend the system\n");
|
||||
return 1; /* Aborting suspend */
|
||||
}
|
||||
|
||||
static int exynos_cpu_suspend(unsigned long arg)
|
||||
static void exynos_flush_cache_all(void)
|
||||
{
|
||||
flush_cache_all();
|
||||
outer_flush_all();
|
||||
}
|
||||
|
||||
static int exynos_cpu_suspend(unsigned long arg)
|
||||
{
|
||||
exynos_flush_cache_all();
|
||||
return exynos_cpu_do_idle();
|
||||
}
|
||||
|
||||
static int exynos5420_cpu_suspend(unsigned long arg)
|
||||
{
|
||||
/* MCPM works with HW CPU identifiers */
|
||||
unsigned int mpidr = read_cpuid_mpidr();
|
||||
unsigned int cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
|
||||
unsigned int cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
|
||||
|
||||
__raw_writel(0x0, sysram_base_addr + EXYNOS5420_CPU_STATE);
|
||||
|
||||
if (IS_ENABLED(CONFIG_EXYNOS5420_MCPM)) {
|
||||
mcpm_set_entry_vector(cpu, cluster, exynos_cpu_resume);
|
||||
|
||||
/*
|
||||
* Residency value passed to mcpm_cpu_suspend back-end
|
||||
* has to be given clear semantics. Set to 0 as a
|
||||
* temporary value.
|
||||
*/
|
||||
mcpm_cpu_suspend(0);
|
||||
}
|
||||
|
||||
pr_info("Failed to suspend the system\n");
|
||||
|
||||
/* return value != 0 means failure */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void exynos_pm_set_wakeup_mask(void)
|
||||
{
|
||||
/* Set wake-up mask registers */
|
||||
|
@ -155,9 +211,6 @@ static void exynos_pm_enter_sleep_mode(void)
|
|||
/* Set value of power down register for sleep mode */
|
||||
exynos_sys_powerdown_conf(SYS_SLEEP);
|
||||
pmu_raw_writel(S5P_CHECK_SLEEP, S5P_INFORM1);
|
||||
|
||||
/* ensure at least INFORM0 has the resume address */
|
||||
pmu_raw_writel(virt_to_phys(exynos_cpu_resume), S5P_INFORM0);
|
||||
}
|
||||
|
||||
static void exynos_pm_prepare(void)
|
||||
|
@ -172,8 +225,59 @@ static void exynos_pm_prepare(void)
|
|||
pm_data->num_extra_save);
|
||||
|
||||
exynos_pm_enter_sleep_mode();
|
||||
|
||||
/* ensure at least INFORM0 has the resume address */
|
||||
pmu_raw_writel(virt_to_phys(exynos_cpu_resume), S5P_INFORM0);
|
||||
}
|
||||
|
||||
static void exynos5420_pm_prepare(void)
|
||||
{
|
||||
unsigned int tmp;
|
||||
|
||||
/* Set wake-up mask registers */
|
||||
exynos_pm_set_wakeup_mask();
|
||||
|
||||
s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save));
|
||||
|
||||
exynos_pmu_spare3 = pmu_raw_readl(S5P_PMU_SPARE3);
|
||||
/*
|
||||
* The cpu state needs to be saved and restored so that the
|
||||
* secondary CPUs will enter low power start. Though the U-Boot
|
||||
* is setting the cpu state with low power flag, the kernel
|
||||
* needs to restore it back in case, the primary cpu fails to
|
||||
* suspend for any reason.
|
||||
*/
|
||||
exynos5420_cpu_state = __raw_readl(sysram_base_addr +
|
||||
EXYNOS5420_CPU_STATE);
|
||||
|
||||
exynos_pm_enter_sleep_mode();
|
||||
|
||||
/* ensure at least INFORM0 has the resume address */
|
||||
if (IS_ENABLED(CONFIG_EXYNOS5420_MCPM))
|
||||
pmu_raw_writel(virt_to_phys(mcpm_entry_point), S5P_INFORM0);
|
||||
|
||||
tmp = pmu_raw_readl(EXYNOS5_ARM_L2_OPTION);
|
||||
tmp &= ~EXYNOS5_USE_RETENTION;
|
||||
pmu_raw_writel(tmp, EXYNOS5_ARM_L2_OPTION);
|
||||
|
||||
tmp = pmu_raw_readl(EXYNOS5420_SFR_AXI_CGDIS1);
|
||||
tmp |= EXYNOS5420_UFS;
|
||||
pmu_raw_writel(tmp, EXYNOS5420_SFR_AXI_CGDIS1);
|
||||
|
||||
tmp = pmu_raw_readl(EXYNOS5420_ARM_COMMON_OPTION);
|
||||
tmp &= ~EXYNOS5420_L2RSTDISABLE_VALUE;
|
||||
pmu_raw_writel(tmp, EXYNOS5420_ARM_COMMON_OPTION);
|
||||
|
||||
tmp = pmu_raw_readl(EXYNOS5420_FSYS2_OPTION);
|
||||
tmp |= EXYNOS5420_EMULATION;
|
||||
pmu_raw_writel(tmp, EXYNOS5420_FSYS2_OPTION);
|
||||
|
||||
tmp = pmu_raw_readl(EXYNOS5420_PSGEN_OPTION);
|
||||
tmp |= EXYNOS5420_EMULATION;
|
||||
pmu_raw_writel(tmp, EXYNOS5420_PSGEN_OPTION);
|
||||
}
|
||||
|
||||
|
||||
static int exynos_pm_suspend(void)
|
||||
{
|
||||
exynos_pm_central_suspend();
|
||||
|
@ -184,6 +288,24 @@ static int exynos_pm_suspend(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int exynos5420_pm_suspend(void)
|
||||
{
|
||||
u32 this_cluster;
|
||||
|
||||
exynos_pm_central_suspend();
|
||||
|
||||
/* Setting SEQ_OPTION register */
|
||||
|
||||
this_cluster = MPIDR_AFFINITY_LEVEL(read_cpuid_mpidr(), 1);
|
||||
if (!this_cluster)
|
||||
pmu_raw_writel(EXYNOS5420_ARM_USE_STANDBY_WFI0,
|
||||
S5P_CENTRAL_SEQ_OPTION);
|
||||
else
|
||||
pmu_raw_writel(EXYNOS5420_KFC_USE_STANDBY_WFI0,
|
||||
S5P_CENTRAL_SEQ_OPTION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void exynos_pm_release_retention(void)
|
||||
{
|
||||
unsigned int i;
|
||||
|
@ -222,6 +344,56 @@ early_wakeup:
|
|||
pmu_raw_writel(0x0, S5P_INFORM1);
|
||||
}
|
||||
|
||||
static void exynos5420_prepare_pm_resume(void)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_EXYNOS5420_MCPM))
|
||||
WARN_ON(mcpm_cpu_powered_up());
|
||||
}
|
||||
|
||||
static void exynos5420_pm_resume(void)
|
||||
{
|
||||
unsigned long tmp;
|
||||
|
||||
/* Restore the CPU0 low power state register */
|
||||
tmp = pmu_raw_readl(EXYNOS5_ARM_CORE0_SYS_PWR_REG);
|
||||
pmu_raw_writel(tmp | S5P_CORE_LOCAL_PWR_EN,
|
||||
EXYNOS5_ARM_CORE0_SYS_PWR_REG);
|
||||
|
||||
/* Restore the sysram cpu state register */
|
||||
__raw_writel(exynos5420_cpu_state,
|
||||
sysram_base_addr + EXYNOS5420_CPU_STATE);
|
||||
|
||||
pmu_raw_writel(EXYNOS5420_USE_STANDBY_WFI_ALL,
|
||||
S5P_CENTRAL_SEQ_OPTION);
|
||||
|
||||
if (exynos_pm_central_resume())
|
||||
goto early_wakeup;
|
||||
|
||||
/* For release retention */
|
||||
exynos_pm_release_retention();
|
||||
|
||||
pmu_raw_writel(exynos_pmu_spare3, S5P_PMU_SPARE3);
|
||||
|
||||
s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save));
|
||||
|
||||
early_wakeup:
|
||||
|
||||
tmp = pmu_raw_readl(EXYNOS5420_SFR_AXI_CGDIS1);
|
||||
tmp &= ~EXYNOS5420_UFS;
|
||||
pmu_raw_writel(tmp, EXYNOS5420_SFR_AXI_CGDIS1);
|
||||
|
||||
tmp = pmu_raw_readl(EXYNOS5420_FSYS2_OPTION);
|
||||
tmp &= ~EXYNOS5420_EMULATION;
|
||||
pmu_raw_writel(tmp, EXYNOS5420_FSYS2_OPTION);
|
||||
|
||||
tmp = pmu_raw_readl(EXYNOS5420_PSGEN_OPTION);
|
||||
tmp &= ~EXYNOS5420_EMULATION;
|
||||
pmu_raw_writel(tmp, EXYNOS5420_PSGEN_OPTION);
|
||||
|
||||
/* Clear SLEEP mode set in INFORM1 */
|
||||
pmu_raw_writel(0x0, S5P_INFORM1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Suspend Ops
|
||||
*/
|
||||
|
@ -256,6 +428,8 @@ static int exynos_suspend_enter(suspend_state_t state)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (pm_data->pm_resume_prepare)
|
||||
pm_data->pm_resume_prepare();
|
||||
s3c_pm_restore_uarts();
|
||||
|
||||
S3C_PMDBG("%s: wakeup stat: %08x\n", __func__,
|
||||
|
@ -270,6 +444,22 @@ static int exynos_suspend_enter(suspend_state_t state)
|
|||
|
||||
static int exynos_suspend_prepare(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* REVISIT: It would be better if struct platform_suspend_ops
|
||||
* .prepare handler get the suspend_state_t as a parameter to
|
||||
* avoid hard-coding the suspend to mem state. It's safe to do
|
||||
* it now only because the suspend_valid_only_mem function is
|
||||
* used as the .valid callback used to check if a given state
|
||||
* is supported by the platform anyways.
|
||||
*/
|
||||
ret = regulator_suspend_prepare(PM_SUSPEND_MEM);
|
||||
if (ret) {
|
||||
pr_err("Failed to prepare regulators for suspend (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
s3c_pm_check_prepare();
|
||||
|
||||
return 0;
|
||||
|
@ -277,7 +467,13 @@ static int exynos_suspend_prepare(void)
|
|||
|
||||
static void exynos_suspend_finish(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
s3c_pm_check_cleanup();
|
||||
|
||||
ret = regulator_suspend_finish();
|
||||
if (ret)
|
||||
pr_warn("Failed to resume regulators from suspend (%d)\n", ret);
|
||||
}
|
||||
|
||||
static const struct platform_suspend_ops exynos_suspend_ops = {
|
||||
|
@ -309,6 +505,17 @@ static const struct exynos_pm_data exynos5250_pm_data = {
|
|||
.cpu_suspend = exynos_cpu_suspend,
|
||||
};
|
||||
|
||||
static struct exynos_pm_data exynos5420_pm_data = {
|
||||
.wkup_irq = exynos5250_wkup_irq,
|
||||
.wake_disable_mask = (0x7F << 7) | (0x1F << 1),
|
||||
.release_ret_regs = exynos5420_release_ret_regs,
|
||||
.pm_resume_prepare = exynos5420_prepare_pm_resume,
|
||||
.pm_resume = exynos5420_pm_resume,
|
||||
.pm_suspend = exynos5420_pm_suspend,
|
||||
.pm_prepare = exynos5420_pm_prepare,
|
||||
.cpu_suspend = exynos5420_cpu_suspend,
|
||||
};
|
||||
|
||||
static struct of_device_id exynos_pmu_of_device_ids[] = {
|
||||
{
|
||||
.compatible = "samsung,exynos4210-pmu",
|
||||
|
@ -322,6 +529,9 @@ static struct of_device_id exynos_pmu_of_device_ids[] = {
|
|||
}, {
|
||||
.compatible = "samsung,exynos5250-pmu",
|
||||
.data = &exynos5250_pm_data,
|
||||
}, {
|
||||
.compatible = "samsung,exynos5420-pmu",
|
||||
.data = &exynos5420_pm_data,
|
||||
},
|
||||
{ /*sentinel*/ },
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue