drv_i2c.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  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-08-21 hywing The first version
  9. */
  10. #include <rtdevice.h>
  11. #include "fsl_lpi2c.h"
  12. #include "fsl_lpi2c_edma.h"
  13. #include "fsl_edma.h"
  14. #ifdef RT_USING_I2C
  15. #define DBG_TAG "drv.i2c"
  16. #define DBG_LVL DBG_INFO
  17. #include <rtdbg.h>
  18. #if (defined(CPU_MCXA346VLH) || defined(CPU_MCXA346VLL) || defined(CPU_MCXA346VLQ) || defined(CPU_MCXA346VPN) || \
  19. defined(CPU_MCXA366VLH) || defined(CPU_MCXA366VLL) || defined(CPU_MCXA366VLQ) || defined(CPU_MCXA366VPN))
  20. #define MCXA_I2C_USE_FRO_LF_DIV
  21. #endif
  22. enum
  23. {
  24. #ifdef BSP_USING_I2C0
  25. I2C0_INDEX,
  26. #endif
  27. #ifdef BSP_USING_I2C1
  28. I2C1_INDEX,
  29. #endif
  30. #ifdef BSP_USING_I2C2
  31. I2C2_INDEX,
  32. #endif
  33. #ifdef BSP_USING_I2C3
  34. I2C3_INDEX,
  35. #endif
  36. };
  37. struct lpc_i2c_bus
  38. {
  39. struct rt_i2c_bus_device parent;
  40. LPI2C_Type *I2C;
  41. clock_attach_id_t clock_attach_id;
  42. clock_div_name_t clock_div_name;
  43. clock_name_t clock_src;
  44. uint32_t baud;
  45. char *name;
  46. };
  47. struct lpc_i2c_bus lpc_obj[] =
  48. {
  49. #ifdef BSP_USING_I2C0
  50. {
  51. .I2C = LPI2C0,
  52. .baud = 100000U,
  53. #if defined(MCXA_I2C_USE_FRO_LF_DIV)
  54. .clock_attach_id = kFRO_LF_DIV_to_LPI2C0,
  55. #else
  56. .clock_attach_id = kFRO12M_to_LPI2C0,
  57. #endif
  58. .clock_div_name = kCLOCK_DivLPI2C0,
  59. .clock_src = kCLOCK_Fro12M,
  60. .name = "i2c0",
  61. },
  62. #endif
  63. #ifdef BSP_USING_I2C1
  64. {
  65. .I2C = LPI2C1,
  66. .baud = 100000U,
  67. #if defined(MCXA_I2C_USE_FRO_LF_DIV)
  68. .clock_attach_id = kFRO_LF_DIV_to_LPI2C1,
  69. #else
  70. .clock_attach_id = kFRO12M_to_LPI2C1,
  71. #endif
  72. .clock_div_name = kCLOCK_DivLPI2C1,
  73. .clock_src = kCLOCK_Fro12M,
  74. .name = "i2c1",
  75. },
  76. #endif
  77. #ifdef BSP_USING_I2C2
  78. {
  79. .I2C = LPI2C2,
  80. .baud = 100000U,
  81. #if defined(MCXA_I2C_USE_FRO_LF_DIV)
  82. .clock_attach_id = kFRO_LF_DIV_to_LPI2C2,
  83. #else
  84. .clock_attach_id = kFRO12M_to_LPI2C2,
  85. #endif
  86. .clock_div_name = kCLOCK_DivLPI2C2,
  87. .clock_src = kCLOCK_Fro12M,
  88. .name = "i2c2",
  89. },
  90. #endif
  91. #ifdef BSP_USING_I2C3
  92. {
  93. .I2C = LPI2C3,
  94. .baud = 100000U,
  95. #if defined(MCXA_I2C_USE_FRO_LF_DIV)
  96. .clock_attach_id = kFRO_LF_DIV_to_LPI2C3,
  97. #else
  98. .clock_attach_id = kFRO12M_to_LPI2C3,
  99. #endif
  100. .clock_div_name = kCLOCK_DivLPI2C3,
  101. .clock_src = kCLOCK_Fro12M,
  102. .name = "i2c3",
  103. },
  104. #endif
  105. };
  106. static rt_ssize_t lpc_i2c_xfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num)
  107. {
  108. struct rt_i2c_msg *msg;
  109. lpi2c_master_transfer_t xfer = {0};
  110. rt_uint32_t i;
  111. rt_ssize_t ret = 0;
  112. struct lpc_i2c_bus *lpc_i2c = (struct lpc_i2c_bus *)bus;
  113. for (i = 0; i < num; i++)
  114. {
  115. msg = &msgs[i];
  116. if (msg->flags & RT_I2C_RD)
  117. {
  118. xfer.slaveAddress = msg->addr;
  119. xfer.direction = kLPI2C_Read;
  120. xfer.subaddress = 0;
  121. xfer.subaddressSize = 0;
  122. xfer.data = msg->buf;
  123. xfer.dataSize = msg->len;
  124. if(i != 0)
  125. xfer.flags = kLPI2C_TransferRepeatedStartFlag;
  126. else
  127. xfer.flags = kLPI2C_TransferDefaultFlag;
  128. if (LPI2C_MasterTransferBlocking(lpc_i2c->I2C, &xfer) != kStatus_Success)
  129. {
  130. LOG_D("i2c bus read failed!\n");
  131. return i;
  132. }
  133. }
  134. else
  135. {
  136. xfer.slaveAddress = msg->addr;
  137. xfer.direction = kLPI2C_Write;
  138. xfer.subaddress = 0;
  139. xfer.subaddressSize = 0;
  140. xfer.data = msg->buf;
  141. xfer.dataSize = msg->len;
  142. if(i == 0)
  143. xfer.flags = kLPI2C_TransferNoStopFlag;
  144. else
  145. xfer.flags = kLPI2C_TransferDefaultFlag;
  146. if (LPI2C_MasterTransferBlocking(lpc_i2c->I2C, &xfer) != kStatus_Success)
  147. {
  148. LOG_D("i2c bus write failed!\n");
  149. return i;
  150. }
  151. }
  152. }
  153. ret = i;
  154. return ret;
  155. }
  156. static const struct rt_i2c_bus_device_ops i2c_ops =
  157. {
  158. lpc_i2c_xfer,
  159. RT_NULL,
  160. RT_NULL
  161. };
  162. int rt_hw_i2c_init(void)
  163. {
  164. int i;
  165. lpi2c_master_config_t masterConfig;
  166. for(i=0; i<ARRAY_SIZE(lpc_obj); i++)
  167. {
  168. CLOCK_SetClockDiv(lpc_obj[i].clock_div_name, 1u);
  169. CLOCK_AttachClk(lpc_obj[i].clock_attach_id);
  170. LPI2C_MasterGetDefaultConfig(&masterConfig);
  171. masterConfig.baudRate_Hz = lpc_obj[i].baud;
  172. LPI2C_MasterInit(lpc_obj[i].I2C, &masterConfig, CLOCK_GetFreq(lpc_obj[i].clock_src));
  173. lpc_obj[i].parent.ops = &i2c_ops;
  174. rt_i2c_bus_device_register(&lpc_obj[i].parent, lpc_obj[i].name);
  175. }
  176. return RT_EOK;
  177. }
  178. INIT_DEVICE_EXPORT(rt_hw_i2c_init);
  179. #endif /* RT_USING_I2C */