pic.c 24 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151
  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. 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 = RT_EOK;
  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. void rt_pic_irq_enable(int irq)
  433. {
  434. struct rt_pic_irq *pirq = irq2pirq(irq);
  435. RT_ASSERT(pirq != RT_NULL);
  436. rt_spin_lock(&pirq->rw_lock);
  437. if (pirq->pic->ops->irq_enable)
  438. {
  439. pirq->pic->ops->irq_enable(pirq);
  440. }
  441. rt_spin_unlock(&pirq->rw_lock);
  442. }
  443. void rt_pic_irq_disable(int irq)
  444. {
  445. struct rt_pic_irq *pirq = irq2pirq(irq);
  446. RT_ASSERT(pirq != RT_NULL);
  447. rt_spin_lock(&pirq->rw_lock);
  448. if (pirq->pic->ops->irq_disable)
  449. {
  450. pirq->pic->ops->irq_disable(pirq);
  451. }
  452. rt_spin_unlock(&pirq->rw_lock);
  453. }
  454. void rt_pic_irq_ack(int irq)
  455. {
  456. struct rt_pic_irq *pirq = irq2pirq(irq);
  457. RT_ASSERT(pirq != RT_NULL);
  458. rt_spin_lock(&pirq->rw_lock);
  459. if (pirq->pic->ops->irq_ack)
  460. {
  461. pirq->pic->ops->irq_ack(pirq);
  462. }
  463. rt_spin_unlock(&pirq->rw_lock);
  464. }
  465. void rt_pic_irq_mask(int irq)
  466. {
  467. struct rt_pic_irq *pirq = irq2pirq(irq);
  468. RT_ASSERT(pirq != RT_NULL);
  469. rt_spin_lock(&pirq->rw_lock);
  470. if (pirq->pic->ops->irq_mask)
  471. {
  472. pirq->pic->ops->irq_mask(pirq);
  473. }
  474. rt_spin_unlock(&pirq->rw_lock);
  475. }
  476. void rt_pic_irq_unmask(int irq)
  477. {
  478. struct rt_pic_irq *pirq = irq2pirq(irq);
  479. RT_ASSERT(pirq != RT_NULL);
  480. rt_spin_lock(&pirq->rw_lock);
  481. if (pirq->pic->ops->irq_unmask)
  482. {
  483. pirq->pic->ops->irq_unmask(pirq);
  484. }
  485. rt_spin_unlock(&pirq->rw_lock);
  486. }
  487. void rt_pic_irq_eoi(int irq)
  488. {
  489. struct rt_pic_irq *pirq = irq2pirq(irq);
  490. RT_ASSERT(pirq != RT_NULL);
  491. rt_spin_lock(&pirq->rw_lock);
  492. if (pirq->pic->ops->irq_eoi)
  493. {
  494. pirq->pic->ops->irq_eoi(pirq);
  495. }
  496. rt_spin_unlock(&pirq->rw_lock);
  497. }
  498. rt_err_t rt_pic_irq_set_priority(int irq, rt_uint32_t priority)
  499. {
  500. rt_err_t err = -RT_EINVAL;
  501. struct rt_pic_irq *pirq = irq2pirq(irq);
  502. if (pirq)
  503. {
  504. rt_spin_lock(&pirq->rw_lock);
  505. if (pirq->pic->ops->irq_set_priority)
  506. {
  507. err = pirq->pic->ops->irq_set_priority(pirq, priority);
  508. if (!err)
  509. {
  510. pirq->priority = priority;
  511. }
  512. }
  513. else
  514. {
  515. err = -RT_ENOSYS;
  516. }
  517. rt_spin_unlock(&pirq->rw_lock);
  518. }
  519. return err;
  520. }
  521. rt_uint32_t rt_pic_irq_get_priority(int irq)
  522. {
  523. rt_uint32_t priority = RT_UINT32_MAX;
  524. struct rt_pic_irq *pirq = irq2pirq(irq);
  525. if (pirq)
  526. {
  527. rt_spin_lock(&pirq->rw_lock);
  528. priority = pirq->priority;
  529. rt_spin_unlock(&pirq->rw_lock);
  530. }
  531. return priority;
  532. }
  533. rt_err_t rt_pic_irq_set_affinity(int irq, rt_bitmap_t *affinity)
  534. {
  535. rt_err_t err = -RT_EINVAL;
  536. struct rt_pic_irq *pirq;
  537. if (affinity && (pirq = irq2pirq(irq)))
  538. {
  539. rt_spin_lock(&pirq->rw_lock);
  540. if (pirq->pic->ops->irq_set_affinity)
  541. {
  542. err = pirq->pic->ops->irq_set_affinity(pirq, affinity);
  543. if (!err)
  544. {
  545. rt_memcpy(pirq->affinity, affinity, sizeof(pirq->affinity));
  546. }
  547. }
  548. else
  549. {
  550. err = -RT_ENOSYS;
  551. }
  552. rt_spin_unlock(&pirq->rw_lock);
  553. }
  554. return err;
  555. }
  556. rt_err_t rt_pic_irq_get_affinity(int irq, rt_bitmap_t *out_affinity)
  557. {
  558. rt_err_t err = -RT_EINVAL;
  559. struct rt_pic_irq *pirq;
  560. if (out_affinity && (pirq = irq2pirq(irq)))
  561. {
  562. rt_spin_lock(&pirq->rw_lock);
  563. rt_memcpy(out_affinity, pirq->affinity, sizeof(pirq->affinity));
  564. err = RT_EOK;
  565. rt_spin_unlock(&pirq->rw_lock);
  566. }
  567. return err;
  568. }
  569. rt_err_t rt_pic_irq_set_triger_mode(int irq, rt_uint32_t mode)
  570. {
  571. rt_err_t err = -RT_EINVAL;
  572. struct rt_pic_irq *pirq;
  573. if ((~mode & RT_IRQ_MODE_MASK) && (pirq = irq2pirq(irq)))
  574. {
  575. rt_spin_lock(&pirq->rw_lock);
  576. if (pirq->pic->ops->irq_set_triger_mode)
  577. {
  578. err = pirq->pic->ops->irq_set_triger_mode(pirq, mode);
  579. if (!err)
  580. {
  581. pirq->mode = mode;
  582. }
  583. }
  584. else
  585. {
  586. err = -RT_ENOSYS;
  587. }
  588. rt_spin_unlock(&pirq->rw_lock);
  589. }
  590. return err;
  591. }
  592. rt_uint32_t rt_pic_irq_get_triger_mode(int irq)
  593. {
  594. rt_uint32_t mode = RT_UINT32_MAX;
  595. struct rt_pic_irq *pirq = irq2pirq(irq);
  596. if (pirq)
  597. {
  598. rt_spin_lock(&pirq->rw_lock);
  599. mode = pirq->mode;
  600. rt_spin_unlock(&pirq->rw_lock);
  601. }
  602. return mode;
  603. }
  604. void rt_pic_irq_send_ipi(int irq, rt_bitmap_t *cpumask)
  605. {
  606. struct rt_pic_irq *pirq;
  607. if (cpumask && (pirq = irq2pirq(irq)))
  608. {
  609. rt_hw_spin_lock(&pirq->rw_lock.lock);
  610. if (pirq->pic->ops->irq_send_ipi)
  611. {
  612. pirq->pic->ops->irq_send_ipi(pirq, cpumask);
  613. }
  614. rt_hw_spin_unlock(&pirq->rw_lock.lock);
  615. }
  616. }
  617. #define _pic_push(stack, pirq, ppic) struct rt_pic *(stack) = (pirq)->pic; (pirq)->pic = ppic;
  618. #define _pic_pop(stack, pirq) (pirq)->pic = (stack)
  619. void rt_pic_irq_parent_enable(struct rt_pic *ppic, struct rt_pic_irq *pirq)
  620. {
  621. RT_ASSERT(ppic != RT_NULL);
  622. RT_ASSERT(pirq != RT_NULL);
  623. rt_spin_lock(&pirq->rw_lock);
  624. if (ppic->ops->irq_enable)
  625. {
  626. _pic_push(pic_stack, pirq, ppic);
  627. ppic->ops->irq_enable(pirq);
  628. _pic_pop(pic_stack, pirq);
  629. }
  630. rt_spin_unlock(&pirq->rw_lock);
  631. }
  632. void rt_pic_irq_parent_disable(struct rt_pic *ppic, struct rt_pic_irq *pirq)
  633. {
  634. RT_ASSERT(ppic != RT_NULL);
  635. RT_ASSERT(pirq != RT_NULL);
  636. rt_spin_lock(&pirq->rw_lock);
  637. if (ppic->ops->irq_disable)
  638. {
  639. _pic_push(pic_stack, pirq, ppic);
  640. ppic->ops->irq_disable(pirq);
  641. _pic_pop(pic_stack, pirq);
  642. }
  643. rt_spin_unlock(&pirq->rw_lock);
  644. }
  645. void rt_pic_irq_parent_ack(struct rt_pic *ppic, struct rt_pic_irq *pirq)
  646. {
  647. RT_ASSERT(ppic != RT_NULL);
  648. RT_ASSERT(pirq != RT_NULL);
  649. rt_spin_lock(&pirq->rw_lock);
  650. if (ppic->ops->irq_ack)
  651. {
  652. _pic_push(pic_stack, pirq, ppic);
  653. ppic->ops->irq_ack(pirq);
  654. _pic_pop(pic_stack, pirq);
  655. }
  656. rt_spin_unlock(&pirq->rw_lock);
  657. }
  658. void rt_pic_irq_parent_mask(struct rt_pic *ppic, struct rt_pic_irq *pirq)
  659. {
  660. RT_ASSERT(ppic != RT_NULL);
  661. RT_ASSERT(pirq != RT_NULL);
  662. rt_spin_lock(&pirq->rw_lock);
  663. if (ppic->ops->irq_mask)
  664. {
  665. _pic_push(pic_stack, pirq, ppic);
  666. ppic->ops->irq_mask(pirq);
  667. _pic_pop(pic_stack, pirq);
  668. }
  669. rt_spin_unlock(&pirq->rw_lock);
  670. }
  671. void rt_pic_irq_parent_unmask(struct rt_pic *ppic, struct rt_pic_irq *pirq)
  672. {
  673. RT_ASSERT(ppic != RT_NULL);
  674. RT_ASSERT(pirq != RT_NULL);
  675. rt_spin_lock(&pirq->rw_lock);
  676. if (ppic->ops->irq_unmask)
  677. {
  678. _pic_push(pic_stack, pirq, ppic);
  679. ppic->ops->irq_unmask(pirq);
  680. _pic_pop(pic_stack, pirq);
  681. }
  682. rt_spin_unlock(&pirq->rw_lock);
  683. }
  684. void rt_pic_irq_parent_eoi(struct rt_pic *ppic, struct rt_pic_irq *pirq)
  685. {
  686. RT_ASSERT(ppic != RT_NULL);
  687. RT_ASSERT(pirq != RT_NULL);
  688. rt_spin_lock(&pirq->rw_lock);
  689. if (ppic->ops->irq_eoi)
  690. {
  691. _pic_push(pic_stack, pirq, ppic);
  692. ppic->ops->irq_eoi(pirq);
  693. _pic_pop(pic_stack, pirq);
  694. }
  695. rt_spin_unlock(&pirq->rw_lock);
  696. }
  697. rt_err_t rt_pic_irq_parent_set_priority(struct rt_pic *ppic, struct rt_pic_irq *pirq, rt_uint32_t priority)
  698. {
  699. rt_err_t err = -RT_ENOSYS;
  700. RT_ASSERT(ppic != RT_NULL);
  701. RT_ASSERT(pirq != RT_NULL);
  702. rt_spin_lock(&pirq->rw_lock);
  703. if (ppic->ops->irq_set_priority)
  704. {
  705. _pic_push(pic_stack, pirq, ppic);
  706. if (!(err = ppic->ops->irq_set_priority(pirq, priority)))
  707. {
  708. pirq->priority = priority;
  709. }
  710. _pic_pop(pic_stack, pirq);
  711. }
  712. rt_spin_unlock(&pirq->rw_lock);
  713. return err;
  714. }
  715. rt_err_t rt_pic_irq_parent_set_affinity(struct rt_pic *ppic, struct rt_pic_irq *pirq, rt_bitmap_t *affinity)
  716. {
  717. rt_err_t err = -RT_ENOSYS;
  718. RT_ASSERT(ppic != RT_NULL);
  719. RT_ASSERT(pirq != RT_NULL);
  720. rt_spin_lock(&pirq->rw_lock);
  721. if (ppic->ops->irq_set_affinity)
  722. {
  723. _pic_push(pic_stack, pirq, ppic);
  724. if (!(err = ppic->ops->irq_set_affinity(pirq, affinity)))
  725. {
  726. rt_memcpy(pirq->affinity, affinity, sizeof(pirq->affinity));
  727. }
  728. _pic_pop(pic_stack, pirq);
  729. }
  730. rt_spin_unlock(&pirq->rw_lock);
  731. return err;
  732. }
  733. rt_err_t rt_pic_irq_parent_set_triger_mode(struct rt_pic *ppic, struct rt_pic_irq *pirq, rt_uint32_t mode)
  734. {
  735. rt_err_t err = -RT_ENOSYS;
  736. RT_ASSERT(ppic != RT_NULL);
  737. RT_ASSERT(pirq != RT_NULL);
  738. rt_spin_lock(&pirq->rw_lock);
  739. if (ppic->ops->irq_set_triger_mode)
  740. {
  741. _pic_push(pic_stack, pirq, ppic);
  742. if (!(err = ppic->ops->irq_set_triger_mode(pirq, mode)))
  743. {
  744. pirq->mode = mode;
  745. }
  746. _pic_pop(pic_stack, pirq);
  747. }
  748. rt_spin_unlock(&pirq->rw_lock);
  749. return err;
  750. }
  751. #undef _pic_push
  752. #undef _pic_pop
  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 < 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 */