1*4c0cb471SAntonio Borneo // SPDX-License-Identifier: BSD-2-Clause
2*4c0cb471SAntonio Borneo /*
3*4c0cb471SAntonio Borneo * Copyright (c) 2021-2025, STMicroelectronics
4*4c0cb471SAntonio Borneo */
5*4c0cb471SAntonio Borneo
6*4c0cb471SAntonio Borneo #include <drivers/stm32_rif.h>
7*4c0cb471SAntonio Borneo #include <dt-bindings/interrupt-controller/irq.h>
8*4c0cb471SAntonio Borneo #include <io.h>
9*4c0cb471SAntonio Borneo #include <kernel/boot.h>
10*4c0cb471SAntonio Borneo #include <kernel/dt.h>
11*4c0cb471SAntonio Borneo #include <kernel/dt_driver.h>
12*4c0cb471SAntonio Borneo #include <kernel/interrupt.h>
13*4c0cb471SAntonio Borneo #include <kernel/pm.h>
14*4c0cb471SAntonio Borneo #include <kernel/spinlock.h>
15*4c0cb471SAntonio Borneo #include <libfdt.h>
16*4c0cb471SAntonio Borneo #include <mm/core_memprot.h>
17*4c0cb471SAntonio Borneo #include <tee_api_types.h>
18*4c0cb471SAntonio Borneo #include <util.h>
19*4c0cb471SAntonio Borneo
20*4c0cb471SAntonio Borneo /* Registers */
21*4c0cb471SAntonio Borneo #define _EXTI_RTSR(n) (0x000U + (n) * 0x20U)
22*4c0cb471SAntonio Borneo #define _EXTI_FTSR(n) (0x004U + (n) * 0x20U)
23*4c0cb471SAntonio Borneo #define _EXTI_RPR(n) (0x00cU + (n) * 0x20U)
24*4c0cb471SAntonio Borneo #define _EXTI_FPR(n) (0x010U + (n) * 0x20U)
25*4c0cb471SAntonio Borneo #define _EXTI_SECCFGR(n) (0x014U + (n) * 0x20U)
26*4c0cb471SAntonio Borneo #define _EXTI_PRIVCFGR(n) (0x018U + (n) * 0x20U)
27*4c0cb471SAntonio Borneo #define _EXTI_CR(n) (0x060U + (n) * 4U)
28*4c0cb471SAntonio Borneo #define _EXTI_LOCKR 0x070U
29*4c0cb471SAntonio Borneo #define _EXTI_C1IMR(n) (0x080U + (n) * 0x10U)
30*4c0cb471SAntonio Borneo #define _EXTI_EnCIDCFGR(n) (0x180U + (n) * 4U)
31*4c0cb471SAntonio Borneo #define _EXTI_CmCIDCFGR(n) (0x300U + (n) * 4U)
32*4c0cb471SAntonio Borneo #define _EXTI_TRG(n) (0x3ecU - (n) * 4U) /* HWCFGR2..4 */
33*4c0cb471SAntonio Borneo #define _EXTI_HWCFGR1 0x3f0U
34*4c0cb471SAntonio Borneo
35*4c0cb471SAntonio Borneo /* SECCFGR register bitfields */
36*4c0cb471SAntonio Borneo #define _EXTI_SECCFGR_MASK GENMASK_32(31, 0)
37*4c0cb471SAntonio Borneo
38*4c0cb471SAntonio Borneo /* PRIVCFGR register bitfields */
39*4c0cb471SAntonio Borneo #define _EXTI_PRIVCFGR_MASK GENMASK_32(31, 0)
40*4c0cb471SAntonio Borneo
41*4c0cb471SAntonio Borneo /* LOCKR register bitfields */
42*4c0cb471SAntonio Borneo #define _EXTI_LOCKR_GLOCK BIT(0)
43*4c0cb471SAntonio Borneo
44*4c0cb471SAntonio Borneo /* CIDCFGR register bitfields */
45*4c0cb471SAntonio Borneo #define _EXTI_CIDCFGR_CFEN BIT(0)
46*4c0cb471SAntonio Borneo #define _EXTI_CIDCFGR_SCID_MASK GENMASK_32(6, 4)
47*4c0cb471SAntonio Borneo #define _EXTI_CIDCFGR_SCID_SHIFT 4U
48*4c0cb471SAntonio Borneo #define _EXTI_CIDCFGR_CONF_MASK (_EXTI_CIDCFGR_CFEN | \
49*4c0cb471SAntonio Borneo _EXTI_CIDCFGR_SCID_MASK)
50*4c0cb471SAntonio Borneo
51*4c0cb471SAntonio Borneo /* _EXTI_HWCFGR1 bit fields */
52*4c0cb471SAntonio Borneo #define _EXTI_HWCFGR1_NBEVENTS_MASK GENMASK_32(7, 0)
53*4c0cb471SAntonio Borneo #define _EXTI_HWCFGR1_NBEVENTS_SHIFT 0U
54*4c0cb471SAntonio Borneo #define _EXTI_HWCFGR1_NBCPUS_MASK GENMASK_32(11, 8)
55*4c0cb471SAntonio Borneo #define _EXTI_HWCFGR1_NBCPUS_SHIFT 8U
56*4c0cb471SAntonio Borneo #define _EXTI_HWCFGR1_CIDWIDTH_MASK GENMASK_32(27, 24)
57*4c0cb471SAntonio Borneo #define _EXTI_HWCFGR1_CIDWIDTH_SHIFT 24U
58*4c0cb471SAntonio Borneo
59*4c0cb471SAntonio Borneo #define _EXTI_MAX_CR 4U
60*4c0cb471SAntonio Borneo #define _EXTI_BANK_NR 3U
61*4c0cb471SAntonio Borneo #define _EXTI_LINES_PER_BANK 32U
62*4c0cb471SAntonio Borneo
63*4c0cb471SAntonio Borneo #define _EXTI_CID1 0x1U
64*4c0cb471SAntonio Borneo
65*4c0cb471SAntonio Borneo /*
66*4c0cb471SAntonio Borneo * struct stm32_exti_itr_hierarchy - EXTI line interrupt hierarchy
67*4c0cb471SAntonio Borneo * @this: An EXTI interrupt number and its EXTI interrupt controller
68*4c0cb471SAntonio Borneo * @parent: The interrupt (number and controller) that drives the interrupt
69*4c0cb471SAntonio Borneo */
70*4c0cb471SAntonio Borneo struct stm32_exti_itr_hierarchy {
71*4c0cb471SAntonio Borneo struct itr_desc this;
72*4c0cb471SAntonio Borneo struct itr_desc parent;
73*4c0cb471SAntonio Borneo };
74*4c0cb471SAntonio Borneo
75*4c0cb471SAntonio Borneo struct stm32_exti_pdata {
76*4c0cb471SAntonio Borneo struct itr_chip chip;
77*4c0cb471SAntonio Borneo vaddr_t base;
78*4c0cb471SAntonio Borneo unsigned int lock;
79*4c0cb471SAntonio Borneo uint32_t hwcfgr1;
80*4c0cb471SAntonio Borneo uint32_t trg[_EXTI_BANK_NR];
81*4c0cb471SAntonio Borneo uint32_t wake_active[_EXTI_BANK_NR];
82*4c0cb471SAntonio Borneo uint32_t mask_cache[_EXTI_BANK_NR];
83*4c0cb471SAntonio Borneo uint32_t imr_cache[_EXTI_BANK_NR];
84*4c0cb471SAntonio Borneo uint32_t seccfgr_cache[_EXTI_BANK_NR];
85*4c0cb471SAntonio Borneo uint32_t privcfgr_cache[_EXTI_BANK_NR];
86*4c0cb471SAntonio Borneo uint32_t access_mask[_EXTI_BANK_NR];
87*4c0cb471SAntonio Borneo uint32_t rtsr_cache[_EXTI_BANK_NR];
88*4c0cb471SAntonio Borneo uint32_t ftsr_cache[_EXTI_BANK_NR];
89*4c0cb471SAntonio Borneo uint32_t port_sel_cache[_EXTI_MAX_CR];
90*4c0cb471SAntonio Borneo uint32_t *e_cids;
91*4c0cb471SAntonio Borneo uint32_t *c_cids;
92*4c0cb471SAntonio Borneo struct stm32_exti_itr_hierarchy *
93*4c0cb471SAntonio Borneo hierarchy[_EXTI_LINES_PER_BANK * _EXTI_BANK_NR];
94*4c0cb471SAntonio Borneo bool glock;
95*4c0cb471SAntonio Borneo };
96*4c0cb471SAntonio Borneo
97*4c0cb471SAntonio Borneo static struct stm32_exti_pdata *
itr_chip_to_stm32_exti_pdata(struct itr_chip * chip)98*4c0cb471SAntonio Borneo itr_chip_to_stm32_exti_pdata(struct itr_chip *chip)
99*4c0cb471SAntonio Borneo {
100*4c0cb471SAntonio Borneo return container_of(chip, struct stm32_exti_pdata, chip);
101*4c0cb471SAntonio Borneo }
102*4c0cb471SAntonio Borneo
stm32_exti_get_bank(uint32_t exti_line)103*4c0cb471SAntonio Borneo static unsigned int stm32_exti_get_bank(uint32_t exti_line)
104*4c0cb471SAntonio Borneo {
105*4c0cb471SAntonio Borneo if (exti_line < _EXTI_LINES_PER_BANK)
106*4c0cb471SAntonio Borneo return 0;
107*4c0cb471SAntonio Borneo
108*4c0cb471SAntonio Borneo if (exti_line < 2 * _EXTI_LINES_PER_BANK)
109*4c0cb471SAntonio Borneo return 1;
110*4c0cb471SAntonio Borneo
111*4c0cb471SAntonio Borneo if (exti_line < 3 * _EXTI_LINES_PER_BANK)
112*4c0cb471SAntonio Borneo return 2;
113*4c0cb471SAntonio Borneo
114*4c0cb471SAntonio Borneo panic();
115*4c0cb471SAntonio Borneo }
116*4c0cb471SAntonio Borneo
stm32_exti_maxcid(const struct stm32_exti_pdata * exti)117*4c0cb471SAntonio Borneo static inline uint32_t stm32_exti_maxcid(const struct stm32_exti_pdata *exti)
118*4c0cb471SAntonio Borneo {
119*4c0cb471SAntonio Borneo uint32_t bitfield = (exti->hwcfgr1 & _EXTI_HWCFGR1_CIDWIDTH_MASK) >>
120*4c0cb471SAntonio Borneo _EXTI_HWCFGR1_CIDWIDTH_SHIFT;
121*4c0cb471SAntonio Borneo
122*4c0cb471SAntonio Borneo return BIT(bitfield) - 1;
123*4c0cb471SAntonio Borneo }
124*4c0cb471SAntonio Borneo
stm32_exti_nbevents(const struct stm32_exti_pdata * exti)125*4c0cb471SAntonio Borneo static inline uint32_t stm32_exti_nbevents(const struct stm32_exti_pdata *exti)
126*4c0cb471SAntonio Borneo {
127*4c0cb471SAntonio Borneo uint32_t bitfield = (exti->hwcfgr1 & _EXTI_HWCFGR1_NBEVENTS_MASK) >>
128*4c0cb471SAntonio Borneo _EXTI_HWCFGR1_NBEVENTS_SHIFT;
129*4c0cb471SAntonio Borneo
130*4c0cb471SAntonio Borneo return bitfield + 1;
131*4c0cb471SAntonio Borneo }
132*4c0cb471SAntonio Borneo
stm32_exti_nbcpus(const struct stm32_exti_pdata * exti)133*4c0cb471SAntonio Borneo static inline uint32_t stm32_exti_nbcpus(const struct stm32_exti_pdata *exti)
134*4c0cb471SAntonio Borneo {
135*4c0cb471SAntonio Borneo uint32_t bitfield = (exti->hwcfgr1 & _EXTI_HWCFGR1_NBCPUS_MASK) >>
136*4c0cb471SAntonio Borneo _EXTI_HWCFGR1_NBCPUS_SHIFT;
137*4c0cb471SAntonio Borneo
138*4c0cb471SAntonio Borneo return bitfield + 1;
139*4c0cb471SAntonio Borneo }
140*4c0cb471SAntonio Borneo
141*4c0cb471SAntonio Borneo static bool
stm32_exti_event_is_configurable(const struct stm32_exti_pdata * exti,unsigned int exti_line)142*4c0cb471SAntonio Borneo stm32_exti_event_is_configurable(const struct stm32_exti_pdata *exti,
143*4c0cb471SAntonio Borneo unsigned int exti_line)
144*4c0cb471SAntonio Borneo {
145*4c0cb471SAntonio Borneo unsigned int i = stm32_exti_get_bank(exti_line);
146*4c0cb471SAntonio Borneo uint32_t mask = BIT(exti_line % _EXTI_LINES_PER_BANK);
147*4c0cb471SAntonio Borneo
148*4c0cb471SAntonio Borneo return exti->trg[i] & mask;
149*4c0cb471SAntonio Borneo }
150*4c0cb471SAntonio Borneo
stm32_exti_set_type(struct stm32_exti_pdata * exti,uint32_t exti_line,uint32_t type)151*4c0cb471SAntonio Borneo static void stm32_exti_set_type(struct stm32_exti_pdata *exti,
152*4c0cb471SAntonio Borneo uint32_t exti_line, uint32_t type)
153*4c0cb471SAntonio Borneo {
154*4c0cb471SAntonio Borneo unsigned int i = stm32_exti_get_bank(exti_line);
155*4c0cb471SAntonio Borneo uint32_t mask = BIT(exti_line % _EXTI_LINES_PER_BANK);
156*4c0cb471SAntonio Borneo uint32_t r_trig = 0;
157*4c0cb471SAntonio Borneo uint32_t f_trig = 0;
158*4c0cb471SAntonio Borneo uint32_t exceptions = 0;
159*4c0cb471SAntonio Borneo
160*4c0cb471SAntonio Borneo switch (type) {
161*4c0cb471SAntonio Borneo case IRQ_TYPE_EDGE_RISING:
162*4c0cb471SAntonio Borneo r_trig |= mask;
163*4c0cb471SAntonio Borneo f_trig &= ~mask;
164*4c0cb471SAntonio Borneo break;
165*4c0cb471SAntonio Borneo case IRQ_TYPE_EDGE_FALLING:
166*4c0cb471SAntonio Borneo r_trig &= ~mask;
167*4c0cb471SAntonio Borneo f_trig |= mask;
168*4c0cb471SAntonio Borneo break;
169*4c0cb471SAntonio Borneo case IRQ_TYPE_EDGE_BOTH:
170*4c0cb471SAntonio Borneo r_trig |= mask;
171*4c0cb471SAntonio Borneo f_trig |= mask;
172*4c0cb471SAntonio Borneo break;
173*4c0cb471SAntonio Borneo default:
174*4c0cb471SAntonio Borneo EMSG("Unsupported interrupt type 0x%"PRIx32, type);
175*4c0cb471SAntonio Borneo panic();
176*4c0cb471SAntonio Borneo }
177*4c0cb471SAntonio Borneo
178*4c0cb471SAntonio Borneo exceptions = cpu_spin_lock_xsave(&exti->lock);
179*4c0cb471SAntonio Borneo
180*4c0cb471SAntonio Borneo io_mask32(exti->base + _EXTI_RTSR(i), r_trig, mask);
181*4c0cb471SAntonio Borneo io_mask32(exti->base + _EXTI_FTSR(i), f_trig, mask);
182*4c0cb471SAntonio Borneo
183*4c0cb471SAntonio Borneo cpu_spin_unlock_xrestore(&exti->lock, exceptions);
184*4c0cb471SAntonio Borneo }
185*4c0cb471SAntonio Borneo
stm32_exti_mask(struct stm32_exti_pdata * exti,uint32_t exti_line)186*4c0cb471SAntonio Borneo static void stm32_exti_mask(struct stm32_exti_pdata *exti, uint32_t exti_line)
187*4c0cb471SAntonio Borneo {
188*4c0cb471SAntonio Borneo unsigned int i = stm32_exti_get_bank(exti_line);
189*4c0cb471SAntonio Borneo uint32_t mask = BIT(exti_line % _EXTI_LINES_PER_BANK);
190*4c0cb471SAntonio Borneo uint32_t exceptions = 0;
191*4c0cb471SAntonio Borneo
192*4c0cb471SAntonio Borneo exceptions = cpu_spin_lock_xsave(&exti->lock);
193*4c0cb471SAntonio Borneo
194*4c0cb471SAntonio Borneo io_clrbits32(exti->base + _EXTI_C1IMR(i), mask);
195*4c0cb471SAntonio Borneo exti->mask_cache[i] &= ~mask;
196*4c0cb471SAntonio Borneo
197*4c0cb471SAntonio Borneo cpu_spin_unlock_xrestore(&exti->lock, exceptions);
198*4c0cb471SAntonio Borneo }
199*4c0cb471SAntonio Borneo
stm32_exti_unmask(struct stm32_exti_pdata * exti,uint32_t exti_line)200*4c0cb471SAntonio Borneo static void stm32_exti_unmask(struct stm32_exti_pdata *exti,
201*4c0cb471SAntonio Borneo uint32_t exti_line)
202*4c0cb471SAntonio Borneo {
203*4c0cb471SAntonio Borneo unsigned int i = stm32_exti_get_bank(exti_line);
204*4c0cb471SAntonio Borneo uint32_t mask = BIT(exti_line % _EXTI_LINES_PER_BANK);
205*4c0cb471SAntonio Borneo uint32_t exceptions = 0;
206*4c0cb471SAntonio Borneo
207*4c0cb471SAntonio Borneo exceptions = cpu_spin_lock_xsave(&exti->lock);
208*4c0cb471SAntonio Borneo
209*4c0cb471SAntonio Borneo io_setbits32(exti->base + _EXTI_C1IMR(i), mask);
210*4c0cb471SAntonio Borneo exti->mask_cache[i] |= mask;
211*4c0cb471SAntonio Borneo
212*4c0cb471SAntonio Borneo cpu_spin_unlock_xrestore(&exti->lock, exceptions);
213*4c0cb471SAntonio Borneo }
214*4c0cb471SAntonio Borneo
stm32_exti_enable_wake(struct stm32_exti_pdata * exti,uint32_t exti_line)215*4c0cb471SAntonio Borneo static void stm32_exti_enable_wake(struct stm32_exti_pdata *exti,
216*4c0cb471SAntonio Borneo uint32_t exti_line)
217*4c0cb471SAntonio Borneo {
218*4c0cb471SAntonio Borneo unsigned int i = stm32_exti_get_bank(exti_line);
219*4c0cb471SAntonio Borneo uint32_t mask = BIT(exti_line % _EXTI_LINES_PER_BANK);
220*4c0cb471SAntonio Borneo uint32_t exceptions = 0;
221*4c0cb471SAntonio Borneo
222*4c0cb471SAntonio Borneo exceptions = cpu_spin_lock_xsave(&exti->lock);
223*4c0cb471SAntonio Borneo
224*4c0cb471SAntonio Borneo exti->wake_active[i] |= mask;
225*4c0cb471SAntonio Borneo
226*4c0cb471SAntonio Borneo cpu_spin_unlock_xrestore(&exti->lock, exceptions);
227*4c0cb471SAntonio Borneo }
228*4c0cb471SAntonio Borneo
stm32_exti_disable_wake(struct stm32_exti_pdata * exti,uint32_t exti_line)229*4c0cb471SAntonio Borneo static void stm32_exti_disable_wake(struct stm32_exti_pdata *exti,
230*4c0cb471SAntonio Borneo uint32_t exti_line)
231*4c0cb471SAntonio Borneo {
232*4c0cb471SAntonio Borneo unsigned int i = stm32_exti_get_bank(exti_line);
233*4c0cb471SAntonio Borneo uint32_t mask = BIT(exti_line % _EXTI_LINES_PER_BANK);
234*4c0cb471SAntonio Borneo uint32_t exceptions = 0;
235*4c0cb471SAntonio Borneo
236*4c0cb471SAntonio Borneo exceptions = cpu_spin_lock_xsave(&exti->lock);
237*4c0cb471SAntonio Borneo
238*4c0cb471SAntonio Borneo exti->wake_active[i] &= ~mask;
239*4c0cb471SAntonio Borneo
240*4c0cb471SAntonio Borneo cpu_spin_unlock_xrestore(&exti->lock, exceptions);
241*4c0cb471SAntonio Borneo }
242*4c0cb471SAntonio Borneo
stm32_exti_clear(struct stm32_exti_pdata * exti,uint32_t exti_line)243*4c0cb471SAntonio Borneo static void stm32_exti_clear(struct stm32_exti_pdata *exti, uint32_t exti_line)
244*4c0cb471SAntonio Borneo {
245*4c0cb471SAntonio Borneo unsigned int i = stm32_exti_get_bank(exti_line);
246*4c0cb471SAntonio Borneo uint32_t mask = BIT(exti_line % _EXTI_LINES_PER_BANK);
247*4c0cb471SAntonio Borneo uint32_t exceptions = 0;
248*4c0cb471SAntonio Borneo
249*4c0cb471SAntonio Borneo exceptions = cpu_spin_lock_xsave(&exti->lock);
250*4c0cb471SAntonio Borneo
251*4c0cb471SAntonio Borneo io_setbits32(exti->base + _EXTI_RPR(i), mask);
252*4c0cb471SAntonio Borneo io_setbits32(exti->base + _EXTI_FPR(i), mask);
253*4c0cb471SAntonio Borneo
254*4c0cb471SAntonio Borneo cpu_spin_unlock_xrestore(&exti->lock, exceptions);
255*4c0cb471SAntonio Borneo }
256*4c0cb471SAntonio Borneo
stm32_exti_set_tz(struct stm32_exti_pdata * exti,uint32_t exti_line)257*4c0cb471SAntonio Borneo static void stm32_exti_set_tz(struct stm32_exti_pdata *exti,
258*4c0cb471SAntonio Borneo uint32_t exti_line)
259*4c0cb471SAntonio Borneo {
260*4c0cb471SAntonio Borneo unsigned int i = stm32_exti_get_bank(exti_line);
261*4c0cb471SAntonio Borneo uint32_t mask = BIT(exti_line % _EXTI_LINES_PER_BANK);
262*4c0cb471SAntonio Borneo uint32_t exceptions = 0;
263*4c0cb471SAntonio Borneo
264*4c0cb471SAntonio Borneo exceptions = cpu_spin_lock_xsave(&exti->lock);
265*4c0cb471SAntonio Borneo
266*4c0cb471SAntonio Borneo io_setbits32(exti->base + _EXTI_SECCFGR(i), mask);
267*4c0cb471SAntonio Borneo
268*4c0cb471SAntonio Borneo cpu_spin_unlock_xrestore(&exti->lock, exceptions);
269*4c0cb471SAntonio Borneo }
270*4c0cb471SAntonio Borneo
271*4c0cb471SAntonio Borneo static struct itr_desc *
stm32_exti_get_parent_itr(struct stm32_exti_pdata * exti,size_t it)272*4c0cb471SAntonio Borneo stm32_exti_get_parent_itr(struct stm32_exti_pdata *exti, size_t it)
273*4c0cb471SAntonio Borneo {
274*4c0cb471SAntonio Borneo if (!exti || it >= stm32_exti_nbevents(exti) || !exti->hierarchy[it])
275*4c0cb471SAntonio Borneo panic();
276*4c0cb471SAntonio Borneo
277*4c0cb471SAntonio Borneo return &exti->hierarchy[it]->parent;
278*4c0cb471SAntonio Borneo }
279*4c0cb471SAntonio Borneo
280*4c0cb471SAntonio Borneo /* Enable an interrupt */
stm32_exti_op_enable(struct itr_chip * chip,size_t it)281*4c0cb471SAntonio Borneo static void stm32_exti_op_enable(struct itr_chip *chip, size_t it)
282*4c0cb471SAntonio Borneo {
283*4c0cb471SAntonio Borneo struct stm32_exti_pdata *exti = itr_chip_to_stm32_exti_pdata(chip);
284*4c0cb471SAntonio Borneo struct itr_desc *parent = stm32_exti_get_parent_itr(exti, it);
285*4c0cb471SAntonio Borneo
286*4c0cb471SAntonio Borneo stm32_exti_unmask(exti, it);
287*4c0cb471SAntonio Borneo
288*4c0cb471SAntonio Borneo interrupt_enable(parent->chip, parent->itr_num);
289*4c0cb471SAntonio Borneo }
290*4c0cb471SAntonio Borneo
291*4c0cb471SAntonio Borneo /* Disable an interrupt */
stm32_exti_op_disable(struct itr_chip * chip,size_t it)292*4c0cb471SAntonio Borneo static void stm32_exti_op_disable(struct itr_chip *chip, size_t it)
293*4c0cb471SAntonio Borneo {
294*4c0cb471SAntonio Borneo struct stm32_exti_pdata *exti = itr_chip_to_stm32_exti_pdata(chip);
295*4c0cb471SAntonio Borneo struct itr_desc *parent = stm32_exti_get_parent_itr(exti, it);
296*4c0cb471SAntonio Borneo
297*4c0cb471SAntonio Borneo stm32_exti_mask(exti, it);
298*4c0cb471SAntonio Borneo
299*4c0cb471SAntonio Borneo interrupt_disable(parent->chip, parent->itr_num);
300*4c0cb471SAntonio Borneo }
301*4c0cb471SAntonio Borneo
302*4c0cb471SAntonio Borneo /* Mask an interrupt, may be called from an interrupt context */
stm32_exti_op_mask(struct itr_chip * chip,size_t it)303*4c0cb471SAntonio Borneo static void stm32_exti_op_mask(struct itr_chip *chip, size_t it)
304*4c0cb471SAntonio Borneo {
305*4c0cb471SAntonio Borneo struct stm32_exti_pdata *exti = itr_chip_to_stm32_exti_pdata(chip);
306*4c0cb471SAntonio Borneo struct itr_desc *parent = stm32_exti_get_parent_itr(exti, it);
307*4c0cb471SAntonio Borneo
308*4c0cb471SAntonio Borneo stm32_exti_mask(exti, it);
309*4c0cb471SAntonio Borneo
310*4c0cb471SAntonio Borneo interrupt_mask(parent->chip, parent->itr_num);
311*4c0cb471SAntonio Borneo }
312*4c0cb471SAntonio Borneo
313*4c0cb471SAntonio Borneo /* Unmask an interrupt, may be called from an interrupt context */
stm32_exti_op_unmask(struct itr_chip * chip,size_t it)314*4c0cb471SAntonio Borneo static void stm32_exti_op_unmask(struct itr_chip *chip, size_t it)
315*4c0cb471SAntonio Borneo {
316*4c0cb471SAntonio Borneo struct stm32_exti_pdata *exti = itr_chip_to_stm32_exti_pdata(chip);
317*4c0cb471SAntonio Borneo struct itr_desc *parent = stm32_exti_get_parent_itr(exti, it);
318*4c0cb471SAntonio Borneo
319*4c0cb471SAntonio Borneo stm32_exti_unmask(exti, it);
320*4c0cb471SAntonio Borneo
321*4c0cb471SAntonio Borneo interrupt_unmask(parent->chip, parent->itr_num);
322*4c0cb471SAntonio Borneo }
323*4c0cb471SAntonio Borneo
324*4c0cb471SAntonio Borneo /* Raise per-cpu interrupt (optional) */
stm32_exti_op_raise_pi(struct itr_chip * chip,size_t it)325*4c0cb471SAntonio Borneo static void stm32_exti_op_raise_pi(struct itr_chip *chip, size_t it)
326*4c0cb471SAntonio Borneo {
327*4c0cb471SAntonio Borneo struct stm32_exti_pdata *exti = itr_chip_to_stm32_exti_pdata(chip);
328*4c0cb471SAntonio Borneo struct itr_desc *parent = stm32_exti_get_parent_itr(exti, it);
329*4c0cb471SAntonio Borneo
330*4c0cb471SAntonio Borneo if (interrupt_can_raise_pi(parent->chip))
331*4c0cb471SAntonio Borneo interrupt_raise_pi(parent->chip, parent->itr_num);
332*4c0cb471SAntonio Borneo }
333*4c0cb471SAntonio Borneo
334*4c0cb471SAntonio Borneo /* Raise a SGI (optional) */
stm32_exti_op_raise_sgi(struct itr_chip * chip,size_t it,uint32_t cpu_mask)335*4c0cb471SAntonio Borneo static void stm32_exti_op_raise_sgi(struct itr_chip *chip, size_t it,
336*4c0cb471SAntonio Borneo uint32_t cpu_mask)
337*4c0cb471SAntonio Borneo {
338*4c0cb471SAntonio Borneo struct stm32_exti_pdata *exti = itr_chip_to_stm32_exti_pdata(chip);
339*4c0cb471SAntonio Borneo struct itr_desc *parent = stm32_exti_get_parent_itr(exti, it);
340*4c0cb471SAntonio Borneo
341*4c0cb471SAntonio Borneo if (interrupt_can_raise_sgi(parent->chip))
342*4c0cb471SAntonio Borneo interrupt_raise_sgi(parent->chip, parent->itr_num, cpu_mask);
343*4c0cb471SAntonio Borneo }
344*4c0cb471SAntonio Borneo
345*4c0cb471SAntonio Borneo /* Set interrupt/cpu affinity (optional) */
stm32_exti_op_set_affinity(struct itr_chip * chip,size_t it,uint8_t cpu_mask)346*4c0cb471SAntonio Borneo static void stm32_exti_op_set_affinity(struct itr_chip *chip, size_t it,
347*4c0cb471SAntonio Borneo uint8_t cpu_mask)
348*4c0cb471SAntonio Borneo {
349*4c0cb471SAntonio Borneo struct stm32_exti_pdata *exti = itr_chip_to_stm32_exti_pdata(chip);
350*4c0cb471SAntonio Borneo struct itr_desc *parent = stm32_exti_get_parent_itr(exti, it);
351*4c0cb471SAntonio Borneo
352*4c0cb471SAntonio Borneo if (interrupt_can_set_affinity(parent->chip))
353*4c0cb471SAntonio Borneo interrupt_set_affinity(parent->chip, parent->itr_num,
354*4c0cb471SAntonio Borneo cpu_mask);
355*4c0cb471SAntonio Borneo }
356*4c0cb471SAntonio Borneo
357*4c0cb471SAntonio Borneo /* Enable/disable power-management wake-on of an interrupt (optional) */
stm32_exti_op_set_wake(struct itr_chip * chip,size_t it,bool on)358*4c0cb471SAntonio Borneo static void stm32_exti_op_set_wake(struct itr_chip *chip, size_t it,
359*4c0cb471SAntonio Borneo bool on)
360*4c0cb471SAntonio Borneo {
361*4c0cb471SAntonio Borneo struct stm32_exti_pdata *exti = itr_chip_to_stm32_exti_pdata(chip);
362*4c0cb471SAntonio Borneo struct itr_desc *parent = stm32_exti_get_parent_itr(exti, it);
363*4c0cb471SAntonio Borneo
364*4c0cb471SAntonio Borneo if (on)
365*4c0cb471SAntonio Borneo stm32_exti_enable_wake(exti, it);
366*4c0cb471SAntonio Borneo else
367*4c0cb471SAntonio Borneo stm32_exti_disable_wake(exti, it);
368*4c0cb471SAntonio Borneo
369*4c0cb471SAntonio Borneo if (interrupt_can_set_wake(parent->chip))
370*4c0cb471SAntonio Borneo interrupt_set_wake(parent->chip, parent->itr_num, on);
371*4c0cb471SAntonio Borneo }
372*4c0cb471SAntonio Borneo
373*4c0cb471SAntonio Borneo static const struct itr_ops stm32_exti_ops = {
374*4c0cb471SAntonio Borneo .enable = stm32_exti_op_enable,
375*4c0cb471SAntonio Borneo .disable = stm32_exti_op_disable,
376*4c0cb471SAntonio Borneo .mask = stm32_exti_op_mask,
377*4c0cb471SAntonio Borneo .unmask = stm32_exti_op_unmask,
378*4c0cb471SAntonio Borneo .raise_pi = stm32_exti_op_raise_pi,
379*4c0cb471SAntonio Borneo .raise_sgi = stm32_exti_op_raise_sgi,
380*4c0cb471SAntonio Borneo .set_affinity = stm32_exti_op_set_affinity,
381*4c0cb471SAntonio Borneo .set_wake = stm32_exti_op_set_wake,
382*4c0cb471SAntonio Borneo };
383*4c0cb471SAntonio Borneo DECLARE_KEEP_PAGER(stm32_exti_ops);
384*4c0cb471SAntonio Borneo
stm32_exti_rif_check_access(struct stm32_exti_pdata * exti,uint32_t exti_line)385*4c0cb471SAntonio Borneo static TEE_Result stm32_exti_rif_check_access(struct stm32_exti_pdata *exti,
386*4c0cb471SAntonio Borneo uint32_t exti_line)
387*4c0cb471SAntonio Borneo {
388*4c0cb471SAntonio Borneo unsigned int i = stm32_exti_get_bank(exti_line);
389*4c0cb471SAntonio Borneo uint32_t mask = BIT(exti_line % _EXTI_LINES_PER_BANK);
390*4c0cb471SAntonio Borneo
391*4c0cb471SAntonio Borneo /* only configured as secure and privileged */
392*4c0cb471SAntonio Borneo if (!((exti->seccfgr_cache[i] & exti->privcfgr_cache[i] &
393*4c0cb471SAntonio Borneo exti->access_mask[i]) & mask))
394*4c0cb471SAntonio Borneo return TEE_ERROR_ACCESS_DENIED;
395*4c0cb471SAntonio Borneo
396*4c0cb471SAntonio Borneo if ((exti->e_cids[exti_line] & _EXTI_CIDCFGR_CFEN) &&
397*4c0cb471SAntonio Borneo ((exti->e_cids[exti_line] & _EXTI_CIDCFGR_SCID_MASK) !=
398*4c0cb471SAntonio Borneo SHIFT_U32(_EXTI_CID1, _EXTI_CIDCFGR_SCID_SHIFT)))
399*4c0cb471SAntonio Borneo return TEE_ERROR_ACCESS_DENIED;
400*4c0cb471SAntonio Borneo
401*4c0cb471SAntonio Borneo return TEE_SUCCESS;
402*4c0cb471SAntonio Borneo }
403*4c0cb471SAntonio Borneo
stm32_exti_rif_parse_dt(struct stm32_exti_pdata * exti,const void * fdt,int node)404*4c0cb471SAntonio Borneo static void stm32_exti_rif_parse_dt(struct stm32_exti_pdata *exti,
405*4c0cb471SAntonio Borneo const void *fdt, int node)
406*4c0cb471SAntonio Borneo {
407*4c0cb471SAntonio Borneo struct rif_conf_data conf_data = { };
408*4c0cb471SAntonio Borneo const fdt32_t *cuint = NULL;
409*4c0cb471SAntonio Borneo uint32_t rif_conf = 0;
410*4c0cb471SAntonio Borneo unsigned int i = 0;
411*4c0cb471SAntonio Borneo int len = 0;
412*4c0cb471SAntonio Borneo
413*4c0cb471SAntonio Borneo if (fdt_getprop(fdt, node, "st,glocked", NULL))
414*4c0cb471SAntonio Borneo exti->glock = true;
415*4c0cb471SAntonio Borneo else
416*4c0cb471SAntonio Borneo DMSG("No global lock on RIF configuration");
417*4c0cb471SAntonio Borneo
418*4c0cb471SAntonio Borneo cuint = fdt_getprop(fdt, node, "st,protreg", &len);
419*4c0cb471SAntonio Borneo if (!cuint) {
420*4c0cb471SAntonio Borneo DMSG("No RIF configuration available");
421*4c0cb471SAntonio Borneo return;
422*4c0cb471SAntonio Borneo }
423*4c0cb471SAntonio Borneo
424*4c0cb471SAntonio Borneo exti->e_cids = calloc(stm32_exti_nbevents(exti), sizeof(uint32_t));
425*4c0cb471SAntonio Borneo exti->c_cids = calloc(stm32_exti_nbcpus(exti), sizeof(uint32_t));
426*4c0cb471SAntonio Borneo if (!exti->e_cids || !exti->c_cids)
427*4c0cb471SAntonio Borneo panic("Out of memory");
428*4c0cb471SAntonio Borneo
429*4c0cb471SAntonio Borneo conf_data.cid_confs = exti->e_cids;
430*4c0cb471SAntonio Borneo conf_data.sec_conf = exti->seccfgr_cache;
431*4c0cb471SAntonio Borneo conf_data.priv_conf = exti->privcfgr_cache;
432*4c0cb471SAntonio Borneo conf_data.access_mask = exti->access_mask;
433*4c0cb471SAntonio Borneo
434*4c0cb471SAntonio Borneo for (i = 0; i < len / sizeof(uint32_t); i++) {
435*4c0cb471SAntonio Borneo rif_conf = fdt32_to_cpu(cuint[i]);
436*4c0cb471SAntonio Borneo
437*4c0cb471SAntonio Borneo stm32_rif_parse_cfg(rif_conf, &conf_data,
438*4c0cb471SAntonio Borneo stm32_exti_nbevents(exti));
439*4c0cb471SAntonio Borneo }
440*4c0cb471SAntonio Borneo
441*4c0cb471SAntonio Borneo cuint = fdt_getprop(fdt, node, "st,proccid", &len);
442*4c0cb471SAntonio Borneo if (!cuint)
443*4c0cb471SAntonio Borneo panic("No RIF configuration available");
444*4c0cb471SAntonio Borneo
445*4c0cb471SAntonio Borneo for (i = 0; i < len / (2 * sizeof(uint32_t)); i++) {
446*4c0cb471SAntonio Borneo unsigned int pos = fdt32_to_cpu(cuint[2 * i]);
447*4c0cb471SAntonio Borneo uint32_t c_cid = fdt32_to_cpu(cuint[2 * i + 1]);
448*4c0cb471SAntonio Borneo
449*4c0cb471SAntonio Borneo if (pos == 0 || pos > stm32_exti_nbcpus(exti))
450*4c0cb471SAntonio Borneo panic("CID position out of range");
451*4c0cb471SAntonio Borneo
452*4c0cb471SAntonio Borneo if (c_cid > stm32_exti_maxcid(exti))
453*4c0cb471SAntonio Borneo panic("CID out of range");
454*4c0cb471SAntonio Borneo
455*4c0cb471SAntonio Borneo exti->c_cids[pos - 1] = SHIFT_U32(c_cid, _CIDCFGR_SCID_SHIFT) |
456*4c0cb471SAntonio Borneo _EXTI_CIDCFGR_CFEN;
457*4c0cb471SAntonio Borneo }
458*4c0cb471SAntonio Borneo }
459*4c0cb471SAntonio Borneo
stm32_exti_rif_apply(const struct stm32_exti_pdata * exti)460*4c0cb471SAntonio Borneo static TEE_Result stm32_exti_rif_apply(const struct stm32_exti_pdata *exti)
461*4c0cb471SAntonio Borneo {
462*4c0cb471SAntonio Borneo TEE_Result res = TEE_ERROR_GENERIC;
463*4c0cb471SAntonio Borneo unsigned int bit_offset = 0;
464*4c0cb471SAntonio Borneo bool is_tdcid = false;
465*4c0cb471SAntonio Borneo uint32_t event = 0;
466*4c0cb471SAntonio Borneo unsigned int i = 0;
467*4c0cb471SAntonio Borneo
468*4c0cb471SAntonio Borneo res = stm32_rifsc_check_tdcid(&is_tdcid);
469*4c0cb471SAntonio Borneo if (res)
470*4c0cb471SAntonio Borneo return res;
471*4c0cb471SAntonio Borneo
472*4c0cb471SAntonio Borneo /*
473*4c0cb471SAntonio Borneo * If TDCID, clear EnCIDCFGR and CmCIDCFGR to prevent undesired
474*4c0cb471SAntonio Borneo * events during the following configuration.
475*4c0cb471SAntonio Borneo */
476*4c0cb471SAntonio Borneo
477*4c0cb471SAntonio Borneo if (is_tdcid) {
478*4c0cb471SAntonio Borneo for (event = 0; event < stm32_exti_nbevents(exti); event++) {
479*4c0cb471SAntonio Borneo i = stm32_exti_get_bank(event);
480*4c0cb471SAntonio Borneo bit_offset = event % _EXTI_LINES_PER_BANK;
481*4c0cb471SAntonio Borneo
482*4c0cb471SAntonio Borneo if (!(BIT(bit_offset) & exti->access_mask[i]))
483*4c0cb471SAntonio Borneo continue;
484*4c0cb471SAntonio Borneo
485*4c0cb471SAntonio Borneo io_clrbits32(exti->base + _EXTI_EnCIDCFGR(event),
486*4c0cb471SAntonio Borneo _EXTI_CIDCFGR_CONF_MASK);
487*4c0cb471SAntonio Borneo }
488*4c0cb471SAntonio Borneo
489*4c0cb471SAntonio Borneo for (i = 0; i < stm32_exti_nbcpus(exti); i++)
490*4c0cb471SAntonio Borneo io_clrbits32(exti->base + _EXTI_CmCIDCFGR(i),
491*4c0cb471SAntonio Borneo _EXTI_CIDCFGR_CONF_MASK);
492*4c0cb471SAntonio Borneo }
493*4c0cb471SAntonio Borneo
494*4c0cb471SAntonio Borneo /* Security and privilege RIF configuration */
495*4c0cb471SAntonio Borneo for (i = 0; i < _EXTI_BANK_NR; i++) {
496*4c0cb471SAntonio Borneo if (!exti->access_mask[i])
497*4c0cb471SAntonio Borneo continue;
498*4c0cb471SAntonio Borneo
499*4c0cb471SAntonio Borneo io_clrsetbits32(exti->base + _EXTI_PRIVCFGR(i),
500*4c0cb471SAntonio Borneo _EXTI_PRIVCFGR_MASK & exti->access_mask[i],
501*4c0cb471SAntonio Borneo exti->privcfgr_cache[i]);
502*4c0cb471SAntonio Borneo io_clrsetbits32(exti->base + _EXTI_SECCFGR(i),
503*4c0cb471SAntonio Borneo _EXTI_SECCFGR_MASK & exti->access_mask[i],
504*4c0cb471SAntonio Borneo exti->seccfgr_cache[i]);
505*4c0cb471SAntonio Borneo }
506*4c0cb471SAntonio Borneo
507*4c0cb471SAntonio Borneo if (!is_tdcid)
508*4c0cb471SAntonio Borneo return TEE_SUCCESS;
509*4c0cb471SAntonio Borneo
510*4c0cb471SAntonio Borneo /* If TDCID, configure EnCIDCFGR and CmCIDCFGR */
511*4c0cb471SAntonio Borneo for (event = 0; event < stm32_exti_nbevents(exti); event++) {
512*4c0cb471SAntonio Borneo i = stm32_exti_get_bank(event);
513*4c0cb471SAntonio Borneo bit_offset = event % _EXTI_LINES_PER_BANK;
514*4c0cb471SAntonio Borneo
515*4c0cb471SAntonio Borneo if (!(BIT(bit_offset) & exti->access_mask[i]))
516*4c0cb471SAntonio Borneo continue;
517*4c0cb471SAntonio Borneo
518*4c0cb471SAntonio Borneo io_clrsetbits32(exti->base + _EXTI_EnCIDCFGR(event),
519*4c0cb471SAntonio Borneo _EXTI_CIDCFGR_CONF_MASK, exti->e_cids[event]);
520*4c0cb471SAntonio Borneo }
521*4c0cb471SAntonio Borneo for (i = 0; i < stm32_exti_nbcpus(exti); i++) {
522*4c0cb471SAntonio Borneo if (!(exti->c_cids[i] & _EXTI_CIDCFGR_CFEN))
523*4c0cb471SAntonio Borneo continue;
524*4c0cb471SAntonio Borneo
525*4c0cb471SAntonio Borneo io_clrsetbits32(exti->base + _EXTI_CmCIDCFGR(i),
526*4c0cb471SAntonio Borneo _EXTI_CIDCFGR_CONF_MASK, exti->c_cids[i]);
527*4c0cb471SAntonio Borneo }
528*4c0cb471SAntonio Borneo
529*4c0cb471SAntonio Borneo /* If TDCID, configure global lock */
530*4c0cb471SAntonio Borneo if (exti->glock)
531*4c0cb471SAntonio Borneo io_setbits32(exti->base + _EXTI_LOCKR, _EXTI_LOCKR_GLOCK);
532*4c0cb471SAntonio Borneo
533*4c0cb471SAntonio Borneo return TEE_SUCCESS;
534*4c0cb471SAntonio Borneo }
535*4c0cb471SAntonio Borneo
stm32_exti_rif_save(struct stm32_exti_pdata * exti)536*4c0cb471SAntonio Borneo static void stm32_exti_rif_save(struct stm32_exti_pdata *exti)
537*4c0cb471SAntonio Borneo {
538*4c0cb471SAntonio Borneo unsigned int bit_offset = 0;
539*4c0cb471SAntonio Borneo bool is_tdcid = false;
540*4c0cb471SAntonio Borneo uint32_t event = 0;
541*4c0cb471SAntonio Borneo unsigned int i = 0;
542*4c0cb471SAntonio Borneo
543*4c0cb471SAntonio Borneo for (i = 0; i < _EXTI_BANK_NR; i++) {
544*4c0cb471SAntonio Borneo if (!exti->access_mask[i])
545*4c0cb471SAntonio Borneo continue;
546*4c0cb471SAntonio Borneo
547*4c0cb471SAntonio Borneo exti->privcfgr_cache[i] =
548*4c0cb471SAntonio Borneo io_read32(exti->base + _EXTI_PRIVCFGR(i));
549*4c0cb471SAntonio Borneo exti->seccfgr_cache[i] =
550*4c0cb471SAntonio Borneo io_read32(exti->base + _EXTI_SECCFGR(i));
551*4c0cb471SAntonio Borneo }
552*4c0cb471SAntonio Borneo
553*4c0cb471SAntonio Borneo stm32_rifsc_check_tdcid(&is_tdcid);
554*4c0cb471SAntonio Borneo if (!is_tdcid)
555*4c0cb471SAntonio Borneo return;
556*4c0cb471SAntonio Borneo
557*4c0cb471SAntonio Borneo for (event = 0; event < stm32_exti_nbevents(exti); event++) {
558*4c0cb471SAntonio Borneo i = stm32_exti_get_bank(event);
559*4c0cb471SAntonio Borneo bit_offset = event % _EXTI_LINES_PER_BANK;
560*4c0cb471SAntonio Borneo
561*4c0cb471SAntonio Borneo if (!(BIT(bit_offset) & exti->access_mask[i]))
562*4c0cb471SAntonio Borneo continue;
563*4c0cb471SAntonio Borneo
564*4c0cb471SAntonio Borneo exti->e_cids[event] = io_read32(exti->base +
565*4c0cb471SAntonio Borneo _EXTI_EnCIDCFGR(event));
566*4c0cb471SAntonio Borneo }
567*4c0cb471SAntonio Borneo for (i = 0; i < stm32_exti_nbcpus(exti); i++)
568*4c0cb471SAntonio Borneo exti->c_cids[i] = io_read32(exti->base + _EXTI_CmCIDCFGR(i));
569*4c0cb471SAntonio Borneo }
570*4c0cb471SAntonio Borneo
stm32_exti_pm_suspend(struct stm32_exti_pdata * exti)571*4c0cb471SAntonio Borneo static void stm32_exti_pm_suspend(struct stm32_exti_pdata *exti)
572*4c0cb471SAntonio Borneo {
573*4c0cb471SAntonio Borneo uint32_t base = exti->base;
574*4c0cb471SAntonio Borneo uint32_t i = 0;
575*4c0cb471SAntonio Borneo
576*4c0cb471SAntonio Borneo if (IS_ENABLED(CFG_STM32_RIF) && stm32_exti_maxcid(exti))
577*4c0cb471SAntonio Borneo stm32_exti_rif_save(exti);
578*4c0cb471SAntonio Borneo
579*4c0cb471SAntonio Borneo for (i = 0; i < _EXTI_BANK_NR; i++) {
580*4c0cb471SAntonio Borneo /* Save ftsr, rtsr and seccfgr registers */
581*4c0cb471SAntonio Borneo exti->ftsr_cache[i] = io_read32(base + _EXTI_FTSR(i));
582*4c0cb471SAntonio Borneo exti->rtsr_cache[i] = io_read32(base + _EXTI_RTSR(i));
583*4c0cb471SAntonio Borneo exti->seccfgr_cache[i] = io_read32(base + _EXTI_SECCFGR(i));
584*4c0cb471SAntonio Borneo }
585*4c0cb471SAntonio Borneo
586*4c0cb471SAntonio Borneo /* Save EXTI port selection */
587*4c0cb471SAntonio Borneo for (i = 0; i < _EXTI_MAX_CR; i++)
588*4c0cb471SAntonio Borneo exti->port_sel_cache[i] = io_read32(base + _EXTI_CR(i));
589*4c0cb471SAntonio Borneo }
590*4c0cb471SAntonio Borneo
stm32_exti_pm_resume(struct stm32_exti_pdata * exti)591*4c0cb471SAntonio Borneo static void stm32_exti_pm_resume(struct stm32_exti_pdata *exti)
592*4c0cb471SAntonio Borneo {
593*4c0cb471SAntonio Borneo uint32_t base = exti->base;
594*4c0cb471SAntonio Borneo uint32_t i = 0;
595*4c0cb471SAntonio Borneo
596*4c0cb471SAntonio Borneo for (i = 0; i < _EXTI_BANK_NR; i++) {
597*4c0cb471SAntonio Borneo /* Restore ftsr, rtsr and seccfgr registers */
598*4c0cb471SAntonio Borneo io_write32(base + _EXTI_FTSR(i), exti->ftsr_cache[i]);
599*4c0cb471SAntonio Borneo io_write32(base + _EXTI_RTSR(i), exti->rtsr_cache[i]);
600*4c0cb471SAntonio Borneo io_write32(base + _EXTI_SECCFGR(i), exti->seccfgr_cache[i]);
601*4c0cb471SAntonio Borneo }
602*4c0cb471SAntonio Borneo
603*4c0cb471SAntonio Borneo /* Restore EXTI port selection */
604*4c0cb471SAntonio Borneo for (i = 0; i < _EXTI_MAX_CR; i++)
605*4c0cb471SAntonio Borneo io_write32(base + _EXTI_CR(i), exti->port_sel_cache[i]);
606*4c0cb471SAntonio Borneo
607*4c0cb471SAntonio Borneo if (IS_ENABLED(CFG_STM32_RIF) && stm32_exti_maxcid(exti))
608*4c0cb471SAntonio Borneo stm32_exti_rif_apply(exti);
609*4c0cb471SAntonio Borneo }
610*4c0cb471SAntonio Borneo
611*4c0cb471SAntonio Borneo /* PM function: configure the wake_up line for OP-TEE */
stm32_exti_configure_wake(struct stm32_exti_pdata * exti)612*4c0cb471SAntonio Borneo static void stm32_exti_configure_wake(struct stm32_exti_pdata *exti)
613*4c0cb471SAntonio Borneo {
614*4c0cb471SAntonio Borneo uint32_t i = 0;
615*4c0cb471SAntonio Borneo
616*4c0cb471SAntonio Borneo for (i = 0; i < _EXTI_BANK_NR; i++) {
617*4c0cb471SAntonio Borneo /* save IMR value, lost in Standby */
618*4c0cb471SAntonio Borneo exti->imr_cache[i] = io_read32(exti->base + _EXTI_C1IMR(i));
619*4c0cb471SAntonio Borneo /* deactivate in IMR the interruption activated in OP-TEE */
620*4c0cb471SAntonio Borneo io_clrbits32(exti->base + _EXTI_C1IMR(i), exti->mask_cache[i]);
621*4c0cb471SAntonio Borneo /* activate in IMR for OP-TEE wakeup interruption */
622*4c0cb471SAntonio Borneo io_setbits32(exti->base + _EXTI_C1IMR(i), exti->wake_active[i]);
623*4c0cb471SAntonio Borneo }
624*4c0cb471SAntonio Borneo }
625*4c0cb471SAntonio Borneo
stm32_exti_restore_wake(struct stm32_exti_pdata * exti)626*4c0cb471SAntonio Borneo static void stm32_exti_restore_wake(struct stm32_exti_pdata *exti)
627*4c0cb471SAntonio Borneo {
628*4c0cb471SAntonio Borneo uint32_t i = 0;
629*4c0cb471SAntonio Borneo
630*4c0cb471SAntonio Borneo /* restore saved IMR value: interruption secure/unsecure */
631*4c0cb471SAntonio Borneo for (i = 0; i < _EXTI_BANK_NR; i++)
632*4c0cb471SAntonio Borneo io_write32(exti->base + _EXTI_C1IMR(i), exti->imr_cache[i]);
633*4c0cb471SAntonio Borneo }
634*4c0cb471SAntonio Borneo
635*4c0cb471SAntonio Borneo static TEE_Result
stm32_exti_pm(enum pm_op op,unsigned int pm_hint,const struct pm_callback_handle * pm_handle)636*4c0cb471SAntonio Borneo stm32_exti_pm(enum pm_op op, unsigned int pm_hint,
637*4c0cb471SAntonio Borneo const struct pm_callback_handle *pm_handle)
638*4c0cb471SAntonio Borneo {
639*4c0cb471SAntonio Borneo struct stm32_exti_pdata *exti =
640*4c0cb471SAntonio Borneo (struct stm32_exti_pdata *)PM_CALLBACK_GET_HANDLE(pm_handle);
641*4c0cb471SAntonio Borneo
642*4c0cb471SAntonio Borneo if (op == PM_OP_SUSPEND)
643*4c0cb471SAntonio Borneo stm32_exti_configure_wake(exti);
644*4c0cb471SAntonio Borneo else
645*4c0cb471SAntonio Borneo stm32_exti_restore_wake(exti);
646*4c0cb471SAntonio Borneo
647*4c0cb471SAntonio Borneo if (!PM_HINT_IS_STATE(pm_hint, CONTEXT))
648*4c0cb471SAntonio Borneo return TEE_SUCCESS;
649*4c0cb471SAntonio Borneo
650*4c0cb471SAntonio Borneo if (op == PM_OP_SUSPEND)
651*4c0cb471SAntonio Borneo stm32_exti_pm_suspend(exti);
652*4c0cb471SAntonio Borneo else
653*4c0cb471SAntonio Borneo stm32_exti_pm_resume(exti);
654*4c0cb471SAntonio Borneo
655*4c0cb471SAntonio Borneo return TEE_SUCCESS;
656*4c0cb471SAntonio Borneo }
657*4c0cb471SAntonio Borneo DECLARE_KEEP_PAGER(stm32_exti_pm);
658*4c0cb471SAntonio Borneo
stm32_exti_it_handler(struct itr_handler * h)659*4c0cb471SAntonio Borneo static enum itr_return stm32_exti_it_handler(struct itr_handler *h)
660*4c0cb471SAntonio Borneo {
661*4c0cb471SAntonio Borneo struct stm32_exti_itr_hierarchy *hierarchy = h->data;
662*4c0cb471SAntonio Borneo struct itr_desc *itr_desc = &hierarchy->this;
663*4c0cb471SAntonio Borneo struct stm32_exti_pdata *exti =
664*4c0cb471SAntonio Borneo itr_chip_to_stm32_exti_pdata(itr_desc->chip);
665*4c0cb471SAntonio Borneo
666*4c0cb471SAntonio Borneo interrupt_call_handlers(itr_desc->chip, itr_desc->itr_num);
667*4c0cb471SAntonio Borneo
668*4c0cb471SAntonio Borneo if (stm32_exti_event_is_configurable(exti, itr_desc->itr_num))
669*4c0cb471SAntonio Borneo stm32_exti_clear(exti, itr_desc->itr_num);
670*4c0cb471SAntonio Borneo
671*4c0cb471SAntonio Borneo return ITRR_HANDLED;
672*4c0cb471SAntonio Borneo }
673*4c0cb471SAntonio Borneo DECLARE_KEEP_PAGER(stm32_exti_it_handler);
674*4c0cb471SAntonio Borneo
675*4c0cb471SAntonio Borneo /* Callback for "interrupts" and "interrupts-extended" DT node properties */
676*4c0cb471SAntonio Borneo static TEE_Result
stm32_exti_dt_get_chip_cb(struct dt_pargs * pargs,void * priv_data,struct itr_desc * itr_desc)677*4c0cb471SAntonio Borneo stm32_exti_dt_get_chip_cb(struct dt_pargs *pargs, void *priv_data,
678*4c0cb471SAntonio Borneo struct itr_desc *itr_desc)
679*4c0cb471SAntonio Borneo {
680*4c0cb471SAntonio Borneo struct stm32_exti_pdata *exti = priv_data;
681*4c0cb471SAntonio Borneo struct stm32_exti_itr_hierarchy *hierarchy = NULL;
682*4c0cb471SAntonio Borneo size_t exti_line = 0;
683*4c0cb471SAntonio Borneo uint32_t type = 0;
684*4c0cb471SAntonio Borneo TEE_Result res = TEE_ERROR_GENERIC;
685*4c0cb471SAntonio Borneo
686*4c0cb471SAntonio Borneo if (pargs->args_count != 2)
687*4c0cb471SAntonio Borneo return TEE_ERROR_GENERIC;
688*4c0cb471SAntonio Borneo
689*4c0cb471SAntonio Borneo exti_line = pargs->args[0];
690*4c0cb471SAntonio Borneo type = pargs->args[1];
691*4c0cb471SAntonio Borneo
692*4c0cb471SAntonio Borneo itr_desc->chip = &exti->chip;
693*4c0cb471SAntonio Borneo itr_desc->itr_num = exti_line;
694*4c0cb471SAntonio Borneo
695*4c0cb471SAntonio Borneo if (exti_line >= stm32_exti_nbevents(exti))
696*4c0cb471SAntonio Borneo return TEE_ERROR_GENERIC;
697*4c0cb471SAntonio Borneo
698*4c0cb471SAntonio Borneo /* With RIF, check the permission */
699*4c0cb471SAntonio Borneo if (IS_ENABLED(CFG_STM32_RIF) && stm32_exti_maxcid(exti)) {
700*4c0cb471SAntonio Borneo res = stm32_exti_rif_check_access(exti, exti_line);
701*4c0cb471SAntonio Borneo if (res)
702*4c0cb471SAntonio Borneo return res;
703*4c0cb471SAntonio Borneo }
704*4c0cb471SAntonio Borneo
705*4c0cb471SAntonio Borneo hierarchy = exti->hierarchy[exti_line];
706*4c0cb471SAntonio Borneo if (!hierarchy) {
707*4c0cb471SAntonio Borneo hierarchy = calloc(1, sizeof(*hierarchy));
708*4c0cb471SAntonio Borneo if (!hierarchy)
709*4c0cb471SAntonio Borneo return TEE_ERROR_OUT_OF_MEMORY;
710*4c0cb471SAntonio Borneo exti->hierarchy[exti_line] = hierarchy;
711*4c0cb471SAntonio Borneo }
712*4c0cb471SAntonio Borneo
713*4c0cb471SAntonio Borneo hierarchy->this.chip = &exti->chip;
714*4c0cb471SAntonio Borneo hierarchy->this.itr_num = exti_line;
715*4c0cb471SAntonio Borneo
716*4c0cb471SAntonio Borneo res = interrupt_dt_get_by_index(pargs->fdt, pargs->phandle_node,
717*4c0cb471SAntonio Borneo exti_line,
718*4c0cb471SAntonio Borneo &hierarchy->parent.chip,
719*4c0cb471SAntonio Borneo &hierarchy->parent.itr_num);
720*4c0cb471SAntonio Borneo if (res)
721*4c0cb471SAntonio Borneo return res;
722*4c0cb471SAntonio Borneo
723*4c0cb471SAntonio Borneo res = interrupt_create_handler(hierarchy->parent.chip,
724*4c0cb471SAntonio Borneo hierarchy->parent.itr_num,
725*4c0cb471SAntonio Borneo stm32_exti_it_handler, hierarchy,
726*4c0cb471SAntonio Borneo ITRF_TRIGGER_LEVEL, NULL);
727*4c0cb471SAntonio Borneo if (res)
728*4c0cb471SAntonio Borneo return res;
729*4c0cb471SAntonio Borneo
730*4c0cb471SAntonio Borneo /* set_type valid for configurable events only */
731*4c0cb471SAntonio Borneo if (stm32_exti_event_is_configurable(exti, exti_line))
732*4c0cb471SAntonio Borneo stm32_exti_set_type(exti, exti_line, type);
733*4c0cb471SAntonio Borneo
734*4c0cb471SAntonio Borneo /* Without RIF, predate the line by setting it as secure */
735*4c0cb471SAntonio Borneo if (!IS_ENABLED(CFG_STM32_RIF) || !stm32_exti_maxcid(exti))
736*4c0cb471SAntonio Borneo stm32_exti_set_tz(exti, exti_line);
737*4c0cb471SAntonio Borneo
738*4c0cb471SAntonio Borneo return TEE_SUCCESS;
739*4c0cb471SAntonio Borneo }
740*4c0cb471SAntonio Borneo
stm32_exti_probe(const void * fdt,int node,const void * comp_data __unused)741*4c0cb471SAntonio Borneo static TEE_Result stm32_exti_probe(const void *fdt, int node,
742*4c0cb471SAntonio Borneo const void *comp_data __unused)
743*4c0cb471SAntonio Borneo {
744*4c0cb471SAntonio Borneo struct stm32_exti_pdata *exti = NULL;
745*4c0cb471SAntonio Borneo TEE_Result res = TEE_ERROR_GENERIC;
746*4c0cb471SAntonio Borneo struct io_pa_va base = { };
747*4c0cb471SAntonio Borneo size_t reg_size = 0;
748*4c0cb471SAntonio Borneo unsigned int i = 0;
749*4c0cb471SAntonio Borneo
750*4c0cb471SAntonio Borneo exti = calloc(1, sizeof(*exti));
751*4c0cb471SAntonio Borneo if (!exti)
752*4c0cb471SAntonio Borneo panic("Out of memory");
753*4c0cb471SAntonio Borneo
754*4c0cb471SAntonio Borneo exti->lock = SPINLOCK_UNLOCK;
755*4c0cb471SAntonio Borneo exti->chip.ops = &stm32_exti_ops;
756*4c0cb471SAntonio Borneo exti->chip.name = strdup(fdt_get_name(fdt, node, NULL));
757*4c0cb471SAntonio Borneo
758*4c0cb471SAntonio Borneo res = itr_chip_dt_only_init(&exti->chip);
759*4c0cb471SAntonio Borneo if (res)
760*4c0cb471SAntonio Borneo panic();
761*4c0cb471SAntonio Borneo
762*4c0cb471SAntonio Borneo if (fdt_reg_info(fdt, node, &base.pa, ®_size))
763*4c0cb471SAntonio Borneo panic();
764*4c0cb471SAntonio Borneo
765*4c0cb471SAntonio Borneo exti->base = io_pa_or_va_secure(&base, reg_size);
766*4c0cb471SAntonio Borneo assert(exti->base);
767*4c0cb471SAntonio Borneo
768*4c0cb471SAntonio Borneo exti->hwcfgr1 = io_read32(exti->base + _EXTI_HWCFGR1);
769*4c0cb471SAntonio Borneo for (i = 0; i < _EXTI_BANK_NR; i++)
770*4c0cb471SAntonio Borneo exti->trg[i] = io_read32(exti->base + _EXTI_TRG(i));
771*4c0cb471SAntonio Borneo
772*4c0cb471SAntonio Borneo if (IS_ENABLED(CFG_STM32_RIF) && stm32_exti_maxcid(exti)) {
773*4c0cb471SAntonio Borneo stm32_exti_rif_parse_dt(exti, fdt, node);
774*4c0cb471SAntonio Borneo res = stm32_exti_rif_apply(exti);
775*4c0cb471SAntonio Borneo if (res)
776*4c0cb471SAntonio Borneo goto err;
777*4c0cb471SAntonio Borneo }
778*4c0cb471SAntonio Borneo
779*4c0cb471SAntonio Borneo res = interrupt_register_provider(fdt, node, stm32_exti_dt_get_chip_cb,
780*4c0cb471SAntonio Borneo exti);
781*4c0cb471SAntonio Borneo if (res)
782*4c0cb471SAntonio Borneo goto err;
783*4c0cb471SAntonio Borneo
784*4c0cb471SAntonio Borneo register_pm_core_service_cb(stm32_exti_pm, exti, "stm32-exti");
785*4c0cb471SAntonio Borneo
786*4c0cb471SAntonio Borneo return TEE_SUCCESS;
787*4c0cb471SAntonio Borneo
788*4c0cb471SAntonio Borneo err:
789*4c0cb471SAntonio Borneo free(exti->e_cids);
790*4c0cb471SAntonio Borneo free(exti->c_cids);
791*4c0cb471SAntonio Borneo free((char *)exti->chip.name);
792*4c0cb471SAntonio Borneo free(exti);
793*4c0cb471SAntonio Borneo return res;
794*4c0cb471SAntonio Borneo }
795*4c0cb471SAntonio Borneo
796*4c0cb471SAntonio Borneo static const struct dt_device_match stm32_exti_match_table[] = {
797*4c0cb471SAntonio Borneo { .compatible = "st,stm32mp1-exti" },
798*4c0cb471SAntonio Borneo { }
799*4c0cb471SAntonio Borneo };
800*4c0cb471SAntonio Borneo
801*4c0cb471SAntonio Borneo DEFINE_DT_DRIVER(stm32_exti_dt_driver) = {
802*4c0cb471SAntonio Borneo .name = "stm32-exti",
803*4c0cb471SAntonio Borneo .match_table = stm32_exti_match_table,
804*4c0cb471SAntonio Borneo .probe = &stm32_exti_probe,
805*4c0cb471SAntonio Borneo };
806