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:
parent
3ccaecfa6f
commit
b177a917da
|
|
@ -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)) {
|
printf("power key long pressed...\n");
|
||||||
pressed_time = get_timer(0);
|
else if (state == KEY_PRESS_DOWN)
|
||||||
return KEY_NOT_PRESSED;
|
printf("power key short pressed...\n");
|
||||||
} else {
|
|
||||||
debug("key state = %d\n", state);
|
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
|
* We must wait for key release event finish, otherwise
|
||||||
* treat 'key long pressed' release as a 'short key pressed'
|
* we may read key state too early.
|
||||||
* release.
|
|
||||||
*/
|
*/
|
||||||
} else if ((state == KEY_PRESS_UP) &&
|
mdelay(300);
|
||||||
(old_state != KEY_LONG_PRESSED)) {
|
} else {
|
||||||
report = KEY_SHORT_PRESSED;
|
printf("\nWfi\n");
|
||||||
old_state = report;
|
wfi();
|
||||||
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");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
return 0;
|
||||||
return report;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue