14e6670feSJoseph Chen /*
24e6670feSJoseph Chen * (C) Copyright 2017 Rockchip Electronics Co., Ltd
34e6670feSJoseph Chen *
44e6670feSJoseph Chen * SPDX-License-Identifier: GPL-2.0+
54e6670feSJoseph Chen */
64e6670feSJoseph Chen
74e6670feSJoseph Chen #include <asm/io.h>
84e6670feSJoseph Chen #include <asm/u-boot-arm.h>
9ae63f119SJoseph Chen #include <dm.h>
104e6670feSJoseph Chen #include <irq-generic.h>
11cf344252SJoseph Chen #include "irq-internal.h"
124e6670feSJoseph Chen
134e6670feSJoseph Chen DECLARE_GLOBAL_DATA_PTR;
144e6670feSJoseph Chen
154e6670feSJoseph Chen struct irq_desc {
1642865eb5SJoseph Chen interrupt_handler_t *handle_irq;
1742865eb5SJoseph Chen void *data;
18ae63f119SJoseph Chen u32 flag;
19ae63f119SJoseph Chen u32 count;
204e6670feSJoseph Chen };
214e6670feSJoseph Chen
22cf344252SJoseph Chen struct irqchip_desc {
23cf344252SJoseph Chen struct irq_chip *gic;
24cf344252SJoseph Chen struct irq_chip *gpio;
2541766119SJoseph Chen struct irq_chip *virq;
2641766119SJoseph Chen
272c4e90c1SJoseph Chen int suspend_irq[PLATFORM_SUSPEND_MAX_IRQ];
282c4e90c1SJoseph Chen int suspend_num;
29cf344252SJoseph Chen };
304e6670feSJoseph Chen
31cf344252SJoseph Chen static struct irq_desc irq_desc[PLATFORM_MAX_IRQ];
32cf344252SJoseph Chen static struct irqchip_desc irqchip;
33cf344252SJoseph Chen static bool intr_setup;
34cf344252SJoseph Chen
bad_irq(int irq)35cf344252SJoseph Chen int bad_irq(int irq)
364e6670feSJoseph Chen {
37cf344252SJoseph Chen if (!intr_setup) {
38cf344252SJoseph Chen IRQ_W("Interrupt framework is not setup\n");
394e6670feSJoseph Chen return -EINVAL;
404e6670feSJoseph Chen }
414e6670feSJoseph Chen
4241766119SJoseph Chen if (irq < PLATFORM_MAX_IRQ) {
4341766119SJoseph Chen if (!irq_desc[irq].handle_irq)
4441766119SJoseph Chen return -EINVAL;
4541766119SJoseph Chen } else {
4641766119SJoseph Chen if (bad_virq(irq)) {
4741766119SJoseph Chen IRQ_E("Unknown virq: %d\n", irq);
484e6670feSJoseph Chen return -EINVAL;
494e6670feSJoseph Chen }
5041766119SJoseph Chen }
514e6670feSJoseph Chen
5241766119SJoseph Chen return 0;
534e6670feSJoseph Chen }
544e6670feSJoseph Chen
554e6670feSJoseph Chen /* general interrupt handler for gpio chip */
__generic_gpio_handle_irq(int irq)56269512fdSJoseph Chen void __generic_gpio_handle_irq(int irq)
574e6670feSJoseph Chen {
58269512fdSJoseph Chen if (bad_irq(irq))
594e6670feSJoseph Chen return;
604e6670feSJoseph Chen
61cf344252SJoseph Chen if (irq < PLATFORM_GIC_MAX_IRQ) {
62cf344252SJoseph Chen IRQ_W("IRQ %d: Invalid GPIO irq\n", irq);
634e6670feSJoseph Chen return;
644e6670feSJoseph Chen }
654e6670feSJoseph Chen
66ae63f119SJoseph Chen if (irq_desc[irq].handle_irq) {
67ae63f119SJoseph Chen irq_desc[irq].count++;
68cf344252SJoseph Chen irq_desc[irq].handle_irq(irq, irq_desc[irq].data);
694e6670feSJoseph Chen }
70ae63f119SJoseph Chen }
714e6670feSJoseph Chen
__do_generic_irq_handler(void)72269512fdSJoseph Chen void __do_generic_irq_handler(void)
734e6670feSJoseph Chen {
74cf344252SJoseph Chen u32 irq;
754e6670feSJoseph Chen
76cf344252SJoseph Chen assert(irqchip.gic->irq_get);
77cf344252SJoseph Chen assert(irqchip.gic->irq_eoi);
78cf344252SJoseph Chen
79cf344252SJoseph Chen irq = irqchip.gic->irq_get();
80cf344252SJoseph Chen
81cf344252SJoseph Chen if (irq < PLATFORM_GIC_MAX_IRQ) {
82ae63f119SJoseph Chen if (irq_desc[irq].handle_irq) {
83ae63f119SJoseph Chen irq_desc[irq].count++;
84cf344252SJoseph Chen irq_desc[irq].handle_irq(irq, irq_desc[irq].data);
854e6670feSJoseph Chen }
86ae63f119SJoseph Chen }
874e6670feSJoseph Chen
88cf344252SJoseph Chen irqchip.gic->irq_eoi(irq);
894e6670feSJoseph Chen }
904e6670feSJoseph Chen
irq_is_busy(int irq)918696cc38SJoseph Chen int irq_is_busy(int irq)
928696cc38SJoseph Chen {
93cf344252SJoseph Chen return (irq >= 0 && irq_desc[irq].handle_irq) ? -EBUSY : 0;
948696cc38SJoseph Chen }
958696cc38SJoseph Chen
bad_irq_chip(struct irq_chip * chip)96269512fdSJoseph Chen static int bad_irq_chip(struct irq_chip *chip)
974e6670feSJoseph Chen {
98cf344252SJoseph Chen return (!chip->name || !chip->irq_init || !chip->irq_enable ||
9941766119SJoseph Chen !chip->irq_disable) ? -EINVAL : 0;
1004e6670feSJoseph Chen }
1014e6670feSJoseph Chen
__do_arch_irq_init(void)102269512fdSJoseph Chen static int __do_arch_irq_init(void)
1034e6670feSJoseph Chen {
104cf344252SJoseph Chen int ret = -EINVAL;
1054e6670feSJoseph Chen
106cf344252SJoseph Chen /* After relocation done, bss data intr_setup */
1074e6670feSJoseph Chen if (!(gd->flags & GD_FLG_RELOC)) {
108269512fdSJoseph Chen IRQ_W("Interrupt framework should initialize after reloc\n");
1094e6670feSJoseph Chen return -EINVAL;
1104e6670feSJoseph Chen }
1114e6670feSJoseph Chen
1124e6670feSJoseph Chen /*
113269512fdSJoseph Chen * We set true before arch_gpio_irq_init() to avoid fail when
114269512fdSJoseph Chen * request irq for gpio banks.
1154e6670feSJoseph Chen */
116cf344252SJoseph Chen intr_setup = true;
117cf344252SJoseph Chen memset(irq_desc, 0, sizeof(irq_desc));
1184e6670feSJoseph Chen
119cf344252SJoseph Chen irqchip.gic = arch_gic_get_irqchip();
120cf344252SJoseph Chen if (bad_irq_chip(irqchip.gic)) {
121269512fdSJoseph Chen IRQ_E("Bad gic irqchip\n");
1224e6670feSJoseph Chen goto out;
1234e6670feSJoseph Chen }
1244e6670feSJoseph Chen
125cf344252SJoseph Chen irqchip.gpio = arch_gpio_get_irqchip();
126cf344252SJoseph Chen if (bad_irq_chip(irqchip.gpio)) {
127269512fdSJoseph Chen IRQ_E("Bad gpio irqchip\n");
1284e6670feSJoseph Chen goto out;
1294e6670feSJoseph Chen }
1304e6670feSJoseph Chen
13141766119SJoseph Chen irqchip.virq = arch_virq_get_irqchip();
13241766119SJoseph Chen if (bad_irq_chip(irqchip.virq)) {
13341766119SJoseph Chen IRQ_E("Bad virq irqchip\n");
13441766119SJoseph Chen goto out;
13541766119SJoseph Chen }
13641766119SJoseph Chen
137cf344252SJoseph Chen ret = irqchip.gic->irq_init();
138cf344252SJoseph Chen if (ret) {
139cf344252SJoseph Chen IRQ_E("GIC Interrupt setup failed, ret=%d\n", ret);
1404e6670feSJoseph Chen goto out;
1414e6670feSJoseph Chen }
1424e6670feSJoseph Chen
143cf344252SJoseph Chen ret = irqchip.gpio->irq_init();
144cf344252SJoseph Chen if (ret) {
145cf344252SJoseph Chen IRQ_E("GPIO Interrupt setup failed, ret=%d\n", ret);
1464e6670feSJoseph Chen goto out;
1474e6670feSJoseph Chen }
1484e6670feSJoseph Chen
14941766119SJoseph Chen ret = irqchip.virq->irq_init();
15041766119SJoseph Chen if (ret) {
15141766119SJoseph Chen IRQ_E("VIRQ Interrupt setup failed, ret=%d\n", ret);
15241766119SJoseph Chen goto out;
15341766119SJoseph Chen }
15441766119SJoseph Chen
1554e6670feSJoseph Chen return 0;
1564e6670feSJoseph Chen
1574e6670feSJoseph Chen out:
158cf344252SJoseph Chen intr_setup = false;
1594e6670feSJoseph Chen
160cf344252SJoseph Chen return ret;
1614e6670feSJoseph Chen }
1624e6670feSJoseph Chen
irq_handler_enable(int irq)1634e6670feSJoseph Chen int irq_handler_enable(int irq)
1644e6670feSJoseph Chen {
165ae63f119SJoseph Chen int ret;
166ae63f119SJoseph Chen
167269512fdSJoseph Chen if (bad_irq(irq))
1684e6670feSJoseph Chen return -EINVAL;
1694e6670feSJoseph Chen
170cf344252SJoseph Chen if (irq < PLATFORM_GIC_MAX_IRQ)
171ae63f119SJoseph Chen ret = irqchip.gic->irq_enable(irq);
17241766119SJoseph Chen else if (irq < PLATFORM_GPIO_MAX_IRQ)
173ae63f119SJoseph Chen ret = irqchip.gpio->irq_enable(irq);
17441766119SJoseph Chen else
175ae63f119SJoseph Chen ret = irqchip.virq->irq_enable(irq);
176ae63f119SJoseph Chen
177ae63f119SJoseph Chen if (!ret && irq < PLATFORM_MAX_IRQ)
178ae63f119SJoseph Chen irq_desc[irq].flag |= IRQ_FLG_ENABLE;
179ae63f119SJoseph Chen
180ae63f119SJoseph Chen return ret;
1814e6670feSJoseph Chen }
1824e6670feSJoseph Chen
irq_handler_disable(int irq)1834e6670feSJoseph Chen int irq_handler_disable(int irq)
1844e6670feSJoseph Chen {
185ae63f119SJoseph Chen int ret;
186ae63f119SJoseph Chen
187269512fdSJoseph Chen if (bad_irq(irq))
1884e6670feSJoseph Chen return -EINVAL;
1894e6670feSJoseph Chen
190cf344252SJoseph Chen if (irq < PLATFORM_GIC_MAX_IRQ)
191ae63f119SJoseph Chen ret = irqchip.gic->irq_disable(irq);
19241766119SJoseph Chen else if (irq < PLATFORM_GPIO_MAX_IRQ)
193ae63f119SJoseph Chen ret = irqchip.gpio->irq_disable(irq);
19441766119SJoseph Chen else
195ae63f119SJoseph Chen ret = irqchip.virq->irq_disable(irq);
196ae63f119SJoseph Chen
197ae63f119SJoseph Chen if (!ret && irq < PLATFORM_MAX_IRQ)
198ae63f119SJoseph Chen irq_desc[irq].flag &= ~IRQ_FLG_ENABLE;
199ae63f119SJoseph Chen
200ae63f119SJoseph Chen return ret;
2014e6670feSJoseph Chen }
2024e6670feSJoseph Chen
irq_set_irq_type(int irq,unsigned int type)2034e6670feSJoseph Chen int irq_set_irq_type(int irq, unsigned int type)
2044e6670feSJoseph Chen {
205269512fdSJoseph Chen if (bad_irq(irq))
2064e6670feSJoseph Chen return -EINVAL;
2074e6670feSJoseph Chen
208cf344252SJoseph Chen if (irq < PLATFORM_GIC_MAX_IRQ)
209cf344252SJoseph Chen return irqchip.gic->irq_set_type(irq, type);
21041766119SJoseph Chen else if (irq < PLATFORM_GPIO_MAX_IRQ)
211cf344252SJoseph Chen return irqchip.gpio->irq_set_type(irq, type);
21241766119SJoseph Chen else
21341766119SJoseph Chen return -ENOSYS;
2144e6670feSJoseph Chen }
2154e6670feSJoseph Chen
irq_revert_irq_type(int irq)216c234b81eSJoseph Chen int irq_revert_irq_type(int irq)
217c234b81eSJoseph Chen {
218269512fdSJoseph Chen if (bad_irq(irq))
219c234b81eSJoseph Chen return -EINVAL;
220c234b81eSJoseph Chen
221cf344252SJoseph Chen if (irq < PLATFORM_GIC_MAX_IRQ)
222c234b81eSJoseph Chen return 0;
22341766119SJoseph Chen else if (irq < PLATFORM_GPIO_MAX_IRQ)
224cf344252SJoseph Chen return irqchip.gpio->irq_revert_type(irq);
22541766119SJoseph Chen else
22641766119SJoseph Chen return -ENOSYS;
227c234b81eSJoseph Chen }
228c234b81eSJoseph Chen
irq_get_gpio_level(int irq)229c234b81eSJoseph Chen int irq_get_gpio_level(int irq)
230c234b81eSJoseph Chen {
231269512fdSJoseph Chen if (bad_irq(irq))
232c234b81eSJoseph Chen return -EINVAL;
233c234b81eSJoseph Chen
234cf344252SJoseph Chen if (irq < PLATFORM_GIC_MAX_IRQ)
235c234b81eSJoseph Chen return 0;
23641766119SJoseph Chen else if (irq < PLATFORM_GPIO_MAX_IRQ)
237cf344252SJoseph Chen return irqchip.gpio->irq_get_gpio_level(irq);
23841766119SJoseph Chen else
23941766119SJoseph Chen return -ENOSYS;
240c234b81eSJoseph Chen }
241c234b81eSJoseph Chen
irq_install_handler(int irq,interrupt_handler_t * handler,void * data)2424e6670feSJoseph Chen void irq_install_handler(int irq, interrupt_handler_t *handler, void *data)
2434e6670feSJoseph Chen {
244cf344252SJoseph Chen if (!intr_setup) {
245cf344252SJoseph Chen IRQ_W("Interrupt framework is not intr_setup\n");
2464e6670feSJoseph Chen return;
247269512fdSJoseph Chen }
248269512fdSJoseph Chen
24941766119SJoseph Chen if (irq < PLATFORM_MAX_IRQ) {
250cf344252SJoseph Chen if (!handler || irq_desc[irq].handle_irq)
251cf344252SJoseph Chen return;
252cf344252SJoseph Chen irq_desc[irq].handle_irq = handler;
253cf344252SJoseph Chen irq_desc[irq].data = data;
25441766119SJoseph Chen } else {
25541766119SJoseph Chen virq_install_handler(irq, handler, data);
25641766119SJoseph Chen }
2574e6670feSJoseph Chen }
2584e6670feSJoseph Chen
irq_free_handler(int irq)2594e6670feSJoseph Chen void irq_free_handler(int irq)
2604e6670feSJoseph Chen {
2610e508c4fSJoseph Chen if (irq_handler_disable(irq))
2624e6670feSJoseph Chen return;
2634e6670feSJoseph Chen
26441766119SJoseph Chen if (irq < PLATFORM_MAX_IRQ) {
265cf344252SJoseph Chen irq_desc[irq].handle_irq = NULL;
266cf344252SJoseph Chen irq_desc[irq].data = NULL;
26741766119SJoseph Chen } else {
26841766119SJoseph Chen virq_free_handler(irq);
26941766119SJoseph Chen }
2704e6670feSJoseph Chen }
2714e6670feSJoseph Chen
irq_handler_enable_suspend_only(int irq)2722c4e90c1SJoseph Chen int irq_handler_enable_suspend_only(int irq)
2732c4e90c1SJoseph Chen {
2742c4e90c1SJoseph Chen if (bad_irq(irq))
2752c4e90c1SJoseph Chen return -EINVAL;
2762c4e90c1SJoseph Chen
2772c4e90c1SJoseph Chen if (irqchip.suspend_num >= PLATFORM_SUSPEND_MAX_IRQ) {
2782c4e90c1SJoseph Chen printf("Over max count(%d) of suspend irq\n",
2792c4e90c1SJoseph Chen PLATFORM_SUSPEND_MAX_IRQ);
2802c4e90c1SJoseph Chen return -EPERM;
2812c4e90c1SJoseph Chen }
2822c4e90c1SJoseph Chen
2832c4e90c1SJoseph Chen irqchip.suspend_irq[irqchip.suspend_num++] = irq;
2842c4e90c1SJoseph Chen return 0;
2852c4e90c1SJoseph Chen }
2862c4e90c1SJoseph Chen
irqs_suspend(void)287ed837edfSJoseph Chen int irqs_suspend(void)
288ed837edfSJoseph Chen {
2892c4e90c1SJoseph Chen int i;
2902c4e90c1SJoseph Chen
2912c4e90c1SJoseph Chen for (i = 0; i < irqchip.suspend_num; i++)
2922c4e90c1SJoseph Chen irq_handler_enable(irqchip.suspend_irq[i]);
2932c4e90c1SJoseph Chen
294cf344252SJoseph Chen return irqchip.gic->irq_suspend();
295ed837edfSJoseph Chen }
296ed837edfSJoseph Chen
irqs_resume(void)297ed837edfSJoseph Chen int irqs_resume(void)
298ed837edfSJoseph Chen {
2992c4e90c1SJoseph Chen int i;
3002c4e90c1SJoseph Chen
3012c4e90c1SJoseph Chen for (i = 0; i < irqchip.suspend_num; i++)
3022c4e90c1SJoseph Chen irq_handler_disable(irqchip.suspend_irq[i]);
3032c4e90c1SJoseph Chen
304cf344252SJoseph Chen return irqchip.gic->irq_resume();
305ed837edfSJoseph Chen }
306ed837edfSJoseph Chen
3074e6670feSJoseph Chen #ifdef CONFIG_ARM64
do_irq(struct pt_regs * pt_regs,unsigned int esr)3084e6670feSJoseph Chen void do_irq(struct pt_regs *pt_regs, unsigned int esr)
3094e6670feSJoseph Chen {
310c563adc7SJoseph Chen #ifdef CONFIG_ROCKCHIP_DEBUGGER
311c563adc7SJoseph Chen printf("\n>>> Rockchip Debugger:\n");
312c563adc7SJoseph Chen show_regs(pt_regs);
313c563adc7SJoseph Chen #endif
314c563adc7SJoseph Chen
315269512fdSJoseph Chen __do_generic_irq_handler();
3164e6670feSJoseph Chen }
3174e6670feSJoseph Chen #else
do_irq(struct pt_regs * pt_regs)3184e6670feSJoseph Chen void do_irq(struct pt_regs *pt_regs)
3194e6670feSJoseph Chen {
320c563adc7SJoseph Chen #ifdef CONFIG_ROCKCHIP_DEBUGGER
321c563adc7SJoseph Chen printf("\n>>> Rockchp Debugger:\n");
322c563adc7SJoseph Chen show_regs(pt_regs);
323c563adc7SJoseph Chen #endif
324c563adc7SJoseph Chen
325269512fdSJoseph Chen __do_generic_irq_handler();
3264e6670feSJoseph Chen }
3274e6670feSJoseph Chen #endif
3284e6670feSJoseph Chen
arch_interrupt_init(void)3294e6670feSJoseph Chen int arch_interrupt_init(void)
3304e6670feSJoseph Chen {
3314e6670feSJoseph Chen #ifndef CONFIG_ARM64
3324e6670feSJoseph Chen unsigned long cpsr __maybe_unused;
3334e6670feSJoseph Chen
3344e6670feSJoseph Chen /* stack has been reserved in: arch_reserve_stacks() */
3354e6670feSJoseph Chen IRQ_STACK_START = gd->irq_sp;
336c15709b5SJoseph Chen IRQ_STACK_START_IN = gd->irq_sp;
3374e6670feSJoseph Chen
3384e6670feSJoseph Chen __asm__ __volatile__("mrs %0, cpsr\n"
3394e6670feSJoseph Chen : "=r" (cpsr)
3404e6670feSJoseph Chen :
3414e6670feSJoseph Chen : "memory");
3424e6670feSJoseph Chen
3434e6670feSJoseph Chen __asm__ __volatile__("msr cpsr_c, %0\n"
3444e6670feSJoseph Chen "mov sp, %1\n"
3454e6670feSJoseph Chen :
3464e6670feSJoseph Chen : "r" (IRQ_MODE | I_BIT |
3474e6670feSJoseph Chen F_BIT | (cpsr & ~FIQ_MODE)),
3484e6670feSJoseph Chen "r" (IRQ_STACK_START)
3494e6670feSJoseph Chen : "memory");
3504e6670feSJoseph Chen
3514e6670feSJoseph Chen __asm__ __volatile__("msr cpsr_c, %0"
3524e6670feSJoseph Chen :
3534e6670feSJoseph Chen : "r" (cpsr)
3544e6670feSJoseph Chen : "memory");
3554e6670feSJoseph Chen #endif
356269512fdSJoseph Chen return __do_arch_irq_init();
3574e6670feSJoseph Chen }
3584e6670feSJoseph Chen
interrupt_init(void)3594e6670feSJoseph Chen int interrupt_init(void)
3604e6670feSJoseph Chen {
3614e6670feSJoseph Chen return arch_interrupt_init();
3624e6670feSJoseph Chen }
3634e6670feSJoseph Chen
enable_interrupts(void)3644e6670feSJoseph Chen void enable_interrupts(void)
3654e6670feSJoseph Chen {
366*54cbaa17SJoseph Chen local_irq_enable();
3674e6670feSJoseph Chen }
3684e6670feSJoseph Chen
disable_interrupts(void)3694e6670feSJoseph Chen int disable_interrupts(void)
3704e6670feSJoseph Chen {
371*54cbaa17SJoseph Chen int flags;
372*54cbaa17SJoseph Chen
373*54cbaa17SJoseph Chen local_irq_save(flags);
374*54cbaa17SJoseph Chen return flags;
3754e6670feSJoseph Chen }
37692f4f090SJoseph Chen
do_dump_irqs(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])37792f4f090SJoseph Chen static int do_dump_irqs(cmd_tbl_t *cmdtp, int flag,
37892f4f090SJoseph Chen int argc, char * const argv[])
37992f4f090SJoseph Chen
38092f4f090SJoseph Chen {
38192f4f090SJoseph Chen struct udevice *dev;
38292f4f090SJoseph Chen char *drv_name;
38392f4f090SJoseph Chen int pirq;
38492f4f090SJoseph Chen
38525c13168SJoseph Chen printf(" IRQ En Handler Driver Name Trig\n");
38692f4f090SJoseph Chen printf("----------------------------------------------------------------------\n");
38792f4f090SJoseph Chen
38892f4f090SJoseph Chen for (pirq = 0; pirq < PLATFORM_MAX_IRQ; pirq++) {
38992f4f090SJoseph Chen if (!irq_desc[pirq].handle_irq)
39092f4f090SJoseph Chen continue;
39192f4f090SJoseph Chen
39292f4f090SJoseph Chen dev = (struct udevice *)irq_desc[pirq].data;
39392f4f090SJoseph Chen if (strstr(dev->name, "gpio"))
39492f4f090SJoseph Chen drv_name = "IRQ";
39592f4f090SJoseph Chen else
39692f4f090SJoseph Chen drv_name = dev->driver->name;
39792f4f090SJoseph Chen
39892f4f090SJoseph Chen printf(" %3d %d 0x%08lx %-12s %-12s %d\n",
39992f4f090SJoseph Chen pirq, irq_desc[pirq].flag & IRQ_FLG_ENABLE ? 1 : 0,
40092f4f090SJoseph Chen (ulong)irq_desc[pirq].handle_irq,
40192f4f090SJoseph Chen drv_name, dev->name, irq_desc[pirq].count);
40292f4f090SJoseph Chen
40392f4f090SJoseph Chen virqs_show(pirq);
40492f4f090SJoseph Chen }
40592f4f090SJoseph Chen
40692f4f090SJoseph Chen return 0;
40792f4f090SJoseph Chen }
40892f4f090SJoseph Chen
40992f4f090SJoseph Chen U_BOOT_CMD(
41092f4f090SJoseph Chen dump_irqs, 1, 1, do_dump_irqs, "Dump IRQs", ""
41192f4f090SJoseph Chen );
412