Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 281864
b: refs/heads/master
c: b2b9762
h: refs/heads/master
v: v3
  • Loading branch information
Santosh Shilimkar authored and Kevin Hilman committed Dec 8, 2011
1 parent 1c700f9 commit 351db37
Show file tree
Hide file tree
Showing 9 changed files with 596 additions and 3 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: fcf6efa3ffbc3cc19e7abe39e0b90f497df2fc42
refs/heads/master: b2b9762f76981c16a8768255284efeae7f27e4f1
6 changes: 4 additions & 2 deletions trunk/arch/arm/mach-omap2/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,13 @@ obj-$(CONFIG_TWL4030_CORE) += omap_twl.o
obj-$(CONFIG_SMP) += omap-smp.o omap-headsmp.o
obj-$(CONFIG_LOCAL_TIMERS) += timer-mpu.o
obj-$(CONFIG_HOTPLUG_CPU) += omap-hotplug.o
obj-$(CONFIG_ARCH_OMAP4) += omap4-common.o omap-wakeupgen.o
obj-$(CONFIG_ARCH_OMAP4) += omap4-common.o omap-wakeupgen.o \
sleep44xx.o

plus_sec := $(call as-instr,.arch_extension sec,+sec)
AFLAGS_omap-headsmp.o :=-Wa,-march=armv7-a$(plus_sec)
AFLAGS_omap-smc.o :=-Wa,-march=armv7-a$(plus_sec)
AFLAGS_sleep44xx.o :=-Wa,-march=armv7-a$(plus_sec)

# Functions loaded to SRAM
obj-$(CONFIG_SOC_OMAP2420) += sram242x.o
Expand Down Expand Up @@ -63,7 +65,7 @@ obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o
obj-$(CONFIG_ARCH_OMAP2) += sleep24xx.o
obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o \
cpuidle34xx.o
obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o
obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o omap-mpuss-lowpower.o
obj-$(CONFIG_PM_DEBUG) += pm-debug.o
obj-$(CONFIG_OMAP_SMARTREFLEX) += sr_device.o smartreflex.o
obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS3) += smartreflex-class3.o
Expand Down
30 changes: 30 additions & 0 deletions trunk/arch/arm/mach-omap2/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@

#ifndef __ARCH_ARM_MACH_OMAP2PLUS_COMMON_H
#define __ARCH_ARM_MACH_OMAP2PLUS_COMMON_H
#ifndef __ASSEMBLER__

#include <linux/delay.h>
#include <plat/common.h>
#include <asm/proc-fns.h>

#ifdef CONFIG_SOC_OMAP2420
extern void omap242x_map_common_io(void);
Expand Down Expand Up @@ -183,6 +185,7 @@ static inline void __iomem *omap4_get_scu_base(void)
extern void __init gic_init_irq(void);
extern void omap_smc1(u32 fn, u32 arg);
extern void __iomem *omap4_get_sar_ram_base(void);
extern void omap_do_wfi(void);

#ifdef CONFIG_SMP
/* Needed for secondary core boot */
Expand All @@ -192,4 +195,31 @@ extern void omap_auxcoreboot_addr(u32 cpu_addr);
extern u32 omap_read_auxcoreboot0(void);
#endif

#if defined(CONFIG_SMP) && defined(CONFIG_PM)
extern int omap4_mpuss_init(void);
extern int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state);
extern int omap4_finish_suspend(unsigned long cpu_state);
extern void omap4_cpu_resume(void);
#else
static inline int omap4_enter_lowpower(unsigned int cpu,
unsigned int power_state)
{
cpu_do_idle();
return 0;
}

static inline int omap4_mpuss_init(void)
{
return 0;
}

static inline int omap4_finish_suspend(unsigned long cpu_state)
{
return 0;
}

static inline void omap4_cpu_resume(void)
{}
#endif
#endif /* __ASSEMBLER__ */
#endif /* __ARCH_ARM_MACH_OMAP2PLUS_COMMON_H */
9 changes: 9 additions & 0 deletions trunk/arch/arm/mach-omap2/include/mach/omap-secure.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,18 @@
#define OMAP4_HAL_SAVEALL_INDEX 0x1c
#define OMAP4_HAL_SAVEGIC_INDEX 0x1d

/* Secure Monitor mode APIs */
#define OMAP4_MON_SCU_PWR_INDEX 0x108

/* Secure PPA(Primary Protected Application) APIs */
#define OMAP4_PPA_CPU_ACTRL_SMP_INDEX 0x25

#ifndef __ASSEMBLER__

extern u32 omap_secure_dispatcher(u32 idx, u32 flag, u32 nargs,
u32 arg1, u32 arg2, u32 arg3, u32 arg4);
extern u32 omap_smc2(u32 id, u32 falg, u32 pargs);
extern phys_addr_t omap_secure_ram_mempool_base(void);

#endif /* __ASSEMBLER__ */
#endif /* OMAP_ARCH_OMAP_SECURE_H */
248 changes: 248 additions & 0 deletions trunk/arch/arm/mach-omap2/omap-mpuss-lowpower.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
/*
* OMAP MPUSS low power code
*
* Copyright (C) 2011 Texas Instruments, Inc.
* Santosh Shilimkar <santosh.shilimkar@ti.com>
*
* OMAP4430 MPUSS mainly consists of dual Cortex-A9 with per-CPU
* Local timer and Watchdog, GIC, SCU, PL310 L2 cache controller,
* CPU0 and CPU1 LPRM modules.
* CPU0, CPU1 and MPUSS each have there own power domain and
* hence multiple low power combinations of MPUSS are possible.
*
* The CPU0 and CPU1 can't support Closed switch Retention (CSWR)
* because the mode is not supported by hw constraints of dormant
* mode. While waking up from the dormant mode, a reset signal
* to the Cortex-A9 processor must be asserted by the external
* power controller.
*
* With architectural inputs and hardware recommendations, only
* below modes are supported from power gain vs latency point of view.
*
* CPU0 CPU1 MPUSS
* ----------------------------------------------
* ON ON ON
* ON(Inactive) OFF ON(Inactive)
* OFF OFF CSWR
* OFF OFF OSWR (*TBD)
* OFF OFF OFF* (*TBD)
* ----------------------------------------------
*
* Note: CPU0 is the master core and it is the last CPU to go down
* and first to wake-up when MPUSS low power states are excercised
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/

#include <linux/kernel.h>
#include <linux/io.h>
#include <linux/errno.h>
#include <linux/linkage.h>
#include <linux/smp.h>

#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
#include <asm/smp_scu.h>
#include <asm/system.h>
#include <asm/pgalloc.h>
#include <asm/suspend.h>

#include <plat/omap44xx.h>

#include "common.h"
#include "omap4-sar-layout.h"
#include "pm.h"
#include "powerdomain.h"

#ifdef CONFIG_SMP

struct omap4_cpu_pm_info {
struct powerdomain *pwrdm;
void __iomem *scu_sar_addr;
void __iomem *wkup_sar_addr;
};

static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info);

/*
* Program the wakeup routine address for the CPU0 and CPU1
* used for OFF or DORMANT wakeup.
*/
static inline void set_cpu_wakeup_addr(unsigned int cpu_id, u32 addr)
{
struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id);

__raw_writel(addr, pm_info->wkup_sar_addr);
}

/*
* Set the CPUx powerdomain's previous power state
*/
static inline void set_cpu_next_pwrst(unsigned int cpu_id,
unsigned int power_state)
{
struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id);

pwrdm_set_next_pwrst(pm_info->pwrdm, power_state);
}

/*
* Read CPU's previous power state
*/
static inline unsigned int read_cpu_prev_pwrst(unsigned int cpu_id)
{
struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id);

return pwrdm_read_prev_pwrst(pm_info->pwrdm);
}

/*
* Clear the CPUx powerdomain's previous power state
*/
static inline void clear_cpu_prev_pwrst(unsigned int cpu_id)
{
struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id);

pwrdm_clear_all_prev_pwrst(pm_info->pwrdm);
}

/*
* Store the SCU power status value to scratchpad memory
*/
static void scu_pwrst_prepare(unsigned int cpu_id, unsigned int cpu_state)
{
struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id);
u32 scu_pwr_st;

switch (cpu_state) {
case PWRDM_POWER_RET:
scu_pwr_st = SCU_PM_DORMANT;
break;
case PWRDM_POWER_OFF:
scu_pwr_st = SCU_PM_POWEROFF;
break;
case PWRDM_POWER_ON:
case PWRDM_POWER_INACTIVE:
default:
scu_pwr_st = SCU_PM_NORMAL;
break;
}

__raw_writel(scu_pwr_st, pm_info->scu_sar_addr);
}

/**
* omap4_enter_lowpower: OMAP4 MPUSS Low Power Entry Function
* The purpose of this function is to manage low power programming
* of OMAP4 MPUSS subsystem
* @cpu : CPU ID
* @power_state: Low power state.
*/
int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
{
unsigned int save_state = 0;
unsigned int wakeup_cpu;

if (omap_rev() == OMAP4430_REV_ES1_0)
return -ENXIO;

switch (power_state) {
case PWRDM_POWER_ON:
case PWRDM_POWER_INACTIVE:
save_state = 0;
break;
case PWRDM_POWER_OFF:
save_state = 1;
break;
case PWRDM_POWER_RET:
default:
/*
* CPUx CSWR is invalid hardware state. Also CPUx OSWR
* doesn't make much scense, since logic is lost and $L1
* needs to be cleaned because of coherency. This makes
* CPUx OSWR equivalent to CPUX OFF and hence not supported
*/
WARN_ON(1);
return -ENXIO;
}

clear_cpu_prev_pwrst(cpu);
set_cpu_next_pwrst(cpu, power_state);
set_cpu_wakeup_addr(cpu, virt_to_phys(omap4_cpu_resume));
scu_pwrst_prepare(cpu, power_state);

/*
* Call low level function with targeted low power state.
*/
cpu_suspend(save_state, omap4_finish_suspend);

/*
* Restore the CPUx power state to ON otherwise CPUx
* power domain can transitions to programmed low power
* state while doing WFI outside the low powe code. On
* secure devices, CPUx does WFI which can result in
* domain transition
*/
wakeup_cpu = smp_processor_id();
set_cpu_next_pwrst(wakeup_cpu, PWRDM_POWER_ON);

return 0;
}

/*
* Initialise OMAP4 MPUSS
*/
int __init omap4_mpuss_init(void)
{
struct omap4_cpu_pm_info *pm_info;
void __iomem *sar_base = omap4_get_sar_ram_base();

if (omap_rev() == OMAP4430_REV_ES1_0) {
WARN(1, "Power Management not supported on OMAP4430 ES1.0\n");
return -ENODEV;
}

/* Initilaise per CPU PM information */
pm_info = &per_cpu(omap4_pm_info, 0x0);
pm_info->scu_sar_addr = sar_base + SCU_OFFSET0;
pm_info->wkup_sar_addr = sar_base + CPU0_WAKEUP_NS_PA_ADDR_OFFSET;
pm_info->pwrdm = pwrdm_lookup("cpu0_pwrdm");
if (!pm_info->pwrdm) {
pr_err("Lookup failed for CPU0 pwrdm\n");
return -ENODEV;
}

/* Clear CPU previous power domain state */
pwrdm_clear_all_prev_pwrst(pm_info->pwrdm);

/* Initialise CPU0 power domain state to ON */
pwrdm_set_next_pwrst(pm_info->pwrdm, PWRDM_POWER_ON);

pm_info = &per_cpu(omap4_pm_info, 0x1);
pm_info->scu_sar_addr = sar_base + SCU_OFFSET1;
pm_info->wkup_sar_addr = sar_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET;
pm_info->pwrdm = pwrdm_lookup("cpu1_pwrdm");
if (!pm_info->pwrdm) {
pr_err("Lookup failed for CPU1 pwrdm\n");
return -ENODEV;
}

/* Clear CPU previous power domain state */
pwrdm_clear_all_prev_pwrst(pm_info->pwrdm);

/* Initialise CPU1 power domain state to ON */
pwrdm_set_next_pwrst(pm_info->pwrdm, PWRDM_POWER_ON);

/* Save device type on scratchpad for low level code to use */
if (omap_type() != OMAP2_DEVICE_TYPE_GP)
__raw_writel(1, sar_base + OMAP_TYPE_OFFSET);
else
__raw_writel(0, sar_base + OMAP_TYPE_OFFSET);

return 0;
}

#endif
13 changes: 13 additions & 0 deletions trunk/arch/arm/mach-omap2/omap-smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <asm/hardware/gic.h>
#include <asm/smp_scu.h>
#include <mach/hardware.h>
#include <mach/omap-secure.h>

#include "common.h"

Expand All @@ -39,6 +40,18 @@ void __iomem *omap4_get_scu_base(void)

void __cpuinit platform_secondary_init(unsigned int cpu)
{
/*
* Configure ACTRL and enable NS SMP bit access on CPU1 on HS device.
* OMAP44XX EMU/HS devices - CPU0 SMP bit access is enabled in PPA
* init and for CPU1, a secure PPA API provided. CPU0 must be ON
* while executing NS_SMP API on CPU1 and PPA version must be 1.4.0+.
* OMAP443X GP devices- SMP bit isn't accessible.
* OMAP446X GP devices - SMP bit access is enabled on both CPUs.
*/
if (cpu_is_omap443x() && (omap_type() != OMAP2_DEVICE_TYPE_GP))
omap_secure_dispatcher(OMAP4_PPA_CPU_ACTRL_SMP_INDEX,
4, 0, 0, 0, 0, 0);

/*
* If any interrupts are already enabled for the primary
* core (e.g. timer irq), then they will not have been enabled
Expand Down
9 changes: 9 additions & 0 deletions trunk/arch/arm/mach-omap2/omap4-sar-layout.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,13 @@
#define SAR_BANK3_OFFSET 0x2000
#define SAR_BANK4_OFFSET 0x3000

/* Scratch pad memory offsets from SAR_BANK1 */
#define SCU_OFFSET0 0xd00
#define SCU_OFFSET1 0xd04
#define OMAP_TYPE_OFFSET 0xd10

/* CPUx Wakeup Non-Secure Physical Address offsets in SAR_BANK3 */
#define CPU0_WAKEUP_NS_PA_ADDR_OFFSET 0xa04
#define CPU1_WAKEUP_NS_PA_ADDR_OFFSET 0xa08

#endif
Loading

0 comments on commit 351db37

Please sign in to comment.