power: charge animation: add system suspend support

cpu0 will trap into ATF for system suspend, ATF can
lead system to a extrem low power state.

Change-Id: I1fad3671a11ed41d22533d21fb0df656b4a84e82
Signed-off-by: Joseph Chen <chenjh@rock-chips.com>
This commit is contained in:
Joseph Chen 2017-11-27 16:57:51 +08:00 committed by Kever Yang
parent 3ccaecfa6f
commit b177a917da
1 changed files with 52 additions and 67 deletions

View File

@ -4,12 +4,15 @@
* SPDX-License-Identifier: GPL-2.0+
*/
#include <asm/suspend.h>
#include <asm/arch/rockchip_smccc.h>
#include <asm/arch/bootrkp.h>
#include <common.h>
#include <console.h>
#include <dm.h>
#include <errno.h>
#include <key.h>
#include <irq-generic.h>
#include <linux/input.h>
#include <pwm.h>
#include <power/charge_display.h>
@ -21,15 +24,8 @@
DECLARE_GLOBAL_DATA_PTR;
#define LONG_PRESSED_TIME 2000 /* 2s */
#define IMAGE_SHOW_RESET -1
enum key_event {
KEY_NOT_PRESSED = 0,
KEY_SHORT_PRESSED,
KEY_LONG_PRESSED,
};
struct charge_image {
const char *name;
int soc;
@ -167,60 +163,61 @@ static int charge_animation_ofdata_to_platdata(struct udevice *dev)
return 0;
}
static int check_key_press(struct udevice *dev, bool restar_time)
static int check_key_press(struct udevice *dev)
{
static unsigned long pressed_time;
static int old_state;
int report = KEY_NOT_PRESSED;
int state;
/* just for restart time */
if (restar_time) {
pressed_time = get_timer(0);
goto out;
}
u32 state;
state = key_read(dev);
if (state < 0) {
if (state < 0)
printf("read power key failed: %d\n", state);
goto out;
}
/* Start time is not initialized, let's do it */
if (!pressed_time && (state == KEY_PRESS_DOWN)) {
pressed_time = get_timer(0);
return KEY_NOT_PRESSED;
} else {
debug("key state = %d\n", state);
if (state == KEY_PRESS_LONG_DOWN)
printf("power key long pressed...\n");
else if (state == KEY_PRESS_DOWN)
printf("power key short pressed...\n");
return state;
}
static int system_suspend_enter(void)
{
/*
* TODO: enter low power mode:
* 3. auto turn off screen when timout;
* 4. power key wakeup;
* 5. timer period wakeup for pmic fg ?
*/
if (IS_ENABLED(CONFIG_ARM_SMCCC)) {
printf("\nSystem suspend: ");
putc('1');
local_irq_disable();
putc('2');
irqs_suspend();
putc('3');
putc('\n');
/* Trap into ATF for low power mode */
cpu_suspend(0, psci_system_suspend);
putc('\n');
putc('3');
irqs_resume();
putc('2');
local_irq_enable();
putc('1');
putc('\n');
if (state == KEY_PRESS_DOWN) {
if (get_timer(pressed_time) >= LONG_PRESSED_TIME) {
report = KEY_LONG_PRESSED;
pressed_time = 0;
old_state = KEY_LONG_PRESSED;
printf("power key long pressed...\n");
}
/*
* If you don't check 'old_state != KEY_LONG_PRESSED', it will
* treat 'key long pressed' release as a 'short key pressed'
* release.
* We must wait for key release event finish, otherwise
* we may read key state too early.
*/
} else if ((state == KEY_PRESS_UP) &&
(old_state != KEY_LONG_PRESSED)) {
report = KEY_SHORT_PRESSED;
old_state = report;
pressed_time = 0;
printf("power key short pressed...\n");
} else {
report = KEY_NOT_PRESSED;
old_state = report;
pressed_time = 0;
debug("power key Not pressed...\n");
}
mdelay(300);
} else {
printf("\nWfi\n");
wfi();
}
out:
return report;
return 0;
}
static int charge_animation_show(struct udevice *dev)
@ -379,15 +376,7 @@ static int charge_animation_show(struct udevice *dev)
debug("SHOW: %s\n", image[show_idx].name);
rockchip_show_bmp(image[show_idx].name);
} else {
/*
* TODO: enter low power mode:
*
* 1. cut off some regualtors;
* 2. set 24MHZ for some PLLs;
* 3. auto turn off screen when timout;
* 4. power key wakeup;
* 5. timer period wakeup for pmic fg ?
*/
system_suspend_enter();
}
mdelay(5);
@ -409,8 +398,8 @@ static int charge_animation_show(struct udevice *dev)
* Short key event: turn on/off screen;
* Long key event: show logo and boot system or still charging.
*/
key_state = check_key_press(pwrkey, false);
if (key_state == KEY_SHORT_PRESSED) {
key_state = check_key_press(pwrkey);
if (key_state == KEY_PRESS_DOWN) {
/* NULL means show nothing, ie. turn off screen */
if (screen_on)
rockchip_show_bmp(NULL);
@ -435,7 +424,7 @@ static int charge_animation_show(struct udevice *dev)
screen_on = false;
else
screen_on = true;
} else if (key_state == KEY_LONG_PRESSED) {
} else if (key_state == KEY_PRESS_LONG_DOWN) {
/* Only long pressed while screen off needs screen_on true */
if (!screen_on)
screen_on = true;
@ -445,8 +434,6 @@ static int charge_animation_show(struct udevice *dev)
printf("soc=%d%%, threshold soc=%d%%\n",
soc, pdata->power_on_soc_threshold);
printf("Low power, unable to boot, charging...\n");
/* 'true': just for clear time of check key */
check_key_press(pwrkey, true);
show_idx = image_num - 1;
continue;
}
@ -455,8 +442,6 @@ static int charge_animation_show(struct udevice *dev)
printf("voltage=%dmv, threshold voltage=%dmv\n",
voltage, pdata->power_on_voltage_threshold);
printf("Low power, unable to boot, charging...\n");
/* 'true': just for clear time of check key */
check_key_press(pwrkey, true);
show_idx = image_num - 1;
continue;
}