pic.c 25 KB

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