Blame view

drivers/irqchip/irq-mmp.c 13.4 KB
c24b31147   Haojian Zhuang   ARM: mmp: support...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  /*
   *  linux/arch/arm/mach-mmp/irq.c
   *
   *  Generic IRQ handling, GPIO IRQ demultiplexing, etc.
   *  Copyright (C) 2008 - 2012 Marvell Technology Group Ltd.
   *
   *  Author:	Bin Yang <bin.yang@marvell.com>
   *              Haojian Zhuang <haojian.zhuang@gmail.com>
   *
   *  This program is free software; you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License version 2 as
   *  published by the Free Software Foundation.
   */
  
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/irq.h>
41a83e06e   Joel Porquet   irqchip: Prepare ...
18
  #include <linux/irqchip.h>
c24b31147   Haojian Zhuang   ARM: mmp: support...
19
20
21
22
23
  #include <linux/irqdomain.h>
  #include <linux/io.h>
  #include <linux/ioport.h>
  #include <linux/of_address.h>
  #include <linux/of_irq.h>
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
24
  #include <asm/exception.h>
13dde8182   Neil Zhang   irqchip: mmp: avo...
25
  #include <asm/hardirq.h>
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
26

c24b31147   Haojian Zhuang   ARM: mmp: support...
27
  #define MAX_ICU_NR		16
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
28
29
30
31
32
33
  #define PJ1_INT_SEL		0x10c
  #define PJ4_INT_SEL		0x104
  
  /* bit fields in PJ1_INT_SEL and PJ4_INT_SEL */
  #define SEL_INT_PENDING		(1 << 6)
  #define SEL_INT_NUM_MASK	0x3f
1bf791023   Lubomir Rintel   irqchip/mmp: Only...
34
35
  #define MMP2_ICU_INT_ROUTE_PJ4_IRQ	(1 << 5)
  #define MMP2_ICU_INT_ROUTE_PJ4_FIQ	(1 << 6)
c24b31147   Haojian Zhuang   ARM: mmp: support...
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
  struct icu_chip_data {
  	int			nr_irqs;
  	unsigned int		virq_base;
  	unsigned int		cascade_irq;
  	void __iomem		*reg_status;
  	void __iomem		*reg_mask;
  	unsigned int		conf_enable;
  	unsigned int		conf_disable;
  	unsigned int		conf_mask;
  	unsigned int		clr_mfp_irq_base;
  	unsigned int		clr_mfp_hwirq;
  	struct irq_domain	*domain;
  };
  
  struct mmp_intc_conf {
  	unsigned int	conf_enable;
  	unsigned int	conf_disable;
  	unsigned int	conf_mask;
  };
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
55
  static void __iomem *mmp_icu_base;
c24b31147   Haojian Zhuang   ARM: mmp: support...
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
  static struct icu_chip_data icu_data[MAX_ICU_NR];
  static int max_icu_nr;
  
  extern void mmp2_clear_pmic_int(void);
  
  static void icu_mask_ack_irq(struct irq_data *d)
  {
  	struct irq_domain *domain = d->domain;
  	struct icu_chip_data *data = (struct icu_chip_data *)domain->host_data;
  	int hwirq;
  	u32 r;
  
  	hwirq = d->irq - data->virq_base;
  	if (data == &icu_data[0]) {
  		r = readl_relaxed(mmp_icu_base + (hwirq << 2));
  		r &= ~data->conf_mask;
  		r |= data->conf_disable;
  		writel_relaxed(r, mmp_icu_base + (hwirq << 2));
  	} else {
  #ifdef CONFIG_CPU_MMP2
  		if ((data->virq_base == data->clr_mfp_irq_base)
  			&& (hwirq == data->clr_mfp_hwirq))
  			mmp2_clear_pmic_int();
  #endif
  		r = readl_relaxed(data->reg_mask) | (1 << hwirq);
  		writel_relaxed(r, data->reg_mask);
  	}
  }
  
  static void icu_mask_irq(struct irq_data *d)
  {
  	struct irq_domain *domain = d->domain;
  	struct icu_chip_data *data = (struct icu_chip_data *)domain->host_data;
  	int hwirq;
  	u32 r;
  
  	hwirq = d->irq - data->virq_base;
  	if (data == &icu_data[0]) {
  		r = readl_relaxed(mmp_icu_base + (hwirq << 2));
  		r &= ~data->conf_mask;
  		r |= data->conf_disable;
  		writel_relaxed(r, mmp_icu_base + (hwirq << 2));
  	} else {
  		r = readl_relaxed(data->reg_mask) | (1 << hwirq);
  		writel_relaxed(r, data->reg_mask);
  	}
  }
  
  static void icu_unmask_irq(struct irq_data *d)
  {
  	struct irq_domain *domain = d->domain;
  	struct icu_chip_data *data = (struct icu_chip_data *)domain->host_data;
  	int hwirq;
  	u32 r;
  
  	hwirq = d->irq - data->virq_base;
  	if (data == &icu_data[0]) {
  		r = readl_relaxed(mmp_icu_base + (hwirq << 2));
  		r &= ~data->conf_mask;
  		r |= data->conf_enable;
  		writel_relaxed(r, mmp_icu_base + (hwirq << 2));
  	} else {
  		r = readl_relaxed(data->reg_mask) & ~(1 << hwirq);
  		writel_relaxed(r, data->reg_mask);
  	}
  }
0f102b6cc   Haojian Zhuang   ARM: mmp: avoid t...
122
  struct irq_chip icu_irq_chip = {
c24b31147   Haojian Zhuang   ARM: mmp: support...
123
124
125
126
127
  	.name		= "icu_irq",
  	.irq_mask	= icu_mask_irq,
  	.irq_mask_ack	= icu_mask_ack_irq,
  	.irq_unmask	= icu_unmask_irq,
  };
bd0b9ac40   Thomas Gleixner   genirq: Remove ir...
128
  static void icu_mux_irq_demux(struct irq_desc *desc)
c24b31147   Haojian Zhuang   ARM: mmp: support...
129
  {
14873aa1d   Thomas Gleixner   irqchip/mmp: Prep...
130
  	unsigned int irq = irq_desc_get_irq(desc);
c24b31147   Haojian Zhuang   ARM: mmp: support...
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
  	struct irq_domain *domain;
  	struct icu_chip_data *data;
  	int i;
  	unsigned long mask, status, n;
  
  	for (i = 1; i < max_icu_nr; i++) {
  		if (irq == icu_data[i].cascade_irq) {
  			domain = icu_data[i].domain;
  			data = (struct icu_chip_data *)domain->host_data;
  			break;
  		}
  	}
  	if (i >= max_icu_nr) {
  		pr_err("Spurious irq %d in MMP INTC
  ", irq);
  		return;
  	}
  
  	mask = readl_relaxed(data->reg_mask);
  	while (1) {
  		status = readl_relaxed(data->reg_status) & ~mask;
  		if (status == 0)
  			break;
93d429a77   Wei Yongjun   ARM: mmp: using f...
154
  		for_each_set_bit(n, &status, BITS_PER_LONG) {
c24b31147   Haojian Zhuang   ARM: mmp: support...
155
  			generic_handle_irq(icu_data[i].virq_base + n);
c24b31147   Haojian Zhuang   ARM: mmp: support...
156
157
158
159
160
161
162
163
  		}
  	}
  }
  
  static int mmp_irq_domain_map(struct irq_domain *d, unsigned int irq,
  			      irq_hw_number_t hw)
  {
  	irq_set_chip_and_handler(irq, &icu_irq_chip, handle_level_irq);
c24b31147   Haojian Zhuang   ARM: mmp: support...
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
  	return 0;
  }
  
  static int mmp_irq_domain_xlate(struct irq_domain *d, struct device_node *node,
  				const u32 *intspec, unsigned int intsize,
  				unsigned long *out_hwirq,
  				unsigned int *out_type)
  {
  	*out_hwirq = intspec[0];
  	return 0;
  }
  
  const struct irq_domain_ops mmp_irq_domain_ops = {
  	.map		= mmp_irq_domain_map,
  	.xlate		= mmp_irq_domain_xlate,
  };
c8c7d93dc   Bhumika Goyal   irqchip/mmp: Make...
180
  static const struct mmp_intc_conf mmp_conf = {
c24b31147   Haojian Zhuang   ARM: mmp: support...
181
182
183
184
  	.conf_enable	= 0x51,
  	.conf_disable	= 0x0,
  	.conf_mask	= 0x7f,
  };
c8c7d93dc   Bhumika Goyal   irqchip/mmp: Make...
185
  static const struct mmp_intc_conf mmp2_conf = {
c24b31147   Haojian Zhuang   ARM: mmp: support...
186
187
  	.conf_enable	= 0x20,
  	.conf_disable	= 0x0,
1bf791023   Lubomir Rintel   irqchip/mmp: Only...
188
189
  	.conf_mask	= MMP2_ICU_INT_ROUTE_PJ4_IRQ |
  			  MMP2_ICU_INT_ROUTE_PJ4_FIQ,
c24b31147   Haojian Zhuang   ARM: mmp: support...
190
  };
8783dd3a3   Stephen Boyd   irqchip: Remove a...
191
  static void __exception_irq_entry mmp_handle_irq(struct pt_regs *regs)
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
192
  {
b918402c8   Marc Zyngier   irqchip: mmp: Con...
193
  	int hwirq;
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
194
195
196
197
198
  
  	hwirq = readl_relaxed(mmp_icu_base + PJ1_INT_SEL);
  	if (!(hwirq & SEL_INT_PENDING))
  		return;
  	hwirq &= SEL_INT_NUM_MASK;
b918402c8   Marc Zyngier   irqchip: mmp: Con...
199
  	handle_domain_irq(icu_data[0].domain, hwirq, regs);
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
200
  }
8783dd3a3   Stephen Boyd   irqchip: Remove a...
201
  static void __exception_irq_entry mmp2_handle_irq(struct pt_regs *regs)
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
202
  {
b918402c8   Marc Zyngier   irqchip: mmp: Con...
203
  	int hwirq;
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
204
205
206
207
208
  
  	hwirq = readl_relaxed(mmp_icu_base + PJ4_INT_SEL);
  	if (!(hwirq & SEL_INT_PENDING))
  		return;
  	hwirq &= SEL_INT_NUM_MASK;
b918402c8   Marc Zyngier   irqchip: mmp: Con...
209
  	handle_domain_irq(icu_data[0].domain, hwirq, regs);
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
210
  }
c24b31147   Haojian Zhuang   ARM: mmp: support...
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
  /* MMP (ARMv5) */
  void __init icu_init_irq(void)
  {
  	int irq;
  
  	max_icu_nr = 1;
  	mmp_icu_base = ioremap(0xd4282000, 0x1000);
  	icu_data[0].conf_enable = mmp_conf.conf_enable;
  	icu_data[0].conf_disable = mmp_conf.conf_disable;
  	icu_data[0].conf_mask = mmp_conf.conf_mask;
  	icu_data[0].nr_irqs = 64;
  	icu_data[0].virq_base = 0;
  	icu_data[0].domain = irq_domain_add_legacy(NULL, 64, 0, 0,
  						   &irq_domain_simple_ops,
  						   &icu_data[0]);
  	for (irq = 0; irq < 64; irq++) {
  		icu_mask_irq(irq_get_irq_data(irq));
  		irq_set_chip_and_handler(irq, &icu_irq_chip, handle_level_irq);
c24b31147   Haojian Zhuang   ARM: mmp: support...
229
230
  	}
  	irq_set_default_host(icu_data[0].domain);
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
231
  	set_handle_irq(mmp_handle_irq);
c24b31147   Haojian Zhuang   ARM: mmp: support...
232
233
234
235
236
  }
  
  /* MMP2 (ARMv7) */
  void __init mmp2_init_icu(void)
  {
942f42214   Haojian Zhuang   irqchip: mmp: avo...
237
  	int irq, end;
c24b31147   Haojian Zhuang   ARM: mmp: support...
238
239
240
241
242
243
244
245
246
247
248
249
250
  
  	max_icu_nr = 8;
  	mmp_icu_base = ioremap(0xd4282000, 0x1000);
  	icu_data[0].conf_enable = mmp2_conf.conf_enable;
  	icu_data[0].conf_disable = mmp2_conf.conf_disable;
  	icu_data[0].conf_mask = mmp2_conf.conf_mask;
  	icu_data[0].nr_irqs = 64;
  	icu_data[0].virq_base = 0;
  	icu_data[0].domain = irq_domain_add_legacy(NULL, 64, 0, 0,
  						   &irq_domain_simple_ops,
  						   &icu_data[0]);
  	icu_data[1].reg_status = mmp_icu_base + 0x150;
  	icu_data[1].reg_mask = mmp_icu_base + 0x168;
942f42214   Haojian Zhuang   irqchip: mmp: avo...
251
252
253
  	icu_data[1].clr_mfp_irq_base = icu_data[0].virq_base +
  				icu_data[0].nr_irqs;
  	icu_data[1].clr_mfp_hwirq = 1;		/* offset to IRQ_MMP2_PMIC_BASE */
c24b31147   Haojian Zhuang   ARM: mmp: support...
254
  	icu_data[1].nr_irqs = 2;
10bd21c05   Haojian Zhuang   ARM: mmp: fix mis...
255
  	icu_data[1].cascade_irq = 4;
942f42214   Haojian Zhuang   irqchip: mmp: avo...
256
  	icu_data[1].virq_base = icu_data[0].virq_base + icu_data[0].nr_irqs;
c24b31147   Haojian Zhuang   ARM: mmp: support...
257
258
259
260
261
262
263
  	icu_data[1].domain = irq_domain_add_legacy(NULL, icu_data[1].nr_irqs,
  						   icu_data[1].virq_base, 0,
  						   &irq_domain_simple_ops,
  						   &icu_data[1]);
  	icu_data[2].reg_status = mmp_icu_base + 0x154;
  	icu_data[2].reg_mask = mmp_icu_base + 0x16c;
  	icu_data[2].nr_irqs = 2;
10bd21c05   Haojian Zhuang   ARM: mmp: fix mis...
264
  	icu_data[2].cascade_irq = 5;
942f42214   Haojian Zhuang   irqchip: mmp: avo...
265
  	icu_data[2].virq_base = icu_data[1].virq_base + icu_data[1].nr_irqs;
c24b31147   Haojian Zhuang   ARM: mmp: support...
266
267
268
269
270
271
272
  	icu_data[2].domain = irq_domain_add_legacy(NULL, icu_data[2].nr_irqs,
  						   icu_data[2].virq_base, 0,
  						   &irq_domain_simple_ops,
  						   &icu_data[2]);
  	icu_data[3].reg_status = mmp_icu_base + 0x180;
  	icu_data[3].reg_mask = mmp_icu_base + 0x17c;
  	icu_data[3].nr_irqs = 3;
10bd21c05   Haojian Zhuang   ARM: mmp: fix mis...
273
  	icu_data[3].cascade_irq = 9;
942f42214   Haojian Zhuang   irqchip: mmp: avo...
274
  	icu_data[3].virq_base = icu_data[2].virq_base + icu_data[2].nr_irqs;
c24b31147   Haojian Zhuang   ARM: mmp: support...
275
276
277
278
279
280
281
  	icu_data[3].domain = irq_domain_add_legacy(NULL, icu_data[3].nr_irqs,
  						   icu_data[3].virq_base, 0,
  						   &irq_domain_simple_ops,
  						   &icu_data[3]);
  	icu_data[4].reg_status = mmp_icu_base + 0x158;
  	icu_data[4].reg_mask = mmp_icu_base + 0x170;
  	icu_data[4].nr_irqs = 5;
10bd21c05   Haojian Zhuang   ARM: mmp: fix mis...
282
  	icu_data[4].cascade_irq = 17;
942f42214   Haojian Zhuang   irqchip: mmp: avo...
283
  	icu_data[4].virq_base = icu_data[3].virq_base + icu_data[3].nr_irqs;
c24b31147   Haojian Zhuang   ARM: mmp: support...
284
285
286
287
288
289
290
  	icu_data[4].domain = irq_domain_add_legacy(NULL, icu_data[4].nr_irqs,
  						   icu_data[4].virq_base, 0,
  						   &irq_domain_simple_ops,
  						   &icu_data[4]);
  	icu_data[5].reg_status = mmp_icu_base + 0x15c;
  	icu_data[5].reg_mask = mmp_icu_base + 0x174;
  	icu_data[5].nr_irqs = 15;
10bd21c05   Haojian Zhuang   ARM: mmp: fix mis...
291
  	icu_data[5].cascade_irq = 35;
942f42214   Haojian Zhuang   irqchip: mmp: avo...
292
  	icu_data[5].virq_base = icu_data[4].virq_base + icu_data[4].nr_irqs;
c24b31147   Haojian Zhuang   ARM: mmp: support...
293
294
295
296
297
298
299
  	icu_data[5].domain = irq_domain_add_legacy(NULL, icu_data[5].nr_irqs,
  						   icu_data[5].virq_base, 0,
  						   &irq_domain_simple_ops,
  						   &icu_data[5]);
  	icu_data[6].reg_status = mmp_icu_base + 0x160;
  	icu_data[6].reg_mask = mmp_icu_base + 0x178;
  	icu_data[6].nr_irqs = 2;
10bd21c05   Haojian Zhuang   ARM: mmp: fix mis...
300
  	icu_data[6].cascade_irq = 51;
942f42214   Haojian Zhuang   irqchip: mmp: avo...
301
  	icu_data[6].virq_base = icu_data[5].virq_base + icu_data[5].nr_irqs;
c24b31147   Haojian Zhuang   ARM: mmp: support...
302
303
304
305
306
307
308
  	icu_data[6].domain = irq_domain_add_legacy(NULL, icu_data[6].nr_irqs,
  						   icu_data[6].virq_base, 0,
  						   &irq_domain_simple_ops,
  						   &icu_data[6]);
  	icu_data[7].reg_status = mmp_icu_base + 0x188;
  	icu_data[7].reg_mask = mmp_icu_base + 0x184;
  	icu_data[7].nr_irqs = 2;
10bd21c05   Haojian Zhuang   ARM: mmp: fix mis...
309
  	icu_data[7].cascade_irq = 55;
942f42214   Haojian Zhuang   irqchip: mmp: avo...
310
  	icu_data[7].virq_base = icu_data[6].virq_base + icu_data[6].nr_irqs;
c24b31147   Haojian Zhuang   ARM: mmp: support...
311
312
313
314
  	icu_data[7].domain = irq_domain_add_legacy(NULL, icu_data[7].nr_irqs,
  						   icu_data[7].virq_base, 0,
  						   &irq_domain_simple_ops,
  						   &icu_data[7]);
942f42214   Haojian Zhuang   irqchip: mmp: avo...
315
316
  	end = icu_data[7].virq_base + icu_data[7].nr_irqs;
  	for (irq = 0; irq < end; irq++) {
c24b31147   Haojian Zhuang   ARM: mmp: support...
317
  		icu_mask_irq(irq_get_irq_data(irq));
942f42214   Haojian Zhuang   irqchip: mmp: avo...
318
319
320
321
322
323
324
  		if (irq == icu_data[1].cascade_irq ||
  		    irq == icu_data[2].cascade_irq ||
  		    irq == icu_data[3].cascade_irq ||
  		    irq == icu_data[4].cascade_irq ||
  		    irq == icu_data[5].cascade_irq ||
  		    irq == icu_data[6].cascade_irq ||
  		    irq == icu_data[7].cascade_irq) {
c24b31147   Haojian Zhuang   ARM: mmp: support...
325
326
  			irq_set_chip(irq, &icu_irq_chip);
  			irq_set_chained_handler(irq, icu_mux_irq_demux);
942f42214   Haojian Zhuang   irqchip: mmp: avo...
327
  		} else {
c24b31147   Haojian Zhuang   ARM: mmp: support...
328
329
  			irq_set_chip_and_handler(irq, &icu_irq_chip,
  						 handle_level_irq);
c24b31147   Haojian Zhuang   ARM: mmp: support...
330
  		}
c24b31147   Haojian Zhuang   ARM: mmp: support...
331
332
  	}
  	irq_set_default_host(icu_data[0].domain);
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
333
  	set_handle_irq(mmp2_handle_irq);
c24b31147   Haojian Zhuang   ARM: mmp: support...
334
335
336
  }
  
  #ifdef CONFIG_OF
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
337
  static int __init mmp_init_bases(struct device_node *node)
c24b31147   Haojian Zhuang   ARM: mmp: support...
338
  {
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
339
  	int ret, nr_irqs, irq, i = 0;
c24b31147   Haojian Zhuang   ARM: mmp: support...
340

0f374561b   Haojian Zhuang   irqchip: mmp: sup...
341
342
343
344
345
346
  	ret = of_property_read_u32(node, "mrvl,intc-nr-irqs", &nr_irqs);
  	if (ret) {
  		pr_err("Not found mrvl,intc-nr-irqs property
  ");
  		return ret;
  	}
c24b31147   Haojian Zhuang   ARM: mmp: support...
347

0f374561b   Haojian Zhuang   irqchip: mmp: sup...
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
  	mmp_icu_base = of_iomap(node, 0);
  	if (!mmp_icu_base) {
  		pr_err("Failed to get interrupt controller register
  ");
  		return -ENOMEM;
  	}
  
  	icu_data[0].virq_base = 0;
  	icu_data[0].domain = irq_domain_add_linear(node, nr_irqs,
  						   &mmp_irq_domain_ops,
  						   &icu_data[0]);
  	for (irq = 0; irq < nr_irqs; irq++) {
  		ret = irq_create_mapping(icu_data[0].domain, irq);
  		if (!ret) {
  			pr_err("Failed to mapping hwirq
  ");
c24b31147   Haojian Zhuang   ARM: mmp: support...
364
365
  			goto err;
  		}
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
366
367
  		if (!irq)
  			icu_data[0].virq_base = ret;
c24b31147   Haojian Zhuang   ARM: mmp: support...
368
  	}
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
369
  	icu_data[0].nr_irqs = nr_irqs;
c24b31147   Haojian Zhuang   ARM: mmp: support...
370
371
  	return 0;
  err:
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
372
373
374
375
376
377
378
  	if (icu_data[0].virq_base) {
  		for (i = 0; i < irq; i++)
  			irq_dispose_mapping(icu_data[0].virq_base + i);
  	}
  	irq_domain_remove(icu_data[0].domain);
  	iounmap(mmp_icu_base);
  	return -EINVAL;
c24b31147   Haojian Zhuang   ARM: mmp: support...
379
  }
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
380
381
  static int __init mmp_of_init(struct device_node *node,
  			      struct device_node *parent)
c24b31147   Haojian Zhuang   ARM: mmp: support...
382
  {
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
383
  	int ret;
c24b31147   Haojian Zhuang   ARM: mmp: support...
384

0f374561b   Haojian Zhuang   irqchip: mmp: sup...
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
  	ret = mmp_init_bases(node);
  	if (ret < 0)
  		return ret;
  
  	icu_data[0].conf_enable = mmp_conf.conf_enable;
  	icu_data[0].conf_disable = mmp_conf.conf_disable;
  	icu_data[0].conf_mask = mmp_conf.conf_mask;
  	irq_set_default_host(icu_data[0].domain);
  	set_handle_irq(mmp_handle_irq);
  	max_icu_nr = 1;
  	return 0;
  }
  IRQCHIP_DECLARE(mmp_intc, "mrvl,mmp-intc", mmp_of_init);
  
  static int __init mmp2_of_init(struct device_node *node,
  			       struct device_node *parent)
  {
  	int ret;
  
  	ret = mmp_init_bases(node);
  	if (ret < 0)
  		return ret;
  
  	icu_data[0].conf_enable = mmp2_conf.conf_enable;
  	icu_data[0].conf_disable = mmp2_conf.conf_disable;
  	icu_data[0].conf_mask = mmp2_conf.conf_mask;
  	irq_set_default_host(icu_data[0].domain);
  	set_handle_irq(mmp2_handle_irq);
  	max_icu_nr = 1;
  	return 0;
  }
  IRQCHIP_DECLARE(mmp2_intc, "mrvl,mmp2-intc", mmp2_of_init);
  
  static int __init mmp2_mux_of_init(struct device_node *node,
  				   struct device_node *parent)
  {
  	struct resource res;
  	int i, ret, irq, j = 0;
  	u32 nr_irqs, mfp_irq;
  
  	if (!parent)
  		return -ENODEV;
  
  	i = max_icu_nr;
  	ret = of_property_read_u32(node, "mrvl,intc-nr-irqs",
  				   &nr_irqs);
c24b31147   Haojian Zhuang   ARM: mmp: support...
431
432
433
  	if (ret) {
  		pr_err("Not found mrvl,intc-nr-irqs property
  ");
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
434
  		return -EINVAL;
c24b31147   Haojian Zhuang   ARM: mmp: support...
435
  	}
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
436
437
438
439
440
  	ret = of_address_to_resource(node, 0, &res);
  	if (ret < 0) {
  		pr_err("Not found reg property
  ");
  		return -EINVAL;
c24b31147   Haojian Zhuang   ARM: mmp: support...
441
  	}
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
442
443
444
445
446
447
  	icu_data[i].reg_status = mmp_icu_base + res.start;
  	ret = of_address_to_resource(node, 1, &res);
  	if (ret < 0) {
  		pr_err("Not found reg property
  ");
  		return -EINVAL;
c24b31147   Haojian Zhuang   ARM: mmp: support...
448
  	}
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
449
450
451
452
453
454
455
  	icu_data[i].reg_mask = mmp_icu_base + res.start;
  	icu_data[i].cascade_irq = irq_of_parse_and_map(node, 0);
  	if (!icu_data[i].cascade_irq)
  		return -EINVAL;
  
  	icu_data[i].virq_base = 0;
  	icu_data[i].domain = irq_domain_add_linear(node, nr_irqs,
c24b31147   Haojian Zhuang   ARM: mmp: support...
456
  						   &mmp_irq_domain_ops,
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
  						   &icu_data[i]);
  	for (irq = 0; irq < nr_irqs; irq++) {
  		ret = irq_create_mapping(icu_data[i].domain, irq);
  		if (!ret) {
  			pr_err("Failed to mapping hwirq
  ");
  			goto err;
  		}
  		if (!irq)
  			icu_data[i].virq_base = ret;
  	}
  	icu_data[i].nr_irqs = nr_irqs;
  	if (!of_property_read_u32(node, "mrvl,clr-mfp-irq",
  				  &mfp_irq)) {
  		icu_data[i].clr_mfp_irq_base = icu_data[i].virq_base;
  		icu_data[i].clr_mfp_hwirq = mfp_irq;
  	}
  	irq_set_chained_handler(icu_data[i].cascade_irq,
  				icu_mux_irq_demux);
  	max_icu_nr++;
  	return 0;
c24b31147   Haojian Zhuang   ARM: mmp: support...
478
  err:
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
479
480
481
482
483
484
  	if (icu_data[i].virq_base) {
  		for (j = 0; j < irq; j++)
  			irq_dispose_mapping(icu_data[i].virq_base + j);
  	}
  	irq_domain_remove(icu_data[i].domain);
  	return -EINVAL;
c24b31147   Haojian Zhuang   ARM: mmp: support...
485
  }
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
486
  IRQCHIP_DECLARE(mmp2_mux_intc, "mrvl,mmp2-mux-intc", mmp2_mux_of_init);
c24b31147   Haojian Zhuang   ARM: mmp: support...
487
  #endif