1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se> |
4 | * Copyright (C) 2014 Stefan Kristansson <stefan.kristiansson@saunalahti.fi> |
5 | */ |
6 | |
7 | #include <linux/irq.h> |
8 | #include <linux/irqchip.h> |
9 | #include <linux/of.h> |
10 | #include <linux/of_irq.h> |
11 | #include <linux/of_address.h> |
12 | |
13 | /* OR1K PIC implementation */ |
14 | |
15 | struct or1k_pic_dev { |
16 | struct irq_chip chip; |
17 | irq_flow_handler_t handle; |
18 | unsigned long flags; |
19 | }; |
20 | |
21 | /* |
22 | * We're a couple of cycles faster than the generic implementations with |
23 | * these 'fast' versions. |
24 | */ |
25 | |
26 | static void or1k_pic_mask(struct irq_data *data) |
27 | { |
28 | mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1UL << data->hwirq)); |
29 | } |
30 | |
31 | static void or1k_pic_unmask(struct irq_data *data) |
32 | { |
33 | mtspr(SPR_PICMR, mfspr(SPR_PICMR) | (1UL << data->hwirq)); |
34 | } |
35 | |
36 | static void or1k_pic_ack(struct irq_data *data) |
37 | { |
38 | mtspr(SPR_PICSR, (1UL << data->hwirq)); |
39 | } |
40 | |
41 | static void or1k_pic_mask_ack(struct irq_data *data) |
42 | { |
43 | mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1UL << data->hwirq)); |
44 | mtspr(SPR_PICSR, (1UL << data->hwirq)); |
45 | } |
46 | |
47 | /* |
48 | * There are two oddities with the OR1200 PIC implementation: |
49 | * i) LEVEL-triggered interrupts are latched and need to be cleared |
50 | * ii) the interrupt latch is cleared by writing a 0 to the bit, |
51 | * as opposed to a 1 as mandated by the spec |
52 | */ |
53 | static void or1k_pic_or1200_ack(struct irq_data *data) |
54 | { |
55 | mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(1UL << data->hwirq)); |
56 | } |
57 | |
58 | static void or1k_pic_or1200_mask_ack(struct irq_data *data) |
59 | { |
60 | mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1UL << data->hwirq)); |
61 | mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(1UL << data->hwirq)); |
62 | } |
63 | |
64 | static struct or1k_pic_dev or1k_pic_level = { |
65 | .chip = { |
66 | .name = "or1k-PIC-level" , |
67 | .irq_unmask = or1k_pic_unmask, |
68 | .irq_mask = or1k_pic_mask, |
69 | }, |
70 | .handle = handle_level_irq, |
71 | .flags = IRQ_LEVEL | IRQ_NOPROBE, |
72 | }; |
73 | |
74 | static struct or1k_pic_dev or1k_pic_edge = { |
75 | .chip = { |
76 | .name = "or1k-PIC-edge" , |
77 | .irq_unmask = or1k_pic_unmask, |
78 | .irq_mask = or1k_pic_mask, |
79 | .irq_ack = or1k_pic_ack, |
80 | .irq_mask_ack = or1k_pic_mask_ack, |
81 | }, |
82 | .handle = handle_edge_irq, |
83 | .flags = IRQ_LEVEL | IRQ_NOPROBE, |
84 | }; |
85 | |
86 | static struct or1k_pic_dev or1k_pic_or1200 = { |
87 | .chip = { |
88 | .name = "or1200-PIC" , |
89 | .irq_unmask = or1k_pic_unmask, |
90 | .irq_mask = or1k_pic_mask, |
91 | .irq_ack = or1k_pic_or1200_ack, |
92 | .irq_mask_ack = or1k_pic_or1200_mask_ack, |
93 | }, |
94 | .handle = handle_level_irq, |
95 | .flags = IRQ_LEVEL | IRQ_NOPROBE, |
96 | }; |
97 | |
98 | static struct irq_domain *root_domain; |
99 | |
100 | static inline int pic_get_irq(int first) |
101 | { |
102 | int hwirq; |
103 | |
104 | hwirq = ffs(mfspr(SPR_PICSR) >> first); |
105 | if (!hwirq) |
106 | return NO_IRQ; |
107 | else |
108 | hwirq = hwirq + first - 1; |
109 | |
110 | return hwirq; |
111 | } |
112 | |
113 | static void or1k_pic_handle_irq(struct pt_regs *regs) |
114 | { |
115 | int irq = -1; |
116 | |
117 | while ((irq = pic_get_irq(first: irq + 1)) != NO_IRQ) |
118 | generic_handle_domain_irq(domain: root_domain, hwirq: irq); |
119 | } |
120 | |
121 | static int or1k_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) |
122 | { |
123 | struct or1k_pic_dev *pic = d->host_data; |
124 | |
125 | irq_set_chip_and_handler(irq, chip: &pic->chip, handle: pic->handle); |
126 | irq_set_status_flags(irq, set: pic->flags); |
127 | |
128 | return 0; |
129 | } |
130 | |
131 | static const struct irq_domain_ops or1k_irq_domain_ops = { |
132 | .xlate = irq_domain_xlate_onecell, |
133 | .map = or1k_map, |
134 | }; |
135 | |
136 | /* |
137 | * This sets up the IRQ domain for the PIC built in to the OpenRISC |
138 | * 1000 CPU. This is the "root" domain as these are the interrupts |
139 | * that directly trigger an exception in the CPU. |
140 | */ |
141 | static int __init or1k_pic_init(struct device_node *node, |
142 | struct or1k_pic_dev *pic) |
143 | { |
144 | /* Disable all interrupts until explicitly requested */ |
145 | mtspr(SPR_PICMR, (0UL)); |
146 | |
147 | root_domain = irq_domain_add_linear(of_node: node, size: 32, ops: &or1k_irq_domain_ops, |
148 | host_data: pic); |
149 | |
150 | set_handle_irq(or1k_pic_handle_irq); |
151 | |
152 | return 0; |
153 | } |
154 | |
155 | static int __init or1k_pic_or1200_init(struct device_node *node, |
156 | struct device_node *parent) |
157 | { |
158 | return or1k_pic_init(node, pic: &or1k_pic_or1200); |
159 | } |
160 | IRQCHIP_DECLARE(or1k_pic_or1200, "opencores,or1200-pic" , or1k_pic_or1200_init); |
161 | IRQCHIP_DECLARE(or1k_pic, "opencores,or1k-pic" , or1k_pic_or1200_init); |
162 | |
163 | static int __init or1k_pic_level_init(struct device_node *node, |
164 | struct device_node *parent) |
165 | { |
166 | return or1k_pic_init(node, pic: &or1k_pic_level); |
167 | } |
168 | IRQCHIP_DECLARE(or1k_pic_level, "opencores,or1k-pic-level" , |
169 | or1k_pic_level_init); |
170 | |
171 | static int __init or1k_pic_edge_init(struct device_node *node, |
172 | struct device_node *parent) |
173 | { |
174 | return or1k_pic_init(node, pic: &or1k_pic_edge); |
175 | } |
176 | IRQCHIP_DECLARE(or1k_pic_edge, "opencores,or1k-pic-edge" , or1k_pic_edge_init); |
177 | |