1// SPDX-License-Identifier: GPL-2.0
2#include <linux/types.h>
3#include <linux/kernel.h>
4#include <linux/irq.h>
5#include <linux/smp.h>
6#include <linux/interrupt.h>
7#include <linux/init.h>
8#include <linux/cpu.h>
9#include <linux/of.h>
10#include <linux/spinlock.h>
11#include <linux/msi.h>
12
13#include <asm/smp.h>
14#include <asm/machdep.h>
15#include <asm/irq.h>
16#include <asm/errno.h>
17#include <asm/xics.h>
18#include <asm/rtas.h>
19
20/* RTAS service tokens */
21static int ibm_get_xive;
22static int ibm_set_xive;
23static int ibm_int_on;
24static int ibm_int_off;
25
26static void ics_rtas_unmask_irq(struct irq_data *d)
27{
28	unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);
29	int call_status;
30	int server;
31
32	pr_devel("xics: unmask virq %d [hw 0x%x]\n", d->irq, hw_irq);
33
34	if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS)
35		return;
36
37	server = xics_get_irq_server(d->irq, irq_data_get_affinity_mask(d), 0);
38
39	call_status = rtas_call(ibm_set_xive, 3, 1, NULL, hw_irq, server,
40				DEFAULT_PRIORITY);
41	if (call_status != 0) {
42		printk(KERN_ERR
43			"%s: ibm_set_xive irq %u server %x returned %d\n",
44			__func__, hw_irq, server, call_status);
45		return;
46	}
47
48	/* Now unmask the interrupt (often a no-op) */
49	call_status = rtas_call(ibm_int_on, 1, 1, NULL, hw_irq);
50	if (call_status != 0) {
51		printk(KERN_ERR "%s: ibm_int_on irq=%u returned %d\n",
52			__func__, hw_irq, call_status);
53		return;
54	}
55}
56
57static unsigned int ics_rtas_startup(struct irq_data *d)
58{
59	/* unmask it */
60	ics_rtas_unmask_irq(d);
61	return 0;
62}
63
64static void ics_rtas_mask_real_irq(unsigned int hw_irq)
65{
66	int call_status;
67
68	if (hw_irq == XICS_IPI)
69		return;
70
71	call_status = rtas_call(ibm_int_off, 1, 1, NULL, hw_irq);
72	if (call_status != 0) {
73		printk(KERN_ERR "%s: ibm_int_off irq=%u returned %d\n",
74			__func__, hw_irq, call_status);
75		return;
76	}
77
78	/* Have to set XIVE to 0xff to be able to remove a slot */
79	call_status = rtas_call(ibm_set_xive, 3, 1, NULL, hw_irq,
80				xics_default_server, 0xff);
81	if (call_status != 0) {
82		printk(KERN_ERR "%s: ibm_set_xive(0xff) irq=%u returned %d\n",
83			__func__, hw_irq, call_status);
84		return;
85	}
86}
87
88static void ics_rtas_mask_irq(struct irq_data *d)
89{
90	unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);
91
92	pr_devel("xics: mask virq %d [hw 0x%x]\n", d->irq, hw_irq);
93
94	if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS)
95		return;
96	ics_rtas_mask_real_irq(hw_irq);
97}
98
99static int ics_rtas_set_affinity(struct irq_data *d,
100				 const struct cpumask *cpumask,
101				 bool force)
102{
103	unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);
104	int status;
105	int xics_status[2];
106	int irq_server;
107
108	if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS)
109		return -1;
110
111	status = rtas_call(ibm_get_xive, 1, 3, xics_status, hw_irq);
112
113	if (status) {
114		printk(KERN_ERR "%s: ibm,get-xive irq=%u returns %d\n",
115			__func__, hw_irq, status);
116		return -1;
117	}
118
119	irq_server = xics_get_irq_server(d->irq, cpumask, 1);
120	if (irq_server == -1) {
121		pr_warn("%s: No online cpus in the mask %*pb for irq %d\n",
122			__func__, cpumask_pr_args(cpumask), d->irq);
123		return -1;
124	}
125
126	pr_debug("%s: irq %d [hw 0x%x] server: 0x%x\n", __func__, d->irq,
127		 hw_irq, irq_server);
128
129	status = rtas_call(ibm_set_xive, 3, 1, NULL,
130			   hw_irq, irq_server, xics_status[1]);
131
132	if (status) {
133		printk(KERN_ERR "%s: ibm,set-xive irq=%u returns %d\n",
134			__func__, hw_irq, status);
135		return -1;
136	}
137
138	return IRQ_SET_MASK_OK;
139}
140
141static struct irq_chip ics_rtas_irq_chip = {
142	.name = "XICS",
143	.irq_startup = ics_rtas_startup,
144	.irq_mask = ics_rtas_mask_irq,
145	.irq_unmask = ics_rtas_unmask_irq,
146	.irq_eoi = NULL, /* Patched at init time */
147	.irq_set_affinity = ics_rtas_set_affinity,
148	.irq_set_type = xics_set_irq_type,
149	.irq_retrigger = xics_retrigger,
150};
151
152static int ics_rtas_check(struct ics *ics, unsigned int hw_irq)
153{
154	int status[2];
155	int rc;
156
157	if (WARN_ON(hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS))
158		return -EINVAL;
159
160	/* Check if RTAS knows about this interrupt */
161	rc = rtas_call(ibm_get_xive, 1, 3, status, hw_irq);
162	if (rc)
163		return -ENXIO;
164
165	return 0;
166}
167
168static void ics_rtas_mask_unknown(struct ics *ics, unsigned long vec)
169{
170	ics_rtas_mask_real_irq(vec);
171}
172
173static long ics_rtas_get_server(struct ics *ics, unsigned long vec)
174{
175	int rc, status[2];
176
177	rc = rtas_call(ibm_get_xive, 1, 3, status, vec);
178	if (rc)
179		return -1;
180	return status[0];
181}
182
183static int ics_rtas_host_match(struct ics *ics, struct device_node *node)
184{
185	/* IBM machines have interrupt parents of various funky types for things
186	 * like vdevices, events, etc... The trick we use here is to match
187	 * everything here except the legacy 8259 which is compatible "chrp,iic"
188	 */
189	return !of_device_is_compatible(node, "chrp,iic");
190}
191
192/* Only one global & state struct ics */
193static struct ics ics_rtas = {
194	.check		= ics_rtas_check,
195	.mask_unknown	= ics_rtas_mask_unknown,
196	.get_server	= ics_rtas_get_server,
197	.host_match	= ics_rtas_host_match,
198	.chip = &ics_rtas_irq_chip,
199};
200
201__init int ics_rtas_init(void)
202{
203	ibm_get_xive = rtas_function_token(RTAS_FN_IBM_GET_XIVE);
204	ibm_set_xive = rtas_function_token(RTAS_FN_IBM_SET_XIVE);
205	ibm_int_on  = rtas_function_token(RTAS_FN_IBM_INT_ON);
206	ibm_int_off = rtas_function_token(RTAS_FN_IBM_INT_OFF);
207
208	/* We enable the RTAS "ICS" if RTAS is present with the
209	 * appropriate tokens
210	 */
211	if (ibm_get_xive == RTAS_UNKNOWN_SERVICE ||
212	    ibm_set_xive == RTAS_UNKNOWN_SERVICE)
213		return -ENODEV;
214
215	/* We need to patch our irq chip's EOI to point to the
216	 * right ICP
217	 */
218	ics_rtas_irq_chip.irq_eoi = icp_ops->eoi;
219
220	/* Register ourselves */
221	xics_register_ics(&ics_rtas);
222
223	return 0;
224}
225
226