drv_i2c.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  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. #ifdef RT_USING_I2C
  13. #define DBG_TAG "drv.i2c"
  14. #define DBG_LVL DBG_INFO
  15. #include <rtdbg.h>
  16. enum
  17. {
  18. #ifdef BSP_USING_I2C0
  19. I2C0_INDEX,
  20. #endif
  21. #ifdef BSP_USING_I2C1
  22. I2C1_INDEX,
  23. #endif
  24. };
  25. struct mcx_i2c_bus
  26. {
  27. struct rt_i2c_bus_device i2c_bus;
  28. LPI2C_Type *i2c_base;
  29. uint32_t baud;
  30. clock_ip_name_t clock_ip_name;
  31. clock_ip_src_t clock_ip_src;
  32. char *name;
  33. };
  34. static struct mcx_i2c_bus i2c_buses[] =
  35. {
  36. #ifdef BSP_USING_I2C0
  37. {
  38. .i2c_base = LPI2C0,
  39. .baud = 100000U,
  40. .clock_ip_name = kCLOCK_Lpi2c0,
  41. .clock_ip_src = kCLOCK_IpSrcSysOscAsync,
  42. .name = "i2c0",
  43. },
  44. #endif
  45. #ifdef BSP_USING_I2C1
  46. {
  47. .i2c_base = LPI2C1,
  48. .baud = 100000U,
  49. .clock_ip_name = kCLOCK_Lpi2c1,
  50. .clock_ip_src = kCLOCK_IpSrcSysOscAsync,
  51. .name = "i2c1",
  52. },
  53. #endif
  54. };
  55. static rt_ssize_t lpc_i2c_xfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num)
  56. {
  57. struct rt_i2c_msg *msg;
  58. lpi2c_master_transfer_t xfer = {0};
  59. rt_uint32_t i;
  60. rt_ssize_t ret = 0;
  61. struct mcx_i2c_bus *priv = (struct mcx_i2c_bus *)bus;
  62. for (i = 0; i < num; i++)
  63. {
  64. msg = &msgs[i];
  65. if (msg->flags & RT_I2C_RD)
  66. {
  67. xfer.slaveAddress = msg->addr;
  68. xfer.direction = kLPI2C_Read;
  69. xfer.subaddress = 0;
  70. xfer.subaddressSize = 0;
  71. xfer.data = msg->buf;
  72. xfer.dataSize = msg->len;
  73. xfer.flags = kLPI2C_TransferDefaultFlag;
  74. if (i != 0)
  75. {
  76. xfer.flags |= kLPI2C_TransferRepeatedStartFlag;
  77. }
  78. if (i != num - 1)
  79. {
  80. xfer.flags |= kLPI2C_TransferNoStopFlag;
  81. }
  82. if (LPI2C_MasterTransferBlocking(priv->i2c_base, &xfer) != kStatus_Success)
  83. {
  84. LOG_D("i2c bus read failed!\n");
  85. return i;
  86. }
  87. }
  88. else
  89. {
  90. xfer.slaveAddress = msg->addr;
  91. xfer.direction = kLPI2C_Write;
  92. xfer.subaddress = 0;
  93. xfer.subaddressSize = 0;
  94. xfer.data = msg->buf;
  95. xfer.dataSize = msg->len;
  96. xfer.flags = kLPI2C_TransferDefaultFlag;
  97. if (i != 0)
  98. {
  99. xfer.flags |= kLPI2C_TransferRepeatedStartFlag;
  100. }
  101. if (i != num - 1)
  102. {
  103. xfer.flags |= kLPI2C_TransferNoStopFlag;
  104. }
  105. if (LPI2C_MasterTransferBlocking(priv->i2c_base, &xfer) != kStatus_Success)
  106. {
  107. LOG_D("i2c bus write failed!\n");
  108. return i;
  109. }
  110. }
  111. }
  112. ret = i;
  113. return ret;
  114. }
  115. static const struct rt_i2c_bus_device_ops i2c_ops = {
  116. .master_xfer = lpc_i2c_xfer,
  117. .slave_xfer = RT_NULL,
  118. .i2c_bus_control = RT_NULL,
  119. };
  120. int rt_hw_i2c_init(void)
  121. {
  122. int i;
  123. lpi2c_master_config_t masterConfig;
  124. for (i = 0; i < ARRAY_SIZE(i2c_buses); i++)
  125. {
  126. struct mcx_i2c_bus *priv = &i2c_buses[i];
  127. CLOCK_SetIpSrc(priv->clock_ip_name, priv->clock_ip_src);
  128. LPI2C_MasterGetDefaultConfig(&masterConfig);
  129. masterConfig.baudRate_Hz = priv->baud;
  130. LPI2C_MasterInit(priv->i2c_base, &masterConfig, CLOCK_GetIpFreq(priv->clock_ip_name));
  131. priv->i2c_bus.ops = &i2c_ops;
  132. rt_i2c_bus_device_register(&priv->i2c_bus, priv->name);
  133. }
  134. return RT_EOK;
  135. }
  136. INIT_DEVICE_EXPORT(rt_hw_i2c_init);
  137. #endif /* RT_USING_I2C */