1 /*
2  * Copyright (c) 2018 Foundries.io Ltd
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef SOC_RISCV32_OPENISA_RV32M1_SOC_H_
8 #define SOC_RISCV32_OPENISA_RV32M1_SOC_H_
9 
10 #ifndef _ASMLANGUAGE
11 
12 #include "fsl_device_registers.h"
13 #include <zephyr/types.h>
14 
15 /*
16  * Helpers related to interrupt handling. This SoC has two levels of
17  * interrupts.
18  *
19  * Level 1 interrupts go straight to the SoC. Level 2 interrupts must
20  * go through one of the 8 channels in the the INTMUX
21  * peripheral. There are 32 level 1 interrupts, including 8 INTMUX
22  * interrupts. Each INTMUX interrupt can mux at most
23  * CONFIG_MAX_IRQ_PER_AGGREGATOR (which happens to be 32) interrupts
24  * to its level 1 interrupt.
25  *
26  * See gen_isr_tables.py for details on the Zephyr multi-level IRQ
27  * number encoding, which determines how these helpers work.
28  */
29 
30 /**
31  * @brief Get an IRQ's level
32  * @param irq The IRQ number in the Zephyr irq.h numbering system
33  * @return IRQ level, either 1 or 2
34  */
rv32m1_irq_level(unsigned int irq)35 static inline unsigned int rv32m1_irq_level(unsigned int irq)
36 {
37 	return ((irq >> 8) & 0xff) == 0U ? 1 : 2;
38 }
39 
40 /**
41  * @brief Level 1 interrupt line associated with an IRQ
42  *
43  * Results are undefined if rv32m1_irq_level(irq) is not 1.
44  *
45  * @param The IRQ number in the Zephyr <irq.h> numbering system
46  * @return Level 1 (i.e. event unit) IRQ number associated with irq
47  */
rv32m1_level1_irq(unsigned int irq)48 static inline uint32_t rv32m1_level1_irq(unsigned int irq)
49 {
50 	/*
51 	 * There's no need to do any math; the precondition is that
52 	 * it's a level 1 IRQ.
53 	 */
54 	return irq;
55 }
56 
57 /**
58  * @brief INTMUX channel (i.e. level 2 aggregator number) for an IRQ
59  *
60  * Results are undefined if rv32m1_irq_level(irq) is not 2.
61  *
62  * @param irq The IRQ number whose INTMUX channel / level 2 aggregator
63  *            to get, in the Zephyr <irq.h> numbering system
64  * @return INTMUX channel number associated with the IRQ
65  */
rv32m1_intmux_channel(unsigned int irq)66 static inline uint32_t rv32m1_intmux_channel(unsigned int irq)
67 {
68 	/*
69 	 * Here we make use of these facts:
70 	 *
71 	 * - the INTMUX output IRQ numbers are arranged consecutively
72 	 *   by channel in the event unit IRQ numbering assignment,
73 	 *   starting from channel 0.
74 	 *
75 	 * - CONFIG_2ND_LVL_INTR_00_OFFSET is defined to
76 	 *   be the offset of the first level 2 aggregator in the parent
77 	 *   interrupt controller's IRQ numbers, i.e. channel 0's
78 	 *   IRQ number in the event unit.
79 	 */
80 	return (irq & 0xff) - CONFIG_2ND_LVL_INTR_00_OFFSET;
81 }
82 
83 /**
84  * @brief INTMUX interrupt ID number for an IRQ
85  *
86  * Results are undefined if rv32m1_irq_level(irq) is not 2.
87  *
88  * @param The IRQ number whose INTMUX interrupt ID to get, in the Zephyr
89  *        <irq.h> numbering system
90  * @return The INTMUX interrupt ID, in the inclusive range 0 to 31
91  */
rv32m1_intmux_line(unsigned int irq)92 static inline uint32_t rv32m1_intmux_line(unsigned int irq)
93 {
94 	return ((irq >> 8) & 0xff) - 1;
95 }
96 
97 void soc_interrupt_init(void);
98 
99 #endif	/* !_ASMLANGUAGE */
100 
101 #if defined(CONFIG_SOC_OPENISA_RV32M1_RI5CY)
102 #include "soc_ri5cy.h"
103 #elif defined(CONFIG_SOC_OPENISA_RV32M1_ZERO_RISCY)
104 #include "soc_zero_riscy.h"
105 #endif
106 
107 /* helper macro to convert from a DT_INST to HAL clock_ip_name */
108 #define INST_DT_CLOCK_IP_NAME(n) \
109 	MAKE_PCC_REGADDR(DT_REG_ADDR(DT_INST_PHANDLE(n, clocks)), \
110 			DT_INST_CLOCKS_CELL(n, name))
111 
112 #endif /* SOC_RISCV32_OPENISA_RV32M1_SOC_H_ */
113