aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/irqchip
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/irqchip')
-rw-r--r--drivers/irqchip/spear-shirq.c97
1 files changed, 45 insertions, 52 deletions
diff --git a/drivers/irqchip/spear-shirq.c b/drivers/irqchip/spear-shirq.c
index 8765aa7f7a15..169ef9a385d0 100644
--- a/drivers/irqchip/spear-shirq.c
+++ b/drivers/irqchip/spear-shirq.c
@@ -49,7 +49,8 @@ struct shirq_regs {
49 * virq_base: Base virtual interrupt number 49 * virq_base: Base virtual interrupt number
50 * nr_irqs: Number of interrupts handled by this block 50 * nr_irqs: Number of interrupts handled by this block
51 * offset: Bit offset of the first interrupt 51 * offset: Bit offset of the first interrupt
52 * disabled: Group is disabled, but accounted 52 * irq_chip: Interrupt controller chip used for this instance,
53 * if NULL group is disabled, but accounted
53 */ 54 */
54struct spear_shirq { 55struct spear_shirq {
55 void __iomem *base; 56 void __iomem *base;
@@ -58,19 +59,50 @@ struct spear_shirq {
58 u32 virq_base; 59 u32 virq_base;
59 u32 nr_irqs; 60 u32 nr_irqs;
60 u32 offset; 61 u32 offset;
61 bool disabled; 62 struct irq_chip *irq_chip;
62}; 63};
63 64
64static DEFINE_SPINLOCK(lock);
65
66/* spear300 shared irq registers offsets and masks */ 65/* spear300 shared irq registers offsets and masks */
67#define SPEAR300_INT_ENB_MASK_REG 0x54 66#define SPEAR300_INT_ENB_MASK_REG 0x54
68#define SPEAR300_INT_STS_MASK_REG 0x58 67#define SPEAR300_INT_STS_MASK_REG 0x58
69 68
69static DEFINE_RAW_SPINLOCK(shirq_lock);
70
71static void shirq_irq_mask(struct irq_data *d)
72{
73 struct spear_shirq *shirq = irq_data_get_irq_chip_data(d);
74 u32 val, shift = d->irq - shirq->virq_base + shirq->offset;
75 u32 __iomem *reg = shirq->base + shirq->regs.enb_reg;
76
77 raw_spin_lock(&shirq_lock);
78 val = readl(reg) & ~(0x1 << shift);
79 writel(val, reg);
80 raw_spin_unlock(&shirq_lock);
81}
82
83static void shirq_irq_unmask(struct irq_data *d)
84{
85 struct spear_shirq *shirq = irq_data_get_irq_chip_data(d);
86 u32 val, shift = d->irq - shirq->virq_base + shirq->offset;
87 u32 __iomem *reg = shirq->base + shirq->regs.enb_reg;
88
89 raw_spin_lock(&shirq_lock);
90 val = readl(reg) | (0x1 << shift);
91 writel(val, reg);
92 raw_spin_unlock(&shirq_lock);
93}
94
95static struct irq_chip shirq_chip = {
96 .name = "spear-shirq",
97 .irq_mask = shirq_irq_mask,
98 .irq_unmask = shirq_irq_unmask,
99};
100
70static struct spear_shirq spear300_shirq_ras1 = { 101static struct spear_shirq spear300_shirq_ras1 = {
71 .offset = 0, 102 .offset = 0,
72 .nr_irqs = 9, 103 .nr_irqs = 9,
73 .mask = ((0x1 << 9) - 1) << 0, 104 .mask = ((0x1 << 9) - 1) << 0,
105 .irq_chip = &shirq_chip,
74 .regs = { 106 .regs = {
75 .enb_reg = SPEAR300_INT_ENB_MASK_REG, 107 .enb_reg = SPEAR300_INT_ENB_MASK_REG,
76 .status_reg = SPEAR300_INT_STS_MASK_REG, 108 .status_reg = SPEAR300_INT_STS_MASK_REG,
@@ -88,8 +120,8 @@ static struct spear_shirq spear310_shirq_ras1 = {
88 .offset = 0, 120 .offset = 0,
89 .nr_irqs = 8, 121 .nr_irqs = 8,
90 .mask = ((0x1 << 8) - 1) << 0, 122 .mask = ((0x1 << 8) - 1) << 0,
123 .irq_chip = &dummy_irq_chip,
91 .regs = { 124 .regs = {
92 .enb_reg = -1,
93 .status_reg = SPEAR310_INT_STS_MASK_REG, 125 .status_reg = SPEAR310_INT_STS_MASK_REG,
94 }, 126 },
95}; 127};
@@ -98,6 +130,7 @@ static struct spear_shirq spear310_shirq_ras2 = {
98 .offset = 8, 130 .offset = 8,
99 .nr_irqs = 5, 131 .nr_irqs = 5,
100 .mask = ((0x1 << 5) - 1) << 8, 132 .mask = ((0x1 << 5) - 1) << 8,
133 .irq_chip = &dummy_irq_chip,
101 .regs = { 134 .regs = {
102 .enb_reg = -1, 135 .enb_reg = -1,
103 .status_reg = SPEAR310_INT_STS_MASK_REG, 136 .status_reg = SPEAR310_INT_STS_MASK_REG,
@@ -108,8 +141,8 @@ static struct spear_shirq spear310_shirq_ras3 = {
108 .offset = 13, 141 .offset = 13,
109 .nr_irqs = 1, 142 .nr_irqs = 1,
110 .mask = ((0x1 << 1) - 1) << 13, 143 .mask = ((0x1 << 1) - 1) << 13,
144 .irq_chip = &dummy_irq_chip,
111 .regs = { 145 .regs = {
112 .enb_reg = -1,
113 .status_reg = SPEAR310_INT_STS_MASK_REG, 146 .status_reg = SPEAR310_INT_STS_MASK_REG,
114 }, 147 },
115}; 148};
@@ -118,8 +151,8 @@ static struct spear_shirq spear310_shirq_intrcomm_ras = {
118 .offset = 14, 151 .offset = 14,
119 .nr_irqs = 3, 152 .nr_irqs = 3,
120 .mask = ((0x1 << 3) - 1) << 14, 153 .mask = ((0x1 << 3) - 1) << 14,
154 .irq_chip = &dummy_irq_chip,
121 .regs = { 155 .regs = {
122 .enb_reg = -1,
123 .status_reg = SPEAR310_INT_STS_MASK_REG, 156 .status_reg = SPEAR310_INT_STS_MASK_REG,
124 }, 157 },
125}; 158};
@@ -140,15 +173,14 @@ static struct spear_shirq spear320_shirq_ras3 = {
140 .offset = 0, 173 .offset = 0,
141 .nr_irqs = 7, 174 .nr_irqs = 7,
142 .mask = ((0x1 << 7) - 1) << 0, 175 .mask = ((0x1 << 7) - 1) << 0,
143 .disabled = 1,
144}; 176};
145 177
146static struct spear_shirq spear320_shirq_ras1 = { 178static struct spear_shirq spear320_shirq_ras1 = {
147 .offset = 7, 179 .offset = 7,
148 .nr_irqs = 3, 180 .nr_irqs = 3,
149 .mask = ((0x1 << 3) - 1) << 7, 181 .mask = ((0x1 << 3) - 1) << 7,
182 .irq_chip = &dummy_irq_chip,
150 .regs = { 183 .regs = {
151 .enb_reg = -1,
152 .status_reg = SPEAR320_INT_STS_MASK_REG, 184 .status_reg = SPEAR320_INT_STS_MASK_REG,
153 }, 185 },
154}; 186};
@@ -157,8 +189,8 @@ static struct spear_shirq spear320_shirq_ras2 = {
157 .offset = 10, 189 .offset = 10,
158 .nr_irqs = 1, 190 .nr_irqs = 1,
159 .mask = ((0x1 << 1) - 1) << 10, 191 .mask = ((0x1 << 1) - 1) << 10,
192 .irq_chip = &dummy_irq_chip,
160 .regs = { 193 .regs = {
161 .enb_reg = -1,
162 .status_reg = SPEAR320_INT_STS_MASK_REG, 194 .status_reg = SPEAR320_INT_STS_MASK_REG,
163 }, 195 },
164}; 196};
@@ -167,8 +199,8 @@ static struct spear_shirq spear320_shirq_intrcomm_ras = {
167 .offset = 11, 199 .offset = 11,
168 .nr_irqs = 11, 200 .nr_irqs = 11,
169 .mask = ((0x1 << 11) - 1) << 11, 201 .mask = ((0x1 << 11) - 1) << 11,
202 .irq_chip = &dummy_irq_chip,
170 .regs = { 203 .regs = {
171 .enb_reg = -1,
172 .status_reg = SPEAR320_INT_STS_MASK_REG, 204 .status_reg = SPEAR320_INT_STS_MASK_REG,
173 }, 205 },
174}; 206};
@@ -180,45 +212,6 @@ static struct spear_shirq *spear320_shirq_blocks[] = {
180 &spear320_shirq_intrcomm_ras, 212 &spear320_shirq_intrcomm_ras,
181}; 213};
182 214
183static void shirq_irq_mask_unmask(struct irq_data *d, bool mask)
184{
185 struct spear_shirq *shirq = irq_data_get_irq_chip_data(d);
186 u32 val, offset = d->irq - shirq->virq_base;
187 unsigned long flags;
188
189 if (shirq->regs.enb_reg == -1)
190 return;
191
192 spin_lock_irqsave(&lock, flags);
193 val = readl(shirq->base + shirq->regs.enb_reg);
194
195 if (mask ^ shirq->regs.reset_to_enb)
196 val &= ~(0x1 << shirq->offset << offset);
197 else
198 val |= 0x1 << shirq->offset << offset;
199
200 writel(val, shirq->base + shirq->regs.enb_reg);
201 spin_unlock_irqrestore(&lock, flags);
202
203}
204
205static void shirq_irq_mask(struct irq_data *d)
206{
207 shirq_irq_mask_unmask(d, 1);
208}
209
210static void shirq_irq_unmask(struct irq_data *d)
211{
212 shirq_irq_mask_unmask(d, 0);
213}
214
215static struct irq_chip shirq_chip = {
216 .name = "spear-shirq",
217 .irq_ack = shirq_irq_mask,
218 .irq_mask = shirq_irq_mask,
219 .irq_unmask = shirq_irq_unmask,
220};
221
222static void shirq_handler(unsigned irq, struct irq_desc *desc) 215static void shirq_handler(unsigned irq, struct irq_desc *desc)
223{ 216{
224 struct spear_shirq *shirq = irq_get_handler_data(irq); 217 struct spear_shirq *shirq = irq_get_handler_data(irq);
@@ -240,7 +233,7 @@ static void __init spear_shirq_register(struct spear_shirq *shirq,
240{ 233{
241 int i; 234 int i;
242 235
243 if (shirq->disabled) 236 if (!shirq->irq_chip)
244 return; 237 return;
245 238
246 irq_set_chained_handler(parent_irq, shirq_handler); 239 irq_set_chained_handler(parent_irq, shirq_handler);
@@ -248,7 +241,7 @@ static void __init spear_shirq_register(struct spear_shirq *shirq,
248 241
249 for (i = 0; i < shirq->nr_irqs; i++) { 242 for (i = 0; i < shirq->nr_irqs; i++) {
250 irq_set_chip_and_handler(shirq->virq_base + i, 243 irq_set_chip_and_handler(shirq->virq_base + i,
251 &shirq_chip, handle_simple_irq); 244 shirq->irq_chip, handle_simple_irq);
252 set_irq_flags(shirq->virq_base + i, IRQF_VALID); 245 set_irq_flags(shirq->virq_base + i, IRQF_VALID);
253 irq_set_chip_data(shirq->virq_base + i, shirq); 246 irq_set_chip_data(shirq->virq_base + i, shirq);
254 } 247 }