Commit e550c631 authored by Caesar Wang's avatar Caesar Wang
Browse files

rockchip: support disable/enable specific gpio when suspend/resume

some specific board need to disable/enable specific gpio when
suspend/resume, so we add this function, bootloader can pass the
specific gpio, and we can handle these gpios in bl31 suspend/resuem
function.

Change-Id: I373b03ef9202ee4a05a2b9caacdfa01b47ee2177
parent 536c2492
......@@ -63,11 +63,22 @@
* alignment fault will occur during accessing its data member.
*/
#define BL31_GPIO_DIR_OUT 0
#define BL31_GPIO_DIR_IN 1
#define BL31_GPIO_LEVEL_LOW 0
#define BL31_GPIO_LEVEL_HIGH 1
#define BL31_GPIO_PULL_NONE 0
#define BL31_GPIO_PULL_UP 1
#define BL31_GPIO_PULL_DOWN 2
/* param type */
enum {
PARAM_NONE = 0,
PARAM_RESET,
PARAM_POWEROFF,
PARAM_SUSPEND_GPIO,
};
struct gpio_info {
......
......@@ -121,8 +121,9 @@ uintptr_t plat_get_sec_entrypoint(void);
void platform_cpu_warmboot(void);
void *plat_get_rockchip_gpio_reset(void);
void *plat_get_rockchip_gpio_poweroff(void);
struct gpio_info *plat_get_rockchip_gpio_reset(void);
struct gpio_info *plat_get_rockchip_gpio_poweroff(void);
struct gpio_info *plat_get_rockchip_suspend_gpio(uint32_t *count);
void plat_rockchip_gpio_init(void);
extern const unsigned char rockchip_power_domain_tree_desc[];
......
......@@ -40,25 +40,32 @@
#include <plat_private.h>
#include <string.h>
static struct bl31_plat_param *bl31_params_head;
static struct bl31_gpio_param param_reset;
static struct bl31_gpio_param param_poweroff;
static struct gpio_info param_reset;
static struct gpio_info param_poweroff;
static struct gpio_info *rst_gpio;
static struct gpio_info *poweroff_gpio;
static struct gpio_info suspend_gpio[10];
uint32_t suspend_gpio_cnt;
void *plat_get_rockchip_gpio_reset(void)
struct gpio_info *plat_get_rockchip_gpio_reset(void)
{
return rst_gpio;
}
void *plat_get_rockchip_gpio_poweroff(void)
struct gpio_info *plat_get_rockchip_gpio_poweroff(void)
{
return poweroff_gpio;
}
struct gpio_info *plat_get_rockchip_suspend_gpio(uint32_t *count)
{
*count = suspend_gpio_cnt;
return &suspend_gpio[0];
}
void params_early_setup(void *plat_param_from_bl2)
{
struct bl31_plat_param *param;
struct bl31_plat_param *bl2_param;
struct bl31_gpio_param *gpio_param;
......@@ -67,25 +74,33 @@ void params_early_setup(void *plat_param_from_bl2)
while (bl2_param) {
switch (bl2_param->type) {
case PARAM_RESET:
param = (struct bl31_plat_param *)&param_reset;
memcpy((void *)param, (void *)bl2_param,
sizeof(struct bl31_gpio_param));
gpio_param = (struct bl31_gpio_param *)param;
rst_gpio = &gpio_param->gpio;
gpio_param = (struct bl31_gpio_param *)bl2_param;
memcpy(&param_reset, &gpio_param->gpio,
sizeof(struct gpio_info));
rst_gpio = &param_reset;
break;
case PARAM_POWEROFF:
param = (struct bl31_plat_param *)&param_poweroff;
memcpy((void *)param, (void *)bl2_param,
sizeof(struct bl31_gpio_param));
gpio_param = (struct bl31_gpio_param *)param;
poweroff_gpio = &gpio_param->gpio;
gpio_param = (struct bl31_gpio_param *)bl2_param;
memcpy(&param_poweroff, &gpio_param->gpio,
sizeof(struct gpio_info));
poweroff_gpio = &param_poweroff;
break;
case PARAM_SUSPEND_GPIO:
if (suspend_gpio_cnt >= ARRAY_SIZE(suspend_gpio)) {
ERROR("exceed support suspend gpio number\n");
break;
}
gpio_param = (struct bl31_gpio_param *)bl2_param;
memcpy(&suspend_gpio[suspend_gpio_cnt],
&gpio_param->gpio,
sizeof(struct gpio_info));
suspend_gpio_cnt++;
break;
default:
NOTICE("not expected type found\n");
return; /* don't continue if unexpected type found */
ERROR("not expected type found %ld\n",
bl2_param->type);
break;
}
param->next = bl31_params_head;
bl31_params_head = param;
bl2_param = bl2_param->next;
}
}
......@@ -874,6 +874,37 @@ static void clr_hw_idle(uint32_t hw_idle)
mmio_clrbits_32(PMU_BASE + PMU_BUS_CLR, hw_idle);
}
static void suspend_gpio(void)
{
struct gpio_info *suspend_gpio;
uint32_t count;
int i;
suspend_gpio = plat_get_rockchip_suspend_gpio(&count);
for (i = 0; i < count; i++) {
gpio_set_value(suspend_gpio[i].index, suspend_gpio[i].polarity);
gpio_set_direction(suspend_gpio[i].index, GPIO_DIR_OUT);
udelay(1);
}
}
static void resume_gpio(void)
{
struct gpio_info *suspend_gpio;
uint32_t count;
int i;
suspend_gpio = plat_get_rockchip_suspend_gpio(&count);
for (i = count - 1; i >= 0; i--) {
gpio_set_value(suspend_gpio[i].index,
!suspend_gpio[i].polarity);
gpio_set_direction(suspend_gpio[i].index, GPIO_DIR_OUT);
udelay(1);
}
}
static int sys_pwr_domain_suspend(void)
{
uint32_t wait_cnt = 0;
......@@ -928,6 +959,7 @@ static int sys_pwr_domain_suspend(void)
disable_dvfs_plls();
disable_pwms();
disable_nodvfs_plls();
suspend_gpio();
return 0;
}
......@@ -937,6 +969,8 @@ static int sys_pwr_domain_resume(void)
uint32_t wait_cnt = 0;
uint32_t status = 0;
resume_gpio();
enable_nodvfs_plls();
enable_pwms();
/* PWM regulators take time to come up; give 300us to be safe. */
......@@ -1010,7 +1044,7 @@ void __dead2 soc_soft_reset(void)
{
struct gpio_info *rst_gpio;
rst_gpio = (struct gpio_info *)plat_get_rockchip_gpio_reset();
rst_gpio = plat_get_rockchip_gpio_reset();
if (rst_gpio) {
gpio_set_direction(rst_gpio->index, GPIO_DIR_OUT);
......@@ -1027,7 +1061,7 @@ void __dead2 soc_system_off(void)
{
struct gpio_info *poweroff_gpio;
poweroff_gpio = (struct gpio_info *)plat_get_rockchip_gpio_poweroff();
poweroff_gpio = plat_get_rockchip_gpio_poweroff();
if (poweroff_gpio) {
/*
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment