Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d7030a08 authored by Olof Johansson's avatar Olof Johansson
Browse files

Merge tag 'v4.3-rockchip32-soc1' of...

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: default avatarOlof Johansson <olof@lixom.net>
parents bc0195aa cb8cc37f
Loading
Loading
Loading
Loading
+34 −22
Original line number Diff line number Diff line
@@ -72,30 +72,23 @@ 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);
	int ret;

	/*
	 * 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);
	int ret;

		if (IS_ERR(rstc)) {
	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);
	}

		if (on)
			reset_control_deassert(rstc);
		else
	/*
	 * 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 (!IS_ERR(rstc) && !on)
		reset_control_assert(rstc);

		reset_control_put(rstc);
	}

	ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
	if (ret < 0) {
		pr_err("%s: could not update power domain\n", __func__);
@@ -112,6 +105,12 @@ static int pmu_set_power_domain(int pd, bool on)
		}
	}

	if (!IS_ERR(rstc)) {
		if (on)
			reset_control_deassert(rstc);
		reset_control_put(rstc);
	}

	return 0;
}

@@ -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;
}
@@ -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);
+43 −2
Original line number Diff line number Diff line
@@ -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) {
+0 −7
Original line number Diff line number Diff line
@@ -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)