aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/ast-bmc/ast-io.c110
-rw-r--r--include/ast.h19
-rw-r--r--platforms/bmc/palmetto.c19
3 files changed, 141 insertions, 7 deletions
diff --git a/hw/ast-bmc/ast-io.c b/hw/ast-bmc/ast-io.c
index e89bf7f..e8bad14 100644
--- a/hw/ast-bmc/ast-io.c
+++ b/hw/ast-bmc/ast-io.c
@@ -286,6 +286,53 @@ int ast_copy_from_ahb(void *dst, uint32_t reg, uint32_t len)
return -EINVAL;
}
+static void ast_setup_sio_irq_polarity(void)
+{
+ /* Send SuperIO password */
+ lpc_outb(0xa5, 0x2e);
+ lpc_outb(0xa5, 0x2e);
+
+ /* Select logical dev 2 */
+ bmc_sio_outb(0x02, 0x07);
+ bmc_sio_outb(0x01, 0x71); /* level low */
+
+ /* Select logical dev 3 */
+ bmc_sio_outb(0x03, 0x07);
+ bmc_sio_outb(0x01, 0x71); /* irq level low */
+
+ /* Select logical dev 4 */
+ bmc_sio_outb(0x04, 0x07);
+ bmc_sio_outb(0x01, 0x71); /* irq level low */
+
+ /* Select logical dev 5 */
+ bmc_sio_outb(0x05, 0x07);
+ bmc_sio_outb(0x01, 0x71); /* irq level low */
+ bmc_sio_outb(0x01, 0x73); /* irq level low */
+
+ /* Select logical dev 7 */
+ bmc_sio_outb(0x07, 0x07);
+ bmc_sio_outb(0x01, 0x71); /* irq level low */
+
+ /* Select logical dev d */
+ bmc_sio_outb(0x0b, 0x07);
+ bmc_sio_outb(0x01, 0x71); /* irq level low */
+
+ /* Select logical dev c */
+ bmc_sio_outb(0x0c, 0x07);
+ bmc_sio_outb(0x01, 0x71); /* irq level low */
+
+ /* Select logical dev d */
+ bmc_sio_outb(0x0d, 0x07);
+ bmc_sio_outb(0x01, 0x71); /* irq level low */
+
+ /* Select logical dev e */
+ bmc_sio_outb(0x0e, 0x07);
+ bmc_sio_outb(0x01, 0x71); /* irq level low */
+
+ /* Re-lock SuperIO */
+ lpc_outb(0xaa, 0x2e);
+}
+
void ast_io_init(void)
{
/* Initialize iLPC->AHB bridge */
@@ -295,10 +342,51 @@ void ast_io_init(void)
bmc_sio_ahb_writel(0x30000e00, LPC_HICR7);
bmc_sio_ahb_writel(0xfe0001ff, LPC_HICR8);
bmc_sio_ahb_writel(0x00000500, LPC_HICR6);
+
+ /* Configure all AIO interrupts to level low */
+ ast_setup_sio_irq_polarity();
+}
+
+void ast_setup_ibt(uint16_t io_base, uint8_t irq)
+{
+ uint32_t v;
+
+ v = bmc_sio_ahb_readl(LPC_iBTCR0);
+ v = v & ~(0xfffffc00u);
+ v = v | (((uint32_t)io_base) << 16);
+ v = v | (((uint32_t)irq) << 12);
+ bmc_sio_ahb_writel(v, LPC_iBTCR0);
+}
+
+bool ast_is_vuart1_enabled(void)
+{
+ uint32_t v;
+
+ v = bmc_sio_ahb_readl(VUART1_GCTRLA);
+ return !!(v & 1);
+}
+
+void ast_setup_vuart1(uint16_t io_base, uint8_t irq)
+{
+ uint32_t v;
+
+ /* IRQ level low */
+ v = bmc_sio_ahb_readl(VUART1_GCTRLA);
+ v = v & ~2u;
+ bmc_sio_ahb_writel(v, VUART1_GCTRLA);
+
+ /* IRQ number */
+ v = bmc_sio_ahb_readl(VUART1_GCTRLB);
+ v = (v & ~0xf0u) | (irq << 4);
+ bmc_sio_ahb_writel(v, VUART1_GCTRLB);
+
+ /* Address */
+ bmc_sio_ahb_writel(io_base & 0xff, VUART1_ADDRL);
+ bmc_sio_ahb_writel(io_base >> 8, VUART1_ADDRH);
}
-/* Setup SuperIO UART 1*/
-void ast_setup_uart1(uint16_t io_base, uint8_t irq)
+/* Setup SuperIO UART 1 */
+void ast_setup_sio_uart1(uint16_t io_base, uint8_t irq)
{
/* Send SuperIO password */
lpc_outb(0xa5, 0x2e);
@@ -308,7 +396,7 @@ void ast_setup_uart1(uint16_t io_base, uint8_t irq)
bmc_sio_outb(0x02, 0x07);
/* Disable UART1 for configuration */
- bmc_sio_outb(0x01, 0x30);
+ bmc_sio_outb(0x00, 0x30);
/* Configure base and interrupt */
bmc_sio_outb(io_base >> 8, 0x60);
@@ -322,3 +410,19 @@ void ast_setup_uart1(uint16_t io_base, uint8_t irq)
/* Re-lock SuperIO */
lpc_outb(0xaa, 0x2e);
}
+
+void ast_disable_sio_uart1(void)
+{
+ /* Send SuperIO password */
+ lpc_outb(0xa5, 0x2e);
+ lpc_outb(0xa5, 0x2e);
+
+ /* Select logical dev 2 */
+ bmc_sio_outb(0x02, 0x07);
+
+ /* Disable UART1 */
+ bmc_sio_outb(0x00, 0x30);
+
+ /* Re-lock SuperIO */
+ lpc_outb(0xaa, 0x2e);
+}
diff --git a/include/ast.h b/include/ast.h
index 17ee17e..f97aa44 100644
--- a/include/ast.h
+++ b/include/ast.h
@@ -36,6 +36,14 @@
#define LPC_HICR6 (LPC_BASE + 0x80)
#define LPC_HICR7 (LPC_BASE + 0x88)
#define LPC_HICR8 (LPC_BASE + 0x8c)
+#define LPC_iBTCR0 (LPC_BASE + 0x140)
+
+/* VUART1 */
+#define VUART1_BASE 0x1e787000
+#define VUART1_GCTRLA (VUART1_BASE + 0x20)
+#define VUART1_GCTRLB (VUART1_BASE + 0x24)
+#define VUART1_ADDRL (VUART1_BASE + 0x28)
+#define VUART1_ADDRH (VUART1_BASE + 0x2c)
/*
* AHB Accessors
@@ -59,8 +67,15 @@ int ast_copy_from_ahb(void *dst, uint32_t reg, uint32_t len);
void ast_io_init(void);
-/* UART init */
-void ast_setup_uart1(uint16_t io_base, uint8_t irq);
+/* UART configuration */
+
+bool ast_is_vuart1_enabled(void);
+void ast_setup_vuart1(uint16_t io_base, uint8_t irq);
+void ast_setup_sio_uart1(uint16_t io_base, uint8_t irq);
+void ast_disable_sio_uart1(void);
+
+/* BT configuration */
+void ast_setup_ibt(uint16_t io_base, uint8_t irq);
#endif /* __SKIBOOT__ */
diff --git a/platforms/bmc/palmetto.c b/platforms/bmc/palmetto.c
index 28af306..5d28b86 100644
--- a/platforms/bmc/palmetto.c
+++ b/platforms/bmc/palmetto.c
@@ -198,8 +198,23 @@ static bool palmetto_probe(void)
/* Send external interrupts to me */
psi_set_external_irq_policy(EXTERNAL_IRQ_POLICY_SKIBOOT);
- /* Configure UART1 on SuperIO */
- ast_setup_uart1(UART_IO_BASE, UART_LPC_IRQ);
+ /*
+ * Depending on which image we are running, it may be configuring
+ * the virtual UART or not. Check if VUART is enabled and use
+ * SIO if not. We also correct the configuration of VUART as some
+ * BMC images don't setup the interrupt properly
+ */
+ if (ast_is_vuart1_enabled()) {
+ printf("PLAT: Using virtual UART\n");
+ ast_disable_sio_uart1();
+ ast_setup_vuart1(UART_IO_BASE, UART_LPC_IRQ);
+ } else {
+ printf("PLAT: Using SuperIO UART\n");
+ ast_setup_sio_uart1(UART_IO_BASE, UART_LPC_IRQ);
+ }
+
+ /* Similarily, some BMCs don't configure the BT interrupt properly */
+ ast_setup_ibt(BT_IO_BASE, BT_LPC_IRQ);
/* Setup UART and use it as console with interrupts */
uart_init(true);