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.
 -----BEGIN PGP SIGNATURE-----
 
 iQJEBAABCgAuFiEE3dJiKD0RGyM7briowTdm5oaLg9cFAlyzVXYQHGtyemtAa2Vy
 bmVsLm9yZwAKCRDBN2bmhouD12kSD/45XOQOV51X81HJ1ztxsMrNBQJqY2kGJJrq
 s3QUo184nCJT9muJ9QXLRCgqzU7fsI5UUb5k7BnJAX5XpV7nWzHuZd7MHoVlyNJH
 p7YKzmHLxrzbFbRx+MQoRlaYjwXa9QD+OB/wACHId3cxmY2UneM7Zjp1dB/pJz+p
 zvGO6nORntFHE3Cdk0hp+j9iyXA/JoUaPQUMsIETqPup+Cql0mM11/UDqI/YCI9N
 E3GmieXYAboENRdZ0yStLjh5d5V4kTPAUh4YLQzhqDZKYlwbb36OBRbxhUdTMBOM
 zPM3sU0x95yWSJwEgXkk4FRdEcjneXG6+9WreyYipLiu9OP1fE/b3UinjmdS6tqt
 h+9xG+tKusDiUMFKxtOg5eQyncAyZMzFRxSbfO83+T8xEEM7MjydO8lpke0+/vf3
 +Hi+GgYR5XLiRViPjQZTc7AvJICDJwncWtSPty+Z62rUb0wNf5EEWO85KE9N2wmK
 vrNQrf4zzQMlDUGDWSeRhApxkZke48koLTU6+FoS6POmdFv1QD5UjFEsr4KF1r22
 J2rK3fTC/R5qM4MZb+OHTBG0/mnY/+dzLBUa/JKaIrTacr1Ghml9DaFwePraAEp1
 a0c5lGtmsYHnnb+tnR/jK8T9qaNN9H1/oNJYC+COENXNGUsyc9cd3SIVmSSvG/wh
 nU6S+wbXPQ==
 =v6It
 -----END PGP SIGNATURE-----

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>
This commit is contained in:
Olof Johansson 2019-04-28 23:04:41 -07:00
commit e5a0be94ee
12 changed files with 89 additions and 24 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -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;

View File

@ -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);

View File

@ -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));

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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);