drv_i2c.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. /*
  2. * Copyright (c) 2022-2024 HPMicro
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. *
  6. */
  7. #include <rtthread.h>
  8. #include <rtdevice.h>
  9. #include <rtdbg.h>
  10. #ifdef BSP_USING_I2C
  11. #include "drv_i2c.h"
  12. #include "hpm_i2c_drv.h"
  13. #include "hpm_dma_mgr.h"
  14. #include "hpm_dmamux_drv.h"
  15. #include "hpm_l1c_drv.h"
  16. #include "board.h"
  17. #ifdef RT_USING_I2C
  18. #define HPM_RTT_DRV_RETRY_TIMEOUT (1000000)
  19. #ifndef HPM_I2C_DRV_DEFAULT_RETRY_COUNT
  20. #define HPM_I2C_DRV_DEFAULT_RETRY_COUNT (5000U)
  21. #endif
  22. struct hpm_i2c
  23. {
  24. struct rt_i2c_bus_device bus;
  25. I2C_Type *base;
  26. clock_name_t clk_name;
  27. char *bus_name;
  28. rt_sem_t xfer_sem;
  29. rt_bool_t enable_dma;
  30. rt_uint8_t dmamux;
  31. dma_resource_t dma;
  32. rt_uint8_t i2c_irq;
  33. rt_uint8_t is_read;
  34. };
  35. static struct hpm_i2c hpm_i2cs[] =
  36. {
  37. #if defined(BSP_USING_I2C0)
  38. {
  39. .base = HPM_I2C0,
  40. .bus_name = "i2c0",
  41. .clk_name = clock_i2c0,
  42. #if defined(BSP_I2C0_USING_DMA)
  43. .enable_dma = RT_TRUE,
  44. #endif
  45. .dmamux = HPM_DMA_SRC_I2C0,
  46. .i2c_irq = IRQn_I2C0,
  47. },
  48. #endif
  49. #if defined(BSP_USING_I2C1)
  50. {
  51. .base = HPM_I2C1,
  52. .bus_name = "i2c1",
  53. .clk_name = clock_i2c1,
  54. #if defined(BSP_I2C1_USING_DMA)
  55. .enable_dma = RT_TRUE,
  56. #endif
  57. .dmamux = HPM_DMA_SRC_I2C1,
  58. .i2c_irq = IRQn_I2C1,
  59. },
  60. #endif
  61. #if defined(BSP_USING_I2C2)
  62. {
  63. .base = HPM_I2C2,
  64. .bus_name = "i2c2",
  65. .clk_name = clock_i2c2,
  66. #if defined(BSP_I2C2_USING_DMA)
  67. .enable_dma = RT_TRUE,
  68. #endif
  69. .dmamux = HPM_DMA_SRC_I2C2,
  70. .i2c_irq = IRQn_I2C2,
  71. },
  72. #endif
  73. #if defined(BSP_USING_I2C3)
  74. {
  75. .base = HPM_I2C3,
  76. .bus_name = "i2c3",
  77. .clk_name = clock_i2c3,
  78. #if defined(BSP_I2C3_USING_DMA)
  79. .enable_dma = RT_TRUE,
  80. #endif
  81. .dmamux = HPM_DMA_SRC_I2C3,
  82. .i2c_irq = IRQn_I2C3,
  83. },
  84. #endif
  85. };
  86. static hpm_stat_t i2c_transfer(I2C_Type *ptr, const uint16_t device_address,
  87. uint8_t *buf, const uint32_t size, uint16_t flags);
  88. static rt_ssize_t hpm_i2c_master_transfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num);
  89. static hpm_stat_t i2c_tx_trigger_dma(DMA_Type *dma_ptr, uint8_t ch_num, I2C_Type *i2c_ptr, uint32_t src, uint32_t size);
  90. static hpm_stat_t i2c_rx_trigger_dma(DMA_Type *dma_ptr, uint8_t ch_num, I2C_Type *i2c_ptr, uint32_t dst, uint32_t size);
  91. struct rt_i2c_bus_device_ops hpm_i2c_ops =
  92. {
  93. hpm_i2c_master_transfer,
  94. RT_NULL,
  95. RT_NULL
  96. };
  97. static inline void handle_i2c_isr(I2C_Type *ptr)
  98. {
  99. volatile uint32_t irq_status;
  100. RT_ASSERT(ptr != RT_NULL);
  101. rt_base_t level;
  102. level = rt_hw_interrupt_disable();
  103. irq_status = i2c_get_status(ptr);
  104. if (irq_status & I2C_EVENT_TRANSACTION_COMPLETE)
  105. {
  106. for (uint32_t i = 0; i < sizeof(hpm_i2cs) / sizeof(hpm_i2cs[0]); i++)
  107. {
  108. if (hpm_i2cs[i].base == ptr)
  109. {
  110. rt_sem_release(hpm_i2cs[i].xfer_sem);
  111. }
  112. }
  113. i2c_disable_irq(ptr, I2C_EVENT_TRANSACTION_COMPLETE);
  114. i2c_clear_status(ptr, I2C_EVENT_TRANSACTION_COMPLETE);
  115. }
  116. rt_hw_interrupt_enable(level);
  117. }
  118. #if defined(BSP_USING_I2C0)
  119. void i2c0_isr(void)
  120. {
  121. handle_i2c_isr(HPM_I2C0);
  122. }
  123. SDK_DECLARE_EXT_ISR_M(IRQn_I2C0, i2c0_isr);
  124. #endif
  125. #if defined(BSP_USING_I2C1)
  126. void i2c1_isr(void)
  127. {
  128. handle_i2c_isr(HPM_I2C1);
  129. }
  130. SDK_DECLARE_EXT_ISR_M(IRQn_I2C1, i2c1_isr);
  131. #endif
  132. #if defined(BSP_USING_I2C2)
  133. void i2c2_isr(void)
  134. {
  135. handle_i2c_isr(HPM_I2C2);
  136. }
  137. SDK_DECLARE_EXT_ISR_M(IRQn_I2C2, i2c2_isr);
  138. #endif
  139. #if defined(BSP_USING_I2C3)
  140. void i2c3_isr(void)
  141. {
  142. handle_i2c_isr(HPM_I2C3);
  143. }
  144. SDK_DECLARE_EXT_ISR_M(IRQn_I2C3, i2c3_isr);
  145. #endif
  146. static hpm_stat_t i2c_tx_trigger_dma(DMA_Type *dma_ptr, uint8_t ch_num, I2C_Type *i2c_ptr, uint32_t src, uint32_t size)
  147. {
  148. dma_handshake_config_t config;
  149. dma_default_handshake_config(dma_ptr, &config);
  150. config.ch_index = ch_num;
  151. config.dst = (uint32_t)&i2c_ptr->DATA;
  152. config.dst_fixed = true;
  153. config.src = src;
  154. config.src_fixed = false;
  155. config.data_width = DMA_TRANSFER_WIDTH_BYTE;
  156. config.size_in_byte = size;
  157. return dma_setup_handshake(dma_ptr, &config, true);
  158. }
  159. static hpm_stat_t i2c_rx_trigger_dma(DMA_Type *dma_ptr, uint8_t ch_num, I2C_Type *i2c_ptr, uint32_t dst, uint32_t size)
  160. {
  161. dma_handshake_config_t config;
  162. dma_default_handshake_config(dma_ptr, &config);
  163. config.ch_index = ch_num;
  164. config.dst = dst;
  165. config.dst_fixed = false;
  166. config.src = (uint32_t)&i2c_ptr->DATA;
  167. config.src_fixed = true;
  168. config.data_width = DMA_TRANSFER_WIDTH_BYTE;
  169. config.size_in_byte = size;
  170. return dma_setup_handshake(dma_ptr, &config, true);
  171. }
  172. void i2c_dma_channel_tc_callback(DMA_Type *ptr, uint32_t channel, void *user_data)
  173. {
  174. struct hpm_i2c *i2c = (struct hpm_i2c *)user_data;
  175. RT_ASSERT(i2c != RT_NULL);
  176. RT_ASSERT(ptr != RT_NULL);
  177. rt_base_t level;
  178. level = rt_hw_interrupt_disable();
  179. if ((i2c->dma.base == ptr) && i2c->dma.channel == channel)
  180. {
  181. dma_mgr_disable_chn_irq(&i2c->dma, DMA_MGR_INTERRUPT_MASK_TC);
  182. if (i2c->is_read == true)
  183. {
  184. rt_sem_release(i2c->xfer_sem);
  185. }
  186. }
  187. rt_hw_interrupt_enable(level);
  188. }
  189. static rt_ssize_t hpm_i2c_master_transfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num)
  190. {
  191. RT_ASSERT(bus != RT_NULL);
  192. RT_ASSERT(msgs != RT_NULL);
  193. struct rt_i2c_msg *msg;
  194. struct hpm_i2c *i2c_info = (struct hpm_i2c *)bus;
  195. hpm_stat_t i2c_stat = status_success;
  196. rt_size_t ret = 0;
  197. rt_uint32_t i;
  198. rt_uint8_t *raw_alloc_buf = RT_NULL;
  199. rt_uint8_t *aligned_buf = RT_NULL;
  200. rt_uint8_t *dummy_buf = RT_NULL;
  201. rt_uint32_t aligned_len = 0;
  202. rt_uint32_t remaining_size = 0;
  203. rt_uint32_t transfer_len;
  204. for (i = 0; i < num; i++)
  205. {
  206. msg = &msgs[i];
  207. remaining_size = msg->len;
  208. if ((msg->len > 0) && (i2c_info->enable_dma))
  209. {
  210. aligned_len = (msg->len + HPM_L1C_CACHELINE_SIZE - 1U) & ~(HPM_L1C_CACHELINE_SIZE - 1U);
  211. if (l1c_dc_is_enabled())
  212. {
  213. if (msg->flags & RT_I2C_RD)
  214. {
  215. /* The allocated pointer is always RT_ALIGN_SIZE aligned */
  216. raw_alloc_buf = (uint8_t*)rt_malloc(aligned_len + HPM_L1C_CACHELINE_SIZE - RT_ALIGN_SIZE);
  217. RT_ASSERT(raw_alloc_buf != RT_NULL);
  218. }
  219. else
  220. {
  221. aligned_buf = (uint8_t*)HPM_L1C_CACHELINE_ALIGN_UP((uint32_t)raw_alloc_buf);
  222. /* The allocated pointer is always RT_ALIGN_SIZE aligned */
  223. raw_alloc_buf = (uint8_t*)rt_malloc(aligned_len + HPM_L1C_CACHELINE_SIZE - RT_ALIGN_SIZE);
  224. RT_ASSERT(raw_alloc_buf != RT_NULL);
  225. aligned_buf = (uint8_t*)HPM_L1C_CACHELINE_ALIGN_UP((uint32_t)raw_alloc_buf);
  226. rt_memcpy(aligned_buf, msg->buf, msg->len);
  227. l1c_dc_flush((uint32_t)aligned_buf, aligned_len);
  228. }
  229. }
  230. }
  231. else
  232. {
  233. aligned_buf = (uint8_t*) msg->buf;
  234. }
  235. if (msg->flags & RT_I2C_ADDR_10BIT)
  236. {
  237. i2c_enable_10bit_address_mode(i2c_info->base, true);
  238. }
  239. else
  240. {
  241. i2c_enable_10bit_address_mode(i2c_info->base, false);
  242. }
  243. dummy_buf = aligned_buf;
  244. if (msg->flags & RT_I2C_RD)
  245. {
  246. /* maybe probe i2c device */
  247. if (msg->len == 0)
  248. {
  249. i2c_stat = i2c_master_read(i2c_info->base, msg->addr, dummy_buf, remaining_size);
  250. }
  251. else
  252. {
  253. while (remaining_size)
  254. {
  255. transfer_len = MIN(I2C_SOC_TRANSFER_COUNT_MAX, remaining_size);
  256. if ((i2c_info->enable_dma))
  257. {
  258. /* sequential transfer now is not support dma */
  259. if ((msg->flags & RT_I2C_NO_START) || (msg->flags & RT_I2C_NO_STOP) ||
  260. (msg->flags & RT_I2C_NO_READ_ACK) || (msg->flags & RT_I2C_NO_READ_ACK) ) {
  261. i2c_stat = status_invalid_argument;
  262. break;
  263. }
  264. i2c_info->is_read = true;
  265. i2c_enable_irq(i2c_info->base, I2C_EVENT_TRANSACTION_COMPLETE);
  266. dmamux_config(HPM_DMAMUX, i2c_info->dma.channel, i2c_info->dmamux, true);
  267. i2c_stat = i2c_rx_trigger_dma(i2c_info->dma.base, i2c_info->dma.channel, i2c_info->base,
  268. core_local_mem_to_sys_address(0, (uint32_t) dummy_buf), transfer_len);
  269. if (i2c_stat != status_success)
  270. {
  271. break;
  272. }
  273. i2c_stat = i2c_master_start_dma_read(i2c_info->base, msg->addr, msg->len);
  274. if (i2c_stat != status_success)
  275. {
  276. break;
  277. }
  278. rt_sem_take(i2c_info->xfer_sem, RT_WAITING_FOREVER);
  279. }
  280. else
  281. {
  282. i2c_master_transfer(i2c_info->base, msg->addr, dummy_buf, transfer_len, msg->flags);
  283. }
  284. dummy_buf += transfer_len;
  285. remaining_size -= transfer_len;
  286. }
  287. if (raw_alloc_buf != RT_NULL)
  288. {
  289. l1c_dc_invalidate((uint32_t) aligned_buf, aligned_len);
  290. rt_memcpy(msg->buf, aligned_buf, msg->len);
  291. rt_free(raw_alloc_buf);
  292. raw_alloc_buf = RT_NULL;
  293. aligned_buf = RT_NULL;
  294. }
  295. }
  296. }
  297. else
  298. {
  299. /* maybe probe i2c device */
  300. if (msg->len == 0)
  301. {
  302. i2c_stat = i2c_master_write(i2c_info->base, msg->addr, dummy_buf, remaining_size);
  303. }
  304. else
  305. {
  306. while (remaining_size)
  307. {
  308. transfer_len = MIN(I2C_SOC_TRANSFER_COUNT_MAX, remaining_size);
  309. if (i2c_info->enable_dma)
  310. {
  311. /* sequential transfer now is not support dma */
  312. if ((msg->flags & RT_I2C_NO_START) || (msg->flags & RT_I2C_NO_STOP) ||
  313. (msg->flags & RT_I2C_NO_READ_ACK) || (msg->flags & RT_I2C_NO_READ_ACK) ) {
  314. i2c_stat = status_invalid_argument;
  315. break;
  316. }
  317. i2c_info->is_read = false;
  318. i2c_enable_irq(i2c_info->base, I2C_EVENT_TRANSACTION_COMPLETE);
  319. dmamux_config(HPM_DMAMUX, i2c_info->dma.channel, i2c_info->dmamux, true);
  320. i2c_stat = i2c_tx_trigger_dma(i2c_info->dma.base, i2c_info->dma.channel, i2c_info->base,
  321. core_local_mem_to_sys_address(0, (uint32_t) dummy_buf), transfer_len);
  322. if (i2c_stat != status_success)
  323. {
  324. break;
  325. }
  326. i2c_stat = i2c_master_start_dma_write(i2c_info->base, msg->addr, msg->len);
  327. if (i2c_stat != status_success)
  328. {
  329. break;
  330. }
  331. rt_sem_take(i2c_info->xfer_sem, RT_WAITING_FOREVER);
  332. }
  333. else
  334. {
  335. i2c_master_transfer(i2c_info->base, msg->addr, dummy_buf, transfer_len, msg->flags);
  336. }
  337. dummy_buf += transfer_len;
  338. remaining_size -= transfer_len;
  339. }
  340. if (raw_alloc_buf != RT_NULL)
  341. {
  342. rt_free(raw_alloc_buf);
  343. raw_alloc_buf = RT_NULL;
  344. aligned_buf = RT_NULL;
  345. }
  346. }
  347. }
  348. if (i2c_stat != status_success)
  349. {
  350. break;
  351. }
  352. }
  353. if (i2c_stat != status_success)
  354. {
  355. return ret;
  356. }
  357. ret = i;
  358. return ret;
  359. }
  360. int rt_hw_i2c_init(void)
  361. {
  362. rt_err_t ret = RT_EOK;
  363. hpm_stat_t stat;
  364. i2c_config_t config;
  365. rt_uint32_t freq;
  366. char sem_name[RT_NAME_MAX];
  367. for (uint32_t i = 0; i < sizeof(hpm_i2cs) / sizeof(hpm_i2cs[0]); i++) {
  368. init_i2c_pins(hpm_i2cs[i].base);
  369. clock_add_to_group(hpm_i2cs[i].clk_name, 0);
  370. clock_set_source_divider(hpm_i2cs[i].clk_name, clk_src_osc24m, 1U);
  371. config.i2c_mode = i2c_mode_normal;
  372. config.is_10bit_addressing = false;
  373. freq = clock_get_frequency(hpm_i2cs[i].clk_name);
  374. stat = i2c_init_master(hpm_i2cs[i].base, freq, &config);
  375. if (stat != status_success) {
  376. LOG_E("rt i2c device %s init failed", hpm_i2cs[i].bus_name);
  377. }
  378. hpm_i2cs[i].bus.ops = &hpm_i2c_ops;
  379. if (hpm_i2cs[i].enable_dma)
  380. {
  381. stat = dma_mgr_request_resource(&hpm_i2cs[i].dma);
  382. if (stat != status_success)
  383. {
  384. return -RT_ERROR;
  385. }
  386. dma_mgr_install_chn_tc_callback(&hpm_i2cs[i].dma, i2c_dma_channel_tc_callback, (void *)&hpm_i2cs[i]);
  387. dma_mgr_enable_dma_irq_with_priority(&hpm_i2cs[i].dma, 1);
  388. intc_m_enable_irq_with_priority(hpm_i2cs[i].i2c_irq, 2);
  389. i2c_disable_irq(hpm_i2cs[i].base, I2C_EVENT_TRANSACTION_COMPLETE);
  390. rt_sprintf(sem_name, "%s_s", hpm_i2cs[i].bus_name);
  391. hpm_i2cs[i].xfer_sem = rt_sem_create(sem_name, 0, RT_IPC_FLAG_PRIO);
  392. if (hpm_i2cs[i].xfer_sem == RT_NULL)
  393. {
  394. ret = RT_ENOMEM;
  395. break;
  396. }
  397. }
  398. ret = rt_i2c_bus_device_register(&hpm_i2cs[i].bus, hpm_i2cs[i].bus_name);
  399. if (ret != RT_EOK) {
  400. LOG_E("rt i2c device %s register failed, status=%d\n", hpm_i2cs[i].bus_name, ret);
  401. }
  402. }
  403. return ret;
  404. }
  405. INIT_DEVICE_EXPORT(rt_hw_i2c_init);
  406. #endif /* RT_USING_I2C */
  407. #endif /*BSP_USING_I2C*/