aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2014-10-05 09:16:36 +1100
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2014-10-05 09:16:36 +1100
commitb33fd8dc893e2ea65ceef5dad2fa8173932443e5 (patch)
tree8fbf5bfd56914848ea0369f67fb4438916576ceb
parent5876e124399cc2e4961020f22b28bfc9abdae3bb (diff)
downloadskiboot-b33fd8dc893e2ea65ceef5dad2fa8173932443e5.zip
skiboot-b33fd8dc893e2ea65ceef5dad2fa8173932443e5.tar.gz
skiboot-b33fd8dc893e2ea65ceef5dad2fa8173932443e5.tar.bz2
plat/palmetto: Fix SIO UART vs UART setup and iBT setup
The AMI images use the virtual UART, not the SIO UART, so configuring the SIO the way we do is incorrect. Additionally, they don't configure the interrupts properly (bad polarity for VUART and bad number for iBT). This reworks the inits to fix that up: - All SIO interrupts are set to level low - Check if VUART is enabled. If yes, configure and use it (and disable SIO UART which hostboot might have left enabled). - Else, reconfigure VUART LPC address and IRQ properly - Configure iBT LPC address and IRQ properly Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-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);