1 /*
2  * Copyright 2024 Microchip Technology Inc. and its subsidiaries.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include <stddef.h>
7 #include <stdint.h>
8 
9 #include <device_mec5.h>
10 #include "mec_pcfg.h"
11 #include "mec_defs.h"
12 #include "mec_ecia_api.h"
13 #include "mec_retval.h"
14 #include "mec_ecia_api.h"
15 
16 /* #define MEC_ECIA_ENABLE_CHECKS */
17 #ifdef MEC_ECIA_ENABLE_CHECKS
18 #include <assert.h>
19 #endif
20 
21 /*
22  * EC Interrupt Aggregator and NVIC configuration.
23  * Implementation:
24  * All NVIC enables and priorities will be set at initialization based
25  * upon the supplied direct bitmap and NVIC priority.
26  * Peripheral level code will use the ECIA GIRQ and any peripheral interrupt
27  * enable/status registers.
28  * Reason:
29  * NVIC interrupt registers may only be accessed when the Cortex-M4 is in
30  * privileged mode.
31  */
32 
33 /* b[4:0] = number of interrupt lines in groups of 32.
34  * 0 = 32
35  * 1 = 64
36  * 2 = 96
37  * ...
38  * 7 = 256
39  */
40 
41 struct mec_nvic_map {
42     uint8_t girq_bitpos;
43     uint8_t nvic_direct;
44 };
45 
46 struct mec_girq_route {
47     uint8_t nvic_aggr;
48     uint8_t num_direct;
49     const struct mec_nvic_map *nmap;
50 };
51 
52 static const struct mec_nvic_map girq13_nvic_map[] = {
53     { 0U, 20U }, { 1U, 21U }, { 2U, 22U }, { 3U, 23U }, { 4U, 158U },
54 #if defined(MEC5_I3C_HOST_CTRL_INSTANCES)
55     { 8U, 181U },
56 #endif
57 #if defined(MEC5_I3C_SEC_CTRL_INSTANCES)
58     { 9U, 182U },
59 #endif
60 #if defined(MEC5_HAS_USB_OTG_0)
61     { 10U, 192U },
62 #endif
63 };
64 #define GIRQ13_NUM_DIRECT (sizeof(girq13_nvic_map) / sizeof(struct mec_nvic_map))
65 
66 static const struct mec_nvic_map girq14_nvic_map[] = {
67     { 0U, 24U }, { 1U, 25U }, { 2U, 26U }, { 3U, 27U }, { 4U, 28U },
68     { 5U, 29U }, { 6U, 30U }, { 7U, 31U }, { 8U, 32U }, { 9U, 33U },
69     { 10U, 34U }, { 11U, 35U }, { 12U, 36U }, { 13U, 37U }, { 14U, 38U },
70     { 15U, 39U },
71 #if MEC5_DMAC_NUM_CHANNELS == 20
72     { 16U, 194U }, { 17U, 195U }, { 18U, 196U }, { 19U, 197U },
73 #endif
74 };
75 #define GIRQ14_NUM_DIRECT (sizeof(girq14_nvic_map) / sizeof(struct mec_nvic_map))
76 
77 static const struct mec_nvic_map girq15_nvic_map[] = {
78     { 0U, 40U }, { 1U, 41U }, { 2U, 42U }, { 3U, 43U }, { 4U, 44U },
79     { 5U, 45U }, { 6U, 46U }, { 7U, 47U }, { 8U, 48U }, { 9U, 49U },
80     { 10U, 50U }, { 11U, 51U }, { 12U, 52U }, { 13U, 53U }, { 14U, 54U },
81     { 15U, 55U }, { 16U, 56U }, { 17U, 57U }, { 18U, 58U }, { 19U, 59U },
82     { 20U, 60U }, { 22U, 62U },
83 #if MEC5_UART_INSTANCES > 2
84     { 25U, 183U },
85 #endif
86 #if MEC5_UART_INSTANCES > 3
87     { 26U, 184 },
88 #endif
89 };
90 #define GIRQ15_NUM_DIRECT (sizeof(girq15_nvic_map) / sizeof(struct mec_nvic_map))
91 
92 static const struct mec_nvic_map girq16_nvic_map[] = {
93     { 0U, 65U }, { 2U, 67U }, { 3U, 68U }
94 };
95 #define GIRQ16_NUM_DIRECT (sizeof(girq16_nvic_map) / sizeof(struct mec_nvic_map))
96 
97 static const struct mec_nvic_map girq17_nvic_map[] = {
98     { 0U, 70U }, { 1U, 71U }, { 2U, 72U }, { 3U, 73U }, { 4U, 159U },
99     { 8U, 78U }, { 9U, 79U }, { 10U, 80U }, { 11U, 81U }, { 12U, 82U },
100     { 13U, 83U }, { 14U, 84U }, { 15U, 85U }, { 16U, 86U }, { 17U, 87U },
101     { 18U, 88U }, { 19U, 89U }, { 20U, 74U }, { 21U, 75U }, { 22U, 76U },
102     { 23U, 77U }
103 };
104 #define GIRQ17_NUM_DIRECT (sizeof(girq17_nvic_map) / sizeof(struct mec_nvic_map))
105 
106 static const struct mec_nvic_map girq18_nvic_map[] = {
107     { 1U, 91U },
108     { 2U, 92U },
109 #if MEC5_GPSPI_CTRL_VERSION == 1
110     { 3U, 93U},
111 #endif
112     { 4U, 94U },
113 #if MEC5_GPSPI_CTRL_VERSION == 1
114     { 5U, 95U},
115 #endif
116     { 6U, 97U }, { 7U, 96U },
117     { 10U, 100U },
118 #if MEC5_P2S_INSTANCES == 2
119     { 11U, 101U },
120 #endif
121     { 20U, 146U }, { 21U, 147U }, { 22U, 148U }, { 23U, 149U }, { 24U, 150U },
122     { 25U, 151U }, { 26U, 152U }, { 27U, 153U }, { 28U, 154U },
123 };
124 #define GIRQ18_NUM_DIRECT (sizeof(girq18_nvic_map) / sizeof(struct mec_nvic_map))
125 
126 static const struct mec_nvic_map girq19_nvic_map[] = {
127     { 0U, 103U }, { 1U, 104U }, { 2U, 105U }, { 3U, 106U }, { 4U, 107U },
128     { 5U, 108U }, { 6U, 109U }, { 7U, 110U }, { 8U, 156U }, { 9U, 166U },
129     { 10U, 167U },
130 };
131 #define GIRQ19_NUM_DIRECT (sizeof(girq19_nvic_map) / sizeof(struct mec_nvic_map))
132 
133 static const struct mec_nvic_map girq20_nvic_map[] = {
134     { 3U, 173U }, { 9U, 174U }
135 };
136 #define GIRQ20_NUM_DIRECT (sizeof(girq20_nvic_map) / sizeof(struct mec_nvic_map))
137 
138 static const struct mec_nvic_map girq21_nvic_map[] = {
139     { 2U, 171U },  { 3U, 114U },  { 4U, 115U },  { 5U, 116U },  { 6U, 117U },
140     { 7U, 118U },  { 8U, 119U },  { 9U, 120U },  { 10U, 121U }, { 11U, 122U },
141     { 12U, 123U }, { 13U, 124U }, { 14U, 125U }, { 18U, 129U }, { 19U, 130U },
142 #if MEC5_P2S_INSTANCES == 2
143     { 21U, 132U },
144 #endif
145     { 24U, 134U }, { 26U, 172U },
146 #ifdef MEC5_HAS_ROM_TIMER
147     { 27U, 193U }
148 #endif
149 };
150 #define GIRQ21_NUM_DIRECT (sizeof(girq21_nvic_map) / sizeof(struct mec_nvic_map))
151 
152 /* NOTE: GIRQ22 aggregated output and individual source interrupt signals
153  * are not connected to the NVIC. GIRQ22's purpose is to signal MEC's power
154  * managemente HW to turn on the PLL to process incoming signal/data from
155  * an external device. HW determins if the event requires EC notification.
156  * If EC notification required the respective peripheral interrupt signal
157  * will assert otherwise HW will turn off the PLL and re-enter full deep sleep.
158  */
159 static const struct mec_nvic_map girq22_nvic_map[] = {
160     { 0U, 255U }, /* Process event received on SPI Target */
161     { 1U, 255U }, /* Process event received on I2C Controller 0 */
162     { 2U, 255U },
163     { 3U, 255U },
164     { 4U, 255U },
165     { 5U, 255U }, /* Process event received on I2C Controller 4 */
166     { 9U, 255U }, /* Process event received on eSPI interface */
167 #if defined(MEC5_I3C_HOST_CTRL_INSTANCES)
168     { 16U, 255U }, /* Process event received on I3C Primary Controller */
169 #endif
170 #if defined(MEC5_I3C_SEC_CTRL_INSTANCES)
171     { 17U, 255U }, /* Process event received on I3C Secondary Controller */
172 #endif
173 };
174 #define GIRQ22_NUM_DIRECT 0
175 
176 static const struct mec_nvic_map girq23_nvic_map[] = {
177     { 0U, 136U }, { 1U, 137U }, { 2U, 138U }, { 3U, 139U }, { 4U, 140U },
178     { 5U, 141U }, { 6U, 142U }, { 7U, 143U }, { 8U, 144U }, { 9U, 145U },
179     { 10U, 111U }, { 16U, 112U }, { 17U, 113U },
180 };
181 #define GIRQ23_NUM_DIRECT (sizeof(girq23_nvic_map) / sizeof(struct mec_nvic_map))
182 
183 static const struct mec_girq_route girq_routing_tbl[MEC5_ECIA_NUM_GIRQS]  = {
184     { 0U, 0U, NULL }, /* GIRQ08 - GIRQ12 aggregated only */
185     { 1U, 0U, NULL },
186     { 2U, 0U, NULL },
187     { 3U, 0U, NULL },
188     { 4U, 0U, NULL },
189     { 5U, GIRQ13_NUM_DIRECT, girq13_nvic_map },
190     { 6U, GIRQ14_NUM_DIRECT, girq14_nvic_map },
191     { 7U, GIRQ15_NUM_DIRECT, girq15_nvic_map },
192     { 8U, GIRQ16_NUM_DIRECT, girq16_nvic_map },
193     { 9U, GIRQ17_NUM_DIRECT, girq17_nvic_map },
194     { 10U, GIRQ18_NUM_DIRECT, girq18_nvic_map },
195     { 11U, GIRQ19_NUM_DIRECT, girq19_nvic_map },
196     { 12U, GIRQ20_NUM_DIRECT, girq20_nvic_map },
197     { 13U, GIRQ21_NUM_DIRECT, girq21_nvic_map },
198     { 255U, GIRQ22_NUM_DIRECT, girq22_nvic_map }, /* GIRQ22 clock wake only */
199     { 14U, GIRQ23_NUM_DIRECT, girq23_nvic_map },
200     { 15U, 0U, NULL }, /* GIRQ24 - GIRQ26 aggregated only */
201     { 16U, 0U, NULL },
202     { 17U, 0U, NULL }
203 };
204 
nvic_extirq_enable(uint32_t extn)205 static void nvic_extirq_enable(uint32_t extn)
206 {
207     if (extn >= MEC5_MAX_NVIC_EXT_INPUTS) {
208         return;
209     }
210 
211     NVIC_EnableIRQ(extn);
212 }
213 
nvic_extirq_disable(uint32_t extn)214 static void nvic_extirq_disable(uint32_t extn)
215 {
216     if (extn >= MEC5_MAX_NVIC_EXT_INPUTS) {
217         return;
218     }
219 
220     NVIC_DisableIRQ(extn);
221 }
222 
nvic_extirq_pend_clear(uint32_t extn)223 static void nvic_extirq_pend_clear(uint32_t extn)
224 {
225     if (extn >= MEC5_MAX_NVIC_EXT_INPUTS) {
226         return;
227     }
228 
229     NVIC_ClearPendingIRQ(extn);
230 }
231 
nvic_extirq_pend_get(uint32_t extn)232 static uint32_t nvic_extirq_pend_get(uint32_t extn)
233 {
234     if (extn >= MEC5_MAX_NVIC_EXT_INPUTS) {
235         return 0;
236     }
237 
238     return NVIC_GetPendingIRQ(extn);
239 }
240 
241 /* priority = Cortex-M4 NVIC for this SoC. 3-bits where 0 = highest and 7 is
242  * lowest priority. Each external interrupt priority is an 8-bit register
243  * where the priority is stored in the upper 3 bits.
244  */
nvic_extirq_priority_set(uint32_t extn,uint8_t priority)245 static void nvic_extirq_priority_set(uint32_t extn, uint8_t priority)
246 {
247     if (extn >= MEC5_MAX_NVIC_EXT_INPUTS) {
248         return;
249     }
250 
251     NVIC_SetPriority(extn, priority);
252 }
253 
nvic_extirq_priority_get(uint32_t extn)254 static uint32_t nvic_extirq_priority_get(uint32_t extn)
255 {
256     if (extn >= MEC5_MAX_NVIC_EXT_INPUTS) {
257         return 0; /* NVIC POR default priority */
258     }
259 
260     return NVIC_GetPriority(extn);
261 }
262 
enable_nvic_aggregated(uint32_t aggr_bitmap)263 static void enable_nvic_aggregated(uint32_t aggr_bitmap)
264 {
265     uint32_t abm = aggr_bitmap & MEC5_ECIA_ALL_BITMAP;
266 
267     for (uint32_t n = MEC5_ECIA_FIRST_GIRQ_NOS; n < MEC5_ECIA_LAST_GIRQ_NOS; n++) {
268         if (!abm) {
269             break;
270         }
271 
272         if (abm & MEC_BIT(n)) {
273             const struct mec_girq_route *pgr = &girq_routing_tbl[n - MEC5_ECIA_FIRST_GIRQ_NOS];
274 
275             NVIC_EnableIRQ(pgr->nvic_aggr);
276             abm &= (uint32_t)~MEC_BIT(n);
277         }
278     }
279 }
280 
enable_nvic_directs(uint32_t girq_bitmap)281 static void enable_nvic_directs(uint32_t girq_bitmap)
282 {
283     for (size_t n = 0; n < MEC5_ECIA_NUM_GIRQS; n++) {
284         const struct mec_girq_route *gr = &girq_routing_tbl[n];
285 
286         if ((gr->nvic_aggr == 0xffu) || (gr->num_direct == 0u)) {
287             continue;
288         }
289 
290         if (!(girq_bitmap & MEC_BIT(n + 8u))) {
291             continue;
292         }
293 
294         const struct mec_nvic_map *map = gr->nmap;
295 
296         for (uint8_t m = 0; m < gr->num_direct; m++) {
297             NVIC_EnableIRQ(map[m].nvic_direct);
298         }
299     }
300 }
301 
302 /* Set all GIRQ enables for specified direct GIRQ's */
enable_girq_direct_bitmap(uint32_t bitmap)303 static void enable_girq_direct_bitmap(uint32_t bitmap)
304 {
305     uint32_t dbm = bitmap & MEC5_ECIA_DIRECT_BITMAP;
306     uint32_t bpos = 0;
307     uint8_t msb = 0;
308 
309     while (dbm) {
310         /* returns 32 if no bits are set */
311         msb = __CLZ(dbm);
312         if (msb == 32U) {
313             break;
314         }
315 
316         bpos = 31u - msb; /* convert number of leading zeros to bit position */
317         if ((bpos >= MEC5_ECIA_FIRST_GIRQ_NOS) && (bpos <= MEC5_ECIA_LAST_GIRQ_NOS)) {
318             const struct mec_girq_route *pgr =
319                 &girq_routing_tbl[bpos - MEC5_ECIA_FIRST_GIRQ_NOS];
320 
321             if (pgr->nmap && !(MEC_ECIA0->BLK_EN_SET & MEC_BIT(bpos))) {
322                 MEC_ECIA0->GIRQ[0].EN_SET = UINT32_MAX;
323             }
324         }
325 
326         dbm &= (uint32_t)~MEC_BIT(bpos);
327     }
328 }
329 
330 /* !!! Touches NVIC registers. Caller must be Privileged !!!
331  * NOTE: Cortex-M4 NVIC encodes priority where 0 = highest and lowests
332  * is equal to all bits set. The number of bits implemented is set at
333  * hardware design time (MEC_NVIC_NUM_PRI_BITS).
334  */
set_all_pri(uint8_t dflt_priority)335 static void set_all_pri(uint8_t dflt_priority)
336 {
337     uint32_t pri32 = ((uint32_t)(dflt_priority & 0x7U) << (8U - __NVIC_PRIO_BITS)) & 0xffu;
338     uintptr_t nvic_ip_addr = (uintptr_t)&NVIC->IP[0];
339 
340     pri32 |= (pri32 << 8);
341     pri32 |= (pri32 << 16);
342 
343     for (uint32_t n = 0; n < MEC5_NVIC_NUM_IP_REGS; n++) {
344         MEC_MMCR32(nvic_ip_addr) = pri32;
345         nvic_ip_addr += 4U;
346     }
347 }
348 
is_direct_allowed(void)349 static inline int is_direct_allowed(void)
350 {
351     if (MEC_ECS->INTR_CTRL & MEC_BIT(MEC_ECS_INTR_CTRL_DIRECT_Pos)) {
352         return 1;
353     }
354     return 0;
355 }
356 
357 /**
358  * mec_ecia_init - Initial EC Interrupt Aggregator and NVIC
359  * external interrupt registers.
360  *
361  * @param direct_bitmap Bit map of GIRQ's caller wants to use direct NVIC
362  * connection.
363  *
364  * @param dflt_priority - Priority 0=highest to 7=lowest to set all
365  * external peripheral NVIC priority to.
366  *
367  * @note - Touches NVIC registers. Caller must be Privileged.
368  * Restrictions on GIRQ's:
369  * Aggregated only: 8-12 and 24-26
370  * Direct or Aggregated: 13-21 and 23
371  * No connection to NVIC: GIRQ22 used to wake AHB fabric only.
372  * The function parameters will be masked with allowed bitmaps.
373  *
374  * Sets all NVIC enables for direct and aggregated interrupt
375  * sources.
376  * TODO - change to set all GIRQ enables for direct. Do not
377  * set any NVIC enables. Drivers will handle NVIC enables.
378  * How to handle Aggregated only GIRQ's?
379  * GIRQ's 8 - 12, and 26 are GPIO's. The GPIO control registers
380  * have interrupt enable fields but ROM enable some. Enabling
381  * the aggregated GIRQ's may cause an issue.
382  * GIRQ's 24 and 25 are for eSPI Controller to Target virtual wires.
383  * Each C2T VWire has an interrupt enable field. We should be able
384  * to enable these.
385  */
mec_hal_ecia_init(uint32_t direct_bitmap,uint8_t dflt_priority,uint32_t flags)386 void mec_hal_ecia_init(uint32_t direct_bitmap, uint8_t dflt_priority, uint32_t flags)
387 {
388     uint32_t aggr_bitmap = 0, i = 0;
389 
390     /* Clear ECIA PCR sleep enable */
391     /* TODO mec_pcr_clr_blk_slp_en(MEC_PCR_ECIA); */
392 
393     /* Disconnect all direct capable GIRQ sources from the NVIC
394      * allowing us to clear direct NVIC pending bits
395      */
396     MEC_ECS->INTR_CTRL &= ~(MEC_ECS_INTR_CTRL_DIRECT_Msk);
397 
398     /* disconnect all GIRQ aggregated block outputs from NVIC */
399     MEC_ECIA0->BLK_EN_CLR = UINT32_MAX;
400 
401     /* clear all ECIA GIRQ individual enables and status(source) bits */
402     for (i = 0; i < MEC5_ECIA_NUM_GIRQS; i++) {
403         MEC_ECIA0->GIRQ[i].EN_CLR = UINT32_MAX;
404         MEC_ECIA0->GIRQ[i].SOURCE = UINT32_MAX;
405     }
406 
407     /* clear all NVIC enables and pending status */
408     for (i = 0; i < MEC5_NVIC_NUM_REGS; i++) {
409         NVIC->ICER[i] = UINT32_MAX;
410         NVIC->ICPR[i] = UINT32_MAX;
411     }
412 
413     set_all_pri(dflt_priority);
414 
415     /* mask out GIRQ's that cannot do direct */
416     direct_bitmap &= MEC5_ECIA_DIRECT_BITMAP;
417     aggr_bitmap = MEC5_ECIA_ALL_BITMAP & ~(direct_bitmap);
418 
419     /* Route all aggregated GIRQn outputs to NVIC */
420     MEC_ECIA0->BLK_EN_SET = aggr_bitmap;
421     if (flags & MEC_ECIA_INIT_FLAG_ALL_AGGR_GIRQ) {
422         enable_nvic_aggregated(aggr_bitmap);
423     }
424 
425     /* enable any direct connections? */
426     if (direct_bitmap) {
427         /* Disconnect aggregated GIRQ output for direct mapped */
428         MEC_ECIA0->BLK_EN_CLR = direct_bitmap;
429         MEC_ECS->INTR_CTRL |= MEC_BIT(MEC_ECS_INTR_CTRL_DIRECT_Pos);
430         if (flags & MEC_ECIA_INIT_FLAG_ALL_DIRECT_GIRQ) {
431             enable_girq_direct_bitmap(direct_bitmap);
432         }
433         if (flags & MEC_ECIA_INIT_FLAG_ALL_DIRECT_NVIC) {
434             enable_nvic_directs(direct_bitmap);
435         }
436     }
437 }
438 
439 /* Enable/disable multiple GIRQ sources */
mec_hal_girq_bm_en(uint32_t girq_num,uint32_t bitmap,uint8_t enable)440 int mec_hal_girq_bm_en(uint32_t girq_num, uint32_t bitmap, uint8_t enable)
441 {
442     if ((girq_num < MEC5_ECIA_FIRST_GIRQ_NOS) || (girq_num > MEC5_ECIA_LAST_GIRQ_NOS)) {
443         return MEC_RET_ERR_INVAL;
444     }
445 
446     if (!bitmap) {
447         return MEC_RET_OK;
448     }
449 
450     uint32_t gidx = girq_num - MEC5_ECIA_FIRST_GIRQ_NOS;
451 
452     if (enable) {
453         MEC_ECIA0->GIRQ[gidx].EN_SET = bitmap;
454     } else {
455         MEC_ECIA0->GIRQ[gidx].EN_CLR = bitmap;
456     }
457 
458     return MEC_RET_OK;
459 }
460 
461 /* Clear multiple GIRQ source(status) bits */
mec_hal_girq_bm_clr_src(uint32_t girq_num,uint32_t bitmap)462 int mec_hal_girq_bm_clr_src(uint32_t girq_num, uint32_t bitmap)
463 {
464     if ((girq_num < MEC5_ECIA_FIRST_GIRQ_NOS) || (girq_num > MEC5_ECIA_LAST_GIRQ_NOS)) {
465         return MEC_RET_ERR_INVAL;
466     }
467 
468     if (!bitmap) {
469         return MEC_RET_OK;
470     }
471 
472     uint32_t gidx = girq_num - MEC5_ECIA_FIRST_GIRQ_NOS;
473 
474     MEC_ECIA0->GIRQ[gidx].SOURCE = bitmap;
475 
476     return MEC_RET_OK;
477 }
478 
mec_hal_girq_source_get(uint32_t girq_num)479 uint32_t mec_hal_girq_source_get(uint32_t girq_num)
480 {
481     if ((girq_num < MEC5_ECIA_FIRST_GIRQ_NOS) || (girq_num > MEC5_ECIA_LAST_GIRQ_NOS)) {
482         return 0u;
483     }
484 
485     uint32_t gidx = girq_num - MEC5_ECIA_FIRST_GIRQ_NOS;
486 
487     return MEC_ECIA0->GIRQ[gidx].SOURCE;
488 }
489 
mec_hal_girq_result_get(uint32_t girq_num)490 uint32_t mec_hal_girq_result_get(uint32_t girq_num)
491 {
492     if ((girq_num < MEC5_ECIA_FIRST_GIRQ_NOS) || (girq_num > MEC5_ECIA_LAST_GIRQ_NOS)) {
493         return 0u;
494     }
495 
496     uint32_t gidx = girq_num - MEC5_ECIA_FIRST_GIRQ_NOS;
497 
498     return MEC_ECIA0->GIRQ[gidx].RESULT;
499 }
500 
mec_hal_girq_result_test(uint32_t girq_num,uint32_t bitpos)501 uint32_t mec_hal_girq_result_test(uint32_t girq_num, uint32_t bitpos)
502 {
503     uint32_t result = mec_hal_girq_result_get(girq_num);
504 
505     return (result & MEC_BIT(bitpos));
506 }
507 
508 /* Set or clear GIRQ enable for a peripheral source. */
mec_hal_girq_ctrl(uint32_t devi,int enable)509 void mec_hal_girq_ctrl(uint32_t devi, int enable)
510 {
511     uint32_t gidx = MEC5_ECIA_INFO_GIRQZ(devi);
512     uint32_t gpos = MEC5_ECIA_INFO_GIRQ_POS(devi);
513 
514     if (gidx >= MEC5_ECIA_NUM_GIRQS) {
515         return;
516     }
517 
518     if (enable) { /* write 1 to set register */
519         MEC_ECIA0->GIRQ[gidx].EN_SET = MEC_BIT(gpos);
520     } else { /* write 1 to clear register */
521         MEC_ECIA0->GIRQ[gidx].EN_CLR = MEC_BIT(gpos);
522     }
523 }
524 
525 /*
526  * Return 0 if source not set else non-zero
527  * (single bit should be set in word)
528  */
mec_hal_girq_src(uint32_t devi)529 uint32_t mec_hal_girq_src(uint32_t devi)
530 {
531     uint32_t gidx = MEC5_ECIA_INFO_GIRQZ(devi);
532     uint32_t gpos = MEC5_ECIA_INFO_GIRQ_POS(devi);
533 
534     if (gidx >= MEC5_ECIA_NUM_GIRQS) {
535         return 0;
536     }
537 
538     return MEC_ECIA0->GIRQ[gidx].SOURCE & MEC_BIT(gpos);
539 }
540 
mec_hal_girq_result(uint32_t devi)541 uint32_t mec_hal_girq_result(uint32_t devi)
542 {
543     uint32_t gidx = MEC5_ECIA_INFO_GIRQZ(devi);
544     uint32_t gpos = MEC5_ECIA_INFO_GIRQ_POS(devi);
545 
546     if (gidx >= MEC5_ECIA_NUM_GIRQS) {
547         return 0;
548     }
549 
550     return MEC_ECIA0->GIRQ[gidx].RESULT & MEC_BIT(gpos);
551 }
552 
553 /* Clear GIRQ source(status) for a peripheral source. */
mec_hal_girq_clr_src(uint32_t devi)554 void mec_hal_girq_clr_src(uint32_t devi)
555 {
556     uint32_t gidx = MEC5_ECIA_INFO_GIRQZ(devi);
557     uint32_t gpos = MEC5_ECIA_INFO_GIRQ_POS(devi);
558 
559     if (gidx >= MEC5_ECIA_NUM_GIRQS) {
560         return;
561     }
562 
563     /* register is write 1 to clear bit(s) */
564     MEC_ECIA0->GIRQ[gidx].SOURCE = MEC_BIT(gpos);
565 }
566 
mec_hal_ecia_girq_aggr_enable(uint32_t girq_num,uint8_t enable)567 int mec_hal_ecia_girq_aggr_enable(uint32_t girq_num, uint8_t enable)
568 {
569     uint8_t gid = (uint8_t)(girq_num & 0xffu);
570 
571     if ((gid < MEC5_ECIA_FIRST_GIRQ_NOS) || (girq_num > MEC5_ECIA_LAST_GIRQ_NOS)) {
572         return MEC_RET_ERR_INVAL;
573     }
574 
575     if (enable) {
576         MEC_ECIA0->BLK_EN_SET = MEC_BIT(gid);
577     } else {
578         MEC_ECIA0->BLK_EN_CLR = MEC_BIT(gid);
579     }
580 
581     return MEC_RET_OK;
582 }
583 
584 /*
585  * This is not a simple question.
586  * This routine only works if Method 1 initialization
587  * is implemented in mec_ecia_init() and the application
588  * developer calls mec_ecia_init() or duplicates its
589  * functionality.
590  */
mec_hal_ecia_is_direct(uint32_t devi)591 int mec_hal_ecia_is_direct(uint32_t devi)
592 {
593     /* Is direct mode disabled? */
594     if (!is_direct_allowed()) {
595         return 0;
596     }
597 
598     uint32_t girq_num = MEC5_ECIA_INFO_GIRQZ(devi) + MEC5_ECIA_FIRST_GIRQ_NOS;
599 
600     if (!(MEC_BIT(girq_num) & MEC5_ECIA_DIRECT_BITMAP)) {
601         return 0;
602     }
603 
604     /* Is aggregated GIRQ routed to NVIC? */
605     if (MEC_ECIA0->BLK_EN_SET & MEC_BIT(girq_num)) {
606         return 0; /* Yes, don't use direct */
607     }
608 
609     return 1;
610 }
611 
612 /* !!! Touches NVIC register(s). Caller must be Privileged !!! */
613 
mec_hal_ecia_nvic_enable(uint32_t devi)614 void mec_hal_ecia_nvic_enable(uint32_t devi)
615 {
616     uint32_t nvic_extn = MEC5_ECIA_INFO_NVIC_AGGR(devi);
617 
618     if (mec_hal_ecia_is_direct(devi)) {
619         nvic_extn = MEC5_ECIA_INFO_NVIC_DIRECT(devi);
620     }
621 
622     nvic_extirq_enable(nvic_extn);
623 }
624 
mec_hal_ecia_nvic_disable(uint32_t devi)625 void mec_hal_ecia_nvic_disable(uint32_t devi)
626 {
627     uint32_t nvic_extn = MEC5_ECIA_INFO_NVIC_AGGR(devi);
628 
629     if (mec_hal_ecia_is_direct(devi)) {
630         nvic_extn = MEC5_ECIA_INFO_NVIC_DIRECT(devi);
631     }
632 
633     nvic_extirq_disable(nvic_extn);
634 }
635 
mec_hal_ecia_nvic_clr_pend(uint32_t devi)636 void mec_hal_ecia_nvic_clr_pend(uint32_t devi)
637 {
638     uint32_t nvic_extn = MEC5_ECIA_INFO_NVIC_AGGR(devi);
639 
640     if (mec_hal_ecia_is_direct(devi)) {
641         nvic_extn = MEC5_ECIA_INFO_NVIC_DIRECT(devi);
642     }
643 
644     nvic_extirq_pend_clear(nvic_extn);
645 }
646 
mec_hal_ecia_nvic_get_pending(uint32_t devi)647 uint32_t mec_hal_ecia_nvic_get_pending(uint32_t devi)
648 {
649     uint32_t extn = MEC5_ECIA_INFO_NVIC_AGGR(devi);
650 
651     if (mec_hal_ecia_is_direct(devi)) {
652         extn = MEC5_ECIA_INFO_NVIC_DIRECT(devi);
653     }
654 
655     return nvic_extirq_pend_get(extn);
656 }
657 
mec_hal_ecia_nvic_get_pri(uint32_t devi)658 uint8_t mec_hal_ecia_nvic_get_pri(uint32_t devi)
659 {
660     uint32_t extn = MEC5_ECIA_INFO_NVIC_AGGR(devi);
661 
662     if (mec_hal_ecia_is_direct(devi)) {
663         extn = MEC5_ECIA_INFO_NVIC_DIRECT(devi);
664     }
665 
666     return (uint8_t)(nvic_extirq_priority_get(extn));
667 }
668 
mec_hal_ecia_nvic_set_pri(uint32_t devi,uint8_t priority)669 void mec_hal_ecia_nvic_set_pri(uint32_t devi, uint8_t priority)
670 {
671     uint32_t extn = MEC5_ECIA_INFO_NVIC_AGGR(devi);
672 
673     if (mec_hal_ecia_is_direct(devi)) {
674         extn = MEC5_ECIA_INFO_NVIC_DIRECT(devi);
675     }
676 
677     if (priority > MEC5_NVIC_PRI_LO_VAL) {
678         priority = MEC5_NVIC_PRI_LO_VAL;
679     }
680 
681     nvic_extirq_priority_set(extn, priority);
682 }
683 
684 /* end mec_ecia.c */
685