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