From 856c7ccb9ce7a061f04bdf586f649cb93654e294 Mon Sep 17 00:00:00 2001 From: Doug Berger Date: Wed, 29 Mar 2017 17:29:09 -0700 Subject: bus: brcmstb_gisb: Use register offsets with writes too This commit corrects the bug introduced in commit f80835875d3d ("bus: brcmstb_gisb: Look up register offsets in a table") such that gisb_write() translates the register enumeration into an offset from the base address for writes as well as reads. Fixes: f80835875d3d ("bus: brcmstb_gisb: Look up register offsets in a table") Signed-off-by: Doug Berger Acked-by: Gregory Fong Signed-off-by: Florian Fainelli --- drivers/bus/brcmstb_gisb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/bus') diff --git a/drivers/bus/brcmstb_gisb.c b/drivers/bus/brcmstb_gisb.c index 72fe0a5a8bf3..a94598d0945a 100644 --- a/drivers/bus/brcmstb_gisb.c +++ b/drivers/bus/brcmstb_gisb.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Broadcom Corporation + * Copyright (C) 2014-2017 Broadcom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -127,9 +127,9 @@ static void gisb_write(struct brcmstb_gisb_arb_device *gdev, u32 val, int reg) return; if (gdev->big_endian) - iowrite32be(val, gdev->base + reg); + iowrite32be(val, gdev->base + offset); else - iowrite32(val, gdev->base + reg); + iowrite32(val, gdev->base + offset); } static ssize_t gisb_arb_get_timeout(struct device *dev, -- cgit v1.2.3-59-g8ed1b From 0c2aa0e4b308815e877601845c1a89913f9bd2b9 Mon Sep 17 00:00:00 2001 From: Doug Berger Date: Wed, 29 Mar 2017 17:29:10 -0700 Subject: bus: brcmstb_gisb: correct support for 64-bit address output The GISB bus can support addresses beyond 32-bits. So this commit corrects support for reading a captured 64-bit address into a 64-bit variable by obtaining the high bits from the ARB_ERR_CAP_HI_ADDR register (when present) and then outputting the full 64-bit value. It also removes unused definitions. Fixes: 44127b771d9c ("bus: add Broadcom GISB bus arbiter timeout/error handler") Signed-off-by: Doug Berger Acked-by: Gregory Fong Signed-off-by: Florian Fainelli --- drivers/bus/brcmstb_gisb.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) (limited to 'drivers/bus') diff --git a/drivers/bus/brcmstb_gisb.c b/drivers/bus/brcmstb_gisb.c index a94598d0945a..017c37b9c7c1 100644 --- a/drivers/bus/brcmstb_gisb.c +++ b/drivers/bus/brcmstb_gisb.c @@ -37,8 +37,6 @@ #define ARB_ERR_CAP_CLEAR (1 << 0) #define ARB_ERR_CAP_STATUS_TIMEOUT (1 << 12) #define ARB_ERR_CAP_STATUS_TEA (1 << 11) -#define ARB_ERR_CAP_STATUS_BS_SHIFT (1 << 2) -#define ARB_ERR_CAP_STATUS_BS_MASK 0x3c #define ARB_ERR_CAP_STATUS_WRITE (1 << 1) #define ARB_ERR_CAP_STATUS_VALID (1 << 0) @@ -47,7 +45,6 @@ enum { ARB_ERR_CAP_CLR, ARB_ERR_CAP_HI_ADDR, ARB_ERR_CAP_ADDR, - ARB_ERR_CAP_DATA, ARB_ERR_CAP_STATUS, ARB_ERR_CAP_MASTER, }; @@ -57,7 +54,6 @@ static const int gisb_offsets_bcm7038[] = { [ARB_ERR_CAP_CLR] = 0x0c4, [ARB_ERR_CAP_HI_ADDR] = -1, [ARB_ERR_CAP_ADDR] = 0x0c8, - [ARB_ERR_CAP_DATA] = 0x0cc, [ARB_ERR_CAP_STATUS] = 0x0d0, [ARB_ERR_CAP_MASTER] = -1, }; @@ -67,7 +63,6 @@ static const int gisb_offsets_bcm7400[] = { [ARB_ERR_CAP_CLR] = 0x0c8, [ARB_ERR_CAP_HI_ADDR] = -1, [ARB_ERR_CAP_ADDR] = 0x0cc, - [ARB_ERR_CAP_DATA] = 0x0d0, [ARB_ERR_CAP_STATUS] = 0x0d4, [ARB_ERR_CAP_MASTER] = 0x0d8, }; @@ -77,7 +72,6 @@ static const int gisb_offsets_bcm7435[] = { [ARB_ERR_CAP_CLR] = 0x168, [ARB_ERR_CAP_HI_ADDR] = -1, [ARB_ERR_CAP_ADDR] = 0x16c, - [ARB_ERR_CAP_DATA] = 0x170, [ARB_ERR_CAP_STATUS] = 0x174, [ARB_ERR_CAP_MASTER] = 0x178, }; @@ -87,7 +81,6 @@ static const int gisb_offsets_bcm7445[] = { [ARB_ERR_CAP_CLR] = 0x7e4, [ARB_ERR_CAP_HI_ADDR] = 0x7e8, [ARB_ERR_CAP_ADDR] = 0x7ec, - [ARB_ERR_CAP_DATA] = 0x7f0, [ARB_ERR_CAP_STATUS] = 0x7f4, [ARB_ERR_CAP_MASTER] = 0x7f8, }; @@ -109,9 +102,13 @@ static u32 gisb_read(struct brcmstb_gisb_arb_device *gdev, int reg) { int offset = gdev->gisb_offsets[reg]; - /* return 1 if the hardware doesn't have ARB_ERR_CAP_MASTER */ - if (offset == -1) - return 1; + if (offset < 0) { + /* return 1 if the hardware doesn't have ARB_ERR_CAP_MASTER */ + if (reg == ARB_ERR_CAP_MASTER) + return 1; + else + return 0; + } if (gdev->big_endian) return ioread32be(gdev->base + offset); @@ -119,6 +116,16 @@ static u32 gisb_read(struct brcmstb_gisb_arb_device *gdev, int reg) return ioread32(gdev->base + offset); } +static u64 gisb_read_address(struct brcmstb_gisb_arb_device *gdev) +{ + u64 value; + + value = gisb_read(gdev, ARB_ERR_CAP_ADDR); + value |= (u64)gisb_read(gdev, ARB_ERR_CAP_HI_ADDR) << 32; + + return value; +} + static void gisb_write(struct brcmstb_gisb_arb_device *gdev, u32 val, int reg) { int offset = gdev->gisb_offsets[reg]; @@ -185,7 +192,7 @@ static int brcmstb_gisb_arb_decode_addr(struct brcmstb_gisb_arb_device *gdev, const char *reason) { u32 cap_status; - unsigned long arb_addr; + u64 arb_addr; u32 master; const char *m_name; char m_fmt[11]; @@ -197,10 +204,7 @@ static int brcmstb_gisb_arb_decode_addr(struct brcmstb_gisb_arb_device *gdev, return 1; /* Read the address and master */ - arb_addr = gisb_read(gdev, ARB_ERR_CAP_ADDR) & 0xffffffff; -#if (IS_ENABLED(CONFIG_PHYS_ADDR_T_64BIT)) - arb_addr |= (u64)gisb_read(gdev, ARB_ERR_CAP_HI_ADDR) << 32; -#endif + arb_addr = gisb_read_address(gdev); master = gisb_read(gdev, ARB_ERR_CAP_MASTER); m_name = brcmstb_gisb_master_to_str(gdev, master); @@ -209,7 +213,7 @@ static int brcmstb_gisb_arb_decode_addr(struct brcmstb_gisb_arb_device *gdev, m_name = m_fmt; } - pr_crit("%s: %s at 0x%lx [%c %s], core: %s\n", + pr_crit("%s: %s at 0x%llx [%c %s], core: %s\n", __func__, reason, arb_addr, cap_status & ARB_ERR_CAP_STATUS_WRITE ? 'W' : 'R', cap_status & ARB_ERR_CAP_STATUS_TIMEOUT ? "timeout" : "", -- cgit v1.2.3-59-g8ed1b From 9eb60880d9a9716d113746ac9daba11005abc22a Mon Sep 17 00:00:00 2001 From: Doug Berger Date: Wed, 29 Mar 2017 17:29:11 -0700 Subject: bus: brcmstb_gisb: add notifier handling Check for GISB arbitration errors through a chained notifier when a process dies or a kernel panic occurs. This allows a meaningful GISB diagnostic message to occur along with other diagnostic information from the event. Signed-off-by: Doug Berger Signed-off-by: Florian Fainelli --- drivers/bus/brcmstb_gisb.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'drivers/bus') diff --git a/drivers/bus/brcmstb_gisb.c b/drivers/bus/brcmstb_gisb.c index 017c37b9c7c1..a2e1c5c25a3a 100644 --- a/drivers/bus/brcmstb_gisb.c +++ b/drivers/bus/brcmstb_gisb.c @@ -24,6 +24,9 @@ #include #include #include +#include +#include +#include #ifdef CONFIG_ARM #include @@ -283,6 +286,36 @@ static irqreturn_t brcmstb_gisb_tea_handler(int irq, void *dev_id) return IRQ_HANDLED; } +/* + * Dump out gisb errors on die or panic. + */ +static int dump_gisb_error(struct notifier_block *self, unsigned long v, + void *p); + +static struct notifier_block gisb_die_notifier = { + .notifier_call = dump_gisb_error, +}; + +static struct notifier_block gisb_panic_notifier = { + .notifier_call = dump_gisb_error, +}; + +static int dump_gisb_error(struct notifier_block *self, unsigned long v, + void *p) +{ + struct brcmstb_gisb_arb_device *gdev; + const char *reason = "panic"; + + if (self == &gisb_die_notifier) + reason = "die"; + + /* iterate over each GISB arb registered handlers */ + list_for_each_entry(gdev, &brcmstb_gisb_arb_device_list, next) + brcmstb_gisb_arb_decode_addr(gdev, reason); + + return NOTIFY_DONE; +} + static DEVICE_ATTR(gisb_arb_timeout, S_IWUSR | S_IRUGO, gisb_arb_get_timeout, gisb_arb_set_timeout); @@ -390,6 +423,12 @@ static int __init brcmstb_gisb_arb_probe(struct platform_device *pdev) board_be_handler = brcmstb_bus_error_handler; #endif + if (list_is_singular(&brcmstb_gisb_arb_device_list)) { + register_die_notifier(&gisb_die_notifier); + atomic_notifier_chain_register(&panic_notifier_list, + &gisb_panic_notifier); + } + dev_info(&pdev->dev, "registered mem: %p, irqs: %d, %d\n", gdev->base, timeout_irq, tea_irq); -- cgit v1.2.3-59-g8ed1b From a3d59ae87083e3c890fe8aaba3cbdd0025f31507 Mon Sep 17 00:00:00 2001 From: Doug Berger Date: Wed, 29 Mar 2017 17:29:12 -0700 Subject: bus: brcmstb_gisb: remove low-level ARM hooks The ARM architecture can provide meaningful diagnostic output from the GISB arbiter solely from interrupts and notifiers without the need to hook the low level fault handlers. Signed-off-by: Doug Berger Signed-off-by: Florian Fainelli --- drivers/bus/brcmstb_gisb.c | 30 ------------------------------ 1 file changed, 30 deletions(-) (limited to 'drivers/bus') diff --git a/drivers/bus/brcmstb_gisb.c b/drivers/bus/brcmstb_gisb.c index a2e1c5c25a3a..3fbc116e6b95 100644 --- a/drivers/bus/brcmstb_gisb.c +++ b/drivers/bus/brcmstb_gisb.c @@ -28,11 +28,6 @@ #include #include -#ifdef CONFIG_ARM -#include -#include -#endif - #ifdef CONFIG_MIPS #include #endif @@ -228,27 +223,6 @@ static int brcmstb_gisb_arb_decode_addr(struct brcmstb_gisb_arb_device *gdev, return 0; } -#ifdef CONFIG_ARM -static int brcmstb_bus_error_handler(unsigned long addr, unsigned int fsr, - struct pt_regs *regs) -{ - int ret = 0; - struct brcmstb_gisb_arb_device *gdev; - - /* iterate over each GISB arb registered handlers */ - list_for_each_entry(gdev, &brcmstb_gisb_arb_device_list, next) - ret |= brcmstb_gisb_arb_decode_addr(gdev, "bus error"); - /* - * If it was an imprecise abort, then we need to correct the - * return address to be _after_ the instruction. - */ - if (fsr & (1 << 10)) - regs->ARM_pc += 4; - - return ret; -} -#endif - #ifdef CONFIG_MIPS static int brcmstb_bus_error_handler(struct pt_regs *regs, int is_fixup) { @@ -415,10 +389,6 @@ static int __init brcmstb_gisb_arb_probe(struct platform_device *pdev) list_add_tail(&gdev->next, &brcmstb_gisb_arb_device_list); -#ifdef CONFIG_ARM - 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 -- cgit v1.2.3-59-g8ed1b From 8c7aa17ad11855e141a9869d7591811b3821024d Mon Sep 17 00:00:00 2001 From: Doug Berger Date: Wed, 29 Mar 2017 17:29:13 -0700 Subject: bus: brcmstb_gisb: enable driver for ARM64 architecture The ARM64 architecture can provide meaningful diagnostic output from the GISB arbiter solely from interrupts and notifiers without the need to hook the low level fault handlers. Signed-off-by: Doug Berger Signed-off-by: Florian Fainelli --- drivers/bus/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/bus') diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig index 0a52da439abf..d2a5f1184022 100644 --- a/drivers/bus/Kconfig +++ b/drivers/bus/Kconfig @@ -57,7 +57,7 @@ config ARM_CCN config BRCMSTB_GISB_ARB bool "Broadcom STB GISB bus arbiter" - depends on ARM || MIPS + depends on ARM || ARM64 || MIPS default ARCH_BRCMSTB || BMIPS_GENERIC help Driver for the Broadcom Set Top Box System-on-a-chip internal bus -- cgit v1.2.3-59-g8ed1b From d523e0cfdca37538fc6048077e1d8a0b05c300a5 Mon Sep 17 00:00:00 2001 From: Doug Berger Date: Wed, 29 Mar 2017 17:29:14 -0700 Subject: bus: brcmstb_gisb: update to support new revision The 7278 introduces a new version of this core. This commit adds support for that revision. Signed-off-by: Doug Berger Signed-off-by: Florian Fainelli --- Documentation/devicetree/bindings/bus/brcm,gisb-arb.txt | 3 ++- drivers/bus/brcmstb_gisb.c | 10 ++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers/bus') diff --git a/Documentation/devicetree/bindings/bus/brcm,gisb-arb.txt b/Documentation/devicetree/bindings/bus/brcm,gisb-arb.txt index 1eceefb20f01..8a6c3c2e58fe 100644 --- a/Documentation/devicetree/bindings/bus/brcm,gisb-arb.txt +++ b/Documentation/devicetree/bindings/bus/brcm,gisb-arb.txt @@ -3,7 +3,8 @@ Broadcom GISB bus Arbiter controller Required properties: - compatible: - "brcm,gisb-arb" or "brcm,bcm7445-gisb-arb" for 28nm chips + "brcm,bcm7278-gisb-arb" for V7 28nm chips + "brcm,gisb-arb" or "brcm,bcm7445-gisb-arb" for other 28nm chips "brcm,bcm7435-gisb-arb" for newer 40nm chips "brcm,bcm7400-gisb-arb" for older 40nm chips and all 65nm chips "brcm,bcm7038-gisb-arb" for 130nm chips diff --git a/drivers/bus/brcmstb_gisb.c b/drivers/bus/brcmstb_gisb.c index 3fbc116e6b95..68ac3e93b600 100644 --- a/drivers/bus/brcmstb_gisb.c +++ b/drivers/bus/brcmstb_gisb.c @@ -56,6 +56,15 @@ static const int gisb_offsets_bcm7038[] = { [ARB_ERR_CAP_MASTER] = -1, }; +static const int gisb_offsets_bcm7278[] = { + [ARB_TIMER] = 0x008, + [ARB_ERR_CAP_CLR] = 0x7f8, + [ARB_ERR_CAP_HI_ADDR] = -1, + [ARB_ERR_CAP_ADDR] = 0x7e0, + [ARB_ERR_CAP_STATUS] = 0x7f0, + [ARB_ERR_CAP_MASTER] = 0x7f4, +}; + static const int gisb_offsets_bcm7400[] = { [ARB_TIMER] = 0x00c, [ARB_ERR_CAP_CLR] = 0x0c8, @@ -307,6 +316,7 @@ static const struct of_device_id brcmstb_gisb_arb_of_match[] = { { .compatible = "brcm,bcm7445-gisb-arb", .data = gisb_offsets_bcm7445 }, { .compatible = "brcm,bcm7435-gisb-arb", .data = gisb_offsets_bcm7435 }, { .compatible = "brcm,bcm7400-gisb-arb", .data = gisb_offsets_bcm7400 }, + { .compatible = "brcm,bcm7278-gisb-arb", .data = gisb_offsets_bcm7278 }, { .compatible = "brcm,bcm7038-gisb-arb", .data = gisb_offsets_bcm7038 }, { }, }; -- cgit v1.2.3-59-g8ed1b