drv_soft_i2c.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2019-03-22 balanceTWK first version
  9. */
  10. #include <board.h>
  11. #include "drv_soft_i2c.h"
  12. #include "wm_regs.h"
  13. #include "wm_gpio.h"
  14. #include "pin_map.h"
  15. #define DBG_SECTION_NAME "soft_i2c"
  16. #define DBG_COLOR
  17. #define DBG_LEVEL DBG_LOG
  18. #include <rtdbg.h>
  19. #ifdef BSP_USING_SOFT_I2C
  20. #if !defined(BSP_USING_SOFT_I2C1) && !defined(BSP_USING_SOFT_I2C2) && !defined(BSP_USING_SOFT_I2C3)
  21. #error "Please define at least one BSP_USING_SOFT_I2Cx"
  22. #endif
  23. static const struct w60x_soft_i2c_config soft_i2c_config[] =
  24. {
  25. #ifdef BSP_USING_SOFT_I2C1
  26. I2C1_BUS_CONFIG,
  27. #endif
  28. #ifdef BSP_USING_SOFT_I2C2
  29. I2C2_BUS_CONFIG,
  30. #endif
  31. #ifdef BSP_USING_SOFT_I2C3
  32. I2C3_BUS_CONFIG,
  33. #endif
  34. };
  35. static struct w60x_i2c i2c_obj[sizeof(soft_i2c_config) / sizeof(soft_i2c_config[0])];
  36. /**
  37. * This function initializes the i2c pin.
  38. *
  39. * @param w60x i2c dirver class.
  40. */
  41. static void w60x_i2c_gpio_init(struct w60x_i2c *i2c)
  42. {
  43. struct w60x_soft_i2c_config* cfg = (struct w60x_soft_i2c_config*)i2c->ops.data;
  44. rt_int16_t scl,sda;
  45. scl = wm_get_pin(cfg->scl);
  46. sda = wm_get_pin(cfg->sda);
  47. tls_gpio_cfg((enum tls_io_name)scl, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH);
  48. tls_gpio_cfg((enum tls_io_name)sda, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH);
  49. tls_gpio_write((enum tls_io_name)scl, 1);
  50. tls_gpio_write((enum tls_io_name)sda, 1);
  51. }
  52. /**
  53. * This function sets the sda pin.
  54. *
  55. * @param w60x config class.
  56. * @param The sda pin state.
  57. */
  58. static void w60x_set_sda(void *data, rt_int32_t state)
  59. {
  60. struct w60x_soft_i2c_config* cfg = (struct w60x_soft_i2c_config*)data;
  61. rt_int16_t sda;
  62. sda = wm_get_pin(cfg->sda);
  63. if (state)
  64. {
  65. tls_gpio_cfg((enum tls_io_name)sda, WM_GPIO_DIR_INPUT, WM_GPIO_ATTR_PULLHIGH);
  66. }
  67. else
  68. {
  69. tls_gpio_cfg((enum tls_io_name)sda, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING);
  70. tls_gpio_write((enum tls_io_name)sda, 0);
  71. }
  72. }
  73. /**
  74. * This function sets the scl pin.
  75. *
  76. * @param w60x config class.
  77. * @param The scl pin state.
  78. */
  79. static void w60x_set_scl(void *data, rt_int32_t state)
  80. {
  81. struct w60x_soft_i2c_config* cfg = (struct w60x_soft_i2c_config*)data;
  82. rt_int16_t scl;
  83. scl = wm_get_pin(cfg->scl);
  84. if (state)
  85. {
  86. tls_gpio_cfg((enum tls_io_name)scl, WM_GPIO_DIR_INPUT, WM_GPIO_ATTR_PULLHIGH);
  87. }
  88. else
  89. {
  90. tls_gpio_cfg((enum tls_io_name)scl, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING);
  91. tls_gpio_write((enum tls_io_name)scl, 0);
  92. }
  93. }
  94. /**
  95. * This function gets the sda pin state.
  96. *
  97. * @param The sda pin state.
  98. */
  99. static rt_int32_t w60x_get_sda(void *data)
  100. {
  101. struct w60x_soft_i2c_config* cfg = (struct w60x_soft_i2c_config*)data;
  102. rt_int16_t sda;
  103. sda = wm_get_pin(cfg->sda);
  104. return tls_gpio_read((enum tls_io_name)sda);
  105. }
  106. /**
  107. * This function gets the scl pin state.
  108. *
  109. * @param The scl pin state.
  110. */
  111. static rt_int32_t w60x_get_scl(void *data)
  112. {
  113. struct w60x_soft_i2c_config* cfg = (struct w60x_soft_i2c_config*)data;
  114. rt_int16_t scl;
  115. scl = wm_get_pin(cfg->scl);
  116. return tls_gpio_read((enum tls_io_name)scl);
  117. }
  118. static const struct rt_i2c_bit_ops w60x_bit_ops_default =
  119. {
  120. .data = RT_NULL,
  121. .set_sda = w60x_set_sda,
  122. .set_scl = w60x_set_scl,
  123. .get_sda = w60x_get_sda,
  124. .get_scl = w60x_get_scl,
  125. .udelay = rt_hw_us_delay,
  126. .delay_us = 1,
  127. .timeout = 100
  128. };
  129. /**
  130. * if i2c is locked, this function will unlock it
  131. *
  132. * @param w60x config class
  133. *
  134. * @return RT_EOK indicates successful unlock.
  135. */
  136. static rt_err_t w60x_i2c_bus_unlock(const struct w60x_soft_i2c_config *cfg)
  137. {
  138. rt_int32_t i = 0;
  139. if (PIN_LOW == rt_pin_read(cfg->sda))
  140. {
  141. while (i++ < 9)
  142. {
  143. rt_pin_write(cfg->scl, PIN_HIGH);
  144. rt_hw_us_delay(100);
  145. rt_pin_write(cfg->scl, PIN_LOW);
  146. rt_hw_us_delay(100);
  147. }
  148. }
  149. if (PIN_LOW == rt_pin_read(cfg->sda))
  150. {
  151. return -RT_ERROR;
  152. }
  153. return RT_EOK;
  154. }
  155. /* I2C initialization function */
  156. int rt_soft_i2c_init(void)
  157. {
  158. rt_size_t obj_num = sizeof(i2c_obj) / sizeof(struct w60x_i2c);
  159. rt_err_t result;
  160. for (int i = 0; i < obj_num; i++)
  161. {
  162. i2c_obj[i].ops = w60x_bit_ops_default;
  163. i2c_obj[i].ops.data = (void*)&soft_i2c_config[i];
  164. i2c_obj[i].i2c2_bus.priv = &i2c_obj[i].ops;
  165. w60x_i2c_gpio_init(&i2c_obj[i]);
  166. result = rt_i2c_bit_add_bus(&i2c_obj[i].i2c2_bus, soft_i2c_config[i].bus_name);
  167. RT_ASSERT(result == RT_EOK);
  168. w60x_i2c_bus_unlock(&soft_i2c_config[i]);
  169. LOG_D("software simulation %s init done, pin scl: %d, pin sda %d",
  170. soft_i2c_config[i].bus_name,
  171. soft_i2c_config[i].scl,
  172. soft_i2c_config[i].sda);
  173. }
  174. return RT_EOK;
  175. }
  176. INIT_DEVICE_EXPORT(rt_soft_i2c_init);
  177. #endif /* BSP_USING_SOFT_I2C */