soc/intel/broadwell: Re-do SerialIO UART console support

Use the same code from Lynx Point on Broadwell, and adjust as needed.
Also add a config file to ensure the code gets build-tested.

Tested on out-of-tree Compal LA-A992P (Haswell ULT), UART 0 works.

Change-Id: I527024098738700d5fbaf3e27cf4db331a0322bd
Signed-off-by: Angel Pons <th3fanbus@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/37553
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
This commit is contained in:
Angel Pons 2021-04-19 17:12:42 +02:00
parent e42ce6bb49
commit 07baa7a7f0
7 changed files with 53 additions and 109 deletions

View File

@ -0,0 +1,5 @@
# Configuration used to build-test Wildcat Point SerialIO UART console code.
CONFIG_VENDOR_GOOGLE=y
CONFIG_BOARD_GOOGLE_GUADO=y
CONFIG_SERIALIO_UART_CONSOLE=y
# CONFIG_DRIVERS_UART_8250IO is not set

View File

@ -153,20 +153,16 @@ config RO_REGION_ONLY
endif # HAVE_MRC endif # HAVE_MRC
config INTEL_PCH_UART_CONSOLE config SERIALIO_UART_CONSOLE
bool "Use Serial IO UART for console" bool
default n default n
select DRIVERS_UART_8250MEM select DRIVERS_UART_8250MEM_32
help
Selected by mainboards where SerialIO UARTs can be used to retrieve
coreboot logs. Boards also need to set UART_FOR_CONSOLE accordingly.
config INTEL_PCH_UART_CONSOLE_NUMBER config CONSOLE_UART_BASE_ADDRESS
hex "Serial IO UART number to use for console" default 0xd6000000 if SERIALIO_UART_CONSOLE
default 0x0
depends on INTEL_PCH_UART_CONSOLE
config TTYS0_BASE
hex
default 0xd6000000
depends on INTEL_PCH_UART_CONSOLE
config EHCI_BAR config EHCI_BAR
hex hex

View File

@ -30,7 +30,6 @@ ramstage-y += serialio.c
ramstage-y += ../../../../southbridge/intel/lynxpoint/smbus.c ramstage-y += ../../../../southbridge/intel/lynxpoint/smbus.c
ramstage-y += smi.c ramstage-y += smi.c
smm-y += smihandler.c smm-y += smihandler.c
romstage-$(CONFIG_DRIVERS_UART_8250MEM) += uart.c
bootblock-y += usb_debug.c bootblock-y += usb_debug.c
romstage-y += usb_debug.c romstage-y += usb_debug.c
ramstage-y += usb_debug.c ramstage-y += usb_debug.c
@ -38,4 +37,9 @@ ramstage-y += usb_ehci.c
ramstage-y += usb_xhci.c ramstage-y += usb_xhci.c
smm-y += usb_xhci.c smm-y += usb_xhci.c
bootblock-$(CONFIG_SERIALIO_UART_CONSOLE) += ../../../../southbridge/intel/lynxpoint/iobp.c
bootblock-$(CONFIG_SERIALIO_UART_CONSOLE) += ../../../../southbridge/intel/lynxpoint/uart_init.c
all-$(CONFIG_SERIALIO_UART_CONSOLE) += ../../../../southbridge/intel/lynxpoint/uart.c
smm-$(CONFIG_SERIALIO_UART_CONSOLE) += ../../../../southbridge/intel/lynxpoint/uart.c
ramstage-srcs += src/mainboard/$(MAINBOARDDIR)/hda_verb.c ramstage-srcs += src/mainboard/$(MAINBOARDDIR)/hda_verb.c

View File

@ -105,6 +105,9 @@ static void pch_early_lpc(void)
RCBA32_OR(FD, PCH_DISABLE_ALWAYS); RCBA32_OR(FD, PCH_DISABLE_ALWAYS);
} }
/* Defined in Lynx Point code */
void uart_bootblock_init(void);
void bootblock_early_southbridge_init(void) void bootblock_early_southbridge_init(void)
{ {
map_rcba(); map_rcba();
@ -112,4 +115,7 @@ void bootblock_early_southbridge_init(void)
enable_port80_on_lpc(); enable_port80_on_lpc();
set_spi_speed(); set_spi_speed();
pch_early_lpc(); pch_early_lpc();
if (CONFIG(SERIALIO_UART_CONSOLE))
uart_bootblock_init();
} }

View File

@ -604,11 +604,12 @@ static unsigned long broadwell_write_acpi_tables(const struct device *device,
unsigned long current, unsigned long current,
struct acpi_rsdp *rsdp) struct acpi_rsdp *rsdp)
{ {
if (CONFIG(INTEL_PCH_UART_CONSOLE)) if (CONFIG(SERIALIO_UART_CONSOLE)) {
current = acpi_write_dbg2_pci_uart(rsdp, current, current = acpi_write_dbg2_pci_uart(rsdp, current,
(CONFIG_INTEL_PCH_UART_CONSOLE_NUMBER == 1) ? (CONFIG_UART_FOR_CONSOLE == 1) ?
PCH_DEV_UART1 : PCH_DEV_UART0, PCH_DEV_UART1 : PCH_DEV_UART0,
ACPI_ACCESS_SIZE_BYTE_ACCESS); ACPI_ACCESS_SIZE_DWORD_ACCESS);
}
return acpi_write_hpet(device, current, rsdp); return acpi_write_hpet(device, current, rsdp);
} }

View File

@ -15,6 +15,7 @@
#include <soc/serialio.h> #include <soc/serialio.h>
#include <soc/intel/broadwell/pch/chip.h> #include <soc/intel/broadwell/pch/chip.h>
#include <southbridge/intel/lynxpoint/iobp.h> #include <southbridge/intel/lynxpoint/iobp.h>
#include <types.h>
/* Set D3Hot Power State in ACPI mode */ /* Set D3Hot Power State in ACPI mode */
static void serialio_enable_d3hot(struct resource *res) static void serialio_enable_d3hot(struct resource *res)
@ -24,17 +25,17 @@ static void serialio_enable_d3hot(struct resource *res)
write32(res2mmio(res, PCH_PCS, 0), reg32); write32(res2mmio(res, PCH_PCS, 0), reg32);
} }
static int serialio_uart_is_debug(struct device *dev) static bool serialio_uart_is_debug(struct device *dev)
{ {
#if CONFIG(INTEL_PCH_UART_CONSOLE) if (CONFIG(SERIALIO_UART_CONSOLE)) {
switch (dev->path.pci.devfn) { switch (dev->path.pci.devfn) {
case PCH_DEVFN_UART0: /* UART0 */ case PCH_DEVFN_UART0:
return !!(CONFIG_INTEL_PCH_UART_CONSOLE_NUMBER == 0); return CONFIG_UART_FOR_CONSOLE == 0;
case PCH_DEVFN_UART1: /* UART1 */ case PCH_DEVFN_UART1:
return !!(CONFIG_INTEL_PCH_UART_CONSOLE_NUMBER == 1); return CONFIG_UART_FOR_CONSOLE == 1;
} }
#endif }
return 0; return false;
} }
/* Enable clock in PCI mode */ /* Enable clock in PCI mode */
@ -239,8 +240,8 @@ static void serialio_init(struct device *dev)
dev_nvs->bar0[sio_index] = (u32)bar0->base; dev_nvs->bar0[sio_index] = (u32)bar0->base;
dev_nvs->bar1[sio_index] = (u32)bar1->base; dev_nvs->bar1[sio_index] = (u32)bar1->base;
if (!serialio_uart_is_debug(dev)) {
/* Do not enable UART if it is used as debug port */ /* Do not enable UART if it is used as debug port */
if (!serialio_uart_is_debug(dev))
dev_nvs->enable[sio_index] = 1; dev_nvs->enable[sio_index] = 1;
/* Put device in D3hot state via BAR1 */ /* Put device in D3hot state via BAR1 */
@ -248,24 +249,24 @@ static void serialio_init(struct device *dev)
serialio_enable_d3hot(bar1); /* all but SDMA */ serialio_enable_d3hot(bar1); /* all but SDMA */
} }
} }
static void serialio_set_resources(struct device *dev)
{
pci_dev_set_resources(dev);
#if CONFIG(INTEL_PCH_UART_CONSOLE)
/* Update UART base address if used for debug */
if (serialio_uart_is_debug(dev)) {
struct resource *res = find_resource(dev, PCI_BASE_ADDRESS_0);
if (res)
uartmem_setbaseaddr(res->base);
} }
#endif
static void serialio_read_resources(struct device *dev)
{
pci_dev_read_resources(dev);
/* Set the configured UART base address for the debug port */
if (CONFIG(SERIALIO_UART_CONSOLE) && serialio_uart_is_debug(dev)) {
struct resource *res = find_resource(dev, PCI_BASE_ADDRESS_0);
res->base = CONFIG_CONSOLE_UART_BASE_ADDRESS;
res->size = 0x1000;
res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
}
} }
static struct device_operations device_ops = { static struct device_operations device_ops = {
.read_resources = &pci_dev_read_resources, .read_resources = &serialio_read_resources,
.set_resources = &serialio_set_resources, .set_resources = &pci_dev_set_resources,
.enable_resources = &pci_dev_enable_resources, .enable_resources = &pci_dev_enable_resources,
.init = &serialio_init, .init = &serialio_init,
.ops_pci = &pci_dev_ops_pci, .ops_pci = &pci_dev_ops_pci,

View File

@ -1,69 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <device/pci_def.h>
#include <reg_script.h>
#include <stdint.h>
#include <uart8250.h>
#include <soc/iobp.h>
#include <soc/serialio.h>
const struct reg_script uart_init[] = {
/* Set MMIO BAR */
REG_PCI_WRITE32(PCI_BASE_ADDRESS_0, CONFIG_TTYS0_BASE),
/* Enable Memory access and Bus Master */
REG_PCI_OR32(PCI_COMMAND, PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER),
/* Initialize LTR */
REG_MMIO_RMW32(CONFIG_TTYS0_BASE + SIO_REG_PPR_GEN,
~SIO_REG_PPR_GEN_LTR_MODE_MASK, 0),
REG_MMIO_RMW32(CONFIG_TTYS0_BASE + SIO_REG_PPR_RST,
~(SIO_REG_PPR_RST_ASSERT), 0),
/* Take UART out of reset */
REG_MMIO_OR32(CONFIG_TTYS0_BASE + SIO_REG_PPR_RST,
SIO_REG_PPR_RST_ASSERT),
/* Set M and N divisor inputs and enable clock */
REG_MMIO_WRITE32(CONFIG_TTYS0_BASE + SIO_REG_PPR_CLOCK,
SIO_REG_PPR_CLOCK_EN | SIO_REG_PPR_CLOCK_UPDATE |
(SIO_REG_PPR_CLOCK_N_DIV << 16) |
(SIO_REG_PPR_CLOCK_M_DIV << 1)),
REG_SCRIPT_END
};
void pch_uart_init(void)
{
/* Program IOBP CB000154h[12,9:8,4:0] = 1001100011111b */
u32 gpiodf = 0x131f;
#if defined(__SIMPLE_DEVICE__)
pci_devfn_t dev;
#else
struct device *dev;
#endif
/* Put UART in byte access mode for 16550 compatibility */
switch (CONFIG_INTEL_PCH_UART_CONSOLE_NUMBER) {
case 0:
dev = PCH_DEV_UART0;
gpiodf |= SIO_IOBP_GPIODF_UART0_BYTE_ACCESS;
break;
case 1:
dev = PCH_DEV_UART1;
gpiodf |= SIO_IOBP_GPIODF_UART1_BYTE_ACCESS;
break;
default:
return;
}
/* Program IOBP GPIODF */
pch_iobp_update(SIO_IOBP_GPIODF, ~gpiodf, gpiodf);
/* Program IOBP CB000180h[5:0] = 111111b (undefined register) */
pch_iobp_update(0xcb000180, ~0x0000003f, 0x0000003f);
/* Initialize chipset uart interface */
reg_script_run_on_dev(dev, uart_init);
/*
* Perform standard UART initialization
* Divisor 1 is 115200 BAUD
*/
uart8250_mem_init(CONFIG_TTYS0_BASE, 1);
}