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
diff --git a/plat/rockchip/common/include/plat_params.h b/plat/rockchip/common/include/plat_params.h
index cad4535..7e1f275 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 b9b634e..4f87a76 100644
--- a/plat/rockchip/common/include/plat_private.h
+++ b/plat/rockchip/common/include/plat_private.h
@@ -121,8 +121,9 @@
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 2a49556..351d213 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 @@
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 50953d8..d2dfdf2 100755
--- a/plat/rockchip/rk3399/drivers/pmu/pmu.c
+++ b/plat/rockchip/rk3399/drivers/pmu/pmu.c
@@ -874,6 +874,37 @@
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 @@
disable_dvfs_plls();
disable_pwms();
disable_nodvfs_plls();
+ suspend_gpio();
return 0;
}
@@ -937,6 +969,8 @@
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 @@
{
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 @@
{
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) {
/*