rockchip: support disable/enable specific gpio when suspend/resume
authorCaesar Wang <[email protected]>
Fri, 9 Sep 2016 18:43:15 +0000 (02:43 +0800)
committerCaesar Wang <[email protected]>
Fri, 9 Sep 2016 20:06:44 +0000 (04:06 +0800)
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
plat/rockchip/common/include/plat_private.h
plat/rockchip/common/params_setup.c
plat/rockchip/rk3399/drivers/pmu/pmu.c

index cad453535ddf1d1e81b692e619518d67e3c91ea6..7e1f275f74beab71f167e7a5a9704f72dbdc0523 100644 (file)
  * 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 {
index b9b634e7bcb62c75c6e52895d11673a3db0d6ef1..4f87a7602029233284ce4b5d44ac738f7c3a4273 100644 (file)
@@ -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[];
index 2a49556f490a2b89781e714aa92cb55948da086c..351d2136156ec485474f29bdf1eaed52c82f9a04 100644 (file)
 #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;
        }
 }
index 50953d831294b41a0f69655c44c9b8ee8769ee56..d2dfdf20e6af3f7a3790cb49dd37e82cb7c04a4f 100755 (executable)
@@ -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) {
                /*