1 /* Copyright 2023 The ChromiumOS Authors
2  * SPDX-License-Identifier: Apache-2.0
3  */
4 
5 #include <zephyr/irq.h>
6 #include <zephyr/devicetree.h>
7 #include <zephyr/device.h>
8 
9 bool intc_mtk_adsp_get_enable(const struct device *dev, int irq);
10 void intc_mtk_adsp_set_enable(const struct device *dev, int irq, bool val);
11 
12 /* Sort of annoying: assumes there are exactly two controller devices
13  * and that their instance IDs (i.e. the order in which they appear in
14  * the .dts file) match their order in the _sw_isr_table[].  A better
15  * scheme would be able to enumerate the tree at runtime.
16  */
irq_dev(unsigned int * irq_inout)17 static const struct device *irq_dev(unsigned int *irq_inout)
18 {
19 #ifdef CONFIG_SOC_SERIES_MT8195
20 	/* Controller 0 is on Xtensa vector 1, controller 1 on vector 23. */
21 	if ((*irq_inout & 0xff) == 1) {
22 		*irq_inout >>= 8;
23 		return DEVICE_DT_GET(DT_INST(0, mediatek_adsp_intc));
24 	}
25 	__ASSERT_NO_MSG((*irq_inout & 0xff) == 23);
26 	*irq_inout = (*irq_inout >> 8) - 1;
27 	return DEVICE_DT_GET(DT_INST(1, mediatek_adsp_intc));
28 #elif defined(CONFIG_SOC_SERIES_MT8196)
29 	/* Two subcontrollers on core IRQs 1 and 2 */
30 	uint32_t lvl1 = *irq_inout & 0xff;
31 
32 	*irq_inout = (*irq_inout >> 8) - 1;
33 	if (lvl1 == 1) {
34 		return DEVICE_DT_GET(DT_INST(0, mediatek_adsp_intc));
35 	}
36 	__ASSERT_NO_MSG(lvl1 == 2);
37 	return DEVICE_DT_GET(DT_INST(1, mediatek_adsp_intc));
38 #else
39 	/* Only one on 818x */
40 	return DEVICE_DT_GET(DT_INST(0, mediatek_adsp_intc));
41 #endif
42 }
43 
z_soc_irq_enable(unsigned int irq)44 void z_soc_irq_enable(unsigned int irq)
45 {
46 	/* First 32 IRQs are the Xtensa architectural vectors,  */
47 	if (irq < 32) {
48 		xtensa_irq_enable(irq);
49 	} else {
50 		const struct device *dev = irq_dev(&irq);
51 
52 		intc_mtk_adsp_set_enable(dev, irq, true);
53 	}
54 }
55 
z_soc_irq_disable(unsigned int irq)56 void z_soc_irq_disable(unsigned int irq)
57 {
58 	if (irq < 32) {
59 		xtensa_irq_disable(irq);
60 	} else {
61 		const struct device *dev = irq_dev(&irq);
62 
63 		intc_mtk_adsp_set_enable(dev, irq, false);
64 	}
65 }
66 
z_soc_irq_is_enabled(unsigned int irq)67 int z_soc_irq_is_enabled(unsigned int irq)
68 {
69 	if (irq < 32) {
70 		return xtensa_irq_is_enabled(irq);
71 	}
72 	return intc_mtk_adsp_get_enable(irq_dev(&irq), irq);
73 }
74