aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorian Fainelli <f.fainelli@gmail.com>2016-01-31 15:29:27 -0500
committerRalf Baechle <ralf@linux-mips.org>2016-05-13 08:01:55 -0400
commitc400d5ebec1828ee00acb53890741a62b45fb23b (patch)
tree1acd18acb2b8dfe04181ac85624ac41892f27257
parent885872b722b73b2026a48bdff4621f289be2b044 (diff)
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>
-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 f364fa4d24eb..72fe0a5a8bf3 100644
--- a/drivers/bus/brcmstb_gisb.c
+++ b/drivers/bus/brcmstb_gisb.c
@@ -30,6 +30,10 @@
30#include <asm/signal.h> 30#include <asm/signal.h>
31#endif 31#endif
32 32
33#ifdef CONFIG_MIPS
34#include <asm/traps.h>
35#endif
36
33#define ARB_ERR_CAP_CLEAR (1 << 0) 37#define ARB_ERR_CAP_CLEAR (1 << 0)
34#define ARB_ERR_CAP_STATUS_TIMEOUT (1 << 12) 38#define ARB_ERR_CAP_STATUS_TIMEOUT (1 << 12)
35#define ARB_ERR_CAP_STATUS_TEA (1 << 11) 39#define ARB_ERR_CAP_STATUS_TEA (1 << 11)
@@ -238,6 +242,29 @@ static int brcmstb_bus_error_handler(unsigned long addr, unsigned int fsr,
238} 242}
239#endif 243#endif
240 244
245#ifdef CONFIG_MIPS
246static int brcmstb_bus_error_handler(struct pt_regs *regs, int is_fixup)
247{
248 int ret = 0;
249 struct brcmstb_gisb_arb_device *gdev;
250 u32 cap_status;
251
252 list_for_each_entry(gdev, &brcmstb_gisb_arb_device_list, next) {
253 cap_status = gisb_read(gdev, ARB_ERR_CAP_STATUS);
254
255 /* Invalid captured address, bail out */
256 if (!(cap_status & ARB_ERR_CAP_STATUS_VALID)) {
257 is_fixup = 1;
258 goto out;
259 }
260
261 ret |= brcmstb_gisb_arb_decode_addr(gdev, "bus error");
262 }
263out:
264 return is_fixup ? MIPS_BE_FIXUP : MIPS_BE_FATAL;
265}
266#endif
267
241static irqreturn_t brcmstb_gisb_timeout_handler(int irq, void *dev_id) 268static irqreturn_t brcmstb_gisb_timeout_handler(int irq, void *dev_id)
242{ 269{
243 brcmstb_gisb_arb_decode_addr(dev_id, "timeout"); 270 brcmstb_gisb_arb_decode_addr(dev_id, "timeout");
@@ -355,6 +382,9 @@ static int __init brcmstb_gisb_arb_probe(struct platform_device *pdev)
355 hook_fault_code(22, brcmstb_bus_error_handler, SIGBUS, 0, 382 hook_fault_code(22, brcmstb_bus_error_handler, SIGBUS, 0,
356 "imprecise external abort"); 383 "imprecise external abort");
357#endif 384#endif
385#ifdef CONFIG_MIPS
386 board_be_handler = brcmstb_bus_error_handler;
387#endif
358 388
359 dev_info(&pdev->dev, "registered mem: %p, irqs: %d, %d\n", 389 dev_info(&pdev->dev, "registered mem: %p, irqs: %d, %d\n",
360 gdev->base, timeout_irq, tea_irq); 390 gdev->base, timeout_irq, tea_irq);