Attention is currently required from: Martin Roth, Patrick Rudolph. Angel Pons has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/52489 )
Change subject: sb/intel/lynxpoint: Add SerialIO UART console support ......................................................................
sb/intel/lynxpoint: Add SerialIO UART console support
Derived from Broadwell and adapted to follow what soc/intel does. Note that SERIALIO_UART_CONSOLE is meant to be selected from the mainboards which expose a SerialIO UART. UART_FOR_CONSOLE also needs to be set in mainboard Kconfig accordingly.
Tested on out-of-tree Compal LA-A992P, SerialIO UART 0 can be used to receive coreboot and SeaBIOS logs.
Change-Id: Ifb3460dd50ed03421a38f03c80f91ae9fd604022 Signed-off-by: Angel Pons th3fanbus@gmail.com --- M src/southbridge/intel/lynxpoint/Kconfig M src/southbridge/intel/lynxpoint/Makefile.inc M src/southbridge/intel/lynxpoint/bootblock.c M src/southbridge/intel/lynxpoint/pch.h M src/southbridge/intel/lynxpoint/serialio.c A src/southbridge/intel/lynxpoint/uart.c A src/southbridge/intel/lynxpoint/uart_init.c 7 files changed, 121 insertions(+), 3 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/89/52489/1
diff --git a/src/southbridge/intel/lynxpoint/Kconfig b/src/southbridge/intel/lynxpoint/Kconfig index a9a2f5b..9a30272 100644 --- a/src/southbridge/intel/lynxpoint/Kconfig +++ b/src/southbridge/intel/lynxpoint/Kconfig @@ -68,4 +68,17 @@ bool default y
+config SERIALIO_UART_CONSOLE + bool + depends on INTEL_LYNXPOINT_LP + default n + select DRIVERS_UART_8250MEM_32 + select FIXED_UART_FOR_CONSOLE + help + Selected by mainboards where SerialIO UARTs can be used to retrieve + coreboot logs. Boards also need to set UART_FOR_CONSOLE accordingly. + +config CONSOLE_UART_BASE_ADDRESS + default 0xd6000000 if SERIALIO_UART_CONSOLE + endif diff --git a/src/southbridge/intel/lynxpoint/Makefile.inc b/src/southbridge/intel/lynxpoint/Makefile.inc index f980a65..f9190db 100644 --- a/src/southbridge/intel/lynxpoint/Makefile.inc +++ b/src/southbridge/intel/lynxpoint/Makefile.inc @@ -41,6 +41,10 @@ romstage-y += lp_gpio.c ramstage-y += lp_gpio.c smm-y += lp_gpio.c +bootblock-$(CONFIG_SERIALIO_UART_CONSOLE) += uart_init.c +bootblock-$(CONFIG_SERIALIO_UART_CONSOLE) += iobp.c +all-$(CONFIG_SERIALIO_UART_CONSOLE) += uart.c +smm-$(CONFIG_SERIALIO_UART_CONSOLE) += uart.c endif
verstage-$(CONFIG_VBOOT_SEPARATE_VERSTAGE) += pmutil.c diff --git a/src/southbridge/intel/lynxpoint/bootblock.c b/src/southbridge/intel/lynxpoint/bootblock.c index c063bfb..495871c 100644 --- a/src/southbridge/intel/lynxpoint/bootblock.c +++ b/src/southbridge/intel/lynxpoint/bootblock.c @@ -51,4 +51,7 @@
pch_enable_lpc(); mainboard_config_superio(); + + if (CONFIG(SERIALIO_UART_CONSOLE)) + uart_bootblock_init(); } diff --git a/src/southbridge/intel/lynxpoint/pch.h b/src/southbridge/intel/lynxpoint/pch.h index 955eb72..081e475 100644 --- a/src/southbridge/intel/lynxpoint/pch.h +++ b/src/southbridge/intel/lynxpoint/pch.h @@ -165,6 +165,7 @@ void enable_usb_bar(void); void early_pch_init(void); void pch_enable_lpc(void); +void uart_bootblock_init(void); void mainboard_config_superio(void); void mainboard_config_rcba(void);
@@ -370,6 +371,9 @@
#define SIO_REG_PPR_CLOCK 0x800 #define SIO_REG_PPR_CLOCK_EN (1 << 0) +#define SIO_REG_PPR_CLOCK_UPDATE (1 << 31) +#define SIO_REG_PPR_CLOCK_M_DIV 0x25a +#define SIO_REG_PPR_CLOCK_N_DIV 0x7fff #define SIO_REG_PPR_RST 0x804 #define SIO_REG_PPR_RST_ASSERT 0x3 #define SIO_REG_PPR_GEN 0x808 diff --git a/src/southbridge/intel/lynxpoint/serialio.c b/src/southbridge/intel/lynxpoint/serialio.c index 05263fe..34f8c78 100644 --- a/src/southbridge/intel/lynxpoint/serialio.c +++ b/src/southbridge/intel/lynxpoint/serialio.c @@ -8,6 +8,7 @@ #include <device/pci.h> #include <device/pci_ids.h> #include <soc/nvs.h> +#include <types.h> #include "chip.h" #include "iobp.h" #include "pch.h" @@ -20,6 +21,19 @@ write32(res2mmio(bar0, SIO_REG_PPR_CLOCK, 0), reg32); }
+static bool serialio_uart_is_debug(struct device *dev) +{ + if (CONFIG(SERIALIO_UART_CONSOLE)) { + switch (dev->path.pci.devfn) { + case PCH_DEVFN_UART0: + return CONFIG_UART_FOR_CONSOLE == 0; + case PCH_DEVFN_UART1: + return CONFIG_UART_FOR_CONSOLE == 1; + } + } + return 0; +} + /* Put Serial IO D21:F0-F6 device into desired mode. */ static void serialio_d21_mode(int sio_index, int int_pin, int acpi_mode) { @@ -197,13 +211,15 @@ break; case PCH_DEVFN_UART0: /* UART0 */ sio_index = SIO_ID_UART0; - serialio_d21_ltr(bar0); + if (!serialio_uart_is_debug(dev)) + serialio_d21_ltr(bar0); serialio_d21_mode(sio_index, SIO_PIN_INTD, config->sio_acpi_mode); break; case PCH_DEVFN_UART1: /* UART1 */ sio_index = SIO_ID_UART1; - serialio_d21_ltr(bar0); + if (!serialio_uart_is_debug(dev)) + serialio_d21_ltr(bar0); serialio_d21_mode(sio_index, SIO_PIN_INTD, config->sio_acpi_mode); break; @@ -221,8 +237,21 @@ update_bars(sio_index, (u32)bar0->base, (u32)bar1->base); }
+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 = { - .read_resources = pci_dev_read_resources, + .read_resources = serialio_read_resources, .set_resources = pci_dev_set_resources, .enable_resources = pci_dev_enable_resources, .init = serialio_init, diff --git a/src/southbridge/intel/lynxpoint/uart.c b/src/southbridge/intel/lynxpoint/uart.c new file mode 100644 index 0000000..95b286e --- /dev/null +++ b/src/southbridge/intel/lynxpoint/uart.c @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <console/uart.h> +#include <types.h> + +uintptr_t uart_platform_base(unsigned int idx) +{ + if (idx == CONFIG_UART_FOR_CONSOLE) + return CONFIG_CONSOLE_UART_BASE_ADDRESS; + + return 0; +} diff --git a/src/southbridge/intel/lynxpoint/uart_init.c b/src/southbridge/intel/lynxpoint/uart_init.c new file mode 100644 index 0000000..b61d977 --- /dev/null +++ b/src/southbridge/intel/lynxpoint/uart_init.c @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <arch/io.h> +#include <arch/mmio.h> +#include <assert.h> +#include <console/uart.h> +#include <device/pci_def.h> +#include <device/pci_ops.h> +#include <southbridge/intel/lynxpoint/iobp.h> +#include <southbridge/intel/lynxpoint/lp_gpio.h> +#include <southbridge/intel/lynxpoint/pch.h> +#include <types.h> + +static pci_devfn_t get_uart_pci_device(void) +{ + switch (CONFIG_UART_FOR_CONSOLE) { + case 0: return PCI_DEV(0, 0x15, 5); + case 1: return PCI_DEV(0, 0x15, 6); + default: return dead_code_t(pci_devfn_t); + } +} + +void uart_bootblock_init(void) +{ + const pci_devfn_t dev = get_uart_pci_device(); + + /* Program IOBP GPIODF */ + pch_iobp_update(SIO_IOBP_GPIODF, ~0x131f, 0x131f); + + /* Program IOBP CB000180h[5:0] = 111111b (undefined register) */ + pch_iobp_update(0xcb000180, ~0x0000003f, 0x0000003f); + + /* Set and enable MMIO BAR */ + pci_write_config32(dev, PCI_BASE_ADDRESS_0, CONFIG_CONSOLE_UART_BASE_ADDRESS); + pci_or_config16(dev, PCI_COMMAND, PCI_COMMAND_MEMORY); + + void *const bar = (void *)(uintptr_t)CONFIG_CONSOLE_UART_BASE_ADDRESS; + + /* Initialize LTR */ + clrbits32(bar + SIO_REG_PPR_GEN, SIO_REG_PPR_GEN_LTR_MODE_MASK); + clrbits32(bar + SIO_REG_PPR_RST, SIO_REG_PPR_RST_ASSERT); + + /* Take UART out of reset */ + setbits32(bar + SIO_REG_PPR_RST, SIO_REG_PPR_RST_ASSERT); + + /* Set M and N divisor inputs and enable clock */ + uint32_t ppr_clock = 0; + ppr_clock |= SIO_REG_PPR_CLOCK_EN; + ppr_clock |= SIO_REG_PPR_CLOCK_UPDATE; + ppr_clock |= SIO_REG_PPR_CLOCK_N_DIV << 16; + ppr_clock |= SIO_REG_PPR_CLOCK_M_DIV << 1; + write32(bar + SIO_REG_PPR_CLOCK, ppr_clock); +}