Blame view

drivers/irqchip/irq-mmp.c 13.3 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
c24b31147   Haojian Zhuang   ARM: mmp: support...
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
  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...
53
  static void __iomem *mmp_icu_base;
c24b31147   Haojian Zhuang   ARM: mmp: support...
54
55
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
  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...
120
  struct irq_chip icu_irq_chip = {
c24b31147   Haojian Zhuang   ARM: mmp: support...
121
122
123
124
125
  	.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...
126
  static void icu_mux_irq_demux(struct irq_desc *desc)
c24b31147   Haojian Zhuang   ARM: mmp: support...
127
  {
14873aa1d   Thomas Gleixner   irqchip/mmp: Prep...
128
  	unsigned int irq = irq_desc_get_irq(desc);
c24b31147   Haojian Zhuang   ARM: mmp: support...
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
  	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...
152
  		for_each_set_bit(n, &status, BITS_PER_LONG) {
c24b31147   Haojian Zhuang   ARM: mmp: support...
153
  			generic_handle_irq(icu_data[i].virq_base + n);
c24b31147   Haojian Zhuang   ARM: mmp: support...
154
155
156
157
158
159
160
161
  		}
  	}
  }
  
  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...
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
  	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,
  };
  
  static struct mmp_intc_conf mmp_conf = {
  	.conf_enable	= 0x51,
  	.conf_disable	= 0x0,
  	.conf_mask	= 0x7f,
  };
  
  static struct mmp_intc_conf mmp2_conf = {
  	.conf_enable	= 0x20,
  	.conf_disable	= 0x0,
  	.conf_mask	= 0x7f,
  };
8783dd3a3   Stephen Boyd   irqchip: Remove a...
190
  static void __exception_irq_entry mmp_handle_irq(struct pt_regs *regs)
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
191
  {
b918402c8   Marc Zyngier   irqchip: mmp: Con...
192
  	int hwirq;
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
193
194
195
196
197
  
  	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...
198
  	handle_domain_irq(icu_data[0].domain, hwirq, regs);
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
199
  }
8783dd3a3   Stephen Boyd   irqchip: Remove a...
200
  static void __exception_irq_entry mmp2_handle_irq(struct pt_regs *regs)
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
201
  {
b918402c8   Marc Zyngier   irqchip: mmp: Con...
202
  	int hwirq;
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
203
204
205
206
207
  
  	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...
208
  	handle_domain_irq(icu_data[0].domain, hwirq, regs);
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
209
  }
c24b31147   Haojian Zhuang   ARM: mmp: support...
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
  /* 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...
228
229
  	}
  	irq_set_default_host(icu_data[0].domain);
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
230
  	set_handle_irq(mmp_handle_irq);
c24b31147   Haojian Zhuang   ARM: mmp: support...
231
232
233
234
235
  }
  
  /* MMP2 (ARMv7) */
  void __init mmp2_init_icu(void)
  {
942f42214   Haojian Zhuang   irqchip: mmp: avo...
236
  	int irq, end;
c24b31147   Haojian Zhuang   ARM: mmp: support...
237
238
239
240
241
242
243
244
245
246
247
248
249
  
  	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...
250
251
252
  	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...
253
  	icu_data[1].nr_irqs = 2;
10bd21c05   Haojian Zhuang   ARM: mmp: fix mis...
254
  	icu_data[1].cascade_irq = 4;
942f42214   Haojian Zhuang   irqchip: mmp: avo...
255
  	icu_data[1].virq_base = icu_data[0].virq_base + icu_data[0].nr_irqs;
c24b31147   Haojian Zhuang   ARM: mmp: support...
256
257
258
259
260
261
262
  	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...
263
  	icu_data[2].cascade_irq = 5;
942f42214   Haojian Zhuang   irqchip: mmp: avo...
264
  	icu_data[2].virq_base = icu_data[1].virq_base + icu_data[1].nr_irqs;
c24b31147   Haojian Zhuang   ARM: mmp: support...
265
266
267
268
269
270
271
  	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...
272
  	icu_data[3].cascade_irq = 9;
942f42214   Haojian Zhuang   irqchip: mmp: avo...
273
  	icu_data[3].virq_base = icu_data[2].virq_base + icu_data[2].nr_irqs;
c24b31147   Haojian Zhuang   ARM: mmp: support...
274
275
276
277
278
279
280
  	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...
281
  	icu_data[4].cascade_irq = 17;
942f42214   Haojian Zhuang   irqchip: mmp: avo...
282
  	icu_data[4].virq_base = icu_data[3].virq_base + icu_data[3].nr_irqs;
c24b31147   Haojian Zhuang   ARM: mmp: support...
283
284
285
286
287
288
289
  	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...
290
  	icu_data[5].cascade_irq = 35;
942f42214   Haojian Zhuang   irqchip: mmp: avo...
291
  	icu_data[5].virq_base = icu_data[4].virq_base + icu_data[4].nr_irqs;
c24b31147   Haojian Zhuang   ARM: mmp: support...
292
293
294
295
296
297
298
  	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...
299
  	icu_data[6].cascade_irq = 51;
942f42214   Haojian Zhuang   irqchip: mmp: avo...
300
  	icu_data[6].virq_base = icu_data[5].virq_base + icu_data[5].nr_irqs;
c24b31147   Haojian Zhuang   ARM: mmp: support...
301
302
303
304
305
306
307
  	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...
308
  	icu_data[7].cascade_irq = 55;
942f42214   Haojian Zhuang   irqchip: mmp: avo...
309
  	icu_data[7].virq_base = icu_data[6].virq_base + icu_data[6].nr_irqs;
c24b31147   Haojian Zhuang   ARM: mmp: support...
310
311
312
313
  	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...
314
315
  	end = icu_data[7].virq_base + icu_data[7].nr_irqs;
  	for (irq = 0; irq < end; irq++) {
c24b31147   Haojian Zhuang   ARM: mmp: support...
316
  		icu_mask_irq(irq_get_irq_data(irq));
942f42214   Haojian Zhuang   irqchip: mmp: avo...
317
318
319
320
321
322
323
  		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...
324
325
  			irq_set_chip(irq, &icu_irq_chip);
  			irq_set_chained_handler(irq, icu_mux_irq_demux);
942f42214   Haojian Zhuang   irqchip: mmp: avo...
326
  		} else {
c24b31147   Haojian Zhuang   ARM: mmp: support...
327
328
  			irq_set_chip_and_handler(irq, &icu_irq_chip,
  						 handle_level_irq);
c24b31147   Haojian Zhuang   ARM: mmp: support...
329
  		}
c24b31147   Haojian Zhuang   ARM: mmp: support...
330
331
  	}
  	irq_set_default_host(icu_data[0].domain);
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
332
  	set_handle_irq(mmp2_handle_irq);
c24b31147   Haojian Zhuang   ARM: mmp: support...
333
334
335
  }
  
  #ifdef CONFIG_OF
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
336
  static int __init mmp_init_bases(struct device_node *node)
c24b31147   Haojian Zhuang   ARM: mmp: support...
337
  {
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
338
  	int ret, nr_irqs, irq, i = 0;
c24b31147   Haojian Zhuang   ARM: mmp: support...
339

0f374561b   Haojian Zhuang   irqchip: mmp: sup...
340
341
342
343
344
345
  	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...
346

0f374561b   Haojian Zhuang   irqchip: mmp: sup...
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
  	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...
363
364
  			goto err;
  		}
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
365
366
  		if (!irq)
  			icu_data[0].virq_base = ret;
c24b31147   Haojian Zhuang   ARM: mmp: support...
367
  	}
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
368
  	icu_data[0].nr_irqs = nr_irqs;
c24b31147   Haojian Zhuang   ARM: mmp: support...
369
370
  	return 0;
  err:
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
371
372
373
374
375
376
377
  	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...
378
  }
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
379
380
  static int __init mmp_of_init(struct device_node *node,
  			      struct device_node *parent)
c24b31147   Haojian Zhuang   ARM: mmp: support...
381
  {
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
382
  	int ret;
c24b31147   Haojian Zhuang   ARM: mmp: support...
383

0f374561b   Haojian Zhuang   irqchip: mmp: sup...
384
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
  	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...
430
431
432
  	if (ret) {
  		pr_err("Not found mrvl,intc-nr-irqs property
  ");
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
433
  		return -EINVAL;
c24b31147   Haojian Zhuang   ARM: mmp: support...
434
  	}
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
435
436
437
438
439
  	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...
440
  	}
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
441
442
443
444
445
446
  	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...
447
  	}
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
448
449
450
451
452
453
454
  	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...
455
  						   &mmp_irq_domain_ops,
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
  						   &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...
477
  err:
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
478
479
480
481
482
483
  	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...
484
  }
0f374561b   Haojian Zhuang   irqchip: mmp: sup...
485
  IRQCHIP_DECLARE(mmp2_mux_intc, "mrvl,mmp2-mux-intc", mmp2_mux_of_init);
c24b31147   Haojian Zhuang   ARM: mmp: support...
486
  #endif