Some suspend improvements enabling the possibility to wakeup

from usbphy events and a rework of how cpu cores are brought
 uü and down, as it was possible to produce lockups when
 hammering the cpu hotplug functions.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQEcBAABCAAGBQJVp7v5AAoJEPOmecmc0R2BIjsIAI/siza1l62HuNCuj96ntlJA
 77jBO2zV0ZfRd/3CPHwkuDajla4KifQXDUcy1UAXhAuyieki3qfUDkurlurV9xK8
 OaTRdc0hc6kbU3C6q+biXkRURtGDXH1fqF+t8gXUbyxv+dZ5NMWbZAXxb0SwvjpY
 m7tpOdoVgTQIp3SiFCo6gVw7aXJcRkm9QLdj05hVMsMOWxu9TkmKrGo7aHTN0A4w
 aTEtOLd8e89YMkcW4Eg0fkasTEKeV1ni30yxmld0hTPi0pPrsBbWRBCp4lltGrVS
 kYl1kIZQk3RURcO3H/Tz0lEWhaUaQYmQqRg8Q+vBIQA6GILOLzwziYGLljigy7g=
 =+S6z
 -----END PGP SIGNATURE-----

Merge tag 'v4.3-rockchip32-soc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip into next/soc

Merge "Rockchip soc changes for 4.3, part1" from Heiko Stuebner:

Some suspend improvements enabling the possibility to wakeup
from usbphy events and a rework of how cpu cores are brought
up and down, as it was possible to produce lockups when
hammering the cpu hotplug functions.

* tag 'v4.3-rockchip32-soc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip:
  ARM: rockchip: fix broken build
  ARM: rockchip: remove some useless macro in pm.h
  ARM: rockchip: add support holding 24Mhz osc during suspend
  ARM: rockchip: fix the SMP code style
  ARM: rockchip: ensure CPU to enter WFI/WFE state
  ARM: rockchip: fix the CPU soft reset
  ARM: rockchip: restore dapswjdp after suspend

Signed-off-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
Olof Johansson 2015-07-17 10:36:32 -07:00
commit d7030a08f6
3 changed files with 77 additions and 31 deletions

View File

@ -72,29 +72,22 @@ static struct reset_control *rockchip_get_core_reset(int cpu)
static int pmu_set_power_domain(int pd, bool on)
{
u32 val = (on) ? 0 : BIT(pd);
struct reset_control *rstc = rockchip_get_core_reset(pd);
int ret;
if (IS_ERR(rstc) && read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) {
pr_err("%s: could not get reset control for core %d\n",
__func__, pd);
return PTR_ERR(rstc);
}
/*
* We need to soft reset the cpu when we turn off the cpu power domain,
* or else the active processors might be stalled when the individual
* processor is powered down.
*/
if (read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) {
struct reset_control *rstc = rockchip_get_core_reset(pd);
if (IS_ERR(rstc)) {
pr_err("%s: could not get reset control for core %d\n",
__func__, pd);
return PTR_ERR(rstc);
}
if (on)
reset_control_deassert(rstc);
else
reset_control_assert(rstc);
reset_control_put(rstc);
}
if (!IS_ERR(rstc) && !on)
reset_control_assert(rstc);
ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
if (ret < 0) {
@ -107,11 +100,17 @@ static int pmu_set_power_domain(int pd, bool on)
ret = pmu_power_domain_is_on(pd);
if (ret < 0) {
pr_err("%s: could not read power domain state\n",
__func__);
__func__);
return ret;
}
}
if (!IS_ERR(rstc)) {
if (on)
reset_control_deassert(rstc);
reset_control_put(rstc);
}
return 0;
}
@ -130,7 +129,7 @@ static int rockchip_boot_secondary(unsigned int cpu, struct task_struct *idle)
if (cpu >= ncores) {
pr_err("%s: cpu %d outside maximum number of cpus %d\n",
__func__, cpu, ncores);
__func__, cpu, ncores);
return -ENXIO;
}
@ -140,14 +139,19 @@ static int rockchip_boot_secondary(unsigned int cpu, struct task_struct *idle)
return ret;
if (read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) {
/* We communicate with the bootrom to active the cpus other
/*
* We communicate with the bootrom to active the cpus other
* than cpu0, after a blob of initialize code, they will
* stay at wfe state, once they are actived, they will check
* the mailbox:
* sram_base_addr + 4: 0xdeadbeaf
* sram_base_addr + 8: start address for pc
* */
udelay(10);
* The cpu0 need to wait the other cpus other than cpu0 entering
* the wfe state.The wait time is affected by many aspects.
* (e.g: cpu frequency, bootrom frequency, sram frequency, ...)
*/
mdelay(1); /* ensure the cpus other than cpu0 to startup */
writel(virt_to_phys(secondary_startup), sram_base_addr + 8);
writel(0xDEADBEAF, sram_base_addr + 4);
dsb_sev();
@ -317,6 +321,13 @@ static void __init rockchip_smp_prepare_cpus(unsigned int max_cpus)
#ifdef CONFIG_HOTPLUG_CPU
static int rockchip_cpu_kill(unsigned int cpu)
{
/*
* We need a delay here to ensure that the dying CPU can finish
* executing v7_coherency_exit() and reach the WFI/WFE state
* prior to having the power domain disabled.
*/
mdelay(1);
pmu_set_power_domain(0 + cpu, false);
return 1;
}
@ -324,7 +335,7 @@ static int rockchip_cpu_kill(unsigned int cpu)
static void rockchip_cpu_die(unsigned int cpu)
{
v7_exit_coherency_flush(louis);
while(1)
while (1)
cpu_do_idle();
}
#endif
@ -337,4 +348,5 @@ static struct smp_operations rockchip_smp_ops __initdata = {
.cpu_die = rockchip_cpu_die,
#endif
};
CPU_METHOD_OF_DECLARE(rk3066_smp, "rockchip,rk3066-smp", &rockchip_smp_ops);

View File

@ -45,9 +45,11 @@ static phys_addr_t rk3288_bootram_phy;
static struct regmap *pmu_regmap;
static struct regmap *sgrf_regmap;
static struct regmap *grf_regmap;
static u32 rk3288_pmu_pwr_mode_con;
static u32 rk3288_sgrf_soc_con0;
static u32 rk3288_sgrf_cpu_con0;
static inline u32 rk3288_l2_config(void)
{
@ -66,10 +68,37 @@ static void rk3288_config_bootdata(void)
rkpm_bootdata_l2ctlr = rk3288_l2_config();
}
#define GRF_UOC0_CON0 0x320
#define GRF_UOC1_CON0 0x334
#define GRF_UOC2_CON0 0x348
#define GRF_SIDDQ BIT(13)
static bool rk3288_slp_disable_osc(void)
{
static const u32 reg_offset[] = { GRF_UOC0_CON0, GRF_UOC1_CON0,
GRF_UOC2_CON0 };
u32 reg, i;
/*
* if any usb phy is still on(GRF_SIDDQ==0), that means we need the
* function of usb wakeup, so do not switch to 32khz, since the usb phy
* clk does not connect to 32khz osc
*/
for (i = 0; i < ARRAY_SIZE(reg_offset); i++) {
regmap_read(grf_regmap, reg_offset[i], &reg);
if (!(reg & GRF_SIDDQ))
return false;
}
return true;
}
static void rk3288_slp_mode_set(int level)
{
u32 mode_set, mode_set1;
bool osc_switch_to_32k = rk3288_slp_disable_osc();
regmap_read(sgrf_regmap, RK3288_SGRF_CPU_CON0, &rk3288_sgrf_cpu_con0);
regmap_read(sgrf_regmap, RK3288_SGRF_SOC_CON0, &rk3288_sgrf_soc_con0);
regmap_read(pmu_regmap, RK3288_PMU_PWRMODE_CON,
@ -107,11 +136,13 @@ static void rk3288_slp_mode_set(int level)
if (level == ROCKCHIP_ARM_OFF_LOGIC_DEEP) {
/* arm off, logic deep sleep */
mode_set |= BIT(PMU_BUS_PD_EN) |
mode_set |= BIT(PMU_BUS_PD_EN) | BIT(PMU_PMU_USE_LF) |
BIT(PMU_DDR1IO_RET_EN) | BIT(PMU_DDR0IO_RET_EN) |
BIT(PMU_OSC_24M_DIS) | BIT(PMU_PMU_USE_LF) |
BIT(PMU_ALIVE_USE_LF) | BIT(PMU_PLL_PD_EN);
if (osc_switch_to_32k)
mode_set |= BIT(PMU_OSC_24M_DIS);
mode_set1 |= BIT(PMU_CLR_ALIVE) | BIT(PMU_CLR_BUS) |
BIT(PMU_CLR_PERI) | BIT(PMU_CLR_DMA);
} else {
@ -129,6 +160,9 @@ static void rk3288_slp_mode_set(int level)
static void rk3288_slp_mode_set_resume(void)
{
regmap_write(sgrf_regmap, RK3288_SGRF_CPU_CON0,
rk3288_sgrf_cpu_con0 | SGRF_DAPDEVICEEN_WRITE);
regmap_write(pmu_regmap, RK3288_PMU_PWRMODE_CON,
rk3288_pmu_pwr_mode_con);
@ -193,6 +227,13 @@ static int rk3288_suspend_init(struct device_node *np)
return PTR_ERR(pmu_regmap);
}
grf_regmap = syscon_regmap_lookup_by_compatible(
"rockchip,rk3288-grf");
if (IS_ERR(grf_regmap)) {
pr_err("%s: could not find grf regmap\n", __func__);
return PTR_ERR(pmu_regmap);
}
sram_np = of_find_compatible_node(NULL, NULL,
"rockchip,rk3288-pmu-sram");
if (!sram_np) {

View File

@ -59,13 +59,6 @@ static inline void rockchip_suspend_init(void)
#define SGRF_DAPDEVICEEN BIT(0)
#define SGRF_DAPDEVICEEN_WRITE BIT(16)
#define RK3288_CRU_MODE_CON 0x50
#define RK3288_CRU_SEL0_CON 0x60
#define RK3288_CRU_SEL1_CON 0x64
#define RK3288_CRU_SEL10_CON 0x88
#define RK3288_CRU_SEL33_CON 0xe4
#define RK3288_CRU_SEL37_CON 0xf4
/* PMU_WAKEUP_CFG1 bits */
#define PMU_ARMINT_WAKEUP_EN BIT(0)