1 /*
2  * Portions copyright (C) 2005-2009 Scientific Atlanta
3  * Portions copyright (C) 2009 Cisco Systems, Inc.
4  *
5  * Modified from arch/mips/kernel/irq-rm7000.c:
6  * Copyright (C) 2003 Ralf Baechle
7  *
8  * This program is free software; you can redistribute  it and/or modify it
9  * under  the terms of  the GNU General  Public License as published by the
10  * Free Software Foundation;  either version 2 of the  License, or (at your
11  * option) any later version.
12  */
13 #include <linux/init.h>
14 #include <linux/interrupt.h>
15 #include <linux/kernel.h>
16 #include <linux/irq.h>
17 
18 #include <asm/irq_cpu.h>
19 #include <asm/mipsregs.h>
20 #include <asm/system.h>
21 
22 #include <asm/mach-powertv/asic_regs.h>
23 
unmask_asic_irq(struct irq_data * d)24 static inline void unmask_asic_irq(struct irq_data *d)
25 {
26 	unsigned long enable_bit;
27 	unsigned int irq = d->irq;
28 
29 	enable_bit = (1 << (irq & 0x1f));
30 
31 	switch (irq >> 5) {
32 	case 0:
33 		asic_write(asic_read(ien_int_0) | enable_bit, ien_int_0);
34 		break;
35 	case 1:
36 		asic_write(asic_read(ien_int_1) | enable_bit, ien_int_1);
37 		break;
38 	case 2:
39 		asic_write(asic_read(ien_int_2) | enable_bit, ien_int_2);
40 		break;
41 	case 3:
42 		asic_write(asic_read(ien_int_3) | enable_bit, ien_int_3);
43 		break;
44 	default:
45 		BUG();
46 	}
47 }
48 
mask_asic_irq(struct irq_data * d)49 static inline void mask_asic_irq(struct irq_data *d)
50 {
51 	unsigned long disable_mask;
52 	unsigned int irq = d->irq;
53 
54 	disable_mask = ~(1 << (irq & 0x1f));
55 
56 	switch (irq >> 5) {
57 	case 0:
58 		asic_write(asic_read(ien_int_0) & disable_mask, ien_int_0);
59 		break;
60 	case 1:
61 		asic_write(asic_read(ien_int_1) & disable_mask, ien_int_1);
62 		break;
63 	case 2:
64 		asic_write(asic_read(ien_int_2) & disable_mask, ien_int_2);
65 		break;
66 	case 3:
67 		asic_write(asic_read(ien_int_3) & disable_mask, ien_int_3);
68 		break;
69 	default:
70 		BUG();
71 	}
72 }
73 
74 static struct irq_chip asic_irq_chip = {
75 	.name = "ASIC Level",
76 	.irq_mask = mask_asic_irq,
77 	.irq_unmask = unmask_asic_irq,
78 };
79 
asic_irq_init(void)80 void __init asic_irq_init(void)
81 {
82 	int i;
83 
84 	/* set priority to 0 */
85 	write_c0_status(read_c0_status() & ~(0x0000fc00));
86 
87 	asic_write(0, ien_int_0);
88 	asic_write(0, ien_int_1);
89 	asic_write(0, ien_int_2);
90 	asic_write(0, ien_int_3);
91 
92 	asic_write(0x0fffffff, int_level_3_3);
93 	asic_write(0xffffffff, int_level_3_2);
94 	asic_write(0xffffffff, int_level_3_1);
95 	asic_write(0xffffffff, int_level_3_0);
96 	asic_write(0xffffffff, int_level_2_3);
97 	asic_write(0xffffffff, int_level_2_2);
98 	asic_write(0xffffffff, int_level_2_1);
99 	asic_write(0xffffffff, int_level_2_0);
100 	asic_write(0xffffffff, int_level_1_3);
101 	asic_write(0xffffffff, int_level_1_2);
102 	asic_write(0xffffffff, int_level_1_1);
103 	asic_write(0xffffffff, int_level_1_0);
104 	asic_write(0xffffffff, int_level_0_3);
105 	asic_write(0xffffffff, int_level_0_2);
106 	asic_write(0xffffffff, int_level_0_1);
107 	asic_write(0xffffffff, int_level_0_0);
108 
109 	asic_write(0xf, int_int_scan);
110 
111 	/*
112 	 * Initialize interrupt handlers.
113 	 */
114 	for (i = 0; i < NR_IRQS; i++)
115 		irq_set_chip_and_handler(i, &asic_irq_chip, handle_level_irq);
116 }
117