summaryrefslogtreecommitdiffstats
path: root/drivers/bus/brcmstb_gisb.c
diff options
context:
space:
mode:
authorFlorian Fainelli <f.fainelli@gmail.com>2016-01-31 12:29:27 -0800
committerRalf Baechle <ralf@linux-mips.org>2016-05-13 14:01:55 +0200
commitc400d5ebec1828ee00acb53890741a62b45fb23b (patch)
tree1acd18acb2b8dfe04181ac85624ac41892f27257 /drivers/bus/brcmstb_gisb.c
parent885872b722b73b2026a48bdff4621f289be2b044 (diff)
downloadlinux-0-day-c400d5ebec1828ee00acb53890741a62b45fb23b.tar.gz
linux-0-day-c400d5ebec1828ee00acb53890741a62b45fb23b.tar.xz
BUS: brcmstb_gisb: Hook to MIPS board_be_handler
MIPS kernels allow platforms to invoke a custom Bus Error handler, add the necessary code to do this for Broadcom SoCs where the GISB bus error handler can be used. We may get a bus error from an address decoded outside of the GISB bus space, so we need to check the validity of such a capture before printing anything. Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> Cc: cernekee@gmail.com Cc: arnd@arndb.de Cc: jaedon.shin@gmail.com Cc: pgynther@google.com Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12284/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'drivers/bus/brcmstb_gisb.c')
-rw-r--r--drivers/bus/brcmstb_gisb.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/drivers/bus/brcmstb_gisb.c b/drivers/bus/brcmstb_gisb.c
index f364fa4d24ebf..72fe0a5a8bf3f 100644
--- a/drivers/bus/brcmstb_gisb.c
+++ b/drivers/bus/brcmstb_gisb.c
@@ -30,6 +30,10 @@
#include <asm/signal.h>
#endif
+#ifdef CONFIG_MIPS
+#include <asm/traps.h>
+#endif
+
#define ARB_ERR_CAP_CLEAR (1 << 0)
#define ARB_ERR_CAP_STATUS_TIMEOUT (1 << 12)
#define ARB_ERR_CAP_STATUS_TEA (1 << 11)
@@ -238,6 +242,29 @@ static int brcmstb_bus_error_handler(unsigned long addr, unsigned int fsr,
}
#endif
+#ifdef CONFIG_MIPS
+static int brcmstb_bus_error_handler(struct pt_regs *regs, int is_fixup)
+{
+ int ret = 0;
+ struct brcmstb_gisb_arb_device *gdev;
+ u32 cap_status;
+
+ list_for_each_entry(gdev, &brcmstb_gisb_arb_device_list, next) {
+ cap_status = gisb_read(gdev, ARB_ERR_CAP_STATUS);
+
+ /* Invalid captured address, bail out */
+ if (!(cap_status & ARB_ERR_CAP_STATUS_VALID)) {
+ is_fixup = 1;
+ goto out;
+ }
+
+ ret |= brcmstb_gisb_arb_decode_addr(gdev, "bus error");
+ }
+out:
+ return is_fixup ? MIPS_BE_FIXUP : MIPS_BE_FATAL;
+}
+#endif
+
static irqreturn_t brcmstb_gisb_timeout_handler(int irq, void *dev_id)
{
brcmstb_gisb_arb_decode_addr(dev_id, "timeout");
@@ -355,6 +382,9 @@ static int __init brcmstb_gisb_arb_probe(struct platform_device *pdev)
hook_fault_code(22, brcmstb_bus_error_handler, SIGBUS, 0,
"imprecise external abort");
#endif
+#ifdef CONFIG_MIPS
+ board_be_handler = brcmstb_bus_error_handler;
+#endif
dev_info(&pdev->dev, "registered mem: %p, irqs: %d, %d\n",
gdev->base, timeout_irq, tea_irq);