summaryrefslogtreecommitdiff
path: root/src/drivers/uart/oxpcie_early.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/drivers/uart/oxpcie_early.c')
-rw-r--r--src/drivers/uart/oxpcie_early.c40
1 files changed, 37 insertions, 3 deletions
diff --git a/src/drivers/uart/oxpcie_early.c b/src/drivers/uart/oxpcie_early.c
index 2cbc8c7948..206f54d1a5 100644
--- a/src/drivers/uart/oxpcie_early.c
+++ b/src/drivers/uart/oxpcie_early.c
@@ -5,8 +5,9 @@
#include <device/pci_ops.h>
#include <console/uart.h>
#include <device/pci.h>
+#include "uart8250reg.h"
-static unsigned int oxpcie_present;
+static int oxpcie_present;
static DEVTREE_CONST u32 uart0_base = CONFIG_EARLY_PCI_MMIO_BASE + 0x1000;
int pci_early_device_probe(u8 bus, u8 dev, u32 mmio_base)
@@ -49,9 +50,42 @@ int pci_early_device_probe(u8 bus, u8 dev, u32 mmio_base)
return 0;
}
-static int oxpcie_uart_active(void)
+/*
+ * Stages that do not call pci_early_device_probe() identify an
+ * enabled UART with a test read. Since PCI bus enumeration
+ * has not happened PCI configuration register access is not
+ * possible here.
+ */
+static int uart_presence(uintptr_t base)
{
- return oxpcie_present;
+ /* LCR has no side-effects on reads. */
+ const u8 reg = UART8250_LCR;
+ u8 val;
+
+ if (CONFIG(DRIVERS_UART_8250MEM_32))
+ val = read32p(base + 4 * reg) & 0xff;
+ else
+ val = read8p(base + reg);
+
+ if (val == 0xff)
+ return -1;
+
+ /* Something decoded MMIO read, assume it was the UART. */
+ return 1;
+}
+
+static bool oxpcie_uart_active(void)
+{
+ if (oxpcie_present == 0)
+ oxpcie_present = uart_presence(uart0_base);
+
+ if (oxpcie_present > 0)
+ return true;
+ if (oxpcie_present < 0)
+ return false;
+
+ /* not reached */
+ return false;
}
uintptr_t uart_platform_base(unsigned int idx)