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+ * SPDX-License-Identifier: GPL-2.0+
*/ */
#include <asm/suspend.h>
#include <asm/arch/rockchip_smccc.h>
#include <asm/arch/bootrkp.h> #include <asm/arch/bootrkp.h>
#include <common.h> #include <common.h>
#include <console.h> #include <console.h>
#include <dm.h> #include <dm.h>
#include <errno.h> #include <errno.h>
#include <key.h> #include <key.h>
#include <irq-generic.h>
#include <linux/input.h> #include <linux/input.h>
#include <pwm.h> #include <pwm.h>
#include <power/charge_display.h> #include <power/charge_display.h>
@ -21,15 +24,8 @@
DECLARE_GLOBAL_DATA_PTR; DECLARE_GLOBAL_DATA_PTR;
#define LONG_PRESSED_TIME 2000 /* 2s */
#define IMAGE_SHOW_RESET -1 #define IMAGE_SHOW_RESET -1
enum key_event {
KEY_NOT_PRESSED = 0,
KEY_SHORT_PRESSED,
KEY_LONG_PRESSED,
};
struct charge_image { struct charge_image {
const char *name; const char *name;
int soc; int soc;
@ -167,60 +163,61 @@ static int charge_animation_ofdata_to_platdata(struct udevice *dev)
return 0; 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; u32 state;
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;
}
state = key_read(dev); state = key_read(dev);
if (state < 0) { if (state < 0)
printf("read power key failed: %d\n", state); printf("read power key failed: %d\n", state);
goto out;
}
/* Start time is not initialized, let's do it */ if (state == KEY_PRESS_LONG_DOWN)
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_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"); printf("power key long pressed...\n");
} else if (state == KEY_PRESS_DOWN)
/*
* If you don't check 'old_state != KEY_LONG_PRESSED', it will
* treat 'key long pressed' release as a 'short key pressed'
* release.
*/
} 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"); printf("power key short pressed...\n");
} else {
report = KEY_NOT_PRESSED; return state;
old_state = report;
pressed_time = 0;
debug("power key Not pressed...\n");
}
} }
out: static int system_suspend_enter(void)
return report; {
/*
* 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');
/*
* We must wait for key release event finish, otherwise
* we may read key state too early.
*/
mdelay(300);
} else {
printf("\nWfi\n");
wfi();
}
return 0;
} }
static int charge_animation_show(struct udevice *dev) 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); debug("SHOW: %s\n", image[show_idx].name);
rockchip_show_bmp(image[show_idx].name); rockchip_show_bmp(image[show_idx].name);
} else { } else {
/* system_suspend_enter();
* 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 ?
*/
} }
mdelay(5); mdelay(5);
@ -409,8 +398,8 @@ static int charge_animation_show(struct udevice *dev)
* Short key event: turn on/off screen; * Short key event: turn on/off screen;
* Long key event: show logo and boot system or still charging. * Long key event: show logo and boot system or still charging.
*/ */
key_state = check_key_press(pwrkey, false); key_state = check_key_press(pwrkey);
if (key_state == KEY_SHORT_PRESSED) { if (key_state == KEY_PRESS_DOWN) {
/* NULL means show nothing, ie. turn off screen */ /* NULL means show nothing, ie. turn off screen */
if (screen_on) if (screen_on)
rockchip_show_bmp(NULL); rockchip_show_bmp(NULL);
@ -435,7 +424,7 @@ static int charge_animation_show(struct udevice *dev)
screen_on = false; screen_on = false;
else else
screen_on = true; 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 */ /* Only long pressed while screen off needs screen_on true */
if (!screen_on) if (!screen_on)
screen_on = true; screen_on = true;
@ -445,8 +434,6 @@ static int charge_animation_show(struct udevice *dev)
printf("soc=%d%%, threshold soc=%d%%\n", printf("soc=%d%%, threshold soc=%d%%\n",
soc, pdata->power_on_soc_threshold); soc, pdata->power_on_soc_threshold);
printf("Low power, unable to boot, charging...\n"); 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; show_idx = image_num - 1;
continue; continue;
} }
@ -455,8 +442,6 @@ static int charge_animation_show(struct udevice *dev)
printf("voltage=%dmv, threshold voltage=%dmv\n", printf("voltage=%dmv, threshold voltage=%dmv\n",
voltage, pdata->power_on_voltage_threshold); voltage, pdata->power_on_voltage_threshold);
printf("Low power, unable to boot, charging...\n"); 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; show_idx = image_num - 1;
continue; continue;
} }