summaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2019-04-28 23:04:41 -0700
committerOlof Johansson <olof@lixom.net>2019-04-28 23:04:41 -0700
commite5a0be94ee8bc56e5594bae19512fb6e431f7c13 (patch)
tree4d2ebeda71f6d26b1999b794b1f2b52fde500f02 /arch/arm
parente639861344f95d72f47eec68077aafb0ec212570 (diff)
parent7676e667c841375b41d9438b559756141aa93d0e (diff)
downloadlinux-e5a0be94ee8bc56e5594bae19512fb6e431f7c13.tar.bz2
Merge tag 'samsung-soc-5.2' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux into arm/soc
Samsung mach/soc changes for v5.2 1. Cleanup in mach code. 2. Add necessary fixes for Suspend to RAM on Exynos5422 boards (tested with Odroid XU3/XU4/HC1 family). Finally this brings a working S2R on these Odroid boards (still other drivers might have some issues but mach code seems to be finished). 3. Require MCPM for Exynos542x boards because otherwise not all of cores will come online. 4. GPIO regulator cleanup on S3C6410 Craig. * tag 'samsung-soc-5.2' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux: ARM: s3c64xx: Tidy up handling of regulator GPIO lookups ARM: exynos: Set MCPM as mandatory for Exynos542x/5800 SoCs ARM: exynos: Fix infinite loops on CPU powerup failure ARM: exynos: Fix a leaked reference by adding missing of_node_put ARM: exynos: Fix undefined instruction during Exynos5422 resume ARM: exynos: Add CPU state management for Exynos542x under secure firmware ARM: exynos: Add Exynos SMC values for secure memory write ARM: exynos: Move Exynos542x CPU state reset to pm_prepare() Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/configs/exynos_defconfig1
-rw-r--r--arch/arm/configs/multi_v7_defconfig1
-rw-r--r--arch/arm/mach-exynos/Kconfig12
-rw-r--r--arch/arm/mach-exynos/Makefile2
-rw-r--r--arch/arm/mach-exynos/common.h1
-rw-r--r--arch/arm/mach-exynos/exynos.c3
-rw-r--r--arch/arm/mach-exynos/firmware.c1
-rw-r--r--arch/arm/mach-exynos/mcpm-exynos.c13
-rw-r--r--arch/arm/mach-exynos/platsmp.c9
-rw-r--r--arch/arm/mach-exynos/smc.h7
-rw-r--r--arch/arm/mach-exynos/suspend.c49
-rw-r--r--arch/arm/mach-s3c64xx/mach-crag6410-module.c14
12 files changed, 89 insertions, 24 deletions
diff --git a/arch/arm/configs/exynos_defconfig b/arch/arm/configs/exynos_defconfig
index d635edfb6ff2..c95c54284da2 100644
--- a/arch/arm/configs/exynos_defconfig
+++ b/arch/arm/configs/exynos_defconfig
@@ -9,7 +9,6 @@ CONFIG_MODULE_UNLOAD=y
CONFIG_PARTITION_ADVANCED=y
CONFIG_ARCH_EXYNOS=y
CONFIG_ARCH_EXYNOS3=y
-CONFIG_EXYNOS5420_MCPM=y
CONFIG_SMP=y
CONFIG_BIG_LITTLE=y
CONFIG_NR_CPUS=8
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index c75051b9392c..e4b5fd46fdef 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -33,7 +33,6 @@ CONFIG_MACH_BERLIN_BG2CD=y
CONFIG_MACH_BERLIN_BG2Q=y
CONFIG_ARCH_DIGICOLOR=y
CONFIG_ARCH_EXYNOS=y
-CONFIG_EXYNOS5420_MCPM=y
CONFIG_ARCH_HIGHBANK=y
CONFIG_ARCH_HISI=y
CONFIG_ARCH_HI3xxx=y
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index b40963cf91c7..1c518b8ee520 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -106,21 +106,15 @@ config SOC_EXYNOS5420
bool "SAMSUNG EXYNOS5420"
default y
depends on ARCH_EXYNOS5
+ select MCPM if SMP
+ select ARM_CCI400_PORT_CTRL
+ select ARM_CPU_SUSPEND
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_CCI400_PORT_CTRL
- select ARM_CPU_SUSPEND
- help
- This is needed to provide CPU and cluster power management
- on Exynos5420 implementing big.LITTLE.
-
config EXYNOS_CPU_SUSPEND
bool
select ARM_CPU_SUSPEND
diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile
index cd00c82a1add..264dbaa89c3d 100644
--- a/arch/arm/mach-exynos/Makefile
+++ b/arch/arm/mach-exynos/Makefile
@@ -18,5 +18,5 @@ plus_sec := $(call as-instr,.arch_extension sec,+sec)
AFLAGS_exynos-smc.o :=-Wa,-march=armv7-a$(plus_sec)
AFLAGS_sleep.o :=-Wa,-march=armv7-a$(plus_sec)
-obj-$(CONFIG_EXYNOS5420_MCPM) += mcpm-exynos.o
+obj-$(CONFIG_MCPM) += mcpm-exynos.o
CFLAGS_mcpm-exynos.o += -march=armv7-a
diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h
index 1b8699e94098..c93356a8d662 100644
--- a/arch/arm/mach-exynos/common.h
+++ b/arch/arm/mach-exynos/common.h
@@ -91,6 +91,7 @@ extern u32 cp15_save_power;
extern void __iomem *sysram_ns_base_addr;
extern void __iomem *sysram_base_addr;
+extern phys_addr_t sysram_base_phys;
extern void __iomem *pmu_base_addr;
void exynos_sysram_init(void);
diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c
index 865dcc4c3181..9aa483366ebc 100644
--- a/arch/arm/mach-exynos/exynos.c
+++ b/arch/arm/mach-exynos/exynos.c
@@ -33,6 +33,7 @@ static struct platform_device exynos_cpuidle = {
};
void __iomem *sysram_base_addr __ro_after_init;
+phys_addr_t sysram_base_phys __ro_after_init;
void __iomem *sysram_ns_base_addr __ro_after_init;
void __init exynos_sysram_init(void)
@@ -43,6 +44,8 @@ void __init exynos_sysram_init(void)
if (!of_device_is_available(node))
continue;
sysram_base_addr = of_iomap(node, 0);
+ sysram_base_phys = of_translate_address(node,
+ of_get_address(node, 0, NULL, NULL));
break;
}
diff --git a/arch/arm/mach-exynos/firmware.c b/arch/arm/mach-exynos/firmware.c
index d602e3bf3f96..2eaf2dbb8e81 100644
--- a/arch/arm/mach-exynos/firmware.c
+++ b/arch/arm/mach-exynos/firmware.c
@@ -196,6 +196,7 @@ bool __init exynos_secure_firmware_available(void)
return false;
addr = of_get_address(nd, 0, NULL, NULL);
+ of_node_put(nd);
if (!addr) {
pr_err("%s: No address specified.\n", __func__);
return false;
diff --git a/arch/arm/mach-exynos/mcpm-exynos.c b/arch/arm/mach-exynos/mcpm-exynos.c
index 72bc035bedbe..9a681b421ae1 100644
--- a/arch/arm/mach-exynos/mcpm-exynos.c
+++ b/arch/arm/mach-exynos/mcpm-exynos.c
@@ -75,14 +75,25 @@ static int exynos_cpu_powerup(unsigned int cpu, unsigned int cluster)
*/
if (cluster &&
cluster == MPIDR_AFFINITY_LEVEL(cpu_logical_map(0), 1)) {
+ unsigned int timeout = 16;
+
/*
* Before we reset the Little cores, we should wait
* the SPARE2 register is set to 1 because the init
* codes of the iROM will set the register after
* initialization.
*/
- while (!pmu_raw_readl(S5P_PMU_SPARE2))
+ while (timeout && !pmu_raw_readl(S5P_PMU_SPARE2)) {
+ timeout--;
udelay(10);
+ }
+
+ if (timeout == 0) {
+ pr_err("cpu %u cluster %u powerup failed\n",
+ cpu, cluster);
+ exynos_cpu_power_down(cpunr);
+ return -ETIMEDOUT;
+ }
pmu_raw_writel(EXYNOS5420_KFC_CORE_RESET(cpu),
EXYNOS_SWRESET);
diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c
index abcac6164233..0cbbae8bf1f8 100644
--- a/arch/arm/mach-exynos/platsmp.c
+++ b/arch/arm/mach-exynos/platsmp.c
@@ -214,13 +214,20 @@ static inline void __iomem *cpu_boot_reg(int cpu)
*/
void exynos_core_restart(u32 core_id)
{
+ unsigned int timeout = 16;
u32 val;
if (!of_machine_is_compatible("samsung,exynos3250"))
return;
- while (!pmu_raw_readl(S5P_PMU_SPARE2))
+ while (timeout && !pmu_raw_readl(S5P_PMU_SPARE2)) {
+ timeout--;
udelay(10);
+ }
+ if (timeout == 0) {
+ pr_err("cpu core %u restart failed\n", core_id);
+ return;
+ }
udelay(10);
val = pmu_raw_readl(EXYNOS_ARM_CORE_STATUS(core_id));
diff --git a/arch/arm/mach-exynos/smc.h b/arch/arm/mach-exynos/smc.h
index f355185d4239..98832e50852d 100644
--- a/arch/arm/mach-exynos/smc.h
+++ b/arch/arm/mach-exynos/smc.h
@@ -25,6 +25,13 @@
#define SMC_CMD_L2X0INVALL (-24)
#define SMC_CMD_L2X0DEBUG (-25)
+/* For Accessing CP15/SFR (General) */
+#define SMC_CMD_REG (-101)
+
+/* defines for SMC_CMD_REG */
+#define SMC_REG_CLASS_SFR_W (0x1 << 30)
+#define SMC_REG_ID_SFR_W(addr) (SMC_REG_CLASS_SFR_W | ((addr) >> 2))
+
#ifndef __ASSEMBLY__
extern void exynos_smc(u32 cmd, u32 arg1, u32 arg2, u32 arg3);
diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c
index 0850505ac78b..be122af0de8f 100644
--- a/arch/arm/mach-exynos/suspend.c
+++ b/arch/arm/mach-exynos/suspend.c
@@ -31,6 +31,7 @@
#include <asm/suspend.h>
#include "common.h"
+#include "smc.h"
#define REG_TABLE_END (-1U)
@@ -62,6 +63,8 @@ struct exynos_pm_state {
int cpu_state;
unsigned int pmu_spare3;
void __iomem *sysram_base;
+ phys_addr_t sysram_phys;
+ bool secure_firmware;
};
static const struct exynos_pm_data *pm_data __ro_after_init;
@@ -265,9 +268,7 @@ static int exynos5420_cpu_suspend(unsigned long arg)
unsigned int cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
unsigned int cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
- writel_relaxed(0x0, pm_state.sysram_base + EXYNOS5420_CPU_STATE);
-
- if (IS_ENABLED(CONFIG_EXYNOS5420_MCPM)) {
+ if (IS_ENABLED(CONFIG_MCPM)) {
mcpm_set_entry_vector(cpu, cluster, exynos_cpu_resume);
mcpm_cpu_suspend();
}
@@ -341,11 +342,16 @@ static void exynos5420_pm_prepare(void)
*/
pm_state.cpu_state = readl_relaxed(pm_state.sysram_base +
EXYNOS5420_CPU_STATE);
+ writel_relaxed(0x0, pm_state.sysram_base + EXYNOS5420_CPU_STATE);
+ if (pm_state.secure_firmware)
+ exynos_smc(SMC_CMD_REG, SMC_REG_ID_SFR_W(pm_state.sysram_phys +
+ EXYNOS5420_CPU_STATE),
+ 0, 0);
exynos_pm_enter_sleep_mode();
/* ensure at least INFORM0 has the resume address */
- if (IS_ENABLED(CONFIG_EXYNOS5420_MCPM))
+ if (IS_ENABLED(CONFIG_MCPM))
pmu_raw_writel(__pa_symbol(mcpm_entry_point), S5P_INFORM0);
tmp = pmu_raw_readl(EXYNOS_L2_OPTION(0));
@@ -444,8 +450,27 @@ early_wakeup:
static void exynos5420_prepare_pm_resume(void)
{
- if (IS_ENABLED(CONFIG_EXYNOS5420_MCPM))
+ unsigned int mpidr, cluster;
+
+ mpidr = read_cpuid_mpidr();
+ cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
+
+ if (IS_ENABLED(CONFIG_MCPM))
WARN_ON(mcpm_cpu_powered_up());
+
+ if (IS_ENABLED(CONFIG_HW_PERF_EVENTS) && cluster != 0) {
+ /*
+ * When system is resumed on the LITTLE/KFC core (cluster 1),
+ * the DSCR is not properly updated until the power is turned
+ * on also for the cluster 0. Enable it for a while to
+ * propagate the SPNIDEN and SPIDEN signals from Secure JTAG
+ * block and avoid undefined instruction issue on CP14 reset.
+ */
+ pmu_raw_writel(S5P_CORE_LOCAL_PWR_EN,
+ EXYNOS_COMMON_CONFIGURATION(0));
+ pmu_raw_writel(0,
+ EXYNOS_COMMON_CONFIGURATION(0));
+ }
}
static void exynos5420_pm_resume(void)
@@ -460,6 +485,11 @@ static void exynos5420_pm_resume(void)
/* Restore the sysram cpu state register */
writel_relaxed(pm_state.cpu_state,
pm_state.sysram_base + EXYNOS5420_CPU_STATE);
+ if (pm_state.secure_firmware)
+ exynos_smc(SMC_CMD_REG,
+ SMC_REG_ID_SFR_W(pm_state.sysram_phys +
+ EXYNOS5420_CPU_STATE),
+ EXYNOS_AFTR_MAGIC, 0);
pmu_raw_writel(EXYNOS5420_USE_STANDBY_WFI_ALL,
S5P_CENTRAL_SEQ_OPTION);
@@ -639,8 +669,10 @@ void __init exynos_pm_init(void)
if (WARN_ON(!of_find_property(np, "interrupt-controller", NULL))) {
pr_warn("Outdated DT detected, suspend/resume will NOT work\n");
+ of_node_put(np);
return;
}
+ of_node_put(np);
pm_data = (const struct exynos_pm_data *) match->data;
@@ -659,8 +691,11 @@ void __init exynos_pm_init(void)
* Applicable as of now only to Exynos542x. If booted under secure
* firmware, the non-secure region of sysram should be used.
*/
- if (exynos_secure_firmware_available())
+ if (exynos_secure_firmware_available()) {
+ pm_state.sysram_phys = sysram_base_phys;
pm_state.sysram_base = sysram_ns_base_addr;
- else
+ pm_state.secure_firmware = true;
+ } else {
pm_state.sysram_base = sysram_base_addr;
+ }
}
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410-module.c b/arch/arm/mach-s3c64xx/mach-crag6410-module.c
index 76c4855a03bc..937d0a83f8fd 100644
--- a/arch/arm/mach-s3c64xx/mach-crag6410-module.c
+++ b/arch/arm/mach-s3c64xx/mach-crag6410-module.c
@@ -328,6 +328,8 @@ static const struct {
int num_i2c_devs;
const struct spi_board_info *spi_devs;
int num_spi_devs;
+
+ struct gpiod_lookup_table *gpiod_table;
} gf_mods[] = {
{ .id = 0x01, .rev = 0xff, .name = "1250-EV1 Springbank" },
{ .id = 0x02, .rev = 0xff, .name = "1251-EV1 Jura" },
@@ -362,13 +364,16 @@ static const struct {
.i2c_devs = wm1255_devs, .num_i2c_devs = ARRAY_SIZE(wm1255_devs) },
{ .id = 0x3c, .rev = 0xff, .name = "1273-EV1 Longmorn" },
{ .id = 0x3d, .rev = 0xff, .name = "1277-EV1 Littlemill",
- .i2c_devs = wm1277_devs, .num_i2c_devs = ARRAY_SIZE(wm1277_devs) },
+ .i2c_devs = wm1277_devs, .num_i2c_devs = ARRAY_SIZE(wm1277_devs),
+ .gpiod_table = &wm8994_gpiod_table },
{ .id = 0x3e, .rev = 0, .name = "WM5102-6271-EV1-CS127 Amrut",
.spi_devs = wm5102_reva_spi_devs,
- .num_spi_devs = ARRAY_SIZE(wm5102_reva_spi_devs) },
+ .num_spi_devs = ARRAY_SIZE(wm5102_reva_spi_devs),
+ .gpiod_table = &wm5102_reva_gpiod_table },
{ .id = 0x3e, .rev = -1, .name = "WM5102-6271-EV1-CS127 Amrut",
.spi_devs = wm5102_spi_devs,
- .num_spi_devs = ARRAY_SIZE(wm5102_spi_devs) },
+ .num_spi_devs = ARRAY_SIZE(wm5102_spi_devs),
+ .gpiod_table = &wm5102_gpiod_table },
{ .id = 0x3f, .rev = -1, .name = "WM2200-6271-CS90-M-REV1",
.i2c_devs = wm2200_i2c, .num_i2c_devs = ARRAY_SIZE(wm2200_i2c) },
};
@@ -408,6 +413,9 @@ static int wlf_gf_module_probe(struct i2c_client *i2c,
spi_register_board_info(gf_mods[i].spi_devs,
gf_mods[i].num_spi_devs);
+
+ if (gf_mods[i].gpiod_table)
+ gpiod_add_lookup_table(gf_mods[i].gpiod_table);
} else {
dev_warn(&i2c->dev, "Unknown module ID 0x%x revision %d\n",
id, rev + 1);