pic.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2022-08-24 GuEe-GUI first version
  9. */
  10. #include <rthw.h>
  11. #include <rtthread.h>
  12. #define DBG_TAG "rtdm.pic"
  13. #define DBG_LVL DBG_INFO
  14. #include <rtdbg.h>
  15. #include <drivers/pic.h>
  16. struct irq_traps
  17. {
  18. rt_list_t list;
  19. void *data;
  20. rt_bool_t (*handler)(void *);
  21. };
  22. static int _ipi_hash[] =
  23. {
  24. #ifdef RT_USING_SMP
  25. [RT_SCHEDULE_IPI] = RT_SCHEDULE_IPI,
  26. [RT_STOP_IPI] = RT_STOP_IPI,
  27. #endif
  28. };
  29. /* reserved ipi */
  30. static int _pirq_hash_idx = RT_ARRAY_SIZE(_ipi_hash);
  31. static struct rt_pic_irq _pirq_hash[MAX_HANDLERS] =
  32. {
  33. [0 ... MAX_HANDLERS - 1] =
  34. {
  35. .irq = -1,
  36. .hwirq = -1,
  37. .mode = RT_IRQ_MODE_NONE,
  38. .priority = RT_UINT32_MAX,
  39. .rw_lock = { },
  40. }
  41. };
  42. static struct rt_spinlock _pic_lock = { };
  43. static rt_size_t _pic_name_max = sizeof("PIC");
  44. static rt_list_t _pic_nodes = RT_LIST_OBJECT_INIT(_pic_nodes);
  45. static rt_list_t _traps_nodes = RT_LIST_OBJECT_INIT(_traps_nodes);
  46. static struct rt_pic_irq *irq2pirq(int irq)
  47. {
  48. struct rt_pic_irq *pirq;
  49. if (irq >= 0 && irq < MAX_HANDLERS)
  50. {
  51. pirq = &_pirq_hash[irq];
  52. if (pirq->irq < 0)
  53. {
  54. pirq = RT_NULL;
  55. }
  56. }
  57. if (!pirq)
  58. {
  59. LOG_E("irq = %d is invalid", irq);
  60. }
  61. return pirq;
  62. }
  63. static void append_pic(struct rt_pic *pic)
  64. {
  65. int pic_name_len = rt_strlen(pic->ops->name);
  66. rt_list_insert_before(&_pic_nodes, &pic->list);
  67. if (pic_name_len > _pic_name_max)
  68. {
  69. _pic_name_max = pic_name_len;
  70. }
  71. }
  72. rt_err_t rt_pic_linear_irq(struct rt_pic *pic, rt_size_t irq_nr)
  73. {
  74. rt_err_t err = RT_EOK;
  75. if (pic && pic->ops && pic->ops->name)
  76. {
  77. rt_ubase_t level = rt_spin_lock_irqsave(&_pic_lock);
  78. if (_pirq_hash_idx + irq_nr <= RT_ARRAY_SIZE(_pirq_hash))
  79. {
  80. rt_list_init(&pic->list);
  81. pic->irq_start = _pirq_hash_idx;
  82. pic->irq_nr = irq_nr;
  83. pic->pirqs = &_pirq_hash[_pirq_hash_idx];
  84. _pirq_hash_idx += irq_nr;
  85. append_pic(pic);
  86. LOG_D("%s alloc irqs ranges [%d, %d]", pic->ops->name,
  87. pic->irq_start, pic->irq_start + pic->irq_nr);
  88. }
  89. else
  90. {
  91. LOG_E("%s alloc %d irqs is overflow", pic->ops->name, irq_nr);
  92. err = -RT_EEMPTY;
  93. }
  94. rt_spin_unlock_irqrestore(&_pic_lock, level);
  95. }
  96. else
  97. {
  98. err = -RT_EINVAL;
  99. }
  100. return err;
  101. }
  102. static void config_pirq(struct rt_pic *pic, struct rt_pic_irq *pirq, int irq, int hwirq)
  103. {
  104. rt_ubase_t level = rt_spin_lock_irqsave(&pirq->rw_lock);
  105. pirq->irq = irq;
  106. pirq->hwirq = hwirq;
  107. pirq->pic = pic;
  108. rt_list_init(&pirq->isr.list);
  109. rt_spin_unlock_irqrestore(&pirq->rw_lock, level);
  110. }
  111. int rt_pic_config_ipi(struct rt_pic *pic, int ipi_index, int hwirq)
  112. {
  113. int ipi = ipi_index;
  114. if (pic && ipi < RT_ARRAY_SIZE(_ipi_hash) && hwirq >= 0 && pic->ops->irq_send_ipi)
  115. {
  116. config_pirq(pic, &_pirq_hash[ipi], ipi, hwirq);
  117. LOG_D("%s config %s %d to hwirq %d", pic->ops->name, "ipi", ipi, hwirq);
  118. }
  119. else
  120. {
  121. ipi = -RT_EINVAL;
  122. }
  123. return ipi;
  124. }
  125. int rt_pic_config_irq(struct rt_pic *pic, int irq_index, int hwirq)
  126. {
  127. int irq;
  128. if (pic && hwirq >= 0)
  129. {
  130. irq = pic->irq_start + irq_index;
  131. if (irq >= 0 && irq < MAX_HANDLERS)
  132. {
  133. config_pirq(pic, &_pirq_hash[irq], irq, hwirq);
  134. LOG_D("%s config %s %d to hwirq %d", pic->ops->name, "irq", irq, hwirq);
  135. }
  136. else
  137. {
  138. irq = -RT_ERROR;
  139. }
  140. }
  141. else
  142. {
  143. irq = -RT_EINVAL;
  144. }
  145. return irq;
  146. }
  147. struct rt_pic_irq *rt_pic_find_ipi(struct rt_pic *pic, int ipi_index)
  148. {
  149. struct rt_pic_irq *pirq = &_pirq_hash[ipi_index];
  150. RT_ASSERT(ipi_index < RT_ARRAY_SIZE(_ipi_hash));
  151. RT_ASSERT(pirq->pic == pic);
  152. return pirq;
  153. }
  154. int rt_pic_cascade(struct rt_pic *pic, struct rt_pic *parent_pic, int hwirq, rt_uint32_t mode)
  155. {
  156. int irq = -RT_EINVAL;
  157. if (pic && parent_pic && hwirq >= 0)
  158. {
  159. struct rt_pic *ppic = parent_pic;
  160. rt_ubase_t level = rt_spin_lock_irqsave(&_pic_lock);
  161. while (!ppic->ops->irq_map && ppic->parent)
  162. {
  163. ppic = ppic->parent;
  164. }
  165. rt_spin_unlock_irqrestore(&_pic_lock, level);
  166. if (ppic->ops->irq_map)
  167. {
  168. struct rt_pic_irq *pirq;
  169. irq = ppic->ops->irq_map(ppic, hwirq, mode);
  170. if (irq >= 0 && (pirq = irq2pirq(irq)))
  171. {
  172. rt_spin_lock(&pirq->rw_lock);
  173. pirq->pic = pic;
  174. pic->parent = parent_pic;
  175. rt_spin_unlock(&pirq->rw_lock);
  176. if (rt_list_isempty(&pic->list))
  177. {
  178. rt_ubase_t level = rt_spin_lock_irqsave(&_pic_lock);
  179. append_pic(pic);
  180. rt_spin_unlock_irqrestore(&_pic_lock, level);
  181. }
  182. }
  183. }
  184. else
  185. {
  186. irq = -RT_ENOSYS;
  187. }
  188. }
  189. return irq;
  190. }
  191. void rt_pic_uncascade(struct rt_pic *pic, int irq)
  192. {
  193. struct rt_pic_irq *pirq;
  194. if (pic && pic->parent && irq >= 0 && (pirq = irq2pirq(irq)))
  195. {
  196. struct rt_pic *ppic, *prev = RT_NULL;
  197. rt_spin_lock(&pirq->rw_lock);
  198. ppic = pirq->pic;
  199. while (ppic && pic->parent != ppic->parent)
  200. {
  201. prev = ppic;
  202. ppic = ppic->parent;
  203. }
  204. if (ppic)
  205. {
  206. if (prev)
  207. {
  208. pirq->pic = prev;
  209. prev->parent = pic->parent;
  210. }
  211. else
  212. {
  213. pirq->pic = pic->parent;
  214. }
  215. pic->parent = RT_NULL;
  216. }
  217. rt_spin_unlock(&pirq->rw_lock);
  218. }
  219. }
  220. rt_err_t rt_pic_attach_irq(int irq, rt_isr_handler_t handler, void *uid, const char *name, int flags)
  221. {
  222. rt_err_t err = -RT_EINVAL;
  223. struct rt_pic_irq *pirq;
  224. if (handler && name && (pirq = irq2pirq(irq)))
  225. {
  226. struct rt_pic_isr *isr = RT_NULL;
  227. rt_ubase_t level = rt_spin_lock_irqsave(&pirq->rw_lock);
  228. err = RT_EOK;
  229. if (!pirq->isr.action.handler)
  230. {
  231. /* first attach */
  232. isr = &pirq->isr;
  233. rt_list_init(&isr->list);
  234. }
  235. else
  236. {
  237. rt_spin_unlock_irqrestore(&pirq->rw_lock, level);
  238. if ((isr = rt_malloc(sizeof(*isr))))
  239. {
  240. rt_list_init(&isr->list);
  241. level = rt_spin_lock_irqsave(&pirq->rw_lock);
  242. rt_list_insert_after(&pirq->isr.list, &isr->list);
  243. }
  244. else
  245. {
  246. LOG_E("No memory to save '%s' isr", name);
  247. err = -RT_ERROR;
  248. }
  249. }
  250. if (!err)
  251. {
  252. isr->flags = flags;
  253. isr->action.handler = handler;
  254. isr->action.param = uid;
  255. #ifdef RT_USING_INTERRUPT_INFO
  256. isr->action.counter = 0;
  257. rt_strncpy(isr->action.name, name, RT_NAME_MAX);
  258. #endif
  259. rt_spin_unlock_irqrestore(&pirq->rw_lock, level);
  260. }
  261. }
  262. return err;
  263. }
  264. rt_err_t rt_pic_detach_irq(int irq, void *uid)
  265. {
  266. rt_err_t err = -RT_EINVAL;
  267. struct rt_pic_irq *pirq = irq2pirq(irq);
  268. if (pirq)
  269. {
  270. rt_bool_t will_free = RT_FALSE;
  271. struct rt_pic_isr *isr = RT_NULL;
  272. rt_ubase_t level = rt_spin_lock_irqsave(&pirq->rw_lock);
  273. isr = &pirq->isr;
  274. if (isr->action.param == uid)
  275. {
  276. if (rt_list_isempty(&isr->list))
  277. {
  278. isr->action.handler = RT_NULL;
  279. isr->action.param = RT_NULL;
  280. }
  281. else
  282. {
  283. struct rt_pic_isr *next_isr = rt_list_entry(isr->list.next, struct rt_pic_isr, list);
  284. rt_list_remove(&next_isr->list);
  285. isr->action.handler = next_isr->action.handler;
  286. isr->action.param = next_isr->action.param;
  287. #ifdef RT_USING_INTERRUPT_INFO
  288. isr->action.counter = next_isr->action.counter;
  289. rt_strncpy(isr->action.name, next_isr->action.name, RT_NAME_MAX);
  290. #endif
  291. isr = next_isr;
  292. will_free = RT_TRUE;
  293. }
  294. err = RT_EOK;
  295. }
  296. else
  297. {
  298. rt_list_for_each_entry(isr, &pirq->isr.list, list)
  299. {
  300. if (isr->action.param == uid)
  301. {
  302. err = RT_EOK;
  303. will_free = RT_TRUE;
  304. rt_list_remove(&isr->list);
  305. break;
  306. }
  307. }
  308. }
  309. rt_spin_unlock_irqrestore(&pirq->rw_lock, level);
  310. if (will_free)
  311. {
  312. rt_free(isr);
  313. }
  314. }
  315. return err;
  316. }
  317. rt_err_t rt_pic_add_traps(rt_bool_t (*handler)(void *), void *data)
  318. {
  319. rt_err_t err = -RT_EINVAL;
  320. if (handler)
  321. {
  322. struct irq_traps *traps = rt_malloc(sizeof(*traps));
  323. if (traps)
  324. {
  325. rt_ubase_t level = rt_hw_interrupt_disable();
  326. rt_list_init(&traps->list);
  327. traps->data = data;
  328. traps->handler = handler;
  329. rt_list_insert_before(&_traps_nodes, &traps->list);
  330. err = RT_EOK;
  331. rt_hw_interrupt_enable(level);
  332. }
  333. else
  334. {
  335. LOG_E("No memory to save '%p' handler", handler);
  336. err = -RT_ENOMEM;
  337. }
  338. }
  339. return err;
  340. }
  341. rt_err_t rt_pic_do_traps(void)
  342. {
  343. rt_err_t err = -RT_ERROR;
  344. struct irq_traps *traps;
  345. rt_list_for_each_entry(traps, &_traps_nodes, list)
  346. {
  347. if (traps->handler(traps->data))
  348. {
  349. err = RT_EOK;
  350. break;
  351. }
  352. }
  353. return err;
  354. }
  355. rt_err_t rt_pic_handle_isr(struct rt_pic_irq *pirq)
  356. {
  357. rt_err_t err;
  358. rt_list_t *handler_nodes;
  359. struct rt_irq_desc *action;
  360. RT_ASSERT(pirq != RT_NULL);
  361. RT_ASSERT(pirq->pic != RT_NULL);
  362. /* Corrected irq affinity */
  363. rt_bitmap_set_bit(pirq->affinity, rt_hw_cpu_id());
  364. handler_nodes = &pirq->isr.list;
  365. action = &pirq->isr.action;
  366. if (action->handler)
  367. {
  368. action->handler(pirq->irq, action->param);
  369. #ifdef RT_USING_INTERRUPT_INFO
  370. action->counter++;
  371. #endif
  372. if (!rt_list_isempty(handler_nodes))
  373. {
  374. struct rt_pic_isr *isr;
  375. rt_list_for_each_entry(isr, handler_nodes, list)
  376. {
  377. action = &isr->action;
  378. RT_ASSERT(action->handler != RT_NULL);
  379. action->handler(pirq->irq, action->param);
  380. #ifdef RT_USING_INTERRUPT_INFO
  381. action->counter++;
  382. #endif
  383. }
  384. }
  385. }
  386. else
  387. {
  388. err = -RT_EEMPTY;
  389. }
  390. return err;
  391. }
  392. rt_weak rt_err_t rt_pic_user_extends(struct rt_pic *pic)
  393. {
  394. return -RT_ENOSYS;
  395. }
  396. rt_err_t rt_pic_irq_init(void)
  397. {
  398. rt_err_t err = RT_EOK;
  399. struct rt_pic *pic;
  400. rt_list_for_each_entry(pic, &_pic_nodes, list)
  401. {
  402. if (pic->ops->irq_init)
  403. {
  404. err = pic->ops->irq_init(pic);
  405. if (err)
  406. {
  407. LOG_E("PIC = %s init fail", pic->ops->name);
  408. break;
  409. }
  410. }
  411. }
  412. return err;
  413. }
  414. rt_err_t rt_pic_irq_finit(void)
  415. {
  416. rt_err_t err = RT_EOK;
  417. struct rt_pic *pic;
  418. rt_list_for_each_entry(pic, &_pic_nodes, list)
  419. {
  420. if (pic->ops->irq_finit)
  421. {
  422. err = pic->ops->irq_finit(pic);
  423. if (err)
  424. {
  425. LOG_E("PIC = %s finit fail", pic->ops->name);
  426. break;
  427. }
  428. }
  429. }
  430. return err;
  431. }
  432. #define _irq_call_helper(irq, fn) \
  433. ({ \
  434. struct rt_pic_irq *pirq; \
  435. if ((pirq = irq2pirq(irq))) \
  436. { \
  437. rt_spin_lock(&pirq->rw_lock); \
  438. if (pirq->pic->ops->fn) \
  439. pirq->pic->ops->fn(pirq); \
  440. rt_spin_unlock(&pirq->rw_lock); \
  441. } \
  442. })
  443. void rt_pic_irq_enable(int irq)
  444. {
  445. _irq_call_helper(irq, irq_enable);
  446. }
  447. void rt_pic_irq_disable(int irq)
  448. {
  449. _irq_call_helper(irq, irq_disable);
  450. }
  451. void rt_pic_irq_ack(int irq)
  452. {
  453. _irq_call_helper(irq, irq_ack);
  454. }
  455. void rt_pic_irq_mask(int irq)
  456. {
  457. _irq_call_helper(irq, irq_mask);
  458. }
  459. void rt_pic_irq_unmask(int irq)
  460. {
  461. _irq_call_helper(irq, irq_unmask);
  462. }
  463. void rt_pic_irq_eoi(int irq)
  464. {
  465. _irq_call_helper(irq, irq_eoi);
  466. }
  467. #undef _irq_call_helper
  468. rt_err_t rt_pic_irq_set_priority(int irq, rt_uint32_t priority)
  469. {
  470. rt_err_t err = -RT_EINVAL;
  471. struct rt_pic_irq *pirq = irq2pirq(irq);
  472. if (pirq)
  473. {
  474. rt_spin_lock(&pirq->rw_lock);
  475. if (pirq->pic->ops->irq_set_priority)
  476. {
  477. err = pirq->pic->ops->irq_set_priority(pirq, priority);
  478. if (!err)
  479. {
  480. pirq->priority = priority;
  481. }
  482. }
  483. else
  484. {
  485. err = -RT_ENOSYS;
  486. }
  487. rt_spin_unlock(&pirq->rw_lock);
  488. }
  489. return err;
  490. }
  491. rt_uint32_t rt_pic_irq_get_priority(int irq)
  492. {
  493. rt_uint32_t priority = RT_UINT32_MAX;
  494. struct rt_pic_irq *pirq = irq2pirq(irq);
  495. if (pirq)
  496. {
  497. rt_spin_lock(&pirq->rw_lock);
  498. priority = pirq->priority;
  499. rt_spin_unlock(&pirq->rw_lock);
  500. }
  501. return priority;
  502. }
  503. rt_err_t rt_pic_irq_set_affinity(int irq, rt_bitmap_t *affinity)
  504. {
  505. rt_err_t err = -RT_EINVAL;
  506. struct rt_pic_irq *pirq;
  507. if (affinity && (pirq = irq2pirq(irq)))
  508. {
  509. rt_spin_lock(&pirq->rw_lock);
  510. if (pirq->pic->ops->irq_set_affinity)
  511. {
  512. err = pirq->pic->ops->irq_set_affinity(pirq, affinity);
  513. if (!err)
  514. {
  515. rt_memcpy(pirq->affinity, affinity, sizeof(pirq->affinity));
  516. }
  517. }
  518. else
  519. {
  520. err = -RT_ENOSYS;
  521. }
  522. rt_spin_unlock(&pirq->rw_lock);
  523. }
  524. return err;
  525. }
  526. rt_err_t rt_pic_irq_get_affinity(int irq, rt_bitmap_t *out_affinity)
  527. {
  528. rt_err_t err = -RT_EINVAL;
  529. struct rt_pic_irq *pirq;
  530. if (out_affinity && (pirq = irq2pirq(irq)))
  531. {
  532. rt_spin_lock(&pirq->rw_lock);
  533. rt_memcpy(out_affinity, pirq->affinity, sizeof(pirq->affinity));
  534. err = RT_EOK;
  535. rt_spin_unlock(&pirq->rw_lock);
  536. }
  537. return err;
  538. }
  539. rt_err_t rt_pic_irq_set_triger_mode(int irq, rt_uint32_t mode)
  540. {
  541. rt_err_t err = -RT_EINVAL;
  542. struct rt_pic_irq *pirq;
  543. if ((~mode & RT_IRQ_MODE_MASK) && (pirq = irq2pirq(irq)))
  544. {
  545. rt_spin_lock(&pirq->rw_lock);
  546. if (pirq->pic->ops->irq_set_triger_mode)
  547. {
  548. err = pirq->pic->ops->irq_set_triger_mode(pirq, mode);
  549. if (!err)
  550. {
  551. pirq->mode = mode;
  552. }
  553. }
  554. else
  555. {
  556. err = -RT_ENOSYS;
  557. }
  558. rt_spin_unlock(&pirq->rw_lock);
  559. }
  560. return err;
  561. }
  562. rt_uint32_t rt_pic_irq_get_triger_mode(int irq)
  563. {
  564. rt_uint32_t mode = RT_UINT32_MAX;
  565. struct rt_pic_irq *pirq = irq2pirq(irq);
  566. if (pirq)
  567. {
  568. rt_spin_lock(&pirq->rw_lock);
  569. mode = pirq->mode;
  570. rt_spin_unlock(&pirq->rw_lock);
  571. }
  572. return mode;
  573. }
  574. void rt_pic_irq_send_ipi(int irq, rt_bitmap_t *cpumask)
  575. {
  576. struct rt_pic_irq *pirq;
  577. if (cpumask && (pirq = irq2pirq(irq)))
  578. {
  579. rt_hw_spin_lock(&pirq->rw_lock.lock);
  580. if (pirq->pic->ops->irq_send_ipi)
  581. {
  582. pirq->pic->ops->irq_send_ipi(pirq, cpumask);
  583. }
  584. rt_hw_spin_unlock(&pirq->rw_lock.lock);
  585. }
  586. }
  587. #define _pirq_parent_call_helper(ppic, pirq, fn, ret,...) \
  588. ({ \
  589. if (ppic && pirq) \
  590. { \
  591. rt_spin_lock(&pirq->rw_lock); \
  592. if (ppic->ops->fn) \
  593. { \
  594. struct rt_pic *cpic; \
  595. cpic = pirq->pic; /* push old pic */ \
  596. pirq->pic = ppic; \
  597. ret ppic->ops->fn(pirq __VA_ARGS__); \
  598. pirq->pic = cpic; /* pop old pic */ \
  599. } \
  600. rt_spin_unlock(&pirq->rw_lock); \
  601. } \
  602. })
  603. void rt_pic_irq_parent_enable(struct rt_pic *ppic, struct rt_pic_irq *pirq)
  604. {
  605. _pirq_parent_call_helper(ppic, pirq, irq_enable,,);
  606. }
  607. void rt_pic_irq_parent_disable(struct rt_pic *ppic, struct rt_pic_irq *pirq)
  608. {
  609. _pirq_parent_call_helper(ppic, pirq, irq_disable,,);
  610. }
  611. void rt_pic_irq_parent_ack(struct rt_pic *ppic, struct rt_pic_irq *pirq)
  612. {
  613. _pirq_parent_call_helper(ppic, pirq, irq_ack,,);
  614. }
  615. void rt_pic_irq_parent_mask(struct rt_pic *ppic, struct rt_pic_irq *pirq)
  616. {
  617. _pirq_parent_call_helper(ppic, pirq, irq_mask,,);
  618. }
  619. void rt_pic_irq_parent_unmask(struct rt_pic *ppic, struct rt_pic_irq *pirq)
  620. {
  621. _pirq_parent_call_helper(ppic, pirq, irq_unmask,,);
  622. }
  623. void rt_pic_irq_parent_eoi(struct rt_pic *ppic, struct rt_pic_irq *pirq)
  624. {
  625. _pirq_parent_call_helper(ppic, pirq, irq_eoi,,);
  626. }
  627. rt_err_t rt_pic_irq_parent_set_priority(struct rt_pic *ppic, struct rt_pic_irq *pirq, rt_uint32_t priority)
  628. {
  629. rt_err_t err = -RT_ENOSYS;
  630. _pirq_parent_call_helper(ppic, pirq, irq_set_priority, err = , ,priority);
  631. return err;
  632. }
  633. rt_err_t rt_pic_irq_parent_set_affinity(struct rt_pic *ppic, struct rt_pic_irq *pirq, rt_bitmap_t *affinity)
  634. {
  635. rt_err_t err = -RT_ENOSYS;
  636. _pirq_parent_call_helper(ppic, pirq, irq_set_affinity, err = , ,affinity);
  637. return err;
  638. }
  639. rt_err_t rt_pic_irq_parent_set_triger_mode(struct rt_pic *ppic, struct rt_pic_irq *pirq, rt_uint32_t mode)
  640. {
  641. rt_err_t err = -RT_ENOSYS;
  642. _pirq_parent_call_helper(ppic, pirq, irq_set_triger_mode, err = , ,mode);
  643. return err;
  644. }
  645. #undef _pirq_parent_call_helper
  646. #ifdef RT_USING_OFW
  647. RT_OFW_STUB_RANGE_EXPORT(pic, _pic_ofw_start, _pic_ofw_end);
  648. static rt_err_t ofw_pic_init(void)
  649. {
  650. struct rt_ofw_node *ic_np;
  651. rt_ofw_foreach_node_by_prop(ic_np, "interrupt-controller")
  652. {
  653. rt_ofw_stub_probe_range(ic_np, &_pic_ofw_start, &_pic_ofw_end);
  654. }
  655. return RT_EOK;
  656. }
  657. #else
  658. static rt_err_t ofw_pic_init(void)
  659. {
  660. return RT_EOK;
  661. }
  662. #endif /* !RT_USING_OFW */
  663. rt_err_t rt_pic_init(void)
  664. {
  665. rt_err_t err;
  666. LOG_D("init start");
  667. err = ofw_pic_init();
  668. LOG_D("init end");
  669. return err;
  670. }
  671. #if defined(RT_USING_CONSOLE) && defined(RT_USING_MSH)
  672. static int list_irq(int argc, char**argv)
  673. {
  674. rt_ubase_t level;
  675. rt_size_t irq_nr = 0;
  676. rt_bool_t dump_all = RT_FALSE;
  677. const char *const irq_modes[] =
  678. {
  679. [RT_IRQ_MODE_NONE] = "None",
  680. [RT_IRQ_MODE_EDGE_RISING] = "Edge-Rising",
  681. [RT_IRQ_MODE_EDGE_FALLING] = "Edge-Falling",
  682. [RT_IRQ_MODE_EDGE_BOTH] = "Edge-Both",
  683. [RT_IRQ_MODE_LEVEL_HIGH] = "Level-High",
  684. [RT_IRQ_MODE_LEVEL_LOW] = "Level-Low",
  685. };
  686. static char info[RT_CONSOLEBUF_SIZE];
  687. #ifdef RT_USING_SMP
  688. static char cpumask[RT_CPUS_NR + 1] = { [RT_CPUS_NR] = '\0' };
  689. #endif
  690. if (argc > 1)
  691. {
  692. if (!rt_strcmp(argv[1], "all"))
  693. {
  694. dump_all = RT_TRUE;
  695. }
  696. }
  697. level = rt_hw_interrupt_disable();
  698. rt_kprintf("%-*.s %-*.s %s %-*.s %-*.s %-*.s %-*.sUsers%s\n",
  699. 10, "IRQ",
  700. 10, "HW-IRQ",
  701. "MSI",
  702. _pic_name_max, "PIC",
  703. 12, "Mode",
  704. #ifdef RT_USING_SMP
  705. RT_CPUS_NR, "CPUs",
  706. #else
  707. 0, 0,
  708. #endif
  709. #ifdef RT_USING_INTERRUPT_INFO
  710. 11, "Count",
  711. ""
  712. #else
  713. 0, 0,
  714. "-Number"
  715. #endif
  716. );
  717. for (int i = 0; i < RT_ARRAY_SIZE(_pirq_hash); ++i)
  718. {
  719. struct rt_pic_irq *pirq = &_pirq_hash[i];
  720. if (!pirq->pic || !(dump_all || pirq->isr.action.handler))
  721. {
  722. continue;
  723. }
  724. rt_snprintf(info, sizeof(info), "%-10d %-10d %c %-*.s %-*.s ",
  725. pirq->irq,
  726. pirq->hwirq,
  727. pirq->msi_desc ? 'Y' : 'N',
  728. _pic_name_max, pirq->pic->ops->name,
  729. 12, irq_modes[pirq->mode]);
  730. #ifdef RT_USING_SMP
  731. for (int group = 0, id = 0; group < RT_ARRAY_SIZE(pirq->affinity); ++group)
  732. {
  733. rt_bitmap_t mask = pirq->affinity[group];
  734. for (int idx = 0; id < RT_CPUS_NR && idx < BITMAP_BIT_LEN(1); ++idx, ++id)
  735. {
  736. cpumask[RT_ARRAY_SIZE(cpumask) - id - 2] = '0' + ((mask >> idx) & 1);
  737. }
  738. }
  739. #endif /* RT_USING_SMP */
  740. rt_kputs(info);
  741. #ifdef RT_USING_SMP
  742. rt_kputs(cpumask);
  743. #endif
  744. #ifdef RT_USING_INTERRUPT_INFO
  745. rt_kprintf(" %-10d ", pirq->isr.action.counter);
  746. rt_kputs(pirq->isr.action.name);
  747. rt_kputs("\n");
  748. if (!rt_list_isempty(&pirq->isr.list))
  749. {
  750. struct rt_pic_isr *repeat_isr;
  751. rt_list_for_each_entry(repeat_isr, &pirq->isr.list, list)
  752. {
  753. rt_kputs(info);
  754. #ifdef RT_USING_SMP
  755. rt_kputs(cpumask);
  756. #endif
  757. rt_kprintf("%-10d ", repeat_isr->action.counter);
  758. rt_kputs(repeat_isr->action.name);
  759. rt_kputs("\n");
  760. }
  761. }
  762. #else
  763. rt_kprintf(" %d\n", rt_list_len(&pirq->isr.list));
  764. #endif
  765. ++irq_nr;
  766. }
  767. rt_hw_interrupt_enable(level);
  768. rt_kprintf("%d IRQs found\n", irq_nr);
  769. return 0;
  770. }
  771. MSH_CMD_EXPORT(list_irq, dump using or args = all of irq information);
  772. #endif /* RT_USING_CONSOLE && RT_USING_MSH */