baytrail: workaround kernel using serial console on resume
The UART hardware loses power while the system is suspended. However,
the kernel currently doesn't handle the notion of the serial port losing
its settings through a suspend. Because of this using a serial console
in the kernel can cause hangs. Work around this by always initializing
the serial port (if enabled) to 115200 8n1. Though the configuration
may differ it should at least keep hangs and crashes from occuring
with uninitialized serial port.
BUG=chrome-os-partner:25353
BRANCH=baytrail
TEST=Suspend/resume cycles successfully completed with and without
'echo N > /sys/module/printk/parameters/console_suspend'. With
a serial console enabled in the kernel. Also confirmed that
there are not any hiccups when coreboot has its console enabled.
Change-Id: I6fd8a0ae261318769d8f677ef04320a0d6ff1b6d
Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/188011
Reviewed-by: Duncan Laurie <dlaurie@chromium.org>
This commit is contained in:
parent
cee89d7c83
commit
b0da3bdb5b
1 changed files with 41 additions and 0 deletions
|
|
@ -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 <uart8250.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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue