iic_hw.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. #include "asm/iic_hw.h"
  2. #include "system/generic/gpio.h"
  3. #include "system/generic/log.h"
  4. #include "asm/clock.h"
  5. #include "asm/cpu.h"
  6. #if 0
  7. /*
  8. [[ 注意!!! ]]
  9. * 适用于带cfg_done的硬件IIC,另一种硬件IIC另作说明
  10. * 硬件IIC的START / ACK(NACK)必须在发送或接收字节cfg_done前设置,且不能
  11. 接cfg_done单独发送;而STOP则应在发送或接收字节cfg_done后设置,必须接
  12. cfg_done单独发送
  13. */
  14. /* const struct hw_iic_config hw_iic_cfg_test[] = { */
  15. /* //iic0 data */
  16. /* { */
  17. /* // SCL SDA */
  18. /* .port = {IO_PORTA_06, IO_PORTA_07}, */
  19. /* .baudrate = 100000, //IIC通讯波特率 */
  20. /* .hdrive = 0, //是否打开IO口强驱 */
  21. /* .io_filter = 1, //是否打开滤波器(去纹波) */
  22. /* .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 */
  23. /* .role = IIC_MASTER, */
  24. /* }, */
  25. /* }; */
  26. static JL_IIC_TypeDef *const iic_regs[IIC_HW_NUM] = {
  27. JL_IIC,
  28. };
  29. #define iic_get_id(iic) (iic)
  30. #define iic_info_port(iic, x) (hw_iic_cfg[iic_get_id(iic)].port[x])
  31. #define iic_info_baud(iic) (hw_iic_cfg[iic_get_id(iic)].baudrate)
  32. #define iic_info_hdrive(iic) (hw_iic_cfg[iic_get_id(iic)].hdrive)
  33. #define iic_info_io_filt(iic) (hw_iic_cfg[iic_get_id(iic)].io_filter)
  34. #define iic_info_io_pu(iic) (hw_iic_cfg[iic_get_id(iic)].io_pu)
  35. #define iic_info_role(iic) (hw_iic_cfg[iic_get_id(iic)].role)
  36. static inline u32 iic_get_scl(hw_iic_dev iic)
  37. {
  38. u8 port = iic_info_port(iic, 0);
  39. return port;
  40. }
  41. static inline u32 iic_get_sda(hw_iic_dev iic)
  42. {
  43. u8 port = iic_info_port(iic, 1);
  44. return port;
  45. }
  46. static int iic_port_init(hw_iic_dev iic)
  47. {
  48. u32 reg;
  49. int ret = 0;
  50. u8 id = iic_get_id(iic);
  51. u32 scl, sda;
  52. scl = iic_get_scl(iic);
  53. sda = iic_get_sda(iic);
  54. if (id == 0) {
  55. gpio_set_fun_output_port(scl, FO_IIC_SCL, 1, 1);
  56. gpio_set_fun_output_port(sda, FO_IIC_SDA, 1, 1);
  57. gpio_set_fun_input_port(scl, PFI_IIC_SCL);
  58. gpio_set_fun_input_port(sda, PFI_IIC_SDA);
  59. if (scl >= IO_PORT_DP || sda >= IO_PORT_DP) {
  60. usb_iomode(1);
  61. }
  62. if (iic_info_hdrive(iic)) {
  63. gpio_set_hd(scl, 1);
  64. gpio_set_hd(sda, 1);
  65. } else {
  66. gpio_set_hd(scl, 0);
  67. gpio_set_hd(sda, 0);
  68. }
  69. if (iic_info_io_pu(iic)) {
  70. gpio_set_pull_up(scl, 1);
  71. gpio_set_pull_down(scl, 0);
  72. gpio_set_pull_up(sda, 1);
  73. gpio_set_pull_down(sda, 0);
  74. } else {
  75. gpio_set_pull_up(scl, 0);
  76. gpio_set_pull_down(scl, 0);
  77. gpio_set_pull_up(sda, 0);
  78. gpio_set_pull_down(sda, 0);
  79. }
  80. } else {
  81. ret = -EINVAL;
  82. }
  83. return ret;
  84. }
  85. int hw_iic_set_baud(hw_iic_dev iic, u32 baud)
  86. {
  87. //f_iic = f_sys / (IIC_BAUD * 2)
  88. //=> IIC_BAUD = f_sys / (2 * f_iic)
  89. u32 sysclk;
  90. u8 id = iic_get_id(iic);
  91. sysclk = clk_get("lsb");
  92. /* printf("lsb clk:%d",sysclk); */
  93. if (sysclk < 2 * baud) {
  94. return -EINVAL;
  95. }
  96. iic_baud_reg(iic_regs[id]) = sysclk / (2 * baud);
  97. return 0;
  98. }
  99. static void hw_iic_set_die(hw_iic_dev iic, u8 en)
  100. {
  101. u8 id = iic_get_id(iic);
  102. u32 scl, sda;
  103. scl = iic_get_scl(iic);
  104. sda = iic_get_sda(iic);
  105. if (id == 0) {
  106. gpio_set_die(scl, en);
  107. gpio_set_die(sda, en);
  108. } else {
  109. //undefined
  110. }
  111. }
  112. void hw_iic_suspend(hw_iic_dev iic)
  113. {
  114. hw_iic_set_die(iic, 0);
  115. }
  116. void hw_iic_resume(hw_iic_dev iic)
  117. {
  118. hw_iic_set_die(iic, 1);
  119. }
  120. int hw_iic_init(hw_iic_dev iic)
  121. {
  122. int ret;
  123. u8 id = iic_get_id(iic);
  124. if ((ret = iic_port_init(iic))) {
  125. printf("invalid hardware iic port\n");
  126. return ret;
  127. }
  128. hw_iic_set_die(iic, 1);
  129. if (iic_info_role(iic) == IIC_MASTER) {
  130. iic_host_mode(iic_regs[id]);
  131. if ((ret = hw_iic_set_baud(iic, iic_info_baud(iic)))) {
  132. printf("iic baudrate is invalid\n");
  133. return ret ;
  134. }
  135. } else {
  136. iic_slave_mode(iic_regs[id]);
  137. iic_slave_scl_pull_down_enble(iic_regs[id]); //在收到/在发送数据时把SCL拉低
  138. iic_dir_in(iic_regs[id]);
  139. }
  140. if (iic_info_io_filt(iic)) {
  141. iic_isel_filter(iic_regs[id]);
  142. } else {
  143. iic_isel_direct(iic_regs[id]);
  144. }
  145. iic_auto_ack(iic_regs[id]);
  146. iic_int_disable(iic_regs[id]);
  147. iic_pnding_clr(iic_regs[id]);
  148. iic_enable(iic_regs[id]);
  149. /* iic_disable(iic_regs[id]); */
  150. #if 0
  151. printf("info->scl = %d\n", iic_get_scl(iic));
  152. printf("info->sda = %d\n", iic_get_sda(iic));
  153. printf("info->baudrate = %d\n", iic_info_baud(iic));
  154. printf("info->hdrive = %d\n", iic_info_hdrive(iic));
  155. printf("info->io_filter = %d\n", iic_info_io_filt(iic));
  156. printf("info->io_pu = %d\n", iic_info_io_pu(iic));
  157. printf("info->role = %d\n", iic_info_role(iic));
  158. printf("IIC_CON0 0x%04x\n", iic_regs[id]->CON0);
  159. printf("IIC_CON1 0x%04x\n", iic_regs[id]->CON1);
  160. printf("IIC_BAUD 0x%02x\n", iic_regs[id]->BAUD);
  161. //printf("IIC_BUF %02x\n", iic_regs[id]->BUF);
  162. printf("IOMC1 0x%08x\n", JL_IOMAP->CON1);
  163. #endif
  164. return 0;
  165. }
  166. void hw_iic_uninit(hw_iic_dev iic)
  167. {
  168. u8 id = iic_get_id(iic);
  169. u32 scl, sda;
  170. scl = iic_get_scl(iic);
  171. sda = iic_get_sda(iic);
  172. hw_iic_set_die(iic, 0);
  173. if (id == 0) {
  174. gpio_set_hd(scl, 0);
  175. gpio_set_hd(sda, 0);
  176. gpio_set_pull_up(scl, 0);
  177. gpio_set_pull_up(sda, 0);
  178. if (scl >= IO_PORT_DP || sda >= IO_PORT_DP) {
  179. usb_iomode(0);
  180. }
  181. }
  182. iic_disable(iic_regs[id]);
  183. }
  184. //必要的延时,两次通信之间至少20us
  185. static u8 start_signal = 0;
  186. static u8 end_signal = 0;
  187. void hw_iic_start(hw_iic_dev iic)
  188. {
  189. u8 id = iic_get_id(iic);
  190. /* iic_enable(iic_regs[id]); */
  191. start_signal |= BIT(7);
  192. start_signal++;
  193. if ((start_signal & 0x7f) == 2) {
  194. start_signal &= ~BIT(7);
  195. }
  196. }
  197. //必要的延时,两次通信之间至少20us
  198. void hw_iic_stop(hw_iic_dev iic)
  199. {
  200. u8 id = iic_get_id(iic);
  201. /* iic_disable(iic_regs[id]); */
  202. iic_host_send_stop(iic_regs[id]); //stop singal
  203. start_signal = 0;
  204. while (!iic_host_is_stop_pending(iic_regs[id]));
  205. }
  206. u8 hw_iic_tx_byte(hw_iic_dev iic, u8 byte)
  207. {
  208. u8 ack = 0;
  209. u8 id = iic_get_id(iic);
  210. iic_dir_out(iic_regs[id]);
  211. if ((start_signal & 0x7f) >= 2) { //连续两次起始信号则进入发送地址并接收模式
  212. iic_dir_in(iic_regs[id]);
  213. iic_host_receive_continue_byte(iic_regs[id]);
  214. iic_restart(iic_regs[id]);
  215. /* printf("rst/\n"); */
  216. }
  217. iic_buf_reg(iic_regs[id]) = byte;
  218. if (start_signal & BIT(7)) {
  219. iic_kick_start(iic_regs[id]); //kick start
  220. start_signal &= ~BIT(7);
  221. /* printf("st/\n"); */
  222. }
  223. while (!iic_is_pnding(iic_regs[id]));
  224. if (!iic_host_send_is_ack(iic_regs[id])) {
  225. ack = 1;
  226. }
  227. iic_pnding_clr(iic_regs[id]);
  228. return ack;
  229. }
  230. u8 hw_iic_rx_byte(hw_iic_dev iic, u8 ack)
  231. {
  232. u8 data = 0;
  233. u8 id = iic_get_id(iic);
  234. iic_dir_in(iic_regs[id]);
  235. iic_host_receive_continue_byte(iic_regs[id]);
  236. iic_host_read_kick_start(iic_regs[id]);
  237. if (ack) {
  238. } else {
  239. iic_host_nack_auto_stop(iic_regs[id]); //硬件检测到nack(这个nack是我们硬件发出的), 自动长生stop信号
  240. iic_host_receive_continue_byte_stop(iic_regs[id]); //最后1byte, 完成后自动nack;
  241. }
  242. while (!iic_is_pnding(iic_regs[id]));
  243. data = iic_buf_reg(iic_regs[id]);
  244. iic_pnding_clr(iic_regs[id]);
  245. return data;
  246. }
  247. int hw_iic_write_buf(hw_iic_dev iic, const void *buf, int len)
  248. {
  249. u8 id = iic_get_id(iic);
  250. int i = 0;
  251. if (!buf || !len) {
  252. return -1;
  253. }
  254. iic_dir_out(iic_regs[id]);
  255. for (i = 0; i < len; i++) {
  256. iic_buf_reg(iic_regs[id]) = ((u8 *)buf)[i];
  257. /* if (i == 0) { */
  258. /* iic_kick_start(iic_regs[id]); //kick start */
  259. /* } */
  260. while (!iic_is_pnding(iic_regs[id]));
  261. if (iic_host_send_is_ack(iic_regs[id])) {
  262. iic_pnding_clr(iic_regs[id]);
  263. break;
  264. }
  265. iic_pnding_clr(iic_regs[id]);
  266. }
  267. return i;
  268. }
  269. int hw_iic_read_buf(hw_iic_dev iic, void *buf, int len)
  270. {
  271. u8 id = iic_get_id(iic);
  272. int i;
  273. if (!buf || !len) {
  274. return -1;
  275. }
  276. iic_dir_in(iic_regs[id]);
  277. iic_host_receive_continue_byte(iic_regs[id]);
  278. for (i = 0; i < len; i++) {
  279. iic_host_read_kick_start(iic_regs[id]);
  280. if (i == len - 1) {
  281. iic_host_nack_auto_stop(iic_regs[id]); //硬件检测到nack(这个nack是我们硬件发出的), 自动长生stop信号
  282. iic_host_receive_continue_byte_stop(iic_regs[id]); //最后1byte, 完成后自动nack;
  283. }
  284. while (!iic_is_pnding(iic_regs[id]));
  285. iic_pnding_clr(iic_regs[id]);
  286. ((u8 *)buf)[i] = iic_buf_reg(iic_regs[id]);
  287. }
  288. return len;
  289. }
  290. void iic_disable_for_ota()
  291. {
  292. JL_IIC->CON0 = 0;
  293. }
  294. #endif