Index: linux-2.6.16/arch/arm/kernel/apm.c =================================================================== --- linux-2.6.16.orig/arch/arm/kernel/apm.c +++ linux-2.6.16/arch/arm/kernel/apm.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -30,6 +31,21 @@ #include /* apm_power_info */ #include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + /* * The apm_bios device is one of the misc char devices. * This is its minor number. @@ -608,4 +624,64 @@ EXPORT_SYMBOL(apm_queue_event); void pm_do_poweroff(void) { /* FIXME */ + if (!GPIO_is_high(GPIO_BB_WDI2)) { + printk(KERN_DEBUG "got BB_WDI2 signal when power down\n"); + mdelay(1); + cpu_proc_fin(); + clr_GPIO(GPIO_WDI_AP); + + while(1); + } + +#if 0 + unsigned long start = jiffies; + + *(unsigned long *)(phys_to_virt(BPSIG_ADDR)) = NO_FLAG; + do { + if (!GPIO_is_high(GPIO_BB_WDI)) { + printk(KERN_DEBUG "got BB_WDI signal when power down\n"); + cpu_proc_fin(); + *(unsigned long *)(phys_to_virt(BPSIG_ADDR)) = WDI_FLAG; + + pcap_switch_off_usb(); + mdelay(1000); + pcap_switch_on_usb(); + + GPCR(GPIO_BB_RESET) = GPIO_bit(GPIO_BB_RESET); + mdelay(1); + GPSR(GPIO_BB_RESET) = GPIO_bit(GPIO_BB_RESET); + + /* Initialize the watchdog and let it fire */ + OWER = OWER_WME; + OSSR = OSSR_M3; + OSMR3 = OSCR + CLOCK_TICK_RATE/100; /* ... in 10 ms */ + + MDREFR |= MDREFR_SLFRSH; + while(1); + } + + if (!(GPLR(GPIO_BB_WDI2) & GPIO_bit(GPIO_BB_WDI2))) { + printk(KERN_DEBUG "got BB_WDI2 signal when power down\n"); + mdelay(1); + cpu_proc_fin(); + if (user_off_available) { + APM_DPRINTK("enter useroff\n"); + break; + } else { + GPCR(GPIO_WDI_AP) = GPIO_bit(GPIO_WDI_AP); + while(1); + } + } + + if ((jiffies - start) >= POWER_OFF_TIMEOUT) { + printk(KERN_DEBUG "timeout when power down\n"); + mdelay(1); + GPCR(GPIO_WDI_AP) = GPIO_bit(GPIO_WDI_AP); + while(1); + } + } while(1); + + pm_do_useroff(); + printk(KERN_DEBUG "resume from useroff\n"); +#endif }