summaryrefslogtreecommitdiffstats
path: root/platforms
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2015-06-15 10:00:14 +1000
committerStewart Smith <stewart@linux.vnet.ibm.com>2015-06-19 15:12:57 +1000
commit35b433b79bb41f2cdb45e18ea1d20d326fefb344 (patch)
treeb029d8bb3476d29bc2dcc3de7ce7f691eba61cf3 /platforms
parenta921764eed0a38670cacc47fa3aa9d5e87e1ab6b (diff)
downloadtalos-skiboot-35b433b79bb41f2cdb45e18ea1d20d326fefb344.tar.gz
talos-skiboot-35b433b79bb41f2cdb45e18ea1d20d326fefb344.zip
Support for Naples LPC serial interrupts
This adds support for the HW SerIRQ deserializer of the P8 LPC bridge which is properly wired up on Naples. It also adds support for detecting and reporting LPC error interrupts on all P8s. On most platforms (Rhesus is the exception here due to the way it lets Linux handle the UART interrupts directly), we modify the device-tree to properly represent the LPC controller as a cascaded interrupt-controller and the "interrupts" property of LPC devices to contain the actual LPC interrupt number for the device. We add a mechanism for drivers to register specific LPC interrupts, and a "workaround" for pre-Naples P8 which platforms can use to call all of them for when the external FPGA based deserializer is used. There's also a callback on LPC resets which isn't used yet, we need a bit more work on the general LPC error handling, but it can be done a separate patches. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'platforms')
-rw-r--r--platforms/astbmc/astbmc.h2
-rw-r--r--platforms/astbmc/common.c20
-rw-r--r--platforms/astbmc/firestone.c2
-rw-r--r--platforms/astbmc/habanero.c2
-rw-r--r--platforms/astbmc/palmetto.c2
-rw-r--r--platforms/rhesus/rhesus.c27
6 files changed, 28 insertions, 27 deletions
diff --git a/platforms/astbmc/astbmc.h b/platforms/astbmc/astbmc.h
index cee475a9..489ffd20 100644
--- a/platforms/astbmc/astbmc.h
+++ b/platforms/astbmc/astbmc.h
@@ -22,7 +22,7 @@ extern void astbmc_early_init(void);
extern int64_t astbmc_ipmi_reboot(void);
extern int64_t astbmc_ipmi_power_down(uint64_t request);
extern void astbmc_init(void);
-extern void astbmc_ext_irq(unsigned int chip_id);
+extern void astbmc_ext_irq_serirq_cpld(unsigned int chip_id);
extern int pnor_init(void);
#endif /* __ASTBMC_H */
diff --git a/platforms/astbmc/common.c b/platforms/astbmc/common.c
index c89af63c..50341d61 100644
--- a/platforms/astbmc/common.c
+++ b/platforms/astbmc/common.c
@@ -25,6 +25,7 @@
#include <ipmi.h>
#include <bt.h>
#include <errorlog.h>
+#include <lpc.h>
#include "astbmc.h"
@@ -38,10 +39,9 @@
#define BT_IO_COUNT 3
#define BT_LPC_IRQ 10
-void astbmc_ext_irq(unsigned int chip_id __unused)
+void astbmc_ext_irq_serirq_cpld(unsigned int chip_id)
{
- uart_irq();
- bt_irq();
+ lpc_all_interrupts(chip_id);
}
static void astbmc_ipmi_error(struct ipmi_msg *msg)
@@ -180,6 +180,9 @@ static void astbmc_fixup_dt_bt(struct dt_node *lpc)
/* Mark it as reserved to avoid Linux trying to claim it */
dt_add_property_strings(bt, "status", "reserved");
+
+ dt_add_property_cells(bt, "interrupts", BT_LPC_IRQ);
+ dt_add_property_cells(bt, "interrupt-parent", lpc->phandle);
}
static void astbmc_fixup_dt_uart(struct dt_node *lpc)
@@ -222,14 +225,9 @@ static void astbmc_fixup_dt_uart(struct dt_node *lpc)
*/
dt_add_property_strings(uart, "device_type", "serial");
- /*
- * Add interrupt. This simulates coming from HostBoot which
- * does not know our interrupt numbering scheme. Instead, it
- * just tells us which chip the interrupt is wired to, it will
- * be the PSI "host error" interrupt of that chip. For now we
- * assume the same chip as the LPC bus is on.
- */
- dt_add_property_cells(uart, "ibm,irq-chip-id", dt_get_chip_id(lpc));
+ /* Add interrupt */
+ dt_add_property_cells(uart, "interrupts", UART_LPC_IRQ);
+ dt_add_property_cells(uart, "interrupt-parent", lpc->phandle);
}
static void del_compatible(struct dt_node *node)
diff --git a/platforms/astbmc/firestone.c b/platforms/astbmc/firestone.c
index 362f1b6c..cda9d06e 100644
--- a/platforms/astbmc/firestone.c
+++ b/platforms/astbmc/firestone.c
@@ -40,7 +40,7 @@ DECLARE_PLATFORM(firestone) = {
.name = "Firestone",
.probe = firestone_probe,
.init = astbmc_init,
- .external_irq = astbmc_ext_irq,
+ .external_irq = astbmc_ext_irq_serirq_cpld,
.cec_power_down = astbmc_ipmi_power_down,
.cec_reboot = astbmc_ipmi_reboot,
.elog_commit = ipmi_elog_commit,
diff --git a/platforms/astbmc/habanero.c b/platforms/astbmc/habanero.c
index a2eec4a5..7ae5dc4c 100644
--- a/platforms/astbmc/habanero.c
+++ b/platforms/astbmc/habanero.c
@@ -49,7 +49,7 @@ DECLARE_PLATFORM(habanero) = {
.name = "Habanero",
.probe = habanero_probe,
.init = astbmc_init,
- .external_irq = astbmc_ext_irq,
+ .external_irq = astbmc_ext_irq_serirq_cpld,
.cec_power_down = astbmc_ipmi_power_down,
.cec_reboot = astbmc_ipmi_reboot,
.elog_commit = ipmi_elog_commit,
diff --git a/platforms/astbmc/palmetto.c b/platforms/astbmc/palmetto.c
index 803ca46c..7c2a1578 100644
--- a/platforms/astbmc/palmetto.c
+++ b/platforms/astbmc/palmetto.c
@@ -49,7 +49,7 @@ DECLARE_PLATFORM(palmetto) = {
.name = "Palmetto",
.probe = palmetto_probe,
.init = astbmc_init,
- .external_irq = astbmc_ext_irq,
+ .external_irq = astbmc_ext_irq_serirq_cpld,
.cec_power_down = astbmc_ipmi_power_down,
.cec_reboot = astbmc_ipmi_reboot,
.elog_commit = ipmi_elog_commit,
diff --git a/platforms/rhesus/rhesus.c b/platforms/rhesus/rhesus.c
index 7a43b1f4..b597ba02 100644
--- a/platforms/rhesus/rhesus.c
+++ b/platforms/rhesus/rhesus.c
@@ -20,6 +20,7 @@
#include <lpc.h>
#include <console.h>
#include <opal.h>
+#include <interrupts.h>
#include <libflash/libflash.h>
#include <libflash/libffs.h>
#include <libflash/blocklevel.h>
@@ -156,7 +157,7 @@ static void rhesus_init(void)
uart_setup_linux_passthrough();
}
-static void rhesus_dt_fixup_uart(struct dt_node *lpc)
+static void rhesus_dt_fixup_uart(struct dt_node *lpc, bool has_irq)
{
/*
* The official OF ISA/LPC binding is a bit odd, it prefixes
@@ -193,14 +194,15 @@ static void rhesus_dt_fixup_uart(struct dt_node *lpc)
*/
dt_add_property_strings(uart, "device_type", "serial");
- /*
- * Add interrupt. This simulates coming from HostBoot which
- * does not know our interrupt numbering scheme. Instead, it
- * just tells us which chip the interrupt is wired to, it will
- * be the PSI "host error" interrupt of that chip. For now we
- * assume the same chip as the LPC bus is on.
+ /* Expose the external interrupt if supported
*/
- dt_add_property_cells(uart, "ibm,irq-chip-id", dt_get_chip_id(lpc));
+ if (has_irq) {
+ uint32_t chip_id = dt_get_chip_id(lpc);
+ uint32_t irq = get_psi_interrupt(chip_id) + P8_IRQ_PSI_HOST_ERR;
+ dt_add_property_cells(uart, "interrupts", irq);
+ dt_add_property_cells(uart, "interrupt-parent",
+ get_ics_phandle());
+ }
}
/*
@@ -224,7 +226,7 @@ static void rhesus_dt_fixup_rtc(struct dt_node *lpc)
(EC_RTC_BLOCK_SIZE / 128) * 2);
}
-static void rhesus_dt_fixup(void)
+static void rhesus_dt_fixup(bool has_uart_irq)
{
struct dt_node *n, *primary_lpc = NULL;
@@ -240,13 +242,14 @@ static void rhesus_dt_fixup(void)
return;
rhesus_dt_fixup_rtc(primary_lpc);
- rhesus_dt_fixup_uart(primary_lpc);
+ rhesus_dt_fixup_uart(primary_lpc, has_uart_irq);
}
static bool rhesus_probe(void)
{
const char *model;
int rev;
+ bool has_uart_irq = false;
if (!dt_node_is_compatible(dt_root, "ibm,powernv"))
return false;
@@ -264,14 +267,14 @@ static bool rhesus_probe(void)
prerror("Rhesus board revision not found !\n");
/* Add missing bits of device-tree such as the UART */
- rhesus_dt_fixup();
+ rhesus_dt_fixup(has_uart_irq);
/*
* Setup UART and use it as console. For now, we
* don't expose the interrupt as we know it's not
* working properly yet
*/
- uart_init(false);
+ uart_init(has_uart_irq);
return true;
}
OpenPOWER on IntegriCloud