diff options
-rw-r--r-- | board/chromebook-x86/chromeos/power_management.c | 89 | ||||
-rw-r--r-- | board/chromebook-x86/coreboot/coreboot.c | 18 | ||||
-rw-r--r-- | drivers/video/cfb_console.c | 8 | ||||
-rw-r--r-- | include/video.h | 1 | ||||
-rw-r--r-- | lib/vbexport/display.c | 7 |
5 files changed, 114 insertions, 9 deletions
diff --git a/board/chromebook-x86/chromeos/power_management.c b/board/chromebook-x86/chromeos/power_management.c index 8510c8e7b5..068eb18dea 100644 --- a/board/chromebook-x86/chromeos/power_management.c +++ b/board/chromebook-x86/chromeos/power_management.c @@ -12,6 +12,25 @@ #include <chromeos/power_management.h> #include <common.h> +#include <asm/io.h> +#include <pci.h> + +#define PM1_STS 0x00 +#define PWRBTN_STS (1 << 8) +#define PM1_EN 0x02 +#define PM1_CNT 0x04 +#define SLP_EN (1 << 13) +#define SLP_TYP (7 << 10) +#define SLP_TYP_S0 (0 << 10) +#define SLP_TYP_S1 (1 << 10) +#define SLP_TYP_S3 (5 << 10) +#define SLP_TYP_S4 (6 << 10) +#define SLP_TYP_S5 (7 << 10) +#define GPE0_EN 0x2c + +#define RST_CNT 0xcf9 +#define SYS_RST (1 << 1) +#define RST_CPU (1 << 2) int is_processor_reset(void) { @@ -19,14 +38,76 @@ int is_processor_reset(void) return 1; } -/* This function never returns */ +/* Do a hard reset through the chipset's reset control register. This + * register is available on all x86 systems (at least those built in + * the last 10ys) + * + * This function never returns. + */ void cold_reboot(void) { - printf("cold_reboot used but not implemented.\n"); + printf("Rebooting...\n"); + outb(SYS_RST, RST_CNT); + outb(SYS_RST | RST_CPU, RST_CNT); } -/* This function never returns */ +/* Power down the machine by using the power management sleep control + * of the chipset. This will currently only work on Intel chipsets. + * However, adapting it to new chipsets is fairly simple. You will + * have to find the IO address of the power management register block + * in your southbridge, and look up the appropriate SLP_TYP_S5 value + * from your southbridge's data sheet. + * + * This function never returns. + */ void power_off(void) { - printf("power_off used but not implemented.\n"); + u16 id, pmbase; + u32 reg32; + + /* Make sure this is an Intel chipset with the + * LPC device hard coded at 0:1f.0 + */ + pci_read_config_word(PCI_BDF(0, 0x1f, 0), 0x00, &id); + if(id != 0x8086) { + printf("Power off is not implemented for this chipset. " + "Halting the CPU.\n"); + for (;;) + asm("hlt"); + } + + /* Find the base address of the powermanagement registers */ + pci_read_config_word(PCI_BDF(0, 0x1f, 0), 0x40, &pmbase); + pmbase &= 0xfffe; + + /* Mask interrupts or system might stay in a coma + * (not executing code anymore, but not powered off either) + */ + asm("cli"); + + /* Avoid any GPI waking the system from S5 + * or the system might stay in a coma + */ + outl(0x00000000, pmbase + GPE0_EN); + + /* Clear Power Button Status */ + outw(PWRBTN_STS, pmbase + PM1_STS); + + /* PMBASE + 4, Bit 10-12, Sleeping Type, + * set to 111 -> S5, soft_off */ + + reg32 = inl(pmbase + PM1_CNT); + + /* Set Sleeping Type to S5 (poweroff) */ + reg32 &= ~(SLP_EN | SLP_TYP); + reg32 |= SLP_TYP_S5; + outl(reg32, pmbase + PM1_CNT); + + /* Now set the Sleep Enable bit */ + reg32 |= SLP_EN; + outl(reg32, pmbase + PM1_CNT); + + for (;;) + asm("hlt"); } + diff --git a/board/chromebook-x86/coreboot/coreboot.c b/board/chromebook-x86/coreboot/coreboot.c index 2ee0d86598..e660ddbca4 100644 --- a/board/chromebook-x86/coreboot/coreboot.c +++ b/board/chromebook-x86/coreboot/coreboot.c @@ -31,6 +31,7 @@ #include <netdev.h> #include <asm/ic/coreboot/tables.h> #include <asm/ic/coreboot/sysinfo.h> +#include <chromeos/power_management.h> #ifdef CONFIG_HW_WATCHDOG #include <watchdog.h> @@ -128,3 +129,20 @@ void hw_watchdog_reset(void) { } #endif + +int do_coldboot(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) +{ + cold_reboot(); + return (0); +} + +U_BOOT_CMD(coldboot, 1, 1, do_coldboot, "Initiate a cold reboot.", ""); + +int do_poweroff(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) +{ + power_off(); + return (0); +} + +U_BOOT_CMD(poweroff, 1, 1, do_poweroff, "Switch off power", ""); + diff --git a/drivers/video/cfb_console.c b/drivers/video/cfb_console.c index 6b0b766321..d79fa1efb1 100644 --- a/drivers/video/cfb_console.c +++ b/drivers/video/cfb_console.c @@ -1709,3 +1709,11 @@ int video_get_screen_columns (void) return CONSOLE_COLS; } +int video_clear(void) +{ + memsetl(video_fb_address, + (VIDEO_VISIBLE_ROWS * VIDEO_LINE_LEN) / sizeof(int), 0); + + return 0; +} + diff --git a/include/video.h b/include/video.h index 8b3799b0b0..a24035368c 100644 --- a/include/video.h +++ b/include/video.h @@ -21,5 +21,6 @@ int video_get_screen_rows (void); int video_get_screen_columns (void); int video_get_pixel_width (void); int video_get_pixel_height(void); +int video_clear(void); #endif diff --git a/lib/vbexport/display.c b/lib/vbexport/display.c index cdf8862783..80f45128d9 100644 --- a/lib/vbexport/display.c +++ b/lib/vbexport/display.c @@ -55,6 +55,7 @@ static struct display_callbacks display_callbacks_ = { .dc_position_cursor = video_position_cursor, .dc_puts = video_puts, .dc_display_bitmap = video_display_bitmap, + .dc_display_clear = video_clear #endif }; @@ -191,9 +192,5 @@ VbError_t VbExDisplayDebugInfo(const char *info_str) /* this function is not technically part of the vboot interface */ int display_clear(void) { - if (display_callbacks_.dc_display_clear) - return display_callbacks_.dc_display_clear(); - - printf ("%s: not implemented!\n", __FUNCTION__); - return -1; + return display_callbacks_.dc_display_clear(); } |