dm.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600
  1. /*
  2. * Copyright (c) 2006-2024, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2023-04-20 ErikChan the first version
  9. */
  10. #include <rtthread.h>
  11. #ifdef RT_USING_OFW
  12. #include <drivers/ofw_io.h>
  13. #include <drivers/ofw_irq.h>
  14. #endif
  15. #include <drivers/core/dm.h>
  16. #ifdef RT_USING_SMP
  17. static int rti_secondary_cpu_start(void)
  18. {
  19. return 0;
  20. }
  21. INIT_EXPORT(rti_secondary_cpu_start, "6.end");
  22. static int rti_secondary_cpu_end(void)
  23. {
  24. return 0;
  25. }
  26. INIT_EXPORT(rti_secondary_cpu_end, "7.end");
  27. void rt_dm_secondary_cpu_init(void)
  28. {
  29. #ifdef RT_DEBUGING_AUTO_INIT
  30. int result;
  31. const struct rt_init_desc *desc;
  32. rt_kprintf("do secondary cpu initialization.\n");
  33. for (desc = &__rt_init_desc_rti_secondary_cpu_start; desc < &__rt_init_desc_rti_secondary_cpu_end; ++desc)
  34. {
  35. rt_kprintf("initialize %s", desc->fn_name);
  36. result = desc->fn();
  37. rt_kprintf(":%d done\n", result);
  38. }
  39. #else
  40. volatile const init_fn_t *fn_ptr;
  41. for (fn_ptr = &__rt_init_rti_secondary_cpu_start; fn_ptr < &__rt_init_rti_secondary_cpu_end; ++fn_ptr)
  42. {
  43. (*fn_ptr)();
  44. }
  45. #endif /* RT_DEBUGING_AUTO_INIT */
  46. }
  47. #endif /* RT_USING_SMP */
  48. /**
  49. * @brief This function will alloc an id in an IDA object
  50. *
  51. * @param ida is the IDA object
  52. *
  53. * @return the id or -RT_EEMPTY
  54. */
  55. int rt_dm_ida_alloc(struct rt_dm_ida *ida)
  56. {
  57. int id;
  58. RT_ASSERT(ida != RT_NULL);
  59. rt_spin_lock(&ida->lock);
  60. id = rt_bitmap_next_clear_bit(ida->map, 0, RT_DM_IDA_NUM);
  61. if (id != RT_DM_IDA_NUM)
  62. {
  63. rt_bitmap_set_bit(ida->map, id);
  64. }
  65. rt_spin_unlock(&ida->lock);
  66. if (id != RT_DM_IDA_NUM)
  67. {
  68. return id;
  69. }
  70. return -RT_EEMPTY;
  71. }
  72. /**
  73. * @brief This function will take (force) an id in an IDA object
  74. *
  75. * @param ida is the IDA object
  76. *
  77. * @param id is the id that want to take
  78. *
  79. * @return the result of taking
  80. */
  81. rt_bool_t rt_dm_ida_take(struct rt_dm_ida *ida, int id)
  82. {
  83. RT_ASSERT(ida != RT_NULL);
  84. RT_ASSERT(id >= 0);
  85. rt_spin_lock(&ida->lock);
  86. if (!rt_bitmap_test_bit(ida->map, id))
  87. {
  88. rt_bitmap_set_bit(ida->map, id);
  89. }
  90. else
  91. {
  92. id = RT_DM_IDA_NUM;
  93. }
  94. rt_spin_unlock(&ida->lock);
  95. return id != RT_DM_IDA_NUM;
  96. }
  97. /**
  98. * @brief This function will release an id in an IDA object
  99. *
  100. * @param ida is the IDA object
  101. *
  102. * @param id is the id of IDA object
  103. */
  104. void rt_dm_ida_free(struct rt_dm_ida *ida, int id)
  105. {
  106. RT_ASSERT(ida != RT_NULL);
  107. RT_ASSERT(id >= 0);
  108. rt_spin_lock(&ida->lock);
  109. rt_bitmap_clear_bit(ida->map, id);
  110. rt_spin_unlock(&ida->lock);
  111. }
  112. /**
  113. * @brief This function will return the specified master id and device id of device.
  114. *
  115. * @param master_id is the master id (0, 255] of device
  116. *
  117. * @param device_id is the device id [-1, 255] of device, when device_id is -1,
  118. * the function will end when find the first device.
  119. *
  120. * @return the device object or RT_NULL
  121. */
  122. rt_device_t rt_dm_device_find(int master_id, int device_id)
  123. {
  124. struct rt_device *dev, *ret_dev = RT_NULL;
  125. struct rt_object_information *information = RT_NULL;
  126. if (master_id <= 0 || device_id > 255)
  127. {
  128. return RT_NULL;
  129. }
  130. information = rt_object_get_information(RT_Object_Class_Device);
  131. /* parameter check */
  132. if (!information)
  133. {
  134. return RT_NULL;
  135. }
  136. /* which is invoke in interrupt status */
  137. RT_DEBUG_NOT_IN_INTERRUPT;
  138. /* enter critical */
  139. rt_enter_critical();
  140. /* try to find object */
  141. rt_list_for_each_entry(dev, &information->object_list, parent.list)
  142. {
  143. if (master_id == dev->master_id &&
  144. (device_id == -1 || device_id == dev->device_id))
  145. {
  146. ret_dev = dev;
  147. break;
  148. }
  149. }
  150. /* leave critical */
  151. rt_exit_critical();
  152. return ret_dev;
  153. }
  154. struct prefix_track
  155. {
  156. rt_list_t list;
  157. int uid;
  158. const char *prefix;
  159. };
  160. static RT_DEFINE_SPINLOCK(_prefix_nodes_lock);
  161. static rt_list_t _prefix_nodes = RT_LIST_OBJECT_INIT(_prefix_nodes);
  162. int rt_dm_dev_set_name_auto(rt_device_t dev, const char *prefix)
  163. {
  164. int uid = -1;
  165. struct prefix_track *pt = RT_NULL;
  166. RT_ASSERT(dev != RT_NULL);
  167. RT_ASSERT(prefix != RT_NULL);
  168. RT_DEBUG_NOT_IN_INTERRUPT;
  169. rt_spin_lock(&_prefix_nodes_lock);
  170. rt_list_for_each_entry(pt, &_prefix_nodes, list)
  171. {
  172. /* caller always input constants string, check ptr is faster */
  173. if (pt->prefix == prefix || !rt_strcmp(pt->prefix, prefix))
  174. {
  175. uid = ++pt->uid;
  176. break;
  177. }
  178. }
  179. rt_spin_unlock(&_prefix_nodes_lock);
  180. if (uid < 0)
  181. {
  182. pt = rt_malloc(sizeof(*pt));
  183. if (!pt)
  184. {
  185. return -RT_ENOMEM;
  186. }
  187. rt_list_init(&pt->list);
  188. pt->uid = uid = 0;
  189. pt->prefix = prefix;
  190. rt_spin_lock(&_prefix_nodes_lock);
  191. rt_list_insert_before(&_prefix_nodes, &pt->list);
  192. rt_spin_unlock(&_prefix_nodes_lock);
  193. }
  194. return rt_dm_dev_set_name(dev, "%s%u", prefix, uid);
  195. }
  196. int rt_dm_dev_get_name_id(rt_device_t dev)
  197. {
  198. int id = 0, len;
  199. const char *name;
  200. RT_ASSERT(dev != RT_NULL);
  201. name = rt_dm_dev_get_name(dev);
  202. len = rt_strlen(name) - 1;
  203. name += len;
  204. while (len --> 0)
  205. {
  206. if (*name < '0' || *name > '9')
  207. {
  208. while (*(++name))
  209. {
  210. id *= 10;
  211. id += *name - '0';
  212. }
  213. break;
  214. }
  215. --name;
  216. }
  217. return id;
  218. }
  219. int rt_dm_dev_set_name(rt_device_t dev, const char *format, ...)
  220. {
  221. int n;
  222. va_list arg_ptr;
  223. RT_ASSERT(dev != RT_NULL);
  224. RT_ASSERT(format != RT_NULL);
  225. va_start(arg_ptr, format);
  226. n = rt_vsnprintf(dev->parent.name, RT_NAME_MAX, format, arg_ptr);
  227. va_end(arg_ptr);
  228. return n;
  229. }
  230. const char *rt_dm_dev_get_name(rt_device_t dev)
  231. {
  232. RT_ASSERT(dev != RT_NULL);
  233. return dev->parent.name;
  234. }
  235. #ifdef RT_USING_OFW
  236. #define ofw_api_call(name, ...) rt_ofw_##name(__VA_ARGS__)
  237. #define ofw_api_call_ptr(name, ...) ofw_api_call(name, __VA_ARGS__)
  238. #else
  239. #define ofw_api_call(name, ...) (-RT_ENOSYS)
  240. #define ofw_api_call_ptr(name, ...) RT_NULL
  241. #endif
  242. int rt_dm_dev_get_address_count(rt_device_t dev)
  243. {
  244. RT_ASSERT(dev != RT_NULL);
  245. #ifdef RT_USING_OFW
  246. if (dev->ofw_node)
  247. {
  248. return ofw_api_call(get_address_count, dev->ofw_node);
  249. }
  250. #endif
  251. return -RT_ENOSYS;
  252. }
  253. rt_err_t rt_dm_dev_get_address(rt_device_t dev, int index,
  254. rt_uint64_t *out_address, rt_uint64_t *out_size)
  255. {
  256. RT_ASSERT(dev != RT_NULL);
  257. #ifdef RT_USING_OFW
  258. if (dev->ofw_node)
  259. {
  260. return ofw_api_call(get_address, dev->ofw_node, index,
  261. out_address, out_size);
  262. }
  263. #endif
  264. return -RT_ENOSYS;
  265. }
  266. rt_err_t rt_dm_dev_get_address_by_name(rt_device_t dev, const char *name,
  267. rt_uint64_t *out_address, rt_uint64_t *out_size)
  268. {
  269. RT_ASSERT(dev != RT_NULL);
  270. #ifdef RT_USING_OFW
  271. if (dev->ofw_node)
  272. {
  273. return ofw_api_call(get_address_by_name, dev->ofw_node, name,
  274. out_address, out_size);
  275. }
  276. #endif
  277. return -RT_ENOSYS;
  278. }
  279. int rt_dm_dev_get_address_array(rt_device_t dev, int nr, rt_uint64_t *out_regs)
  280. {
  281. RT_ASSERT(dev != RT_NULL);
  282. #ifdef RT_USING_OFW
  283. if (dev->ofw_node)
  284. {
  285. return ofw_api_call(get_address_array, dev->ofw_node, nr, out_regs);
  286. }
  287. #endif
  288. return -RT_ENOSYS;
  289. }
  290. void *rt_dm_dev_iomap(rt_device_t dev, int index)
  291. {
  292. RT_ASSERT(dev != RT_NULL);
  293. #ifdef RT_USING_OFW
  294. if (dev->ofw_node)
  295. {
  296. return ofw_api_call_ptr(iomap, dev->ofw_node, index);
  297. }
  298. #endif
  299. return RT_NULL;
  300. }
  301. void *rt_dm_dev_iomap_by_name(rt_device_t dev, const char *name)
  302. {
  303. RT_ASSERT(dev != RT_NULL);
  304. #ifdef RT_USING_OFW
  305. if (dev->ofw_node)
  306. {
  307. return ofw_api_call_ptr(iomap_by_name, dev->ofw_node, name);
  308. }
  309. #endif
  310. return RT_NULL;
  311. }
  312. int rt_dm_dev_get_irq_count(rt_device_t dev)
  313. {
  314. RT_ASSERT(dev != RT_NULL);
  315. #if defined(RT_USING_OFW) && defined(RT_USING_PIC)
  316. if (dev->ofw_node)
  317. {
  318. return ofw_api_call(get_irq_count, dev->ofw_node);
  319. }
  320. #endif
  321. return -RT_ENOSYS;
  322. }
  323. int rt_dm_dev_get_irq(rt_device_t dev, int index)
  324. {
  325. RT_ASSERT(dev != RT_NULL);
  326. #if defined(RT_USING_OFW) && defined(RT_USING_PIC)
  327. if (dev->ofw_node)
  328. {
  329. return ofw_api_call(get_irq, dev->ofw_node, index);
  330. }
  331. #endif
  332. return -RT_ENOSYS;
  333. }
  334. int rt_dm_dev_get_irq_by_name(rt_device_t dev, const char *name)
  335. {
  336. RT_ASSERT(dev != RT_NULL);
  337. #if defined(RT_USING_OFW) && defined(RT_USING_PIC)
  338. if (dev->ofw_node)
  339. {
  340. return ofw_api_call(get_irq_by_name, dev->ofw_node, name);
  341. }
  342. #endif
  343. return -RT_ENOSYS;
  344. }
  345. void rt_dm_dev_bind_fwdata(rt_device_t dev, void *fw_np, void *data)
  346. {
  347. RT_ASSERT(dev != RT_NULL);
  348. #ifdef RT_USING_OFW
  349. if (!dev->ofw_node && fw_np)
  350. {
  351. dev->ofw_node = fw_np;
  352. rt_ofw_data(fw_np) = data;
  353. }
  354. if (dev->ofw_node == RT_NULL)
  355. {
  356. rt_kprintf("[%s:%s] line=%d ofw_node is NULL\r\n", __FILE__, __func__, __LINE__);
  357. return;
  358. }
  359. rt_ofw_data(dev->ofw_node) = data;
  360. #endif
  361. }
  362. void rt_dm_dev_unbind_fwdata(rt_device_t dev, void *fw_np)
  363. {
  364. RT_ASSERT(dev!= RT_NULL);
  365. #ifdef RT_USING_OFW
  366. void *dev_fw_np = RT_NULL;
  367. if (!dev->ofw_node && fw_np)
  368. {
  369. dev_fw_np = fw_np;
  370. rt_ofw_data(fw_np) = RT_NULL;
  371. }
  372. if (dev_fw_np == RT_NULL)
  373. {
  374. rt_kprintf("[%s:%s] line=%d dev_fw_np is NULL\r\n", __FILE__, __func__, __LINE__);
  375. return;
  376. }
  377. rt_ofw_data(dev_fw_np) = RT_NULL;
  378. #endif
  379. }
  380. int rt_dm_dev_prop_read_u8_array_index(rt_device_t dev, const char *propname,
  381. int index, int nr, rt_uint8_t *out_values)
  382. {
  383. RT_ASSERT(dev != RT_NULL);
  384. #ifdef RT_UISNG_OFW
  385. if (dev->ofw_node)
  386. {
  387. return ofw_api_call(prop_read_u8_array_index, dev->ofw_node, propname,
  388. index, nr, out_value);
  389. }
  390. #endif
  391. return -RT_ENOSYS;
  392. }
  393. int rt_dm_dev_prop_read_u16_array_index(rt_device_t dev, const char *propname,
  394. int index, int nr, rt_uint16_t *out_values)
  395. {
  396. RT_ASSERT(dev != RT_NULL);
  397. #ifdef RT_USING_OFW
  398. if (dev->ofw_node)
  399. {
  400. return ofw_api_call(prop_read_u16_array_index, dev->ofw_node, propname,
  401. index, nr, out_values);
  402. }
  403. #endif
  404. return -RT_ENOSYS;
  405. }
  406. int rt_dm_dev_prop_read_u32_array_index(rt_device_t dev, const char *propname,
  407. int index, int nr, rt_uint32_t *out_values)
  408. {
  409. RT_ASSERT(dev != RT_NULL);
  410. #ifdef RT_USING_OFW
  411. if (dev->ofw_node)
  412. {
  413. return ofw_api_call(prop_read_u32_array_index, dev->ofw_node, propname,
  414. index, nr, out_values);
  415. }
  416. #endif
  417. return -RT_ENOSYS;
  418. }
  419. int rt_dm_dev_prop_read_u64_array_index(rt_device_t dev, const char *propname,
  420. int index, int nr, rt_uint64_t *out_values)
  421. {
  422. RT_ASSERT(dev != RT_NULL);
  423. #ifdef RT_USING_OFW
  424. if (dev->ofw_node)
  425. {
  426. return ofw_api_call(prop_read_u64_array_index, dev->ofw_node, propname,
  427. index, nr, out_values);
  428. }
  429. #endif
  430. return -RT_ENOSYS;
  431. }
  432. int rt_dm_dev_prop_read_string_array_index(rt_device_t dev, const char *propname,
  433. int index, int nr, const char **out_strings)
  434. {
  435. RT_ASSERT(dev != RT_NULL);
  436. #ifdef RT_USING_OFW
  437. if (dev->ofw_node)
  438. {
  439. return ofw_api_call(prop_read_string_array_index, dev->ofw_node, propname,
  440. index, nr, out_strings);
  441. }
  442. #endif
  443. return -RT_ENOSYS;
  444. }
  445. int rt_dm_dev_prop_count_of_size(rt_device_t dev, const char *propname, int size)
  446. {
  447. RT_ASSERT(dev != RT_NULL);
  448. #ifdef RT_USING_OFW
  449. if (dev->ofw_node)
  450. {
  451. return ofw_api_call(prop_count_of_size, dev->ofw_node, propname, size);
  452. }
  453. #endif
  454. return -RT_ENOSYS;
  455. }
  456. int rt_dm_dev_prop_index_of_string(rt_device_t dev, const char *propname, const char *string)
  457. {
  458. RT_ASSERT(dev != RT_NULL);
  459. #ifdef RT_USING_OFW
  460. if (dev->ofw_node)
  461. {
  462. return ofw_api_call(prop_index_of_string, dev->ofw_node, propname, string);
  463. }
  464. #endif
  465. return -RT_ENOSYS;
  466. }
  467. rt_bool_t rt_dm_dev_prop_read_bool(rt_device_t dev, const char *propname)
  468. {
  469. RT_ASSERT(dev != RT_NULL);
  470. #ifdef RT_USING_OFW
  471. if (dev->ofw_node)
  472. {
  473. return ofw_api_call(prop_read_bool, dev->ofw_node, propname);
  474. }
  475. #endif
  476. return RT_FALSE;
  477. }