mirror of
https://github.com/AetherDroid/android_kernel_samsung_on5xelte.git
synced 2025-09-09 01:28:05 -04:00
Fixed MTP to work with TWRP
This commit is contained in:
commit
f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions
126
arch/arm/mach-exynos/Kconfig
Normal file
126
arch/arm/mach-exynos/Kconfig
Normal file
|
@ -0,0 +1,126 @@
|
|||
# arch/arm/mach-exynos/Kconfig
|
||||
#
|
||||
# Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
|
||||
# http://www.samsung.com/
|
||||
#
|
||||
# Licensed under GPLv2
|
||||
|
||||
# Configuration options for the EXYNOS4
|
||||
|
||||
menuconfig ARCH_EXYNOS
|
||||
bool "Samsung EXYNOS" if ARCH_MULTI_V7
|
||||
select ARCH_HAS_BANDGAP
|
||||
select ARCH_HAS_HOLES_MEMORYMODEL
|
||||
select ARCH_REQUIRE_GPIOLIB
|
||||
select ARM_AMBA
|
||||
select ARM_GIC
|
||||
select COMMON_CLK_SAMSUNG
|
||||
select HAVE_ARM_SCU if SMP
|
||||
select HAVE_S3C2410_I2C if I2C
|
||||
select HAVE_S3C2410_WATCHDOG if WATCHDOG
|
||||
select HAVE_S3C_RTC if RTC_CLASS
|
||||
select PINCTRL
|
||||
select PINCTRL_EXYNOS
|
||||
select PM_GENERIC_DOMAINS if PM_RUNTIME
|
||||
select S5P_DEV_MFC
|
||||
select SRAM
|
||||
help
|
||||
Support for SAMSUNG EXYNOS SoCs (EXYNOS4/5)
|
||||
|
||||
if ARCH_EXYNOS
|
||||
|
||||
config ARCH_EXYNOS3
|
||||
bool "SAMSUNG EXYNOS3"
|
||||
select ARM_CPU_SUSPEND if PM
|
||||
help
|
||||
Samsung EXYNOS3 (Crotex-A7) SoC based systems
|
||||
|
||||
config ARCH_EXYNOS4
|
||||
bool "SAMSUNG EXYNOS4"
|
||||
default y
|
||||
select ARM_CPU_SUSPEND if PM_SLEEP
|
||||
select CLKSRC_SAMSUNG_PWM if CPU_EXYNOS4210
|
||||
select CPU_EXYNOS4210
|
||||
select GIC_NON_BANKED
|
||||
select KEYBOARD_SAMSUNG if INPUT_KEYBOARD
|
||||
select MIGHT_HAVE_CACHE_L2X0
|
||||
help
|
||||
Samsung EXYNOS4 (Cortex-A9) SoC based systems
|
||||
|
||||
config ARCH_EXYNOS5
|
||||
bool "SAMSUNG EXYNOS5"
|
||||
default y
|
||||
help
|
||||
Samsung EXYNOS5 (Cortex-A15/A7) SoC based systems
|
||||
|
||||
comment "EXYNOS SoCs"
|
||||
|
||||
config SOC_EXYNOS3250
|
||||
bool "SAMSUNG EXYNOS3250"
|
||||
default y
|
||||
depends on ARCH_EXYNOS3
|
||||
|
||||
config CPU_EXYNOS4210
|
||||
bool "SAMSUNG EXYNOS4210"
|
||||
default y
|
||||
depends on ARCH_EXYNOS4
|
||||
|
||||
config SOC_EXYNOS4212
|
||||
bool "SAMSUNG EXYNOS4212"
|
||||
default y
|
||||
depends on ARCH_EXYNOS4
|
||||
|
||||
config SOC_EXYNOS4412
|
||||
bool "SAMSUNG EXYNOS4412"
|
||||
default y
|
||||
depends on ARCH_EXYNOS4
|
||||
|
||||
config SOC_EXYNOS5250
|
||||
bool "SAMSUNG EXYNOS5250"
|
||||
default y
|
||||
depends on ARCH_EXYNOS5
|
||||
|
||||
config SOC_EXYNOS5260
|
||||
bool "SAMSUNG EXYNOS5260"
|
||||
default y
|
||||
depends on ARCH_EXYNOS5
|
||||
|
||||
config SOC_EXYNOS5410
|
||||
bool "SAMSUNG EXYNOS5410"
|
||||
default y
|
||||
depends on ARCH_EXYNOS5
|
||||
|
||||
config SOC_EXYNOS5420
|
||||
bool "SAMSUNG EXYNOS5420"
|
||||
default y
|
||||
depends on ARCH_EXYNOS5
|
||||
|
||||
config SOC_EXYNOS5440
|
||||
bool "SAMSUNG EXYNOS5440"
|
||||
default y
|
||||
depends on ARCH_EXYNOS5
|
||||
select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
|
||||
select HAVE_ARM_ARCH_TIMER
|
||||
select AUTO_ZRELADDR
|
||||
select MIGHT_HAVE_PCI
|
||||
select PCI_DOMAINS if PCI
|
||||
select PINCTRL_EXYNOS5440
|
||||
select PM_OPP
|
||||
help
|
||||
Enable EXYNOS5440 SoC support
|
||||
|
||||
config SOC_EXYNOS5800
|
||||
bool "SAMSUNG EXYNOS5800"
|
||||
default y
|
||||
depends on SOC_EXYNOS5420
|
||||
|
||||
config EXYNOS5420_MCPM
|
||||
bool "Exynos5420 Multi-Cluster PM support"
|
||||
depends on MCPM && SOC_EXYNOS5420
|
||||
select ARM_CCI
|
||||
select ARM_CPU_SUSPEND
|
||||
help
|
||||
This is needed to provide CPU and cluster power management
|
||||
on Exynos5420 implementing big.LITTLE.
|
||||
|
||||
endif
|
26
arch/arm/mach-exynos/Makefile
Normal file
26
arch/arm/mach-exynos/Makefile
Normal file
|
@ -0,0 +1,26 @@
|
|||
# arch/arm/mach-exynos/Makefile
|
||||
#
|
||||
# Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
|
||||
# http://www.samsung.com/
|
||||
#
|
||||
# Licensed under GPLv2
|
||||
|
||||
ccflags-$(CONFIG_ARCH_MULTIPLATFORM) += -I$(srctree)/$(src)/include -I$(srctree)/arch/arm/plat-samsung/include
|
||||
|
||||
# Core
|
||||
|
||||
obj-$(CONFIG_ARCH_EXYNOS) += exynos.o pmu.o exynos-smc.o firmware.o
|
||||
|
||||
obj-$(CONFIG_PM_SLEEP) += pm.o sleep.o
|
||||
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)
|
||||
|
||||
obj-$(CONFIG_EXYNOS5420_MCPM) += mcpm-exynos.o
|
||||
CFLAGS_mcpm-exynos.o += -march=armv7-a
|
2
arch/arm/mach-exynos/Makefile.boot
Normal file
2
arch/arm/mach-exynos/Makefile.boot
Normal file
|
@ -0,0 +1,2 @@
|
|||
zreladdr-y += 0x40008000
|
||||
params_phys-y := 0x40000100
|
173
arch/arm/mach-exynos/common.h
Normal file
173
arch/arm/mach-exynos/common.h
Normal file
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* Common Header for EXYNOS machines
|
||||
*
|
||||
* 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 __ARCH_ARM_MACH_EXYNOS_COMMON_H
|
||||
#define __ARCH_ARM_MACH_EXYNOS_COMMON_H
|
||||
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#define EXYNOS3250_SOC_ID 0xE3472000
|
||||
#define EXYNOS3_SOC_MASK 0xFFFFF000
|
||||
|
||||
#define EXYNOS4210_CPU_ID 0x43210000
|
||||
#define EXYNOS4212_CPU_ID 0x43220000
|
||||
#define EXYNOS4412_CPU_ID 0xE4412200
|
||||
#define EXYNOS4_CPU_MASK 0xFFFE0000
|
||||
|
||||
#define EXYNOS5250_SOC_ID 0x43520000
|
||||
#define EXYNOS5410_SOC_ID 0xE5410000
|
||||
#define EXYNOS5420_SOC_ID 0xE5420000
|
||||
#define EXYNOS5440_SOC_ID 0xE5440000
|
||||
#define EXYNOS5800_SOC_ID 0xE5422000
|
||||
#define EXYNOS5_SOC_MASK 0xFFFFF000
|
||||
|
||||
extern unsigned long samsung_cpu_id;
|
||||
|
||||
#define IS_SAMSUNG_CPU(name, id, mask) \
|
||||
static inline int is_samsung_##name(void) \
|
||||
{ \
|
||||
return ((samsung_cpu_id & mask) == (id & mask)); \
|
||||
}
|
||||
|
||||
IS_SAMSUNG_CPU(exynos3250, EXYNOS3250_SOC_ID, EXYNOS3_SOC_MASK)
|
||||
IS_SAMSUNG_CPU(exynos4210, EXYNOS4210_CPU_ID, EXYNOS4_CPU_MASK)
|
||||
IS_SAMSUNG_CPU(exynos4212, EXYNOS4212_CPU_ID, EXYNOS4_CPU_MASK)
|
||||
IS_SAMSUNG_CPU(exynos4412, EXYNOS4412_CPU_ID, EXYNOS4_CPU_MASK)
|
||||
IS_SAMSUNG_CPU(exynos5250, EXYNOS5250_SOC_ID, EXYNOS5_SOC_MASK)
|
||||
IS_SAMSUNG_CPU(exynos5410, EXYNOS5410_SOC_ID, EXYNOS5_SOC_MASK)
|
||||
IS_SAMSUNG_CPU(exynos5420, EXYNOS5420_SOC_ID, EXYNOS5_SOC_MASK)
|
||||
IS_SAMSUNG_CPU(exynos5440, EXYNOS5440_SOC_ID, EXYNOS5_SOC_MASK)
|
||||
IS_SAMSUNG_CPU(exynos5800, EXYNOS5800_SOC_ID, EXYNOS5_SOC_MASK)
|
||||
|
||||
#if defined(CONFIG_SOC_EXYNOS3250)
|
||||
# define soc_is_exynos3250() is_samsung_exynos3250()
|
||||
#else
|
||||
# define soc_is_exynos3250() 0
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CPU_EXYNOS4210)
|
||||
# define soc_is_exynos4210() is_samsung_exynos4210()
|
||||
#else
|
||||
# define soc_is_exynos4210() 0
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SOC_EXYNOS4212)
|
||||
# define soc_is_exynos4212() is_samsung_exynos4212()
|
||||
#else
|
||||
# define soc_is_exynos4212() 0
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SOC_EXYNOS4412)
|
||||
# define soc_is_exynos4412() is_samsung_exynos4412()
|
||||
#else
|
||||
# define soc_is_exynos4412() 0
|
||||
#endif
|
||||
|
||||
#define EXYNOS4210_REV_0 (0x0)
|
||||
#define EXYNOS4210_REV_1_0 (0x10)
|
||||
#define EXYNOS4210_REV_1_1 (0x11)
|
||||
|
||||
#if defined(CONFIG_SOC_EXYNOS5250)
|
||||
# define soc_is_exynos5250() is_samsung_exynos5250()
|
||||
#else
|
||||
# define soc_is_exynos5250() 0
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SOC_EXYNOS5410)
|
||||
# define soc_is_exynos5410() is_samsung_exynos5410()
|
||||
#else
|
||||
# define soc_is_exynos5410() 0
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SOC_EXYNOS5420)
|
||||
# define soc_is_exynos5420() is_samsung_exynos5420()
|
||||
#else
|
||||
# define soc_is_exynos5420() 0
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SOC_EXYNOS5440)
|
||||
# define soc_is_exynos5440() is_samsung_exynos5440()
|
||||
#else
|
||||
# define soc_is_exynos5440() 0
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SOC_EXYNOS5800)
|
||||
# define soc_is_exynos5800() is_samsung_exynos5800()
|
||||
#else
|
||||
# define soc_is_exynos5800() 0
|
||||
#endif
|
||||
|
||||
#define soc_is_exynos4() (soc_is_exynos4210() || soc_is_exynos4212() || \
|
||||
soc_is_exynos4412())
|
||||
#define soc_is_exynos5() (soc_is_exynos5250() || soc_is_exynos5410() || \
|
||||
soc_is_exynos5420() || soc_is_exynos5800())
|
||||
|
||||
extern void __iomem *sysram_ns_base_addr;
|
||||
extern void __iomem *sysram_base_addr;
|
||||
extern void __iomem *pmu_base_addr;
|
||||
void exynos_sysram_init(void);
|
||||
|
||||
void exynos_firmware_init(void);
|
||||
|
||||
extern u32 exynos_get_eint_wake_mask(void);
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
extern void __init exynos_pm_init(void);
|
||||
#else
|
||||
static inline void exynos_pm_init(void) {}
|
||||
#endif
|
||||
|
||||
extern void exynos_cpu_resume(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);
|
||||
extern void exynos_cluster_power_down(int cluster);
|
||||
extern void exynos_cluster_power_up(int cluster);
|
||||
extern int exynos_cluster_power_state(int cluster);
|
||||
extern void exynos_enter_aftr(void);
|
||||
|
||||
extern void s5p_init_cpu(void __iomem *cpuid_addr);
|
||||
extern unsigned int samsung_rev(void);
|
||||
|
||||
static inline void pmu_raw_writel(u32 val, u32 offset)
|
||||
{
|
||||
__raw_writel(val, pmu_base_addr + offset);
|
||||
}
|
||||
|
||||
static inline u32 pmu_raw_readl(u32 offset)
|
||||
{
|
||||
return __raw_readl(pmu_base_addr + offset);
|
||||
}
|
||||
|
||||
#endif /* __ARCH_ARM_MACH_EXYNOS_COMMON_H */
|
215
arch/arm/mach-exynos/core_sysfs.c
Normal file
215
arch/arm/mach-exynos/core_sysfs.c
Normal file
|
@ -0,0 +1,215 @@
|
|||
/*
|
||||
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* EXYNOS - support to view information of big.LITTLE switcher
|
||||
*
|
||||
* 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/device.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/moduleparam.h>
|
||||
|
||||
#include <asm/cputype.h>
|
||||
#include <asm/smp_plat.h>
|
||||
|
||||
#include <mach/regs-pmu.h>
|
||||
|
||||
static struct bus_type core_subsys = {
|
||||
.name = "b.L",
|
||||
.dev_name = "b.L",
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SCHED_HMP
|
||||
extern struct cpumask hmp_fast_cpu_mask;
|
||||
extern struct cpumask hmp_slow_cpu_mask;
|
||||
#endif
|
||||
|
||||
static unsigned int cpu_state(unsigned int cpu)
|
||||
{
|
||||
unsigned int state, offset;
|
||||
#ifdef CONFIG_SCHED_HMP
|
||||
unsigned int cluster, core;
|
||||
core = MPIDR_AFFINITY_LEVEL(cpu_logical_map(cpu), 0);
|
||||
cluster = MPIDR_AFFINITY_LEVEL(cpu_logical_map(cpu), 1);
|
||||
offset = (cluster << 2) + core;
|
||||
#else
|
||||
offset = cpu;
|
||||
#endif
|
||||
|
||||
state = __raw_readl(EXYNOS_ARM_CORE_STATUS(offset));
|
||||
|
||||
return (state & 0xf) != 0;
|
||||
}
|
||||
|
||||
static ssize_t exynos5_core_status_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
ssize_t n = 0;
|
||||
int cpu;
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
unsigned int v = cpu_state(cpu);
|
||||
n += scnprintf(buf + n, 11, "cpu %d : %d\n", cpu, v);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SCHED_HMP
|
||||
static ssize_t exynos5_boot_cluster_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
ssize_t n = 0;
|
||||
|
||||
n += scnprintf(buf + n, 20, "boot_cluster : %d\n",
|
||||
MPIDR_AFFINITY_LEVEL(cpu_logical_map(0), 1));
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static ssize_t exynos5_big_threads_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
ssize_t n = 0;
|
||||
int cpu;
|
||||
unsigned long nr_running = 0;
|
||||
|
||||
for_each_cpu_mask(cpu, hmp_fast_cpu_mask)
|
||||
nr_running += nr_running_cpu(cpu);
|
||||
|
||||
n += scnprintf(buf + n, 20, "%ld\n", nr_running);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static ssize_t exynos5_little_threads_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
ssize_t n = 0;
|
||||
int cpu;
|
||||
unsigned long nr_running = 0;
|
||||
|
||||
for_each_cpu_mask(cpu, hmp_slow_cpu_mask)
|
||||
nr_running += nr_running_cpu(cpu);
|
||||
|
||||
n += scnprintf(buf + n, 20, "%ld\n", nr_running);
|
||||
|
||||
return n;
|
||||
|
||||
}
|
||||
|
||||
static unsigned long long up_migrations, down_migrations;
|
||||
|
||||
static ssize_t exynos5_up_migrations_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
ssize_t n = 0;
|
||||
|
||||
n += scnprintf(buf + n, 20, "%lld\n", up_migrations);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static ssize_t exynos5_down_migrations_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
ssize_t n = 0;
|
||||
|
||||
n += scnprintf(buf + n, 20, "%lld\n", down_migrations);
|
||||
|
||||
return n;
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct kobj_attribute exynos5_core_status_attr =
|
||||
__ATTR(core_status, 0644, exynos5_core_status_show, NULL);
|
||||
#ifdef CONFIG_SCHED_HMP
|
||||
static struct kobj_attribute exynos5_boot_cluster_attr =
|
||||
__ATTR(boot_cluster, 0644, exynos5_boot_cluster_show, NULL);
|
||||
static struct kobj_attribute exynos5_big_threads_attr =
|
||||
__ATTR(big_threads, 0644, exynos5_big_threads_show, NULL);
|
||||
static struct kobj_attribute exynos5_little_threads_attr =
|
||||
__ATTR(little_threads, 0644, exynos5_little_threads_show, NULL);
|
||||
static struct kobj_attribute exynos5_up_migrations_attr =
|
||||
__ATTR(up_migrations, 0644, exynos5_up_migrations_show, NULL);
|
||||
static struct kobj_attribute exynos5_down_migrations_attr =
|
||||
__ATTR(down_migrations, 0644, exynos5_down_migrations_show, NULL);
|
||||
#endif
|
||||
|
||||
static struct attribute *exynos5_core_sysfs_attrs[] = {
|
||||
&exynos5_core_status_attr.attr,
|
||||
#ifdef CONFIG_SCHED_HMP
|
||||
&exynos5_boot_cluster_attr.attr,
|
||||
&exynos5_big_threads_attr.attr,
|
||||
&exynos5_little_threads_attr.attr,
|
||||
&exynos5_up_migrations_attr.attr,
|
||||
&exynos5_down_migrations_attr.attr,
|
||||
#endif
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct attribute_group exynos5_core_sysfs_group = {
|
||||
.attrs = exynos5_core_sysfs_attrs,
|
||||
};
|
||||
|
||||
static const struct attribute_group *exynos5_core_sysfs_groups[] = {
|
||||
&exynos5_core_sysfs_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static int __init exynos5_core_sysfs_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = subsys_system_register(&core_subsys, exynos5_core_sysfs_groups);
|
||||
if (ret)
|
||||
pr_err("Fail to register exynos5 core subsys\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
late_initcall(exynos5_core_sysfs_init);
|
||||
|
||||
#ifdef CONFIG_SCHED_HMP
|
||||
static int hmp_migration_notifier_handler(struct notifier_block *nb,
|
||||
unsigned long cmd, void *data)
|
||||
{
|
||||
switch (cmd) {
|
||||
case HMP_UP_MIGRATION:
|
||||
up_migrations++;
|
||||
break;
|
||||
case HMP_DOWN_MIGRATION:
|
||||
down_migrations++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct notifier_block hmp_nb = {
|
||||
.notifier_call = hmp_migration_notifier_handler,
|
||||
};
|
||||
|
||||
static int __init exynos5_core_info_early_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = register_hmp_task_migration_notifier(&hmp_nb);
|
||||
if (ret)
|
||||
pr_err("Fail to register hmp notification\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
early_initcall(exynos5_core_info_early_init);
|
||||
#endif
|
22
arch/arm/mach-exynos/exynos-smc.S
Normal file
22
arch/arm/mach-exynos/exynos-smc.S
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Samsung Electronics.
|
||||
*
|
||||
* Copied from omap-smc.S Copyright (C) 2010 Texas Instruments, Inc.
|
||||
*
|
||||
* 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/linkage.h>
|
||||
|
||||
/*
|
||||
* Function signature: void exynos_smc(u32 cmd, u32 arg1, u32 arg2, u32 arg3)
|
||||
*/
|
||||
|
||||
ENTRY(exynos_smc)
|
||||
stmfd sp!, {r4-r11, lr}
|
||||
dsb
|
||||
smc #0
|
||||
ldmfd sp!, {r4-r11, pc}
|
||||
ENDPROC(exynos_smc)
|
384
arch/arm/mach-exynos/exynos.c
Normal file
384
arch/arm/mach-exynos/exynos.c
Normal file
|
@ -0,0 +1,384 @@
|
|||
/*
|
||||
* SAMSUNG EXYNOS Flattened Device Tree enabled machine
|
||||
*
|
||||
* Copyright (c) 2010-2014 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* 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/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/serial_s3c.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/irqchip.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/hardware/cache-l2x0.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/memory.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "mfc.h"
|
||||
#include "regs-pmu.h"
|
||||
#include "regs-sys.h"
|
||||
|
||||
void __iomem *pmu_base_addr;
|
||||
|
||||
static struct map_desc exynos4_iodesc[] __initdata = {
|
||||
{
|
||||
.virtual = (unsigned long)S3C_VA_SYS,
|
||||
.pfn = __phys_to_pfn(EXYNOS4_PA_SYSCON),
|
||||
.length = SZ_64K,
|
||||
.type = MT_DEVICE,
|
||||
}, {
|
||||
.virtual = (unsigned long)S3C_VA_TIMER,
|
||||
.pfn = __phys_to_pfn(EXYNOS4_PA_TIMER),
|
||||
.length = SZ_16K,
|
||||
.type = MT_DEVICE,
|
||||
}, {
|
||||
.virtual = (unsigned long)S3C_VA_WATCHDOG,
|
||||
.pfn = __phys_to_pfn(EXYNOS4_PA_WATCHDOG),
|
||||
.length = SZ_4K,
|
||||
.type = MT_DEVICE,
|
||||
}, {
|
||||
.virtual = (unsigned long)S5P_VA_SROMC,
|
||||
.pfn = __phys_to_pfn(EXYNOS4_PA_SROMC),
|
||||
.length = SZ_4K,
|
||||
.type = MT_DEVICE,
|
||||
}, {
|
||||
.virtual = (unsigned long)S5P_VA_SYSTIMER,
|
||||
.pfn = __phys_to_pfn(EXYNOS4_PA_SYSTIMER),
|
||||
.length = SZ_4K,
|
||||
.type = MT_DEVICE,
|
||||
}, {
|
||||
.virtual = (unsigned long)S5P_VA_COMBINER_BASE,
|
||||
.pfn = __phys_to_pfn(EXYNOS4_PA_COMBINER),
|
||||
.length = SZ_4K,
|
||||
.type = MT_DEVICE,
|
||||
}, {
|
||||
.virtual = (unsigned long)S5P_VA_GIC_CPU,
|
||||
.pfn = __phys_to_pfn(EXYNOS4_PA_GIC_CPU),
|
||||
.length = SZ_64K,
|
||||
.type = MT_DEVICE,
|
||||
}, {
|
||||
.virtual = (unsigned long)S5P_VA_GIC_DIST,
|
||||
.pfn = __phys_to_pfn(EXYNOS4_PA_GIC_DIST),
|
||||
.length = SZ_64K,
|
||||
.type = MT_DEVICE,
|
||||
}, {
|
||||
.virtual = (unsigned long)S5P_VA_CMU,
|
||||
.pfn = __phys_to_pfn(EXYNOS4_PA_CMU),
|
||||
.length = SZ_128K,
|
||||
.type = MT_DEVICE,
|
||||
}, {
|
||||
.virtual = (unsigned long)S5P_VA_COREPERI_BASE,
|
||||
.pfn = __phys_to_pfn(EXYNOS4_PA_COREPERI),
|
||||
.length = SZ_8K,
|
||||
.type = MT_DEVICE,
|
||||
}, {
|
||||
.virtual = (unsigned long)S5P_VA_L2CC,
|
||||
.pfn = __phys_to_pfn(EXYNOS4_PA_L2CC),
|
||||
.length = SZ_4K,
|
||||
.type = MT_DEVICE,
|
||||
}, {
|
||||
.virtual = (unsigned long)S5P_VA_DMC0,
|
||||
.pfn = __phys_to_pfn(EXYNOS4_PA_DMC0),
|
||||
.length = SZ_64K,
|
||||
.type = MT_DEVICE,
|
||||
}, {
|
||||
.virtual = (unsigned long)S5P_VA_DMC1,
|
||||
.pfn = __phys_to_pfn(EXYNOS4_PA_DMC1),
|
||||
.length = SZ_64K,
|
||||
.type = MT_DEVICE,
|
||||
}, {
|
||||
.virtual = (unsigned long)S3C_VA_USB_HSPHY,
|
||||
.pfn = __phys_to_pfn(EXYNOS4_PA_HSPHY),
|
||||
.length = SZ_4K,
|
||||
.type = MT_DEVICE,
|
||||
},
|
||||
};
|
||||
|
||||
static struct map_desc exynos5_iodesc[] __initdata = {
|
||||
{
|
||||
.virtual = (unsigned long)S3C_VA_SYS,
|
||||
.pfn = __phys_to_pfn(EXYNOS5_PA_SYSCON),
|
||||
.length = SZ_64K,
|
||||
.type = MT_DEVICE,
|
||||
}, {
|
||||
.virtual = (unsigned long)S3C_VA_TIMER,
|
||||
.pfn = __phys_to_pfn(EXYNOS5_PA_TIMER),
|
||||
.length = SZ_16K,
|
||||
.type = MT_DEVICE,
|
||||
}, {
|
||||
.virtual = (unsigned long)S3C_VA_WATCHDOG,
|
||||
.pfn = __phys_to_pfn(EXYNOS5_PA_WATCHDOG),
|
||||
.length = SZ_4K,
|
||||
.type = MT_DEVICE,
|
||||
}, {
|
||||
.virtual = (unsigned long)S5P_VA_SROMC,
|
||||
.pfn = __phys_to_pfn(EXYNOS5_PA_SROMC),
|
||||
.length = SZ_4K,
|
||||
.type = MT_DEVICE,
|
||||
}, {
|
||||
.virtual = (unsigned long)S5P_VA_CMU,
|
||||
.pfn = __phys_to_pfn(EXYNOS5_PA_CMU),
|
||||
.length = 144 * SZ_1K,
|
||||
.type = MT_DEVICE,
|
||||
},
|
||||
};
|
||||
|
||||
static void exynos_restart(enum reboot_mode mode, const char *cmd)
|
||||
{
|
||||
struct device_node *np;
|
||||
u32 val = 0x1;
|
||||
void __iomem *addr = pmu_base_addr + EXYNOS_SWRESET;
|
||||
|
||||
if (of_machine_is_compatible("samsung,exynos5440")) {
|
||||
u32 status;
|
||||
np = of_find_compatible_node(NULL, NULL, "samsung,exynos5440-clock");
|
||||
|
||||
addr = of_iomap(np, 0) + 0xbc;
|
||||
status = __raw_readl(addr);
|
||||
|
||||
addr = of_iomap(np, 0) + 0xcc;
|
||||
val = __raw_readl(addr);
|
||||
|
||||
val = (val & 0xffff0000) | (status & 0xffff);
|
||||
}
|
||||
|
||||
__raw_writel(val, addr);
|
||||
}
|
||||
|
||||
static struct platform_device exynos_cpuidle = {
|
||||
.name = "exynos_cpuidle",
|
||||
#ifdef CONFIG_ARM_EXYNOS_CPUIDLE
|
||||
.dev.platform_data = exynos_enter_aftr,
|
||||
#endif
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
void __iomem *sysram_base_addr;
|
||||
void __iomem *sysram_ns_base_addr;
|
||||
|
||||
void __init exynos_sysram_init(void)
|
||||
{
|
||||
struct device_node *node;
|
||||
|
||||
for_each_compatible_node(node, NULL, "samsung,exynos4210-sysram") {
|
||||
if (!of_device_is_available(node))
|
||||
continue;
|
||||
sysram_base_addr = of_iomap(node, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
for_each_compatible_node(node, NULL, "samsung,exynos4210-sysram-ns") {
|
||||
if (!of_device_is_available(node))
|
||||
continue;
|
||||
sysram_ns_base_addr = of_iomap(node, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void __init exynos_init_late(void)
|
||||
{
|
||||
if (of_machine_is_compatible("samsung,exynos5440"))
|
||||
/* to be supported later */
|
||||
return;
|
||||
|
||||
exynos_pm_init();
|
||||
}
|
||||
|
||||
static int __init exynos_fdt_map_chipid(unsigned long node, const char *uname,
|
||||
int depth, void *data)
|
||||
{
|
||||
struct map_desc iodesc;
|
||||
const __be32 *reg;
|
||||
int len;
|
||||
|
||||
if (!of_flat_dt_is_compatible(node, "samsung,exynos4210-chipid") &&
|
||||
!of_flat_dt_is_compatible(node, "samsung,exynos5440-clock"))
|
||||
return 0;
|
||||
|
||||
reg = of_get_flat_dt_prop(node, "reg", &len);
|
||||
if (reg == NULL || len != (sizeof(unsigned long) * 2))
|
||||
return 0;
|
||||
|
||||
iodesc.pfn = __phys_to_pfn(be32_to_cpu(reg[0]));
|
||||
iodesc.length = be32_to_cpu(reg[1]) - 1;
|
||||
iodesc.virtual = (unsigned long)S5P_VA_CHIPID;
|
||||
iodesc.type = MT_DEVICE;
|
||||
iotable_init(&iodesc, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* exynos_map_io
|
||||
*
|
||||
* register the standard cpu IO areas
|
||||
*/
|
||||
static void __init exynos_map_io(void)
|
||||
{
|
||||
if (soc_is_exynos4())
|
||||
iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc));
|
||||
|
||||
if (soc_is_exynos5())
|
||||
iotable_init(exynos5_iodesc, ARRAY_SIZE(exynos5_iodesc));
|
||||
}
|
||||
|
||||
static void __init exynos_init_io(void)
|
||||
{
|
||||
debug_ll_io_init();
|
||||
|
||||
of_scan_flat_dt(exynos_fdt_map_chipid, NULL);
|
||||
|
||||
/* detect cpu id and rev. */
|
||||
s5p_init_cpu(S5P_VA_CHIPID);
|
||||
|
||||
exynos_map_io();
|
||||
}
|
||||
|
||||
static const struct of_device_id exynos_dt_pmu_match[] = {
|
||||
{ .compatible = "samsung,exynos3250-pmu" },
|
||||
{ .compatible = "samsung,exynos4210-pmu" },
|
||||
{ .compatible = "samsung,exynos4212-pmu" },
|
||||
{ .compatible = "samsung,exynos4412-pmu" },
|
||||
{ .compatible = "samsung,exynos5250-pmu" },
|
||||
{ .compatible = "samsung,exynos5260-pmu" },
|
||||
{ .compatible = "samsung,exynos5410-pmu" },
|
||||
{ .compatible = "samsung,exynos5420-pmu" },
|
||||
{ /*sentinel*/ },
|
||||
};
|
||||
|
||||
static void exynos_map_pmu(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
|
||||
np = of_find_matching_node(NULL, exynos_dt_pmu_match);
|
||||
if (np)
|
||||
pmu_base_addr = of_iomap(np, 0);
|
||||
|
||||
if (!pmu_base_addr)
|
||||
panic("failed to find exynos pmu register\n");
|
||||
}
|
||||
|
||||
static void __init exynos_init_irq(void)
|
||||
{
|
||||
irqchip_init();
|
||||
/*
|
||||
* Since platsmp.c needs pmu base address by the time
|
||||
* DT is not unflatten so we can't use DT APIs before
|
||||
* init_irq
|
||||
*/
|
||||
exynos_map_pmu();
|
||||
}
|
||||
|
||||
static void __init exynos_dt_machine_init(void)
|
||||
{
|
||||
struct device_node *i2c_np;
|
||||
const char *i2c_compat = "samsung,s3c2440-i2c";
|
||||
unsigned int tmp;
|
||||
int id;
|
||||
|
||||
/*
|
||||
* Exynos5's legacy i2c controller and new high speed i2c
|
||||
* controller have muxed interrupt sources. By default the
|
||||
* interrupts for 4-channel HS-I2C controller are enabled.
|
||||
* If node for first four channels of legacy i2c controller
|
||||
* are available then re-configure the interrupts via the
|
||||
* system register.
|
||||
*/
|
||||
if (soc_is_exynos5()) {
|
||||
for_each_compatible_node(i2c_np, NULL, i2c_compat) {
|
||||
if (of_device_is_available(i2c_np)) {
|
||||
id = of_alias_get_id(i2c_np, "i2c");
|
||||
if (id < 4) {
|
||||
tmp = readl(EXYNOS5_SYS_I2C_CFG);
|
||||
writel(tmp & ~(0x1 << id),
|
||||
EXYNOS5_SYS_I2C_CFG);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called from smp_prepare_cpus if we've built for SMP, but
|
||||
* we still need to set it up for PM and firmware ops if not.
|
||||
*/
|
||||
if (!IS_ENABLED(CONFIG_SMP))
|
||||
exynos_sysram_init();
|
||||
|
||||
if (of_machine_is_compatible("samsung,exynos4210") ||
|
||||
of_machine_is_compatible("samsung,exynos5250"))
|
||||
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);
|
||||
}
|
||||
|
||||
static char const *exynos_dt_compat[] __initconst = {
|
||||
"samsung,exynos3",
|
||||
"samsung,exynos3250",
|
||||
"samsung,exynos4",
|
||||
"samsung,exynos4210",
|
||||
"samsung,exynos4212",
|
||||
"samsung,exynos4412",
|
||||
"samsung,exynos5",
|
||||
"samsung,exynos5250",
|
||||
"samsung,exynos5260",
|
||||
"samsung,exynos5420",
|
||||
"samsung,exynos5440",
|
||||
NULL
|
||||
};
|
||||
|
||||
static void __init exynos_reserve(void)
|
||||
{
|
||||
#ifdef CONFIG_S5P_DEV_MFC
|
||||
int i;
|
||||
char *mfc_mem[] = {
|
||||
"samsung,mfc-v5",
|
||||
"samsung,mfc-v6",
|
||||
"samsung,mfc-v7",
|
||||
};
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mfc_mem); i++)
|
||||
if (of_scan_flat_dt(s5p_fdt_alloc_mfc_mem, mfc_mem[i]))
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __init exynos_dt_fixup(void)
|
||||
{
|
||||
/*
|
||||
* Some versions of uboot pass garbage entries in the memory node,
|
||||
* use the old CONFIG_ARM_NR_BANKS
|
||||
*/
|
||||
of_fdt_limit_memory(8);
|
||||
}
|
||||
|
||||
DT_MACHINE_START(EXYNOS_DT, "SAMSUNG EXYNOS (Flattened Device Tree)")
|
||||
/* Maintainer: Thomas Abraham <thomas.abraham@linaro.org> */
|
||||
/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
|
||||
.l2c_aux_val = 0x3c400001,
|
||||
.l2c_aux_mask = 0xc20fffff,
|
||||
.smp = smp_ops(exynos_smp_ops),
|
||||
.map_io = exynos_init_io,
|
||||
.init_early = exynos_firmware_init,
|
||||
.init_irq = exynos_init_irq,
|
||||
.init_machine = exynos_dt_machine_init,
|
||||
.init_late = exynos_init_late,
|
||||
.dt_compat = exynos_dt_compat,
|
||||
.restart = exynos_restart,
|
||||
.reserve = exynos_reserve,
|
||||
.dt_fixup = exynos_dt_fixup,
|
||||
MACHINE_END
|
97
arch/arm/mach-exynos/firmware.c
Normal file
97
arch/arm/mach-exynos/firmware.c
Normal file
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Samsung Electronics.
|
||||
* Kyungmin Park <kyungmin.park@samsung.com>
|
||||
* Tomasz Figa <t.figa@samsung.com>
|
||||
*
|
||||
* 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/io.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
|
||||
#include <asm/firmware.h>
|
||||
|
||||
#include <mach/map.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "smc.h"
|
||||
|
||||
static int exynos_do_idle(void)
|
||||
{
|
||||
exynos_smc(SMC_CMD_SLEEP, 0, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int exynos_cpu_boot(int cpu)
|
||||
{
|
||||
/*
|
||||
* Exynos3250 doesn't need to send smc command for secondary CPU boot
|
||||
* because Exynos3250 removes WFE in secure mode.
|
||||
*/
|
||||
if (soc_is_exynos3250())
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* The second parameter of SMC_CMD_CPU1BOOT command means CPU id.
|
||||
* But, Exynos4212 has only one secondary CPU so second parameter
|
||||
* isn't used for informing secure firmware about CPU id.
|
||||
*/
|
||||
if (soc_is_exynos4212())
|
||||
cpu = 0;
|
||||
|
||||
exynos_smc(SMC_CMD_CPU1BOOT, cpu, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int exynos_set_cpu_boot_addr(int cpu, unsigned long boot_addr)
|
||||
{
|
||||
void __iomem *boot_reg;
|
||||
|
||||
if (!sysram_ns_base_addr)
|
||||
return -ENODEV;
|
||||
|
||||
boot_reg = sysram_ns_base_addr + 0x1c;
|
||||
|
||||
/*
|
||||
* Almost all Exynos-series of SoCs that run in secure mode don't need
|
||||
* additional offset for every CPU, with Exynos4412 being the only
|
||||
* exception.
|
||||
*/
|
||||
if (soc_is_exynos4412())
|
||||
boot_reg += 4 * cpu;
|
||||
|
||||
__raw_writel(boot_addr, boot_reg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct firmware_ops exynos_firmware_ops = {
|
||||
.do_idle = exynos_do_idle,
|
||||
.set_cpu_boot_addr = exynos_set_cpu_boot_addr,
|
||||
.cpu_boot = exynos_cpu_boot,
|
||||
};
|
||||
|
||||
void __init exynos_firmware_init(void)
|
||||
{
|
||||
struct device_node *nd;
|
||||
const __be32 *addr;
|
||||
|
||||
nd = of_find_compatible_node(NULL, NULL,
|
||||
"samsung,secure-firmware");
|
||||
if (!nd)
|
||||
return;
|
||||
|
||||
addr = of_get_address(nd, 0, NULL, NULL);
|
||||
if (!addr) {
|
||||
pr_err("%s: No address specified.\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
pr_info("Running under secure firmware.\n");
|
||||
|
||||
register_firmware_ops(&exynos_firmware_ops);
|
||||
}
|
40
arch/arm/mach-exynos/headsmp.S
Normal file
40
arch/arm/mach-exynos/headsmp.S
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
*
|
||||
* Cloned from linux/arch/arm/mach-realview/headsmp.S
|
||||
*
|
||||
* Copyright (c) 2003 ARM Limited
|
||||
* 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/linkage.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
/*
|
||||
* exynos4 specific entry point for secondary CPUs. This provides
|
||||
* a "holding pen" into which all secondary cores are held until we're
|
||||
* ready for them to initialise.
|
||||
*/
|
||||
ENTRY(exynos4_secondary_startup)
|
||||
mrc p15, 0, r0, c0, c0, 5
|
||||
and r0, r0, #15
|
||||
adr r4, 1f
|
||||
ldmia r4, {r5, r6}
|
||||
sub r4, r4, r5
|
||||
add r6, r6, r4
|
||||
pen: ldr r7, [r6]
|
||||
cmp r7, r0
|
||||
bne pen
|
||||
|
||||
/*
|
||||
* we've been released from the holding pen: secondary_stack
|
||||
* should now contain the SVC stack for this core
|
||||
*/
|
||||
b secondary_startup
|
||||
ENDPROC(exynos4_secondary_startup)
|
||||
|
||||
.align 2
|
||||
1: .long .
|
||||
.long pen_release
|
91
arch/arm/mach-exynos/hotplug.c
Normal file
91
arch/arm/mach-exynos/hotplug.c
Normal file
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* 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);
|
||||
}
|
26
arch/arm/mach-exynos/include/mach/dma.h
Normal file
26
arch/arm/mach-exynos/include/mach/dma.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (C) 2010 Samsung Electronics Co. Ltd.
|
||||
* Jaswinder Singh <jassi.brar@samsung.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __MACH_DMA_H
|
||||
#define __MACH_DMA_H
|
||||
|
||||
/* This platform uses the common DMA API driver for PL330 */
|
||||
#include <plat/dma-pl330.h>
|
||||
|
||||
#endif /* __MACH_DMA_H */
|
60
arch/arm/mach-exynos/include/mach/exynos-hevc.h
Normal file
60
arch/arm/mach-exynos/include/mach/exynos-hevc.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
/* linux/arch/arm/mach-exynos/include/mach/exynos-hevc.h
|
||||
*
|
||||
* Copyright 2011 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com/
|
||||
*
|
||||
* Header file for exynos hevc 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_HEVC_H
|
||||
#define _EXYNOS_HEVC_H
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#if defined(CONFIG_ARM_EXYNOS5410_BUS_DEVFREQ) || \
|
||||
defined(CONFIG_ARM_EXYNOS5420_BUS_DEVFREQ) || \
|
||||
defined(CONFIG_ARM_EXYNOS5430_BUS_DEVFREQ) || \
|
||||
defined(CONFIG_ARM_EXYNOS5433_BUS_DEVFREQ)
|
||||
#define CONFIG_HEVC_USE_BUS_DEVFREQ
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HEVC_USE_BUS_DEVFREQ
|
||||
/*
|
||||
* thrd_mb - threshold of total MB(macroblock) count
|
||||
* Total MB count can be calculated by
|
||||
* (MB of width) * (MB of height) * fps
|
||||
*/
|
||||
struct hevc_qos {
|
||||
unsigned int thrd_mb;
|
||||
unsigned int freq_hevc;
|
||||
unsigned int freq_int;
|
||||
unsigned int freq_mif;
|
||||
unsigned int freq_cpu;
|
||||
#ifndef CONFIG_ARM_EXYNOS_IKS_CPUFREQ
|
||||
unsigned int freq_kfc;
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
enum hevc_ip_version {
|
||||
IP_VER_HEVC_1 = 1,
|
||||
};
|
||||
|
||||
struct hevc_platdata {
|
||||
int ip_ver;
|
||||
int clock_rate;
|
||||
int min_rate;
|
||||
#ifdef CONFIG_HEVC_USE_BUS_DEVFREQ
|
||||
int num_qos_steps;
|
||||
struct hevc_qos *qos_table;
|
||||
#endif
|
||||
};
|
||||
|
||||
void hevc_set_platdata(struct hevc_platdata *pd);
|
||||
void hevc_setname(struct platform_device *pdev, char *name);
|
||||
|
||||
#endif /* _EXYNOS_HEVC_H */
|
69
arch/arm/mach-exynos/include/mach/map.h
Normal file
69
arch/arm/mach-exynos/include/mach/map.h
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com/
|
||||
*
|
||||
* EXYNOS4 - Memory map definitions
|
||||
*
|
||||
* 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_MAP_H
|
||||
#define __ASM_ARCH_MAP_H __FILE__
|
||||
|
||||
#include <plat/map-base.h>
|
||||
|
||||
/*
|
||||
* EXYNOS4 UART offset is 0x10000 but the older S5P SoCs are 0x400.
|
||||
* So need to define it, and here is to avoid redefinition warning.
|
||||
*/
|
||||
#define S3C_UART_OFFSET (0x10000)
|
||||
|
||||
#include <plat/map-s5p.h>
|
||||
|
||||
#define EXYNOS_PA_CHIPID 0x10000000
|
||||
|
||||
#define EXYNOS4_PA_SYSCON 0x10010000
|
||||
#define EXYNOS5_PA_SYSCON 0x10050100
|
||||
|
||||
#define EXYNOS4_PA_CMU 0x10030000
|
||||
#define EXYNOS5_PA_CMU 0x10010000
|
||||
|
||||
#define EXYNOS4_PA_SYSTIMER 0x10050000
|
||||
|
||||
#define EXYNOS4_PA_WATCHDOG 0x10060000
|
||||
#define EXYNOS5_PA_WATCHDOG 0x101D0000
|
||||
|
||||
#define EXYNOS4_PA_DMC0 0x10400000
|
||||
#define EXYNOS4_PA_DMC1 0x10410000
|
||||
|
||||
#define EXYNOS4_PA_COMBINER 0x10440000
|
||||
#define EXYNOS5_PA_COMBINER 0x10440000
|
||||
|
||||
#define EXYNOS4_PA_GIC_CPU 0x10480000
|
||||
#define EXYNOS4_PA_GIC_DIST 0x10490000
|
||||
#define EXYNOS5_PA_GIC_CPU 0x10482000
|
||||
#define EXYNOS5_PA_GIC_DIST 0x10481000
|
||||
|
||||
#define EXYNOS4_PA_COREPERI 0x10500000
|
||||
#define EXYNOS4_PA_L2CC 0x10502000
|
||||
|
||||
#define EXYNOS4_PA_SROMC 0x12570000
|
||||
#define EXYNOS5_PA_SROMC 0x12250000
|
||||
|
||||
#define EXYNOS4_PA_HSPHY 0x125B0000
|
||||
|
||||
#define EXYNOS4_PA_UART 0x13800000
|
||||
#define EXYNOS5_PA_UART 0x12C00000
|
||||
|
||||
#define EXYNOS4_PA_TIMER 0x139D0000
|
||||
#define EXYNOS5_PA_TIMER 0x12DD0000
|
||||
|
||||
/* Compatibility UART */
|
||||
|
||||
#define EXYNOS5440_PA_UART0 0x000B0000
|
||||
|
||||
#define S3C_VA_UARTx(x) (S3C_VA_UART + ((x) * S3C_UART_OFFSET))
|
||||
|
||||
#endif /* __ASM_ARCH_MAP_H */
|
404
arch/arm/mach-exynos/mcpm-exynos.c
Normal file
404
arch/arm/mach-exynos/mcpm-exynos.c
Normal file
|
@ -0,0 +1,404 @@
|
|||
/*
|
||||
* Copyright (c) 2014 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* arch/arm/mach-exynos/mcpm-exynos.c
|
||||
*
|
||||
* Based on arch/arm/mach-vexpress/dcscb.c
|
||||
*
|
||||
* 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/arm-cci.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of_address.h>
|
||||
|
||||
#include <asm/cputype.h>
|
||||
#include <asm/cp15.h>
|
||||
#include <asm/mcpm.h>
|
||||
|
||||
#include "regs-pmu.h"
|
||||
#include "common.h"
|
||||
|
||||
#define EXYNOS5420_CPUS_PER_CLUSTER 4
|
||||
#define EXYNOS5420_NR_CLUSTERS 2
|
||||
|
||||
#define EXYNOS5420_ENABLE_AUTOMATIC_CORE_DOWN BIT(9)
|
||||
#define EXYNOS5420_USE_ARM_CORE_DOWN_STATE BIT(29)
|
||||
#define EXYNOS5420_USE_L2_COMMON_UP_STATE BIT(30)
|
||||
|
||||
/*
|
||||
* 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
|
||||
* arch/arm/include/asm/cacheflush.h) except for the erratum handling.
|
||||
*/
|
||||
#define exynos_v7_exit_coherency_flush(level) \
|
||||
asm volatile( \
|
||||
"stmfd sp!, {fp, ip}\n\t"\
|
||||
"mrc p15, 0, r0, c1, c0, 0 @ get SCTLR\n\t" \
|
||||
"bic r0, r0, #"__stringify(CR_C)"\n\t" \
|
||||
"mcr p15, 0, r0, c1, c0, 0 @ set SCTLR\n\t" \
|
||||
"isb\n\t"\
|
||||
"bl v7_flush_dcache_"__stringify(level)"\n\t" \
|
||||
"mrc p15, 0, r0, c1, c0, 1 @ get ACTLR\n\t" \
|
||||
"bic r0, r0, #(1 << 6) @ disable local coherency\n\t" \
|
||||
/* Dummy Load of a device register to avoid Erratum 799270 */ \
|
||||
"ldr r4, [%0]\n\t" \
|
||||
"and r4, r4, #0\n\t" \
|
||||
"orr r0, r0, r4\n\t" \
|
||||
"mcr p15, 0, r0, c1, c0, 1 @ set ACTLR\n\t" \
|
||||
"isb\n\t" \
|
||||
"dsb\n\t" \
|
||||
"ldmfd sp!, {fp, ip}" \
|
||||
: \
|
||||
: "Ir" (pmu_base_addr + S5P_INFORM0) \
|
||||
: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
|
||||
"r9", "r10", "lr", "memory")
|
||||
|
||||
/*
|
||||
* We can't use regular spinlocks. In the switcher case, it is possible
|
||||
* for an outbound CPU to call power_down() after its inbound counterpart
|
||||
* is already live using the same logical CPU number which trips lockdep
|
||||
* debugging.
|
||||
*/
|
||||
static arch_spinlock_t exynos_mcpm_lock = __ARCH_SPIN_LOCK_UNLOCKED;
|
||||
static int
|
||||
cpu_use_count[EXYNOS5420_CPUS_PER_CLUSTER][EXYNOS5420_NR_CLUSTERS];
|
||||
|
||||
#define exynos_cluster_usecnt(cluster) \
|
||||
(cpu_use_count[0][cluster] + \
|
||||
cpu_use_count[1][cluster] + \
|
||||
cpu_use_count[2][cluster] + \
|
||||
cpu_use_count[3][cluster])
|
||||
|
||||
#define exynos_cluster_unused(cluster) !exynos_cluster_usecnt(cluster)
|
||||
|
||||
static int exynos_power_up(unsigned int cpu, unsigned int cluster)
|
||||
{
|
||||
unsigned int cpunr = cpu + (cluster * EXYNOS5420_CPUS_PER_CLUSTER);
|
||||
|
||||
pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
|
||||
if (cpu >= EXYNOS5420_CPUS_PER_CLUSTER ||
|
||||
cluster >= EXYNOS5420_NR_CLUSTERS)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Since this is called with IRQs enabled, and no arch_spin_lock_irq
|
||||
* variant exists, we need to disable IRQs manually here.
|
||||
*/
|
||||
local_irq_disable();
|
||||
arch_spin_lock(&exynos_mcpm_lock);
|
||||
|
||||
cpu_use_count[cpu][cluster]++;
|
||||
if (cpu_use_count[cpu][cluster] == 1) {
|
||||
bool was_cluster_down =
|
||||
(exynos_cluster_usecnt(cluster) == 1);
|
||||
|
||||
/*
|
||||
* Turn on the cluster (L2/COMMON) and then power on the
|
||||
* cores.
|
||||
*/
|
||||
if (was_cluster_down)
|
||||
exynos_cluster_power_up(cluster);
|
||||
|
||||
exynos_cpu_power_up(cpunr);
|
||||
} else if (cpu_use_count[cpu][cluster] != 2) {
|
||||
/*
|
||||
* The only possible values are:
|
||||
* 0 = CPU down
|
||||
* 1 = CPU (still) up
|
||||
* 2 = CPU requested to be up before it had a chance
|
||||
* to actually make itself down.
|
||||
* Any other value is a bug.
|
||||
*/
|
||||
BUG();
|
||||
}
|
||||
|
||||
arch_spin_unlock(&exynos_mcpm_lock);
|
||||
local_irq_enable();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: This function requires the stack data to be visible through power down
|
||||
* and can only be executed on processors like A15 and A7 that hit the cache
|
||||
* with the C bit clear in the SCTLR register.
|
||||
*/
|
||||
static void exynos_power_down(void)
|
||||
{
|
||||
unsigned int mpidr, cpu, cluster;
|
||||
bool last_man = false, skip_wfi = false;
|
||||
unsigned int cpunr;
|
||||
|
||||
mpidr = read_cpuid_mpidr();
|
||||
cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
|
||||
cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
|
||||
cpunr = cpu + (cluster * EXYNOS5420_CPUS_PER_CLUSTER);
|
||||
|
||||
pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
|
||||
BUG_ON(cpu >= EXYNOS5420_CPUS_PER_CLUSTER ||
|
||||
cluster >= EXYNOS5420_NR_CLUSTERS);
|
||||
|
||||
__mcpm_cpu_going_down(cpu, cluster);
|
||||
|
||||
arch_spin_lock(&exynos_mcpm_lock);
|
||||
BUG_ON(__mcpm_cluster_state(cluster) != CLUSTER_UP);
|
||||
cpu_use_count[cpu][cluster]--;
|
||||
if (cpu_use_count[cpu][cluster] == 0) {
|
||||
exynos_cpu_power_down(cpunr);
|
||||
|
||||
if (exynos_cluster_unused(cluster)) {
|
||||
exynos_cluster_power_down(cluster);
|
||||
last_man = true;
|
||||
}
|
||||
} else if (cpu_use_count[cpu][cluster] == 1) {
|
||||
/*
|
||||
* A power_up request went ahead of us.
|
||||
* Even if we do not want to shut this CPU down,
|
||||
* the caller expects a certain state as if the WFI
|
||||
* was aborted. So let's continue with cache cleaning.
|
||||
*/
|
||||
skip_wfi = true;
|
||||
} else {
|
||||
BUG();
|
||||
}
|
||||
|
||||
if (last_man && __mcpm_outbound_enter_critical(cpu, cluster)) {
|
||||
arch_spin_unlock(&exynos_mcpm_lock);
|
||||
|
||||
if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A15) {
|
||||
/*
|
||||
* On the Cortex-A15 we need to disable
|
||||
* L2 prefetching before flushing the cache.
|
||||
*/
|
||||
asm volatile(
|
||||
"mcr p15, 1, %0, c15, c0, 3\n\t"
|
||||
"isb\n\t"
|
||||
"dsb"
|
||||
: : "r" (0x400));
|
||||
}
|
||||
|
||||
/* Flush all cache levels for this cluster. */
|
||||
exynos_v7_exit_coherency_flush(all);
|
||||
|
||||
/*
|
||||
* Disable cluster-level coherency by masking
|
||||
* incoming snoops and DVM messages:
|
||||
*/
|
||||
cci_disable_port_by_cpu(mpidr);
|
||||
|
||||
__mcpm_outbound_leave_critical(cluster, CLUSTER_DOWN);
|
||||
} else {
|
||||
arch_spin_unlock(&exynos_mcpm_lock);
|
||||
|
||||
/* Disable and flush the local CPU cache. */
|
||||
exynos_v7_exit_coherency_flush(louis);
|
||||
}
|
||||
|
||||
__mcpm_cpu_down(cpu, cluster);
|
||||
|
||||
/* Now we are prepared for power-down, do it: */
|
||||
if (!skip_wfi)
|
||||
wfi();
|
||||
|
||||
/* Not dead at this point? Let our caller cope. */
|
||||
}
|
||||
|
||||
static int exynos_wait_for_powerdown(unsigned int cpu, unsigned int cluster)
|
||||
{
|
||||
unsigned int tries = 100;
|
||||
unsigned int cpunr = cpu + (cluster * EXYNOS5420_CPUS_PER_CLUSTER);
|
||||
|
||||
pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
|
||||
BUG_ON(cpu >= EXYNOS5420_CPUS_PER_CLUSTER ||
|
||||
cluster >= EXYNOS5420_NR_CLUSTERS);
|
||||
|
||||
/* Wait for the core state to be OFF */
|
||||
while (tries--) {
|
||||
if (ACCESS_ONCE(cpu_use_count[cpu][cluster]) == 0) {
|
||||
if ((exynos_cpu_power_state(cpunr) == 0))
|
||||
return 0; /* success: the CPU is halted */
|
||||
}
|
||||
|
||||
/* Otherwise, wait and retry: */
|
||||
msleep(1);
|
||||
}
|
||||
|
||||
return -ETIMEDOUT; /* timeout */
|
||||
}
|
||||
|
||||
static void exynos_powered_up(void)
|
||||
{
|
||||
unsigned int mpidr, cpu, cluster;
|
||||
|
||||
mpidr = read_cpuid_mpidr();
|
||||
cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
|
||||
cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
|
||||
|
||||
arch_spin_lock(&exynos_mcpm_lock);
|
||||
if (cpu_use_count[cpu][cluster] == 0)
|
||||
cpu_use_count[cpu][cluster] = 1;
|
||||
arch_spin_unlock(&exynos_mcpm_lock);
|
||||
}
|
||||
|
||||
static void exynos_suspend(u64 residency)
|
||||
{
|
||||
unsigned int mpidr, cpunr;
|
||||
|
||||
exynos_power_down();
|
||||
|
||||
/*
|
||||
* Execution reaches here only if cpu did not power down.
|
||||
* Hence roll back the changes done in exynos_power_down function.
|
||||
*
|
||||
* CAUTION: "This function requires the stack data to be visible through
|
||||
* power down and can only be executed on processors like A15 and A7
|
||||
* that hit the cache with the C bit clear in the SCTLR register."
|
||||
*/
|
||||
mpidr = read_cpuid_mpidr();
|
||||
cpunr = exynos_pmu_cpunr(mpidr);
|
||||
|
||||
exynos_cpu_power_up(cpunr);
|
||||
}
|
||||
|
||||
static const struct mcpm_platform_ops exynos_power_ops = {
|
||||
.power_up = exynos_power_up,
|
||||
.power_down = exynos_power_down,
|
||||
.wait_for_powerdown = exynos_wait_for_powerdown,
|
||||
.suspend = exynos_suspend,
|
||||
.powered_up = exynos_powered_up,
|
||||
};
|
||||
|
||||
static void __init exynos_mcpm_usage_count_init(void)
|
||||
{
|
||||
unsigned int mpidr, cpu, cluster;
|
||||
|
||||
mpidr = read_cpuid_mpidr();
|
||||
cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
|
||||
cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
|
||||
|
||||
pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
|
||||
BUG_ON(cpu >= EXYNOS5420_CPUS_PER_CLUSTER ||
|
||||
cluster >= EXYNOS5420_NR_CLUSTERS);
|
||||
|
||||
cpu_use_count[cpu][cluster] = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable cluster-level coherency, in preparation for turning on the MMU.
|
||||
*/
|
||||
static void __naked exynos_pm_power_up_setup(unsigned int affinity_level)
|
||||
{
|
||||
asm volatile ("\n"
|
||||
"cmp r0, #1\n"
|
||||
"bxne lr\n"
|
||||
"b cci_enable_port_for_self");
|
||||
}
|
||||
|
||||
static void __init exynos_cache_off(void)
|
||||
{
|
||||
if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A15) {
|
||||
/* disable L2 prefetching on the Cortex-A15 */
|
||||
asm volatile(
|
||||
"mcr p15, 1, %0, c15, c0, 3\n\t"
|
||||
"isb\n\t"
|
||||
"dsb"
|
||||
: : "r" (0x400));
|
||||
}
|
||||
exynos_v7_exit_coherency_flush(all);
|
||||
}
|
||||
|
||||
static const struct of_device_id exynos_dt_mcpm_match[] = {
|
||||
{ .compatible = "samsung,exynos5420" },
|
||||
{ .compatible = "samsung,exynos5800" },
|
||||
{},
|
||||
};
|
||||
|
||||
static int __init exynos_mcpm_init(void)
|
||||
{
|
||||
struct device_node *node;
|
||||
void __iomem *ns_sram_base_addr;
|
||||
unsigned int value, i;
|
||||
int ret;
|
||||
|
||||
node = of_find_matching_node(NULL, exynos_dt_mcpm_match);
|
||||
if (!node)
|
||||
return -ENODEV;
|
||||
of_node_put(node);
|
||||
|
||||
if (!cci_probed())
|
||||
return -ENODEV;
|
||||
|
||||
node = of_find_compatible_node(NULL, NULL,
|
||||
"samsung,exynos4210-sysram-ns");
|
||||
if (!node)
|
||||
return -ENODEV;
|
||||
|
||||
ns_sram_base_addr = of_iomap(node, 0);
|
||||
of_node_put(node);
|
||||
if (!ns_sram_base_addr) {
|
||||
pr_err("failed to map non-secure iRAM base address\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* To increase the stability of KFC reset we need to program
|
||||
* the PMU SPARE3 register
|
||||
*/
|
||||
pmu_raw_writel(EXYNOS5420_SWRESET_KFC_SEL, S5P_PMU_SPARE3);
|
||||
|
||||
exynos_mcpm_usage_count_init();
|
||||
|
||||
ret = mcpm_platform_register(&exynos_power_ops);
|
||||
if (!ret)
|
||||
ret = mcpm_sync_init(exynos_pm_power_up_setup);
|
||||
if (!ret)
|
||||
ret = mcpm_loopback(exynos_cache_off); /* turn on the CCI */
|
||||
if (ret) {
|
||||
iounmap(ns_sram_base_addr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mcpm_smp_set_ops();
|
||||
|
||||
pr_info("Exynos MCPM support installed\n");
|
||||
|
||||
/*
|
||||
* On Exynos5420/5800 for the A15 and A7 clusters:
|
||||
*
|
||||
* EXYNOS5420_ENABLE_AUTOMATIC_CORE_DOWN ensures that all the cores
|
||||
* in a cluster are turned off before turning off the cluster L2.
|
||||
*
|
||||
* EXYNOS5420_USE_ARM_CORE_DOWN_STATE ensures that a cores is powered
|
||||
* off before waking it up.
|
||||
*
|
||||
* EXYNOS5420_USE_L2_COMMON_UP_STATE ensures that cluster L2 will be
|
||||
* turned on before the first man is powered up.
|
||||
*/
|
||||
for (i = 0; i < EXYNOS5420_NR_CLUSTERS; i++) {
|
||||
value = pmu_raw_readl(EXYNOS_COMMON_OPTION(i));
|
||||
value |= EXYNOS5420_ENABLE_AUTOMATIC_CORE_DOWN |
|
||||
EXYNOS5420_USE_ARM_CORE_DOWN_STATE |
|
||||
EXYNOS5420_USE_L2_COMMON_UP_STATE;
|
||||
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);
|
||||
|
||||
iounmap(ns_sram_base_addr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
early_initcall(exynos_mcpm_init);
|
16
arch/arm/mach-exynos/mfc.h
Normal file
16
arch/arm/mach-exynos/mfc.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* Copyright (C) 2013 Samsung Electronics Co.Ltd
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef __MACH_EXYNOS_MFC_H
|
||||
#define __MACH_EXYNOS_MFC_H __FILE__
|
||||
|
||||
int __init s5p_fdt_alloc_mfc_mem(unsigned long node, const char *uname,
|
||||
int depth, void *data);
|
||||
|
||||
#endif /* __MACH_EXYNOS_MFC_H */
|
329
arch/arm/mach-exynos/platsmp.c
Normal file
329
arch/arm/mach-exynos/platsmp.c
Normal file
|
@ -0,0 +1,329 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* Cloned from linux/arch/arm/mach-vexpress/platsmp.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/init.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#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>
|
||||
#include <asm/smp_scu.h>
|
||||
#include <asm/firmware.h>
|
||||
|
||||
#include <mach/map.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "regs-pmu.h"
|
||||
|
||||
extern void exynos4_secondary_startup(void);
|
||||
|
||||
/**
|
||||
* exynos_core_power_down : power down the specified cpu
|
||||
* @cpu : the cpu to power down
|
||||
*
|
||||
* Power down the specified cpu. The sequence must be finished by a
|
||||
* call to cpu_do_idle()
|
||||
*
|
||||
*/
|
||||
void exynos_cpu_power_down(int cpu)
|
||||
{
|
||||
pmu_raw_writel(0, EXYNOS_ARM_CORE_CONFIGURATION(cpu));
|
||||
}
|
||||
|
||||
/**
|
||||
* exynos_cpu_power_up : power up the specified cpu
|
||||
* @cpu : the cpu to power up
|
||||
*
|
||||
* Power up the specified cpu
|
||||
*/
|
||||
void exynos_cpu_power_up(int cpu)
|
||||
{
|
||||
pmu_raw_writel(S5P_CORE_LOCAL_PWR_EN,
|
||||
EXYNOS_ARM_CORE_CONFIGURATION(cpu));
|
||||
}
|
||||
|
||||
/**
|
||||
* exynos_cpu_power_state : returns the power state of the cpu
|
||||
* @cpu : the cpu to retrieve the power state from
|
||||
*
|
||||
*/
|
||||
int exynos_cpu_power_state(int cpu)
|
||||
{
|
||||
return (pmu_raw_readl(EXYNOS_ARM_CORE_STATUS(cpu)) &
|
||||
S5P_CORE_LOCAL_PWR_EN);
|
||||
}
|
||||
|
||||
/**
|
||||
* exynos_cluster_power_down : power down the specified cluster
|
||||
* @cluster : the cluster to power down
|
||||
*/
|
||||
void exynos_cluster_power_down(int cluster)
|
||||
{
|
||||
pmu_raw_writel(0, EXYNOS_COMMON_CONFIGURATION(cluster));
|
||||
}
|
||||
|
||||
/**
|
||||
* exynos_cluster_power_up : power up the specified cluster
|
||||
* @cluster : the cluster to power up
|
||||
*/
|
||||
void exynos_cluster_power_up(int cluster)
|
||||
{
|
||||
pmu_raw_writel(S5P_CORE_LOCAL_PWR_EN,
|
||||
EXYNOS_COMMON_CONFIGURATION(cluster));
|
||||
}
|
||||
|
||||
/**
|
||||
* exynos_cluster_power_state : returns the power state of the cluster
|
||||
* @cluster : the cluster to retrieve the power state from
|
||||
*
|
||||
*/
|
||||
int exynos_cluster_power_state(int cluster)
|
||||
{
|
||||
return (pmu_raw_readl(EXYNOS_COMMON_STATUS(cluster)) &
|
||||
S5P_CORE_LOCAL_PWR_EN);
|
||||
}
|
||||
|
||||
static inline void __iomem *cpu_boot_reg_base(void)
|
||||
{
|
||||
if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_1_1)
|
||||
return pmu_base_addr + S5P_INFORM5;
|
||||
return sysram_base_addr;
|
||||
}
|
||||
|
||||
static inline void __iomem *cpu_boot_reg(int cpu)
|
||||
{
|
||||
void __iomem *boot_reg;
|
||||
|
||||
boot_reg = cpu_boot_reg_base();
|
||||
if (!boot_reg)
|
||||
return ERR_PTR(-ENODEV);
|
||||
if (soc_is_exynos4412())
|
||||
boot_reg += 4*cpu;
|
||||
else if (soc_is_exynos5420() || soc_is_exynos5800())
|
||||
boot_reg += 4;
|
||||
return boot_reg;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write pen_release in a way that is guaranteed to be visible to all
|
||||
* observers, irrespective of whether they're taking part in coherency
|
||||
* or not. This is necessary for the hotplug code to work reliably.
|
||||
*/
|
||||
static void write_pen_release(int val)
|
||||
{
|
||||
pen_release = val;
|
||||
smp_wmb();
|
||||
sync_cache_w(&pen_release);
|
||||
}
|
||||
|
||||
static void __iomem *scu_base_addr(void)
|
||||
{
|
||||
return (void __iomem *)(S5P_VA_SCU);
|
||||
}
|
||||
|
||||
static DEFINE_SPINLOCK(boot_lock);
|
||||
|
||||
static void exynos_secondary_init(unsigned int cpu)
|
||||
{
|
||||
/*
|
||||
* let the primary processor know we're out of the
|
||||
* pen, then head off into the C entry point
|
||||
*/
|
||||
write_pen_release(-1);
|
||||
|
||||
/*
|
||||
* Synchronise with the boot thread.
|
||||
*/
|
||||
spin_lock(&boot_lock);
|
||||
spin_unlock(&boot_lock);
|
||||
}
|
||||
|
||||
static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||
{
|
||||
unsigned long timeout;
|
||||
u32 mpidr = cpu_logical_map(cpu);
|
||||
u32 core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
|
||||
int ret = -ENOSYS;
|
||||
|
||||
/*
|
||||
* Set synchronisation state between this boot processor
|
||||
* and the secondary one
|
||||
*/
|
||||
spin_lock(&boot_lock);
|
||||
|
||||
/*
|
||||
* The secondary processor is waiting to be released from
|
||||
* the holding pen - release it, then wait for it to flag
|
||||
* that it has been released by resetting pen_release.
|
||||
*
|
||||
* Note that "pen_release" is the hardware CPU core ID, whereas
|
||||
* "cpu" is Linux's internal ID.
|
||||
*/
|
||||
write_pen_release(core_id);
|
||||
|
||||
if (!exynos_cpu_power_state(core_id)) {
|
||||
exynos_cpu_power_up(core_id);
|
||||
timeout = 10;
|
||||
|
||||
/* wait max 10 ms until cpu1 is on */
|
||||
while (exynos_cpu_power_state(core_id)
|
||||
!= S5P_CORE_LOCAL_PWR_EN) {
|
||||
if (timeout-- == 0)
|
||||
break;
|
||||
|
||||
mdelay(1);
|
||||
}
|
||||
|
||||
if (timeout == 0) {
|
||||
printk(KERN_ERR "cpu1 power enable failed");
|
||||
spin_unlock(&boot_lock);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Send the secondary CPU a soft interrupt, thereby causing
|
||||
* the boot monitor to read the system wide flags register,
|
||||
* and branch to the address found there.
|
||||
*/
|
||||
|
||||
timeout = jiffies + (1 * HZ);
|
||||
while (time_before(jiffies, timeout)) {
|
||||
unsigned long boot_addr;
|
||||
|
||||
smp_rmb();
|
||||
|
||||
boot_addr = virt_to_phys(exynos4_secondary_startup);
|
||||
|
||||
/*
|
||||
* Try to set boot address using firmware first
|
||||
* and fall back to boot register if it fails.
|
||||
*/
|
||||
ret = call_firmware_op(set_cpu_boot_addr, core_id, boot_addr);
|
||||
if (ret && ret != -ENOSYS)
|
||||
goto fail;
|
||||
if (ret == -ENOSYS) {
|
||||
void __iomem *boot_reg = cpu_boot_reg(core_id);
|
||||
|
||||
if (IS_ERR(boot_reg)) {
|
||||
ret = PTR_ERR(boot_reg);
|
||||
goto fail;
|
||||
}
|
||||
__raw_writel(boot_addr, boot_reg);
|
||||
}
|
||||
|
||||
call_firmware_op(cpu_boot, core_id);
|
||||
|
||||
arch_send_wakeup_ipi_mask(cpumask_of(cpu));
|
||||
|
||||
if (pen_release == -1)
|
||||
break;
|
||||
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
/*
|
||||
* now the secondary core is starting up let it run its
|
||||
* calibrations, then wait for it to finish
|
||||
*/
|
||||
fail:
|
||||
spin_unlock(&boot_lock);
|
||||
|
||||
return pen_release != -1 ? ret : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialise the CPU possible map early - this describes the CPUs
|
||||
* which may be present or become present in the system.
|
||||
*/
|
||||
|
||||
static void __init exynos_smp_init_cpus(void)
|
||||
{
|
||||
void __iomem *scu_base = scu_base_addr();
|
||||
unsigned int i, ncores;
|
||||
|
||||
if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
|
||||
ncores = scu_base ? scu_get_core_count(scu_base) : 1;
|
||||
else
|
||||
/*
|
||||
* CPU Nodes are passed thru DT and set_cpu_possible
|
||||
* is set by "arm_dt_init_cpu_maps".
|
||||
*/
|
||||
return;
|
||||
|
||||
/* sanity check */
|
||||
if (ncores > nr_cpu_ids) {
|
||||
pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
|
||||
ncores, nr_cpu_ids);
|
||||
ncores = nr_cpu_ids;
|
||||
}
|
||||
|
||||
for (i = 0; i < ncores; i++)
|
||||
set_cpu_possible(i, true);
|
||||
}
|
||||
|
||||
static void __init exynos_smp_prepare_cpus(unsigned int max_cpus)
|
||||
{
|
||||
int i;
|
||||
|
||||
exynos_sysram_init();
|
||||
|
||||
if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
|
||||
scu_enable(scu_base_addr());
|
||||
|
||||
/*
|
||||
* Write the address of secondary startup into the
|
||||
* system-wide flags register. The boot monitor waits
|
||||
* until it receives a soft interrupt, and then the
|
||||
* secondary CPU branches to this address.
|
||||
*
|
||||
* Try using firmware operation first and fall back to
|
||||
* boot register if it fails.
|
||||
*/
|
||||
for (i = 1; i < max_cpus; ++i) {
|
||||
unsigned long boot_addr;
|
||||
u32 mpidr;
|
||||
u32 core_id;
|
||||
int ret;
|
||||
|
||||
mpidr = cpu_logical_map(i);
|
||||
core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
|
||||
boot_addr = virt_to_phys(exynos4_secondary_startup);
|
||||
|
||||
ret = call_firmware_op(set_cpu_boot_addr, core_id, boot_addr);
|
||||
if (ret && ret != -ENOSYS)
|
||||
break;
|
||||
if (ret == -ENOSYS) {
|
||||
void __iomem *boot_reg = cpu_boot_reg(core_id);
|
||||
|
||||
if (IS_ERR(boot_reg))
|
||||
break;
|
||||
__raw_writel(boot_addr, boot_reg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct smp_operations exynos_smp_ops __initdata = {
|
||||
.smp_init_cpus = exynos_smp_init_cpus,
|
||||
.smp_prepare_cpus = exynos_smp_prepare_cpus,
|
||||
.smp_secondary_init = exynos_secondary_init,
|
||||
.smp_boot_secondary = exynos_boot_secondary,
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
.cpu_die = exynos_cpu_die,
|
||||
#endif
|
||||
};
|
409
arch/arm/mach-exynos/pm.c
Normal file
409
arch/arm/mach-exynos/pm.c
Normal file
|
@ -0,0 +1,409 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2012 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* EXYNOS - Power Management support
|
||||
*
|
||||
* Based on arch/arm/mach-s3c2410/pm.c
|
||||
* Copyright (c) 2006 Simtec Electronics
|
||||
* Ben Dooks <ben@simtec.co.uk>
|
||||
*
|
||||
* 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/init.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/syscore_ops.h>
|
||||
#include <linux/cpu_pm.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/irqchip/arm-gic.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/clk.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/hardware/cache-l2x0.h>
|
||||
#include <asm/smp_scu.h>
|
||||
#include <asm/suspend.h>
|
||||
|
||||
#include <plat/pm-common.h>
|
||||
#include <plat/regs-srom.h>
|
||||
|
||||
#include <mach/map.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "regs-pmu.h"
|
||||
#include "regs-sys.h"
|
||||
|
||||
/**
|
||||
* struct exynos_wkup_irq - Exynos GIC to PMU IRQ mapping
|
||||
* @hwirq: Hardware IRQ signal of the GIC
|
||||
* @mask: Mask in PMU wake-up mask register
|
||||
*/
|
||||
struct exynos_wkup_irq {
|
||||
unsigned int hwirq;
|
||||
u32 mask;
|
||||
};
|
||||
|
||||
static struct sleep_save exynos5_sys_save[] = {
|
||||
SAVE_ITEM(EXYNOS5_SYS_I2C_CFG),
|
||||
};
|
||||
|
||||
static struct sleep_save exynos_core_save[] = {
|
||||
/* SROM side */
|
||||
SAVE_ITEM(S5P_SROM_BW),
|
||||
SAVE_ITEM(S5P_SROM_BC0),
|
||||
SAVE_ITEM(S5P_SROM_BC1),
|
||||
SAVE_ITEM(S5P_SROM_BC2),
|
||||
SAVE_ITEM(S5P_SROM_BC3),
|
||||
};
|
||||
|
||||
/*
|
||||
* GIC wake-up support
|
||||
*/
|
||||
|
||||
static u32 exynos_irqwake_intmask = 0xffffffff;
|
||||
|
||||
static const struct exynos_wkup_irq exynos4_wkup_irq[] = {
|
||||
{ 76, BIT(1) }, /* RTC alarm */
|
||||
{ 77, BIT(2) }, /* RTC tick */
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
static const struct exynos_wkup_irq exynos5250_wkup_irq[] = {
|
||||
{ 75, BIT(1) }, /* RTC alarm */
|
||||
{ 76, BIT(2) }, /* RTC tick */
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
static int exynos_irq_set_wake(struct irq_data *data, unsigned int state)
|
||||
{
|
||||
const struct exynos_wkup_irq *wkup_irq;
|
||||
|
||||
if (soc_is_exynos5250())
|
||||
wkup_irq = exynos5250_wkup_irq;
|
||||
else
|
||||
wkup_irq = exynos4_wkup_irq;
|
||||
|
||||
while (wkup_irq->mask) {
|
||||
if (wkup_irq->hwirq == data->hwirq) {
|
||||
if (!state)
|
||||
exynos_irqwake_intmask |= wkup_irq->mask;
|
||||
else
|
||||
exynos_irqwake_intmask &= ~wkup_irq->mask;
|
||||
return 0;
|
||||
}
|
||||
++wkup_irq;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
#define EXYNOS_BOOT_VECTOR_ADDR (samsung_rev() == EXYNOS4210_REV_1_1 ? \
|
||||
pmu_base_addr + S5P_INFORM7 : \
|
||||
(samsung_rev() == EXYNOS4210_REV_1_0 ? \
|
||||
(sysram_base_addr + 0x24) : \
|
||||
pmu_base_addr + S5P_INFORM0))
|
||||
#define EXYNOS_BOOT_VECTOR_FLAG (samsung_rev() == EXYNOS4210_REV_1_1 ? \
|
||||
pmu_base_addr + S5P_INFORM6 : \
|
||||
(samsung_rev() == EXYNOS4210_REV_1_0 ? \
|
||||
(sysram_base_addr + 0x20) : \
|
||||
pmu_base_addr + S5P_INFORM1))
|
||||
|
||||
#define S5P_CHECK_AFTR 0xFCBA0D10
|
||||
#define S5P_CHECK_SLEEP 0x00000BAD
|
||||
|
||||
/* For Cortex-A9 Diagnostic and Power control register */
|
||||
static unsigned int save_arm_register[2];
|
||||
|
||||
static void exynos_cpu_save_register(void)
|
||||
{
|
||||
unsigned long tmp;
|
||||
|
||||
/* Save Power control register */
|
||||
asm ("mrc p15, 0, %0, c15, c0, 0"
|
||||
: "=r" (tmp) : : "cc");
|
||||
|
||||
save_arm_register[0] = tmp;
|
||||
|
||||
/* Save Diagnostic register */
|
||||
asm ("mrc p15, 0, %0, c15, c0, 1"
|
||||
: "=r" (tmp) : : "cc");
|
||||
|
||||
save_arm_register[1] = tmp;
|
||||
}
|
||||
|
||||
static void exynos_cpu_restore_register(void)
|
||||
{
|
||||
unsigned long tmp;
|
||||
|
||||
/* Restore Power control register */
|
||||
tmp = save_arm_register[0];
|
||||
|
||||
asm volatile ("mcr p15, 0, %0, c15, c0, 0"
|
||||
: : "r" (tmp)
|
||||
: "cc");
|
||||
|
||||
/* Restore Diagnostic register */
|
||||
tmp = save_arm_register[1];
|
||||
|
||||
asm volatile ("mcr p15, 0, %0, c15, c0, 1"
|
||||
: : "r" (tmp)
|
||||
: "cc");
|
||||
}
|
||||
|
||||
static void exynos_pm_central_suspend(void)
|
||||
{
|
||||
unsigned long tmp;
|
||||
|
||||
/* Setting Central Sequence Register for power down mode */
|
||||
tmp = pmu_raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
|
||||
tmp &= ~S5P_CENTRAL_LOWPWR_CFG;
|
||||
pmu_raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
|
||||
}
|
||||
|
||||
static int exynos_pm_central_resume(void)
|
||||
{
|
||||
unsigned long tmp;
|
||||
|
||||
/*
|
||||
* If PMU failed while entering sleep mode, WFI will be
|
||||
* ignored by PMU and then exiting cpu_do_idle().
|
||||
* S5P_CENTRAL_LOWPWR_CFG bit will not be set automatically
|
||||
* in this situation.
|
||||
*/
|
||||
tmp = pmu_raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
|
||||
if (!(tmp & S5P_CENTRAL_LOWPWR_CFG)) {
|
||||
tmp |= S5P_CENTRAL_LOWPWR_CFG;
|
||||
pmu_raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
|
||||
/* clear the wakeup state register */
|
||||
pmu_raw_writel(0x0, S5P_WAKEUP_STAT);
|
||||
/* No need to perform below restore code */
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Ext-GIC nIRQ/nFIQ is the only wakeup source in AFTR */
|
||||
static void exynos_set_wakeupmask(long mask)
|
||||
{
|
||||
pmu_raw_writel(mask, S5P_WAKEUP_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);
|
||||
}
|
||||
|
||||
static int exynos_aftr_finisher(unsigned long flags)
|
||||
{
|
||||
exynos_set_wakeupmask(0x0000ff3e);
|
||||
exynos_cpu_set_boot_vector(S5P_CHECK_AFTR);
|
||||
/* Set value of power down register for aftr mode */
|
||||
exynos_sys_powerdown_conf(SYS_AFTR);
|
||||
cpu_do_idle();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void exynos_enter_aftr(void)
|
||||
{
|
||||
cpu_pm_enter();
|
||||
|
||||
exynos_pm_central_suspend();
|
||||
if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
|
||||
exynos_cpu_save_register();
|
||||
|
||||
cpu_suspend(0, exynos_aftr_finisher);
|
||||
|
||||
if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) {
|
||||
scu_enable(S5P_VA_SCU);
|
||||
exynos_cpu_restore_register();
|
||||
}
|
||||
|
||||
exynos_pm_central_resume();
|
||||
|
||||
cpu_pm_exit();
|
||||
}
|
||||
|
||||
static int exynos_cpu_suspend(unsigned long arg)
|
||||
{
|
||||
#ifdef CONFIG_CACHE_L2X0
|
||||
outer_flush_all();
|
||||
#endif
|
||||
|
||||
if (soc_is_exynos5250())
|
||||
flush_cache_all();
|
||||
|
||||
/* issue the standby signal into the pm unit. */
|
||||
cpu_do_idle();
|
||||
|
||||
pr_info("Failed to suspend the system\n");
|
||||
return 1; /* Aborting suspend */
|
||||
}
|
||||
|
||||
static void exynos_pm_prepare(void)
|
||||
{
|
||||
unsigned int tmp;
|
||||
|
||||
/* Set wake-up mask registers */
|
||||
pmu_raw_writel(exynos_get_eint_wake_mask(), S5P_EINT_WAKEUP_MASK);
|
||||
pmu_raw_writel(exynos_irqwake_intmask & ~(1 << 31), S5P_WAKEUP_MASK);
|
||||
|
||||
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 = pmu_raw_readl(EXYNOS5_JPEG_MEM_OPTION);
|
||||
tmp &= ~EXYNOS5_OPTION_USE_RETENTION;
|
||||
pmu_raw_writel(tmp, EXYNOS5_JPEG_MEM_OPTION);
|
||||
}
|
||||
|
||||
/* 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 int exynos_pm_suspend(void)
|
||||
{
|
||||
unsigned long tmp;
|
||||
|
||||
exynos_pm_central_suspend();
|
||||
|
||||
/* Setting SEQ_OPTION register */
|
||||
|
||||
tmp = (S5P_USE_STANDBY_WFI0 | S5P_USE_STANDBY_WFE0);
|
||||
pmu_raw_writel(tmp, S5P_CENTRAL_SEQ_OPTION);
|
||||
|
||||
if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
|
||||
exynos_cpu_save_register();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void exynos_pm_resume(void)
|
||||
{
|
||||
if (exynos_pm_central_resume())
|
||||
goto early_wakeup;
|
||||
|
||||
if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
|
||||
exynos_cpu_restore_register();
|
||||
|
||||
/* For release retention */
|
||||
|
||||
pmu_raw_writel((1 << 28), S5P_PAD_RET_MAUDIO_OPTION);
|
||||
pmu_raw_writel((1 << 28), S5P_PAD_RET_GPIO_OPTION);
|
||||
pmu_raw_writel((1 << 28), S5P_PAD_RET_UART_OPTION);
|
||||
pmu_raw_writel((1 << 28), S5P_PAD_RET_MMCA_OPTION);
|
||||
pmu_raw_writel((1 << 28), S5P_PAD_RET_MMCB_OPTION);
|
||||
pmu_raw_writel((1 << 28), S5P_PAD_RET_EBIA_OPTION);
|
||||
pmu_raw_writel((1 << 28), S5P_PAD_RET_EBIB_OPTION);
|
||||
|
||||
if (soc_is_exynos5250())
|
||||
s3c_pm_do_restore(exynos5_sys_save,
|
||||
ARRAY_SIZE(exynos5_sys_save));
|
||||
|
||||
s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save));
|
||||
|
||||
if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
|
||||
scu_enable(S5P_VA_SCU);
|
||||
|
||||
early_wakeup:
|
||||
|
||||
/* Clear SLEEP mode set in INFORM1 */
|
||||
pmu_raw_writel(0x0, S5P_INFORM1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static struct syscore_ops exynos_pm_syscore_ops = {
|
||||
.suspend = exynos_pm_suspend,
|
||||
.resume = exynos_pm_resume,
|
||||
};
|
||||
|
||||
/*
|
||||
* Suspend Ops
|
||||
*/
|
||||
|
||||
static int exynos_suspend_enter(suspend_state_t state)
|
||||
{
|
||||
int ret;
|
||||
|
||||
s3c_pm_debug_init();
|
||||
|
||||
S3C_PMDBG("%s: suspending the system...\n", __func__);
|
||||
|
||||
S3C_PMDBG("%s: wakeup masks: %08x,%08x\n", __func__,
|
||||
exynos_irqwake_intmask, exynos_get_eint_wake_mask());
|
||||
|
||||
if (exynos_irqwake_intmask == -1U
|
||||
&& exynos_get_eint_wake_mask() == -1U) {
|
||||
pr_err("%s: No wake-up sources!\n", __func__);
|
||||
pr_err("%s: Aborting sleep\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
s3c_pm_save_uarts();
|
||||
exynos_pm_prepare();
|
||||
flush_cache_all();
|
||||
s3c_pm_check_store();
|
||||
|
||||
ret = cpu_suspend(0, exynos_cpu_suspend);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
s3c_pm_restore_uarts();
|
||||
|
||||
S3C_PMDBG("%s: wakeup stat: %08x\n", __func__,
|
||||
pmu_raw_readl(S5P_WAKEUP_STAT));
|
||||
|
||||
s3c_pm_check_restore();
|
||||
|
||||
S3C_PMDBG("%s: resuming the system...\n", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int exynos_suspend_prepare(void)
|
||||
{
|
||||
s3c_pm_check_prepare();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void exynos_suspend_finish(void)
|
||||
{
|
||||
s3c_pm_check_cleanup();
|
||||
}
|
||||
|
||||
static const struct platform_suspend_ops exynos_suspend_ops = {
|
||||
.enter = exynos_suspend_enter,
|
||||
.prepare = exynos_suspend_prepare,
|
||||
.finish = exynos_suspend_finish,
|
||||
.valid = suspend_valid_only_mem,
|
||||
};
|
||||
|
||||
void __init exynos_pm_init(void)
|
||||
{
|
||||
u32 tmp;
|
||||
|
||||
/* Platform-specific GIC callback */
|
||||
gic_arch_extn.irq_set_wake = exynos_irq_set_wake;
|
||||
|
||||
/* All wakeup disable */
|
||||
tmp = pmu_raw_readl(S5P_WAKEUP_MASK);
|
||||
tmp |= ((0xFF << 8) | (0x1F << 1));
|
||||
pmu_raw_writel(tmp, S5P_WAKEUP_MASK);
|
||||
|
||||
register_syscore_ops(&exynos_pm_syscore_ops);
|
||||
suspend_set_ops(&exynos_suspend_ops);
|
||||
}
|
166
arch/arm/mach-exynos/pm_domains.c
Normal file
166
arch/arm/mach-exynos/pm_domains.c
Normal file
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
* Exynos Generic power domain support.
|
||||
*
|
||||
* Copyright (c) 2012 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* Implementation of Exynos specific power domain control which is used in
|
||||
* conjunction with runtime-pm. Support for both device-tree and non-device-tree
|
||||
* based power domain support is included.
|
||||
*
|
||||
* 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/io.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#define INT_LOCAL_PWR_EN 0x7
|
||||
#define MAX_CLK_PER_DOMAIN 4
|
||||
|
||||
/*
|
||||
* Exynos specific wrapper around the generic power domain
|
||||
*/
|
||||
struct exynos_pm_domain {
|
||||
void __iomem *base;
|
||||
char const *name;
|
||||
bool is_off;
|
||||
struct generic_pm_domain pd;
|
||||
struct clk *oscclk;
|
||||
struct clk *clk[MAX_CLK_PER_DOMAIN];
|
||||
struct clk *pclk[MAX_CLK_PER_DOMAIN];
|
||||
};
|
||||
|
||||
static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on)
|
||||
{
|
||||
struct exynos_pm_domain *pd;
|
||||
void __iomem *base;
|
||||
u32 timeout, pwr;
|
||||
char *op;
|
||||
|
||||
pd = container_of(domain, struct exynos_pm_domain, pd);
|
||||
base = pd->base;
|
||||
|
||||
/* Set oscclk before powering off a domain*/
|
||||
if (!power_on) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
|
||||
if (IS_ERR(pd->clk[i]))
|
||||
break;
|
||||
if (clk_set_parent(pd->clk[i], pd->oscclk))
|
||||
pr_err("%s: error setting oscclk as parent to clock %d\n",
|
||||
pd->name, i);
|
||||
}
|
||||
}
|
||||
|
||||
pwr = power_on ? INT_LOCAL_PWR_EN : 0;
|
||||
__raw_writel(pwr, base);
|
||||
|
||||
/* Wait max 1ms */
|
||||
timeout = 10;
|
||||
|
||||
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);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
timeout--;
|
||||
cpu_relax();
|
||||
usleep_range(80, 100);
|
||||
}
|
||||
|
||||
/* Restore clocks after powering on a domain*/
|
||||
if (power_on) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
|
||||
if (IS_ERR(pd->clk[i]))
|
||||
break;
|
||||
if (clk_set_parent(pd->clk[i], pd->pclk[i]))
|
||||
pr_err("%s: error setting parent to clock%d\n",
|
||||
pd->name, i);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int exynos_pd_power_on(struct generic_pm_domain *domain)
|
||||
{
|
||||
return exynos_pd_power(domain, true);
|
||||
}
|
||||
|
||||
static int exynos_pd_power_off(struct generic_pm_domain *domain)
|
||||
{
|
||||
return exynos_pd_power(domain, false);
|
||||
}
|
||||
|
||||
static __init int exynos4_pm_init_power_domain(void)
|
||||
{
|
||||
struct platform_device *pdev;
|
||||
struct device_node *np;
|
||||
|
||||
for_each_compatible_node(np, NULL, "samsung,exynos4210-pd") {
|
||||
struct exynos_pm_domain *pd;
|
||||
int on, i;
|
||||
struct device *dev;
|
||||
|
||||
pdev = of_find_device_by_node(np);
|
||||
dev = &pdev->dev;
|
||||
|
||||
pd = kzalloc(sizeof(*pd), GFP_KERNEL);
|
||||
if (!pd) {
|
||||
pr_err("%s: failed to allocate memory for domain\n",
|
||||
__func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pd->pd.name = kstrdup(np->name, GFP_KERNEL);
|
||||
pd->name = pd->pd.name;
|
||||
pd->base = of_iomap(np, 0);
|
||||
pd->pd.power_off = exynos_pd_power_off;
|
||||
pd->pd.power_on = exynos_pd_power_on;
|
||||
|
||||
pd->oscclk = clk_get(dev, "oscclk");
|
||||
if (IS_ERR(pd->oscclk))
|
||||
goto no_clk;
|
||||
|
||||
for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
|
||||
char clk_name[8];
|
||||
|
||||
snprintf(clk_name, sizeof(clk_name), "clk%d", i);
|
||||
pd->clk[i] = clk_get(dev, clk_name);
|
||||
if (IS_ERR(pd->clk[i]))
|
||||
break;
|
||||
snprintf(clk_name, sizeof(clk_name), "pclk%d", i);
|
||||
pd->pclk[i] = clk_get(dev, clk_name);
|
||||
if (IS_ERR(pd->pclk[i])) {
|
||||
clk_put(pd->clk[i]);
|
||||
pd->clk[i] = ERR_PTR(-EINVAL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_ERR(pd->clk[0]))
|
||||
clk_put(pd->oscclk);
|
||||
|
||||
no_clk:
|
||||
on = __raw_readl(pd->base + 0x4) & INT_LOCAL_PWR_EN;
|
||||
|
||||
pm_genpd_init(&pd->pd, NULL, !on);
|
||||
of_genpd_add_provider_simple(np, &pd->pd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(exynos4_pm_init_power_domain);
|
422
arch/arm/mach-exynos/pmu.c
Normal file
422
arch/arm/mach-exynos/pmu.c
Normal file
|
@ -0,0 +1,422 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2012 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com/
|
||||
*
|
||||
* EXYNOS - CPU PMU(Power Management Unit) 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.
|
||||
*/
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "regs-pmu.h"
|
||||
|
||||
static const struct exynos_pmu_conf *exynos_pmu_config;
|
||||
|
||||
static const struct exynos_pmu_conf exynos4210_pmu_config[] = {
|
||||
/* { .offset = offset, .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 } },
|
||||
{ S5P_ARM_CORE1_LOWPWR, { 0x0, 0x0, 0x2 } },
|
||||
{ S5P_DIS_IRQ_CORE1, { 0x0, 0x0, 0x0 } },
|
||||
{ S5P_DIS_IRQ_CENTRAL1, { 0x0, 0x0, 0x0 } },
|
||||
{ S5P_ARM_COMMON_LOWPWR, { 0x0, 0x0, 0x2 } },
|
||||
{ S5P_L2_0_LOWPWR, { 0x2, 0x2, 0x3 } },
|
||||
{ S5P_L2_1_LOWPWR, { 0x2, 0x2, 0x3 } },
|
||||
{ S5P_CMU_ACLKSTOP_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_CMU_SCLKSTOP_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_CMU_RESET_LOWPWR, { 0x1, 0x1, 0x0 } },
|
||||
{ S5P_APLL_SYSCLK_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_MPLL_SYSCLK_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_VPLL_SYSCLK_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_EPLL_SYSCLK_LOWPWR, { 0x1, 0x1, 0x0 } },
|
||||
{ S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR, { 0x1, 0x1, 0x0 } },
|
||||
{ S5P_CMU_RESET_GPSALIVE_LOWPWR, { 0x1, 0x1, 0x0 } },
|
||||
{ S5P_CMU_CLKSTOP_CAM_LOWPWR, { 0x1, 0x1, 0x0 } },
|
||||
{ S5P_CMU_CLKSTOP_TV_LOWPWR, { 0x1, 0x1, 0x0 } },
|
||||
{ S5P_CMU_CLKSTOP_MFC_LOWPWR, { 0x1, 0x1, 0x0 } },
|
||||
{ S5P_CMU_CLKSTOP_G3D_LOWPWR, { 0x1, 0x1, 0x0 } },
|
||||
{ S5P_CMU_CLKSTOP_LCD0_LOWPWR, { 0x1, 0x1, 0x0 } },
|
||||
{ S5P_CMU_CLKSTOP_LCD1_LOWPWR, { 0x1, 0x1, 0x0 } },
|
||||
{ S5P_CMU_CLKSTOP_MAUDIO_LOWPWR, { 0x1, 0x1, 0x0 } },
|
||||
{ S5P_CMU_CLKSTOP_GPS_LOWPWR, { 0x1, 0x1, 0x0 } },
|
||||
{ S5P_CMU_RESET_CAM_LOWPWR, { 0x1, 0x1, 0x0 } },
|
||||
{ S5P_CMU_RESET_TV_LOWPWR, { 0x1, 0x1, 0x0 } },
|
||||
{ S5P_CMU_RESET_MFC_LOWPWR, { 0x1, 0x1, 0x0 } },
|
||||
{ S5P_CMU_RESET_G3D_LOWPWR, { 0x1, 0x1, 0x0 } },
|
||||
{ S5P_CMU_RESET_LCD0_LOWPWR, { 0x1, 0x1, 0x0 } },
|
||||
{ S5P_CMU_RESET_LCD1_LOWPWR, { 0x1, 0x1, 0x0 } },
|
||||
{ S5P_CMU_RESET_MAUDIO_LOWPWR, { 0x1, 0x1, 0x0 } },
|
||||
{ S5P_CMU_RESET_GPS_LOWPWR, { 0x1, 0x1, 0x0 } },
|
||||
{ S5P_TOP_BUS_LOWPWR, { 0x3, 0x0, 0x0 } },
|
||||
{ S5P_TOP_RETENTION_LOWPWR, { 0x1, 0x0, 0x1 } },
|
||||
{ S5P_TOP_PWR_LOWPWR, { 0x3, 0x0, 0x3 } },
|
||||
{ S5P_LOGIC_RESET_LOWPWR, { 0x1, 0x1, 0x0 } },
|
||||
{ S5P_ONENAND_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
|
||||
{ S5P_MODIMIF_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
|
||||
{ S5P_G2D_ACP_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
|
||||
{ S5P_USBOTG_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
|
||||
{ S5P_HSMMC_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
|
||||
{ S5P_CSSYS_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
|
||||
{ S5P_SECSS_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
|
||||
{ S5P_PCIE_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
|
||||
{ S5P_SATA_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
|
||||
{ S5P_PAD_RETENTION_DRAM_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_PAD_RETENTION_MAUDIO_LOWPWR, { 0x1, 0x1, 0x0 } },
|
||||
{ S5P_PAD_RETENTION_GPIO_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_PAD_RETENTION_UART_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_PAD_RETENTION_MMCA_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_PAD_RETENTION_MMCB_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_PAD_RETENTION_EBIA_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_PAD_RETENTION_EBIB_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_PAD_RETENTION_ISOLATION_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_PAD_RETENTION_ALV_SEL_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_XUSBXTI_LOWPWR, { 0x1, 0x1, 0x0 } },
|
||||
{ S5P_XXTI_LOWPWR, { 0x1, 0x1, 0x0 } },
|
||||
{ S5P_EXT_REGULATOR_LOWPWR, { 0x1, 0x1, 0x0 } },
|
||||
{ S5P_GPIO_MODE_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_GPIO_MODE_MAUDIO_LOWPWR, { 0x1, 0x1, 0x0 } },
|
||||
{ S5P_CAM_LOWPWR, { 0x7, 0x0, 0x0 } },
|
||||
{ S5P_TV_LOWPWR, { 0x7, 0x0, 0x0 } },
|
||||
{ S5P_MFC_LOWPWR, { 0x7, 0x0, 0x0 } },
|
||||
{ S5P_G3D_LOWPWR, { 0x7, 0x0, 0x0 } },
|
||||
{ S5P_LCD0_LOWPWR, { 0x7, 0x0, 0x0 } },
|
||||
{ S5P_LCD1_LOWPWR, { 0x7, 0x0, 0x0 } },
|
||||
{ S5P_MAUDIO_LOWPWR, { 0x7, 0x7, 0x0 } },
|
||||
{ S5P_GPS_LOWPWR, { 0x7, 0x0, 0x0 } },
|
||||
{ S5P_GPS_ALIVE_LOWPWR, { 0x7, 0x0, 0x0 } },
|
||||
{ PMU_TABLE_END,},
|
||||
};
|
||||
|
||||
static const struct exynos_pmu_conf exynos4x12_pmu_config[] = {
|
||||
{ S5P_ARM_CORE0_LOWPWR, { 0x0, 0x0, 0x2 } },
|
||||
{ S5P_DIS_IRQ_CORE0, { 0x0, 0x0, 0x0 } },
|
||||
{ S5P_DIS_IRQ_CENTRAL0, { 0x0, 0x0, 0x0 } },
|
||||
{ S5P_ARM_CORE1_LOWPWR, { 0x0, 0x0, 0x2 } },
|
||||
{ S5P_DIS_IRQ_CORE1, { 0x0, 0x0, 0x0 } },
|
||||
{ S5P_DIS_IRQ_CENTRAL1, { 0x0, 0x0, 0x0 } },
|
||||
{ S5P_ISP_ARM_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_DIS_IRQ_ISP_ARM_LOCAL_LOWPWR, { 0x0, 0x0, 0x0 } },
|
||||
{ S5P_DIS_IRQ_ISP_ARM_CENTRAL_LOWPWR, { 0x0, 0x0, 0x0 } },
|
||||
{ S5P_ARM_COMMON_LOWPWR, { 0x0, 0x0, 0x2 } },
|
||||
{ S5P_L2_0_LOWPWR, { 0x0, 0x0, 0x3 } },
|
||||
/* XXX_OPTION register should be set other field */
|
||||
{ S5P_ARM_L2_0_OPTION, { 0x10, 0x10, 0x0 } },
|
||||
{ S5P_L2_1_LOWPWR, { 0x0, 0x0, 0x3 } },
|
||||
{ S5P_ARM_L2_1_OPTION, { 0x10, 0x10, 0x0 } },
|
||||
{ S5P_CMU_ACLKSTOP_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_CMU_SCLKSTOP_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_CMU_RESET_LOWPWR, { 0x1, 0x1, 0x0 } },
|
||||
{ S5P_DRAM_FREQ_DOWN_LOWPWR, { 0x1, 0x1, 0x1 } },
|
||||
{ S5P_DDRPHY_DLLOFF_LOWPWR, { 0x1, 0x1, 0x1 } },
|
||||
{ S5P_LPDDR_PHY_DLL_LOCK_LOWPWR, { 0x1, 0x1, 0x1 } },
|
||||
{ S5P_CMU_ACLKSTOP_COREBLK_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_CMU_SCLKSTOP_COREBLK_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_CMU_RESET_COREBLK_LOWPWR, { 0x1, 0x1, 0x0 } },
|
||||
{ S5P_APLL_SYSCLK_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_MPLL_SYSCLK_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_VPLL_SYSCLK_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_EPLL_SYSCLK_LOWPWR, { 0x1, 0x1, 0x0 } },
|
||||
{ S5P_MPLLUSER_SYSCLK_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_CMU_RESET_GPSALIVE_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_CMU_CLKSTOP_CAM_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_CMU_CLKSTOP_TV_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_CMU_CLKSTOP_MFC_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_CMU_CLKSTOP_G3D_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_CMU_CLKSTOP_LCD0_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_CMU_CLKSTOP_ISP_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_CMU_CLKSTOP_MAUDIO_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_CMU_CLKSTOP_GPS_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_CMU_RESET_CAM_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_CMU_RESET_TV_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_CMU_RESET_MFC_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_CMU_RESET_G3D_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_CMU_RESET_LCD0_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_CMU_RESET_ISP_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_CMU_RESET_MAUDIO_LOWPWR, { 0x1, 0x1, 0x0 } },
|
||||
{ S5P_CMU_RESET_GPS_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_TOP_BUS_LOWPWR, { 0x3, 0x0, 0x0 } },
|
||||
{ S5P_TOP_RETENTION_LOWPWR, { 0x1, 0x0, 0x1 } },
|
||||
{ S5P_TOP_PWR_LOWPWR, { 0x3, 0x0, 0x3 } },
|
||||
{ S5P_TOP_BUS_COREBLK_LOWPWR, { 0x3, 0x0, 0x0 } },
|
||||
{ S5P_TOP_RETENTION_COREBLK_LOWPWR, { 0x1, 0x0, 0x1 } },
|
||||
{ S5P_TOP_PWR_COREBLK_LOWPWR, { 0x3, 0x0, 0x3 } },
|
||||
{ S5P_LOGIC_RESET_LOWPWR, { 0x1, 0x1, 0x0 } },
|
||||
{ S5P_OSCCLK_GATE_LOWPWR, { 0x1, 0x0, 0x1 } },
|
||||
{ S5P_LOGIC_RESET_COREBLK_LOWPWR, { 0x1, 0x1, 0x0 } },
|
||||
{ S5P_OSCCLK_GATE_COREBLK_LOWPWR, { 0x1, 0x0, 0x1 } },
|
||||
{ S5P_ONENAND_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
|
||||
{ S5P_ONENAND_MEM_OPTION, { 0x10, 0x10, 0x0 } },
|
||||
{ S5P_HSI_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
|
||||
{ S5P_HSI_MEM_OPTION, { 0x10, 0x10, 0x0 } },
|
||||
{ S5P_G2D_ACP_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
|
||||
{ S5P_G2D_ACP_MEM_OPTION, { 0x10, 0x10, 0x0 } },
|
||||
{ S5P_USBOTG_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
|
||||
{ S5P_USBOTG_MEM_OPTION, { 0x10, 0x10, 0x0 } },
|
||||
{ S5P_HSMMC_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
|
||||
{ S5P_HSMMC_MEM_OPTION, { 0x10, 0x10, 0x0 } },
|
||||
{ S5P_CSSYS_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
|
||||
{ S5P_CSSYS_MEM_OPTION, { 0x10, 0x10, 0x0 } },
|
||||
{ S5P_SECSS_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
|
||||
{ S5P_SECSS_MEM_OPTION, { 0x10, 0x10, 0x0 } },
|
||||
{ S5P_ROTATOR_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
|
||||
{ S5P_ROTATOR_MEM_OPTION, { 0x10, 0x10, 0x0 } },
|
||||
{ S5P_PAD_RETENTION_DRAM_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_PAD_RETENTION_MAUDIO_LOWPWR, { 0x1, 0x1, 0x0 } },
|
||||
{ S5P_PAD_RETENTION_GPIO_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_PAD_RETENTION_UART_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_PAD_RETENTION_MMCA_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_PAD_RETENTION_MMCB_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_PAD_RETENTION_EBIA_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_PAD_RETENTION_EBIB_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_PAD_RETENTION_GPIO_COREBLK_LOWPWR,{ 0x1, 0x0, 0x0 } },
|
||||
{ S5P_PAD_RETENTION_ISOLATION_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_PAD_ISOLATION_COREBLK_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_PAD_RETENTION_ALV_SEL_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_XUSBXTI_LOWPWR, { 0x1, 0x1, 0x0 } },
|
||||
{ S5P_XXTI_LOWPWR, { 0x1, 0x1, 0x0 } },
|
||||
{ S5P_EXT_REGULATOR_LOWPWR, { 0x1, 0x1, 0x0 } },
|
||||
{ S5P_GPIO_MODE_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_GPIO_MODE_COREBLK_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_GPIO_MODE_MAUDIO_LOWPWR, { 0x1, 0x1, 0x0 } },
|
||||
{ S5P_TOP_ASB_RESET_LOWPWR, { 0x1, 0x1, 0x1 } },
|
||||
{ S5P_TOP_ASB_ISOLATION_LOWPWR, { 0x1, 0x0, 0x1 } },
|
||||
{ S5P_CAM_LOWPWR, { 0x7, 0x0, 0x0 } },
|
||||
{ S5P_TV_LOWPWR, { 0x7, 0x0, 0x0 } },
|
||||
{ S5P_MFC_LOWPWR, { 0x7, 0x0, 0x0 } },
|
||||
{ S5P_G3D_LOWPWR, { 0x7, 0x0, 0x0 } },
|
||||
{ S5P_LCD0_LOWPWR, { 0x7, 0x0, 0x0 } },
|
||||
{ S5P_ISP_LOWPWR, { 0x7, 0x0, 0x0 } },
|
||||
{ S5P_MAUDIO_LOWPWR, { 0x7, 0x7, 0x0 } },
|
||||
{ S5P_GPS_LOWPWR, { 0x7, 0x0, 0x0 } },
|
||||
{ S5P_GPS_ALIVE_LOWPWR, { 0x7, 0x0, 0x0 } },
|
||||
{ S5P_CMU_SYSCLK_ISP_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_CMU_SYSCLK_GPS_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ PMU_TABLE_END,},
|
||||
};
|
||||
|
||||
static const struct exynos_pmu_conf exynos4412_pmu_config[] = {
|
||||
{ S5P_ARM_CORE2_LOWPWR, { 0x0, 0x0, 0x2 } },
|
||||
{ S5P_DIS_IRQ_CORE2, { 0x0, 0x0, 0x0 } },
|
||||
{ S5P_DIS_IRQ_CENTRAL2, { 0x0, 0x0, 0x0 } },
|
||||
{ S5P_ARM_CORE3_LOWPWR, { 0x0, 0x0, 0x2 } },
|
||||
{ S5P_DIS_IRQ_CORE3, { 0x0, 0x0, 0x0 } },
|
||||
{ S5P_DIS_IRQ_CENTRAL3, { 0x0, 0x0, 0x0 } },
|
||||
{ PMU_TABLE_END,},
|
||||
};
|
||||
|
||||
static const struct exynos_pmu_conf exynos5250_pmu_config[] = {
|
||||
/* { .offset = offset, .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} },
|
||||
{ EXYNOS5_ARM_CORE1_SYS_PWR_REG, { 0x0, 0x0, 0x2} },
|
||||
{ EXYNOS5_DIS_IRQ_ARM_CORE1_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5_DIS_IRQ_ARM_CORE1_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5_FSYS_ARM_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_DIS_IRQ_FSYS_ARM_CENTRAL_SYS_PWR_REG, { 0x1, 0x1, 0x1} },
|
||||
{ EXYNOS5_ISP_ARM_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_DIS_IRQ_ISP_ARM_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5_DIS_IRQ_ISP_ARM_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
|
||||
{ EXYNOS5_ARM_COMMON_SYS_PWR_REG, { 0x0, 0x0, 0x2} },
|
||||
{ EXYNOS5_ARM_L2_SYS_PWR_REG, { 0x3, 0x3, 0x3} },
|
||||
{ EXYNOS5_ARM_L2_OPTION, { 0x10, 0x10, 0x0 } },
|
||||
{ EXYNOS5_CMU_ACLKSTOP_SYS_PWR_REG, { 0x1, 0x0, 0x1} },
|
||||
{ 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, 0x1} },
|
||||
{ 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, 0x1, 0x1} },
|
||||
{ EXYNOS5_DDRPHY_DLLOFF_SYS_PWR_REG, { 0x1, 0x1, 0x1} },
|
||||
{ EXYNOS5_DDRPHY_DLLLOCK_SYS_PWR_REG, { 0x1, 0x1, 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} },
|
||||
{ EXYNOS5_MPLLUSER_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_BPLLUSER_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_TOP_BUS_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
|
||||
{ EXYNOS5_TOP_RETENTION_SYS_PWR_REG, { 0x1, 0x0, 0x1} },
|
||||
{ EXYNOS5_TOP_PWR_SYS_PWR_REG, { 0x3, 0x0, 0x3} },
|
||||
{ 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, 0x3} },
|
||||
{ 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, 0x1, 0x0} },
|
||||
{ EXYNOS5_OSCCLK_GATE_SYSMEM_SYS_PWR_REG, { 0x1, 0x0, 0x1} },
|
||||
{ EXYNOS5_USBOTG_MEM_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
|
||||
{ EXYNOS5_G2D_MEM_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
|
||||
{ EXYNOS5_USBDRD_MEM_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
|
||||
{ EXYNOS5_SDMMC_MEM_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
|
||||
{ EXYNOS5_CSSYS_MEM_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
|
||||
{ EXYNOS5_SECSS_MEM_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
|
||||
{ EXYNOS5_ROTATOR_MEM_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
|
||||
{ EXYNOS5_INTRAM_MEM_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
|
||||
{ EXYNOS5_INTROM_MEM_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
|
||||
{ EXYNOS5_JPEG_MEM_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
|
||||
{ EXYNOS5_HSI_MEM_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
|
||||
{ EXYNOS5_MCUIOP_MEM_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
|
||||
{ EXYNOS5_SATA_MEM_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
|
||||
{ EXYNOS5_PAD_RETENTION_DRAM_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_PAD_RETENTION_MAU_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
|
||||
{ EXYNOS5_PAD_RETENTION_GPIO_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_PAD_RETENTION_UART_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_PAD_RETENTION_MMCA_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_PAD_RETENTION_MMCB_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_PAD_RETENTION_EBIA_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_PAD_RETENTION_EBIB_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_PAD_RETENTION_SPI_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_PAD_RETENTION_GPIO_SYSMEM_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_PAD_ISOLATION_SYS_PWR_REG, { 0x1, 0x0, 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, 0x1} },
|
||||
{ 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, 0x0, 0x0} },
|
||||
{ EXYNOS5_GPIO_MODE_MAU_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
|
||||
{ EXYNOS5_TOP_ASB_RESET_SYS_PWR_REG, { 0x1, 0x1, 0x1} },
|
||||
{ EXYNOS5_TOP_ASB_ISOLATION_SYS_PWR_REG, { 0x1, 0x0, 0x1} },
|
||||
{ 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} },
|
||||
{ EXYNOS5_DISP1_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
|
||||
{ EXYNOS5_MAU_SYS_PWR_REG, { 0x7, 0x7, 0x0} },
|
||||
{ EXYNOS5_CMU_CLKSTOP_GSCL_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_CMU_CLKSTOP_ISP_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_CMU_CLKSTOP_MFC_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_CMU_CLKSTOP_G3D_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_CMU_CLKSTOP_DISP1_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_CMU_CLKSTOP_MAU_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
|
||||
{ EXYNOS5_CMU_SYSCLK_GSCL_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_CMU_SYSCLK_ISP_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_CMU_SYSCLK_MFC_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_CMU_SYSCLK_G3D_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_CMU_SYSCLK_DISP1_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_CMU_SYSCLK_MAU_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
|
||||
{ EXYNOS5_CMU_RESET_GSCL_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_CMU_RESET_ISP_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_CMU_RESET_MFC_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_CMU_RESET_G3D_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_CMU_RESET_DISP1_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
|
||||
{ EXYNOS5_CMU_RESET_MAU_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
|
||||
{ PMU_TABLE_END,},
|
||||
};
|
||||
|
||||
static unsigned int const exynos5_list_both_cnt_feed[] = {
|
||||
EXYNOS5_ARM_CORE0_OPTION,
|
||||
EXYNOS5_ARM_CORE1_OPTION,
|
||||
EXYNOS5_ARM_COMMON_OPTION,
|
||||
EXYNOS5_GSCL_OPTION,
|
||||
EXYNOS5_ISP_OPTION,
|
||||
EXYNOS5_MFC_OPTION,
|
||||
EXYNOS5_G3D_OPTION,
|
||||
EXYNOS5_DISP1_OPTION,
|
||||
EXYNOS5_MAU_OPTION,
|
||||
EXYNOS5_TOP_PWR_OPTION,
|
||||
EXYNOS5_TOP_PWR_SYSMEM_OPTION,
|
||||
};
|
||||
|
||||
static unsigned int const exynos5_list_diable_wfi_wfe[] = {
|
||||
EXYNOS5_ARM_CORE1_OPTION,
|
||||
EXYNOS5_FSYS_ARM_OPTION,
|
||||
EXYNOS5_ISP_ARM_OPTION,
|
||||
};
|
||||
|
||||
static void exynos5_init_pmu(void)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int tmp;
|
||||
|
||||
/*
|
||||
* Enable both SC_FEEDBACK and SC_COUNTER
|
||||
*/
|
||||
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);
|
||||
pmu_raw_writel(tmp, exynos5_list_both_cnt_feed[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
* SKIP_DEACTIVATE_ACEACP_IN_PWDN_BITFIELD Enable
|
||||
*/
|
||||
tmp = pmu_raw_readl(EXYNOS5_ARM_COMMON_OPTION);
|
||||
tmp |= EXYNOS5_SKIP_DEACTIVATE_ACEACP_IN_PWDN;
|
||||
pmu_raw_writel(tmp, EXYNOS5_ARM_COMMON_OPTION);
|
||||
|
||||
/*
|
||||
* 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]);
|
||||
tmp &= ~(EXYNOS5_OPTION_USE_STANDBYWFE |
|
||||
EXYNOS5_OPTION_USE_STANDBYWFI);
|
||||
pmu_raw_writel(tmp, exynos5_list_diable_wfi_wfe[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void exynos_sys_powerdown_conf(enum sys_powerdown mode)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (soc_is_exynos5250())
|
||||
exynos5_init_pmu();
|
||||
|
||||
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 (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);
|
||||
}
|
||||
}
|
||||
|
||||
static int __init exynos_pmu_init(void)
|
||||
{
|
||||
unsigned int value;
|
||||
|
||||
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);
|
329
arch/arm/mach-exynos/regs-pmu.h
Normal file
329
arch/arm/mach-exynos/regs-pmu.h
Normal file
|
@ -0,0 +1,329 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2012 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* EXYNOS - Power management unit 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_PMU_H
|
||||
#define __ASM_ARCH_REGS_PMU_H __FILE__
|
||||
|
||||
#define S5P_CENTRAL_SEQ_CONFIGURATION 0x0200
|
||||
|
||||
#define S5P_CENTRAL_LOWPWR_CFG (1 << 16)
|
||||
|
||||
#define S5P_CENTRAL_SEQ_OPTION 0x0208
|
||||
|
||||
#define S5P_USE_STANDBY_WFI0 (1 << 16)
|
||||
#define S5P_USE_STANDBY_WFE0 (1 << 24)
|
||||
|
||||
#define EXYNOS_SWRESET 0x0400
|
||||
#define EXYNOS5440_SWRESET 0x00C4
|
||||
|
||||
#define S5P_WAKEUP_STAT 0x0600
|
||||
#define S5P_EINT_WAKEUP_MASK 0x0604
|
||||
#define S5P_WAKEUP_MASK 0x0608
|
||||
|
||||
#define S5P_INFORM0 0x0800
|
||||
#define S5P_INFORM1 0x0804
|
||||
#define S5P_INFORM5 0x0814
|
||||
#define S5P_INFORM6 0x0818
|
||||
#define S5P_INFORM7 0x081C
|
||||
#define S5P_PMU_SPARE3 0x090C
|
||||
|
||||
#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 EXYNOS_ARM_CORE0_CONFIGURATION 0x2000
|
||||
#define EXYNOS_ARM_CORE_CONFIGURATION(_nr) \
|
||||
(EXYNOS_ARM_CORE0_CONFIGURATION + (0x80 * (_nr)))
|
||||
#define EXYNOS_ARM_CORE_STATUS(_nr) \
|
||||
(EXYNOS_ARM_CORE_CONFIGURATION(_nr) + 0x4)
|
||||
|
||||
#define EXYNOS_ARM_COMMON_CONFIGURATION 0x2500
|
||||
#define EXYNOS_COMMON_CONFIGURATION(_nr) \
|
||||
(EXYNOS_ARM_COMMON_CONFIGURATION + (0x80 * (_nr)))
|
||||
#define EXYNOS_COMMON_STATUS(_nr) \
|
||||
(EXYNOS_COMMON_CONFIGURATION(_nr) + 0x4)
|
||||
#define EXYNOS_COMMON_OPTION(_nr) \
|
||||
(EXYNOS_COMMON_CONFIGURATION(_nr) + 0x8)
|
||||
|
||||
#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 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 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 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 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 0x0408
|
||||
#define EXYNOS5_MASK_WDTRESET_REQUEST 0x040C
|
||||
|
||||
#define EXYNOS5_SYS_WDTRESET (1 << 20)
|
||||
|
||||
#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 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)
|
||||
|
||||
#define EXYNOS5_SKIP_DEACTIVATE_ACEACP_IN_PWDN (1 << 7)
|
||||
|
||||
#define EXYNOS5_OPTION_USE_STANDBYWFE (1 << 24)
|
||||
#define EXYNOS5_OPTION_USE_STANDBYWFI (1 << 16)
|
||||
|
||||
#define EXYNOS5_OPTION_USE_RETENTION (1 << 4)
|
||||
|
||||
#define EXYNOS5420_SWRESET_KFC_SEL 0x3
|
||||
|
||||
#include <asm/cputype.h>
|
||||
#define MAX_CPUS_IN_CLUSTER 4
|
||||
|
||||
static inline unsigned int exynos_pmu_cpunr(unsigned int mpidr)
|
||||
{
|
||||
return ((MPIDR_AFFINITY_LEVEL(mpidr, 1) * MAX_CPUS_IN_CLUSTER)
|
||||
+ MPIDR_AFFINITY_LEVEL(mpidr, 0));
|
||||
}
|
||||
|
||||
#endif /* __ASM_ARCH_REGS_PMU_H */
|
22
arch/arm/mach-exynos/regs-sys.h
Normal file
22
arch/arm/mach-exynos/regs-sys.h
Normal file
|
@ -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 */
|
57
arch/arm/mach-exynos/sleep.S
Normal file
57
arch/arm/mach-exynos/sleep.S
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* Exynos low-level resume code
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
|
||||
#define CPU_MASK 0xff0ffff0
|
||||
#define CPU_CORTEX_A9 0x410fc090
|
||||
|
||||
/*
|
||||
* The following code is located into the .data section. This is to
|
||||
* allow l2x0_regs_phys to be accessed with a relative load while we
|
||||
* can't rely on any MMU translation. We could have put l2x0_regs_phys
|
||||
* in the .text section as well, but some setups might insist on it to
|
||||
* be truly read-only. (Reference from: arch/arm/kernel/sleep.S)
|
||||
*/
|
||||
.data
|
||||
.align
|
||||
|
||||
/*
|
||||
* sleep magic, to allow the bootloader to check for an valid
|
||||
* image to resume to. Must be the first word before the
|
||||
* exynos_cpu_resume entry.
|
||||
*/
|
||||
|
||||
.word 0x2bedf00d
|
||||
|
||||
/*
|
||||
* exynos_cpu_resume
|
||||
*
|
||||
* resume code entry for bootloader to call
|
||||
*/
|
||||
|
||||
ENTRY(exynos_cpu_resume)
|
||||
#ifdef CONFIG_CACHE_L2X0
|
||||
mrc p15, 0, r0, c0, c0, 0
|
||||
ldr r1, =CPU_MASK
|
||||
and r0, r0, r1
|
||||
ldr r1, =CPU_CORTEX_A9
|
||||
cmp r0, r1
|
||||
bleq l2c310_early_resume
|
||||
#endif
|
||||
b cpu_resume
|
||||
ENDPROC(exynos_cpu_resume)
|
31
arch/arm/mach-exynos/smc.h
Normal file
31
arch/arm/mach-exynos/smc.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Samsung Electronics.
|
||||
*
|
||||
* EXYNOS - SMC Call
|
||||
*
|
||||
* 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_EXYNOS_SMC_H
|
||||
#define __ASM_ARCH_EXYNOS_SMC_H
|
||||
|
||||
#define SMC_CMD_INIT (-1)
|
||||
#define SMC_CMD_INFO (-2)
|
||||
/* For Power Management */
|
||||
#define SMC_CMD_SLEEP (-3)
|
||||
#define SMC_CMD_CPU1BOOT (-4)
|
||||
#define SMC_CMD_CPU0AFTR (-5)
|
||||
/* For CP15 Access */
|
||||
#define SMC_CMD_C15RESUME (-11)
|
||||
/* For L2 Cache Access */
|
||||
#define SMC_CMD_L2X0CTRL (-21)
|
||||
#define SMC_CMD_L2X0SETUP1 (-22)
|
||||
#define SMC_CMD_L2X0SETUP2 (-23)
|
||||
#define SMC_CMD_L2X0INVALL (-24)
|
||||
#define SMC_CMD_L2X0DEBUG (-25)
|
||||
|
||||
extern void exynos_smc(u32 cmd, u32 arg1, u32 arg2, u32 arg3);
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue