dm.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  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. struct prefix_track
  49. {
  50. rt_list_t list;
  51. int uid;
  52. const char *prefix;
  53. };
  54. static struct rt_spinlock _prefix_nodes_lock = { 0 };
  55. static rt_list_t _prefix_nodes = RT_LIST_OBJECT_INIT(_prefix_nodes);
  56. int rt_dm_dev_set_name_auto(rt_device_t dev, const char *prefix)
  57. {
  58. int uid = -1;
  59. struct prefix_track *pt = RT_NULL;
  60. RT_ASSERT(dev != RT_NULL);
  61. RT_ASSERT(prefix != RT_NULL);
  62. RT_DEBUG_NOT_IN_INTERRUPT;
  63. rt_spin_lock(&_prefix_nodes_lock);
  64. rt_list_for_each_entry(pt, &_prefix_nodes, list)
  65. {
  66. /* caller always input constants string, check ptr is faster */
  67. if (pt->prefix == prefix || !rt_strcmp(pt->prefix, prefix))
  68. {
  69. uid = ++pt->uid;
  70. break;
  71. }
  72. }
  73. rt_spin_unlock(&_prefix_nodes_lock);
  74. if (uid < 0)
  75. {
  76. pt = rt_malloc(sizeof(*pt));
  77. if (!pt)
  78. {
  79. return -RT_ENOMEM;
  80. }
  81. rt_list_init(&pt->list);
  82. pt->uid = uid = 0;
  83. pt->prefix = prefix;
  84. rt_spin_lock(&_prefix_nodes_lock);
  85. rt_list_insert_before(&_prefix_nodes, &pt->list);
  86. rt_spin_unlock(&_prefix_nodes_lock);
  87. }
  88. return rt_dm_dev_set_name(dev, "%s%u", prefix, uid);
  89. }
  90. int rt_dm_dev_get_name_id(rt_device_t dev)
  91. {
  92. int id = 0, len;
  93. const char *name;
  94. RT_ASSERT(dev != RT_NULL);
  95. name = rt_dm_dev_get_name(dev);
  96. len = rt_strlen(name) - 1;
  97. name += len;
  98. while (len --> 0)
  99. {
  100. if (*name < '0' || *name > '9')
  101. {
  102. while (*(++name))
  103. {
  104. id *= 10;
  105. id += *name - '0';
  106. }
  107. break;
  108. }
  109. --name;
  110. }
  111. return id;
  112. }
  113. int rt_dm_dev_set_name(rt_device_t dev, const char *format, ...)
  114. {
  115. int n;
  116. va_list arg_ptr;
  117. RT_ASSERT(dev != RT_NULL);
  118. RT_ASSERT(format != RT_NULL);
  119. va_start(arg_ptr, format);
  120. n = rt_vsnprintf(dev->parent.name, RT_NAME_MAX, format, arg_ptr);
  121. va_end(arg_ptr);
  122. return n;
  123. }
  124. const char *rt_dm_dev_get_name(rt_device_t dev)
  125. {
  126. RT_ASSERT(dev != RT_NULL);
  127. return dev->parent.name;
  128. }
  129. #ifdef RT_USING_OFW
  130. #define ofw_api_call(name, ...) rt_ofw_##name(__VA_ARGS__)
  131. #define ofw_api_call_ptr(name, ...) ofw_api_call(name, __VA_ARGS__)
  132. #else
  133. #define ofw_api_call(name, ...) (-RT_ENOSYS)
  134. #define ofw_api_call_ptr(name, ...) RT_NULL
  135. #endif
  136. int rt_dm_dev_get_address_count(rt_device_t dev)
  137. {
  138. RT_ASSERT(dev != RT_NULL);
  139. #ifdef RT_USING_OFW
  140. if (dev->ofw_node)
  141. {
  142. return ofw_api_call(get_address_count, dev->ofw_node);
  143. }
  144. #endif
  145. return -RT_ENOSYS;
  146. }
  147. rt_err_t rt_dm_dev_get_address(rt_device_t dev, int index,
  148. rt_uint64_t *out_address, rt_uint64_t *out_size)
  149. {
  150. RT_ASSERT(dev != RT_NULL);
  151. #ifdef RT_USING_OFW
  152. if (dev->ofw_node)
  153. {
  154. return ofw_api_call(get_address, dev->ofw_node, index,
  155. out_address, out_size);
  156. }
  157. #endif
  158. return -RT_ENOSYS;
  159. }
  160. rt_err_t rt_dm_dev_get_address_by_name(rt_device_t dev, const char *name,
  161. rt_uint64_t *out_address, rt_uint64_t *out_size)
  162. {
  163. RT_ASSERT(dev != RT_NULL);
  164. #ifdef RT_USING_OFW
  165. if (dev->ofw_node)
  166. {
  167. return ofw_api_call(get_address_by_name, dev->ofw_node, name,
  168. out_address, out_size);
  169. }
  170. #endif
  171. return -RT_ENOSYS;
  172. }
  173. int rt_dm_dev_get_address_array(rt_device_t dev, int nr, rt_uint64_t *out_regs)
  174. {
  175. RT_ASSERT(dev != RT_NULL);
  176. #ifdef RT_USING_OFW
  177. if (dev->ofw_node)
  178. {
  179. return ofw_api_call(get_address_array, dev->ofw_node, nr, out_regs);
  180. }
  181. #endif
  182. return -RT_ENOSYS;
  183. }
  184. void *rt_dm_dev_iomap(rt_device_t dev, int index)
  185. {
  186. RT_ASSERT(dev != RT_NULL);
  187. #ifdef RT_USING_OFW
  188. if (dev->ofw_node)
  189. {
  190. return ofw_api_call_ptr(iomap, dev->ofw_node, index);
  191. }
  192. #endif
  193. return RT_NULL;
  194. }
  195. void *rt_dm_dev_iomap_by_name(rt_device_t dev, const char *name)
  196. {
  197. RT_ASSERT(dev != RT_NULL);
  198. #ifdef RT_USING_OFW
  199. if (dev->ofw_node)
  200. {
  201. return ofw_api_call_ptr(iomap_by_name, dev->ofw_node, name);
  202. }
  203. #endif
  204. return RT_NULL;
  205. }
  206. int rt_dm_dev_get_irq_count(rt_device_t dev)
  207. {
  208. RT_ASSERT(dev != RT_NULL);
  209. #if defined(RT_USING_OFW) && defined(RT_USING_PIC)
  210. if (dev->ofw_node)
  211. {
  212. return ofw_api_call(get_irq_count, dev->ofw_node);
  213. }
  214. #endif
  215. return -RT_ENOSYS;
  216. }
  217. int rt_dm_dev_get_irq(rt_device_t dev, int index)
  218. {
  219. RT_ASSERT(dev != RT_NULL);
  220. #if defined(RT_USING_OFW) && defined(RT_USING_PIC)
  221. if (dev->ofw_node)
  222. {
  223. return ofw_api_call(get_irq, dev->ofw_node, index);
  224. }
  225. #endif
  226. return -RT_ENOSYS;
  227. }
  228. int rt_dm_dev_get_irq_by_name(rt_device_t dev, const char *name)
  229. {
  230. RT_ASSERT(dev != RT_NULL);
  231. #if defined(RT_USING_OFW) && defined(RT_USING_PIC)
  232. if (dev->ofw_node)
  233. {
  234. return ofw_api_call(get_irq_by_name, dev->ofw_node, name);
  235. }
  236. #endif
  237. return -RT_ENOSYS;
  238. }
  239. void rt_dm_dev_bind_fwdata(rt_device_t dev, void *fw_np, void *data)
  240. {
  241. RT_ASSERT(dev != RT_NULL);
  242. #ifdef RT_USING_OFW
  243. if (!dev->ofw_node && fw_np)
  244. {
  245. dev->ofw_node = fw_np;
  246. rt_ofw_data(fw_np) = data;
  247. }
  248. if (dev->ofw_node == RT_NULL)
  249. {
  250. rt_kprintf("[%s:%s] line=%d ofw_node is NULL\r\n", __FILE__, __func__, __LINE__);
  251. return;
  252. }
  253. rt_ofw_data(dev->ofw_node) = data;
  254. #endif
  255. }
  256. void rt_dm_dev_unbind_fwdata(rt_device_t dev, void *fw_np)
  257. {
  258. RT_ASSERT(dev!= RT_NULL);
  259. #ifdef RT_USING_OFW
  260. void *dev_fw_np = RT_NULL;
  261. if (!dev->ofw_node && fw_np)
  262. {
  263. dev_fw_np = fw_np;
  264. rt_ofw_data(fw_np) = RT_NULL;
  265. }
  266. if (dev_fw_np == RT_NULL)
  267. {
  268. rt_kprintf("[%s:%s] line=%d dev_fw_np is NULL\r\n", __FILE__, __func__, __LINE__);
  269. return;
  270. }
  271. rt_ofw_data(dev_fw_np) = RT_NULL;
  272. #endif
  273. }
  274. int rt_dm_dev_prop_read_u8_array_index(rt_device_t dev, const char *propname,
  275. int index, int nr, rt_uint8_t *out_values)
  276. {
  277. RT_ASSERT(dev != RT_NULL);
  278. #ifdef RT_UISNG_OFW
  279. if (dev->ofw_node)
  280. {
  281. return ofw_api_call(prop_read_u8_array_index, dev->ofw_node, propname,
  282. index, nr, out_value);
  283. }
  284. #endif
  285. return -RT_ENOSYS;
  286. }
  287. int rt_dm_dev_prop_read_u16_array_index(rt_device_t dev, const char *propname,
  288. int index, int nr, rt_uint16_t *out_values)
  289. {
  290. RT_ASSERT(dev != RT_NULL);
  291. #ifdef RT_USING_OFW
  292. if (dev->ofw_node)
  293. {
  294. return ofw_api_call(prop_read_u16_array_index, dev->ofw_node, propname,
  295. index, nr, out_values);
  296. }
  297. #endif
  298. return -RT_ENOSYS;
  299. }
  300. int rt_dm_dev_prop_read_u32_array_index(rt_device_t dev, const char *propname,
  301. int index, int nr, rt_uint32_t *out_values)
  302. {
  303. RT_ASSERT(dev != RT_NULL);
  304. #ifdef RT_USING_OFW
  305. if (dev->ofw_node)
  306. {
  307. return ofw_api_call(prop_read_u32_array_index, dev->ofw_node, propname,
  308. index, nr, out_values);
  309. }
  310. #endif
  311. return -RT_ENOSYS;
  312. }
  313. int rt_dm_dev_prop_read_u64_array_index(rt_device_t dev, const char *propname,
  314. int index, int nr, rt_uint64_t *out_values)
  315. {
  316. RT_ASSERT(dev != RT_NULL);
  317. #ifdef RT_USING_OFW
  318. if (dev->ofw_node)
  319. {
  320. return ofw_api_call(prop_read_u64_array_index, dev->ofw_node, propname,
  321. index, nr, out_values);
  322. }
  323. #endif
  324. return -RT_ENOSYS;
  325. }
  326. int rt_dm_dev_prop_read_string_array_index(rt_device_t dev, const char *propname,
  327. int index, int nr, const char **out_strings)
  328. {
  329. RT_ASSERT(dev != RT_NULL);
  330. #ifdef RT_USING_OFW
  331. if (dev->ofw_node)
  332. {
  333. return ofw_api_call(prop_read_string_array_index, dev->ofw_node, propname,
  334. index, nr, out_strings);
  335. }
  336. #endif
  337. return -RT_ENOSYS;
  338. }
  339. int rt_dm_dev_prop_count_of_size(rt_device_t dev, const char *propname, int size)
  340. {
  341. RT_ASSERT(dev != RT_NULL);
  342. #ifdef RT_USING_OFW
  343. if (dev->ofw_node)
  344. {
  345. return ofw_api_call(prop_count_of_size, dev->ofw_node, propname, size);
  346. }
  347. #endif
  348. return -RT_ENOSYS;
  349. }
  350. int rt_dm_dev_prop_index_of_string(rt_device_t dev, const char *propname, const char *string)
  351. {
  352. RT_ASSERT(dev != RT_NULL);
  353. #ifdef RT_USING_OFW
  354. if (dev->ofw_node)
  355. {
  356. return ofw_api_call(prop_index_of_string, dev->ofw_node, propname, string);
  357. }
  358. #endif
  359. return -RT_ENOSYS;
  360. }
  361. rt_bool_t rt_dm_dev_prop_read_bool(rt_device_t dev, const char *propname)
  362. {
  363. RT_ASSERT(dev != RT_NULL);
  364. #ifdef RT_USING_OFW
  365. if (dev->ofw_node)
  366. {
  367. return ofw_api_call(prop_read_bool, dev->ofw_node, propname);
  368. }
  369. #endif
  370. return RT_FALSE;
  371. }