Commit e5a0be94 authored by Olof Johansson's avatar Olof Johansson

Merge tag 'samsung-soc-5.2' of...

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: default avatarOlof Johansson <olof@lixom.net>
parents e6398613 7676e667
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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
......@@ -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);
......
......@@ -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;
}
......
......@@ -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;
......
......@@ -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);
......
......@@ -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));
......
......@@ -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);
......
......@@ -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 @@ static void exynos3250_pm_resume(void)
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;
}
}
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment