pic.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125
  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 */