summaryrefslogtreecommitdiffstats
path: root/platforms
diff options
context:
space:
mode:
Diffstat (limited to 'platforms')
-rw-r--r--platforms/astbmc/astbmc.h1
-rw-r--r--platforms/astbmc/common.c112
-rw-r--r--platforms/astbmc/romulus.c2
-rw-r--r--platforms/astbmc/witherspoon.c3
-rw-r--r--platforms/qemu/qemu.c4
5 files changed, 98 insertions, 24 deletions
diff --git a/platforms/astbmc/astbmc.h b/platforms/astbmc/astbmc.h
index fb6c68a2..fc53d1a1 100644
--- a/platforms/astbmc/astbmc.h
+++ b/platforms/astbmc/astbmc.h
@@ -89,6 +89,7 @@ extern void astbmc_init(void);
extern void astbmc_ext_irq_serirq_cpld(unsigned int chip_id);
extern int pnor_init(void);
extern void check_all_slot_table(void);
+extern void astbmc_exit(void);
extern void slot_table_init(const struct slot_table_entry *top_table);
extern void slot_table_get_slot_info(struct phb *phb, struct pci_device * pd);
diff --git a/platforms/astbmc/common.c b/platforms/astbmc/common.c
index 6c90b7db..4b5d9a68 100644
--- a/platforms/astbmc/common.c
+++ b/platforms/astbmc/common.c
@@ -372,25 +372,13 @@ static void astbmc_fixup_psi_bar(void)
xscom_write(chip->id, 0x201090A, psibar);
}
-void astbmc_early_init(void)
+static void astbmc_fixup_uart(void)
{
- /* Hostboot's device-tree isn't quite right yet */
- astbmc_fixup_dt();
-
- /* Hostboot forgets to populate the PSI BAR */
- astbmc_fixup_psi_bar();
-
- /* Send external interrupts to me */
- psi_set_external_irq_policy(EXTERNAL_IRQ_POLICY_SKIBOOT);
-
- /* Initialize AHB accesses via AST2400 */
- ast_io_init();
-
/*
- * 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
+ * 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");
@@ -400,11 +388,37 @@ void astbmc_early_init(void)
printf("PLAT: Using SuperIO UART\n");
ast_setup_sio_uart1(UART_IO_BASE, UART_LPC_IRQ);
}
+}
+
+void astbmc_early_init(void)
+{
+ /* Hostboot's device-tree isn't quite right yet */
+ astbmc_fixup_dt();
- /* Similarly, some BMCs don't configure the BT interrupt properly */
- ast_setup_ibt(BT_IO_BASE, BT_LPC_IRQ);
+ /* Hostboot forgets to populate the PSI BAR */
+ astbmc_fixup_psi_bar();
+
+ /* Send external interrupts to me */
+ psi_set_external_irq_policy(EXTERNAL_IRQ_POLICY_SKIBOOT);
- ast_setup_sio_mbox(MBOX_IO_BASE, MBOX_LPC_IRQ);
+ if (ast_sio_init()) {
+ if (!ast_can_isolate_sp()) {
+ /*
+ * BMCs claiming support for isolation must have
+ * correctly configured the UART and BT for host
+ * firmware. If not, let's apply some fixups for broken
+ * BMC firmwares.
+ */
+ if (ast_io_init()) {
+ astbmc_fixup_uart();
+ ast_setup_ibt(BT_IO_BASE, BT_LPC_IRQ);
+ } else
+ prerror("PLAT: AST IO initialisation failed!\n");
+ }
+
+ ast_setup_sio_mbox(MBOX_IO_BASE, MBOX_LPC_IRQ);
+ } else
+ prerror("PLAT: AST SIO initialisation failed!\n");
/* Setup UART and use it as console */
uart_init();
@@ -414,6 +428,64 @@ void astbmc_early_init(void)
prd_init();
}
+static bool astbmc_isolate_via_io(void)
+{
+ uint32_t hw_strapping;
+ uint32_t silicon_rev;
+ uint8_t family;
+
+ silicon_rev = ast_ahb_readl(SCU_REVISION_ID);
+ family = SCU_REVISION_SOC_FAMILY(silicon_rev);
+
+ if (family == SCU_REVISION_SOC_FAMILY_2400) {
+ /* Strapping is read-modify-write on SCU70 */
+ hw_strapping = SCU_STRAP_SIO_DECODE_DISABLE;
+ hw_strapping |= ast_ahb_readl(SCU_HW_STRAPPING);
+ } else if (family == SCU_REVISION_SOC_FAMILY_2500) {
+ /*
+ * Strapping is W1S on SCU70, W1C on SCU7C. We're setting a bit
+ * so read-modify-write *should* work, but in reality it breaks
+ * the AXI/AHB divider, so don't do that.
+ */
+ hw_strapping = SCU_STRAP_SIO_DECODE_DISABLE;
+ } else {
+ prerror("PLAT: Unrecognised BMC silicon revision 0x%x, isolation failed\n",
+ silicon_rev);
+ return false;
+ }
+
+ ast_ahb_writel(hw_strapping, SCU_HW_STRAPPING);
+
+ return true;
+}
+
+static bool astbmc_isolate_via_ipmi(void)
+{
+ return false;
+}
+
+static void astbmc_isolate(void)
+{
+ bool isolated;
+
+ isolated = ast_io_is_rw() ? astbmc_isolate_via_io()
+ : astbmc_isolate_via_ipmi();
+
+ if (!isolated) {
+ prlog(PR_EMERG, "PLAT: BMC isolation failed\n");
+ abort();
+ }
+
+ prlog(PR_INFO, "PLAT: Isolated BMC\n");
+}
+
+void astbmc_exit(void)
+{
+ if (ast_can_isolate_sp())
+ astbmc_isolate();
+ ipmi_wdt_final_reset();
+}
+
const struct bmc_platform astbmc_ami = {
.name = "AMI",
.ipmi_oem_partial_add_esel = IPMI_CODE(0x3a, 0xf0),
diff --git a/platforms/astbmc/romulus.c b/platforms/astbmc/romulus.c
index 8d3d1046..67c59463 100644
--- a/platforms/astbmc/romulus.c
+++ b/platforms/astbmc/romulus.c
@@ -80,6 +80,6 @@ DECLARE_PLATFORM(romulus) = {
.cec_power_down = astbmc_ipmi_power_down,
.cec_reboot = astbmc_ipmi_reboot,
.elog_commit = ipmi_elog_commit,
- .exit = ipmi_wdt_final_reset,
+ .exit = astbmc_exit,
.terminate = ipmi_terminate,
};
diff --git a/platforms/astbmc/witherspoon.c b/platforms/astbmc/witherspoon.c
index cb09eefe..d663709f 100644
--- a/platforms/astbmc/witherspoon.c
+++ b/platforms/astbmc/witherspoon.c
@@ -29,6 +29,7 @@
#include <phb4.h>
#include "astbmc.h"
+#include "ast.h"
/*
* HACK: Hostboot doesn't export the correct data for the system VPD EEPROM
@@ -165,7 +166,7 @@ DECLARE_PLATFORM(witherspoon) = {
.cec_power_down = astbmc_ipmi_power_down,
.cec_reboot = astbmc_ipmi_reboot,
.elog_commit = ipmi_elog_commit,
- .exit = ipmi_wdt_final_reset,
+ .exit = astbmc_exit,
.terminate = ipmi_terminate,
.pci_get_slot_info = dt_slot_get_slot_info,
diff --git a/platforms/qemu/qemu.c b/platforms/qemu/qemu.c
index dee61cce..a9b4f57b 100644
--- a/platforms/qemu/qemu.c
+++ b/platforms/qemu/qemu.c
@@ -246,8 +246,8 @@ static bool qemu_probe(void)
psi_set_external_irq_policy(EXTERNAL_IRQ_POLICY_SKIBOOT);
- /* Initialize AHB accesses via AST2400 */
- ast_io_init();
+ if (!ast_sio_init())
+ prerror("PLAT: AST SIO initialisation failed!\n");
/* Setup UART and use it as console */
uart_init();
OpenPOWER on IntegriCloud