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+
3342enum {
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
4256static 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
5170static 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
6084static 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
6998static 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
78112static 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+
128177static 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