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

Commit 0adf882b authored by Dinh Nguyen's avatar Dinh Nguyen Committed by Sascha Hauer
Browse files

ARM: mx51: Implement code to allow mx51 to enter WFI



Implement code for MX51 that allows the SoC to enter WFI when
arch_idle is called.

This patch is also necessary for correctly suspending the system.

Signed-off-by: default avatarDinh Nguyen <Dinh.Nguyen@freescale.com>
Signed-off-by: default avatarSascha Hauer <s.hauer@pengutronix.de>
parent b6e89b21
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -3,7 +3,7 @@
#

# Object file lists.
obj-y   := cpu.o mm.o clock-mx51-mx53.o devices.o ehci.o
obj-y   := cpu.o mm.o clock-mx51-mx53.o devices.o ehci.o system.o
obj-$(CONFIG_SOC_IMX50) += mm-mx50.o

obj-$(CONFIG_CPU_FREQ_IMX)    += cpu_op-mx51.o
+84 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
 */

/*
 * The code contained herein is licensed under the GNU General Public
 * License. You may obtain a copy of the GNU General Public License
 * Version 2 or later at the following locations:
 *
 * http://www.opensource.org/licenses/gpl-license.html
 * http://www.gnu.org/copyleft/gpl.html
 */
#include <linux/platform_device.h>
#include <linux/io.h>
#include <mach/hardware.h>
#include "crm_regs.h"

/* set cpu low power mode before WFI instruction. This function is called
  * mx5 because it can be used for mx50, mx51, and mx53.*/
void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
{
	u32 plat_lpc, arm_srpgcr, ccm_clpcr;
	u32 empgc0, empgc1;
	int stop_mode = 0;

	/* always allow platform to issue a deep sleep mode request */
	plat_lpc = __raw_readl(MXC_CORTEXA8_PLAT_LPC) &
	    ~(MXC_CORTEXA8_PLAT_LPC_DSM);
	ccm_clpcr = __raw_readl(MXC_CCM_CLPCR) & ~(MXC_CCM_CLPCR_LPM_MASK);
	arm_srpgcr = __raw_readl(MXC_SRPG_ARM_SRPGCR) & ~(MXC_SRPGCR_PCR);
	empgc0 = __raw_readl(MXC_SRPG_EMPGC0_SRPGCR) & ~(MXC_SRPGCR_PCR);
	empgc1 = __raw_readl(MXC_SRPG_EMPGC1_SRPGCR) & ~(MXC_SRPGCR_PCR);

	switch (mode) {
	case WAIT_CLOCKED:
		break;
	case WAIT_UNCLOCKED:
		ccm_clpcr |= 0x1 << MXC_CCM_CLPCR_LPM_OFFSET;
		break;
	case WAIT_UNCLOCKED_POWER_OFF:
	case STOP_POWER_OFF:
		plat_lpc |= MXC_CORTEXA8_PLAT_LPC_DSM
			    | MXC_CORTEXA8_PLAT_LPC_DBG_DSM;
		if (mode == WAIT_UNCLOCKED_POWER_OFF) {
			ccm_clpcr |= 0x1 << MXC_CCM_CLPCR_LPM_OFFSET;
			ccm_clpcr &= ~MXC_CCM_CLPCR_VSTBY;
			ccm_clpcr &= ~MXC_CCM_CLPCR_SBYOS;
			stop_mode = 0;
		} else {
			ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET;
			ccm_clpcr |= 0x3 << MXC_CCM_CLPCR_STBY_COUNT_OFFSET;
			ccm_clpcr |= MXC_CCM_CLPCR_VSTBY;
			ccm_clpcr |= MXC_CCM_CLPCR_SBYOS;
			stop_mode = 1;
		}
		arm_srpgcr |= MXC_SRPGCR_PCR;

		if (tzic_enable_wake(1) != 0)
			return;
		break;
	case STOP_POWER_ON:
		ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET;
		break;
	default:
		printk(KERN_WARNING "UNKNOWN cpu power mode: %d\n", mode);
		return;
	}

	__raw_writel(plat_lpc, MXC_CORTEXA8_PLAT_LPC);
	__raw_writel(ccm_clpcr, MXC_CCM_CLPCR);
	__raw_writel(arm_srpgcr, MXC_SRPG_ARM_SRPGCR);

	/* Enable NEON SRPG for all but MX50TO1.0. */
	if (mx50_revision() != IMX_CHIP_REVISION_1_0)
		__raw_writel(arm_srpgcr, MXC_SRPG_NEON_SRPGCR);

	if (stop_mode) {
		empgc0 |= MXC_SRPGCR_PCR;
		empgc1 |= MXC_SRPGCR_PCR;

		__raw_writel(empgc0, MXC_SRPG_EMPGC0_SRPGCR);
		__raw_writel(empgc1, MXC_SRPG_EMPGC1_SRPGCR);
	}
}
+9 −0
Original line number Diff line number Diff line
@@ -195,6 +195,15 @@ struct cpu_op {
	u32 cpu_rate;
};

int tzic_enable_wake(int is_idle);
enum mxc_cpu_pwr_mode {
	WAIT_CLOCKED,		/* wfi only */
	WAIT_UNCLOCKED,		/* WAIT */
	WAIT_UNCLOCKED_POWER_OFF,	/* WAIT + SRPG */
	STOP_POWER_ON,		/* just STOP */
	STOP_POWER_OFF,		/* STOP + SRPG */
};

extern struct cpu_op *(*get_cpu_op)(int *op);
#endif

+5 −1
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@
#include <mach/hardware.h>
#include <mach/common.h>

extern void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode);

static inline void arch_idle(void)
{
#ifdef CONFIG_ARCH_MXC91231
@@ -54,7 +56,9 @@ static inline void arch_idle(void)
			"orr %0, %0, #0x00000004\n"
			"mcr p15, 0, %0, c1, c0, 0\n"
			: "=r" (reg));
	} else
	} else if (cpu_is_mx51())
		mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
	else
		cpu_do_idle();
}