Skip to content

Commit fb8a0b8

Browse files
committed
bus: brcmstb_gisb: Add support for breakpoint interrupts
GISB breakpoint interrupts can be raised when a breakpoint has been enabled to match a specific master and/or GISB register address. Being able to print a message, similar to those done during target abort or timeout greatly helps debug systems. Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
1 parent 541b6e6 commit fb8a0b8

1 file changed

Lines changed: 95 additions & 1 deletion

File tree

drivers/bus/brcmstb_gisb.c

Lines changed: 95 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,22 @@
3030
#define ARB_ERR_CAP_STATUS_WRITE (1 << 1)
3131
#define ARB_ERR_CAP_STATUS_VALID (1 << 0)
3232

33+
#define ARB_BP_CAP_CLEAR (1 << 0)
34+
#define ARB_BP_CAP_STATUS_PROT_SHIFT 14
35+
#define ARB_BP_CAP_STATUS_TYPE (1 << 13)
36+
#define ARB_BP_CAP_STATUS_RSP_SHIFT 10
37+
#define ARB_BP_CAP_STATUS_MASK GENMASK(1, 0)
38+
#define ARB_BP_CAP_STATUS_BS_SHIFT 2
39+
#define ARB_BP_CAP_STATUS_WRITE (1 << 1)
40+
#define ARB_BP_CAP_STATUS_VALID (1 << 0)
41+
3342
enum {
3443
ARB_TIMER,
44+
ARB_BP_CAP_CLR,
45+
ARB_BP_CAP_HI_ADDR,
46+
ARB_BP_CAP_ADDR,
47+
ARB_BP_CAP_STATUS,
48+
ARB_BP_CAP_MASTER,
3549
ARB_ERR_CAP_CLR,
3650
ARB_ERR_CAP_HI_ADDR,
3751
ARB_ERR_CAP_ADDR,
@@ -41,6 +55,11 @@ enum {
4155

4256
static const int gisb_offsets_bcm7038[] = {
4357
[ARB_TIMER] = 0x00c,
58+
[ARB_BP_CAP_CLR] = 0x014,
59+
[ARB_BP_CAP_HI_ADDR] = -1,
60+
[ARB_BP_CAP_ADDR] = 0x0b8,
61+
[ARB_BP_CAP_STATUS] = 0x0c0,
62+
[ARB_BP_CAP_MASTER] = -1,
4463
[ARB_ERR_CAP_CLR] = 0x0c4,
4564
[ARB_ERR_CAP_HI_ADDR] = -1,
4665
[ARB_ERR_CAP_ADDR] = 0x0c8,
@@ -50,6 +69,11 @@ static const int gisb_offsets_bcm7038[] = {
5069

5170
static const int gisb_offsets_bcm7278[] = {
5271
[ARB_TIMER] = 0x008,
72+
[ARB_BP_CAP_CLR] = 0x01c,
73+
[ARB_BP_CAP_HI_ADDR] = -1,
74+
[ARB_BP_CAP_ADDR] = 0x220,
75+
[ARB_BP_CAP_STATUS] = 0x230,
76+
[ARB_BP_CAP_MASTER] = 0x234,
5377
[ARB_ERR_CAP_CLR] = 0x7f8,
5478
[ARB_ERR_CAP_HI_ADDR] = -1,
5579
[ARB_ERR_CAP_ADDR] = 0x7e0,
@@ -59,6 +83,11 @@ static const int gisb_offsets_bcm7278[] = {
5983

6084
static const int gisb_offsets_bcm7400[] = {
6185
[ARB_TIMER] = 0x00c,
86+
[ARB_BP_CAP_CLR] = 0x014,
87+
[ARB_BP_CAP_HI_ADDR] = -1,
88+
[ARB_BP_CAP_ADDR] = 0x0b8,
89+
[ARB_BP_CAP_STATUS] = 0x0c0,
90+
[ARB_BP_CAP_MASTER] = 0x0c4,
6291
[ARB_ERR_CAP_CLR] = 0x0c8,
6392
[ARB_ERR_CAP_HI_ADDR] = -1,
6493
[ARB_ERR_CAP_ADDR] = 0x0cc,
@@ -68,6 +97,11 @@ static const int gisb_offsets_bcm7400[] = {
6897

6998
static const int gisb_offsets_bcm7435[] = {
7099
[ARB_TIMER] = 0x00c,
100+
[ARB_BP_CAP_CLR] = 0x014,
101+
[ARB_BP_CAP_HI_ADDR] = -1,
102+
[ARB_BP_CAP_ADDR] = 0x158,
103+
[ARB_BP_CAP_STATUS] = 0x160,
104+
[ARB_BP_CAP_MASTER] = 0x164,
71105
[ARB_ERR_CAP_CLR] = 0x168,
72106
[ARB_ERR_CAP_HI_ADDR] = -1,
73107
[ARB_ERR_CAP_ADDR] = 0x16c,
@@ -77,6 +111,11 @@ static const int gisb_offsets_bcm7435[] = {
77111

78112
static const int gisb_offsets_bcm7445[] = {
79113
[ARB_TIMER] = 0x008,
114+
[ARB_BP_CAP_CLR] = 0x010,
115+
[ARB_BP_CAP_HI_ADDR] = -1,
116+
[ARB_BP_CAP_ADDR] = 0x1d8,
117+
[ARB_BP_CAP_STATUS] = 0x1e0,
118+
[ARB_BP_CAP_MASTER] = 0x1e4,
80119
[ARB_ERR_CAP_CLR] = 0x7e4,
81120
[ARB_ERR_CAP_HI_ADDR] = 0x7e8,
82121
[ARB_ERR_CAP_ADDR] = 0x7ec,
@@ -125,6 +164,16 @@ static u64 gisb_read_address(struct brcmstb_gisb_arb_device *gdev)
125164
return value;
126165
}
127166

167+
static u64 gisb_read_bp_address(struct brcmstb_gisb_arb_device *gdev)
168+
{
169+
u64 value;
170+
171+
value = gisb_read(gdev, ARB_BP_CAP_ADDR);
172+
value |= (u64)gisb_read(gdev, ARB_BP_CAP_HI_ADDR) << 32;
173+
174+
return value;
175+
}
176+
128177
static void gisb_write(struct brcmstb_gisb_arb_device *gdev, u32 val, int reg)
129178
{
130179
int offset = gdev->gisb_offsets[reg];
@@ -259,6 +308,41 @@ static irqreturn_t brcmstb_gisb_tea_handler(int irq, void *dev_id)
259308
return IRQ_HANDLED;
260309
}
261310

311+
static irqreturn_t brcmstb_gisb_bp_handler(int irq, void *dev_id)
312+
{
313+
struct brcmstb_gisb_arb_device *gdev = dev_id;
314+
const char *m_name;
315+
u32 bp_status;
316+
u64 arb_addr;
317+
u32 master;
318+
char m_fmt[11];
319+
320+
bp_status = gisb_read(gdev, ARB_BP_CAP_STATUS);
321+
322+
/* Invalid captured address, bail out */
323+
if (!(bp_status & ARB_BP_CAP_STATUS_VALID))
324+
return IRQ_HANDLED;
325+
326+
/* Read the address and master */
327+
arb_addr = gisb_read_bp_address(gdev);
328+
master = gisb_read(gdev, ARB_BP_CAP_MASTER);
329+
330+
m_name = brcmstb_gisb_master_to_str(gdev, master);
331+
if (!m_name) {
332+
snprintf(m_fmt, sizeof(m_fmt), "0x%08x", master);
333+
m_name = m_fmt;
334+
}
335+
336+
pr_crit("GISB: breakpoint at 0x%llx [%c], core: %s\n",
337+
arb_addr, bp_status & ARB_BP_CAP_STATUS_WRITE ? 'W' : 'R',
338+
m_name);
339+
340+
/* clear the GISB error */
341+
gisb_write(gdev, ARB_ERR_CAP_CLEAR, ARB_ERR_CAP_CLR);
342+
343+
return IRQ_HANDLED;
344+
}
345+
262346
/*
263347
* Dump out gisb errors on die or panic.
264348
*/
@@ -317,13 +401,14 @@ static int __init brcmstb_gisb_arb_probe(struct platform_device *pdev)
317401
struct brcmstb_gisb_arb_device *gdev;
318402
const struct of_device_id *of_id;
319403
struct resource *r;
320-
int err, timeout_irq, tea_irq;
404+
int err, timeout_irq, tea_irq, bp_irq;
321405
unsigned int num_masters, j = 0;
322406
int i, first, last;
323407

324408
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
325409
timeout_irq = platform_get_irq(pdev, 0);
326410
tea_irq = platform_get_irq(pdev, 1);
411+
bp_irq = platform_get_irq(pdev, 2);
327412

328413
gdev = devm_kzalloc(&pdev->dev, sizeof(*gdev), GFP_KERNEL);
329414
if (!gdev)
@@ -356,6 +441,15 @@ static int __init brcmstb_gisb_arb_probe(struct platform_device *pdev)
356441
if (err < 0)
357442
return err;
358443

444+
/* Interrupt is optional */
445+
if (bp_irq > 0) {
446+
err = devm_request_irq(&pdev->dev, bp_irq,
447+
brcmstb_gisb_bp_handler, 0, pdev->name,
448+
gdev);
449+
if (err < 0)
450+
return err;
451+
}
452+
359453
/* If we do not have a valid mask, assume all masters are enabled */
360454
if (of_property_read_u32(dn, "brcm,gisb-arb-master-mask",
361455
&gdev->valid_mask))

0 commit comments

Comments
 (0)