1 // SPDX-License-Identifier: GPL-2.0-only
3 * Realtek RTL83XX architecture specific IRQ handling
5 * based on the original BSP
6 * Copyright (C) 2006-2012 Tony Wu (tonywu@realtek.com)
7 * Copyright (C) 2020 B. Koblitz
8 * Copyright (C) 2020 Bert Vermeulen <bert@biot.com>
9 * Copyright (C) 2020 John Crispin <john@phrozen.org>
12 #include <linux/irqchip.h>
13 #include <linux/spinlock.h>
14 #include <linux/of_address.h>
15 #include <asm/irq_cpu.h>
16 #include <linux/of_irq.h>
17 #include <asm/cevt-r4k.h>
19 #include <mach-rtl83xx.h>
22 #define REALTEK_CPU_IRQ_SHARED0 (MIPS_CPU_IRQ_BASE + 2)
23 #define REALTEK_CPU_IRQ_UART (MIPS_CPU_IRQ_BASE + 3)
24 #define REALTEK_CPU_IRQ_SWITCH (MIPS_CPU_IRQ_BASE + 4)
25 #define REALTEK_CPU_IRQ_SHARED1 (MIPS_CPU_IRQ_BASE + 5)
26 #define REALTEK_CPU_IRQ_EXTERNAL (MIPS_CPU_IRQ_BASE + 6)
27 #define REALTEK_CPU_IRQ_COUNTER (MIPS_CPU_IRQ_BASE + 7)
29 #define REG(x) (rtl83xx_ictl_base + x)
31 extern struct rtl83xx_soc_info soc_info
;
33 static DEFINE_RAW_SPINLOCK(irq_lock
);
34 static void __iomem
*rtl83xx_ictl_base
;
36 static void rtl83xx_ictl_enable_irq(struct irq_data
*i
)
41 raw_spin_lock_irqsave(&irq_lock
, flags
);
43 value
= rtl83xx_r32(REG(RTL83XX_ICTL_GIMR
));
44 value
|= BIT(i
->hwirq
);
45 rtl83xx_w32(value
, REG(RTL83XX_ICTL_GIMR
));
47 raw_spin_unlock_irqrestore(&irq_lock
, flags
);
50 static void rtl83xx_ictl_disable_irq(struct irq_data
*i
)
55 raw_spin_lock_irqsave(&irq_lock
, flags
);
57 value
= rtl83xx_r32(REG(RTL83XX_ICTL_GIMR
));
58 value
&= ~BIT(i
->hwirq
);
59 rtl83xx_w32(value
, REG(RTL83XX_ICTL_GIMR
));
61 raw_spin_unlock_irqrestore(&irq_lock
, flags
);
64 static struct irq_chip rtl83xx_ictl_irq
= {
66 .irq_enable
= rtl83xx_ictl_enable_irq
,
67 .irq_disable
= rtl83xx_ictl_disable_irq
,
68 .irq_ack
= rtl83xx_ictl_disable_irq
,
69 .irq_mask
= rtl83xx_ictl_disable_irq
,
70 .irq_unmask
= rtl83xx_ictl_enable_irq
,
71 .irq_eoi
= rtl83xx_ictl_enable_irq
,
74 static int intc_map(struct irq_domain
*d
, unsigned int irq
, irq_hw_number_t hw
)
76 irq_set_chip_and_handler(hw
, &rtl83xx_ictl_irq
, handle_level_irq
);
81 static const struct irq_domain_ops irq_domain_ops
= {
83 .xlate
= irq_domain_xlate_onecell
,
86 static void rtl838x_irq_dispatch(struct irq_desc
*desc
)
88 unsigned int pending
= rtl83xx_r32(REG(RTL83XX_ICTL_GIMR
)) & rtl83xx_r32(REG(RTL83XX_ICTL_GISR
));
91 struct irq_domain
*domain
= irq_desc_get_handler_data(desc
);
92 generic_handle_irq(irq_find_mapping(domain
, __ffs(pending
)));
98 asmlinkage
void plat_irq_dispatch(void)
100 unsigned int pending
;
102 pending
= read_c0_cause() & read_c0_status() & ST0_IM
;
104 if (pending
& CAUSEF_IP7
)
105 do_IRQ(REALTEK_CPU_IRQ_COUNTER
);
107 else if (pending
& CAUSEF_IP6
)
108 do_IRQ(REALTEK_CPU_IRQ_EXTERNAL
);
110 else if (pending
& CAUSEF_IP5
)
111 do_IRQ(REALTEK_CPU_IRQ_SHARED1
);
113 else if (pending
& CAUSEF_IP4
)
114 do_IRQ(REALTEK_CPU_IRQ_SWITCH
);
116 else if (pending
& CAUSEF_IP3
)
117 do_IRQ(REALTEK_CPU_IRQ_UART
);
119 else if (pending
& CAUSEF_IP2
)
120 do_IRQ(REALTEK_CPU_IRQ_SHARED0
);
123 spurious_interrupt();
126 static void __init
icu_of_init(struct device_node
*node
, struct device_node
*parent
)
128 struct irq_domain
*domain
;
130 domain
= irq_domain_add_simple(node
, 32, 0,
131 &irq_domain_ops
, NULL
);
132 irq_set_chained_handler_and_data(2, rtl838x_irq_dispatch
, domain
);
133 irq_set_chained_handler_and_data(5, rtl838x_irq_dispatch
, domain
);
135 rtl83xx_ictl_base
= of_iomap(node
, 0);
136 if (!rtl83xx_ictl_base
)
139 /* Disable all cascaded interrupts */
140 rtl83xx_w32(0, REG(RTL83XX_ICTL_GIMR
));
142 /* Set up interrupt routing */
143 rtl83xx_w32(RTL83XX_IRR0_SETTING
, REG(RTL83XX_IRR0
));
144 rtl83xx_w32(RTL83XX_IRR1_SETTING
, REG(RTL83XX_IRR1
));
145 rtl83xx_w32(RTL83XX_IRR2_SETTING
, REG(RTL83XX_IRR2
));
146 rtl83xx_w32(RTL83XX_IRR3_SETTING
, REG(RTL83XX_IRR3
));
148 /* Clear timer interrupt */
151 /* Enable all CPU interrupts */
152 write_c0_status(read_c0_status() | ST0_IM
);
154 /* Enable timer0 and uart0 interrupts */
155 rtl83xx_w32(BIT(RTL83XX_IRQ_TC0
) | BIT(RTL83XX_IRQ_UART0
), REG(RTL83XX_ICTL_GIMR
));
158 static struct of_device_id __initdata of_irq_ids
[] = {
159 { .compatible
= "mti,cpu-interrupt-controller", .data
= mips_cpu_irq_of_init
},
160 { .compatible
= "realtek,rt8380-intc", .data
= icu_of_init
},
164 void __init
arch_init_irq(void)
166 of_irq_init(of_irq_ids
);