Commit 0065198e authored by Olof Johansson's avatar Olof Johansson
Browse files

Merge tag 'omap-for-v5.2/am4-pm-v2-signed' of...

Merge tag 'omap-for-v5.2/am4-pm-v2-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into arm/drivers

PM changes for am335x and am437x

This series adds support for am437x RTC-only mode in suspend. In the
RTC-only mode suspend, everything is shut down except the RTC. This
makes the power consumption very low for suspend mode.

To support RTC-only mode, we need to export omap_rtc_power_off_program()
from the rtc driver and improve PM code to save and restore the wkup
domain context. As RTC-only mode depends on the device being wired
properly for things like memory, we need to also check for the machine
type before we allow it. We also need to run DDR3 hardware leveling on
resume.

Note that there is a trivial merge conflict between the RTC branch
and these changes where the RTC branch makes tm2bcd() a void function
and the error handling parts can be just dropped.

* tag 'omap-for-v5.2/am4-pm-v2-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap

:
  ARM: OMAP2+: sleep43xx: Run EMIF HW leveling on resume path
  memory: ti-emif-sram: Add ti_emif_run_hw_leveling for DDR3 hardware leveling
  soc: ti: pm33xx: AM437X: Add rtc_only with ddr in self-refresh support
  soc: ti: pm33xx: Move the am33xx_push_sram_idle to the top
  ARM: OMAP2+: pm33xx: Add support for rtc+ddr in self refresh mode
  rtc: OMAP: Add support for rtc-only mode

Signed-off-by: default avatarOlof Johansson <olof@lixom.net>
parents 424adc17 35667d81
Loading
Loading
Loading
Loading
+75 −1
Original line number Diff line number Diff line
@@ -10,6 +10,12 @@
#include <asm/suspend.h>
#include <linux/errno.h>
#include <linux/platform_data/pm33xx.h>
#include <linux/clk.h>
#include <linux/platform_data/gpio-omap.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/wkup_m3_ipc.h>
#include <linux/of.h>
#include <linux/rtc.h>

#include "cm33xx.h"
#include "common.h"
@@ -38,6 +44,29 @@ static int am43xx_map_scu(void)
	return 0;
}

static int am33xx_check_off_mode_enable(void)
{
	if (enable_off_mode)
		pr_warn("WARNING: This platform does not support off-mode, entering DeepSleep suspend.\n");

	/* off mode not supported on am335x so return 0 always */
	return 0;
}

static int am43xx_check_off_mode_enable(void)
{
	/*
	 * Check for am437x-gp-evm which has the right Hardware design to
	 * support this mode reliably.
	 */
	if (of_machine_is_compatible("ti,am437x-gp-evm") && enable_off_mode)
		return enable_off_mode;
	else if (enable_off_mode)
		pr_warn("WARNING: This platform does not support off-mode, entering DeepSleep suspend.\n");

	return 0;
}

static int amx3_common_init(void)
{
	gfx_pwrdm = pwrdm_lookup("gfx_pwrdm");
@@ -139,6 +168,8 @@ static int am43xx_suspend(unsigned int state, int (*fn)(unsigned long),
	scu_power_mode(scu_base, SCU_PM_POWEROFF);
	ret = cpu_suspend(args, fn);
	scu_power_mode(scu_base, SCU_PM_NORMAL);

	if (!am43xx_check_off_mode_enable())
		amx3_post_suspend_common();

	return ret;
@@ -161,10 +192,48 @@ void __iomem *am43xx_get_rtc_base_addr(void)
	return omap_hwmod_get_mpu_rt_va(rtc_oh);
}

static void am43xx_save_context(void)
{
}

static void am33xx_save_context(void)
{
	omap_intc_save_context();
}

static void am33xx_restore_context(void)
{
	omap_intc_restore_context();
}

static void am43xx_restore_context(void)
{
	/*
	 * HACK: restore dpll_per_clkdcoldo register contents, to avoid
	 * breaking suspend-resume
	 */
	writel_relaxed(0x0, AM33XX_L4_WK_IO_ADDRESS(0x44df2e14));
}

static void am43xx_prepare_rtc_suspend(void)
{
	omap_hwmod_enable(rtc_oh);
}

static void am43xx_prepare_rtc_resume(void)
{
	omap_hwmod_idle(rtc_oh);
}

static struct am33xx_pm_platform_data am33xx_ops = {
	.init = am33xx_suspend_init,
	.soc_suspend = am33xx_suspend,
	.get_sram_addrs = amx3_get_sram_addrs,
	.save_context = am33xx_save_context,
	.restore_context = am33xx_restore_context,
	.prepare_rtc_suspend = am43xx_prepare_rtc_suspend,
	.prepare_rtc_resume = am43xx_prepare_rtc_resume,
	.check_off_mode_enable = am33xx_check_off_mode_enable,
	.get_rtc_base_addr = am43xx_get_rtc_base_addr,
};

@@ -172,6 +241,11 @@ static struct am33xx_pm_platform_data am43xx_ops = {
	.init = am43xx_suspend_init,
	.soc_suspend = am43xx_suspend,
	.get_sram_addrs = amx3_get_sram_addrs,
	.save_context = am43xx_save_context,
	.restore_context = am43xx_restore_context,
	.prepare_rtc_suspend = am43xx_prepare_rtc_suspend,
	.prepare_rtc_resume = am43xx_prepare_rtc_resume,
	.check_off_mode_enable = am43xx_check_off_mode_enable,
	.get_rtc_base_addr = am43xx_get_rtc_base_addr,
};

+3 −0
Original line number Diff line number Diff line
@@ -368,6 +368,9 @@ wait_emif_enable1:
	mov     r1, #AM43XX_EMIF_POWEROFF_DISABLE
	str     r1, [r2, #0x0]

	ldr     r1, [r9, #EMIF_PM_RUN_HW_LEVELING]
	blx     r1

#ifdef CONFIG_CACHE_L2X0
	ldr	r2, l2_cache_base
	ldr	r0, [r2, #L2X0_CTRL]
+4 −0
Original line number Diff line number Diff line
@@ -537,6 +537,9 @@
#define MCONNID_SHIFT					0
#define MCONNID_MASK					(0xff << 0)

/* READ_WRITE_LEVELING_CONTROL */
#define RDWRLVLFULL_START				0x80000000

/* DDR_PHY_CTRL_1 - EMIF4D */
#define DLL_SLAVE_DLY_CTRL_SHIFT_4D			4
#define DLL_SLAVE_DLY_CTRL_MASK_4D			(0xFF << 4)
@@ -598,6 +601,7 @@ extern struct emif_regs_amx3 ti_emif_regs_amx3;

void ti_emif_save_context(void);
void ti_emif_restore_context(void);
void ti_emif_run_hw_leveling(void);
void ti_emif_enter_sr(void);
void ti_emif_exit_sr(void);
void ti_emif_abort_sr(void);
+3 −0
Original line number Diff line number Diff line
@@ -138,6 +138,9 @@ static int ti_emif_alloc_sram(struct device *dev,
	emif_data->pm_functions.exit_sr =
		sram_resume_address(emif_data,
				    (unsigned long)ti_emif_exit_sr);
	emif_data->pm_functions.run_hw_leveling =
		sram_resume_address(emif_data,
				    (unsigned long)ti_emif_run_hw_leveling);

	emif_data->pm_data.regs_virt =
		(struct emif_regs_amx3 *)emif_data->ti_emif_sram_data_virt;
+41 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#define EMIF_POWER_MGMT_SELF_REFRESH_MODE_MASK		0x0700

#define EMIF_SDCFG_TYPE_DDR2				0x2 << SDRAM_TYPE_SHIFT
#define EMIF_SDCFG_TYPE_DDR3				0x3 << SDRAM_TYPE_SHIFT
#define EMIF_STATUS_READY				0x4

#define AM43XX_EMIF_PHY_CTRL_REG_COUNT                  0x120
@@ -244,6 +245,46 @@ emif_skip_restore_extra_regs:
	mov	pc, lr
ENDPROC(ti_emif_restore_context)

/*
 * void ti_emif_run_hw_leveling(void)
 *
 * Used during resume to run hardware leveling again and restore the
 * configuration of the EMIF PHY, only for DDR3.
 */
ENTRY(ti_emif_run_hw_leveling)
	adr	r4, ti_emif_pm_sram_data
	ldr	r0, [r4, #EMIF_PM_BASE_ADDR_PHYS_OFFSET]

	ldr	r3, [r0, #EMIF_READ_WRITE_LEVELING_CONTROL]
	orr	r3, r3, #RDWRLVLFULL_START
	ldr	r2, [r0, #EMIF_SDRAM_CONFIG]
	and	r2, r2, #SDRAM_TYPE_MASK
	cmp	r2, #EMIF_SDCFG_TYPE_DDR3
	bne	skip_hwlvl

	str	r3, [r0, #EMIF_READ_WRITE_LEVELING_CONTROL]

	/*
	 * If EMIF registers are touched during initial stage of HW
	 * leveling sequence there will be an L3 NOC timeout error issued
	 * as the EMIF will not respond, which is not fatal, but it is
	 * avoidable. This small wait loop is enough time for this condition
	 * to clear, even at worst case of CPU running at max speed of 1Ghz.
	 */
	mov	r2, #0x2000
1:
	subs	r2, r2, #0x1
	bne	1b

	/* Bit clears when operation is complete */
2:	ldr     r1, [r0, #EMIF_READ_WRITE_LEVELING_CONTROL]
	tst     r1, #RDWRLVLFULL_START
	bne     2b

skip_hwlvl:
	mov	pc, lr
ENDPROC(ti_emif_run_hw_leveling)

/*
 * void ti_emif_enter_sr(void)
 *
Loading