drv_soft_i2c.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  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. static void w60x_i2c_pin_init(void)
  53. {
  54. rt_size_t obj_num = sizeof(i2c_obj) / sizeof(struct w60x_i2c);
  55. for(rt_size_t i = 0; i < obj_num; i++)
  56. {
  57. w60x_i2c_gpio_init(&i2c_obj[i]);
  58. }
  59. }
  60. /**
  61. * This function sets the sda pin.
  62. *
  63. * @param w60x config class.
  64. * @param The sda pin state.
  65. */
  66. static void w60x_set_sda(void *data, rt_int32_t state)
  67. {
  68. struct w60x_soft_i2c_config* cfg = (struct w60x_soft_i2c_config*)data;
  69. rt_int16_t sda;
  70. sda = wm_get_pin(cfg->sda);
  71. if (state)
  72. {
  73. tls_gpio_cfg((enum tls_io_name)sda, WM_GPIO_DIR_INPUT, WM_GPIO_ATTR_PULLHIGH);
  74. }
  75. else
  76. {
  77. tls_gpio_cfg((enum tls_io_name)sda, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING);
  78. tls_gpio_write((enum tls_io_name)sda, 0);
  79. }
  80. }
  81. /**
  82. * This function sets the scl pin.
  83. *
  84. * @param w60x config class.
  85. * @param The scl pin state.
  86. */
  87. static void w60x_set_scl(void *data, rt_int32_t state)
  88. {
  89. struct w60x_soft_i2c_config* cfg = (struct w60x_soft_i2c_config*)data;
  90. rt_int16_t scl;
  91. scl = wm_get_pin(cfg->scl);
  92. if (state)
  93. {
  94. tls_gpio_cfg((enum tls_io_name)scl, WM_GPIO_DIR_INPUT, WM_GPIO_ATTR_PULLHIGH);
  95. }
  96. else
  97. {
  98. tls_gpio_cfg((enum tls_io_name)scl, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING);
  99. tls_gpio_write((enum tls_io_name)scl, 0);
  100. }
  101. }
  102. /**
  103. * This function gets the sda pin state.
  104. *
  105. * @param The sda pin state.
  106. */
  107. static rt_int32_t w60x_get_sda(void *data)
  108. {
  109. struct w60x_soft_i2c_config* cfg = (struct w60x_soft_i2c_config*)data;
  110. rt_int16_t sda;
  111. sda = wm_get_pin(cfg->sda);
  112. return tls_gpio_read((enum tls_io_name)sda);
  113. }
  114. /**
  115. * This function gets the scl pin state.
  116. *
  117. * @param The scl pin state.
  118. */
  119. static rt_int32_t w60x_get_scl(void *data)
  120. {
  121. struct w60x_soft_i2c_config* cfg = (struct w60x_soft_i2c_config*)data;
  122. rt_int16_t scl;
  123. scl = wm_get_pin(cfg->scl);
  124. return tls_gpio_read((enum tls_io_name)scl);
  125. }
  126. static const struct rt_i2c_bit_ops w60x_bit_ops_default =
  127. {
  128. .data = RT_NULL,
  129. .pin_init = w60x_i2c_pin_init,
  130. .set_sda = w60x_set_sda,
  131. .set_scl = w60x_set_scl,
  132. .get_sda = w60x_get_sda,
  133. .get_scl = w60x_get_scl,
  134. .udelay = rt_hw_us_delay,
  135. .delay_us = 1,
  136. .timeout = 100,
  137. .i2c_pin_init_flag = RT_FALSE
  138. };
  139. /**
  140. * if i2c is locked, this function will unlock it
  141. *
  142. * @param w60x config class
  143. *
  144. * @return RT_EOK indicates successful unlock.
  145. */
  146. static rt_err_t w60x_i2c_bus_unlock(const struct w60x_soft_i2c_config *cfg)
  147. {
  148. rt_int32_t i = 0;
  149. if (PIN_LOW == rt_pin_read(cfg->sda))
  150. {
  151. while (i++ < 9)
  152. {
  153. rt_pin_write(cfg->scl, PIN_HIGH);
  154. rt_hw_us_delay(100);
  155. rt_pin_write(cfg->scl, PIN_LOW);
  156. rt_hw_us_delay(100);
  157. }
  158. }
  159. if (PIN_LOW == rt_pin_read(cfg->sda))
  160. {
  161. return -RT_ERROR;
  162. }
  163. return RT_EOK;
  164. }
  165. /* I2C initialization function */
  166. int rt_soft_i2c_init(void)
  167. {
  168. rt_size_t obj_num = sizeof(i2c_obj) / sizeof(struct w60x_i2c);
  169. rt_err_t result;
  170. for (rt_size_t i = 0; i < obj_num; i++)
  171. {
  172. i2c_obj[i].ops = w60x_bit_ops_default;
  173. i2c_obj[i].ops.data = (void*)&soft_i2c_config[i];
  174. i2c_obj[i].i2c_bus.priv = &i2c_obj[i].ops;
  175. result = rt_i2c_bit_add_bus(&i2c_obj[i].i2c_bus, soft_i2c_config[i].bus_name);
  176. RT_ASSERT(result == RT_EOK);
  177. w60x_i2c_bus_unlock(&soft_i2c_config[i]);
  178. LOG_D("software simulation %s init done, pin scl: %d, pin sda %d",
  179. soft_i2c_config[i].bus_name,
  180. soft_i2c_config[i].scl,
  181. soft_i2c_config[i].sda);
  182. }
  183. return RT_EOK;
  184. }
  185. INIT_DEVICE_EXPORT(rt_soft_i2c_init);
  186. #endif /* BSP_USING_SOFT_I2C */