943 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			943 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* arch/arm/mach-msm/pm.c
 | 
						|
 *
 | 
						|
 * MSM Power Management Routines
 | 
						|
 *
 | 
						|
 * Copyright (C) 2007 Google, Inc.
 | 
						|
 *
 | 
						|
 * This software is licensed under the terms of the GNU General Public
 | 
						|
 * License version 2, as published by the Free Software Foundation, and
 | 
						|
 * may be copied, distributed, and modified under those terms.
 | 
						|
 *
 | 
						|
 * This program is distributed in the hope that it will be useful,
 | 
						|
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
 * GNU General Public License for more details.
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
#include <linux/module.h>
 | 
						|
#include <linux/kernel.h>
 | 
						|
#include <linux/clk.h>
 | 
						|
#include <linux/console.h>
 | 
						|
#include <linux/delay.h>
 | 
						|
#include <linux/init.h>
 | 
						|
#include <linux/pm.h>
 | 
						|
#include <linux/proc_fs.h>
 | 
						|
#include <linux/suspend.h>
 | 
						|
#include <linux/reboot.h>
 | 
						|
#include <linux/earlysuspend.h>
 | 
						|
#include <mach/msm_iomap.h>
 | 
						|
#include <mach/system.h>
 | 
						|
#include <asm/io.h>
 | 
						|
#ifdef CONFIG_VFP
 | 
						|
#include <asm/vfp.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef CONFIG_CACHE_L2X0
 | 
						|
#include <asm/hardware/cache-l2x0.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include "smd_private.h"
 | 
						|
#include "smd_rpcrouter.h"
 | 
						|
#include "acpuclock.h"
 | 
						|
#include "proc_comm.h"
 | 
						|
#include "pmic_global.h"
 | 
						|
#include "clock.h"
 | 
						|
#include "spm.h"
 | 
						|
#ifdef CONFIG_HAS_WAKELOCK
 | 
						|
#include <linux/wakelock.h>
 | 
						|
#endif
 | 
						|
#include "board-htcleo.h"
 | 
						|
 | 
						|
enum {
 | 
						|
	MSM_PM_DEBUG_SUSPEND = 1U << 0,
 | 
						|
	MSM_PM_DEBUG_POWER_COLLAPSE = 1U << 1,
 | 
						|
	MSM_PM_DEBUG_STATE = 1U << 2,
 | 
						|
	MSM_PM_DEBUG_CLOCK = 1U << 3,
 | 
						|
	MSM_PM_DEBUG_RESET_VECTOR = 1U << 4,
 | 
						|
	MSM_PM_DEBUG_SMSM_STATE = 1U << 5,
 | 
						|
	MSM_PM_DEBUG_IDLE = 1U << 6,
 | 
						|
	MSM_PM_DEBUG_SLEEP_LIMIT = 1U << 7,
 | 
						|
	MSM_PM_DEBUG_WAKEUP_REASON = 1U << 8,
 | 
						|
};
 | 
						|
static int msm_pm_debug_mask = MSM_PM_DEBUG_SLEEP_LIMIT | MSM_PM_DEBUG_WAKEUP_REASON;
 | 
						|
module_param_named(debug_mask, msm_pm_debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
 | 
						|
 | 
						|
enum {
 | 
						|
	MSM_PM_SLEEP_MODE_POWER_COLLAPSE_SUSPEND,
 | 
						|
	MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
 | 
						|
	MSM_PM_SLEEP_MODE_APPS_SLEEP,
 | 
						|
	MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT,
 | 
						|
	MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT,
 | 
						|
};
 | 
						|
static int msm_pm_sleep_mode = CONFIG_MSM7X00A_SLEEP_MODE;
 | 
						|
module_param_named(sleep_mode, msm_pm_sleep_mode, int, S_IRUGO | S_IWUSR | S_IWGRP);
 | 
						|
static int msm_pm_idle_sleep_mode = CONFIG_MSM7X00A_IDLE_SLEEP_MODE;
 | 
						|
module_param_named(idle_sleep_mode, msm_pm_idle_sleep_mode, int, S_IRUGO | S_IWUSR | S_IWGRP);
 | 
						|
static int msm_pm_idle_sleep_min_time = CONFIG_MSM7X00A_IDLE_SLEEP_MIN_TIME;
 | 
						|
module_param_named(idle_sleep_min_time, msm_pm_idle_sleep_min_time, int, S_IRUGO | S_IWUSR | S_IWGRP);
 | 
						|
static int msm_pm_idle_spin_time = CONFIG_MSM7X00A_IDLE_SPIN_TIME;
 | 
						|
module_param_named(idle_spin_time, msm_pm_idle_spin_time, int, S_IRUGO | S_IWUSR | S_IWGRP);
 | 
						|
 | 
						|
#if defined (CONFIG_ARCH_MSM7X30)
 | 
						|
#define A11S_CLK_SLEEP_EN (MSM_GCC_BASE + 0x020)
 | 
						|
#define A11S_PWRDOWN (MSM_ACC_BASE + 0x01C)
 | 
						|
#define A11S_SECOP (MSM_TCSR_BASE + 0x38)
 | 
						|
#else
 | 
						|
#define A11S_CLK_SLEEP_EN (MSM_CSR_BASE + 0x11c)
 | 
						|
#define A11S_PWRDOWN (MSM_CSR_BASE + 0x440)
 | 
						|
#define A11S_STANDBY_CTL (MSM_CSR_BASE + 0x108)
 | 
						|
#endif
 | 
						|
#define A11RAMBACKBIAS (MSM_CSR_BASE + 0x508)
 | 
						|
 | 
						|
#if defined(CONFIG_MSM_N_WAY_SMD)
 | 
						|
#define DEM_MASTER_BITS_PER_CPU             6
 | 
						|
 | 
						|
/* Power Master State Bits - Per CPU */
 | 
						|
#define DEM_MASTER_SMSM_RUN \
 | 
						|
        (0x01UL << (DEM_MASTER_BITS_PER_CPU * SMSM_STATE_APPS))
 | 
						|
#define DEM_MASTER_SMSM_RSA \
 | 
						|
        (0x02UL << (DEM_MASTER_BITS_PER_CPU * SMSM_STATE_APPS))
 | 
						|
#define DEM_MASTER_SMSM_PWRC_EARLY_EXIT \
 | 
						|
        (0x04UL << (DEM_MASTER_BITS_PER_CPU * SMSM_STATE_APPS))
 | 
						|
#define DEM_MASTER_SMSM_SLEEP_EXIT \
 | 
						|
        (0x08UL << (DEM_MASTER_BITS_PER_CPU * SMSM_STATE_APPS))
 | 
						|
#define DEM_MASTER_SMSM_READY \
 | 
						|
        (0x10UL << (DEM_MASTER_BITS_PER_CPU * SMSM_STATE_APPS))
 | 
						|
#define DEM_MASTER_SMSM_SLEEP \
 | 
						|
        (0x20UL << (DEM_MASTER_BITS_PER_CPU * SMSM_STATE_APPS))
 | 
						|
 | 
						|
/* Power Slave State Bits */
 | 
						|
#define DEM_SLAVE_SMSM_RUN                  (0x0001)
 | 
						|
#define DEM_SLAVE_SMSM_PWRC                 (0x0002)
 | 
						|
#define DEM_SLAVE_SMSM_PWRC_DELAY           (0x0004)
 | 
						|
#define DEM_SLAVE_SMSM_PWRC_EARLY_EXIT      (0x0008)
 | 
						|
#define DEM_SLAVE_SMSM_WFPI                 (0x0010)
 | 
						|
#define DEM_SLAVE_SMSM_SLEEP                (0x0020)
 | 
						|
#define DEM_SLAVE_SMSM_SLEEP_EXIT           (0x0040)
 | 
						|
#define DEM_SLAVE_SMSM_MSGS_REDUCED         (0x0080)
 | 
						|
#define DEM_SLAVE_SMSM_RESET                (0x0100)
 | 
						|
#define DEM_SLAVE_SMSM_PWRC_SUSPEND         (0x0200)
 | 
						|
 | 
						|
#define PM_SMSM_WRITE_STATE	SMSM_STATE_APPS_DEM
 | 
						|
#define PM_SMSM_READ_STATE	SMSM_STATE_POWER_MASTER_DEM
 | 
						|
 | 
						|
#define PM_SMSM_WRITE_RUN	DEM_SLAVE_SMSM_RUN
 | 
						|
#define PM_SMSM_READ_RUN	DEM_MASTER_SMSM_RUN
 | 
						|
#else
 | 
						|
#define PM_SMSM_WRITE_STATE     SMSM_STATE_APPS
 | 
						|
#define PM_SMSM_READ_STATE      SMSM_STATE_MODEM
 | 
						|
 | 
						|
#define PM_SMSM_WRITE_RUN       SMSM_RUN
 | 
						|
#define PM_SMSM_READ_RUN        SMSM_RUN
 | 
						|
#endif
 | 
						|
 | 
						|
int msm_pm_collapse(void);
 | 
						|
int msm_arch_idle(void);
 | 
						|
void msm_pm_collapse_exit(void);
 | 
						|
 | 
						|
int64_t msm_timer_enter_idle(void);
 | 
						|
void msm_timer_exit_idle(int low_power);
 | 
						|
int msm_irq_idle_sleep_allowed(void);
 | 
						|
int msm_irq_pending(void);
 | 
						|
int clks_allow_tcxo_locked_debug(void);
 | 
						|
extern int board_mfg_mode(void);
 | 
						|
extern char * board_get_mfg_sleep_gpio_table(void);
 | 
						|
extern void gpio_set_diag_gpio_table(unsigned long * dwMFG_gpio_table);
 | 
						|
extern void wait_rmt_final_call_back(int timeout);
 | 
						|
 | 
						|
static int axi_rate;
 | 
						|
static int sleep_axi_rate;
 | 
						|
static struct clk *axi_clk;
 | 
						|
static uint32_t *msm_pm_reset_vector;
 | 
						|
 | 
						|
static uint32_t msm_pm_max_sleep_time;
 | 
						|
 | 
						|
#ifdef CONFIG_MSM_IDLE_STATS
 | 
						|
enum msm_pm_time_stats_id {
 | 
						|
	MSM_PM_STAT_REQUESTED_IDLE,
 | 
						|
	MSM_PM_STAT_IDLE_SPIN,
 | 
						|
	MSM_PM_STAT_IDLE_WFI,
 | 
						|
	MSM_PM_STAT_IDLE_SLEEP,
 | 
						|
	MSM_PM_STAT_IDLE_FAILED_SLEEP,
 | 
						|
	MSM_PM_STAT_NOT_IDLE,
 | 
						|
	MSM_PM_STAT_COUNT
 | 
						|
};
 | 
						|
 | 
						|
static struct msm_pm_time_stats {
 | 
						|
	const char *name;
 | 
						|
	int bucket[CONFIG_MSM_IDLE_STATS_BUCKET_COUNT];
 | 
						|
	int64_t min_time[CONFIG_MSM_IDLE_STATS_BUCKET_COUNT];
 | 
						|
	int64_t max_time[CONFIG_MSM_IDLE_STATS_BUCKET_COUNT];
 | 
						|
	int count;
 | 
						|
	int64_t total_time;
 | 
						|
} msm_pm_stats[MSM_PM_STAT_COUNT] = {
 | 
						|
	[MSM_PM_STAT_REQUESTED_IDLE].name = "idle-request",
 | 
						|
	[MSM_PM_STAT_IDLE_SPIN].name = "idle-spin",
 | 
						|
	[MSM_PM_STAT_IDLE_WFI].name = "idle-wfi",
 | 
						|
	[MSM_PM_STAT_IDLE_SLEEP].name = "idle-sleep",
 | 
						|
	[MSM_PM_STAT_IDLE_FAILED_SLEEP].name = "idle-failed-sleep",
 | 
						|
	[MSM_PM_STAT_NOT_IDLE].name = "not-idle",
 | 
						|
};
 | 
						|
 | 
						|
static void msm_pm_add_stat(enum msm_pm_time_stats_id id, int64_t t)
 | 
						|
{
 | 
						|
	int i;
 | 
						|
	int64_t bt;
 | 
						|
	msm_pm_stats[id].total_time += t;
 | 
						|
	msm_pm_stats[id].count++;
 | 
						|
	bt = t;
 | 
						|
	do_div(bt, CONFIG_MSM_IDLE_STATS_FIRST_BUCKET);
 | 
						|
	if (bt < 1ULL << (CONFIG_MSM_IDLE_STATS_BUCKET_SHIFT *
 | 
						|
				(CONFIG_MSM_IDLE_STATS_BUCKET_COUNT - 1)))
 | 
						|
		i = DIV_ROUND_UP(fls((uint32_t)bt),
 | 
						|
					CONFIG_MSM_IDLE_STATS_BUCKET_SHIFT);
 | 
						|
	else
 | 
						|
		i = CONFIG_MSM_IDLE_STATS_BUCKET_COUNT - 1;
 | 
						|
	msm_pm_stats[id].bucket[i]++;
 | 
						|
	if (t < msm_pm_stats[id].min_time[i] || !msm_pm_stats[id].max_time[i])
 | 
						|
		msm_pm_stats[id].min_time[i] = t;
 | 
						|
	if (t > msm_pm_stats[id].max_time[i])
 | 
						|
		msm_pm_stats[id].max_time[i] = t;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
static int
 | 
						|
msm_pm_wait_state(uint32_t wait_all_set, uint32_t wait_all_clear,
 | 
						|
                  uint32_t wait_any_set, uint32_t wait_any_clear)
 | 
						|
{
 | 
						|
	int i;
 | 
						|
	uint32_t state;
 | 
						|
 | 
						|
	for (i = 0; i < 100000; i++) {
 | 
						|
		state = smsm_get_state(PM_SMSM_READ_STATE);
 | 
						|
		if (((wait_all_set || wait_all_clear) && 
 | 
						|
		     !(~state & wait_all_set) && !(state & wait_all_clear)) ||
 | 
						|
		    (state & wait_any_set) || (~state & wait_any_clear))
 | 
						|
			return 0;
 | 
						|
		udelay(1);
 | 
						|
	}
 | 
						|
	pr_err("msm_pm_wait_state(%x, %x, %x, %x) failed %x\n",	wait_all_set,
 | 
						|
		wait_all_clear, wait_any_set, wait_any_clear, state);
 | 
						|
	return -ETIMEDOUT;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * For speeding up boot time:
 | 
						|
 * During booting up, disable entering arch_idle() by disable_hlt()
 | 
						|
 * Enable it after booting up BOOT_LOCK_TIMEOUT sec.
 | 
						|
 */
 | 
						|
#define BOOT_LOCK_TIMEOUT      (60 * HZ)
 | 
						|
static void do_expire_boot_lock(struct work_struct *work)
 | 
						|
{
 | 
						|
	enable_hlt();
 | 
						|
	pr_info("Release 'boot-time' halt_lock\n");
 | 
						|
}
 | 
						|
static DECLARE_DELAYED_WORK(work_expire_boot_lock, do_expire_boot_lock);
 | 
						|
 | 
						|
#ifdef CONFIG_MSM_FIQ_SUPPORT
 | 
						|
void msm_fiq_exit_sleep(void);
 | 
						|
#else
 | 
						|
static inline void msm_fiq_exit_sleep(void) { }
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef CONFIG_HTC_POWER_COLLAPSE_MAGIC
 | 
						|
/* Set magic number in SMEM for power collapse state */
 | 
						|
#define HTC_POWER_COLLAPSE_ADD	(MSM_SHARED_RAM_BASE + 0x000F8000 + 0x000007F8)
 | 
						|
#define HTC_POWER_COLLAPSE_MAGIC_NUM	(HTC_POWER_COLLAPSE_ADD - 0x04)
 | 
						|
unsigned int magic_num;
 | 
						|
#endif
 | 
						|
 | 
						|
static int msm_sleep(int sleep_mode, uint32_t sleep_delay, int from_idle)
 | 
						|
{
 | 
						|
	uint32_t saved_vector[2];
 | 
						|
	int collapsed;
 | 
						|
	void msm_irq_enter_sleep1(bool arm9_wake, int from_idle);
 | 
						|
	int msm_irq_enter_sleep2(bool arm9_wake, int from_idle);
 | 
						|
	void msm_irq_exit_sleep1(void);
 | 
						|
	void msm_irq_exit_sleep2(void);
 | 
						|
	void msm_irq_exit_sleep3(void);
 | 
						|
	void msm_gpio_enter_sleep(int from_idle);
 | 
						|
	void msm_gpio_exit_sleep(void);
 | 
						|
	void smd_sleep_exit(void);
 | 
						|
	uint32_t enter_state;
 | 
						|
	uint32_t enter_wait_set = 0;
 | 
						|
	uint32_t enter_wait_clear = 0;
 | 
						|
	uint32_t exit_state;
 | 
						|
	uint32_t exit_wait_clear = 0;
 | 
						|
	uint32_t exit_wait_any_set = 0;
 | 
						|
	unsigned long pm_saved_acpu_clk_rate = 0;
 | 
						|
	int ret;
 | 
						|
	int rv = -EINTR;
 | 
						|
	bool invalid_inital_state = false;
 | 
						|
#if defined(CONFIG_MACH_HTCLEO) 
 | 
						|
	if(!htcleo_is_nand_boot() && sleep_mode<2)
 | 
						|
		sleep_mode=2;
 | 
						|
#endif
 | 
						|
	if (board_mfg_mode() == 4) /*power test mode*/
 | 
						|
		gpio_set_diag_gpio_table(board_get_mfg_sleep_gpio_table());
 | 
						|
 | 
						|
	if (msm_pm_debug_mask & MSM_PM_DEBUG_SUSPEND)
 | 
						|
		printk(KERN_INFO "msm_sleep(): mode %d delay %u idle %d\n",
 | 
						|
		       sleep_mode, sleep_delay, from_idle);
 | 
						|
#if defined(CONFIG_MSM_N_WAY_SMD)
 | 
						|
	switch (sleep_mode) {
 | 
						|
	case MSM_PM_SLEEP_MODE_POWER_COLLAPSE:
 | 
						|
		enter_state = DEM_SLAVE_SMSM_PWRC;
 | 
						|
		enter_wait_set = DEM_MASTER_SMSM_RSA;
 | 
						|
		exit_state = DEM_SLAVE_SMSM_WFPI;
 | 
						|
		exit_wait_any_set =
 | 
						|
			DEM_MASTER_SMSM_RUN | DEM_MASTER_SMSM_PWRC_EARLY_EXIT;
 | 
						|
		break;
 | 
						|
	case MSM_PM_SLEEP_MODE_POWER_COLLAPSE_SUSPEND:
 | 
						|
		enter_state = DEM_SLAVE_SMSM_PWRC_SUSPEND;
 | 
						|
		enter_wait_set = DEM_MASTER_SMSM_RSA;
 | 
						|
		exit_state = DEM_SLAVE_SMSM_WFPI;
 | 
						|
		exit_wait_any_set =
 | 
						|
			DEM_MASTER_SMSM_RUN | DEM_MASTER_SMSM_PWRC_EARLY_EXIT;
 | 
						|
		break;
 | 
						|
	case MSM_PM_SLEEP_MODE_APPS_SLEEP:
 | 
						|
		enter_state = DEM_SLAVE_SMSM_SLEEP;
 | 
						|
		enter_wait_set = DEM_MASTER_SMSM_SLEEP;
 | 
						|
		exit_state = DEM_SLAVE_SMSM_SLEEP_EXIT;
 | 
						|
		exit_wait_any_set = DEM_MASTER_SMSM_SLEEP_EXIT;
 | 
						|
		break;
 | 
						|
	default:
 | 
						|
		enter_state = 0;
 | 
						|
		exit_state = 0;
 | 
						|
	}
 | 
						|
#else
 | 
						|
	switch (sleep_mode) {
 | 
						|
	case MSM_PM_SLEEP_MODE_POWER_COLLAPSE:
 | 
						|
		enter_state = SMSM_PWRC;
 | 
						|
		enter_wait_set = SMSM_RSA;
 | 
						|
		exit_state = SMSM_WFPI;
 | 
						|
		exit_wait_clear = SMSM_RSA;
 | 
						|
		break;
 | 
						|
	case MSM_PM_SLEEP_MODE_POWER_COLLAPSE_SUSPEND:
 | 
						|
		enter_state = SMSM_PWRC_SUSPEND;
 | 
						|
		enter_wait_set = SMSM_RSA;
 | 
						|
		exit_state = SMSM_WFPI;
 | 
						|
		exit_wait_clear = SMSM_RSA;
 | 
						|
		break;
 | 
						|
	case MSM_PM_SLEEP_MODE_APPS_SLEEP:
 | 
						|
		enter_state = SMSM_SLEEP;
 | 
						|
		exit_state = SMSM_SLEEPEXIT;
 | 
						|
		exit_wait_any_set = SMSM_SLEEPEXIT;
 | 
						|
		break;
 | 
						|
	default:
 | 
						|
		enter_state = 0;
 | 
						|
		exit_state = 0;
 | 
						|
	}
 | 
						|
#endif
 | 
						|
	clk_enter_sleep(from_idle);
 | 
						|
	msm_irq_enter_sleep1(!!enter_state, from_idle);
 | 
						|
	msm_gpio_enter_sleep(from_idle);
 | 
						|
 | 
						|
	if (enter_state) {
 | 
						|
		/* Make sure last sleep request did not end with a timeout */
 | 
						|
		ret = msm_pm_wait_state(PM_SMSM_READ_RUN, 0, 0, 0);
 | 
						|
		if (ret) {
 | 
						|
			printk(KERN_ERR "msm_sleep(): invalid inital state\n");
 | 
						|
			invalid_inital_state = true;
 | 
						|
		}
 | 
						|
 | 
						|
		if (sleep_delay == 0 && sleep_mode >= MSM_PM_SLEEP_MODE_APPS_SLEEP)
 | 
						|
			sleep_delay = 192000*5; /* APPS_SLEEP does not allow infinite timeout */
 | 
						|
		ret = smsm_set_sleep_duration(sleep_delay);
 | 
						|
		if (ret) {
 | 
						|
			printk(KERN_ERR "msm_sleep(): smsm_set_sleep_duration %x failed\n", enter_state);
 | 
						|
			enter_state = 0;
 | 
						|
			exit_state = 0;
 | 
						|
		}
 | 
						|
		if ((!from_idle && msm_pm_debug_mask & MSM_PM_DEBUG_SLEEP_LIMIT) ||
 | 
						|
			(from_idle && msm_pm_debug_mask & MSM_PM_DEBUG_IDLE))
 | 
						|
			clks_allow_tcxo_locked_debug();
 | 
						|
 | 
						|
		ret = smsm_change_state(PM_SMSM_WRITE_STATE, PM_SMSM_WRITE_RUN, enter_state);
 | 
						|
		if (ret) {
 | 
						|
			printk(KERN_ERR "msm_sleep(): smsm_change_state %x failed\n", enter_state);
 | 
						|
			enter_state = 0;
 | 
						|
			exit_state = 0;
 | 
						|
		}
 | 
						|
		ret = msm_pm_wait_state(enter_wait_set, enter_wait_clear, 0, 0);
 | 
						|
		if (ret || invalid_inital_state) {
 | 
						|
			printk(KERN_INFO "msm_sleep(): msm_pm_wait_state failed, %x\n", smsm_get_state(PM_SMSM_READ_STATE));
 | 
						|
			goto enter_failed;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if (msm_irq_enter_sleep2(!!enter_state, from_idle))
 | 
						|
		goto enter_failed;
 | 
						|
 | 
						|
	if (enter_state) {
 | 
						|
#if defined (CONFIG_ARCH_MSM7X30)
 | 
						|
		writel(1, A11S_PWRDOWN);
 | 
						|
		writel(4, A11S_SECOP);
 | 
						|
#else
 | 
						|
		writel(0x1f, A11S_CLK_SLEEP_EN);
 | 
						|
		writel(1, A11S_PWRDOWN);
 | 
						|
 | 
						|
		writel(0, A11S_STANDBY_CTL);
 | 
						|
#endif
 | 
						|
#if !defined(CONFIG_MSM_N_WAY_SMD)
 | 
						|
		writel(0, A11RAMBACKBIAS);
 | 
						|
#endif
 | 
						|
 | 
						|
		if (msm_pm_debug_mask & MSM_PM_DEBUG_STATE)
 | 
						|
			printk(KERN_INFO "msm_sleep(): enter "
 | 
						|
			       "A11S_CLK_SLEEP_EN %x, A11S_PWRDOWN %x, "
 | 
						|
			       "smsm_get_state %x\n", readl(A11S_CLK_SLEEP_EN),
 | 
						|
			       readl(A11S_PWRDOWN), smsm_get_state(PM_SMSM_READ_STATE));
 | 
						|
	}
 | 
						|
 | 
						|
	if (sleep_mode <= MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT) {
 | 
						|
		pm_saved_acpu_clk_rate = acpuclk_power_collapse(from_idle);
 | 
						|
		if (msm_pm_debug_mask & MSM_PM_DEBUG_CLOCK)
 | 
						|
			printk(KERN_INFO "msm_sleep(): %ld enter power collapse"
 | 
						|
			       "\n", pm_saved_acpu_clk_rate);
 | 
						|
		if (pm_saved_acpu_clk_rate == 0)
 | 
						|
			goto ramp_down_failed;
 | 
						|
 | 
						|
#ifdef CONFIG_AXI_SCREEN_POLICY
 | 
						|
		/* Drop AXI request when the screen is on */
 | 
						|
		if (axi_rate)
 | 
						|
			clk_set_rate(axi_clk, sleep_axi_rate);
 | 
						|
#endif
 | 
						|
	}
 | 
						|
#ifdef CONFIG_HTC_POWER_COLLAPSE_MAGIC
 | 
						|
	magic_num = 0xAAAA1111;
 | 
						|
	writel(magic_num, HTC_POWER_COLLAPSE_MAGIC_NUM);
 | 
						|
#endif
 | 
						|
	if (sleep_mode < MSM_PM_SLEEP_MODE_APPS_SLEEP) {
 | 
						|
		if (msm_pm_debug_mask & MSM_PM_DEBUG_SMSM_STATE)
 | 
						|
			smsm_print_sleep_info(0);
 | 
						|
		saved_vector[0] = msm_pm_reset_vector[0];
 | 
						|
		saved_vector[1] = msm_pm_reset_vector[1];
 | 
						|
		msm_pm_reset_vector[0] = 0xE51FF004; /* ldr pc, 4 */
 | 
						|
		msm_pm_reset_vector[1] = virt_to_phys(msm_pm_collapse_exit);
 | 
						|
		if (msm_pm_debug_mask & MSM_PM_DEBUG_RESET_VECTOR)
 | 
						|
			printk(KERN_INFO "msm_sleep(): vector %x %x -> "
 | 
						|
			       "%x %x\n", saved_vector[0], saved_vector[1],
 | 
						|
			       msm_pm_reset_vector[0], msm_pm_reset_vector[1]);
 | 
						|
#ifdef CONFIG_VFP
 | 
						|
		if (from_idle)
 | 
						|
			vfp_flush_context();
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef CONFIG_CACHE_L2X0
 | 
						|
		l2x0_suspend();
 | 
						|
#endif
 | 
						|
		if (!from_idle) printk(KERN_INFO "[R] suspend end\n");
 | 
						|
		/* reset idle sleep mode when suspend. */
 | 
						|
		if (!from_idle) msm_pm_idle_sleep_mode = CONFIG_MSM7X00A_IDLE_SLEEP_MODE;
 | 
						|
		collapsed = msm_pm_collapse();
 | 
						|
		if (!from_idle) printk(KERN_INFO "[R] resume start\n");
 | 
						|
#ifdef CONFIG_CACHE_L2X0
 | 
						|
		l2x0_resume(collapsed);
 | 
						|
#endif
 | 
						|
		msm_pm_reset_vector[0] = saved_vector[0];
 | 
						|
		msm_pm_reset_vector[1] = saved_vector[1];
 | 
						|
		if (collapsed) {
 | 
						|
#ifdef CONFIG_VFP
 | 
						|
			if (from_idle)
 | 
						|
				vfp_reinit();
 | 
						|
#endif
 | 
						|
			cpu_init();
 | 
						|
			__asm__("cpsie   a");
 | 
						|
			msm_fiq_exit_sleep();
 | 
						|
			local_fiq_enable();
 | 
						|
			rv = 0;
 | 
						|
		}
 | 
						|
		if (msm_pm_debug_mask & MSM_PM_DEBUG_POWER_COLLAPSE)
 | 
						|
			printk(KERN_INFO "msm_pm_collapse(): returned %d\n",
 | 
						|
			       collapsed);
 | 
						|
		if (msm_pm_debug_mask & MSM_PM_DEBUG_SMSM_STATE)
 | 
						|
			smsm_print_sleep_info(0);
 | 
						|
	} else {
 | 
						|
		msm_arch_idle();
 | 
						|
		rv = 0;
 | 
						|
	}
 | 
						|
#ifdef CONFIG_HTC_POWER_COLLAPSE_MAGIC
 | 
						|
	magic_num = 0xBBBB9999;
 | 
						|
	writel(magic_num, HTC_POWER_COLLAPSE_MAGIC_NUM);
 | 
						|
#endif
 | 
						|
	if (sleep_mode <= MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT) {
 | 
						|
		if (msm_pm_debug_mask & MSM_PM_DEBUG_CLOCK)
 | 
						|
			printk(KERN_INFO "msm_sleep(): exit power collapse %ld"
 | 
						|
			       "\n", pm_saved_acpu_clk_rate);
 | 
						|
#if defined(CONFIG_ARCH_QSD8X50)
 | 
						|
		if (acpuclk_set_rate(pm_saved_acpu_clk_rate, 1) < 0)
 | 
						|
#else
 | 
						|
		if (acpuclk_set_rate(pm_saved_acpu_clk_rate,
 | 
						|
			from_idle ? SETRATE_PC_IDLE : SETRATE_PC) < 0)
 | 
						|
#endif
 | 
						|
			printk(KERN_ERR "msm_sleep(): clk_set_rate %ld "
 | 
						|
			       "failed\n", pm_saved_acpu_clk_rate);
 | 
						|
 | 
						|
#ifdef CONFIG_AXI_SCREEN_POLICY
 | 
						|
		/* Restore axi rate if needed */
 | 
						|
		if (axi_rate)
 | 
						|
			clk_set_rate(axi_clk, axi_rate);
 | 
						|
#endif
 | 
						|
	}
 | 
						|
	if (msm_pm_debug_mask & MSM_PM_DEBUG_STATE)
 | 
						|
		printk(KERN_INFO "msm_sleep(): exit A11S_CLK_SLEEP_EN %x, "
 | 
						|
		       "A11S_PWRDOWN %x, smsm_get_state %x\n",
 | 
						|
		       readl(A11S_CLK_SLEEP_EN), readl(A11S_PWRDOWN),
 | 
						|
		       smsm_get_state(PM_SMSM_READ_STATE));
 | 
						|
ramp_down_failed:
 | 
						|
	msm_irq_exit_sleep1();
 | 
						|
enter_failed:
 | 
						|
	if (enter_state) {
 | 
						|
#if defined (CONFIG_ARCH_MSM7X30)
 | 
						|
		writel(0, A11S_SECOP);
 | 
						|
		writel(0, A11S_PWRDOWN);
 | 
						|
		msm_spm_reinit();
 | 
						|
#else
 | 
						|
		writel(0x00, A11S_CLK_SLEEP_EN);
 | 
						|
		writel(0, A11S_PWRDOWN);
 | 
						|
#endif
 | 
						|
		smsm_change_state(PM_SMSM_WRITE_STATE, enter_state, exit_state);
 | 
						|
		msm_pm_wait_state(0, exit_wait_clear, exit_wait_any_set, 0);
 | 
						|
		if (msm_pm_debug_mask & MSM_PM_DEBUG_STATE)
 | 
						|
			printk(KERN_INFO "msm_sleep(): sleep exit "
 | 
						|
			       "A11S_CLK_SLEEP_EN %x, A11S_PWRDOWN %x, "
 | 
						|
			       "smsm_get_state %x\n", readl(A11S_CLK_SLEEP_EN),
 | 
						|
			       readl(A11S_PWRDOWN), smsm_get_state(PM_SMSM_READ_STATE));
 | 
						|
		if (msm_pm_debug_mask & MSM_PM_DEBUG_SMSM_STATE)
 | 
						|
			smsm_print_sleep_info(0);
 | 
						|
		if (msm_pm_debug_mask & MSM_PM_DEBUG_WAKEUP_REASON && !from_idle)
 | 
						|
			smsm_print_sleep_info(1);
 | 
						|
	}
 | 
						|
	msm_irq_exit_sleep2();
 | 
						|
	if (enter_state) {
 | 
						|
		smsm_change_state(PM_SMSM_WRITE_STATE, exit_state, PM_SMSM_WRITE_RUN);
 | 
						|
		msm_pm_wait_state(PM_SMSM_READ_RUN, 0, 0, 0);
 | 
						|
		if (msm_pm_debug_mask & MSM_PM_DEBUG_STATE)
 | 
						|
			printk(KERN_INFO "msm_sleep(): sleep exit "
 | 
						|
			       "A11S_CLK_SLEEP_EN %x, A11S_PWRDOWN %x, "
 | 
						|
			       "smsm_get_state %x\n", readl(A11S_CLK_SLEEP_EN),
 | 
						|
			       readl(A11S_PWRDOWN), smsm_get_state(PM_SMSM_READ_STATE));
 | 
						|
	}
 | 
						|
	msm_irq_exit_sleep3();
 | 
						|
	msm_gpio_exit_sleep();
 | 
						|
	smd_sleep_exit();
 | 
						|
	clk_exit_sleep();
 | 
						|
	return rv;
 | 
						|
}
 | 
						|
 | 
						|
static int msm_pm_idle_spin(void)
 | 
						|
{
 | 
						|
	int spin;
 | 
						|
	spin = msm_pm_idle_spin_time >> 10;
 | 
						|
	while (spin-- > 0) {
 | 
						|
		if (msm_irq_pending()) {
 | 
						|
			return -1;
 | 
						|
		}
 | 
						|
		udelay(1);
 | 
						|
	}
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
void arch_idle(void)
 | 
						|
{
 | 
						|
	int ret;
 | 
						|
	int64_t sleep_time;
 | 
						|
	int low_power = 0;
 | 
						|
#ifdef CONFIG_MSM_IDLE_STATS
 | 
						|
	int64_t t1;
 | 
						|
	static int64_t t2;
 | 
						|
	int exit_stat;
 | 
						|
#endif
 | 
						|
	int allow_sleep =
 | 
						|
		msm_pm_idle_sleep_mode < MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT &&
 | 
						|
#ifdef CONFIG_HAS_WAKELOCK
 | 
						|
		!has_wake_lock(WAKE_LOCK_IDLE) &&
 | 
						|
#endif
 | 
						|
		msm_irq_idle_sleep_allowed();
 | 
						|
	if (msm_pm_reset_vector == NULL)
 | 
						|
		return;
 | 
						|
 | 
						|
	sleep_time = msm_timer_enter_idle();
 | 
						|
#ifdef CONFIG_MSM_IDLE_STATS
 | 
						|
	t1 = ktime_to_ns(ktime_get());
 | 
						|
	msm_pm_add_stat(MSM_PM_STAT_NOT_IDLE, t1 - t2);
 | 
						|
	msm_pm_add_stat(MSM_PM_STAT_REQUESTED_IDLE, sleep_time);
 | 
						|
#endif
 | 
						|
	if (msm_pm_debug_mask & MSM_PM_DEBUG_IDLE)
 | 
						|
		printk(KERN_INFO "arch_idle: sleep time %llu, allow_sleep %d\n",
 | 
						|
		       sleep_time, allow_sleep);
 | 
						|
	if (sleep_time < msm_pm_idle_sleep_min_time || !allow_sleep) {
 | 
						|
		unsigned long saved_rate;
 | 
						|
		/* only spin while trying wfi ramp down */
 | 
						|
		if (acpuclk_get_wfi_rate() && msm_pm_idle_spin() < 0) {
 | 
						|
#ifdef CONFIG_MSM_IDLE_STATS
 | 
						|
			exit_stat = MSM_PM_STAT_IDLE_SPIN;
 | 
						|
#endif
 | 
						|
			goto abort_idle;
 | 
						|
		}
 | 
						|
		saved_rate = acpuclk_wait_for_irq();
 | 
						|
 | 
						|
 | 
						|
		if (saved_rate && msm_pm_debug_mask & MSM_PM_DEBUG_CLOCK)
 | 
						|
			printk(KERN_DEBUG "arch_idle: clk %ld -> swfi\n",
 | 
						|
				saved_rate);
 | 
						|
 | 
						|
		/*
 | 
						|
		 * If there is a wfi speed specified and we failed to ramp, do not
 | 
						|
		 * go into wfi.
 | 
						|
		 */
 | 
						|
		if (acpuclk_get_wfi_rate() && !saved_rate)
 | 
						|
			while (!msm_irq_pending())
 | 
						|
				udelay(1);
 | 
						|
		else
 | 
						|
			msm_arch_idle();
 | 
						|
 | 
						|
		if (msm_pm_debug_mask & MSM_PM_DEBUG_CLOCK)
 | 
						|
			printk(KERN_DEBUG "msm_sleep: clk swfi -> %ld\n",
 | 
						|
				saved_rate);
 | 
						|
#if defined(CONFIG_ARCH_QSD8X50)
 | 
						|
		if (saved_rate && acpuclk_set_rate(saved_rate, 1) < 0)
 | 
						|
#else
 | 
						|
		if (saved_rate
 | 
						|
		    && acpuclk_set_rate(saved_rate, SETRATE_SWFI) < 0)
 | 
						|
#endif
 | 
						|
			printk(KERN_ERR "msm_sleep(): clk_set_rate %ld "
 | 
						|
			       "failed\n", saved_rate);
 | 
						|
#ifdef CONFIG_MSM_IDLE_STATS
 | 
						|
		exit_stat = MSM_PM_STAT_IDLE_WFI;
 | 
						|
#endif
 | 
						|
  	} else {
 | 
						|
		if (msm_pm_idle_spin() < 0) {
 | 
						|
#ifdef CONFIG_MSM_IDLE_STATS
 | 
						|
			exit_stat = MSM_PM_STAT_IDLE_SPIN;
 | 
						|
#endif
 | 
						|
			goto abort_idle;
 | 
						|
		}
 | 
						|
 | 
						|
		low_power = 1;
 | 
						|
		do_div(sleep_time, NSEC_PER_SEC / 32768);
 | 
						|
		if (sleep_time > 0x6DDD000) {
 | 
						|
			printk("sleep_time too big %lld\n", sleep_time);
 | 
						|
			sleep_time = 0x6DDD000;
 | 
						|
		}
 | 
						|
		ret = msm_sleep(msm_pm_idle_sleep_mode, sleep_time, 1);
 | 
						|
#ifdef CONFIG_MSM_IDLE_STATS
 | 
						|
		if (ret)
 | 
						|
			exit_stat = MSM_PM_STAT_IDLE_FAILED_SLEEP;
 | 
						|
		else
 | 
						|
			exit_stat = MSM_PM_STAT_IDLE_SLEEP;
 | 
						|
#endif
 | 
						|
	}
 | 
						|
abort_idle:
 | 
						|
	msm_timer_exit_idle(low_power);
 | 
						|
#ifdef CONFIG_MSM_IDLE_STATS
 | 
						|
	t2 = ktime_to_ns(ktime_get());
 | 
						|
	msm_pm_add_stat(exit_stat, t2 - t1);
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
static int msm_pm_enter(suspend_state_t state)
 | 
						|
{
 | 
						|
	msm_sleep(msm_pm_sleep_mode, msm_pm_max_sleep_time, 0);
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
static struct platform_suspend_ops msm_pm_ops = {
 | 
						|
	.enter		= msm_pm_enter,
 | 
						|
	.valid		= suspend_valid_only_mem,
 | 
						|
};
 | 
						|
 | 
						|
static uint32_t restart_reason = 0x776655AA;
 | 
						|
 | 
						|
static int msm_wakeup_after;	/* default, no wakeup by alarm */
 | 
						|
static int msm_power_wakeup_after(const char *val, struct kernel_param *kp)
 | 
						|
{
 | 
						|
	int ret;
 | 
						|
	struct uart_port *port;
 | 
						|
	struct msm_port *msm_port;
 | 
						|
 | 
						|
	ret = param_set_int(val, kp);
 | 
						|
	printk(KERN_INFO "+msm_power_wakeup_after, ret=%d\r\n", ret);
 | 
						|
 | 
						|
	if (!ret) {
 | 
						|
		printk(KERN_INFO "msm_wakeup_after=%d\r\n", msm_wakeup_after);
 | 
						|
		if (msm_wakeup_after < 0)
 | 
						|
			msm_wakeup_after = 0; /* invalid, no wakeup */
 | 
						|
	}
 | 
						|
	printk(KERN_INFO "-msm_power_wakeup_after, msm_wakeup_after=%d\r\n", msm_wakeup_after);
 | 
						|
	return ret;
 | 
						|
}
 | 
						|
 | 
						|
module_param_call(wakeup_after, msm_power_wakeup_after, param_get_int,
 | 
						|
		  &msm_wakeup_after, S_IWUSR | S_IRUGO);
 | 
						|
 | 
						|
static void msm_pm_power_off(void)
 | 
						|
{
 | 
						|
	printk(KERN_INFO "msm_pm_power_off:wakeup after %d\r\n", msm_wakeup_after);
 | 
						|
 | 
						|
	if (msm_wakeup_after)
 | 
						|
		msm_proc_comm(PCOM_SET_RTC_ALARM, &msm_wakeup_after, 0);
 | 
						|
 | 
						|
	pmic_glb_power_down();
 | 
						|
 | 
						|
#if CONFIG_MSM_RMT_STORAGE_SERVER
 | 
						|
		printk(KERN_INFO "from %s\r\n", __func__);
 | 
						|
		wait_rmt_final_call_back(10);
 | 
						|
		printk(KERN_INFO "back %s\r\n", __func__);
 | 
						|
#endif
 | 
						|
	for (;;) ;
 | 
						|
}
 | 
						|
 | 
						|
static bool console_flushed;
 | 
						|
 | 
						|
void msm_pm_flush_console(void)
 | 
						|
{
 | 
						|
	if (console_flushed)
 | 
						|
		return;
 | 
						|
	console_flushed = true;
 | 
						|
 | 
						|
	printk("\n");
 | 
						|
	printk(KERN_EMERG "Restarting %s\n", linux_banner);
 | 
						|
	if (!try_acquire_console_sem()) {
 | 
						|
		release_console_sem();
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	mdelay(50);
 | 
						|
 | 
						|
	local_irq_disable();
 | 
						|
	if (try_acquire_console_sem())
 | 
						|
		printk(KERN_EMERG "msm_restart: Console was locked! Busting\n");
 | 
						|
	else
 | 
						|
		printk(KERN_EMERG "msm_restart: Console was locked!\n");
 | 
						|
	release_console_sem();
 | 
						|
}
 | 
						|
 | 
						|
#if defined(CONFIG_MACH_HTCLEO)
 | 
						|
static void htcleo_save_reset_reason()
 | 
						|
{
 | 
						|
	/* save restart_reason to be accesible in bootloader @ ramconsole - 0x1000*/
 | 
						|
	uint32_t *bootloader_reset_reason = ioremap(0x2FFB0000, PAGE_SIZE);
 | 
						|
	if(bootloader_reset_reason!=NULL)
 | 
						|
	{
 | 
						|
		printk(KERN_INFO "msm_restart saving reason %x @ 0x2FFB0000 \n", restart_reason);
 | 
						|
		bootloader_reset_reason[0]=restart_reason;
 | 
						|
		bootloader_reset_reason[1]=restart_reason^0x004b4c63; //XOR with cLK signature so we know is not trash
 | 
						|
	}
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
static void msm_pm_restart(char str)
 | 
						|
{
 | 
						|
	msm_pm_flush_console();
 | 
						|
 | 
						|
#if defined(CONFIG_MACH_HTCLEO)
 | 
						|
	htcleo_save_reset_reason();
 | 
						|
#endif
 | 
						|
 | 
						|
	/*  always reboot device through proc comm */
 | 
						|
	if (restart_reason == 0x6f656d99)
 | 
						|
		msm_proc_comm(PCOM_RESET_CHIP_IMM, &restart_reason, 0);
 | 
						|
	else
 | 
						|
		msm_proc_comm(PCOM_RESET_CHIP, &restart_reason, 0);
 | 
						|
 | 
						|
#if CONFIG_MSM_RMT_STORAGE_SERVER
 | 
						|
	printk(KERN_INFO "from %s\r\n", __func__);
 | 
						|
	wait_rmt_final_call_back(10);
 | 
						|
	printk(KERN_INFO "back %s\r\n", __func__);
 | 
						|
	/* wait 2 seconds to let radio reset device after the final EFS sync*/
 | 
						|
	mdelay(2000);
 | 
						|
#else
 | 
						|
	/* In case Radio is dead, reset device after notify Radio 5 seconds */
 | 
						|
	mdelay(5000);
 | 
						|
#endif
 | 
						|
 | 
						|
	/* hard reboot if possible */
 | 
						|
	if (msm_hw_reset_hook) {
 | 
						|
		printk(KERN_INFO "%s : Do HW_RESET by APP not by RADIO\r\n", __func__);
 | 
						|
		msm_hw_reset_hook();
 | 
						|
	}
 | 
						|
 | 
						|
	for (;;) ;
 | 
						|
}
 | 
						|
 | 
						|
static int msm_reboot_call(struct notifier_block *this, unsigned long code, void *_cmd)
 | 
						|
{
 | 
						|
	if((code == SYS_RESTART) && _cmd) {
 | 
						|
		char *cmd = _cmd;
 | 
						|
		if (!strcmp(cmd, "bootloader")) {
 | 
						|
			restart_reason = 0x77665500;
 | 
						|
		} else if (!strcmp(cmd, "recovery")) {
 | 
						|
			restart_reason = 0x77665502;
 | 
						|
		} else if (!strcmp(cmd, "eraseflash")) {
 | 
						|
			restart_reason = 0x776655EF;
 | 
						|
		} else if (!strncmp(cmd, "oem-", 4)) {
 | 
						|
			unsigned code = simple_strtoul(cmd + 4, 0, 16) & 0xff;
 | 
						|
			restart_reason = 0x6f656d00 | code;
 | 
						|
		} else if (!strcmp(cmd, "force-hard")) {
 | 
						|
			restart_reason = 0x776655AA;
 | 
						|
		} else {
 | 
						|
			restart_reason = 0x77665501;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return NOTIFY_DONE;
 | 
						|
}
 | 
						|
 | 
						|
static struct notifier_block msm_reboot_notifier =
 | 
						|
{
 | 
						|
	.notifier_call = msm_reboot_call,
 | 
						|
};
 | 
						|
 | 
						|
#ifdef CONFIG_MSM_IDLE_STATS
 | 
						|
static int msm_pm_read_proc(char *page, char **start, off_t off,
 | 
						|
                               int count, int *eof, void *data)
 | 
						|
{
 | 
						|
	int len = 0;
 | 
						|
	int i, j;
 | 
						|
	char *p = page;
 | 
						|
 | 
						|
	for (i = 0; i < ARRAY_SIZE(msm_pm_stats); i++) {
 | 
						|
		int64_t bucket_time;
 | 
						|
		int64_t s;
 | 
						|
		uint32_t ns;
 | 
						|
		s = msm_pm_stats[i].total_time;
 | 
						|
		ns = do_div(s, NSEC_PER_SEC);
 | 
						|
		p += sprintf(p,
 | 
						|
			"%s:\n"
 | 
						|
			"  count: %7d\n"
 | 
						|
			"  total_time: %lld.%09u\n",
 | 
						|
			msm_pm_stats[i].name,
 | 
						|
			msm_pm_stats[i].count,
 | 
						|
			s, ns);
 | 
						|
		bucket_time = CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
 | 
						|
		for (j = 0; j < CONFIG_MSM_IDLE_STATS_BUCKET_COUNT - 1; j++) {
 | 
						|
			s = bucket_time;
 | 
						|
			ns = do_div(s, NSEC_PER_SEC);
 | 
						|
			p += sprintf(p, "   <%2lld.%09u: %7d (%lld-%lld)\n",
 | 
						|
				s, ns, msm_pm_stats[i].bucket[j],
 | 
						|
				msm_pm_stats[i].min_time[j],
 | 
						|
				msm_pm_stats[i].max_time[j]);
 | 
						|
			bucket_time <<= CONFIG_MSM_IDLE_STATS_BUCKET_SHIFT;
 | 
						|
		}
 | 
						|
		p += sprintf(p, "  >=%2lld.%09u: %7d (%lld-%lld)\n",
 | 
						|
			s, ns, msm_pm_stats[i].bucket[j],
 | 
						|
			msm_pm_stats[i].min_time[j],
 | 
						|
			msm_pm_stats[i].max_time[j]);
 | 
						|
	}
 | 
						|
	*start = page + off;
 | 
						|
 | 
						|
	len = p - page;
 | 
						|
	if (len > off)
 | 
						|
		len -= off;
 | 
						|
	else
 | 
						|
		len = 0;
 | 
						|
 | 
						|
	return len < count ? len  : count;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
void msm_pm_set_max_sleep_time(int64_t max_sleep_time_ns)
 | 
						|
{
 | 
						|
	int64_t max_sleep_time_bs = max_sleep_time_ns;
 | 
						|
 | 
						|
	/* Convert from ns -> BS units */
 | 
						|
	do_div(max_sleep_time_bs, NSEC_PER_SEC / 32768);
 | 
						|
 | 
						|
	if (max_sleep_time_bs > 0x6DDD000)
 | 
						|
		msm_pm_max_sleep_time = (uint32_t) 0x6DDD000;
 | 
						|
	else
 | 
						|
		msm_pm_max_sleep_time = (uint32_t) max_sleep_time_bs;
 | 
						|
 | 
						|
	if (msm_pm_debug_mask & MSM_PM_DEBUG_SUSPEND)
 | 
						|
		printk("%s: Requested %lldns (%lldbs), Giving %ubs\n",
 | 
						|
		       __func__, max_sleep_time_ns, 
 | 
						|
		       max_sleep_time_bs, 
 | 
						|
		       msm_pm_max_sleep_time);
 | 
						|
}
 | 
						|
EXPORT_SYMBOL(msm_pm_set_max_sleep_time);
 | 
						|
 | 
						|
#ifdef CONFIG_EARLYSUSPEND
 | 
						|
/* axi 128 screen on, 61mhz screen off */
 | 
						|
static void axi_early_suspend(struct early_suspend *handler)
 | 
						|
{
 | 
						|
	axi_rate = 0;
 | 
						|
	clk_set_rate(axi_clk, axi_rate);
 | 
						|
}
 | 
						|
 | 
						|
static void axi_late_resume(struct early_suspend *handler)
 | 
						|
{
 | 
						|
	axi_rate = 128000000;
 | 
						|
	sleep_axi_rate = 117000000;
 | 
						|
	clk_set_rate(axi_clk, axi_rate);
 | 
						|
}
 | 
						|
 | 
						|
static struct early_suspend axi_screen_suspend = {
 | 
						|
	.suspend = axi_early_suspend,
 | 
						|
	.resume = axi_late_resume,
 | 
						|
};
 | 
						|
#endif
 | 
						|
 | 
						|
static void __init msm_pm_axi_init(void)
 | 
						|
{
 | 
						|
#ifdef CONFIG_EARLYSUSPEND
 | 
						|
	axi_clk = clk_get(NULL, "ebi1_clk");
 | 
						|
	if (IS_ERR(axi_clk)) {
 | 
						|
		int result = PTR_ERR(axi_clk);
 | 
						|
		pr_err("clk_get(ebi1_clk) returned %d\n", result);
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	axi_rate = 128000000;
 | 
						|
	sleep_axi_rate = 117000000;
 | 
						|
	clk_set_rate(axi_clk, axi_rate);
 | 
						|
	register_early_suspend(&axi_screen_suspend);
 | 
						|
#else
 | 
						|
	axi_rate = 0;
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
static int __init msm_pm_init(void)
 | 
						|
{
 | 
						|
	pm_power_off = msm_pm_power_off;
 | 
						|
	arm_pm_restart = msm_pm_restart;
 | 
						|
	msm_pm_max_sleep_time = 0;
 | 
						|
#if defined(CONFIG_ARCH_MSM_SCORPION)
 | 
						|
#ifdef CONFIG_AXI_SCREEN_POLICY
 | 
						|
	msm_pm_axi_init();
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
 | 
						|
	register_reboot_notifier(&msm_reboot_notifier);
 | 
						|
	msm_pm_reset_vector = ioremap(0x0, PAGE_SIZE);
 | 
						|
 | 
						|
#if defined(CONFIG_MACH_HTCLEO)
 | 
						|
	// if cLK is bootloader 0x0 is protected and not writtable but cLK changed reset vecotr to jump at address stored at 0x11800004
 | 
						|
	if(htcleo_is_nand_boot()==2){
 | 
						|
		pr_info("msm_pm: 0x00000000: %x\n", msm_pm_reset_vector[0]);
 | 
						|
		pr_info("msm_pm: 0x00000004: %x\n", msm_pm_reset_vector[1]);
 | 
						|
		msm_pm_reset_vector = ioremap(0x11800000, PAGE_SIZE);
 | 
						|
	}
 | 
						|
#endif
 | 
						|
 | 
						|
	if (msm_pm_reset_vector == NULL) {
 | 
						|
		printk(KERN_ERR "msm_pm_init: failed to map reset vector\n");
 | 
						|
		return -ENODEV;
 | 
						|
	}
 | 
						|
 | 
						|
	suspend_set_ops(&msm_pm_ops);
 | 
						|
 | 
						|
#ifdef CONFIG_MSM_IDLE_STATS
 | 
						|
	create_proc_read_entry("msm_pm_stats", S_IRUGO,
 | 
						|
				NULL, msm_pm_read_proc, NULL);
 | 
						|
#endif
 | 
						|
 | 
						|
	if ((board_mfg_mode() == 0) || (board_mfg_mode() == 1)) {
 | 
						|
		disable_hlt();
 | 
						|
		schedule_delayed_work(&work_expire_boot_lock, BOOT_LOCK_TIMEOUT);
 | 
						|
		pr_info("Acquire 'boot-time' halt_lock\n");
 | 
						|
	}
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
__initcall(msm_pm_init);
 |