19
19
#include <linux/kernel.h>
20
20
#include <linux/module.h>
21
21
#include <linux/delay.h>
22
+ #include <linux/interrupt.h>
22
23
#include <linux/platform_device.h>
23
24
#include <linux/platform_data/b53.h>
24
25
#include <linux/of.h>
47
48
48
49
/* command and status register of the SRAB */
49
50
#define B53_SRAB_CTRLS 0x40
51
+ #define B53_SRAB_CTRLS_HOST_INTR BIT(1)
50
52
#define B53_SRAB_CTRLS_RCAREQ BIT(3)
51
53
#define B53_SRAB_CTRLS_RCAGNT BIT(4)
52
54
#define B53_SRAB_CTRLS_SW_INIT_DONE BIT(6)
60
62
#define B53_SRAB_P7_SLEEP_TIMER BIT(11)
61
63
#define B53_SRAB_IMP0_SLEEP_TIMER BIT(12)
62
64
65
+ struct b53_srab_port_priv {
66
+ int irq ;
67
+ bool irq_enabled ;
68
+ struct b53_device * dev ;
69
+ unsigned int num ;
70
+ };
71
+
63
72
struct b53_srab_priv {
64
73
void __iomem * regs ;
74
+ struct b53_srab_port_priv port_intrs [B53_N_PORTS ];
65
75
};
66
76
67
77
static int b53_srab_request_grant (struct b53_device * dev )
@@ -344,6 +354,49 @@ static int b53_srab_write64(struct b53_device *dev, u8 page, u8 reg,
344
354
return ret ;
345
355
}
346
356
357
+ static irqreturn_t b53_srab_port_thread (int irq , void * dev_id )
358
+ {
359
+ return IRQ_HANDLED ;
360
+ }
361
+
362
+ static irqreturn_t b53_srab_port_isr (int irq , void * dev_id )
363
+ {
364
+ struct b53_srab_port_priv * port = dev_id ;
365
+ struct b53_device * dev = port -> dev ;
366
+ struct b53_srab_priv * priv = dev -> priv ;
367
+
368
+ /* Acknowledge the interrupt */
369
+ writel (BIT (port -> num ), priv -> regs + B53_SRAB_INTR );
370
+
371
+ return IRQ_WAKE_THREAD ;
372
+ }
373
+
374
+ static int b53_srab_irq_enable (struct b53_device * dev , int port )
375
+ {
376
+ struct b53_srab_priv * priv = dev -> priv ;
377
+ struct b53_srab_port_priv * p = & priv -> port_intrs [port ];
378
+ int ret ;
379
+
380
+ ret = request_threaded_irq (p -> irq , b53_srab_port_isr ,
381
+ b53_srab_port_thread , 0 ,
382
+ dev_name (dev -> dev ), p );
383
+ if (!ret )
384
+ p -> irq_enabled = true;
385
+
386
+ return ret ;
387
+ }
388
+
389
+ static void b53_srab_irq_disable (struct b53_device * dev , int port )
390
+ {
391
+ struct b53_srab_priv * priv = dev -> priv ;
392
+ struct b53_srab_port_priv * p = & priv -> port_intrs [port ];
393
+
394
+ if (p -> irq_enabled ) {
395
+ free_irq (p -> irq , p );
396
+ p -> irq_enabled = false;
397
+ }
398
+ }
399
+
347
400
static const struct b53_io_ops b53_srab_ops = {
348
401
.read8 = b53_srab_read8 ,
349
402
.read16 = b53_srab_read16 ,
@@ -355,6 +408,8 @@ static const struct b53_io_ops b53_srab_ops = {
355
408
.write32 = b53_srab_write32 ,
356
409
.write48 = b53_srab_write48 ,
357
410
.write64 = b53_srab_write64 ,
411
+ .irq_enable = b53_srab_irq_enable ,
412
+ .irq_disable = b53_srab_irq_disable ,
358
413
};
359
414
360
415
static const struct of_device_id b53_srab_of_match [] = {
@@ -379,6 +434,52 @@ static const struct of_device_id b53_srab_of_match[] = {
379
434
};
380
435
MODULE_DEVICE_TABLE (of , b53_srab_of_match );
381
436
437
+ static void b53_srab_intr_set (struct b53_srab_priv * priv , bool set )
438
+ {
439
+ u32 reg ;
440
+
441
+ reg = readl (priv -> regs + B53_SRAB_CTRLS );
442
+ if (set )
443
+ reg |= B53_SRAB_CTRLS_HOST_INTR ;
444
+ else
445
+ reg &= ~B53_SRAB_CTRLS_HOST_INTR ;
446
+ writel (reg , priv -> regs + B53_SRAB_CTRLS );
447
+ }
448
+
449
+ static void b53_srab_prepare_irq (struct platform_device * pdev )
450
+ {
451
+ struct b53_device * dev = platform_get_drvdata (pdev );
452
+ struct b53_srab_priv * priv = dev -> priv ;
453
+ struct b53_srab_port_priv * port ;
454
+ unsigned int i ;
455
+ char * name ;
456
+
457
+ /* Clear all pending interrupts */
458
+ writel (0xffffffff , priv -> regs + B53_SRAB_INTR );
459
+
460
+ if (dev -> pdata && dev -> pdata -> chip_id != BCM58XX_DEVICE_ID )
461
+ return ;
462
+
463
+ for (i = 0 ; i < B53_N_PORTS ; i ++ ) {
464
+ port = & priv -> port_intrs [i ];
465
+
466
+ /* There is no port 6 */
467
+ if (i == 6 )
468
+ continue ;
469
+
470
+ name = kasprintf (GFP_KERNEL , "link_state_p%d" , i );
471
+ if (!name )
472
+ return ;
473
+
474
+ port -> num = i ;
475
+ port -> dev = dev ;
476
+ port -> irq = platform_get_irq_byname (pdev , name );
477
+ kfree (name );
478
+ }
479
+
480
+ b53_srab_intr_set (priv , true);
481
+ }
482
+
382
483
static int b53_srab_probe (struct platform_device * pdev )
383
484
{
384
485
struct b53_platform_data * pdata = pdev -> dev .platform_data ;
@@ -417,13 +518,17 @@ static int b53_srab_probe(struct platform_device *pdev)
417
518
418
519
platform_set_drvdata (pdev , dev );
419
520
521
+ b53_srab_prepare_irq (pdev );
522
+
420
523
return b53_switch_register (dev );
421
524
}
422
525
423
526
static int b53_srab_remove (struct platform_device * pdev )
424
527
{
425
528
struct b53_device * dev = platform_get_drvdata (pdev );
529
+ struct b53_srab_priv * priv = dev -> priv ;
426
530
531
+ b53_srab_intr_set (priv , false);
427
532
if (dev )
428
533
b53_switch_remove (dev );
429
534
0 commit comments