aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/irqchip/Kconfig8
-rw-r--r--drivers/irqchip/Makefile2
-rw-r--r--drivers/irqchip/irq-renesas-intc-irqpin.c471
-rw-r--r--drivers/irqchip/irq-renesas-irqc.c307
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-sh73a0.c6
5 files changed, 791 insertions, 3 deletions
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index a350969e5efe..4a33351c25dc 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -25,6 +25,14 @@ config ARM_VIC_NR
25 The maximum number of VICs available in the system, for 25 The maximum number of VICs available in the system, for
26 power management. 26 power management.
27 27
28config RENESAS_INTC_IRQPIN
29 bool
30 select IRQ_DOMAIN
31
32config RENESAS_IRQC
33 bool
34 select IRQ_DOMAIN
35
28config VERSATILE_FPGA_IRQ 36config VERSATILE_FPGA_IRQ
29 bool 37 bool
30 select IRQ_DOMAIN 38 select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 98e3b87bdf1b..e41ceb9bec22 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -8,4 +8,6 @@ obj-$(CONFIG_ARCH_SUNXI) += irq-sunxi.o
8obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o 8obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o
9obj-$(CONFIG_ARM_GIC) += irq-gic.o 9obj-$(CONFIG_ARM_GIC) += irq-gic.o
10obj-$(CONFIG_ARM_VIC) += irq-vic.o 10obj-$(CONFIG_ARM_VIC) += irq-vic.o
11obj-$(CONFIG_RENESAS_INTC_IRQPIN) += irq-renesas-intc-irqpin.o
12obj-$(CONFIG_RENESAS_IRQC) += irq-renesas-irqc.o
11obj-$(CONFIG_VERSATILE_FPGA_IRQ) += irq-versatile-fpga.o 13obj-$(CONFIG_VERSATILE_FPGA_IRQ) += irq-versatile-fpga.o
diff --git a/drivers/irqchip/irq-renesas-intc-irqpin.c b/drivers/irqchip/irq-renesas-intc-irqpin.c
new file mode 100644
index 000000000000..fd5dabc2235d
--- /dev/null
+++ b/drivers/irqchip/irq-renesas-intc-irqpin.c
@@ -0,0 +1,471 @@
1/*
2 * Renesas INTC External IRQ Pin Driver
3 *
4 * Copyright (C) 2013 Magnus Damm
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#include <linux/init.h>
21#include <linux/platform_device.h>
22#include <linux/spinlock.h>
23#include <linux/interrupt.h>
24#include <linux/ioport.h>
25#include <linux/io.h>
26#include <linux/irq.h>
27#include <linux/irqdomain.h>
28#include <linux/err.h>
29#include <linux/slab.h>
30#include <linux/module.h>
31#include <linux/platform_data/irq-renesas-intc-irqpin.h>
32
33#define INTC_IRQPIN_MAX 8 /* maximum 8 interrupts per driver instance */
34
35#define INTC_IRQPIN_REG_SENSE 0 /* ICRn */
36#define INTC_IRQPIN_REG_PRIO 1 /* INTPRInn */
37#define INTC_IRQPIN_REG_SOURCE 2 /* INTREQnn */
38#define INTC_IRQPIN_REG_MASK 3 /* INTMSKnn */
39#define INTC_IRQPIN_REG_CLEAR 4 /* INTMSKCLRnn */
40#define INTC_IRQPIN_REG_NR 5
41
42/* INTC external IRQ PIN hardware register access:
43 *
44 * SENSE is read-write 32-bit with 2-bits or 4-bits per IRQ (*)
45 * PRIO is read-write 32-bit with 4-bits per IRQ (**)
46 * SOURCE is read-only 32-bit or 8-bit with 1-bit per IRQ (***)
47 * MASK is write-only 32-bit or 8-bit with 1-bit per IRQ (***)
48 * CLEAR is write-only 32-bit or 8-bit with 1-bit per IRQ (***)
49 *
50 * (*) May be accessed by more than one driver instance - lock needed
51 * (**) Read-modify-write access by one driver instance - lock needed
52 * (***) Accessed by one driver instance only - no locking needed
53 */
54
55struct intc_irqpin_iomem {
56 void __iomem *iomem;
57 unsigned long (*read)(void __iomem *iomem);
58 void (*write)(void __iomem *iomem, unsigned long data);
59 int width;
60};
61
62struct intc_irqpin_irq {
63 int hw_irq;
64 int requested_irq;
65 int domain_irq;
66 struct intc_irqpin_priv *p;
67};
68
69struct intc_irqpin_priv {
70 struct intc_irqpin_iomem iomem[INTC_IRQPIN_REG_NR];
71 struct intc_irqpin_irq irq[INTC_IRQPIN_MAX];
72 struct renesas_intc_irqpin_config config;
73 unsigned int number_of_irqs;
74 struct platform_device *pdev;
75 struct irq_chip irq_chip;
76 struct irq_domain *irq_domain;
77};
78
79static unsigned long intc_irqpin_read32(void __iomem *iomem)
80{
81 return ioread32(iomem);
82}
83
84static unsigned long intc_irqpin_read8(void __iomem *iomem)
85{
86 return ioread8(iomem);
87}
88
89static void intc_irqpin_write32(void __iomem *iomem, unsigned long data)
90{
91 iowrite32(data, iomem);
92}
93
94static void intc_irqpin_write8(void __iomem *iomem, unsigned long data)
95{
96 iowrite8(data, iomem);
97}
98
99static inline unsigned long intc_irqpin_read(struct intc_irqpin_priv *p,
100 int reg)
101{
102 struct intc_irqpin_iomem *i = &p->iomem[reg];
103
104 return i->read(i->iomem);
105}
106
107static inline void intc_irqpin_write(struct intc_irqpin_priv *p,
108 int reg, unsigned long data)
109{
110 struct intc_irqpin_iomem *i = &p->iomem[reg];
111
112 i->write(i->iomem, data);
113}
114
115static inline unsigned long intc_irqpin_hwirq_mask(struct intc_irqpin_priv *p,
116 int reg, int hw_irq)
117{
118 return BIT((p->iomem[reg].width - 1) - hw_irq);
119}
120
121static inline void intc_irqpin_irq_write_hwirq(struct intc_irqpin_priv *p,
122 int reg, int hw_irq)
123{
124 intc_irqpin_write(p, reg, intc_irqpin_hwirq_mask(p, reg, hw_irq));
125}
126
127static DEFINE_RAW_SPINLOCK(intc_irqpin_lock); /* only used by slow path */
128
129static void intc_irqpin_read_modify_write(struct intc_irqpin_priv *p,
130 int reg, int shift,
131 int width, int value)
132{
133 unsigned long flags;
134 unsigned long tmp;
135
136 raw_spin_lock_irqsave(&intc_irqpin_lock, flags);
137
138 tmp = intc_irqpin_read(p, reg);
139 tmp &= ~(((1 << width) - 1) << shift);
140 tmp |= value << shift;
141 intc_irqpin_write(p, reg, tmp);
142
143 raw_spin_unlock_irqrestore(&intc_irqpin_lock, flags);
144}
145
146static void intc_irqpin_mask_unmask_prio(struct intc_irqpin_priv *p,
147 int irq, int do_mask)
148{
149 int bitfield_width = 4; /* PRIO assumed to have fixed bitfield width */
150 int shift = (7 - irq) * bitfield_width; /* PRIO assumed to be 32-bit */
151
152 intc_irqpin_read_modify_write(p, INTC_IRQPIN_REG_PRIO,
153 shift, bitfield_width,
154 do_mask ? 0 : (1 << bitfield_width) - 1);
155}
156
157static int intc_irqpin_set_sense(struct intc_irqpin_priv *p, int irq, int value)
158{
159 int bitfield_width = p->config.sense_bitfield_width;
160 int shift = (7 - irq) * bitfield_width; /* SENSE assumed to be 32-bit */
161
162 dev_dbg(&p->pdev->dev, "sense irq = %d, mode = %d\n", irq, value);
163
164 if (value >= (1 << bitfield_width))
165 return -EINVAL;
166
167 intc_irqpin_read_modify_write(p, INTC_IRQPIN_REG_SENSE, shift,
168 bitfield_width, value);
169 return 0;
170}
171
172static void intc_irqpin_dbg(struct intc_irqpin_irq *i, char *str)
173{
174 dev_dbg(&i->p->pdev->dev, "%s (%d:%d:%d)\n",
175 str, i->requested_irq, i->hw_irq, i->domain_irq);
176}
177
178static void intc_irqpin_irq_enable(struct irq_data *d)
179{
180 struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d);
181 int hw_irq = irqd_to_hwirq(d);
182
183 intc_irqpin_dbg(&p->irq[hw_irq], "enable");
184 intc_irqpin_irq_write_hwirq(p, INTC_IRQPIN_REG_CLEAR, hw_irq);
185}
186
187static void intc_irqpin_irq_disable(struct irq_data *d)
188{
189 struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d);
190 int hw_irq = irqd_to_hwirq(d);
191
192 intc_irqpin_dbg(&p->irq[hw_irq], "disable");
193 intc_irqpin_irq_write_hwirq(p, INTC_IRQPIN_REG_MASK, hw_irq);
194}
195
196static void intc_irqpin_irq_enable_force(struct irq_data *d)
197{
198 struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d);
199 int irq = p->irq[irqd_to_hwirq(d)].requested_irq;
200
201 intc_irqpin_irq_enable(d);
202
203 /* enable interrupt through parent interrupt controller,
204 * assumes non-shared interrupt with 1:1 mapping
205 * needed for busted IRQs on some SoCs like sh73a0
206 */
207 irq_get_chip(irq)->irq_unmask(irq_get_irq_data(irq));
208}
209
210static void intc_irqpin_irq_disable_force(struct irq_data *d)
211{
212 struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d);
213 int irq = p->irq[irqd_to_hwirq(d)].requested_irq;
214
215 /* disable interrupt through parent interrupt controller,
216 * assumes non-shared interrupt with 1:1 mapping
217 * needed for busted IRQs on some SoCs like sh73a0
218 */
219 irq_get_chip(irq)->irq_mask(irq_get_irq_data(irq));
220 intc_irqpin_irq_disable(d);
221}
222
223#define INTC_IRQ_SENSE_VALID 0x10
224#define INTC_IRQ_SENSE(x) (x + INTC_IRQ_SENSE_VALID)
225
226static unsigned char intc_irqpin_sense[IRQ_TYPE_SENSE_MASK + 1] = {
227 [IRQ_TYPE_EDGE_FALLING] = INTC_IRQ_SENSE(0x00),
228 [IRQ_TYPE_EDGE_RISING] = INTC_IRQ_SENSE(0x01),
229 [IRQ_TYPE_LEVEL_LOW] = INTC_IRQ_SENSE(0x02),
230 [IRQ_TYPE_LEVEL_HIGH] = INTC_IRQ_SENSE(0x03),
231 [IRQ_TYPE_EDGE_BOTH] = INTC_IRQ_SENSE(0x04),
232};
233
234static int intc_irqpin_irq_set_type(struct irq_data *d, unsigned int type)
235{
236 unsigned char value = intc_irqpin_sense[type & IRQ_TYPE_SENSE_MASK];
237 struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d);
238
239 if (!(value & INTC_IRQ_SENSE_VALID))
240 return -EINVAL;
241
242 return intc_irqpin_set_sense(p, irqd_to_hwirq(d),
243 value ^ INTC_IRQ_SENSE_VALID);
244}
245
246static irqreturn_t intc_irqpin_irq_handler(int irq, void *dev_id)
247{
248 struct intc_irqpin_irq *i = dev_id;
249 struct intc_irqpin_priv *p = i->p;
250 unsigned long bit;
251
252 intc_irqpin_dbg(i, "demux1");
253 bit = intc_irqpin_hwirq_mask(p, INTC_IRQPIN_REG_SOURCE, i->hw_irq);
254
255 if (intc_irqpin_read(p, INTC_IRQPIN_REG_SOURCE) & bit) {
256 intc_irqpin_write(p, INTC_IRQPIN_REG_SOURCE, ~bit);
257 intc_irqpin_dbg(i, "demux2");
258 generic_handle_irq(i->domain_irq);
259 return IRQ_HANDLED;
260 }
261 return IRQ_NONE;
262}
263
264static int intc_irqpin_irq_domain_map(struct irq_domain *h, unsigned int virq,
265 irq_hw_number_t hw)
266{
267 struct intc_irqpin_priv *p = h->host_data;
268
269 p->irq[hw].domain_irq = virq;
270 p->irq[hw].hw_irq = hw;
271
272 intc_irqpin_dbg(&p->irq[hw], "map");
273 irq_set_chip_data(virq, h->host_data);
274 irq_set_chip_and_handler(virq, &p->irq_chip, handle_level_irq);
275 set_irq_flags(virq, IRQF_VALID); /* kill me now */
276 return 0;
277}
278
279static struct irq_domain_ops intc_irqpin_irq_domain_ops = {
280 .map = intc_irqpin_irq_domain_map,
281 .xlate = irq_domain_xlate_twocell,
282};
283
284static int intc_irqpin_probe(struct platform_device *pdev)
285{
286 struct renesas_intc_irqpin_config *pdata = pdev->dev.platform_data;
287 struct intc_irqpin_priv *p;
288 struct intc_irqpin_iomem *i;
289 struct resource *io[INTC_IRQPIN_REG_NR];
290 struct resource *irq;
291 struct irq_chip *irq_chip;
292 void (*enable_fn)(struct irq_data *d);
293 void (*disable_fn)(struct irq_data *d);
294 const char *name = dev_name(&pdev->dev);
295 int ret;
296 int k;
297
298 p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);
299 if (!p) {
300 dev_err(&pdev->dev, "failed to allocate driver data\n");
301 ret = -ENOMEM;
302 goto err0;
303 }
304
305 /* deal with driver instance configuration */
306 if (pdata)
307 memcpy(&p->config, pdata, sizeof(*pdata));
308 if (!p->config.sense_bitfield_width)
309 p->config.sense_bitfield_width = 4; /* default to 4 bits */
310
311 p->pdev = pdev;
312 platform_set_drvdata(pdev, p);
313
314 /* get hold of manadatory IOMEM */
315 for (k = 0; k < INTC_IRQPIN_REG_NR; k++) {
316 io[k] = platform_get_resource(pdev, IORESOURCE_MEM, k);
317 if (!io[k]) {
318 dev_err(&pdev->dev, "not enough IOMEM resources\n");
319 ret = -EINVAL;
320 goto err0;
321 }
322 }
323
324 /* allow any number of IRQs between 1 and INTC_IRQPIN_MAX */
325 for (k = 0; k < INTC_IRQPIN_MAX; k++) {
326 irq = platform_get_resource(pdev, IORESOURCE_IRQ, k);
327 if (!irq)
328 break;
329
330 p->irq[k].p = p;
331 p->irq[k].requested_irq = irq->start;
332 }
333
334 p->number_of_irqs = k;
335 if (p->number_of_irqs < 1) {
336 dev_err(&pdev->dev, "not enough IRQ resources\n");
337 ret = -EINVAL;
338 goto err0;
339 }
340
341 /* ioremap IOMEM and setup read/write callbacks */
342 for (k = 0; k < INTC_IRQPIN_REG_NR; k++) {
343 i = &p->iomem[k];
344
345 switch (resource_size(io[k])) {
346 case 1:
347 i->width = 8;
348 i->read = intc_irqpin_read8;
349 i->write = intc_irqpin_write8;
350 break;
351 case 4:
352 i->width = 32;
353 i->read = intc_irqpin_read32;
354 i->write = intc_irqpin_write32;
355 break;
356 default:
357 dev_err(&pdev->dev, "IOMEM size mismatch\n");
358 ret = -EINVAL;
359 goto err0;
360 }
361
362 i->iomem = devm_ioremap_nocache(&pdev->dev, io[k]->start,
363 resource_size(io[k]));
364 if (!i->iomem) {
365 dev_err(&pdev->dev, "failed to remap IOMEM\n");
366 ret = -ENXIO;
367 goto err0;
368 }
369 }
370
371 /* mask all interrupts using priority */
372 for (k = 0; k < p->number_of_irqs; k++)
373 intc_irqpin_mask_unmask_prio(p, k, 1);
374
375 /* use more severe masking method if requested */
376 if (p->config.control_parent) {
377 enable_fn = intc_irqpin_irq_enable_force;
378 disable_fn = intc_irqpin_irq_disable_force;
379 } else {
380 enable_fn = intc_irqpin_irq_enable;
381 disable_fn = intc_irqpin_irq_disable;
382 }
383
384 irq_chip = &p->irq_chip;
385 irq_chip->name = name;
386 irq_chip->irq_mask = disable_fn;
387 irq_chip->irq_unmask = enable_fn;
388 irq_chip->irq_enable = enable_fn;
389 irq_chip->irq_disable = disable_fn;
390 irq_chip->irq_set_type = intc_irqpin_irq_set_type;
391 irq_chip->flags = IRQCHIP_SKIP_SET_WAKE;
392
393 p->irq_domain = irq_domain_add_simple(pdev->dev.of_node,
394 p->number_of_irqs,
395 p->config.irq_base,
396 &intc_irqpin_irq_domain_ops, p);
397 if (!p->irq_domain) {
398 ret = -ENXIO;
399 dev_err(&pdev->dev, "cannot initialize irq domain\n");
400 goto err0;
401 }
402
403 /* request and set priority on interrupts one by one */
404 for (k = 0; k < p->number_of_irqs; k++) {
405 if (devm_request_irq(&pdev->dev, p->irq[k].requested_irq,
406 intc_irqpin_irq_handler,
407 0, name, &p->irq[k])) {
408 dev_err(&pdev->dev, "failed to request low IRQ\n");
409 ret = -ENOENT;
410 goto err1;
411 }
412 intc_irqpin_mask_unmask_prio(p, k, 0);
413 }
414
415 dev_info(&pdev->dev, "driving %d irqs\n", p->number_of_irqs);
416
417 /* warn in case of mismatch if irq base is specified */
418 if (p->config.irq_base) {
419 if (p->config.irq_base != p->irq[0].domain_irq)
420 dev_warn(&pdev->dev, "irq base mismatch (%d/%d)\n",
421 p->config.irq_base, p->irq[0].domain_irq);
422 }
423
424 return 0;
425
426err1:
427 irq_domain_remove(p->irq_domain);
428err0:
429 return ret;
430}
431
432static int intc_irqpin_remove(struct platform_device *pdev)
433{
434 struct intc_irqpin_priv *p = platform_get_drvdata(pdev);
435
436 irq_domain_remove(p->irq_domain);
437
438 return 0;
439}
440
441static const struct of_device_id intc_irqpin_dt_ids[] = {
442 { .compatible = "renesas,intc-irqpin", },
443 {},
444};
445MODULE_DEVICE_TABLE(of, intc_irqpin_dt_ids);
446
447static struct platform_driver intc_irqpin_device_driver = {
448 .probe = intc_irqpin_probe,
449 .remove = intc_irqpin_remove,
450 .driver = {
451 .name = "renesas_intc_irqpin",
452 .of_match_table = intc_irqpin_dt_ids,
453 .owner = THIS_MODULE,
454 }
455};
456
457static int __init intc_irqpin_init(void)
458{
459 return platform_driver_register(&intc_irqpin_device_driver);
460}
461postcore_initcall(intc_irqpin_init);
462
463static void __exit intc_irqpin_exit(void)
464{
465 platform_driver_unregister(&intc_irqpin_device_driver);
466}
467module_exit(intc_irqpin_exit);
468
469MODULE_AUTHOR("Magnus Damm");
470MODULE_DESCRIPTION("Renesas INTC External IRQ Pin Driver");
471MODULE_LICENSE("GPL v2");
diff --git a/drivers/irqchip/irq-renesas-irqc.c b/drivers/irqchip/irq-renesas-irqc.c
new file mode 100644
index 000000000000..927bff373aac
--- /dev/null
+++ b/drivers/irqchip/irq-renesas-irqc.c
@@ -0,0 +1,307 @@
1/*
2 * Renesas IRQC Driver
3 *
4 * Copyright (C) 2013 Magnus Damm
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#include <linux/init.h>
21#include <linux/platform_device.h>
22#include <linux/spinlock.h>
23#include <linux/interrupt.h>
24#include <linux/ioport.h>
25#include <linux/io.h>
26#include <linux/irq.h>
27#include <linux/irqdomain.h>
28#include <linux/err.h>
29#include <linux/slab.h>
30#include <linux/module.h>
31#include <linux/platform_data/irq-renesas-irqc.h>
32
33#define IRQC_IRQ_MAX 32 /* maximum 32 interrupts per driver instance */
34
35#define IRQC_REQ_STS 0x00
36#define IRQC_EN_STS 0x04
37#define IRQC_EN_SET 0x08
38#define IRQC_INT_CPU_BASE(n) (0x000 + ((n) * 0x10))
39#define DETECT_STATUS 0x100
40#define IRQC_CONFIG(n) (0x180 + ((n) * 0x04))
41
42struct irqc_irq {
43 int hw_irq;
44 int requested_irq;
45 int domain_irq;
46 struct irqc_priv *p;
47};
48
49struct irqc_priv {
50 void __iomem *iomem;
51 void __iomem *cpu_int_base;
52 struct irqc_irq irq[IRQC_IRQ_MAX];
53 struct renesas_irqc_config config;
54 unsigned int number_of_irqs;
55 struct platform_device *pdev;
56 struct irq_chip irq_chip;
57 struct irq_domain *irq_domain;
58};
59
60static void irqc_dbg(struct irqc_irq *i, char *str)
61{
62 dev_dbg(&i->p->pdev->dev, "%s (%d:%d:%d)\n",
63 str, i->requested_irq, i->hw_irq, i->domain_irq);
64}
65
66static void irqc_irq_enable(struct irq_data *d)
67{
68 struct irqc_priv *p = irq_data_get_irq_chip_data(d);
69 int hw_irq = irqd_to_hwirq(d);
70
71 irqc_dbg(&p->irq[hw_irq], "enable");
72 iowrite32(BIT(hw_irq), p->cpu_int_base + IRQC_EN_SET);
73}
74
75static void irqc_irq_disable(struct irq_data *d)
76{
77 struct irqc_priv *p = irq_data_get_irq_chip_data(d);
78 int hw_irq = irqd_to_hwirq(d);
79
80 irqc_dbg(&p->irq[hw_irq], "disable");
81 iowrite32(BIT(hw_irq), p->cpu_int_base + IRQC_EN_STS);
82}
83
84#define INTC_IRQ_SENSE_VALID 0x10
85#define INTC_IRQ_SENSE(x) (x + INTC_IRQ_SENSE_VALID)
86
87static unsigned char irqc_sense[IRQ_TYPE_SENSE_MASK + 1] = {
88 [IRQ_TYPE_LEVEL_LOW] = INTC_IRQ_SENSE(0x01),
89 [IRQ_TYPE_LEVEL_HIGH] = INTC_IRQ_SENSE(0x02),
90 [IRQ_TYPE_EDGE_FALLING] = INTC_IRQ_SENSE(0x04), /* Synchronous */
91 [IRQ_TYPE_EDGE_RISING] = INTC_IRQ_SENSE(0x08), /* Synchronous */
92 [IRQ_TYPE_EDGE_BOTH] = INTC_IRQ_SENSE(0x0c), /* Synchronous */
93};
94
95static int irqc_irq_set_type(struct irq_data *d, unsigned int type)
96{
97 struct irqc_priv *p = irq_data_get_irq_chip_data(d);
98 int hw_irq = irqd_to_hwirq(d);
99 unsigned char value = irqc_sense[type & IRQ_TYPE_SENSE_MASK];
100 unsigned long tmp;
101
102 irqc_dbg(&p->irq[hw_irq], "sense");
103
104 if (!(value & INTC_IRQ_SENSE_VALID))
105 return -EINVAL;
106
107 tmp = ioread32(p->iomem + IRQC_CONFIG(hw_irq));
108 tmp &= ~0x3f;
109 tmp |= value ^ INTC_IRQ_SENSE_VALID;
110 iowrite32(tmp, p->iomem + IRQC_CONFIG(hw_irq));
111 return 0;
112}
113
114static irqreturn_t irqc_irq_handler(int irq, void *dev_id)
115{
116 struct irqc_irq *i = dev_id;
117 struct irqc_priv *p = i->p;
118 unsigned long bit = BIT(i->hw_irq);
119
120 irqc_dbg(i, "demux1");
121
122 if (ioread32(p->iomem + DETECT_STATUS) & bit) {
123 iowrite32(bit, p->iomem + DETECT_STATUS);
124 irqc_dbg(i, "demux2");
125 generic_handle_irq(i->domain_irq);
126 return IRQ_HANDLED;
127 }
128 return IRQ_NONE;
129}
130
131static int irqc_irq_domain_map(struct irq_domain *h, unsigned int virq,
132 irq_hw_number_t hw)
133{
134 struct irqc_priv *p = h->host_data;
135
136 p->irq[hw].domain_irq = virq;
137 p->irq[hw].hw_irq = hw;
138
139 irqc_dbg(&p->irq[hw], "map");
140 irq_set_chip_data(virq, h->host_data);
141 irq_set_chip_and_handler(virq, &p->irq_chip, handle_level_irq);
142 set_irq_flags(virq, IRQF_VALID); /* kill me now */
143 return 0;
144}
145
146static struct irq_domain_ops irqc_irq_domain_ops = {
147 .map = irqc_irq_domain_map,
148 .xlate = irq_domain_xlate_twocell,
149};
150
151static int irqc_probe(struct platform_device *pdev)
152{
153 struct renesas_irqc_config *pdata = pdev->dev.platform_data;
154 struct irqc_priv *p;
155 struct resource *io;
156 struct resource *irq;
157 struct irq_chip *irq_chip;
158 const char *name = dev_name(&pdev->dev);
159 int ret;
160 int k;
161
162 p = kzalloc(sizeof(*p), GFP_KERNEL);
163 if (!p) {
164 dev_err(&pdev->dev, "failed to allocate driver data\n");
165 ret = -ENOMEM;
166 goto err0;
167 }
168
169 /* deal with driver instance configuration */
170 if (pdata)
171 memcpy(&p->config, pdata, sizeof(*pdata));
172
173 p->pdev = pdev;
174 platform_set_drvdata(pdev, p);
175
176 /* get hold of manadatory IOMEM */
177 io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
178 if (!io) {
179 dev_err(&pdev->dev, "not enough IOMEM resources\n");
180 ret = -EINVAL;
181 goto err1;
182 }
183
184 /* allow any number of IRQs between 1 and IRQC_IRQ_MAX */
185 for (k = 0; k < IRQC_IRQ_MAX; k++) {
186 irq = platform_get_resource(pdev, IORESOURCE_IRQ, k);
187 if (!irq)
188 break;
189
190 p->irq[k].p = p;
191 p->irq[k].requested_irq = irq->start;
192 }
193
194 p->number_of_irqs = k;
195 if (p->number_of_irqs < 1) {
196 dev_err(&pdev->dev, "not enough IRQ resources\n");
197 ret = -EINVAL;
198 goto err1;
199 }
200
201 /* ioremap IOMEM and setup read/write callbacks */
202 p->iomem = ioremap_nocache(io->start, resource_size(io));
203 if (!p->iomem) {
204 dev_err(&pdev->dev, "failed to remap IOMEM\n");
205 ret = -ENXIO;
206 goto err2;
207 }
208
209 p->cpu_int_base = p->iomem + IRQC_INT_CPU_BASE(0); /* SYS-SPI */
210
211 irq_chip = &p->irq_chip;
212 irq_chip->name = name;
213 irq_chip->irq_mask = irqc_irq_disable;
214 irq_chip->irq_unmask = irqc_irq_enable;
215 irq_chip->irq_enable = irqc_irq_enable;
216 irq_chip->irq_disable = irqc_irq_disable;
217 irq_chip->irq_set_type = irqc_irq_set_type;
218 irq_chip->flags = IRQCHIP_SKIP_SET_WAKE;
219
220 p->irq_domain = irq_domain_add_simple(pdev->dev.of_node,
221 p->number_of_irqs,
222 p->config.irq_base,
223 &irqc_irq_domain_ops, p);
224 if (!p->irq_domain) {
225 ret = -ENXIO;
226 dev_err(&pdev->dev, "cannot initialize irq domain\n");
227 goto err2;
228 }
229
230 /* request interrupts one by one */
231 for (k = 0; k < p->number_of_irqs; k++) {
232 if (request_irq(p->irq[k].requested_irq, irqc_irq_handler,
233 0, name, &p->irq[k])) {
234 dev_err(&pdev->dev, "failed to request IRQ\n");
235 ret = -ENOENT;
236 goto err3;
237 }
238 }
239
240 dev_info(&pdev->dev, "driving %d irqs\n", p->number_of_irqs);
241
242 /* warn in case of mismatch if irq base is specified */
243 if (p->config.irq_base) {
244 if (p->config.irq_base != p->irq[0].domain_irq)
245 dev_warn(&pdev->dev, "irq base mismatch (%d/%d)\n",
246 p->config.irq_base, p->irq[0].domain_irq);
247 }
248
249 return 0;
250err3:
251 for (; k >= 0; k--)
252 free_irq(p->irq[k - 1].requested_irq, &p->irq[k - 1]);
253
254 irq_domain_remove(p->irq_domain);
255err2:
256 iounmap(p->iomem);
257err1:
258 kfree(p);
259err0:
260 return ret;
261}
262
263static int irqc_remove(struct platform_device *pdev)
264{
265 struct irqc_priv *p = platform_get_drvdata(pdev);
266 int k;
267
268 for (k = 0; k < p->number_of_irqs; k++)
269 free_irq(p->irq[k].requested_irq, &p->irq[k]);
270
271 irq_domain_remove(p->irq_domain);
272 iounmap(p->iomem);
273 kfree(p);
274 return 0;
275}
276
277static const struct of_device_id irqc_dt_ids[] = {
278 { .compatible = "renesas,irqc", },
279 {},
280};
281MODULE_DEVICE_TABLE(of, irqc_dt_ids);
282
283static struct platform_driver irqc_device_driver = {
284 .probe = irqc_probe,
285 .remove = irqc_remove,
286 .driver = {
287 .name = "renesas_irqc",
288 .of_match_table = irqc_dt_ids,
289 .owner = THIS_MODULE,
290 }
291};
292
293static int __init irqc_init(void)
294{
295 return platform_driver_register(&irqc_device_driver);
296}
297postcore_initcall(irqc_init);
298
299static void __exit irqc_exit(void)
300{
301 platform_driver_unregister(&irqc_device_driver);
302}
303module_exit(irqc_exit);
304
305MODULE_AUTHOR("Magnus Damm");
306MODULE_DESCRIPTION("Renesas IRQC Driver");
307MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh73a0.c b/drivers/pinctrl/sh-pfc/pfc-sh73a0.c
index 709008e94124..6f15c03077a0 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh73a0.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh73a0.c
@@ -2733,9 +2733,9 @@ static struct pinmux_data_reg pinmux_data_regs[] = {
2733 { }, 2733 { },
2734}; 2734};
2735 2735
2736/* IRQ pins through INTCS with IRQ0->15 from 0x200 and IRQ16-31 from 0x3200 */ 2736/* External IRQ pins mapped at IRQPIN_BASE */
2737#define EXT_IRQ16L(n) intcs_evt2irq(0x200 + ((n) << 5)) 2737#define EXT_IRQ16L(n) irq_pin(n)
2738#define EXT_IRQ16H(n) intcs_evt2irq(0x3200 + ((n - 16) << 5)) 2738#define EXT_IRQ16H(n) irq_pin(n)
2739 2739
2740static struct pinmux_irq pinmux_irqs[] = { 2740static struct pinmux_irq pinmux_irqs[] = {
2741 PINMUX_IRQ(EXT_IRQ16H(19), PORT9_FN0), 2741 PINMUX_IRQ(EXT_IRQ16H(19), PORT9_FN0),