/*++
linux/arch/arm/mach-wmt/pm.c
Copyright (c) 2008 WonderMedia Technologies, Inc.
This program is free software: you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software Foundation,
either version 2 of the License, or (at your option) any later version.
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.
You should have received a copy of the GNU General Public License along with
this program. If not, see .
WonderMedia Technologies, Inc.
10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C.
--*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#define CONFIG_KBDC_WAKEUP
//#define KB_WAKEUP_SUPPORT
//#define MOUSE_WAKEUP_SUPPORT
#define SOFT_POWER_SUPPORT
#define RTC_WAKEUP_SUPPORT
//#ifdef CONFIG_RMTCTL_WonderMedia //define if CIR menuconfig enable
#define CIR_WAKEUP_SUPPORT
//#endif
#define KEYPAD_POWER_SUPPORT
#define PMWT_C_WAKEUP(src, type) ((type & PMWT_TYPEMASK) << (((src - 24) & PMWT_WAKEUPMASK) * 4))
enum wakeup_intr_tri_src_e {
WKS_T_WK0 = 0, /* General Purpose Wakeup Source 0 */
WKS_T_WK2, /* General Purpose Wakeup Source 1 */
WKS_T_WK3, /* General Purpose Wakeup Source 2 */
WKS_T_WK4, /* General Purpose Wakeup Source 3 */
WKS_T_SUS0, /* General Purpose Wakeup Source 4 */
WKS_T_SUS1, /* General Purpose Wakeup Source 5 */
WKS_T_USBATTA0, /* USBATTA0 */
WKS_T_CIRIN, /* CIRIN */
WKS_T_USBOC0, /* WKS_USBOC0 as wakeup */
WKS_T_USBOC1, /* WKS_USBOC0 as wakeup */
WKS_T_USBOC2, /* WKS_USBOC0 as wakeup */
WKS_T_USBOC3, /* WKS_USBOC0 as wakeup */
WKS_T_UHC, /* UHC interrupt as wakeup */
WKS_T_UDC, /* WKS_UDC interrupt as wakeup */
WKS_T_CIR, /* CIR interrupt as wakeupr */
WKS_T_USBSW0, /* USBSW0 interrupt as wakeupr */
WKS_T_SD3 = 18, /* SD3 interrupt as wakeupr */
WKS_T_DCDET = 19, /* DCDET interrupt as wakeupr */
WKS_T_SD2 = 20, /* SD2 interrupt as wakeupr */
WKS_T_HDMICEC = 21, /* HDMICEC interrupt as wakeupr */
WKS_T_SD0 = 22, /* SD0 interrupt as wakeupr */
WKS_T_WK5 = 23, /* Wakeup event number */
WKS_T_PWRBTN = 24, /* PWRBTN as wakeup */
WKS_T_RTC = 25, /* RTC as wakeup */
CA9MP_RST = 26, /* CA9MP_RST */
SOFT_RST = 27, /* SOFT_RST */
CORE0_WD_RST = 28, /* CORE0_WD_RST */
CORE1_WD_RST = 29 /* CORE1_WD_RST */
};
static struct wakeup_source *wmt_ws;
static struct workqueue_struct *wakeup_queue;
static struct delayed_work wakeupwork;
static struct {
bool have_switch;
unsigned int gpio_no;
unsigned int wakeup_source;
}hall_switch;
#define DRIVER_NAME "PMC"
#if defined(CONFIG_PM_RTC_IS_GMT) && defined(RTC_WAKEUP_SUPPORT)
#include
#endif
/*
* Debug macros
*/
#ifdef DEBUG
# define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args)
#else
# define DPRINTK(fmt, args...)
#endif
/*
* For saving discontinuous registers during hibernation.
*/
#define SAVE(x) (saved[SAVED_##x] = (x##_VAL))
#define RESTORE(x) ((x##_VAL) = saved[SAVED_##x])
enum {
SAVED_SP = 0,
SAVED_OSTW, SAVED_OSTI,
SAVED_PMCEL, SAVED_PMCEU,
SAVED_PMCE2, SAVED_PMCE3,
/* SAVED_ATAUDMA, */
SAVED_SIZE
};
struct apm_dev_s {
char id;
};
extern unsigned int wmt_read_oscr(void);
extern void wmt_read_rtc(unsigned int *date, unsigned int *time);
extern void wmt_serial_set_reg(void);
/* Hibernation entry table physical address */
#define LOADER_ADDR 0xffff0000
#define HIBERNATION_ENTER_EXIT_CODE_BASE_ADDR 0xFFFFFFC0
#define DO_POWER_ON_SLEEP (HIBERNATION_ENTER_EXIT_CODE_BASE_ADDR + 0x00)
#define DO_POWER_OFF_SUSPEND (HIBERNATION_ENTER_EXIT_CODE_BASE_ADDR + 0x04)
#define DO_WM_IO_SET (HIBERNATION_ENTER_EXIT_CODE_BASE_ADDR + 0x34)
static unsigned int exec_at = (unsigned int)-1;
/*from = 4 high memory*/
static void (*theKernel)(int from);
//static void (*theKernel_io)(int from);
#if defined(SOFT_POWER_SUPPORT) && defined(CONFIG_PROC_FS)
//static struct proc_dir_entry *proc_softpower;
static unsigned int softpower_data;
#endif
static long rtc2sys;
struct work_struct PMC_shutdown;
struct work_struct PMC_sync;
extern int wmt_getsyspara(char *varname, char *varval, int *varlen);
static int power_on_debounce_value = 100; /*power button debounce time when power on state*/
static int resume_debounce_value = 2000; /*power button debounce time when press button to resume system*/
static int power_up_debounce_value = 2000; /*power button debounce time when press button to power up*/
#define min_debounce_value 0
#define max_debounce_value 4000
char hotplug_path[256] = "/sbin/hotplug";
static int sync_counter = 0;
static unsigned int time1, time2;
#define REG_VAL(addr) (*((volatile unsigned int *)(addr)))
#ifdef KEYPAD_POWER_SUPPORT
#include
#define KPAD_POWER_FUNCTION_NUM 1
#define power_button_timeout (HZ/10)
static struct input_dev *kpadPower_dev;
static unsigned int kpadPower_codes[KPAD_POWER_FUNCTION_NUM] = {
[0] = KEY_POWER
};
static unsigned int powerKey_is_pressed;
static unsigned int pressed_jiffies;
static struct timer_list kpadPower_timer;
static spinlock_t kpadPower_lock;
#endif
#ifdef CONFIG_BATTERY_WMT
static unsigned int battery_used;
#endif
#ifdef CONFIG_CACHE_L2X0
unsigned int l2x0_onoff;
unsigned int l2x0_aux;
unsigned int l2x0_prefetch_ctrl;
unsigned int en_static_address_filtering = 0;
unsigned int address_filtering_start = 0xD8000000;
unsigned int address_filtering_end = 0xD9000000;
static volatile unsigned int l2x0_base;
unsigned int cpu_trustzone_enabled = 0;
#endif
//gri
static unsigned int var_fake_power_button=0;
static unsigned int var_wake_type2=0;
static unsigned int var_wake_type=0;
static unsigned int var_wake_param=0;
static unsigned int var_wake_en=0;
static unsigned int var_1st_flag=0;
volatile unsigned int Wake_up_sts_mask = 0;// all static we add pwbn
static unsigned int dynamic_wakeup = 0;
static unsigned int dynamic_pmc_intr = 0;
static unsigned int pmlock_1st_flag=0;
static unsigned int pmlock_intr_1st_flag=0;
spinlock_t wmt_pm_lock;
spinlock_t wmt_pm_intr_lock;
unsigned int WMT_WAKE_UP_EVENT;//for printing wakeup event
/* wmt_pwrbtn_debounce_value()
*
* Entry to set the power button debounce value, the time unit is ms.
*/
static void wmt_pwrbtn_debounce_value(unsigned int time)
{
volatile unsigned long debounce_value = 0 ;
unsigned long pmpb_value = 0;
/*add a delay to wait pmc & rtc sync*/
udelay(130);
/*Debounce value unit is 1024 * RTC period ,RTC is 32KHz so the unit is ~ 32ms*/
if (time % 32)
debounce_value = (time / 32) + 1;
else
debounce_value = (time / 32);
pmpb_value = PMPB_VAL;
pmpb_value &= ~ PMPB_DEBOUNCE(0xff);
pmpb_value |= PMPB_DEBOUNCE(debounce_value);
PMPB_VAL = pmpb_value;
//udelay(100);
DPRINTK("[%s] PMPB_VAL = 0x%.8X \n",__func__,PMPB_VAL);
}
/* wmt_power_up_debounce_value()
*
* Entry to set the power button debounce value, the time unit is ms.
*/
void wmt_power_up_debounce_value(void) {
//printk("[%s] power_up_debounce_value = %d \n",__func__,power_up_debounce_value);
wmt_pwrbtn_debounce_value(power_up_debounce_value);
}
static void run_sync(struct work_struct *work)
{
int ret;
char *argv[] = { "/system/etc/wmt/script/force.sh", "PMC", NULL };
char *envp_shutdown[] =
{ "HOME=/", "PATH=/sbin:/bin:/usr/sbin:/usr/bin", "", NULL };
wmt_pwrbtn_debounce_value(power_up_debounce_value);
DPRINTK("[%s] start\n",__func__);
ret = call_usermodehelper(argv[0], argv, envp_shutdown, 0);
DPRINTK("[%s] sync end\n",__func__);
}
static void run_shutdown(struct work_struct *work)
{
int ret;
char *argv[] = { hotplug_path, "PMC", NULL };
char *envp_shutdown[] =
{ "HOME=/", "PATH=/sbin:/bin:/usr/sbin:/usr/bin", "ACTION=shutdown", NULL };
DPRINTK("[%s] \n",__func__);
wmt_pwrbtn_debounce_value(power_up_debounce_value);
ret = call_usermodehelper(argv[0], argv, envp_shutdown, 0);
}
//kevin add support wakeup3/wakeup0 to wakeup ap
#include
irqreturn_t viatelcom_irq_cp_wake_ap(int irq, void *data);
extern int gpio_viatel_4wire[4];
void pmc_enable_wakeup_isr(enum wakeup_src_e wakeup_event, unsigned int type)
{
unsigned long pm_lock_flags;
unsigned int wakeup_event_bit, wakeup_event_type;
unsigned int wakeup_event_temp;
if (type > 4)
type = 4;
if (! pmlock_intr_1st_flag) {
pmlock_intr_1st_flag = 1;
spin_lock_init(&wmt_pm_intr_lock);
}
spin_lock_irqsave(&wmt_pm_intr_lock, pm_lock_flags);
switch (wakeup_event) {
case WKS_WK0:
wakeup_event_bit = (INT_TRG_EN_VAL | (1 << WKS_T_WK0));
wakeup_event_type = ((INT_TYPE0_VAL & (~(0xf << (WKS_T_WK0 << 2)))) | (type << (WKS_T_WK0 << 2)));
do {
INT_TYPE0_VAL = wakeup_event_type;
} while(INT_TYPE0_VAL != wakeup_event_type);
break;
case WKS_WK2:
wakeup_event_bit = (INT_TRG_EN_VAL | (1 << WKS_T_WK2));
wakeup_event_type = ((INT_TYPE0_VAL & (~(0xf << (WKS_T_WK2 << 2)))) | (type << (WKS_T_WK2 << 2)));
do {
INT_TYPE0_VAL = wakeup_event_type;
} while(INT_TYPE0_VAL != wakeup_event_type);
break;
case WKS_WK3:
wakeup_event_bit = (INT_TRG_EN_VAL | (1 << WKS_T_WK3));
wakeup_event_type = ((INT_TYPE0_VAL & (~(0xf << (WKS_T_WK3 << 2)))) | (type << (WKS_T_WK3 << 2)));
do {
INT_TYPE0_VAL = wakeup_event_type;
} while(INT_TYPE0_VAL != wakeup_event_type);
break;
case WKS_WK4:
wakeup_event_bit = (INT_TRG_EN_VAL | (1 << WKS_T_WK4));
wakeup_event_type = ((INT_TYPE0_VAL & (~(0xf << (WKS_T_WK4 << 2)))) | (type << (WKS_T_WK4 << 2)));
do {
INT_TYPE0_VAL = wakeup_event_type;
} while(INT_TYPE0_VAL != wakeup_event_type);
break;
case WKS_SUS0:
wakeup_event_bit = (INT_TRG_EN_VAL | (1 << WKS_T_SUS0));
wakeup_event_type = ((INT_TYPE0_VAL & (~(0xf << (WKS_T_SUS0 << 2)))) | (type << (WKS_T_SUS0 << 2)));
do {
INT_TYPE0_VAL = wakeup_event_type;
} while(INT_TYPE0_VAL != wakeup_event_type);
break;
case WKS_SUS1:
wakeup_event_bit = (INT_TRG_EN_VAL | (1 << WKS_T_SUS1));
wakeup_event_type = ((INT_TYPE0_VAL & (~(0xf << (WKS_T_SUS1 << 2)))) | (type << (WKS_T_SUS1 << 2)));
do {
INT_TYPE0_VAL = wakeup_event_type;
} while(INT_TYPE0_VAL != wakeup_event_type);
break;
case WKS_USBATTA0:
wakeup_event_bit = (INT_TRG_EN_VAL | (1 << WKS_T_USBATTA0));
wakeup_event_type = ((INT_TYPE0_VAL & (~(0xf << (WKS_T_USBATTA0 << 2)))) | (type << (WKS_T_USBATTA0 << 2)));
do {
INT_TYPE0_VAL = wakeup_event_type;
} while(INT_TYPE0_VAL != wakeup_event_type);
break;
case WKS_CIRIN:
wakeup_event_bit = (INT_TRG_EN_VAL | (1 << WKS_T_CIRIN));
wakeup_event_type = ((INT_TYPE0_VAL & (~(0xf << (WKS_T_CIRIN << 2)))) | (type << (WKS_T_CIRIN << 2)));
do {
INT_TYPE0_VAL = wakeup_event_type;
} while(INT_TYPE0_VAL != wakeup_event_type);
break;
case WKS_PWRBTN:
wakeup_event_bit = (INT_TRG_EN_VAL | (1 << WKS_T_PWRBTN));
break;
case WKS_RTC:
wakeup_event_bit = (INT_TRG_EN_VAL | (1 << WKS_T_RTC));
break;
case WKS_USBOC0:
wakeup_event_bit = (INT_TRG_EN_VAL | (1 << WKS_T_USBOC0));
wakeup_event_temp = WKS_USBOC0 - WKS_USBOC0;
wakeup_event_type = ((INT_TYPE2_VAL & (~(0xf << (wakeup_event_temp << 2)))) | (type << (wakeup_event_temp << 2)));
do {
INT_TYPE2_VAL = wakeup_event_type;
} while(INT_TYPE2_VAL != wakeup_event_type);
break;
case WKS_USBOC1:
wakeup_event_bit = (INT_TRG_EN_VAL | (1 << WKS_T_USBOC1));
wakeup_event_temp = WKS_USBOC1 - WKS_USBOC0;
wakeup_event_type = ((INT_TYPE2_VAL & (~(0xf << (wakeup_event_temp << 2)))) | (type << (wakeup_event_temp << 2)));
do {
INT_TYPE2_VAL = wakeup_event_type;
} while(INT_TYPE2_VAL != wakeup_event_type);
break;
case WKS_USBOC2:
wakeup_event_bit = (INT_TRG_EN_VAL | (1 << WKS_T_USBOC2));
wakeup_event_temp = WKS_USBOC2 - WKS_USBOC0;
wakeup_event_type = ((INT_TYPE2_VAL & (~(0xf << (wakeup_event_temp << 2)))) | (type << (wakeup_event_temp << 2)));
do {
INT_TYPE2_VAL = wakeup_event_type;
} while(INT_TYPE2_VAL != wakeup_event_type);
break;
case WKS_USBOC3:
wakeup_event_bit = (INT_TRG_EN_VAL | (1 << WKS_T_USBOC3));
wakeup_event_temp = WKS_USBOC3 - WKS_USBOC0;
wakeup_event_type = ((INT_TYPE2_VAL & (~(0xf << (wakeup_event_temp << 2)))) | (type << (wakeup_event_temp << 2)));
do {
INT_TYPE2_VAL = wakeup_event_type;
} while(INT_TYPE2_VAL != wakeup_event_type);
break;
case WKS_UHC:
wakeup_event_bit = (INT_TRG_EN_VAL | (1 << WKS_T_UHC));
wakeup_event_temp = WKS_UHC - WKS_USBOC0;
wakeup_event_type = ((INT_TYPE2_VAL & (~(0xf << (wakeup_event_temp << 2)))) | (type << (wakeup_event_temp << 2)));
do {
INT_TYPE2_VAL = wakeup_event_type;
} while(INT_TYPE2_VAL != wakeup_event_type);
break;
case WKS_UDC:
wakeup_event_bit = (INT_TRG_EN_VAL | (1 << WKS_T_UDC));
wakeup_event_temp = WKS_UDC - WKS_USBOC0;
wakeup_event_type = ((INT_TYPE2_VAL & (~(0xf << (wakeup_event_temp << 2)))) | (type << (wakeup_event_temp << 2)));
do {
INT_TYPE2_VAL = wakeup_event_type;
} while(INT_TYPE2_VAL != wakeup_event_type);
break;
case WKS_CIR:
wakeup_event_bit = (INT_TRG_EN_VAL | (1 << WKS_T_CIR));
wakeup_event_temp = WKS_CIR - WKS_USBOC0;
wakeup_event_type = ((INT_TYPE2_VAL & (~(0xf << (wakeup_event_temp << 2)))) | (type << (wakeup_event_temp << 2)));
do {
INT_TYPE2_VAL = wakeup_event_type;
} while(INT_TYPE2_VAL != wakeup_event_type);
break;
case WKS_USBSW0:
wakeup_event_bit = (INT_TRG_EN_VAL | (1 << WKS_T_USBSW0));
wakeup_event_temp = WKS_USBSW0 - WKS_USBOC0;
wakeup_event_type = ((INT_TYPE2_VAL & (~(0xf << (wakeup_event_temp << 2)))) | (type << (wakeup_event_temp << 2)));
do {
INT_TYPE2_VAL = wakeup_event_type;
} while(INT_TYPE2_VAL != wakeup_event_type);
break;
case WKS_SD3:
wakeup_event_bit = (INT_TRG_EN_VAL | (1 << WKS_T_SD3));
wakeup_event_temp = WKS_SD3 - WKS_SD3 + 2;
wakeup_event_type = ((INT_TYPE1_VAL & (~(0xf << (wakeup_event_temp << 2)))) | (type << (wakeup_event_temp << 2)));
do {
INT_TYPE1_VAL = wakeup_event_type;
} while(INT_TYPE1_VAL != wakeup_event_type);
break;
case WKS_DCDET:
wakeup_event_bit = (INT_TRG_EN_VAL | (1 << WKS_T_DCDET));
wakeup_event_temp = WKS_DCDET - WKS_SD3 + 2;
wakeup_event_type = ((INT_TYPE1_VAL & (~(0xf << (wakeup_event_temp << 2)))) | (type << (wakeup_event_temp << 2)));
do {
INT_TYPE1_VAL = wakeup_event_type;
} while(INT_TYPE1_VAL != wakeup_event_type);
break;
case WKS_SD2:
wakeup_event_bit = (INT_TRG_EN_VAL | (1 << WKS_T_SD2));
wakeup_event_temp = WKS_SD2 - WKS_SD3 + 2;
wakeup_event_type = ((INT_TYPE1_VAL & (~(0xf << (wakeup_event_temp << 2)))) | (type << (wakeup_event_temp << 2)));
do {
INT_TYPE1_VAL = wakeup_event_type;
} while(INT_TYPE1_VAL != wakeup_event_type);
break;
case WKS_HDMICEC:
wakeup_event_bit = (INT_TRG_EN_VAL | (1 << WKS_T_HDMICEC));
wakeup_event_temp = WKS_HDMICEC - WKS_SD3 + 2;
wakeup_event_type = ((INT_TYPE1_VAL & (~(0xf << (wakeup_event_temp << 2)))) | (type << (wakeup_event_temp << 2)));
do {
INT_TYPE1_VAL = wakeup_event_type;
} while(INT_TYPE1_VAL != wakeup_event_type);
break;
case WKS_SD0:
wakeup_event_bit = (INT_TRG_EN_VAL | (1 << WKS_T_SD0));
wakeup_event_temp = WKS_SD0 - WKS_SD3 + 2;
wakeup_event_type = ((INT_TYPE1_VAL & (~(0xf << (wakeup_event_temp << 2)))) | (type << (wakeup_event_temp << 2)));
do {
INT_TYPE1_VAL = wakeup_event_type;
} while(INT_TYPE1_VAL != wakeup_event_type);
break;
case WKS_WK5:
wakeup_event_bit = (INT_TRG_EN_VAL | (1 << WKS_T_WK5));
wakeup_event_temp = WKS_WK5 - WKS_SD3 + 2;
wakeup_event_type = ((INT_TYPE1_VAL & (~(0xf << (wakeup_event_temp << 2)))) | (type << (wakeup_event_temp << 2)));
do {
INT_TYPE1_VAL = wakeup_event_type;
} while(INT_TYPE1_VAL != wakeup_event_type);
break;
default:
goto pmc_enable_wakeup_isr_error;
break;
}
while (PMCIS_VAL & (1 << wakeup_event)) {
PMCIS_VAL = (1 << wakeup_event);
}
do {
INT_TRG_EN_VAL = wakeup_event_bit;
} while(INT_TRG_EN_VAL != wakeup_event_bit);
dynamic_pmc_intr = INT_TRG_EN_VAL;
pmc_enable_wakeup_isr_error:
spin_unlock_irqrestore(&wmt_pm_intr_lock, pm_lock_flags);
}
EXPORT_SYMBOL(pmc_enable_wakeup_isr);
void pmc_disable_wakeup_isr(enum wakeup_src_e wakeup_event)
{
unsigned long pm_lock_flags;
unsigned int wakeup_event_bit;
if (! pmlock_intr_1st_flag) {
pmlock_intr_1st_flag = 1;
spin_lock_init(&wmt_pm_intr_lock);
}
spin_lock_irqsave(&wmt_pm_intr_lock, pm_lock_flags);
switch (wakeup_event) {
case WKS_WK0:
wakeup_event_bit = (INT_TRG_EN_VAL & (~(1 << WKS_T_WK0)));
break;
case WKS_WK2:
wakeup_event_bit = (INT_TRG_EN_VAL & (~(1 << WKS_T_WK2)));
break;
case WKS_WK3:
wakeup_event_bit = (INT_TRG_EN_VAL & (~(1 << WKS_T_WK3)));
break;
case WKS_WK4:
wakeup_event_bit = (INT_TRG_EN_VAL & (~(1 << WKS_T_WK4)));
break;
case WKS_SUS0:
wakeup_event_bit = (INT_TRG_EN_VAL & (~(1 << WKS_T_SUS0)));
break;
case WKS_SUS1:
wakeup_event_bit = (INT_TRG_EN_VAL & (~(1 << WKS_T_SUS1)));
break;
case WKS_USBATTA0:
wakeup_event_bit = (INT_TRG_EN_VAL & (~(1 << WKS_T_USBATTA0)));
break;
case WKS_CIRIN:
wakeup_event_bit = (INT_TRG_EN_VAL & (~(1 << WKS_T_CIRIN)));
break;
case WKS_PWRBTN:
wakeup_event_bit = (INT_TRG_EN_VAL & (~(1 << WKS_T_PWRBTN)));
break;
case WKS_RTC:
wakeup_event_bit = (INT_TRG_EN_VAL & (~(1 << WKS_T_RTC)));
break;
case WKS_USBOC0:
wakeup_event_bit = (INT_TRG_EN_VAL & (~(1 << WKS_T_USBOC0)));
break;
case WKS_USBOC1:
wakeup_event_bit = (INT_TRG_EN_VAL & (~(1 << WKS_T_USBOC1)));
break;
case WKS_USBOC2:
wakeup_event_bit = (INT_TRG_EN_VAL & (~(1 << WKS_T_USBOC2)));
break;
case WKS_USBOC3:
wakeup_event_bit = (INT_TRG_EN_VAL & (~(1 << WKS_T_USBOC3)));
break;
case WKS_UHC:
wakeup_event_bit = (INT_TRG_EN_VAL & (~(1 << WKS_T_UHC)));
break;
case WKS_UDC:
wakeup_event_bit = (INT_TRG_EN_VAL & (~(1 << WKS_T_UDC)));
break;
case WKS_CIR:
wakeup_event_bit = (INT_TRG_EN_VAL & (~(1 << WKS_T_CIR)));
break;
case WKS_USBSW0:
wakeup_event_bit = (INT_TRG_EN_VAL & (~(1 << WKS_T_USBSW0)));
break;
case WKS_SD3:
wakeup_event_bit = (INT_TRG_EN_VAL & (~(1 << WKS_T_SD3)));
break;
case WKS_DCDET:
wakeup_event_bit = (INT_TRG_EN_VAL & (~(1 << WKS_T_DCDET)));
break;
case WKS_SD2:
wakeup_event_bit = (INT_TRG_EN_VAL & (~(1 << WKS_T_SD2)));
break;
case WKS_HDMICEC:
wakeup_event_bit = (INT_TRG_EN_VAL & (~(1 << WKS_T_HDMICEC)));
break;
case WKS_SD0:
wakeup_event_bit = (INT_TRG_EN_VAL & (~(1 << WKS_T_SD0)));
break;
case WKS_WK5:
wakeup_event_bit = (INT_TRG_EN_VAL & (~(1 << WKS_T_WK5)));
break;
default:
goto pmc_disable_wakeup_isr_error;
break;
}
do {
INT_TRG_EN_VAL = wakeup_event_bit;
} while(INT_TRG_EN_VAL != wakeup_event_bit);
dynamic_pmc_intr = INT_TRG_EN_VAL;
pmc_disable_wakeup_isr_error:
spin_unlock_irqrestore(&wmt_pm_intr_lock, pm_lock_flags);
}
EXPORT_SYMBOL(pmc_disable_wakeup_isr);
void pmc_clear_intr_status(enum wakeup_src_e wakeup_event)
{
unsigned long pm_lock_flags;
unsigned int wakeup_event_bit;
if (! pmlock_intr_1st_flag) {
pmlock_intr_1st_flag = 1;
spin_lock_init(&wmt_pm_intr_lock);
}
wakeup_event_bit = (1 << wakeup_event);
spin_lock_irqsave(&wmt_pm_intr_lock, pm_lock_flags);
while (PMCIS_VAL & wakeup_event_bit) {
PMCIS_VAL = wakeup_event_bit;
}
spin_unlock_irqrestore(&wmt_pm_intr_lock, pm_lock_flags);
}
EXPORT_SYMBOL(pmc_clear_intr_status);
void pmc_clear_wakeup_status(enum wakeup_src_e wakeup_event)
{
unsigned long pm_lock_flags;
unsigned int wakeup_event_bit;
if (! pmlock_1st_flag) {
pmlock_1st_flag = 1;
spin_lock_init(&wmt_pm_lock);
}
wakeup_event_bit = (1 << wakeup_event);
spin_lock_irqsave(&wmt_pm_lock, pm_lock_flags);
while (PMWS_VAL & wakeup_event_bit) {
PMWS_VAL = wakeup_event_bit;
}
spin_unlock_irqrestore(&wmt_pm_lock, pm_lock_flags);
}
EXPORT_SYMBOL(pmc_clear_wakeup_status);
void pmc_enable_wakeup_event(enum wakeup_src_e wakeup_event, unsigned int type)
{
unsigned int which_bit;
unsigned ori_type = 0;
unsigned long pm_lock_flags;
if ((wakeup_event > WKS_CIRIN) && (wakeup_event < WKS_PWRBTN))
return;
if ((wakeup_event > WKS_USBSW0) && (wakeup_event < WKS_SD3))
return;
if (type > 4)
return;
if (! pmlock_1st_flag) {
pmlock_1st_flag = 1;
spin_lock_init(&wmt_pm_lock);
}
which_bit = (1 << wakeup_event);
spin_lock_irqsave(&wmt_pm_lock, pm_lock_flags);
if (which_bit < 0x100) {
ori_type = PMWT_VAL;
ori_type &= (~(0xf << (wakeup_event << 2)));
ori_type |= (type << (wakeup_event << 2));
do {
PMWT_VAL = ori_type;
} while(PMWT_VAL != ori_type);
} else if (which_bit >= 0x1000000) {
unsigned int temp;
temp = wakeup_event - 24;
ori_type = PMWTC_VAL;
ori_type &= (~(0xf << (temp << 2)));
ori_type |= (type << (temp << 2));
do {
PMWTC_VAL = ori_type;
} while(PMWTC_VAL != ori_type);
} else if (which_bit >= 0x10000) {
unsigned int temp;
temp = wakeup_event - 16;
ori_type = WK_EVT_TYPE_VAL;
ori_type &= (~(0xf << (temp << 2)));
ori_type |= (type << (temp << 2));
do {
WK_EVT_TYPE_VAL = ori_type;
} while(WK_EVT_TYPE_VAL != ori_type);
}
dynamic_wakeup |= (1 << wakeup_event);
spin_unlock_irqrestore(&wmt_pm_lock, pm_lock_flags);
}
EXPORT_SYMBOL(pmc_enable_wakeup_event);
void pmc_disable_wakeup_event(enum wakeup_src_e wakeup_event)
{
if (! pmlock_1st_flag) {
pmlock_1st_flag = 1;
spin_lock_init(&wmt_pm_lock);
}
dynamic_wakeup &= (~(1 << wakeup_event));
}
EXPORT_SYMBOL(pmc_disable_wakeup_event);
static void wakeup_func(struct work_struct *work)
{
struct file *fp;
mm_segment_t fs;
loff_t pos=0;
unsigned long flags;
char buf[3];
fp = filp_open("/sys/class/backlight/pwm-backlight.0/brightness", O_RDWR, 0777);
if (IS_ERR(fp)) {
printk(KERN_ERR"open file error\n");
return;
}
fs = get_fs();
set_fs(KERNEL_DS);
vfs_read(fp, buf, sizeof(buf), &pos);
filp_close(fp, NULL);
set_fs(fs);
//printk(KERN_ERR"%s buf %s\n",__FUNCTION__,buf);
if(gpio_get_value(hall_switch.gpio_no)){
if(strncmp(buf,"0",1))
{
return;
}
}
else{
if(!strncmp(buf,"0",1))
{
return;
}
}
#ifdef KEYPAD_POWER_SUPPORT
if(kpadPower_dev) {
spin_lock_irqsave(&kpadPower_lock, flags);
if(!powerKey_is_pressed) {
powerKey_is_pressed = 1;
input_report_key(kpadPower_dev, KEY_POWER, 1); //power key is pressed
input_sync(kpadPower_dev);
pressed_jiffies = jiffies;
wmt_pwrbtn_debounce_value(power_up_debounce_value);
DPRINTK("\n[%s]power key pressed -->\n",__func__);
time1 = jiffies_to_msecs(jiffies);
__pm_wakeup_event(wmt_ws, (MSEC_PER_SEC >> 4));
}
//disable_irq(IRQ_PMC_WAKEUP);
spin_unlock_irqrestore(&kpadPower_lock, flags);
mod_timer(&kpadPower_timer, jiffies + power_button_timeout);
}
#endif
}
static irqreturn_t pmc_wakeup_isr(int this_irq, void *dev_id)
{
unsigned int status_i;
unsigned long flags;
status_i = PMCIS_VAL;
rmb();
//kevin add for wakeup3 to wakeup ap
if(status_i & (gpio_viatel_4wire[GPIO_VIATEL_USB_MDM_WAKE_AP]==149?BIT0:BIT2)){
//printk("call viatelcom_irq_cp_wake_ap\n");
viatelcom_irq_cp_wake_ap(this_irq,dev_id);
PMCIS_VAL |= (gpio_viatel_4wire[GPIO_VIATEL_USB_MDM_WAKE_AP]==149?BIT0:BIT2);
}
/*
* TODO : wakeup event and interrupt event share the same interrupt
* source IRQ_PMC. we should make a mechanism like 'request_irq' to
* register interrupt event callback function, and call the right
* function here.
*/
/* DCDET interrupt */
//if (status_i & BIT27) {
// extern void dcdet_isr_callback(void);
// dcdet_isr_callback();
// PMCIS_VAL |= BIT0;
//}
if(hall_switch.have_switch && (status_i & (1<<(hall_switch.wakeup_source)))){
//printk(KERN_ERR"call wakeup0\n");
queue_delayed_work(wakeup_queue, &wakeupwork, msecs_to_jiffies(50));
pmc_clear_intr_status(hall_switch.wakeup_source);
}
if (status_i & BIT14) {
pmc_clear_intr_status(WKS_PWRBTN);
#ifdef KEYPAD_POWER_SUPPORT
if(kpadPower_dev) {
spin_lock_irqsave(&kpadPower_lock, flags);
if(!powerKey_is_pressed) {
powerKey_is_pressed = 1;
input_report_key(kpadPower_dev, KEY_POWER, 1); //power key is pressed
input_sync(kpadPower_dev);
pressed_jiffies = jiffies;
wmt_pwrbtn_debounce_value(power_up_debounce_value);
DPRINTK("\n[%s]power key pressed -->\n",__func__);
time1 = jiffies_to_msecs(jiffies);
__pm_wakeup_event(wmt_ws, (MSEC_PER_SEC >> 4));
}
//disable_irq(IRQ_PMC_WAKEUP);
spin_unlock_irqrestore(&kpadPower_lock, flags);
mod_timer(&kpadPower_timer, jiffies + power_button_timeout);
}
#endif
#if defined(SOFT_POWER_SUPPORT) && defined(CONFIG_PROC_FS)
softpower_data = 1;
#endif
}
return IRQ_HANDLED;
}
extern int PM_device_PostSuspend(void);
extern int PM_device_PreResume(void);
void check_pmc_busy(void)
{
while (PMCS2_VAL&0x3F0038)
;
}
void save_plla_speed(unsigned int *plla_div)
{
plla_div[0] = PMARM_VAL;/*arm_div*/
check_pmc_busy();
plla_div[1]= PML2C_VAL;;/*l2c_div*/
check_pmc_busy();
plla_div[2] = PML2CTAG_VAL;/*l2c_tag_div*/
check_pmc_busy();
plla_div[3] = PML2CDATA_VAL;/*l2c_data_div*/
check_pmc_busy();
plla_div[4] = PML2CAXI_VAL;/*axi_l2c_div*/
check_pmc_busy();
plla_div[5] = PMDBGAPB_VAL;/*dbg_apb_div*/
check_pmc_busy();
plla_div[6] = PMPMA_VAL;
check_pmc_busy();
}
void save_pllb_speed(unsigned int *pllb_div)
{
check_pmc_busy();
pllb_div[0] = PMPWM_VAL;
check_pmc_busy();
pllb_div[1] = PMSDMMC_VAL;
check_pmc_busy();
pllb_div[2] = PMSDMMC1_VAL;
check_pmc_busy();
pllb_div[3] = PMSDMMC2_VAL;
check_pmc_busy();
pllb_div[4] = PMI2C0_VAL;
check_pmc_busy();
pllb_div[5] = PMI2C1_VAL;
check_pmc_busy();
pllb_div[6] = PMI2C2_VAL;
check_pmc_busy();
pllb_div[7] = PMI2C3_VAL;
check_pmc_busy();
pllb_div[8] = PMI2C4_VAL;
check_pmc_busy();
pllb_div[9] = PMSF_VAL;
check_pmc_busy();
pllb_div[10] = PMSPI_VAL;
check_pmc_busy();
pllb_div[11] = PMSPI1_VAL;
check_pmc_busy();
pllb_div[12] = PMNAND_VAL;
check_pmc_busy();
pllb_div[13] = PMNA12_VAL;
check_pmc_busy();
pllb_div[14] = PMADC_VAL;
check_pmc_busy();
pllb_div[15] = PMCSI0_VAL;
check_pmc_busy();
pllb_div[16] = PMCSI1_VAL;
check_pmc_busy();
pllb_div[17] = PMMALI_VAL;
check_pmc_busy();
pllb_div[18] = PMPAXI_VAL;
check_pmc_busy();
pllb_div[19] = PMSE_VAL;
check_pmc_busy();
pllb_div[20] = PMPCM0_VAL;
check_pmc_busy();
pllb_div[21] = PMPCM1_VAL;
check_pmc_busy();
pllb_div[22] = PMAHB_VAL;
check_pmc_busy();
pllb_div[23] = PMAPB0_VAL;
check_pmc_busy();
pllb_div[24] = PMPMB_VAL;
check_pmc_busy();
}
void save_plld_speed(unsigned int *plld_div)
{
check_pmc_busy();
plld_div[0] = PMWMTVDU_VAL;/*vdu_div*/
check_pmc_busy();
plld_div[1]= PMCNMVDU_VAL;;/*cnm_div*/
check_pmc_busy();
plld_div[2] = PMWMTNA_VAL;/*na_vdu_div*/
check_pmc_busy();
plld_div[3] = PMCNMNA_VAL;/*na_cnm_div*/
check_pmc_busy();
}
void restore_plla_speed(unsigned int *plla_div)
{
auto_pll_divisor(DEV_ARM, SET_PLLDIV, 2, 300);
PMARM_VAL = plla_div[0];/*arm_div*/
wmb();
check_pmc_busy();
PML2C_VAL = plla_div[1];/*l2c_div*/
wmb();
check_pmc_busy();
PML2CTAG_VAL = plla_div[2];/*l2c_tag_div*/
wmb();
check_pmc_busy();
PML2CDATA_VAL = plla_div[3];/*l2c_data_div*/
wmb();
check_pmc_busy();
PML2CAXI_VAL = plla_div[4];/*l2c_axi_div*/
wmb();
check_pmc_busy();
PMDBGAPB_VAL = plla_div[5];/*dbg_apb_div*/
wmb();
check_pmc_busy();
PMPMA_VAL = plla_div[6];
wmb();
check_pmc_busy();
}
void restore_pllb_speed(unsigned int *pllb_div)
{
check_pmc_busy();
PMPWM_VAL = pllb_div[0];
wmb();
check_pmc_busy();
#if 0
PMSDMMC_VAL = pllb_div[1];
wmb();
check_pmc_busy();
PMSDMMC1_VAL = pllb_div[2];
wmb();
check_pmc_busy();
PMSDMMC2_VAL = pllb_div[3];
wmb();
check_pmc_busy();
#endif
PMI2C0_VAL = pllb_div[4];
wmb();
check_pmc_busy();
PMI2C1_VAL = pllb_div[5];
wmb();
check_pmc_busy();
PMI2C2_VAL = pllb_div[6];
wmb();
check_pmc_busy();
PMI2C3_VAL = pllb_div[7];
wmb();
check_pmc_busy();
PMI2C4_VAL = pllb_div[8];
wmb();
check_pmc_busy();
PMSF_VAL = pllb_div[9];
wmb();
check_pmc_busy();
PMSPI_VAL = pllb_div[10];
wmb();
check_pmc_busy();
PMSPI1_VAL = pllb_div[11];
wmb();
check_pmc_busy();
PMNAND_VAL = pllb_div[12];
wmb();
check_pmc_busy();
PMNA12_VAL = pllb_div[13];
wmb();
check_pmc_busy();
PMADC_VAL = pllb_div[14];
wmb();
check_pmc_busy();
PMCSI0_VAL = pllb_div[15];
wmb();
check_pmc_busy();
PMCSI1_VAL = pllb_div[16];
wmb();
check_pmc_busy();
PMMALI_VAL = pllb_div[17];
wmb();
check_pmc_busy();
PMPAXI_VAL = pllb_div[18];
wmb();
check_pmc_busy();
PMSE_VAL = pllb_div[19];
wmb();
check_pmc_busy();
PMPCM0_VAL = pllb_div[20];
wmb();
check_pmc_busy();
PMPCM1_VAL = pllb_div[21];
wmb();
check_pmc_busy();
PMAHB_VAL = pllb_div[22];
wmb();
check_pmc_busy();
PMAPB0_VAL = pllb_div[23];
wmb();
check_pmc_busy();
PMPMB_VAL = pllb_div[24];
wmb();
check_pmc_busy();
}
void restore_plld_speed(unsigned int *plld_div)
{
check_pmc_busy();
PMWMTVDU_VAL = plld_div[0]; /*vdu_div*/
wmb();
check_pmc_busy();
PMCNMVDU_VAL = plld_div[1]; /*cnm_div*/
wmb();
check_pmc_busy();
PMWMTNA_VAL = plld_div[2]; /*na_vdu_div*/
wmb();
check_pmc_busy();
PMCNMNA_VAL = plld_div[3]; /*na_cnm_div*/
wmb();
check_pmc_busy();
}
/* wmt_pm_standby()
*
* Entry to the power-on sleep hibernation mode.
*/
static void wmt_pm_standby(void)
{
volatile unsigned int hib_phy_addr = 0,base = 0;
#ifdef CONFIG_CACHE_L2X0
__u32 power_ctrl;
if( l2x0_onoff == 1)
{
outer_cache.flush_all();
outer_cache.disable();
outer_cache.inv_all();
}
#endif
/* Get standby virtual address entry point */
base = (unsigned int)ioremap_nocache(LOADER_ADDR, 0x10000);
exec_at = base + (DO_POWER_ON_SLEEP - LOADER_ADDR);
hib_phy_addr = *(unsigned int *) exec_at;
exec_at = base + (hib_phy_addr - LOADER_ADDR);
//led_light(3);
theKernel = (void (*)(int))exec_at; /* set rom address */
theKernel(4); /* jump to rom */
//led_light(3);
iounmap((void __iomem *)base);
#ifdef CONFIG_CACHE_L2X0
if( l2x0_onoff == 1)
{
if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1))
{
if(cpu_trustzone_enabled == 0)
{
/* l2x0 controller is disabled */
writel_relaxed(l2x0_aux, l2x0_base + L2X0_AUX_CTRL);
if( en_static_address_filtering == 1 )
{
writel_relaxed(address_filtering_end, l2x0_base + 0xC04);
writel_relaxed((address_filtering_start | 0x01), l2x0_base + 0xC00);
}
writel_relaxed(0x110, l2x0_base + L2X0_TAG_LATENCY_CTRL);
writel_relaxed(0x110, l2x0_base + L2X0_DATA_LATENCY_CTRL);
power_ctrl = readl_relaxed(l2x0_base + L2X0_POWER_CTRL) | L2X0_DYNAMIC_CLK_GATING_EN | L2X0_STNDBY_MODE_EN;
writel_relaxed(power_ctrl, l2x0_base + L2X0_POWER_CTRL);
writel_relaxed(l2x0_prefetch_ctrl, l2x0_base + L2X0_PREFETCH_CTRL);
outer_cache.inv_all();
/* enable L2X0 */
writel_relaxed(1, l2x0_base + L2X0_CTRL);
}
else
{
/* l2x0 controller is disabled */
wmt_smc(WMT_SMC_CMD_PL310AUX, l2x0_aux);
if( en_static_address_filtering == 1 )
{
wmt_smc(WMT_SMC_CMD_PL310FILTER_END, address_filtering_end);
wmt_smc(WMT_SMC_CMD_PL310FILTER_START, (address_filtering_start | 0x01));
}
wmt_smc(WMT_SMC_CMD_PL310TAG_LATENCY, 0x110);
wmt_smc(WMT_SMC_CMD_PL310DATA_LATENCY, 0x110);
power_ctrl = readl_relaxed(l2x0_base + L2X0_POWER_CTRL) | L2X0_DYNAMIC_CLK_GATING_EN | L2X0_STNDBY_MODE_EN;
wmt_smc(WMT_SMC_CMD_PL310POWER, power_ctrl);
wmt_smc(WMT_SMC_CMD_PL310PREFETCH, l2x0_prefetch_ctrl);
outer_cache.inv_all();
/* enable L2X0 */
wmt_smc(WMT_SMC_CMD_PL310CTRL, 1);
}
}
}
#endif
}
extern void wmt_assem_suspend(void);
extern void wmt_assem_secure_suspend(void);
extern char use_dvfs;
/* wmt_pm_suspend()
*
* Entry to the power-off suspend hibernation mode.
*/
static void wmt_pm_suspend(void)
{
unsigned int saved[SAVED_SIZE];
int result;
unsigned int plla_div[7];
unsigned int pllb_div[25];
unsigned int plld_div[4];
#ifdef CONFIG_CACHE_L2X0
__u32 power_ctrl;
#endif
/* FIXME */
#if 1
result = PM_device_PostSuspend();
if (result)
printk("PM_device_PostSuspend fail\n");
#endif
#ifdef CONFIG_CACHE_L2X0
if( l2x0_onoff == 1)
{
outer_cache.flush_all();
outer_cache.disable();
outer_cache.inv_all();
}
#endif
SAVE(OSTW); /* save vital registers */
SAVE(OSTI);
SAVE(PMCEL); /* save clock gating */
SAVE(PMCEU);
SAVE(PMCE2);
SAVE(PMCE3);
*(volatile unsigned int *)0xfe018008 |= 0x03030303; //scu output pm
//for single core
#ifndef CONFIG_SMP
HSP7_VAL = 0xffffffb8;
while(HSP7_VAL != 0xffffffb8);
asm("sev" : : "r" (0));
#endif
save_plld_speed(plld_div); /*save plld clock register*/
save_pllb_speed(pllb_div); /*save pllb clock register*/
if (!use_dvfs)
save_plla_speed(plla_div);
//led_light(2);
if(cpu_trustzone_enabled == 1)
wmt_assem_secure_suspend();
else
wmt_assem_suspend();
RESTORE(PMCE3);
RESTORE(PMCE2);
RESTORE(PMCEU); /* restore clock gating */
RESTORE(PMCEL);
RESTORE(OSTI); /* restore vital registers */
RESTORE(OSTW);
wmt_serial_set_reg();
if (!use_dvfs)
restore_plla_speed(plla_div); /* restore plla clock register */
restore_pllb_speed(pllb_div); /* restore pllb clock register */
restore_plld_speed(plld_div); /* restore plld clock register */
PMPB_VAL |= 1; /* enable soft power */
//* ((volatile unsigned int *)0xfe140054) = 0x0;
#ifdef CONFIG_CACHE_L2X0
if( l2x0_onoff == 1)
{
if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1))
{
if(cpu_trustzone_enabled == 0)
{
/* l2x0 controller is disabled */
writel_relaxed(l2x0_aux, l2x0_base + L2X0_AUX_CTRL);
if( en_static_address_filtering == 1 )
{
writel_relaxed(address_filtering_end, l2x0_base + 0xC04);
writel_relaxed((address_filtering_start | 0x01), l2x0_base + 0xC00);
}
writel_relaxed(0x110, l2x0_base + L2X0_TAG_LATENCY_CTRL);
writel_relaxed(0x110, l2x0_base + L2X0_DATA_LATENCY_CTRL);
power_ctrl = readl_relaxed(l2x0_base + L2X0_POWER_CTRL) | L2X0_DYNAMIC_CLK_GATING_EN | L2X0_STNDBY_MODE_EN;
writel_relaxed(power_ctrl, l2x0_base + L2X0_POWER_CTRL);
writel_relaxed(l2x0_prefetch_ctrl, l2x0_base + L2X0_PREFETCH_CTRL);
outer_cache.inv_all();
/* enable L2X0 */
writel_relaxed(1, l2x0_base + L2X0_CTRL);
}
else
{
/* l2x0 controller is disabled */
wmt_smc(WMT_SMC_CMD_PL310AUX, l2x0_aux);
if( en_static_address_filtering == 1 )
{
wmt_smc(WMT_SMC_CMD_PL310FILTER_END, address_filtering_end);
wmt_smc(WMT_SMC_CMD_PL310FILTER_START, (address_filtering_start | 0x01));
}
wmt_smc(WMT_SMC_CMD_PL310TAG_LATENCY, 0x110);
wmt_smc(WMT_SMC_CMD_PL310DATA_LATENCY, 0x110);
power_ctrl = readl_relaxed(l2x0_base + L2X0_POWER_CTRL) | L2X0_DYNAMIC_CLK_GATING_EN | L2X0_STNDBY_MODE_EN;
wmt_smc(WMT_SMC_CMD_PL310POWER, power_ctrl);
wmt_smc(WMT_SMC_CMD_PL310PREFETCH, l2x0_prefetch_ctrl);
outer_cache.inv_all();
/* enable L2X0 */
wmt_smc(WMT_SMC_CMD_PL310CTRL, 1);
}
}
}
#endif
result = PM_device_PreResume();
if (result != 0)
printk("PM_device_PreResume fail\n");
}
/* wmt_pm_enter()
*
* To Finally enter the sleep state.
*
* Note: Only support PM_SUSPEND_STANDBY and PM_SUSPEND_MEM
*/
int wmt_trigger_resume_kpad = 0;
int wmt_trigger_resume_notify = 0;
void wmt_resume_kpad(void)
{
DPRINTK(KERN_ALERT "\n[%s]power key pressed\n",__func__);
powerKey_is_pressed = 1;
input_report_key(kpadPower_dev, KEY_POWER, 1); /*power key is pressed*/
input_sync(kpadPower_dev);
pressed_jiffies = jiffies;
mod_timer(&kpadPower_timer, jiffies + power_button_timeout);
}
void wmt_resume_notify(void)
{
input_report_key(kpadPower_dev, KEY_POWER, 1); /*power key is pressed*/
input_sync(kpadPower_dev);
input_report_key(kpadPower_dev, KEY_POWER, 0); //power key is released
input_sync(kpadPower_dev);
}
static int wmt_pm_enter(suspend_state_t state)
{
unsigned int status, status_i;
// unsigned int wakeup_notify;
int notify_framwork = 0;
if (!((state == PM_SUSPEND_STANDBY) || (state == PM_SUSPEND_MEM))) {
printk(KERN_ALERT "%s, Only support PM_SUSPEND_STANDBY and PM_SUSPEND_MEM\n", DRIVER_NAME);
return -EINVAL;
}
/* only enable fiq in normal operation */
//local_fiq_disable();
//local_irq_disable();
/* disable system OS timer */
OSTC_VAL &= ~OSTC_ENABLE;
/* FIXME, 2009/09/15 */
//PMCDS_VAL = PMCDS_VAL;
WMT_WAKE_UP_EVENT = 0;
/*set power button debounce value*/
wmt_pwrbtn_debounce_value(resume_debounce_value);
/*
* We use pm_standby as apm_standby for power-on hibernation.
* but we still suspend memory in both case.
*/
if (state == PM_SUSPEND_STANDBY)
wmt_pm_standby(); /* Go to standby mode*/
else
wmt_pm_suspend(); /* Go to suspend mode*/
/*set power button debounce value*/
wmt_pwrbtn_debounce_value(power_on_debounce_value);
/*
* Clean wakeup source
*/
status = PMWS_VAL;
status_i = PMCIS_VAL;
WMT_WAKE_UP_EVENT = (PMWS_VAL & (WK_TRG_EN_VAL | 0x4000));//wmt_pm_enter
status = (status & Wake_up_sts_mask);
PMCIS_VAL = PMCIS_VAL;
//notify_framwork=1;
#ifdef KEYPAD_POWER_SUPPORT
if (status & (1 << WKS_PWRBTN)) {
wmt_trigger_resume_kpad = 1;
}
#endif
if (status & (1 << WKS_WK5)){
DPRINTK(KERN_ALERT "\n[%s]WK5 event\n",__func__);
if (var_fake_power_button & (1 << WKS_WK5))
notify_framwork=1;
}
if (status & (1 << WKS_SD0)){
DPRINTK(KERN_ALERT "\n[%s]SD0 event\n",__func__);
if (var_fake_power_button & (1 << WKS_SD0))
notify_framwork=1;
}
if (status & (1 << WKS_HDMICEC)){
DPRINTK(KERN_ALERT "\n[%s]HDMICEC event\n",__func__);
if (var_fake_power_button & (1 << WKS_HDMICEC))
notify_framwork=1;
}
if (status & (1 << WKS_SD2)){
DPRINTK(KERN_ALERT "\n[%s]SD2 event\n",__func__);
if (var_fake_power_button & (1 << WKS_SD2))
notify_framwork=1;
}
if (status & (1 << WKS_DCDET)){
DPRINTK(KERN_ALERT "\n[%s]DCDET event\n",__func__);
if (var_fake_power_button & (1 << WKS_DCDET))
notify_framwork=1;
}
if (status & (1 << WKS_SD3)){
DPRINTK(KERN_ALERT "\n[%s]SD3 event\n",__func__);
if (var_fake_power_button & (1 << WKS_SD3))
notify_framwork=1;
}
if (status & (1 << WKS_USBSW0)){
DPRINTK(KERN_ALERT "\n[%s]USBSW0 event\n",__func__);
if (var_fake_power_button & (1 << WKS_USBSW0))
notify_framwork=1;
}
#ifdef CIR_WAKEUP_SUPPORT
if (status & (1 << WKS_CIR)){
DPRINTK(KERN_ALERT "\n[%s]CIR event\n",__func__);
if (var_fake_power_button & (1 << WKS_CIR))
notify_framwork=1;
}
#endif
#ifdef CONFIG_USB_GADGET_WMT
/*UDC wake up source*/
if (status & (1 << WKS_UDC)){
DPRINTK(KERN_ALERT "\n[%s]UDC event\n",__func__);
if (var_fake_power_button & (1 << WKS_UDC))
notify_framwork=1;
}
#endif
#ifdef CONFIG_USB
//UHC
if (status & (1 << WKS_UHC)){
DPRINTK(KERN_ALERT "\n[%s]UHC event\n",__func__);
if (var_fake_power_button & (1 << WKS_UHC))
notify_framwork=1;
}
if (status & (1 << WKS_USBOC3)){
DPRINTK(KERN_ALERT "\n[%s]USBOC3 event\n",__func__);
if (var_fake_power_button & (1 << WKS_USBOC3))
notify_framwork=1;
}
if (status & (1 << WKS_USBOC2)){
DPRINTK(KERN_ALERT "\n[%s]USBOC2 event\n",__func__);
if (var_fake_power_button & (1 << WKS_USBOC2))
notify_framwork=1;
}
if (status & (1 << WKS_USBOC1)){
DPRINTK(KERN_ALERT "\n[%s]USBOC1 event\n",__func__);
if (var_fake_power_button & (1 << WKS_USBOC1))
notify_framwork=1;
}
if (status & (1 << WKS_USBOC0)){
DPRINTK(KERN_ALERT "\n[%s]USBOC0 event\n",__func__);
if (var_fake_power_button & (1 << WKS_USBOC0))
notify_framwork=1;
}
#endif
#ifdef RTC_WAKEUP_SUPPORT
if (status & (1 << WKS_RTC)){
DPRINTK(KERN_ALERT "\n[%s]RTC event\n",__func__);
if (var_fake_power_button & (1 << WKS_RTC))
notify_framwork=1;
}
#endif
if (status & (1 << WKS_CIRIN)){
DPRINTK(KERN_ALERT "\n[%s]CIRIN event\n",__func__);
if (var_fake_power_button & (1 << WKS_CIRIN))
notify_framwork=1;
}
#ifdef CONFIG_USB_GADGET_WMT
/*UDC2 wake up source*/
if (status & (1 << WKS_USBATTA0)){
DPRINTK(KERN_ALERT "\n[%s]UDCATTA0 event\n",__func__);
if (var_fake_power_button & (1 << WKS_USBATTA0))
notify_framwork=1;
}
#endif
if(status & (1 << WKS_SUS1)){
DPRINTK(KERN_ALERT "\n[%s]SUS1 event\n",__func__);
if (var_fake_power_button & (1 << WKS_SUS1))
notify_framwork=1;
}
if(status & (1 << WKS_SUS0)){
DPRINTK(KERN_ALERT "\n[%s]SUS0 event\n",__func__);
if (var_fake_power_button & (1 << WKS_SUS0))
notify_framwork=1;
}
if(status & (1 << WKS_WK4)){
DPRINTK(KERN_ALERT "\n[%s]WK4 event\n",__func__);
if (var_fake_power_button & (1 << WKS_WK4))
notify_framwork=1;
}
if (status & (1 << WKS_WK3)){
DPRINTK(KERN_ALERT "\n[%s]WK3 event\n",__func__);
if (var_fake_power_button & (1 << WKS_WK3))
notify_framwork=1;
}
if (status & (1 << WKS_WK2)){
DPRINTK(KERN_ALERT "\n[%s]WK2 event\n",__func__);
if (var_fake_power_button & (1 << WKS_WK2))
notify_framwork=1;
}
if (status & (1 << WKS_WK0)){
DPRINTK(KERN_ALERT "\n[%s]WK0 event\n",__func__);
if (var_fake_power_button & (1 << WKS_WK0))
notify_framwork=1;
}
if (notify_framwork) {
wmt_trigger_resume_notify = 1;
}
#ifdef RTC_WAKEUP_SUPPORT
RTAS_VAL = 0x0; /* Disable RTC alarm */
#endif
/*
* Force to do once CPR for system.
*/
OSM1_VAL = wmt_read_oscr() + LATCH;
OSTC_VAL |= OSTC_ENABLE;
//udelay(200); /* delay for resume not complete */
/*
* disable trigger wakeup event
*/
do {
WK_TRG_EN_VAL = 0x4000;
} while(WK_TRG_EN_VAL != 0x4000);
return 0;
}
/* wmt_pm_prepare()
*
* Called after processes are frozen, but before we shut down devices.
*/
static int wmt_pm_prepare(void)
{
unsigned int date, time;
struct timeval tv;
/*
* Estimate time zone so that wmt_pm_finish can update the GMT time
*/
rtc2sys = 0;
if ((*(volatile unsigned int *)SYSTEM_CFG_CTRL_BASE_ADDR)>0x34260102) {
wmt_read_rtc(&date, &time);
}
do_gettimeofday(&tv);
rtc2sys = mktime(RTCD_YEAR(date) + ((RTCD_CENT(date) * 100) + 2000),
RTCD_MON(date),
RTCD_MDAY(date),
RTCT_HOUR(time),
RTCT_MIN(time),
RTCT_SEC(time));
rtc2sys = rtc2sys-tv.tv_sec;
if (rtc2sys > 0)
rtc2sys += 10;
else
rtc2sys -= 10;
rtc2sys = rtc2sys/60/60;
rtc2sys = rtc2sys*60*60;
return 0;
}
/* wmt_pm_finish()
*
* Called after devices are re-setup, but before processes are thawed.
*/
static void wmt_pm_finish(void)
{
unsigned int date, time;
struct timespec tv;
#if 0
struct rtc_time tm;
unsigned long tmp = 0;
struct timeval tv1;
#endif
/* FIXME:
* There are a warning when call iounmap here,
* please iounmap the mapped virtual ram later */
// iounmap((void *)exec_at);
/*
* Update kernel time spec.
*/
if ((*(volatile unsigned int *)SYSTEM_CFG_CTRL_BASE_ADDR)>0x34260102) {
wmt_read_rtc(&date, &time);
}
tv.tv_nsec = 0;
tv.tv_sec = mktime(RTCD_YEAR(date) + ((RTCD_CENT(date) * 100) + 2000),
RTCD_MON(date),
RTCD_MDAY(date),
RTCT_HOUR(time),
RTCT_MIN(time),
RTCT_SEC(time));
/* RTC stores local time, adjust GMT time, tv */
tv.tv_sec = tv.tv_sec-rtc2sys;
do_settimeofday(&tv);
}
static int wmt_pm_valid(suspend_state_t state)
{
switch (state) {
case PM_SUSPEND_STANDBY:
case PM_SUSPEND_MEM:
return 1;
default:
return 0;
}
}
static struct platform_suspend_ops wmt_pm_ops = {
.valid = wmt_pm_valid,
.prepare = wmt_pm_prepare,
.enter = wmt_pm_enter,
.finish = wmt_pm_finish,
};
#if 0
#if defined(SOFT_POWER_SUPPORT) && defined(CONFIG_PROC_FS)
static int procfile_read(char *page, char **start, off_t off, int count, int *eof, void *data)
{
int len = 0;
len = sprintf(page, "%d\n", softpower_data);
return len;
}
static int procfile_write(struct file *file, const char *buffer, unsigned long count, void *data)
{
char *endp;
softpower_data = simple_strtoul(buffer, &endp, 0);
if (softpower_data != 0)
softpower_data = 1;
/* printk("%s: %s, softpower_data=[0x%X]\n", DRIVER_NAME, __FUNCTION__, softpower_data );*/
/* printk("%s: return [%d]\n", DRIVER_NAME, (count + endp - buffer ) );*/
return (count + endp - buffer);
}
#endif /* defined(SOFT_POWER_SUPPORT) && defined(CONFIG_PROC_FS)*/
#endif
#ifdef KEYPAD_POWER_SUPPORT
static inline void kpadPower_timeout(unsigned long fcontext)
{
struct input_dev *dev = (struct input_dev *) fcontext;
//printk("-------------------------> kpadPower time out\n");
time2 = jiffies_to_msecs(jiffies);
if ((time2 - time1) > 2000 && sync_counter > 4) { //2000 msec
schedule_work(&PMC_sync);
//DPRINTK("1[%s]dannier count=%d jiffies=%lu, %d\n",__func__, sync_counter, jiffies,jiffies_to_msecs(jiffies));
} //else
//DPRINTK("0[%s]dannier count=%d jiffies=%lu, %d\n",__func__, sync_counter, jiffies,jiffies_to_msecs(jiffies));
DPRINTK(KERN_ALERT "\n[%s]kpadPower time out GPIO_ID_GPIO_VAL = %x\n",__func__,GPIO_ID_GPIO_VAL);
if(!kpadPower_dev)
return;
spin_lock_irq(&kpadPower_lock);
if(!(PMPB_VAL & BIT24)) {
input_report_key(dev, KEY_POWER, 0); //power key is released
input_sync(dev);
powerKey_is_pressed = 0;
wmt_pwrbtn_debounce_value(power_on_debounce_value);
DPRINTK("[%s]power key released\n",__func__);
sync_counter = 0;
}else {
DPRINTK("[%s]power key not released\n",__func__);
mod_timer(&kpadPower_timer, jiffies + power_button_timeout);
sync_counter++;
}
spin_unlock_irq(&kpadPower_lock);
}
#endif
static int wmt_wakeup_pm_notify(struct notifier_block *nb, unsigned long event,
void *dummy)
{
unsigned long pm_lock_flags;
spin_lock_irqsave(&wmt_pm_lock, pm_lock_flags);
if (event == PM_SUSPEND_PREPARE) {
dynamic_pmc_intr = INT_TRG_EN_VAL;
do {
INT_TRG_EN_VAL = 0;
} while (INT_TRG_EN_VAL != 0);
PMWS_VAL = PMWS_VAL;
do {
WK_TRG_EN_VAL = (Wake_up_sts_mask | dynamic_wakeup);
} while (WK_TRG_EN_VAL != (Wake_up_sts_mask | dynamic_wakeup));
} else if (event == PM_POST_SUSPEND) {
do {
INT_TRG_EN_VAL = dynamic_pmc_intr;
} while (INT_TRG_EN_VAL != dynamic_pmc_intr);
do {
WK_TRG_EN_VAL = 0x4000;
} while (WK_TRG_EN_VAL != 0x4000);
}
spin_unlock_irqrestore(&wmt_pm_lock, pm_lock_flags);
return NOTIFY_OK;
}
static struct notifier_block wmt_pmc_pm_notify = {
.notifier_call = wmt_wakeup_pm_notify,
};
#ifdef CONFIG_HIBERNATION
static int wmt_hibernation_begin(void)
{
printk("\n!!! %s:Enter\n",__FUNCTION__);
disable_hlt();
return 0;
}
unsigned int saved[SAVED_SIZE];
unsigned int plla_div[7];
unsigned int pllb_div[25];
unsigned int plld_div[4];
#ifdef CONFIG_CACHE_L2X0
__u32 power_cntrl;
#endif
static int wmt_hibernation_pre_snapshot(void)
{
int result;
#ifdef CONFIG_CACHE_L2X0
volatile unsigned int l2x0_base;
#endif
printk("\n!!! %s:Enter\n",__FUNCTION__);
#if 1
result = PM_device_PostSuspend();
if (result)
printk("\n %s : PM_device_PostSuspend fail\n", __FUNCTION__);
#endif
#ifdef CONFIG_CACHE_L2X0
if( l2x0_onoff == 1)
{
l2x0_base = (volatile unsigned int) ioremap(0xD9000000, SZ_4K);
outer_cache.flush_all();
outer_cache.disable();
outer_cache.inv_all();
}
#endif
SAVE(OSTW); /* save vital registers */
SAVE(OSTI);
SAVE(PMCEL); /* save clock gating */
SAVE(PMCEU);
SAVE(PMCE2);
SAVE(PMCE3);
//for single core, sev to make cpu1 out of wfe.
#ifndef CONFIG_SMP
HSP7_VAL = 0xffffffb8;
while(HSP7_VAL != 0xffffffb8);
asm("sev" : : "r" (0));
#endif
save_plld_speed(plld_div); /*save plld clock register*/
save_pllb_speed(pllb_div); /*save pllb clock register*/
if (!use_dvfs)
save_plla_speed(plla_div);
return 0;
}
static void wmt_hibernation_leave(void)
{
int result;
#ifdef CONFIG_CACHE_L2X0
volatile unsigned int l2x0_base;
#endif
printk("\n!!! %s:Enter\n",__FUNCTION__);
RESTORE(PMCE3);
RESTORE(PMCE2);
RESTORE(PMCEU); /* restore clock gating */
RESTORE(PMCEL);
RESTORE(OSTI); /* restore vital registers */
RESTORE(OSTW);
wmt_serial_set_reg();
if (!use_dvfs)
restore_plla_speed(plla_div); /* restore plla clock register */
restore_pllb_speed(pllb_div); /* restore pllb clock register */
restore_plld_speed(plld_div); /* restore plld clock register */
PMPB_VAL |= 1; /* enable soft power */
#ifdef CONFIG_CACHE_L2X0
if( l2x0_onoff == 1)
{
l2x0_base = (volatile unsigned int) ioremap(0xD9000000, SZ_4K);
if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1))
{
writel_relaxed(l2x0_aux, l2x0_base + L2X0_AUX_CTRL);
if( en_static_address_filtering == 1 )
{
writel_relaxed(address_filtering_end, l2x0_base + 0xC04);
writel_relaxed((address_filtering_start | 0x01), l2x0_base + 0xC00);
}
writel_relaxed(0x110, l2x0_base + L2X0_TAG_LATENCY_CTRL);
writel_relaxed(0x110, l2x0_base + L2X0_DATA_LATENCY_CTRL);
power_cntrl = readl_relaxed(l2x0_base + L2X0_POWER_CTRL) | L2X0_DYNAMIC_CLK_GATING_EN | L2X0_STNDBY_MODE_EN;
writel_relaxed(power_cntrl, l2x0_base + L2X0_POWER_CTRL);
writel_relaxed(l2x0_prefetch_ctrl, l2x0_base + L2X0_PREFETCH_CTRL);
outer_cache.inv_all();
writel_relaxed(1, l2x0_base + L2X0_CTRL);
}
iounmap((void __iomem *)l2x0_base);
}
#endif
result = PM_device_PreResume();
if (!result)
printk("PM_device_PreResume fail\n");
}
static void wmt_hibernation_finish(void)
{
extern int env_cache_flush(void);
int ret;
printk("\n!!! %s:Enter\n",__FUNCTION__);
ret = env_cache_flush();
if(!ret)
printk("env_cache_flush success.\n");
}
static void wmt_hibernation_end(void)
{
printk("\n!!! %s:Enter\n",__FUNCTION__);
enable_hlt();
}
static int wmt_hibernation_prepare(void)
{
printk("\n!!! %s:Enter\n",__FUNCTION__);
return 0;
}
static int wmt_hibernation_enter(void)
{
int std_stress_test = 0;
int ret;
char buf_env[80];
int varlen = sizeof(buf_env);
printk("\n!!! %s:Enter\n",__FUNCTION__);
ret = wmt_getsyspara("wmt.std.stress", buf_env, &varlen);
if (ret == 0)
sscanf(buf_env, "%d", &std_stress_test);
if(std_stress_test) {
printk(KERN_CRIT "\n Do STD Stress Test \n");
machine_restart(NULL);
}else{
printk(KERN_CRIT "\n No Stress Test \n");
machine_power_off();
}
return 0;
}
static int wmt_hibernation_pre_restore(void)
{
printk("\n!!! %s:Enter\n",__FUNCTION__);
return 0;
}
static void wmt_hibernation_restore_cleanup(void)
{
printk("\n!!! %s:Enter\n",__FUNCTION__);
}
static const struct platform_hibernation_ops wmt_hibernation_ops = {
.begin = wmt_hibernation_begin,
.end = wmt_hibernation_end,
.pre_snapshot = wmt_hibernation_pre_snapshot,
.finish = wmt_hibernation_finish,
.prepare = wmt_hibernation_prepare,
.enter = wmt_hibernation_enter,
.leave = wmt_hibernation_leave,
.pre_restore = wmt_hibernation_pre_restore,
.restore_cleanup = wmt_hibernation_restore_cleanup,
};
#endif
/*
* Initialize power management interface
*/
static int __init wmt_pm_init(void)
{
struct apm_dev_s *pm_dev;
char buf[256];
char varname[] = "wmt.pwbn.param";
int varlen = 256;
char wake_buf[100];
char wake_varname[] = "wmt.pmc.param";
int wake_varlen = 100;
#ifdef CONFIG_BATTERY_WMT
char bat_varname[] = "wmt.io.bat";
#endif
#ifdef KEYPAD_POWER_SUPPORT
int i;
kpadPower_dev = input_allocate_device();
if(kpadPower_dev) {
//Initial the static variable
spin_lock_init(&kpadPower_lock);
powerKey_is_pressed = 0;
pressed_jiffies = 0;
init_timer(&kpadPower_timer);
kpadPower_timer.function = kpadPower_timeout;
kpadPower_timer.data = (unsigned long)kpadPower_dev;
/* Register an input event device. */
set_bit(EV_KEY,kpadPower_dev->evbit);
for (i = 0; i < KPAD_POWER_FUNCTION_NUM; i++)
set_bit(kpadPower_codes[i], kpadPower_dev->keybit);
kpadPower_dev->name = "kpadPower",
kpadPower_dev->phys = "kpadPower",
kpadPower_dev->keycode = kpadPower_codes;
kpadPower_dev->keycodesize = sizeof(unsigned int);
kpadPower_dev->keycodemax = KPAD_POWER_FUNCTION_NUM;
/*
* For better view of /proc/bus/input/devices
*/
kpadPower_dev->id.bustype = 0;
kpadPower_dev->id.vendor = 0;
kpadPower_dev->id.product = 0;
kpadPower_dev->id.version = 0;
input_register_device(kpadPower_dev);
} else
printk("[wmt_pm_init]Error: No memory for registering Kpad Power\n");
#endif
register_pm_notifier(&wmt_pmc_pm_notify);
//gri
if (! pmlock_1st_flag) {
pmlock_1st_flag = 1;
spin_lock_init(&wmt_pm_lock);
}
if (! pmlock_intr_1st_flag) {
pmlock_intr_1st_flag = 1;
spin_lock_init(&wmt_pm_intr_lock);
}
if (wmt_getsyspara(wake_varname, wake_buf, &wake_varlen) == 0) {
sscanf(wake_buf,"%x:%x:%x:%x:%x",
&var_wake_en,
&var_wake_param,
&var_wake_type,
&var_wake_type2,
&var_fake_power_button);
}
else {
var_wake_en = 1;
var_wake_param = 0x0040C080; //cir rtc pwrbtn dcdet(cirin)
var_wake_type = 0x40000000;
var_wake_type2 = 0x0;
var_fake_power_button = 0x00400080;
}
Wake_up_sts_mask = (var_wake_param | BIT14); // add power button
var_1st_flag = 1;
printk("[%s] var define var_wake_en=%x var_wake_param=%x var_wake_type=%x var_wake_type2=%x var_fake_power_button=%x\n",
__func__, var_wake_en, var_wake_param, var_wake_type, var_wake_type2, var_fake_power_button);
#if 0//test pmc_enable_wakeup_event
do {
WK_EVT_TYPE_VAL = 0x33333333;
} while (WK_EVT_TYPE_VAL != 0x33333333);
{
unsigned int i_temp, en_temp, en_type;
i_temp = 0;
en_type = 0;
do {
en_temp = (var_wake_param & (1 << i_temp));
if (en_temp) {
if (en_temp < 0x100)
en_type = ((var_wake_type >> (i_temp << 2)) & 0xf);
else if(en_temp >= 0x1000000)
en_type = ((var_wake_type2 >> ((i_temp - 24) << 2)) & 0xf);
else if(en_temp == 0x200000)
en_type = ((var_wake_type >> 24) & 0xf);
else
en_type = 3;
printk("en_temp 0x%x en_type 0x%x\n",i_temp,en_type);
pmc_enable_wakeup_event(i_temp, en_type);
}
i_temp++;
} while (i_temp < 32);
}
#else
{
unsigned int i_temp;
do {
PMWT_VAL = var_wake_type;
} while(PMWT_VAL != var_wake_type);
do {
PMWTC_VAL = var_wake_type2;
} while(PMWTC_VAL != var_wake_type2);
if (var_wake_param & BIT21)
i_temp = 0x33433333;
else
i_temp = 0x33333333;
do {
WK_EVT_TYPE_VAL = i_temp;
} while(WK_EVT_TYPE_VAL != i_temp);
}
#endif
printk("[%s] WK_TRG_EN_VAL=0x%x PMWT_VAL=0x%x PMWTC_VAL=0x%x WK_EVT_TYPE_VAL=0x%x\n",
__func__, WK_TRG_EN_VAL, PMWT_VAL, PMWTC_VAL, WK_EVT_TYPE_VAL);
#ifdef CONFIG_BATTERY_WMT
if (wmt_getsyspara(bat_varname, buf, &varlen) == 0) {
sscanf(buf,"%x", &battery_used);
}
printk("[%s] battery_used = %x\n",__func__, battery_used);
#endif
#ifdef CONFIG_CACHE_L2X0
if(wmt_getsyspara("wmt.l2c.param",buf,&varlen) == 0)
sscanf(buf,"%d:%x:%x:%d:%x:%x",&l2x0_onoff, &l2x0_aux, &l2x0_prefetch_ctrl, &en_static_address_filtering, &address_filtering_start, &address_filtering_end);
if( l2x0_onoff == 1)
l2x0_base = (volatile unsigned int) ioremap(0xD9000000, SZ_4K);
if (wmt_getsyspara("wmt.secure.param",buf,&varlen) == 0)
sscanf(buf,"%d",&cpu_trustzone_enabled);
if(cpu_trustzone_enabled != 1)
cpu_trustzone_enabled = 0;
#endif
/* Press power button (either hard-power or soft-power) will trigger a power button wakeup interrupt*/
/* Press reset button will not trigger any PMC wakeup interrupt*/
/* Hence, force write clear all PMC wakeup interrupts before request PMC wakeup IRQ*/
//move to wload
//PMWS_VAL = PMWS_VAL;
//PMCIS_VAL = PMCIS_VAL;
INIT_WORK(&PMC_shutdown, run_shutdown);
INIT_WORK(&PMC_sync, run_sync);
/*
* set interrupt service routine
*/
// if (request_irq(IRQ_PMC_WAKEUP, &pmc_wakeup_isr, IRQF_DISABLED, "pmc", &pm_dev) < 0)
if (request_irq(IRQ_PMC_WAKEUP, &pmc_wakeup_isr, IRQF_SHARED, "pmc", &pm_dev) < 0)
printk(KERN_ALERT "%s: [Wondermedia_pm_init] Failed to register pmc wakeup irq \n"
, DRIVER_NAME);
irq_set_irq_wake(IRQ_PMC_WAKEUP, 1);
#ifndef CONFIG_SKIP_DRIVER_MSG
/*
* Plan to remove it to recude core size in the future.
*/
printk(KERN_INFO "%s: WonderMedia Power Management driver\n", DRIVER_NAME);
#endif
/*
* Setup PM core driver into kernel.
*/
suspend_set_ops(&wmt_pm_ops);
#ifdef CONFIG_HIBERNATION
hibernation_set_ops(&wmt_hibernation_ops);//support hibernation platform mode
#endif /* CONFIG_HIBERNATION */
#if defined(SOFT_POWER_SUPPORT) && defined(CONFIG_PROC_FS)
/* Power button is configured as soft power*/
printk("%s: Power button is configured as soft power\n", DRIVER_NAME);
PMPB_VAL |= PMPB_SOFTPWR;
#if 0
/* Create proc entry*/
proc_softpower = create_proc_entry("softpower", 0644, &proc_root);
proc_softpower->data = &softpower_data;
proc_softpower->read_proc = procfile_read;
proc_softpower->write_proc = procfile_write;
#endif
#else
/* Power button is configured as hard power*/
printk("%s: Power button is configured as hard power\n", DRIVER_NAME);
PMPB_VAL = 0;
#endif /* defined(SOFT_POWER_SUPPORT) && defined(CONFIG_PROC_FS)*/
/*read power button debounce value*/
if (wmt_getsyspara(varname, buf, &varlen) == 0){
sscanf(buf,"%d:%d:%d",
&power_on_debounce_value,
&resume_debounce_value,
&power_up_debounce_value);
if (power_on_debounce_value < min_debounce_value)
power_on_debounce_value = min_debounce_value;
if (power_on_debounce_value > max_debounce_value)
power_on_debounce_value = max_debounce_value;
if (resume_debounce_value < min_debounce_value)
resume_debounce_value = min_debounce_value;
if (resume_debounce_value > max_debounce_value)
resume_debounce_value = max_debounce_value;
if (power_up_debounce_value < min_debounce_value)
power_up_debounce_value = min_debounce_value;
if (power_up_debounce_value > max_debounce_value)
power_up_debounce_value = max_debounce_value;
}
/*set power button debounce value*/
printk("[%s] power_on = %d resume = %d power_up = %d\n",
__func__,power_on_debounce_value, resume_debounce_value, power_up_debounce_value);
wmt_pwrbtn_debounce_value(power_on_debounce_value);
wmt_ws = wakeup_source_register("wmt_pwbn");
//enable power button intr
pmc_enable_wakeup_isr(WKS_PWRBTN, 0);
memset(buf ,0, sizeof(buf));
varlen = sizeof(buf);
if ((wmt_getsyspara("wmt.gpo.hall_switch", buf, &varlen) == 0)) {
int ret = sscanf(buf, "%d:%d",
&hall_switch.gpio_no,
&hall_switch.wakeup_source
);
//printk(KERN_ERR"hall_switch gpiono:%d ws:%d\n",hall_switch.gpio_no,hall_switch.wakeup_source);
ret = gpio_request(hall_switch.gpio_no, "hall_switch");
if(ret < 0) {
printk(KERN_ERR"gpio request fail for hall_switch\n");
goto hswitch_done;
}
gpio_direction_input(hall_switch.gpio_no);
wmt_gpio_setpull(hall_switch.gpio_no, WMT_GPIO_PULL_UP);
pmc_enable_wakeup_isr(hall_switch.wakeup_source,4);
wakeup_queue=create_workqueue("wakeup0");
INIT_DELAYED_WORK(&wakeupwork, wakeup_func);
hall_switch.have_switch = 1;
}
hswitch_done:
return 0;
}
late_initcall(wmt_pm_init);