This pull request contains Broadcom ARM/ARM64 SoCs specific driver changes for

4.13, please pull the following:
 
 - Doug adds support for the latest generation GISB bus arbiter (v7), he starts by
   fixing two issues in how registers are written, and how 64-bit addresses are captured
   and then he simplifies the error interception by using notifiers, which allows him
   to add support for ARM64
 
 - Markus updates the SOC_BRCMSTB Kconfig depends to cover ARM64 and BMIPS_GENERIC
   systems where this code is now also used
 -----BEGIN PGP SIGNATURE-----
 
 iQIcBAABCAAGBQJZPs6qAAoJEIfQlpxEBwcE6y8QAOMSWs50jnXn5zJzYxXENsgo
 2tByeT/eQDkCyEvXPQ8igqqw/3eSuEJJZe0218MOo3aoAteBV2hzx0z59YNxL6nM
 oCO+p2WBNZ+LlIkewfGNWgmtd8nFqaH1nhm0Gg2lPhwgNikwDXRrfXcTu8ppJLzb
 V2CuDZh5ZGkL7QM6UMFeHiFW66mCcvhu/WanbrhLN8FgocHLjZKyVaduSvybQiF3
 I8afwCVzDq6Aa2lYxNKSeQm0ionhgyei3PcmiJAGSaVMYG0X7qJjKsaXltRe5lhn
 a2JUp+X0AhuV/Ulr6xCMD6j4DK8czK1Nsj4f2u5Ld0fg+yrCE0bjY1QY/nU7zjCt
 aeYbpeRXiU1T1YSdnx0YkDezSe63nO9Vrmsa9SQp23e1Z0MPoRMJeDOHJZ4LtQwt
 mkavMwj7f5P1NqDh5HrcAsga/4qmC0KUMmQTKBPze82nLuOoYjGWLroMEuALL5yI
 YfkAxBRQr2Ep7Bf5Ska2FDQqnkrv2T/gnMHTqJ6H1ciHsk3C/Z52Px8QZA5ZMjhf
 kELlrKjdVDr1Yldf2rmsOv7GMfPXod9r0G6fgsGrhyoiHVNaChdo78DtVg4ITY7v
 RHSXX/ehZmQpPokQOtguxgSmL5QksUDwTf1S2q3iaWaZdu7eZtkjOQe1AwYrnzse
 s5hQW4oVSEfgXuR66jPa
 =Skk5
 -----END PGP SIGNATURE-----

Merge tag 'arm-soc/for-4.13/drivers' of http://github.com/Broadcom/stblinux into next/drivers

This pull request contains Broadcom ARM/ARM64 SoCs specific driver changes for
4.13, please pull the following:

- Doug adds support for the latest generation GISB bus arbiter (v7), he starts by
  fixing two issues in how registers are written, and how 64-bit addresses are captured
  and then he simplifies the error interception by using notifiers, which allows him
  to add support for ARM64

- Markus updates the SOC_BRCMSTB Kconfig depends to cover ARM64 and BMIPS_GENERIC
  systems where this code is now also used

* tag 'arm-soc/for-4.13/drivers' of http://github.com/Broadcom/stblinux:
  soc: brcmstb: enable drivers for ARM64 and BMIPS
  bus: brcmstb_gisb: update to support new revision
  bus: brcmstb_gisb: enable driver for ARM64 architecture
  bus: brcmstb_gisb: remove low-level ARM hooks
  bus: brcmstb_gisb: add notifier handling
  bus: brcmstb_gisb: correct support for 64-bit address output
  bus: brcmstb_gisb: Use register offsets with writes too

Signed-off-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
Olof Johansson 2017-06-18 20:30:52 -07:00
Родитель 7a699a85e1 1f6ab20f55
Коммит 8c2f8a2fb1
4 изменённых файлов: 76 добавлений и 52 удалений

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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
@ -24,11 +24,9 @@
#include <linux/of.h>
#include <linux/bitops.h>
#include <linux/pm.h>
#ifdef CONFIG_ARM
#include <asm/bug.h>
#include <asm/signal.h>
#endif
#include <linux/kernel.h>
#include <linux/kdebug.h>
#include <linux/notifier.h>
#ifdef CONFIG_MIPS
#include <asm/traps.h>
@ -37,8 +35,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 +43,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,17 +52,24 @@ 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,
};
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,
[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 +79,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 +88,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 +109,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 +123,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];
@ -127,9 +141,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,
@ -185,7 +199,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 +211,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 +220,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" : "",
@ -221,27 +232,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)
{
@ -279,6 +269,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);
@ -296,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 },
{ },
};
@ -378,14 +399,16 @@ 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
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);

Просмотреть файл

@ -11,7 +11,7 @@ config RASPBERRYPI_POWER
config SOC_BRCMSTB
bool "Broadcom STB SoC drivers"
depends on ARM
depends on ARM || ARM64 || BMIPS_GENERIC || COMPILE_TEST
select SOC_BUS
help
Enables drivers for the Broadcom Set-Top Box (STB) series of chips.