summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configs/config.google_panther.pch_serialio_uart5
-rw-r--r--src/southbridge/intel/lynxpoint/Kconfig11
-rw-r--r--src/southbridge/intel/lynxpoint/Makefile.inc4
-rw-r--r--src/southbridge/intel/lynxpoint/bootblock.c3
-rw-r--r--src/southbridge/intel/lynxpoint/pch.h4
-rw-r--r--src/southbridge/intel/lynxpoint/serialio.c35
-rw-r--r--src/southbridge/intel/lynxpoint/uart.c12
-rw-r--r--src/southbridge/intel/lynxpoint/uart_init.c54
8 files changed, 125 insertions, 3 deletions
diff --git a/configs/config.google_panther.pch_serialio_uart b/configs/config.google_panther.pch_serialio_uart
new file mode 100644
index 0000000000..5f7f4c7745
--- /dev/null
+++ b/configs/config.google_panther.pch_serialio_uart
@@ -0,0 +1,5 @@
+# Configuration used to build-test Lynx Point SerialIO UART console code.
+CONFIG_VENDOR_GOOGLE=y
+CONFIG_BOARD_GOOGLE_PANTHER=y
+CONFIG_SERIALIO_UART_CONSOLE=y
+# CONFIG_DRIVERS_UART_8250IO is not set
diff --git a/src/southbridge/intel/lynxpoint/Kconfig b/src/southbridge/intel/lynxpoint/Kconfig
index a9a2f5bb9e..fe859f62ed 100644
--- a/src/southbridge/intel/lynxpoint/Kconfig
+++ b/src/southbridge/intel/lynxpoint/Kconfig
@@ -68,4 +68,15 @@ config PCIEXP_AER
bool
default y
+config SERIALIO_UART_CONSOLE
+ bool "Use SerialIO UART for console"
+ depends on INTEL_LYNXPOINT_LP
+ 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 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 2923035e1e..02022d348d 100644
--- a/src/southbridge/intel/lynxpoint/Makefile.inc
+++ b/src/southbridge/intel/lynxpoint/Makefile.inc
@@ -42,6 +42,10 @@ romstage-y += lp_gpio.c
ramstage-y += lp_gpio.c
smm-y += lp_gpio.c
verstage-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-y += pmutil.c
diff --git a/src/southbridge/intel/lynxpoint/bootblock.c b/src/southbridge/intel/lynxpoint/bootblock.c
index c063bfb10a..495871c6d2 100644
--- a/src/southbridge/intel/lynxpoint/bootblock.c
+++ b/src/southbridge/intel/lynxpoint/bootblock.c
@@ -51,4 +51,7 @@ void bootblock_early_southbridge_init(void)
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 7b09d54f18..598c2dc7b2 100644
--- a/src/southbridge/intel/lynxpoint/pch.h
+++ b/src/southbridge/intel/lynxpoint/pch.h
@@ -157,6 +157,7 @@ void acpi_create_serialio_ssdt(acpi_header_t *ssdt);
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);
@@ -372,6 +373,9 @@ void mainboard_config_rcba(void);
#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 05263fec39..34f8c78c6d 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 @@ static void serialio_enable_clock(struct resource *bar0)
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 @@ static void serialio_init(struct device *dev)
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 @@ static void serialio_init(struct device *dev)
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 0000000000..95b286ebfc
--- /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 0000000000..66b9e01981
--- /dev/null
+++ b/src/southbridge/intel/lynxpoint/uart_init.c
@@ -0,0 +1,54 @@
+/* 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);
+ }
+}
+
+/* TODO: Figure out if all steps are actually necessary */
+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);
+}