From e550c6310118d1369796751ce98fe66167db0861 Mon Sep 17 00:00:00 2001 From: Caesar Wang <wxt@rock-chips.com> Date: Sat, 10 Sep 2016 02:43:15 +0800 Subject: [PATCH] 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 --- plat/rockchip/common/include/plat_params.h | 11 +++++ plat/rockchip/common/include/plat_private.h | 5 +- plat/rockchip/common/params_setup.c | 55 +++++++++++++-------- plat/rockchip/rk3399/drivers/pmu/pmu.c | 38 +++++++++++++- 4 files changed, 85 insertions(+), 24 deletions(-) diff --git a/plat/rockchip/common/include/plat_params.h b/plat/rockchip/common/include/plat_params.h index cad453535..7e1f275f7 100644 --- a/plat/rockchip/common/include/plat_params.h +++ b/plat/rockchip/common/include/plat_params.h @@ -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 { diff --git a/plat/rockchip/common/include/plat_private.h b/plat/rockchip/common/include/plat_private.h index b9b634e7b..4f87a7602 100644 --- a/plat/rockchip/common/include/plat_private.h +++ b/plat/rockchip/common/include/plat_private.h @@ -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[]; diff --git a/plat/rockchip/common/params_setup.c b/plat/rockchip/common/params_setup.c index 2a49556f4..351d21361 100644 --- a/plat/rockchip/common/params_setup.c +++ b/plat/rockchip/common/params_setup.c @@ -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 *)¶m_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(¶m_reset, &gpio_param->gpio, + sizeof(struct gpio_info)); + rst_gpio = ¶m_reset; break; case PARAM_POWEROFF: - param = (struct bl31_plat_param *)¶m_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(¶m_poweroff, &gpio_param->gpio, + sizeof(struct gpio_info)); + poweroff_gpio = ¶m_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; } } diff --git a/plat/rockchip/rk3399/drivers/pmu/pmu.c b/plat/rockchip/rk3399/drivers/pmu/pmu.c index 50953d831..d2dfdf20e 100755 --- a/plat/rockchip/rk3399/drivers/pmu/pmu.c +++ b/plat/rockchip/rk3399/drivers/pmu/pmu.c @@ -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) { /* -- GitLab