i2c.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. /* Copyright 2018 Canaan Inc.
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. #include <stddef.h>
  16. #include "bsp.h"
  17. #include "fpioa.h"
  18. #include "i2c.h"
  19. #include "platform.h"
  20. #include "stdlib.h"
  21. #include "string.h"
  22. #include "sysctl.h"
  23. #include "utils.h"
  24. #include "iomem.h"
  25. typedef struct _i2c_slave_instance
  26. {
  27. uint32_t i2c_num;
  28. const i2c_slave_handler_t *slave_handler;
  29. } i2c_slave_instance_t;
  30. static i2c_slave_instance_t slave_instance[I2C_MAX_NUM];
  31. typedef struct _i2c_instance
  32. {
  33. i2c_device_number_t i2c_num;
  34. i2c_transfer_mode_t transfer_mode;
  35. dmac_channel_number_t dmac_channel;
  36. plic_instance_t i2c_int_instance;
  37. spinlock_t lock;
  38. } i2c_instance_t;
  39. static i2c_instance_t g_i2c_instance[3];
  40. volatile i2c_t *const i2c[3] =
  41. {
  42. (volatile i2c_t *)I2C0_BASE_ADDR,
  43. (volatile i2c_t *)I2C1_BASE_ADDR,
  44. (volatile i2c_t *)I2C2_BASE_ADDR};
  45. static void i2c_clk_init(i2c_device_number_t i2c_num)
  46. {
  47. configASSERT(i2c_num < I2C_MAX_NUM);
  48. sysctl_clock_enable(SYSCTL_CLOCK_I2C0 + i2c_num);
  49. sysctl_clock_set_threshold(SYSCTL_THRESHOLD_I2C0 + i2c_num, 3);
  50. }
  51. void i2c_init(i2c_device_number_t i2c_num, uint32_t slave_address, uint32_t address_width,
  52. uint32_t i2c_clk)
  53. {
  54. configASSERT(i2c_num < I2C_MAX_NUM);
  55. configASSERT(address_width == 7 || address_width == 10);
  56. volatile i2c_t *i2c_adapter = i2c[i2c_num];
  57. i2c_clk_init(i2c_num);
  58. uint32_t v_i2c_freq = sysctl_clock_get_freq(SYSCTL_CLOCK_I2C0 + i2c_num);
  59. uint16_t v_period_clk_cnt = v_i2c_freq / i2c_clk / 2;
  60. if(v_period_clk_cnt == 0)
  61. v_period_clk_cnt = 1;
  62. i2c_adapter->enable = 0;
  63. i2c_adapter->con = I2C_CON_MASTER_MODE | I2C_CON_SLAVE_DISABLE | I2C_CON_RESTART_EN |
  64. (address_width == 10 ? I2C_CON_10BITADDR_SLAVE : 0) | I2C_CON_SPEED(1);
  65. i2c_adapter->ss_scl_hcnt = I2C_SS_SCL_HCNT_COUNT(v_period_clk_cnt);
  66. i2c_adapter->ss_scl_lcnt = I2C_SS_SCL_LCNT_COUNT(v_period_clk_cnt);
  67. i2c_adapter->tar = I2C_TAR_ADDRESS(slave_address);
  68. i2c_adapter->intr_mask = 0;
  69. i2c_adapter->dma_cr = 0x3;
  70. i2c_adapter->dma_rdlr = 0;
  71. i2c_adapter->dma_tdlr = 4;
  72. i2c_adapter->enable = I2C_ENABLE_ENABLE;
  73. }
  74. static int i2c_slave_irq(void *userdata)
  75. {
  76. i2c_slave_instance_t *instance = (i2c_slave_instance_t *)userdata;
  77. volatile i2c_t *i2c_adapter = i2c[instance->i2c_num];
  78. uint32_t status = i2c_adapter->intr_stat;
  79. if(status & I2C_INTR_STAT_START_DET)
  80. {
  81. instance->slave_handler->on_event(I2C_EV_START);
  82. readl(&i2c_adapter->clr_start_det);
  83. }
  84. if(status & I2C_INTR_STAT_STOP_DET)
  85. {
  86. instance->slave_handler->on_event(I2C_EV_STOP);
  87. readl(&i2c_adapter->clr_stop_det);
  88. }
  89. if(status & I2C_INTR_STAT_RX_FULL)
  90. {
  91. instance->slave_handler->on_receive(i2c_adapter->data_cmd);
  92. }
  93. if(status & I2C_INTR_STAT_RD_REQ)
  94. {
  95. i2c_adapter->data_cmd = instance->slave_handler->on_transmit();
  96. readl(&i2c_adapter->clr_rd_req);
  97. }
  98. return 0;
  99. }
  100. void i2c_init_as_slave(i2c_device_number_t i2c_num, uint32_t slave_address, uint32_t address_width,
  101. const i2c_slave_handler_t *handler)
  102. {
  103. configASSERT(address_width == 7 || address_width == 10);
  104. volatile i2c_t *i2c_adapter = i2c[i2c_num];
  105. slave_instance[i2c_num].i2c_num = i2c_num;
  106. slave_instance[i2c_num].slave_handler = handler;
  107. i2c_clk_init(i2c_num);
  108. i2c_adapter->enable = 0;
  109. i2c_adapter->con = (address_width == 10 ? I2C_CON_10BITADDR_SLAVE : 0) | I2C_CON_SPEED(1) | I2C_CON_STOP_DET_IFADDRESSED;
  110. i2c_adapter->ss_scl_hcnt = I2C_SS_SCL_HCNT_COUNT(37);
  111. i2c_adapter->ss_scl_lcnt = I2C_SS_SCL_LCNT_COUNT(40);
  112. i2c_adapter->sar = I2C_SAR_ADDRESS(slave_address);
  113. i2c_adapter->rx_tl = I2C_RX_TL_VALUE(0);
  114. i2c_adapter->tx_tl = I2C_TX_TL_VALUE(0);
  115. i2c_adapter->intr_mask = I2C_INTR_MASK_RX_FULL | I2C_INTR_MASK_START_DET | I2C_INTR_MASK_STOP_DET | I2C_INTR_MASK_RD_REQ;
  116. plic_set_priority(IRQN_I2C0_INTERRUPT + i2c_num, 1);
  117. plic_irq_register(IRQN_I2C0_INTERRUPT + i2c_num, i2c_slave_irq, slave_instance + i2c_num);
  118. plic_irq_enable(IRQN_I2C0_INTERRUPT + i2c_num);
  119. i2c_adapter->enable = I2C_ENABLE_ENABLE;
  120. }
  121. int i2c_send_data(i2c_device_number_t i2c_num, const uint8_t *send_buf, size_t send_buf_len)
  122. {
  123. configASSERT(i2c_num < I2C_MAX_NUM);
  124. volatile i2c_t *i2c_adapter = i2c[i2c_num];
  125. size_t fifo_len, index;
  126. i2c_adapter->clr_tx_abrt = i2c_adapter->clr_tx_abrt;
  127. while(send_buf_len)
  128. {
  129. fifo_len = 8 - i2c_adapter->txflr;
  130. fifo_len = send_buf_len < fifo_len ? send_buf_len : fifo_len;
  131. for(index = 0; index < fifo_len; index++)
  132. i2c_adapter->data_cmd = I2C_DATA_CMD_DATA(*send_buf++);
  133. if(i2c_adapter->tx_abrt_source != 0)
  134. return 1;
  135. send_buf_len -= fifo_len;
  136. }
  137. while((i2c_adapter->status & I2C_STATUS_ACTIVITY) || !(i2c_adapter->status & I2C_STATUS_TFE))
  138. ;
  139. if(i2c_adapter->tx_abrt_source != 0)
  140. return 1;
  141. return 0;
  142. }
  143. void i2c_send_data_dma(dmac_channel_number_t dma_channel_num, i2c_device_number_t i2c_num, const uint8_t *send_buf,
  144. size_t send_buf_len)
  145. {
  146. configASSERT(i2c_num < I2C_MAX_NUM);
  147. volatile i2c_t *i2c_adapter = i2c[i2c_num];
  148. i2c_adapter->clr_tx_abrt = i2c_adapter->clr_tx_abrt;
  149. #if FIX_CACHE
  150. uint32_t *buf = iomem_malloc(send_buf_len * sizeof(uint32_t));
  151. #else
  152. uint32_t *buf = malloc(send_buf_len * sizeof(uint32_t));
  153. #endif
  154. int i;
  155. for(i = 0; i < send_buf_len; i++)
  156. {
  157. buf[i] = send_buf[i];
  158. }
  159. sysctl_dma_select((sysctl_dma_channel_t)dma_channel_num, SYSCTL_DMA_SELECT_I2C0_TX_REQ + i2c_num * 2);
  160. dmac_set_single_mode(dma_channel_num, buf, (void *)(&i2c_adapter->data_cmd), DMAC_ADDR_INCREMENT, DMAC_ADDR_NOCHANGE,
  161. DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, send_buf_len);
  162. dmac_wait_done(dma_channel_num);
  163. #if FIX_CACHE
  164. iomem_free((void *)buf);
  165. #else
  166. free((void *)buf);
  167. #endif
  168. while((i2c_adapter->status & I2C_STATUS_ACTIVITY) || !(i2c_adapter->status & I2C_STATUS_TFE))
  169. {
  170. if(i2c_adapter->tx_abrt_source != 0)
  171. return;
  172. }
  173. }
  174. int i2c_recv_data(i2c_device_number_t i2c_num, const uint8_t *send_buf, size_t send_buf_len, uint8_t *receive_buf,
  175. size_t receive_buf_len)
  176. {
  177. configASSERT(i2c_num < I2C_MAX_NUM);
  178. size_t fifo_len, index;
  179. size_t rx_len = receive_buf_len;
  180. volatile i2c_t *i2c_adapter = i2c[i2c_num];
  181. while(send_buf_len)
  182. {
  183. fifo_len = 8 - i2c_adapter->txflr;
  184. fifo_len = send_buf_len < fifo_len ? send_buf_len : fifo_len;
  185. for(index = 0; index < fifo_len; index++)
  186. i2c_adapter->data_cmd = I2C_DATA_CMD_DATA(*send_buf++);
  187. if(i2c_adapter->tx_abrt_source != 0)
  188. return 1;
  189. send_buf_len -= fifo_len;
  190. }
  191. while(receive_buf_len || rx_len)
  192. {
  193. fifo_len = i2c_adapter->rxflr;
  194. fifo_len = rx_len < fifo_len ? rx_len : fifo_len;
  195. for(index = 0; index < fifo_len; index++)
  196. *receive_buf++ = (uint8_t)i2c_adapter->data_cmd;
  197. rx_len -= fifo_len;
  198. fifo_len = 8 - i2c_adapter->txflr;
  199. fifo_len = receive_buf_len < fifo_len ? receive_buf_len : fifo_len;
  200. for(index = 0; index < fifo_len; index++)
  201. i2c_adapter->data_cmd = I2C_DATA_CMD_CMD;
  202. if(i2c_adapter->tx_abrt_source != 0)
  203. return 1;
  204. receive_buf_len -= fifo_len;
  205. }
  206. return 0;
  207. }
  208. void i2c_recv_data_dma(dmac_channel_number_t dma_send_channel_num, dmac_channel_number_t dma_receive_channel_num,
  209. i2c_device_number_t i2c_num, const uint8_t *send_buf, size_t send_buf_len,
  210. uint8_t *receive_buf, size_t receive_buf_len)
  211. {
  212. configASSERT(i2c_num < I2C_MAX_NUM);
  213. volatile i2c_t *i2c_adapter = i2c[i2c_num];
  214. #if FIX_CACHE
  215. uint32_t *write_cmd = iomem_malloc(sizeof(uint32_t) * (send_buf_len + receive_buf_len));
  216. #else
  217. uint32_t *write_cmd = malloc(sizeof(uint32_t) * (send_buf_len + receive_buf_len));
  218. #endif
  219. size_t i;
  220. for(i = 0; i < send_buf_len; i++)
  221. write_cmd[i] = *send_buf++;
  222. for(i = 0; i < receive_buf_len; i++)
  223. write_cmd[i + send_buf_len] = I2C_DATA_CMD_CMD;
  224. sysctl_dma_select((sysctl_dma_channel_t)dma_send_channel_num, SYSCTL_DMA_SELECT_I2C0_TX_REQ + i2c_num * 2);
  225. sysctl_dma_select((sysctl_dma_channel_t)dma_receive_channel_num, SYSCTL_DMA_SELECT_I2C0_RX_REQ + i2c_num * 2);
  226. dmac_set_single_mode(dma_receive_channel_num, (void *)(&i2c_adapter->data_cmd), write_cmd, DMAC_ADDR_NOCHANGE,
  227. DMAC_ADDR_INCREMENT, DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, receive_buf_len);
  228. dmac_set_single_mode(dma_send_channel_num, write_cmd, (void *)(&i2c_adapter->data_cmd), DMAC_ADDR_INCREMENT,
  229. DMAC_ADDR_NOCHANGE, DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, receive_buf_len + send_buf_len);
  230. dmac_wait_done(dma_send_channel_num);
  231. dmac_wait_done(dma_receive_channel_num);
  232. for(i = 0; i < receive_buf_len; i++)
  233. {
  234. receive_buf[i] = (uint8_t)write_cmd[i];
  235. }
  236. #if FIX_CACHE
  237. iomem_free(write_cmd);
  238. #else
  239. free(write_cmd);
  240. #endif
  241. }
  242. static int i2c_dma_irq(void *ctx)
  243. {
  244. i2c_instance_t *v_instance = (i2c_instance_t *)ctx;
  245. volatile i2c_t *i2c_adapter = i2c[v_instance->i2c_num];
  246. dmac_irq_unregister(v_instance->dmac_channel);
  247. if(v_instance->transfer_mode == I2C_SEND)
  248. {
  249. while((i2c_adapter->status & I2C_STATUS_ACTIVITY) || !(i2c_adapter->status & I2C_STATUS_TFE))
  250. {
  251. if(i2c_adapter->tx_abrt_source != 0)
  252. {
  253. spinlock_unlock(&v_instance->lock);
  254. return -1;
  255. }
  256. }
  257. }
  258. spinlock_unlock(&v_instance->lock);
  259. if(v_instance->i2c_int_instance.callback)
  260. {
  261. v_instance->i2c_int_instance.callback(v_instance->i2c_int_instance.ctx);
  262. }
  263. return 0;
  264. }
  265. void i2c_handle_data_dma(i2c_device_number_t i2c_num, i2c_data_t data, plic_interrupt_t *cb)
  266. {
  267. configASSERT(i2c_num < I2C_MAX_NUM);
  268. configASSERT(data.tx_channel < DMAC_CHANNEL_MAX && data.rx_channel < DMAC_CHANNEL_MAX);
  269. spinlock_lock(&g_i2c_instance[i2c_num].lock);
  270. if(cb)
  271. {
  272. g_i2c_instance[i2c_num].i2c_int_instance.callback = cb->callback;
  273. g_i2c_instance[i2c_num].i2c_int_instance.ctx = cb->ctx;
  274. }
  275. volatile i2c_t *i2c_adapter = i2c[i2c_num];
  276. if(data.transfer_mode == I2C_SEND)
  277. {
  278. configASSERT(data.tx_buf && data.tx_len);
  279. i2c_adapter->clr_tx_abrt = i2c_adapter->clr_tx_abrt;
  280. if(cb)
  281. {
  282. g_i2c_instance[i2c_num].dmac_channel = data.tx_channel;
  283. g_i2c_instance[i2c_num].transfer_mode = I2C_SEND;
  284. dmac_irq_register(data.tx_channel, i2c_dma_irq, &g_i2c_instance[i2c_num], cb->priority);
  285. }
  286. sysctl_dma_select((sysctl_dma_channel_t)data.tx_channel, SYSCTL_DMA_SELECT_I2C0_TX_REQ + i2c_num * 2);
  287. dmac_set_single_mode(data.tx_channel, data.tx_buf, (void *)(&i2c_adapter->data_cmd), DMAC_ADDR_INCREMENT, DMAC_ADDR_NOCHANGE,
  288. DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, data.tx_len);
  289. if(!cb)
  290. {
  291. dmac_wait_done(data.tx_channel);
  292. while((i2c_adapter->status & I2C_STATUS_ACTIVITY) || !(i2c_adapter->status & I2C_STATUS_TFE))
  293. {
  294. if(i2c_adapter->tx_abrt_source != 0)
  295. configASSERT(!"source abort");
  296. }
  297. }
  298. } else
  299. {
  300. configASSERT(data.rx_buf && data.rx_len);
  301. if(data.tx_len)
  302. configASSERT(data.tx_buf);
  303. if(cb)
  304. {
  305. g_i2c_instance[i2c_num].dmac_channel = data.rx_channel;
  306. g_i2c_instance[i2c_num].transfer_mode = I2C_RECEIVE;
  307. dmac_irq_register(data.rx_channel, i2c_dma_irq, &g_i2c_instance[i2c_num], cb->priority);
  308. }
  309. sysctl_dma_select((sysctl_dma_channel_t)data.rx_channel, SYSCTL_DMA_SELECT_I2C0_RX_REQ + i2c_num * 2);
  310. dmac_set_single_mode(data.rx_channel, (void *)(&i2c_adapter->data_cmd), data.rx_buf, DMAC_ADDR_NOCHANGE,
  311. DMAC_ADDR_INCREMENT, DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, data.rx_len);
  312. sysctl_dma_select((sysctl_dma_channel_t)data.tx_channel, SYSCTL_DMA_SELECT_I2C0_TX_REQ + i2c_num * 2);
  313. if(data.tx_len)
  314. {
  315. configASSERT(data.tx_buf);
  316. dmac_set_single_mode(data.tx_channel, data.tx_buf, (void *)(&i2c_adapter->data_cmd), DMAC_ADDR_INCREMENT,
  317. DMAC_ADDR_NOCHANGE, DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, data.tx_len);
  318. dmac_wait_done(data.tx_channel);
  319. }
  320. static uint32_t s_read_cmd = I2C_DATA_CMD_CMD;
  321. dmac_set_single_mode(data.tx_channel, &s_read_cmd, (void *)(&i2c_adapter->data_cmd), DMAC_ADDR_NOCHANGE,
  322. DMAC_ADDR_NOCHANGE, DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, data.rx_len);
  323. if(!cb)
  324. {
  325. dmac_wait_done(data.tx_channel);
  326. dmac_wait_done(data.rx_channel);
  327. }
  328. }
  329. if(!cb)
  330. spinlock_unlock(&g_i2c_instance[i2c_num].lock);
  331. }