pic.c 24 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126
  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 = RT_NULL;
  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. void rt_pic_default_name(struct rt_pic *pic)
  73. {
  74. if (pic)
  75. {
  76. #if RT_NAME_MAX > 0
  77. rt_strncpy(pic->parent.name, "PIC", RT_NAME_MAX);
  78. #else
  79. pic->parent.name = "PIC";
  80. #endif
  81. }
  82. }
  83. struct rt_pic *rt_pic_dynamic_cast(void *ptr)
  84. {
  85. struct rt_pic *pic = RT_NULL, *tmp = RT_NULL;
  86. if (ptr)
  87. {
  88. struct rt_object *obj = ptr;
  89. if (obj->type == RT_Object_Class_Unknown)
  90. {
  91. tmp = (void *)obj;
  92. }
  93. else if (obj->type == RT_Object_Class_Device)
  94. {
  95. tmp = (void *)obj + sizeof(struct rt_device);
  96. }
  97. else
  98. {
  99. tmp = (void *)obj + sizeof(struct rt_object);
  100. }
  101. if (tmp && !rt_strcmp(tmp->parent.name, "PIC"))
  102. {
  103. pic = tmp;
  104. }
  105. }
  106. return pic;
  107. }
  108. rt_err_t rt_pic_linear_irq(struct rt_pic *pic, rt_size_t irq_nr)
  109. {
  110. rt_err_t err = RT_EOK;
  111. if (pic && pic->ops && pic->ops->name)
  112. {
  113. rt_ubase_t level = rt_spin_lock_irqsave(&_pic_lock);
  114. if (_pirq_hash_idx + irq_nr <= RT_ARRAY_SIZE(_pirq_hash))
  115. {
  116. rt_list_init(&pic->list);
  117. rt_pic_default_name(pic);
  118. pic->parent.type = RT_Object_Class_Unknown;
  119. pic->irq_start = _pirq_hash_idx;
  120. pic->irq_nr = irq_nr;
  121. pic->pirqs = &_pirq_hash[_pirq_hash_idx];
  122. _pirq_hash_idx += irq_nr;
  123. append_pic(pic);
  124. LOG_D("%s alloc irqs ranges [%d, %d]", pic->ops->name,
  125. pic->irq_start, pic->irq_start + pic->irq_nr);
  126. }
  127. else
  128. {
  129. LOG_E("%s alloc %d irqs is overflow", pic->ops->name, irq_nr);
  130. err = -RT_EEMPTY;
  131. }
  132. rt_spin_unlock_irqrestore(&_pic_lock, level);
  133. }
  134. else
  135. {
  136. err = -RT_EINVAL;
  137. }
  138. return err;
  139. }
  140. static void config_pirq(struct rt_pic *pic, struct rt_pic_irq *pirq, int irq, int hwirq)
  141. {
  142. rt_ubase_t level = rt_spin_lock_irqsave(&pirq->rw_lock);
  143. pirq->irq = irq;
  144. pirq->hwirq = hwirq;
  145. pirq->pic = pic;
  146. rt_list_init(&pirq->list);
  147. rt_list_init(&pirq->children_nodes);
  148. rt_list_init(&pirq->isr.list);
  149. rt_spin_unlock_irqrestore(&pirq->rw_lock, level);
  150. }
  151. int rt_pic_config_ipi(struct rt_pic *pic, int ipi_index, int hwirq)
  152. {
  153. int ipi = ipi_index;
  154. if (pic && ipi < RT_ARRAY_SIZE(_ipi_hash) && hwirq >= 0 && pic->ops->irq_send_ipi)
  155. {
  156. config_pirq(pic, &_pirq_hash[ipi], ipi, hwirq);
  157. LOG_D("%s config %s %d to hwirq %d", pic->ops->name, "ipi", ipi, hwirq);
  158. }
  159. else
  160. {
  161. ipi = -RT_EINVAL;
  162. }
  163. return ipi;
  164. }
  165. int rt_pic_config_irq(struct rt_pic *pic, int irq_index, int hwirq)
  166. {
  167. int irq;
  168. if (pic && hwirq >= 0)
  169. {
  170. irq = pic->irq_start + irq_index;
  171. if (irq >= 0 && irq < MAX_HANDLERS)
  172. {
  173. config_pirq(pic, &_pirq_hash[irq], irq, hwirq);
  174. LOG_D("%s config %s %d to hwirq %d", pic->ops->name, "irq", irq, hwirq);
  175. }
  176. else
  177. {
  178. irq = -RT_ERROR;
  179. }
  180. }
  181. else
  182. {
  183. irq = -RT_EINVAL;
  184. }
  185. return irq;
  186. }
  187. struct rt_pic_irq *rt_pic_find_ipi(struct rt_pic *pic, int ipi_index)
  188. {
  189. struct rt_pic_irq *pirq = &_pirq_hash[ipi_index];
  190. RT_ASSERT(ipi_index < RT_ARRAY_SIZE(_ipi_hash));
  191. RT_ASSERT(pirq->pic == pic);
  192. return pirq;
  193. }
  194. struct rt_pic_irq *rt_pic_find_pirq(struct rt_pic *pic, int irq)
  195. {
  196. if (pic && irq >= pic->irq_start && irq <= pic->irq_start + pic->irq_nr)
  197. {
  198. return &pic->pirqs[irq - pic->irq_start];
  199. }
  200. return RT_NULL;
  201. }
  202. rt_err_t rt_pic_cascade(struct rt_pic_irq *pirq, int parent_irq)
  203. {
  204. rt_err_t err = RT_EOK;
  205. if (pirq && !pirq->parent && parent_irq >= 0)
  206. {
  207. struct rt_pic_irq *parent;
  208. rt_spin_lock(&pirq->rw_lock);
  209. parent = irq2pirq(parent_irq);
  210. if (parent)
  211. {
  212. pirq->parent = parent;
  213. pirq->priority = parent->priority;
  214. rt_memcpy(&pirq->affinity, &parent->affinity, sizeof(pirq->affinity));
  215. }
  216. rt_spin_unlock(&pirq->rw_lock);
  217. if (parent && pirq->pic->ops->flags & RT_PIC_F_IRQ_ROUTING)
  218. {
  219. rt_spin_lock(&parent->rw_lock);
  220. rt_list_insert_before(&parent->children_nodes, &pirq->list);
  221. rt_spin_unlock(&parent->rw_lock);
  222. }
  223. }
  224. else
  225. {
  226. err = -RT_EINVAL;
  227. }
  228. return err;
  229. }
  230. rt_err_t rt_pic_uncascade(struct rt_pic_irq *pirq)
  231. {
  232. rt_err_t err = RT_EOK;
  233. if (pirq && pirq->parent)
  234. {
  235. struct rt_pic_irq *parent;
  236. rt_spin_lock(&pirq->rw_lock);
  237. parent = pirq->parent;
  238. pirq->parent = RT_NULL;
  239. rt_spin_unlock(&pirq->rw_lock);
  240. if (parent && pirq->pic->ops->flags & RT_PIC_F_IRQ_ROUTING)
  241. {
  242. rt_spin_lock(&parent->rw_lock);
  243. rt_list_remove(&pirq->list);
  244. rt_spin_unlock(&parent->rw_lock);
  245. }
  246. }
  247. else
  248. {
  249. err = -RT_EINVAL;
  250. }
  251. return err;
  252. }
  253. rt_err_t rt_pic_attach_irq(int irq, rt_isr_handler_t handler, void *uid, const char *name, int flags)
  254. {
  255. rt_err_t err = -RT_EINVAL;
  256. struct rt_pic_irq *pirq;
  257. if (handler && name && (pirq = irq2pirq(irq)))
  258. {
  259. struct rt_pic_isr *isr = RT_NULL;
  260. rt_ubase_t level = rt_spin_lock_irqsave(&pirq->rw_lock);
  261. err = RT_EOK;
  262. if (!pirq->isr.action.handler)
  263. {
  264. /* first attach */
  265. isr = &pirq->isr;
  266. rt_list_init(&isr->list);
  267. }
  268. else
  269. {
  270. rt_spin_unlock_irqrestore(&pirq->rw_lock, level);
  271. if ((isr = rt_malloc(sizeof(*isr))))
  272. {
  273. rt_list_init(&isr->list);
  274. level = rt_spin_lock_irqsave(&pirq->rw_lock);
  275. rt_list_insert_after(&pirq->isr.list, &isr->list);
  276. }
  277. else
  278. {
  279. LOG_E("No memory to save '%s' isr", name);
  280. err = -RT_ERROR;
  281. }
  282. }
  283. if (!err)
  284. {
  285. isr->flags = flags;
  286. isr->action.handler = handler;
  287. isr->action.param = uid;
  288. #ifdef RT_USING_INTERRUPT_INFO
  289. isr->action.counter = 0;
  290. rt_strncpy(isr->action.name, name, RT_NAME_MAX);
  291. #endif
  292. rt_spin_unlock_irqrestore(&pirq->rw_lock, level);
  293. }
  294. }
  295. return err;
  296. }
  297. rt_err_t rt_pic_detach_irq(int irq, void *uid)
  298. {
  299. rt_err_t err = -RT_EINVAL;
  300. struct rt_pic_irq *pirq = irq2pirq(irq);
  301. if (pirq)
  302. {
  303. rt_bool_t will_free = RT_FALSE;
  304. struct rt_pic_isr *isr = RT_NULL;
  305. rt_ubase_t level = rt_spin_lock_irqsave(&pirq->rw_lock);
  306. isr = &pirq->isr;
  307. if (isr->action.param == uid)
  308. {
  309. if (rt_list_isempty(&isr->list))
  310. {
  311. isr->action.handler = RT_NULL;
  312. isr->action.param = RT_NULL;
  313. }
  314. else
  315. {
  316. struct rt_pic_isr *next_isr = rt_list_entry(isr->list.next, struct rt_pic_isr, list);
  317. rt_list_remove(&next_isr->list);
  318. isr->action.handler = next_isr->action.handler;
  319. isr->action.param = next_isr->action.param;
  320. #ifdef RT_USING_INTERRUPT_INFO
  321. isr->action.counter = next_isr->action.counter;
  322. rt_strncpy(isr->action.name, next_isr->action.name, RT_NAME_MAX);
  323. #endif
  324. isr = next_isr;
  325. will_free = RT_TRUE;
  326. }
  327. err = RT_EOK;
  328. }
  329. else
  330. {
  331. rt_list_for_each_entry(isr, &pirq->isr.list, list)
  332. {
  333. if (isr->action.param == uid)
  334. {
  335. err = RT_EOK;
  336. will_free = RT_TRUE;
  337. rt_list_remove(&isr->list);
  338. break;
  339. }
  340. }
  341. }
  342. rt_spin_unlock_irqrestore(&pirq->rw_lock, level);
  343. if (will_free)
  344. {
  345. rt_free(isr);
  346. }
  347. }
  348. return err;
  349. }
  350. rt_err_t rt_pic_add_traps(rt_bool_t (*handler)(void *), void *data)
  351. {
  352. rt_err_t err = -RT_EINVAL;
  353. if (handler)
  354. {
  355. struct irq_traps *traps = rt_malloc(sizeof(*traps));
  356. if (traps)
  357. {
  358. rt_ubase_t level = rt_hw_interrupt_disable();
  359. rt_list_init(&traps->list);
  360. traps->data = data;
  361. traps->handler = handler;
  362. rt_list_insert_before(&_traps_nodes, &traps->list);
  363. err = RT_EOK;
  364. rt_hw_interrupt_enable(level);
  365. }
  366. else
  367. {
  368. LOG_E("No memory to save '%p' handler", handler);
  369. err = -RT_ENOMEM;
  370. }
  371. }
  372. return err;
  373. }
  374. rt_err_t rt_pic_do_traps(void)
  375. {
  376. rt_err_t err = -RT_ERROR;
  377. struct irq_traps *traps;
  378. rt_list_for_each_entry(traps, &_traps_nodes, list)
  379. {
  380. if (traps->handler(traps->data))
  381. {
  382. err = RT_EOK;
  383. break;
  384. }
  385. }
  386. return err;
  387. }
  388. rt_err_t rt_pic_handle_isr(struct rt_pic_irq *pirq)
  389. {
  390. rt_err_t err = -RT_EEMPTY;
  391. rt_list_t *handler_nodes;
  392. struct rt_irq_desc *action;
  393. RT_ASSERT(pirq != RT_NULL);
  394. RT_ASSERT(pirq->pic != RT_NULL);
  395. /* Corrected irq affinity */
  396. rt_bitmap_set_bit(pirq->affinity, rt_hw_cpu_id());
  397. handler_nodes = &pirq->isr.list;
  398. action = &pirq->isr.action;
  399. if (!rt_list_isempty(&pirq->children_nodes))
  400. {
  401. struct rt_pic_irq *child;
  402. rt_list_for_each_entry(child, &pirq->children_nodes, list)
  403. {
  404. rt_pic_irq_ack(child->irq);
  405. err = rt_pic_handle_isr(child);
  406. rt_pic_irq_eoi(child->irq);
  407. }
  408. }
  409. if (action->handler)
  410. {
  411. action->handler(pirq->irq, action->param);
  412. #ifdef RT_USING_INTERRUPT_INFO
  413. action->counter++;
  414. #endif
  415. if (!rt_list_isempty(handler_nodes))
  416. {
  417. struct rt_pic_isr *isr;
  418. rt_list_for_each_entry(isr, handler_nodes, list)
  419. {
  420. action = &isr->action;
  421. RT_ASSERT(action->handler != RT_NULL);
  422. action->handler(pirq->irq, action->param);
  423. #ifdef RT_USING_INTERRUPT_INFO
  424. action->counter++;
  425. #endif
  426. }
  427. }
  428. err = RT_EOK;
  429. }
  430. return err;
  431. }
  432. rt_weak rt_err_t rt_pic_user_extends(struct rt_pic *pic)
  433. {
  434. return -RT_ENOSYS;
  435. }
  436. rt_err_t rt_pic_irq_init(void)
  437. {
  438. rt_err_t err = RT_EOK;
  439. struct rt_pic *pic;
  440. rt_list_for_each_entry(pic, &_pic_nodes, list)
  441. {
  442. if (pic->ops->irq_init)
  443. {
  444. err = pic->ops->irq_init(pic);
  445. if (err)
  446. {
  447. LOG_E("PIC = %s init fail", pic->ops->name);
  448. break;
  449. }
  450. }
  451. }
  452. return err;
  453. }
  454. rt_err_t rt_pic_irq_finit(void)
  455. {
  456. rt_err_t err = RT_EOK;
  457. struct rt_pic *pic;
  458. rt_list_for_each_entry(pic, &_pic_nodes, list)
  459. {
  460. if (pic->ops->irq_finit)
  461. {
  462. err = pic->ops->irq_finit(pic);
  463. if (err)
  464. {
  465. LOG_E("PIC = %s finit fail", pic->ops->name);
  466. break;
  467. }
  468. }
  469. }
  470. return err;
  471. }
  472. void rt_pic_irq_enable(int irq)
  473. {
  474. struct rt_pic_irq *pirq = irq2pirq(irq);
  475. RT_ASSERT(pirq != RT_NULL);
  476. rt_hw_spin_lock(&pirq->rw_lock.lock);
  477. if (pirq->pic->ops->irq_enable)
  478. {
  479. pirq->pic->ops->irq_enable(pirq);
  480. }
  481. rt_hw_spin_unlock(&pirq->rw_lock.lock);
  482. }
  483. void rt_pic_irq_disable(int irq)
  484. {
  485. struct rt_pic_irq *pirq = irq2pirq(irq);
  486. RT_ASSERT(pirq != RT_NULL);
  487. rt_hw_spin_lock(&pirq->rw_lock.lock);
  488. if (pirq->pic->ops->irq_disable)
  489. {
  490. pirq->pic->ops->irq_disable(pirq);
  491. }
  492. rt_hw_spin_unlock(&pirq->rw_lock.lock);
  493. }
  494. void rt_pic_irq_ack(int irq)
  495. {
  496. struct rt_pic_irq *pirq = irq2pirq(irq);
  497. RT_ASSERT(pirq != RT_NULL);
  498. rt_hw_spin_lock(&pirq->rw_lock.lock);
  499. if (pirq->pic->ops->irq_ack)
  500. {
  501. pirq->pic->ops->irq_ack(pirq);
  502. }
  503. rt_hw_spin_unlock(&pirq->rw_lock.lock);
  504. }
  505. void rt_pic_irq_mask(int irq)
  506. {
  507. struct rt_pic_irq *pirq = irq2pirq(irq);
  508. RT_ASSERT(pirq != RT_NULL);
  509. rt_hw_spin_lock(&pirq->rw_lock.lock);
  510. if (pirq->pic->ops->irq_mask)
  511. {
  512. pirq->pic->ops->irq_mask(pirq);
  513. }
  514. rt_hw_spin_unlock(&pirq->rw_lock.lock);
  515. }
  516. void rt_pic_irq_unmask(int irq)
  517. {
  518. struct rt_pic_irq *pirq = irq2pirq(irq);
  519. RT_ASSERT(pirq != RT_NULL);
  520. rt_hw_spin_lock(&pirq->rw_lock.lock);
  521. if (pirq->pic->ops->irq_unmask)
  522. {
  523. pirq->pic->ops->irq_unmask(pirq);
  524. }
  525. rt_hw_spin_unlock(&pirq->rw_lock.lock);
  526. }
  527. void rt_pic_irq_eoi(int irq)
  528. {
  529. struct rt_pic_irq *pirq = irq2pirq(irq);
  530. RT_ASSERT(pirq != RT_NULL);
  531. rt_hw_spin_lock(&pirq->rw_lock.lock);
  532. if (pirq->pic->ops->irq_eoi)
  533. {
  534. pirq->pic->ops->irq_eoi(pirq);
  535. }
  536. rt_hw_spin_unlock(&pirq->rw_lock.lock);
  537. }
  538. rt_err_t rt_pic_irq_set_priority(int irq, rt_uint32_t priority)
  539. {
  540. rt_err_t err = -RT_EINVAL;
  541. struct rt_pic_irq *pirq = irq2pirq(irq);
  542. if (pirq)
  543. {
  544. rt_hw_spin_lock(&pirq->rw_lock.lock);
  545. if (pirq->pic->ops->irq_set_priority)
  546. {
  547. err = pirq->pic->ops->irq_set_priority(pirq, priority);
  548. if (!err)
  549. {
  550. pirq->priority = priority;
  551. }
  552. }
  553. else
  554. {
  555. err = -RT_ENOSYS;
  556. }
  557. rt_hw_spin_unlock(&pirq->rw_lock.lock);
  558. }
  559. return err;
  560. }
  561. rt_uint32_t rt_pic_irq_get_priority(int irq)
  562. {
  563. rt_uint32_t priority = RT_UINT32_MAX;
  564. struct rt_pic_irq *pirq = irq2pirq(irq);
  565. if (pirq)
  566. {
  567. rt_hw_spin_lock(&pirq->rw_lock.lock);
  568. priority = pirq->priority;
  569. rt_hw_spin_unlock(&pirq->rw_lock.lock);
  570. }
  571. return priority;
  572. }
  573. rt_err_t rt_pic_irq_set_affinity(int irq, rt_bitmap_t *affinity)
  574. {
  575. rt_err_t err = -RT_EINVAL;
  576. struct rt_pic_irq *pirq;
  577. if (affinity && (pirq = irq2pirq(irq)))
  578. {
  579. rt_hw_spin_lock(&pirq->rw_lock.lock);
  580. if (pirq->pic->ops->irq_set_affinity)
  581. {
  582. err = pirq->pic->ops->irq_set_affinity(pirq, affinity);
  583. if (!err)
  584. {
  585. rt_memcpy(pirq->affinity, affinity, sizeof(pirq->affinity));
  586. }
  587. }
  588. else
  589. {
  590. err = -RT_ENOSYS;
  591. }
  592. rt_hw_spin_unlock(&pirq->rw_lock.lock);
  593. }
  594. return err;
  595. }
  596. rt_err_t rt_pic_irq_get_affinity(int irq, rt_bitmap_t *out_affinity)
  597. {
  598. rt_err_t err = -RT_EINVAL;
  599. struct rt_pic_irq *pirq;
  600. if (out_affinity && (pirq = irq2pirq(irq)))
  601. {
  602. rt_hw_spin_lock(&pirq->rw_lock.lock);
  603. rt_memcpy(out_affinity, pirq->affinity, sizeof(pirq->affinity));
  604. err = RT_EOK;
  605. rt_hw_spin_unlock(&pirq->rw_lock.lock);
  606. }
  607. return err;
  608. }
  609. rt_err_t rt_pic_irq_set_triger_mode(int irq, rt_uint32_t mode)
  610. {
  611. rt_err_t err = -RT_EINVAL;
  612. struct rt_pic_irq *pirq;
  613. if ((~mode & RT_IRQ_MODE_MASK) && (pirq = irq2pirq(irq)))
  614. {
  615. rt_hw_spin_lock(&pirq->rw_lock.lock);
  616. if (pirq->pic->ops->irq_set_triger_mode)
  617. {
  618. err = pirq->pic->ops->irq_set_triger_mode(pirq, mode);
  619. if (!err)
  620. {
  621. pirq->mode = mode;
  622. }
  623. }
  624. else
  625. {
  626. err = -RT_ENOSYS;
  627. }
  628. rt_hw_spin_unlock(&pirq->rw_lock.lock);
  629. }
  630. return err;
  631. }
  632. rt_uint32_t rt_pic_irq_get_triger_mode(int irq)
  633. {
  634. rt_uint32_t mode = RT_UINT32_MAX;
  635. struct rt_pic_irq *pirq = irq2pirq(irq);
  636. if (pirq)
  637. {
  638. rt_hw_spin_lock(&pirq->rw_lock.lock);
  639. mode = pirq->mode;
  640. rt_hw_spin_unlock(&pirq->rw_lock.lock);
  641. }
  642. return mode;
  643. }
  644. void rt_pic_irq_send_ipi(int irq, rt_bitmap_t *cpumask)
  645. {
  646. struct rt_pic_irq *pirq;
  647. if (cpumask && (pirq = irq2pirq(irq)))
  648. {
  649. rt_hw_spin_lock(&pirq->rw_lock.lock);
  650. if (pirq->pic->ops->irq_send_ipi)
  651. {
  652. pirq->pic->ops->irq_send_ipi(pirq, cpumask);
  653. }
  654. rt_hw_spin_unlock(&pirq->rw_lock.lock);
  655. }
  656. }
  657. void rt_pic_irq_parent_enable(struct rt_pic_irq *pirq)
  658. {
  659. RT_ASSERT(pirq != RT_NULL);
  660. pirq = pirq->parent;
  661. if (pirq->pic->ops->irq_enable)
  662. {
  663. pirq->pic->ops->irq_enable(pirq);
  664. }
  665. }
  666. void rt_pic_irq_parent_disable(struct rt_pic_irq *pirq)
  667. {
  668. RT_ASSERT(pirq != RT_NULL);
  669. pirq = pirq->parent;
  670. if (pirq->pic->ops->irq_disable)
  671. {
  672. pirq->pic->ops->irq_disable(pirq);
  673. }
  674. }
  675. void rt_pic_irq_parent_ack(struct rt_pic_irq *pirq)
  676. {
  677. RT_ASSERT(pirq != RT_NULL);
  678. pirq = pirq->parent;
  679. if (pirq->pic->ops->irq_ack)
  680. {
  681. pirq->pic->ops->irq_ack(pirq);
  682. }
  683. }
  684. void rt_pic_irq_parent_mask(struct rt_pic_irq *pirq)
  685. {
  686. RT_ASSERT(pirq != RT_NULL);
  687. pirq = pirq->parent;
  688. if (pirq->pic->ops->irq_mask)
  689. {
  690. pirq->pic->ops->irq_mask(pirq);
  691. }
  692. }
  693. void rt_pic_irq_parent_unmask(struct rt_pic_irq *pirq)
  694. {
  695. RT_ASSERT(pirq != RT_NULL);
  696. pirq = pirq->parent;
  697. if (pirq->pic->ops->irq_unmask)
  698. {
  699. pirq->pic->ops->irq_unmask(pirq);
  700. }
  701. }
  702. void rt_pic_irq_parent_eoi(struct rt_pic_irq *pirq)
  703. {
  704. RT_ASSERT(pirq != RT_NULL);
  705. pirq = pirq->parent;
  706. if (pirq->pic->ops->irq_eoi)
  707. {
  708. pirq->pic->ops->irq_eoi(pirq);
  709. }
  710. }
  711. rt_err_t rt_pic_irq_parent_set_priority(struct rt_pic_irq *pirq, rt_uint32_t priority)
  712. {
  713. rt_err_t err = -RT_ENOSYS;
  714. RT_ASSERT(pirq != RT_NULL);
  715. pirq = pirq->parent;
  716. if (pirq->pic->ops->irq_set_priority)
  717. {
  718. if (!(err = pirq->pic->ops->irq_set_priority(pirq, priority)))
  719. {
  720. pirq->priority = priority;
  721. }
  722. }
  723. return err;
  724. }
  725. rt_err_t rt_pic_irq_parent_set_affinity(struct rt_pic_irq *pirq, rt_bitmap_t *affinity)
  726. {
  727. rt_err_t err = -RT_ENOSYS;
  728. RT_ASSERT(pirq != RT_NULL);
  729. pirq = pirq->parent;
  730. if (pirq->pic->ops->irq_set_affinity)
  731. {
  732. if (!(err = pirq->pic->ops->irq_set_affinity(pirq, affinity)))
  733. {
  734. rt_memcpy(pirq->affinity, affinity, sizeof(pirq->affinity));
  735. }
  736. }
  737. return err;
  738. }
  739. rt_err_t rt_pic_irq_parent_set_triger_mode(struct rt_pic_irq *pirq, rt_uint32_t mode)
  740. {
  741. rt_err_t err = -RT_ENOSYS;
  742. RT_ASSERT(pirq != RT_NULL);
  743. pirq = pirq->parent;
  744. if (pirq->pic->ops->irq_set_triger_mode)
  745. {
  746. if (!(err = pirq->pic->ops->irq_set_triger_mode(pirq, mode)))
  747. {
  748. pirq->mode = mode;
  749. }
  750. }
  751. return err;
  752. }
  753. #ifdef RT_USING_OFW
  754. RT_OFW_STUB_RANGE_EXPORT(pic, _pic_ofw_start, _pic_ofw_end);
  755. static rt_err_t ofw_pic_init(void)
  756. {
  757. struct rt_ofw_node *ic_np;
  758. rt_ofw_foreach_node_by_prop(ic_np, "interrupt-controller")
  759. {
  760. rt_ofw_stub_probe_range(ic_np, &_pic_ofw_start, &_pic_ofw_end);
  761. }
  762. return RT_EOK;
  763. }
  764. #else
  765. static rt_err_t ofw_pic_init(void)
  766. {
  767. return RT_EOK;
  768. }
  769. #endif /* !RT_USING_OFW */
  770. rt_err_t rt_pic_init(void)
  771. {
  772. rt_err_t err;
  773. LOG_D("init start");
  774. err = ofw_pic_init();
  775. LOG_D("init end");
  776. return err;
  777. }
  778. #if defined(RT_USING_CONSOLE) && defined(RT_USING_MSH)
  779. static int list_irq(int argc, char**argv)
  780. {
  781. rt_ubase_t level;
  782. rt_size_t irq_nr = 0;
  783. rt_bool_t dump_all = RT_FALSE;
  784. const char *const irq_modes[] =
  785. {
  786. [RT_IRQ_MODE_NONE] = "None",
  787. [RT_IRQ_MODE_EDGE_RISING] = "Edge-Rising",
  788. [RT_IRQ_MODE_EDGE_FALLING] = "Edge-Falling",
  789. [RT_IRQ_MODE_EDGE_BOTH] = "Edge-Both",
  790. [RT_IRQ_MODE_LEVEL_HIGH] = "Level-High",
  791. [RT_IRQ_MODE_LEVEL_LOW] = "Level-Low",
  792. };
  793. static char info[RT_CONSOLEBUF_SIZE];
  794. #ifdef RT_USING_SMP
  795. static char cpumask[RT_CPUS_NR + 1] = { [RT_CPUS_NR] = '\0' };
  796. #endif
  797. if (argc > 1)
  798. {
  799. if (!rt_strcmp(argv[1], "all"))
  800. {
  801. dump_all = RT_TRUE;
  802. }
  803. }
  804. level = rt_hw_interrupt_disable();
  805. rt_kprintf("%-*.s %-*.s %s %-*.s %-*.s %-*.s %-*.sUsers%s\n",
  806. 10, "IRQ",
  807. 10, "HW-IRQ",
  808. "MSI",
  809. _pic_name_max, "PIC",
  810. 12, "Mode",
  811. #ifdef RT_USING_SMP
  812. RT_CPUS_NR, "CPUs",
  813. #else
  814. 0, 0,
  815. #endif
  816. #ifdef RT_USING_INTERRUPT_INFO
  817. 11, "Count",
  818. ""
  819. #else
  820. 0, 0,
  821. "-Number"
  822. #endif
  823. );
  824. for (int i = 0; i < RT_ARRAY_SIZE(_pirq_hash); ++i)
  825. {
  826. struct rt_pic_irq *pirq = &_pirq_hash[i];
  827. if (!pirq->pic || !(dump_all || pirq->isr.action.handler))
  828. {
  829. continue;
  830. }
  831. rt_snprintf(info, sizeof(info), "%-10d %-10d %c %-*.s %-*.s ",
  832. pirq->irq,
  833. pirq->hwirq,
  834. pirq->msi_desc ? 'Y' : 'N',
  835. _pic_name_max, pirq->pic->ops->name,
  836. 12, irq_modes[pirq->mode]);
  837. #ifdef RT_USING_SMP
  838. for (int group = 0, id = 0; group < RT_ARRAY_SIZE(pirq->affinity); ++group)
  839. {
  840. rt_bitmap_t mask = pirq->affinity[group];
  841. for (int idx = 0; id < RT_CPUS_NR && idx < RT_BITMAP_BIT_LEN(1); ++idx, ++id)
  842. {
  843. cpumask[RT_ARRAY_SIZE(cpumask) - id - 2] = '0' + ((mask >> idx) & 1);
  844. }
  845. }
  846. #endif /* RT_USING_SMP */
  847. rt_kputs(info);
  848. #ifdef RT_USING_SMP
  849. rt_kputs(cpumask);
  850. #endif
  851. #ifdef RT_USING_INTERRUPT_INFO
  852. rt_kprintf(" %-10d ", pirq->isr.action.counter);
  853. rt_kputs(pirq->isr.action.name);
  854. rt_kputs("\n");
  855. if (!rt_list_isempty(&pirq->isr.list))
  856. {
  857. struct rt_pic_isr *repeat_isr;
  858. rt_list_for_each_entry(repeat_isr, &pirq->isr.list, list)
  859. {
  860. rt_kputs(info);
  861. #ifdef RT_USING_SMP
  862. rt_kputs(cpumask);
  863. #endif
  864. rt_kprintf("%-10d ", repeat_isr->action.counter);
  865. rt_kputs(repeat_isr->action.name);
  866. rt_kputs("\n");
  867. }
  868. }
  869. #else
  870. rt_kprintf(" %d\n", rt_list_len(&pirq->isr.list));
  871. #endif
  872. ++irq_nr;
  873. }
  874. rt_hw_interrupt_enable(level);
  875. rt_kprintf("%d IRQs found\n", irq_nr);
  876. return 0;
  877. }
  878. MSH_CMD_EXPORT(list_irq, dump using or args = all of irq information);
  879. #endif /* RT_USING_CONSOLE && RT_USING_MSH */