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