From patchwork Mon Mar 28 09:22:31 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Santosh Shilimkar X-Patchwork-Id: 667801 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p2S9RAFI004341 for ; Mon, 28 Mar 2011 09:27:14 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752305Ab1C1JXH (ORCPT ); Mon, 28 Mar 2011 05:23:07 -0400 Received: from comal.ext.ti.com ([198.47.26.152]:34460 "EHLO comal.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751857Ab1C1JXB (ORCPT ); Mon, 28 Mar 2011 05:23:01 -0400 Received: from dbdp31.itg.ti.com ([172.24.170.98]) by comal.ext.ti.com (8.13.7/8.13.7) with ESMTP id p2S9MgaS025964 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Mon, 28 Mar 2011 04:22:45 -0500 Received: from linfarm476.india.ti.com (localhost [127.0.0.1]) by dbdp31.itg.ti.com (8.13.8/8.13.8) with ESMTP id p2S9Mg0E002334; Mon, 28 Mar 2011 14:52:42 +0530 (IST) Received: from linfarm476.india.ti.com (localhost [127.0.0.1]) by linfarm476.india.ti.com (8.12.11/8.12.11) with ESMTP id p2S9MfBv002832; Mon, 28 Mar 2011 14:52:41 +0530 Received: (from a0393909@localhost) by linfarm476.india.ti.com (8.12.11/8.12.11/Submit) id p2S9Mfdh002830; Mon, 28 Mar 2011 14:52:41 +0530 From: Santosh Shilimkar To: linux-omap@vger.kernel.org Cc: khilman@ti.com, rnayak@ti.com, linux-arm-kernel@lists.infradead.org, Santosh Shilimkar Subject: [pm-core][PATCH v3 15/21] OMAP4: cpuidle: Basic CPUidle support Date: Mon, 28 Mar 2011 14:52:31 +0530 Message-Id: <1301304157-2466-16-git-send-email-santosh.shilimkar@ti.com> X-Mailer: git-send-email 1.5.6.6 In-Reply-To: <1301304157-2466-1-git-send-email-santosh.shilimkar@ti.com> References: <1301304157-2466-1-git-send-email-santosh.shilimkar@ti.com> Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Mon, 28 Mar 2011 09:27:14 +0000 (UTC) diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 8558215..eec783d 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -64,7 +64,8 @@ obj-$(CONFIG_ARCH_OMAP2) += sleep24xx.o pm_bus.o obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o \ cpuidle34xx.o pm_bus.o obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o pm_bus.o \ - omap4-mpuss-lowpower.o sleep44xx.o + omap4-mpuss-lowpower.o sleep44xx.o \ + cpuidle44xx.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 diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c new file mode 100644 index 0000000..270404f --- /dev/null +++ b/arch/arm/mach-omap2/cpuidle44xx.c @@ -0,0 +1,161 @@ +/* + * OMAP4 CPU idle Routines + * + * Copyright (C) 2011 Texas Instruments, Inc. + * Rajendra Nayak + * + * 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 +#include + +#include + +#include + +#include "pm.h" + +#ifdef CONFIG_CPU_IDLE + +#define OMAP4_MAX_STATES 1 +/* C1 - CPU0 ON + + CPU1 ON + MPU ON + CORE ON */ +#define OMAP4_STATE_C1 0 + +struct omap4_processor_cx { + u8 valid; + u8 type; + u32 sleep_latency; + u32 wakeup_latency; + u32 cpu0_state; + u32 mpu_state; + u32 core_state; + u32 threshold; + u32 flags; +}; + +struct omap4_processor_cx omap4_power_states[OMAP4_MAX_STATES]; + +static struct cpuidle_params cpuidle_params_table[] = { + /* C1 */ + {1, 2, 2, 5}, +}; + +/** + * omap4_enter_idle - Programs OMAP4 to enter the specified state + * @dev: cpuidle device + * @state: The target state to be programmed + * + * Called from the CPUidle framework to program the device to the + * specified low power state selected by the governor. + * Returns the amount of time spent in the low power state. + */ +static int omap4_enter_idle(struct cpuidle_device *dev, + struct cpuidle_state *state) +{ + struct timespec ts_preidle, ts_postidle, ts_idle; + + /* Used to keep track of the total time in idle */ + getnstimeofday(&ts_preidle); + + local_irq_disable(); + local_fiq_disable(); + + cpu_do_idle(); + + getnstimeofday(&ts_postidle); + ts_idle = timespec_sub(ts_postidle, ts_preidle); + + local_irq_enable(); + local_fiq_enable(); + + return ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * USEC_PER_SEC; +} + +DEFINE_PER_CPU(struct cpuidle_device, omap4_idle_dev); + +/** + * omap4_init_power_states - Initialises the OMAP4 specific C states. + * + * Below is the desciption of each C state. + * C1 : CPUx wfi + MPU inative + Core inactive + */ +void omap4_init_power_states(void) +{ + /* + * C1 - CPU0 ON + + CPU1 ON + MPU ON + CORE ON + */ + omap4_power_states[OMAP4_STATE_C1].valid = + cpuidle_params_table[OMAP4_STATE_C1].valid; + omap4_power_states[OMAP4_STATE_C1].type = OMAP4_STATE_C1; + omap4_power_states[OMAP4_STATE_C1].sleep_latency = + cpuidle_params_table[OMAP4_STATE_C1].sleep_latency; + omap4_power_states[OMAP4_STATE_C1].wakeup_latency = + cpuidle_params_table[OMAP4_STATE_C1].wake_latency; + omap4_power_states[OMAP4_STATE_C1].threshold = + cpuidle_params_table[OMAP4_STATE_C1].threshold; + omap4_power_states[OMAP4_STATE_C1].mpu_state = PWRDM_POWER_ON; + omap4_power_states[OMAP4_STATE_C1].core_state = PWRDM_POWER_ON; + omap4_power_states[OMAP4_STATE_C1].flags = CPUIDLE_FLAG_TIME_VALID; + +} + +struct cpuidle_driver omap4_idle_driver = { + .name = "omap4_idle", + .owner = THIS_MODULE, +}; + +/** + * omap4_idle_init - Init routine for OMAP4 idle + * + * Registers the OMAP4 specific cpuidle driver with the cpuidle + * framework with the valid set of states. + */ +int __init omap4_idle_init(void) +{ + int cpu_id = 0, i, count = 0; + struct omap4_processor_cx *cx; + struct cpuidle_state *state; + struct cpuidle_device *dev; + + omap4_init_power_states(); + cpuidle_register_driver(&omap4_idle_driver); + + dev = &per_cpu(omap4_idle_dev, cpu_id); + dev->cpu = cpu_id; + count = 0; + for (i = OMAP4_STATE_C1; i < OMAP4_MAX_STATES; i++) { + cx = &omap4_power_states[i]; + state = &dev->states[count]; + + if (!cx->valid) + continue; + cpuidle_set_statedata(state, cx); + state->exit_latency = cx->sleep_latency + + cx->wakeup_latency; + state->target_residency = cx->threshold; + state->flags = cx->flags; + state->enter = omap4_enter_idle; + sprintf(state->name, "C%d", count+1); + count++; + } + + if (!count) + return -EINVAL; + dev->state_count = count; + + if (cpuidle_register_device(dev)) { + pr_err("%s: CPUidle register device failed\n", __func__); + return -EIO; + } + + return 0; +} +#else +int __init omap4_idle_init(void) +{ + return 0; +} +#endif /* CONFIG_CPU_IDLE */ diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h index 797bfd1..b19d5b2 100644 --- a/arch/arm/mach-omap2/pm.h +++ b/arch/arm/mach-omap2/pm.h @@ -21,6 +21,7 @@ extern void omap_sram_idle(void); extern int omap3_can_sleep(void); extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state); extern int omap3_idle_init(void); +extern int omap4_idle_init(void); #if defined(CONFIG_PM_OPP) extern int omap3_opp_init(void); diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c index af3a56d..b78417c 100644 --- a/arch/arm/mach-omap2/pm44xx.c +++ b/arch/arm/mach-omap2/pm44xx.c @@ -206,6 +206,8 @@ static int __init omap4_pm_init(void) suspend_set_ops(&omap_pm_ops); #endif /* CONFIG_SUSPEND */ + omap4_idle_init(); + err2: return ret; }