diff options
Diffstat (limited to 'src/soc/intel/baytrail/southcluster.c')
-rw-r--r-- | src/soc/intel/baytrail/southcluster.c | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/src/soc/intel/baytrail/southcluster.c b/src/soc/intel/baytrail/southcluster.c index 49e4c91a13..261c95ae1d 100644 --- a/src/soc/intel/baytrail/southcluster.c +++ b/src/soc/intel/baytrail/southcluster.c @@ -20,6 +20,7 @@ #include <stdint.h> #include <arch/io.h> +#include <arch/acpi.h> #include <bootstate.h> #include <cbmem.h> #include <console/console.h> @@ -29,6 +30,7 @@ #include <device/pci_ids.h> #include <pc80/mc146818rtc.h> #include <romstage_handoff.h> +#include <drivers/uart/uart8250reg.h> #include <baytrail/iomap.h> #include <baytrail/irq.h> @@ -144,6 +146,42 @@ static void sc_rtc_init(void) rtc_init(rtc_fail); } +/* + * The UART hardware loses power while in suspend. Because of this the kernel + * can hang because it doesn't re-initialize serial ports it is using for + * consoles at resume time. The following function configures the UART + * if the hardware is enabled though it may not be the correct baud rate + * or configuration. This is definitely a hack, but it helps the kernel + * along. + */ +static void com1_configure_resume(device_t dev) +{ + const uint16_t port = 0x3f8; + + /* Is the UART I/O port eanbled? */ + if (!(pci_read_config32(dev, UART_CONT) & 1)) + return; + + /* Disable interrupts */ + outb(0x0, port + UART8250_IER); + + /* Enable FIFOs */ + outb(UART8250_FCR_FIFO_EN, port + UART8250_FCR); + + /* assert DTR and RTS so the other end is happy */ + outb(UART8250_MCR_DTR | UART8250_MCR_RTS, port + UART8250_MCR); + + /* DLAB on */ + outb(UART8250_LCR_DLAB | 3, port + UART8250_LCR); + + /* Set Baud Rate Divisor. 1 ==> 115200 Baud */ + outb(1, port + UART8250_DLL); + outb(0, port + UART8250_DLM); + + /* Set to 3 for 8N1 */ + outb(3, port + UART8250_LCR); +} + static void sc_init(device_t dev) { int i; @@ -176,6 +214,9 @@ static void sc_init(device_t dev) write32(gen_pmcon1, read32(gen_pmcon1) & ~DIS_SLP_X_STRCH_SUS_UP); } + + if (acpi_slp_type == 3) + com1_configure_resume(dev); } /* |