1 /*
2  * Copyright (c) 2021 Microchip Technology Inc.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @brief Driver for External interrupt controller in Microchip XEC devices
9  *
10  * Driver is currently implemented to support MEC172x ECIA GIRQs
11  */
12 
13 #define DT_DRV_COMPAT microchip_xec_ecia
14 
15 #include <zephyr/arch/cpu.h>
16 #include <cmsis_core.h>
17 #include <zephyr/device.h>
18 #include <soc.h>
19 #include <zephyr/sys/__assert.h>
20 #include <zephyr/drivers/clock_control/mchp_xec_clock_control.h>
21 #include <zephyr/drivers/interrupt_controller/intc_mchp_xec_ecia.h>
22 #include <zephyr/dt-bindings/interrupt-controller/mchp-xec-ecia.h>
23 #include <zephyr/irq.h>
24 
25 /* defined at the SoC layer */
26 #define MCHP_FIRST_GIRQ			MCHP_FIRST_GIRQ_NOS
27 #define MCHP_LAST_GIRQ			MCHP_LAST_GIRQ_NOS
28 #define MCHP_XEC_DIRECT_CAPABLE		MCHP_ECIA_DIRECT_BITMAP
29 
30 #define GIRQ_ID_TO_BITPOS(id) ((id) + 8)
31 
32 /*
33  * MEC SoC's have one and only one instance of ECIA. GIRQ8 register are located
34  * at the beginning of the ECIA block.
35  */
36 #define ECIA_XEC_REG_BASE						\
37 	((struct ecia_regs *)(DT_REG_ADDR(DT_NODELABEL(ecia))))
38 
39 #define ECS_XEC_REG_BASE						\
40 	((struct ecs_regs *)(DT_REG_ADDR(DT_NODELABEL(ecs))))
41 
42 #define PCR_XEC_REG_BASE						\
43 	((struct pcr_regs *)(DT_REG_ADDR(DT_NODELABEL(pcr))))
44 
45 #define ECIA_XEC_PCR_REG_IDX	DT_INST_CLOCKS_CELL(0, regidx)
46 #define ECIA_XEC_PCR_BITPOS	DT_INST_CLOCKS_CELL(0, bitpos)
47 
48 #define ECIA_XEC_PCR_INFO						\
49 	MCHP_XEC_PCR_SCR_ENCODE(DT_INST_CLOCKS_CELL(0, regidx),		\
50 				DT_INST_CLOCKS_CELL(0, bitpos),		\
51 				DT_INST_CLOCKS_CELL(0, domain))
52 
53 struct xec_girq_config {
54 	uintptr_t base;
55 	uint8_t girq_id;
56 	uint8_t num_srcs;
57 	uint8_t sources[32];
58 };
59 
60 struct xec_ecia_config {
61 	uintptr_t ecia_base;
62 	struct mchp_xec_pcr_clk_ctrl clk_ctrl;
63 	const struct device *girq_node_handles[32];
64 };
65 
66 struct xec_girq_src_data {
67 	mchp_xec_ecia_callback_t cb;
68 	void *data;
69 };
70 
71 #define DEV_ECIA_CFG(ecia_dev) \
72 	((const struct xec_ecia_config *const)(ecia_dev)->config)
73 
74 #define DEV_GIRQ_CFG(girq_dev) \
75 	((const struct xec_girq_config *const)(girq_dev)->config)
76 
77 #define DEV_GIRQ_DATA(girq_dev) \
78 	((struct xec_girq_src_data *const)(girq_dev)->data)
79 
80 /*
81  * Enable/disable specified GIRQ's aggregated output. Aggregated output is the
82  * bit-wise or of all the GIRQ's result bits.
83  */
mchp_xec_ecia_girq_aggr_en(uint8_t girq_num,uint8_t enable)84 void mchp_xec_ecia_girq_aggr_en(uint8_t girq_num, uint8_t enable)
85 {
86 	struct ecia_regs *regs = ECIA_XEC_REG_BASE;
87 
88 	if (enable) {
89 		regs->BLK_EN_SET = BIT(girq_num);
90 	} else {
91 		regs->BLK_EN_CLR = BIT(girq_num);
92 	}
93 }
94 
mchp_xec_ecia_girq_src_clr(uint8_t girq_num,uint8_t src_bit_pos)95 void mchp_xec_ecia_girq_src_clr(uint8_t girq_num, uint8_t src_bit_pos)
96 {
97 	if ((girq_num < MCHP_FIRST_GIRQ) || (girq_num > MCHP_LAST_GIRQ)) {
98 		return;
99 	}
100 
101 	struct ecia_regs *regs = ECIA_XEC_REG_BASE;
102 
103 	/* write 1 to clear */
104 	regs->GIRQ[girq_num - MCHP_FIRST_GIRQ].SRC = BIT(src_bit_pos);
105 }
106 
mchp_xec_ecia_girq_src_en(uint8_t girq_num,uint8_t src_bit_pos)107 void mchp_xec_ecia_girq_src_en(uint8_t girq_num, uint8_t src_bit_pos)
108 {
109 	if ((girq_num < MCHP_FIRST_GIRQ) || (girq_num > MCHP_LAST_GIRQ)) {
110 		return;
111 	}
112 
113 	struct ecia_regs *regs = ECIA_XEC_REG_BASE;
114 
115 	/* write 1 to set */
116 	regs->GIRQ[girq_num - MCHP_FIRST_GIRQ].EN_SET = BIT(src_bit_pos);
117 }
118 
mchp_xec_ecia_girq_src_dis(uint8_t girq_num,uint8_t src_bit_pos)119 void mchp_xec_ecia_girq_src_dis(uint8_t girq_num, uint8_t src_bit_pos)
120 {
121 	if ((girq_num < MCHP_FIRST_GIRQ) || (girq_num > MCHP_LAST_GIRQ)) {
122 		return;
123 	}
124 
125 	struct ecia_regs *regs = ECIA_XEC_REG_BASE;
126 
127 	/* write 1 to clear */
128 	regs->GIRQ[girq_num - MCHP_FIRST_GIRQ].EN_CLR = BIT(src_bit_pos);
129 }
130 
mchp_xec_ecia_girq_src_clr_bitmap(uint8_t girq_num,uint32_t bitmap)131 void mchp_xec_ecia_girq_src_clr_bitmap(uint8_t girq_num, uint32_t bitmap)
132 {
133 	if ((girq_num < MCHP_FIRST_GIRQ) || (girq_num > MCHP_LAST_GIRQ)) {
134 		return;
135 	}
136 
137 	struct ecia_regs *regs = ECIA_XEC_REG_BASE;
138 
139 	/* write 1 to clear */
140 	regs->GIRQ[girq_num - MCHP_FIRST_GIRQ].SRC = bitmap;
141 }
142 
mchp_xec_ecia_girq_src_en_bitmap(uint8_t girq_num,uint32_t bitmap)143 void mchp_xec_ecia_girq_src_en_bitmap(uint8_t girq_num, uint32_t bitmap)
144 {
145 	if ((girq_num < MCHP_FIRST_GIRQ) || (girq_num > MCHP_LAST_GIRQ)) {
146 		return;
147 	}
148 
149 	struct ecia_regs *regs = ECIA_XEC_REG_BASE;
150 
151 	/* write 1 to clear */
152 	regs->GIRQ[girq_num - MCHP_FIRST_GIRQ].EN_SET = bitmap;
153 }
154 
mchp_xec_ecia_girq_src_dis_bitmap(uint8_t girq_num,uint32_t bitmap)155 void mchp_xec_ecia_girq_src_dis_bitmap(uint8_t girq_num, uint32_t bitmap)
156 {
157 	if ((girq_num < MCHP_FIRST_GIRQ) || (girq_num > MCHP_LAST_GIRQ)) {
158 		return;
159 	}
160 
161 	struct ecia_regs *regs = ECIA_XEC_REG_BASE;
162 
163 	/* write 1 to clear */
164 	regs->GIRQ[girq_num - MCHP_FIRST_GIRQ].EN_CLR = bitmap;
165 }
166 
167 /*
168  * Return read-only GIRQ result register. Result is bit-wise and of source
169  * and enable registers.
170  */
mchp_xec_ecia_girq_result(uint8_t girq_num)171 uint32_t mchp_xec_ecia_girq_result(uint8_t girq_num)
172 {
173 	if ((girq_num < MCHP_FIRST_GIRQ) || (girq_num > MCHP_LAST_GIRQ)) {
174 		return 0U;
175 	}
176 
177 	struct ecia_regs *regs = ECIA_XEC_REG_BASE;
178 
179 	return regs->GIRQ[girq_num - MCHP_FIRST_GIRQ].RESULT;
180 }
181 
182 /* Clear NVIC pending given the external NVIC input number (zero based) */
mchp_xec_ecia_nvic_clr_pend(uint32_t nvic_num)183 void mchp_xec_ecia_nvic_clr_pend(uint32_t nvic_num)
184 {
185 	if (nvic_num >= ((SCnSCB->ICTR + 1) * 32)) {
186 		return;
187 	}
188 
189 	NVIC_ClearPendingIRQ(nvic_num);
190 }
191 
192 /* API taking input encoded with MCHP_XEC_ECIA(g, gb, na, nd) macro */
193 
mchp_xec_ecia_info_girq_aggr_en(int ecia_info,uint8_t enable)194 void mchp_xec_ecia_info_girq_aggr_en(int ecia_info, uint8_t enable)
195 {
196 	uint8_t girq_num = MCHP_XEC_ECIA_GIRQ(ecia_info);
197 
198 	mchp_xec_ecia_girq_aggr_en(girq_num, enable);
199 }
200 
mchp_xec_ecia_info_girq_src_clr(int ecia_info)201 void mchp_xec_ecia_info_girq_src_clr(int ecia_info)
202 {
203 	uint8_t girq_num = MCHP_XEC_ECIA_GIRQ(ecia_info);
204 	uint8_t bitpos = MCHP_XEC_ECIA_GIRQ_POS(ecia_info);
205 
206 	mchp_xec_ecia_girq_src_clr(girq_num, bitpos);
207 }
208 
mchp_xec_ecia_info_girq_src_en(int ecia_info)209 void mchp_xec_ecia_info_girq_src_en(int ecia_info)
210 {
211 	uint8_t girq_num = MCHP_XEC_ECIA_GIRQ(ecia_info);
212 	uint8_t bitpos = MCHP_XEC_ECIA_GIRQ_POS(ecia_info);
213 
214 	mchp_xec_ecia_girq_src_en(girq_num, bitpos);
215 }
216 
mchp_xec_ecia_info_girq_src_dis(int ecia_info)217 void mchp_xec_ecia_info_girq_src_dis(int ecia_info)
218 {
219 	uint8_t girq_num = MCHP_XEC_ECIA_GIRQ(ecia_info);
220 	uint8_t bitpos = MCHP_XEC_ECIA_GIRQ_POS(ecia_info);
221 
222 	mchp_xec_ecia_girq_src_dis(girq_num, bitpos);
223 }
224 
mchp_xec_ecia_info_girq_result(int ecia_info)225 uint32_t mchp_xec_ecia_info_girq_result(int ecia_info)
226 {
227 	uint8_t girq_num = MCHP_XEC_ECIA_GIRQ(ecia_info);
228 
229 	return mchp_xec_ecia_girq_result(girq_num);
230 }
231 
232 /*
233  * Clear NVIC pending status given GIRQ source information encoded by macro
234  * MCHP_XEC_ECIA. For aggregated only sources the encoding sets direct NVIC
235  * number equal to aggregated NVIC number.
236  */
mchp_xec_ecia_info_nvic_clr_pend(int ecia_info)237 void mchp_xec_ecia_info_nvic_clr_pend(int ecia_info)
238 {
239 	uint8_t nvic_num = MCHP_XEC_ECIA_NVIC_DIRECT(ecia_info);
240 
241 	mchp_xec_ecia_nvic_clr_pend(nvic_num);
242 }
243 
244 /**
245  * @brief enable GIRQn interrupt for specific source
246  *
247  * @param girq is the GIRQ number (8 - 26)
248  * @param src is the interrupt source in the GIRQ (0 - 31)
249  */
mchp_xec_ecia_enable(int girq,int src)250 int mchp_xec_ecia_enable(int girq, int src)
251 {
252 	if ((girq < MCHP_FIRST_GIRQ) || (girq > MCHP_LAST_GIRQ) ||
253 	    (src < 0) || (src > 31)) {
254 		return -EINVAL;
255 	}
256 
257 	struct ecia_regs *regs = ECIA_XEC_REG_BASE;
258 
259 	/* write 1 to set */
260 	regs->GIRQ[girq - MCHP_FIRST_GIRQ].EN_SET = BIT(src);
261 
262 	return 0;
263 }
264 
265 /**
266  * @brief enable EXTI interrupt for specific line specified by parameter
267  * encoded with MCHP_XEC_ECIA macro.
268  *
269  * @param ecia_info is GIRQ connection encoded with MCHP_XEC_ECIA
270  */
mchp_xec_ecia_info_enable(int ecia_info)271 int mchp_xec_ecia_info_enable(int ecia_info)
272 {
273 	uint8_t girq = (uint8_t)MCHP_XEC_ECIA_GIRQ(ecia_info);
274 	uint8_t src = (uint8_t)MCHP_XEC_ECIA_GIRQ_POS(ecia_info);
275 
276 	return mchp_xec_ecia_enable(girq, src);
277 }
278 
279 /**
280  * @brief disable EXTI interrupt for specific line
281  *
282  * @param girq is the GIRQ number (8 - 26)
283  * @param src is the interrupt source in the GIRQ (0 - 31)
284  */
mchp_xec_ecia_disable(int girq,int src)285 int mchp_xec_ecia_disable(int girq, int src)
286 {
287 	if ((girq < MCHP_FIRST_GIRQ) || (girq > MCHP_LAST_GIRQ) ||
288 	    (src < 0) || (src > 31)) {
289 		return -EINVAL;
290 	}
291 
292 	struct ecia_regs *regs = ECIA_XEC_REG_BASE;
293 
294 	/* write 1 to clear */
295 	regs->GIRQ[girq - MCHP_FIRST_GIRQ].EN_CLR = BIT(src);
296 
297 	return 0;
298 }
299 
300 /**
301  * @brief disable EXTI interrupt for specific line specified by parameter
302  * encoded with MCHP_XEC_ECIA macro.
303  *
304  * @param ecia_info is GIRQ connection encoded with MCHP_XEC_ECIA
305  */
mchp_xec_ecia_info_disable(int ecia_info)306 int mchp_xec_ecia_info_disable(int ecia_info)
307 {
308 	uint8_t girq = (uint8_t)MCHP_XEC_ECIA_GIRQ(ecia_info);
309 	uint8_t src = (uint8_t)MCHP_XEC_ECIA_GIRQ_POS(ecia_info);
310 
311 	return mchp_xec_ecia_disable(girq, src);
312 }
313 
314 /* forward reference */
315 static const struct device *get_girq_dev(int girq_num);
316 
317 /**
318  * @brief set GIRQn interrupt source callback
319  *
320  * @param dev_girq is the GIRQn device handle
321  * @param src is the interrupt source in the GIRQ (0 - 31)
322  * @param cb user callback
323  * @param data user data
324  */
mchp_xec_ecia_set_callback_by_dev(const struct device * dev_girq,int src,mchp_xec_ecia_callback_t cb,void * data)325 int mchp_xec_ecia_set_callback_by_dev(const struct device *dev_girq, int src,
326 				      mchp_xec_ecia_callback_t cb, void *data)
327 {
328 	if ((dev_girq == NULL) || (src < 0) || (src > 31)) {
329 		return -EINVAL;
330 	}
331 
332 	const struct xec_girq_config *const cfg = DEV_GIRQ_CFG(dev_girq);
333 	struct xec_girq_src_data *girq_data = DEV_GIRQ_DATA(dev_girq);
334 
335 	/* source exists in this GIRQ? */
336 	if (!(cfg->sources[src] & BIT(7))) {
337 		return -EINVAL;
338 	}
339 
340 	/* obtain the callback array index for the source */
341 	int idx = (int)(cfg->sources[src] & ~BIT(7));
342 
343 	girq_data[idx].cb = cb;
344 	girq_data[idx].data = data;
345 
346 	return 0;
347 }
348 
349 /**
350  * @brief set GIRQn interrupt source callback
351  *
352  * @param girq is the GIRQ number (8 - 26)
353  * @param src is the interrupt source in the GIRQ (0 - 31)
354  * @param cb user callback
355  * @param data user data
356  */
mchp_xec_ecia_set_callback(int girq_num,int src,mchp_xec_ecia_callback_t cb,void * data)357 int mchp_xec_ecia_set_callback(int girq_num, int src,
358 			       mchp_xec_ecia_callback_t cb, void *data)
359 {
360 	const struct device *dev = get_girq_dev(girq_num);
361 
362 	return mchp_xec_ecia_set_callback_by_dev(dev, src, cb, data);
363 }
364 
365 /**
366  * @brief set GIRQn interrupt source callback
367  *
368  * @param ecia_info is GIRQ connection encoded with MCHP_XEC_ECIA
369  * @param cb user callback
370  * @param data user data
371  */
mchp_xec_ecia_info_set_callback(int ecia_info,mchp_xec_ecia_callback_t cb,void * data)372 int mchp_xec_ecia_info_set_callback(int ecia_info, mchp_xec_ecia_callback_t cb,
373 				    void *data)
374 {
375 	const struct device *dev = get_girq_dev(MCHP_XEC_ECIA_GIRQ(ecia_info));
376 	uint8_t src = MCHP_XEC_ECIA_GIRQ_POS(ecia_info);
377 
378 	return mchp_xec_ecia_set_callback_by_dev(dev, src, cb, data);
379 }
380 
381 /**
382  * @brief unset GIRQn interrupt source callback by device handle
383  *
384  * @param dev_girq is the GIRQn device handle
385  * @param src is the interrupt source in the GIRQ (0 - 31)
386  */
mchp_ecia_unset_callback_by_dev(const struct device * dev_girq,int src)387 int mchp_ecia_unset_callback_by_dev(const struct device *dev_girq, int src)
388 {
389 	if ((dev_girq == NULL) || (src < 0) || (src > 31)) {
390 		return -EINVAL;
391 	}
392 
393 	const struct xec_girq_config *const cfg = DEV_GIRQ_CFG(dev_girq);
394 	struct xec_girq_src_data *girq_data = DEV_GIRQ_DATA(dev_girq);
395 
396 	/* source exists in this GIRQ? */
397 	if (!(cfg->sources[src] & BIT(7))) {
398 		return -EINVAL;
399 	}
400 
401 	/* obtain the callback array index for the source */
402 	int idx = (int)(cfg->sources[src] & ~BIT(7));
403 
404 	girq_data[idx].cb = NULL;
405 	girq_data[idx].data = NULL;
406 
407 	return 0;
408 }
409 
410 /**
411  * @brief unset GIRQn interrupt source callback
412  *
413  * @param girq is the GIRQ number (8 - 26)
414  * @param src is the interrupt source in the GIRQ (0 - 31)
415  */
mchp_ecia_unset_callback(int girq_num,int src)416 int mchp_ecia_unset_callback(int girq_num, int src)
417 {
418 	const struct device *dev = get_girq_dev(girq_num);
419 
420 	return mchp_ecia_unset_callback_by_dev(dev, src);
421 }
422 
423 /**
424  * @brief unset GIRQn interrupt source callback
425  *
426  * @param ecia_info is GIRQ connection encoded with MCHP_XEC_ECIA
427  */
mchp_ecia_info_unset_callback(int ecia_info)428 int mchp_ecia_info_unset_callback(int ecia_info)
429 {
430 	const struct device *dev = get_girq_dev(MCHP_XEC_ECIA_GIRQ(ecia_info));
431 	uint8_t src = MCHP_XEC_ECIA_GIRQ_POS(ecia_info);
432 
433 	return mchp_ecia_unset_callback_by_dev(dev, src);
434 }
435 
436 
437 /*
438  * Create a build time flag to know if any aggregated GIRQ has been enabled.
439  * We make use of DT FOREACH macro to check GIRQ node status.
440  * Enabling a GIRQ node (status = "okay") implies you want it used in
441  * aggregated mode. Note, GIRQ 8-12, 24-26 are aggregated only by HW design.
442  * If a GIRQ node is disabled(status = "disabled") and is direct capable the
443  * other driver/application may use IRQ_CONNECT, irq_enable, and the helper
444  * functions in this driver to set/clear GIRQ enable bits and status.
445  * Leaving a node disabled also allows another driver/application to take over
446  * aggregation by managing the GIRQ itself.
447  */
448 #define XEC_CHK_REQ_AGGR(n) DT_NODE_HAS_STATUS(n, okay) |
449 
450 #define XEC_ECIA_REQUIRE_AGGR_ISR					\
451 	(								\
452 	DT_FOREACH_CHILD(DT_NODELABEL(ecia), XEC_CHK_REQ_AGGR) \
453 	0)
454 
455 /* static const uint32_t xec_chk_req = (XEC_ECIA_REQUIRE_AGGR_ISR); */
456 
457 #if XEC_ECIA_REQUIRE_AGGR_ISR
458 /*
459  * Generic ISR for aggregated GIRQ's.
460  * GIRQ source(status) bits are latched (R/W1C). The peripheral status
461  * connected to the GIRQ source bit must be cleared first by the callback
462  * and this routine will clear the GIRQ source bit. If a callback was not
463  * registered for a source the enable will also be cleared to prevent
464  * interrupt storms.
465  * NOTE: dev_girq is a pointer to a GIRQ child device instance.
466  */
xec_girq_isr(const struct device * dev_girq)467 static void xec_girq_isr(const struct device *dev_girq)
468 {
469 	const struct xec_girq_config *const cfg = DEV_GIRQ_CFG(dev_girq);
470 	struct xec_girq_src_data *data = DEV_GIRQ_DATA(dev_girq);
471 	struct girq_regs *girq = (struct girq_regs *)cfg->base;
472 	int girq_id = GIRQ_ID_TO_BITPOS(cfg->girq_id);
473 	uint32_t idx = 0;
474 	uint32_t result = girq->RESULT;
475 
476 	for (int i = 0; result && i < 32; i++) {
477 		uint8_t bitpos = 31 - (__builtin_clz(result) & 0x1f);
478 
479 		/* clear GIRQ latched status */
480 		girq->SRC = BIT(bitpos);
481 		result &= ~BIT(bitpos);
482 
483 		/* is it an implemented source? */
484 		if (cfg->sources[bitpos] & BIT(7)) {
485 			/* yes, get the index by removing bit[7] flag */
486 			idx = (uint32_t)cfg->sources[bitpos] & ~BIT(7);
487 			/* callback registered? */
488 			if (data[idx].cb) {
489 				data[idx].cb(girq_id, bitpos, data[idx].data);
490 			} else { /* no callback, clear the enable */
491 				girq->EN_CLR = BIT(bitpos);
492 			}
493 		} else { /* paranoia, we should not get here... */
494 			girq->EN_CLR = BIT(bitpos);
495 		}
496 	}
497 }
498 #endif
499 
500 /**
501  * @brief initialize XEC ECIA driver
502  * NOTE: GIRQ22 is special used for waking the PLL from deep sleep when a
503  * peripheral receives data from an external entity (eSPI, I2C, etc). Once
504  * the data transfer is complete the system re-enters deep sleep unless the
505  * peripheral was configured to wake CPU after reception of data or event.
506  * GIRQ22 aggregated output and sources are not connected to the NVIC.
507  * We enable GIRQ22 aggregated output to ensure clock asynchronous wake
508  * functionality is operational.
509  */
xec_ecia_init(const struct device * dev)510 static int xec_ecia_init(const struct device *dev)
511 {
512 	const struct xec_ecia_config *cfg =
513 		(const struct xec_ecia_config *const) (dev->config);
514 	const struct device *const clk_dev = DEVICE_DT_GET(DT_NODELABEL(pcr));
515 	struct ecs_regs *const ecs = ECS_XEC_REG_BASE;
516 	struct ecia_regs *const ecia = (struct ecia_regs *)cfg->ecia_base;
517 	uint32_t n = 0, nr = 0;
518 	int ret;
519 
520 	if (!device_is_ready(clk_dev)) {
521 		return -ENODEV;
522 	}
523 
524 	ret = clock_control_on(clk_dev,
525 			       (clock_control_subsys_t)&cfg->clk_ctrl);
526 	if (ret < 0) {
527 		return ret;
528 	}
529 
530 	/* Enable all direct NVIC connections */
531 	ecs->INTR_CTRL |= BIT(0);
532 
533 	/* gate off all aggregated outputs */
534 	ecia->BLK_EN_CLR = UINT32_MAX;
535 
536 	/* connect aggregated only GIRQs to NVIC */
537 	ecia->BLK_EN_SET = MCHP_ECIA_AGGR_BITMAP;
538 
539 	/* Clear all GIRQn source enables */
540 	for (n = 0; n < MCHP_GIRQS; n++) {
541 		ecia->GIRQ[n].EN_CLR = UINT32_MAX;
542 	}
543 
544 	/* Clear all external NVIC enables and pending status */
545 	nr = SCnSCB->ICTR;
546 	for (n = 0u; n <= nr; n++) {
547 		NVIC->ICER[n] = UINT32_MAX;
548 		NVIC->ICPR[n] = UINT32_MAX;
549 	}
550 
551 	/* ecia->BLK_ACTIVE = xec_chk_req; */
552 
553 	return 0;
554 }
555 
556 /* xec_config_girq_xxx.sources[] entries from GIRQ node */
557 #define XEC_GIRQ_SOURCES2(node_id, prop, idx)				\
558 	.sources[DT_PROP_BY_IDX(node_id, prop, idx)] =			\
559 		((uint8_t)(idx) | BIT(7)),
560 
561 /* Parameter n is a child node-id */
562 #define GIRQ_XEC_DEVICE(n)						\
563 	static int xec_girq_init_##n(const struct device *dev);		\
564 									\
565 	static struct xec_girq_src_data					\
566 		xec_data_girq_##n[DT_PROP_LEN(n, sources)];		\
567 									\
568 	static const struct xec_girq_config xec_config_girq_##n = {	\
569 		.base = DT_REG_ADDR(n),					\
570 		.girq_id = DT_PROP(n, girq_id),				\
571 		.num_srcs = DT_PROP_LEN(n, sources),			\
572 		DT_FOREACH_PROP_ELEM(n, sources, XEC_GIRQ_SOURCES2)	\
573 	};								\
574 									\
575 	DEVICE_DT_DEFINE(n, xec_girq_init_##n,				\
576 		 NULL, &xec_data_girq_##n, &xec_config_girq_##n,	\
577 		 PRE_KERNEL_1, CONFIG_XEC_GIRQ_INIT_PRIORITY,		\
578 		 NULL);							\
579 									\
580 	static int xec_girq_init_##n(const struct device *dev)		\
581 	{								\
582 		mchp_xec_ecia_girq_aggr_en(				\
583 			GIRQ_ID_TO_BITPOS(DT_PROP(n, girq_id)), 1);	\
584 									\
585 		IRQ_CONNECT(DT_IRQN(n),					\
586 			    DT_IRQ(n, priority),			\
587 			    xec_girq_isr,				\
588 			    DEVICE_DT_GET(n), 0);			\
589 									\
590 		irq_enable(DT_IRQN(n));					\
591 									\
592 		return 0;						\
593 	}
594 
595 /*
596  * iterate over each enabled child node of ECIA
597  * Enable means property status = "okay"
598  */
599 DT_FOREACH_CHILD_STATUS_OKAY(DT_NODELABEL(ecia), GIRQ_XEC_DEVICE)
600 
601 /* n = GIRQ node id */
602 #define XEC_GIRQ_HANDLE(n)					\
603 	.girq_node_handles[DT_PROP(n, girq_id)] = (DEVICE_DT_GET(n)),
604 
605 static const struct xec_ecia_config xec_config_ecia = {
606 	.ecia_base = DT_REG_ADDR(DT_NODELABEL(ecia)),
607 	.clk_ctrl = {
608 		.pcr_info = ECIA_XEC_PCR_INFO,
609 	},
610 	DT_FOREACH_CHILD_STATUS_OKAY(DT_NODELABEL(ecia), XEC_GIRQ_HANDLE)
611 };
612 
613 DEVICE_DT_DEFINE(DT_NODELABEL(ecia), xec_ecia_init,
614 		 NULL, NULL, &xec_config_ecia,
615 		 PRE_KERNEL_1, CONFIG_INTC_INIT_PRIORITY,
616 		 NULL);
617 
618 /* look up GIRQ node handle from ECIA configuration */
get_girq_dev(int girq_num)619 static const struct device *get_girq_dev(int girq_num)
620 {
621 	if ((girq_num < MCHP_FIRST_GIRQ) || (girq_num > MCHP_LAST_GIRQ)) {
622 		return NULL;
623 	}
624 
625 	/* safe to convert to zero based index */
626 	girq_num -= MCHP_FIRST_GIRQ;
627 
628 	return xec_config_ecia.girq_node_handles[girq_num];
629 }
630