rk29sdk: better support power on/off
author黄涛 <huangtao@rock-chips.com>
Thu, 7 Apr 2011 04:18:26 +0000 (12:18 +0800)
committer黄涛 <huangtao@rock-chips.com>
Thu, 7 Apr 2011 04:19:16 +0000 (12:19 +0800)
arch/arm/mach-rk29/Makefile
arch/arm/mach-rk29/board-rk29-ddr3sdk.c
arch/arm/mach-rk29/board-rk29sdk-power.c [new file with mode: 0644]
arch/arm/mach-rk29/board-rk29sdk.c
arch/arm/mach-rk29/include/mach/board.h

index 398be7942d474b3681903f2a564bbe64c931d3cc..e514af5e2323021360862ea1156dc4b43402e9f1 100644 (file)
@@ -8,8 +8,8 @@ obj-$(CONFIG_USB_GADGET) += usb_detect.o
 obj-$(CONFIG_PM) += pm.o
 obj-$(CONFIG_CPU_FREQ) += cpufreq.o
 obj-$(CONFIG_RK29_VPU) += vpu.o vpu_mem.o
-obj-$(CONFIG_MACH_RK29SDK) += board-rk29sdk.o board-rk29sdk-key.o board-rk29sdk-rfkill.o
-obj-$(CONFIG_MACH_RK29SDK_DDR3) += board-rk29-ddr3sdk.o board-rk29sdk-key.o board-rk29sdk-rfkill.o
+obj-$(CONFIG_MACH_RK29SDK) += board-rk29sdk.o board-rk29sdk-key.o board-rk29sdk-rfkill.o board-rk29sdk-power.o
+obj-$(CONFIG_MACH_RK29SDK_DDR3) += board-rk29-ddr3sdk.o board-rk29sdk-key.o board-rk29sdk-rfkill.o board-rk29sdk-power.o
 obj-$(CONFIG_MACH_RK29WINACCORD) += board-rk29-winaccord.o board-rk29sdk-key.o
 obj-$(CONFIG_MACH_RK29_AIGO) += board-rk29-aigo.o board-rk29aigo-key.o board-rk29sdk-rfkill.o
 obj-$(CONFIG_MACH_RK29_MALATA) += board-malata.o board-rk29malata-key.o board-rk29sdk-rfkill.o
index e22a6befc51a7db290e7ef6bb4de4c869811f8c7..72a5f4b868ea27f205528b5b20221b9541ba3f74 100755 (executable)
@@ -1874,22 +1874,11 @@ static void __init machine_rk29_init_irq(void)
        rk29_gpio_init();
 }
 
-#define POWER_ON_PIN RK29_PIN4_PA4
-static void rk29_pm_power_off(void)
-{
-       printk(KERN_ERR "rk29_pm_power_off start...\n");
-       gpio_direction_output(POWER_ON_PIN, GPIO_LOW);
-       while (1);
-}
-
 static void __init machine_rk29_board_init(void)
 {
        rk29_board_iomux_init();
 
-       gpio_request(POWER_ON_PIN,"poweronpin");
-       gpio_set_value(POWER_ON_PIN, GPIO_HIGH);
-       gpio_direction_output(POWER_ON_PIN, GPIO_HIGH);
-       pm_power_off = rk29_pm_power_off;
+       board_power_init();
 
                platform_add_devices(devices, ARRAY_SIZE(devices));
 #ifdef CONFIG_I2C0_RK29
diff --git a/arch/arm/mach-rk29/board-rk29sdk-power.c b/arch/arm/mach-rk29/board-rk29sdk-power.c
new file mode 100644 (file)
index 0000000..e63b0d9
--- /dev/null
@@ -0,0 +1,67 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/pm.h>
+
+#include <mach/rk29_iomap.h>
+#include <mach/gpio.h>
+#include <mach/cru.h>
+
+#define POWER_ON_PIN   RK29_PIN4_PA4
+#define PLAY_ON_PIN    RK29_PIN6_PA7
+
+static void rk29_pm_power_off(void)
+{
+       int count = 0;
+
+       local_irq_disable();
+       local_fiq_disable();
+
+       printk(KERN_ERR "rk29_pm_power_off start...\n");
+
+       /* arm enter slow mode */
+       cru_writel((cru_readl(CRU_MODE_CON) & ~CRU_CPU_MODE_MASK) | CRU_CPU_MODE_SLOW, CRU_MODE_CON);
+       LOOP(LOOPS_PER_USEC);
+
+       while (1) {
+               /* shut down the power by GPIO. */
+               if (gpio_get_value(POWER_ON_PIN) == GPIO_HIGH) {
+                       printk("POWER_ON_PIN is high\n");
+                       gpio_set_value(POWER_ON_PIN, GPIO_LOW);
+               }
+
+               LOOP(5 * LOOPS_PER_MSEC);
+
+               /* only normal power off can restart system safely */
+               if (system_state != SYSTEM_POWER_OFF)
+                       continue;
+
+               if (gpio_get_value(PLAY_ON_PIN) != GPIO_HIGH) {
+                       if (!count)
+                               printk("PLAY_ON_PIN is low\n");
+                       if (50 == count) /* break if keep low about 250ms */
+                               break;
+                       count++;
+               } else {
+                       count = 0;
+               }
+       }
+
+       printk("system reboot\n");
+       gpio_set_value(POWER_ON_PIN, GPIO_HIGH);
+       system_state = SYSTEM_RESTART;
+       arm_pm_restart(0, NULL);
+
+       while (1);
+}
+
+int __init board_power_init(void)
+{
+       gpio_request(POWER_ON_PIN, "poweronpin");
+       gpio_set_value(POWER_ON_PIN, GPIO_HIGH);
+       gpio_direction_output(POWER_ON_PIN, GPIO_HIGH);
+       pm_power_off = rk29_pm_power_off;
+
+       return 0;
+}
+
index 2bbcaf239fc3e75b357b4921ff64fe91250d5c88..ba2f881dab3f1d7e2f20abb5c6d8b909ca70d097 100755 (executable)
@@ -1896,22 +1896,11 @@ static void __init machine_rk29_init_irq(void)
        rk29_gpio_init();
 }
 
-#define POWER_ON_PIN RK29_PIN4_PA4
-static void rk29_pm_power_off(void)
-{
-       printk(KERN_ERR "rk29_pm_power_off start...\n");
-       gpio_direction_output(POWER_ON_PIN, GPIO_LOW);
-       while (1);
-}
-
 static void __init machine_rk29_board_init(void)
 {
        rk29_board_iomux_init();
 
-       gpio_request(POWER_ON_PIN,"poweronpin");
-       gpio_set_value(POWER_ON_PIN, GPIO_HIGH);
-       gpio_direction_output(POWER_ON_PIN, GPIO_HIGH);
-       pm_power_off = rk29_pm_power_off;
+       board_power_init();
 
                platform_add_devices(devices, ARRAY_SIZE(devices));
 #ifdef CONFIG_I2C0_RK29
index 8a111c602baac6265a6f131d376725aee89af655..e16ef7a2bd02d02dacaca80bc913a670fb6b60b9 100755 (executable)
@@ -234,6 +234,7 @@ struct tca6424_platform_data {
 void __init rk29_setup_early_printk(void);
 void __init rk29_map_common_io(void);
 void __init rk29_clock_init(void);
+void __init board_power_init(void);
 
 #define BOOT_MODE_NORMAL               0
 #define BOOT_MODE_FACTORY2             1