forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-13 9d77db3c730780c8ef5ccd4b66403ff5675cfe4e
kernel/arch/arc/kernel/mcip.c
....@@ -1,11 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * ARC ARConnect (MultiCore IP) support (formerly known as MCIP)
34 *
45 * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com)
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 version 2 as
8
- * published by the Free Software Foundation.
96 */
107
118 #include <linux/smp.h>
....@@ -205,8 +202,8 @@
205202 __mcip_cmd_data(CMD_IDU_SET_DEST, cmn_irq, cpu_mask);
206203 }
207204
208
-static void idu_set_mode(unsigned int cmn_irq, unsigned int lvl,
209
- unsigned int distr)
205
+static void idu_set_mode(unsigned int cmn_irq, bool set_lvl, unsigned int lvl,
206
+ bool set_distr, unsigned int distr)
210207 {
211208 union {
212209 unsigned int word;
....@@ -215,8 +212,11 @@
215212 };
216213 } data;
217214
218
- data.distr = distr;
219
- data.lvl = lvl;
215
+ data.word = __mcip_cmd_read(CMD_IDU_READ_MODE, cmn_irq);
216
+ if (set_distr)
217
+ data.distr = distr;
218
+ if (set_lvl)
219
+ data.lvl = lvl;
220220 __mcip_cmd_data(CMD_IDU_SET_MODE, cmn_irq, data.word);
221221 }
222222
....@@ -243,6 +243,25 @@
243243 raw_spin_unlock_irqrestore(&mcip_lock, flags);
244244 }
245245
246
+static void idu_irq_ack(struct irq_data *data)
247
+{
248
+ unsigned long flags;
249
+
250
+ raw_spin_lock_irqsave(&mcip_lock, flags);
251
+ __mcip_cmd(CMD_IDU_ACK_CIRQ, data->hwirq);
252
+ raw_spin_unlock_irqrestore(&mcip_lock, flags);
253
+}
254
+
255
+static void idu_irq_mask_ack(struct irq_data *data)
256
+{
257
+ unsigned long flags;
258
+
259
+ raw_spin_lock_irqsave(&mcip_lock, flags);
260
+ __mcip_cmd_data(CMD_IDU_SET_MASK, data->hwirq, 1);
261
+ __mcip_cmd(CMD_IDU_ACK_CIRQ, data->hwirq);
262
+ raw_spin_unlock_irqrestore(&mcip_lock, flags);
263
+}
264
+
246265 static int
247266 idu_irq_set_affinity(struct irq_data *data, const struct cpumask *cpumask,
248267 bool force)
....@@ -266,11 +285,34 @@
266285 else
267286 distribution_mode = IDU_M_DISTRI_RR;
268287
269
- idu_set_mode(data->hwirq, IDU_M_TRIG_LEVEL, distribution_mode);
288
+ idu_set_mode(data->hwirq, false, 0, true, distribution_mode);
270289
271290 raw_spin_unlock_irqrestore(&mcip_lock, flags);
272291
273292 return IRQ_SET_MASK_OK;
293
+}
294
+
295
+static int idu_irq_set_type(struct irq_data *data, u32 type)
296
+{
297
+ unsigned long flags;
298
+
299
+ /*
300
+ * ARCv2 IDU HW does not support inverse polarity, so these are the
301
+ * only interrupt types supported.
302
+ */
303
+ if (type & ~(IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH))
304
+ return -EINVAL;
305
+
306
+ raw_spin_lock_irqsave(&mcip_lock, flags);
307
+
308
+ idu_set_mode(data->hwirq, true,
309
+ type & IRQ_TYPE_EDGE_RISING ? IDU_M_TRIG_EDGE :
310
+ IDU_M_TRIG_LEVEL,
311
+ false, 0);
312
+
313
+ raw_spin_unlock_irqrestore(&mcip_lock, flags);
314
+
315
+ return 0;
274316 }
275317
276318 static void idu_irq_enable(struct irq_data *data)
....@@ -292,7 +334,10 @@
292334 .name = "MCIP IDU Intc",
293335 .irq_mask = idu_irq_mask,
294336 .irq_unmask = idu_irq_unmask,
337
+ .irq_ack = idu_irq_ack,
338
+ .irq_mask_ack = idu_irq_mask_ack,
295339 .irq_enable = idu_irq_enable,
340
+ .irq_set_type = idu_irq_set_type,
296341 #ifdef CONFIG_SMP
297342 .irq_set_affinity = idu_irq_set_affinity,
298343 #endif
....@@ -320,7 +365,7 @@
320365 }
321366
322367 static const struct irq_domain_ops idu_irq_ops = {
323
- .xlate = irq_domain_xlate_onecell,
368
+ .xlate = irq_domain_xlate_onetwocell,
324369 .map = idu_irq_map,
325370 };
326371