1 /*
2  * Copyright (C) 2015-2020 Alibaba Group Holding Limited
3  */
4 
5 #include "objects.h"
6 #include "PinNames.h"
7 #include "pinmap.h"
8 #include <drv/iic.h>
9 
10 static const PinMap CSI_PinMap_I2C_SCL[] = {
11     {PA_25,     (int32_t)I2C0_DEV,        PIN_DATA(PullUp, PINMUX_FUNCTION_I2C)},
12     {NC,        NC,            0}
13 };
14 
15 static const PinMap CSI_PinMap_I2C_SDA[] = {
16     {PA_26,     (int32_t)I2C0_DEV,        PIN_DATA(PullUp, PINMUX_FUNCTION_I2C)},
17     {NC,        NC,            0}
18 };
19 
csi_iic_init(csi_iic_t * iic,uint32_t idx)20 csi_error_t csi_iic_init(csi_iic_t *iic, uint32_t idx)
21 {
22     if(idx != 0)
23         return CSI_ERROR;
24 
25     if(!iic)
26         return CSI_ERROR;
27 
28     iic->priv = (I2C_InitTypeDef *)malloc(sizeof(I2C_InitTypeDef));
29 
30     uint32_t i2c_idx = idx;
31     I2C_TypeDef * I2Cx;
32     I2C_InitTypeDef *I2C_InitStruct = (I2C_InitTypeDef *)iic->priv;
33 
34     iic->dev.idx = i2c_idx;
35     iic->mode = I2C_MASTER_MODE;
36     I2Cx = I2C_DEV_TABLE[i2c_idx].I2Cx;
37 
38     /* Set I2C Device Number */
39     I2C_InitStruct->I2CIdx = i2c_idx;
40 
41     /* Load I2C default value */
42     I2C_StructInit(I2C_InitStruct);
43 
44     /* Assign I2C Pin Mux */
45     I2C_InitStruct->I2CMaster     = I2C_MASTER_MODE;
46     I2C_InitStruct->I2CSpdMod     = I2C_SS_MODE;
47     I2C_InitStruct->I2CClk        = 100;
48     I2C_InitStruct->I2CAckAddr    = 0;
49 
50     /* I2C Pin Mux Initialization */
51     PinName scl = CSI_PinMap_I2C_SCL[i2c_idx].pin;
52     PinName sda = CSI_PinMap_I2C_SDA[i2c_idx].pin;
53 
54     printf("scl:%d,sda:%d\n",scl,sda);
55 
56     Pinmux_Config(scl, PINMUX_FUNCTION_I2C);
57     Pinmux_Config(sda, PINMUX_FUNCTION_I2C);
58 
59     PAD_PullCtrl(scl, GPIO_PuPd_UP);
60     PAD_PullCtrl(sda, GPIO_PuPd_UP);
61 
62     /* I2C HAL Initialization */
63     I2C_Init(I2Cx, I2C_InitStruct);
64 
65     /* Enable i2c master RESTART function */
66     I2Cx->IC_CON |= BIT_CTRL_IC_CON_IC_RESTART_EN;
67     /* I2C Enable Module */
68     I2C_Cmd(I2Cx, ENABLE);
69     return CSI_OK;
70 }
71 
csi_iic_uninit(csi_iic_t * iic)72 void csi_iic_uninit(csi_iic_t *iic)
73 {
74     uint32_t i2c_idx = iic->dev.idx;
75 
76     if(i2c_idx != 0)
77         return;
78 
79     I2C_TypeDef * I2Cx = I2C_DEV_TABLE[i2c_idx].I2Cx;
80 
81     /* I2C Disable Module */
82     I2C_Cmd(I2Cx, DISABLE);
83 
84     if(iic && iic->priv) {
85         free(iic->priv);
86         iic->priv = NULL;
87     }
88 }
89 
csi_iic_mode(csi_iic_t * iic,csi_iic_mode_t mode)90 csi_error_t csi_iic_mode(csi_iic_t *iic, csi_iic_mode_t mode)
91 {
92     uint32_t i2c_idx = iic->dev.idx;
93 
94     if(i2c_idx != 0)
95         return CSI_ERROR;
96 
97     I2C_TypeDef *I2Cx = I2C_DEV_TABLE[i2c_idx].I2Cx;
98     I2C_InitTypeDef *I2C_InitStruct = (I2C_InitTypeDef *)iic->priv;
99 
100     I2C_Cmd(I2Cx, DISABLE);
101 
102     iic->mode = mode;
103 
104     if(mode == IIC_MODE_MASTER)
105         I2C_InitStruct->I2CMaster = I2C_MASTER_MODE;
106     else if(mode == IIC_MODE_SLAVE)
107         I2C_InitStruct->I2CMaster = I2C_SLAVE_MODE;
108 
109     I2C_Init(I2Cx, I2C_InitStruct);
110     I2C_Cmd(I2Cx, ENABLE);
111     return CSI_OK;
112 }
113 
csi_iic_addr_mode(csi_iic_t * iic,csi_iic_addr_mode_t addr_mode)114 csi_error_t csi_iic_addr_mode(csi_iic_t *iic, csi_iic_addr_mode_t addr_mode)
115 {
116     uint32_t i2c_idx = iic->dev.idx;
117 
118     if(i2c_idx != 0)
119         return CSI_ERROR;
120 
121     I2C_TypeDef * I2Cx = I2C_DEV_TABLE[i2c_idx].I2Cx;
122     I2C_InitTypeDef *I2C_InitStruct = (I2C_InitTypeDef *)iic->priv;
123 
124     I2C_Cmd(I2Cx, DISABLE);
125 
126     I2C_InitStruct->I2CAddrMod = addr_mode;
127     I2C_Init(I2Cx, I2C_InitStruct);
128 
129     I2C_Cmd(I2Cx, ENABLE);
130     return CSI_OK;
131 }
132 
csi_iic_speed(csi_iic_t * iic,csi_iic_speed_t speed)133 csi_error_t csi_iic_speed(csi_iic_t *iic, csi_iic_speed_t speed)
134 {
135     uint32_t i2c_idx = iic->dev.idx;
136 
137     if(i2c_idx != 0)
138         return CSI_ERROR;
139 
140     I2C_TypeDef * I2Cx = I2C_DEV_TABLE[i2c_idx].I2Cx;
141     I2C_InitTypeDef *I2C_InitStruct = (I2C_InitTypeDef *)iic->priv;
142 
143     I2C_Cmd(I2Cx, DISABLE);
144 
145     switch(speed) {
146         case IIC_BUS_SPEED_STANDARD:
147             I2C_InitStruct->I2CSpdMod = I2C_SS_MODE;
148             I2C_InitStruct->I2CClk = 100;
149         break;
150         case IIC_BUS_SPEED_FAST:
151             I2C_InitStruct->I2CSpdMod = I2C_FS_MODE;
152             I2C_InitStruct->I2CClk = 400;
153         break;
154         case IIC_BUS_SPEED_FAST_PLUS:
155         case IIC_BUS_SPEED_HIGH:
156             I2C_InitStruct->I2CSpdMod = I2C_HS_MODE;
157             I2C_InitStruct->I2CClk = 1000;
158         break;
159         default:
160             I2C_InitStruct->I2CSpdMod = I2C_SS_MODE;
161             I2C_InitStruct->I2CClk = 100;
162     }
163     I2C_Init(I2Cx, I2C_InitStruct);
164     I2C_Cmd(I2Cx, ENABLE);
165     return CSI_OK;
166 }
167 
168 /**
169   * @brief  Read data with special length in master mode through the I2Cx peripheral under in-house IP.
170   * @param  I2Cx: where I2Cx can be I2C0_DEV .
171   * @param  pBuf: point to the buffer to hold the received data.
172   * @param  len: the length of data that to be received.
173   * @param  timeout_ms: specifies timeout time, unit is ms.
174   * @retval the length of data read.
175   */
I2C_MasterRead_TimeOut(I2C_TypeDef * I2Cx,uint8_t * pBuf,uint8_t len,uint32_t timeout_ms)176 int32_t I2C_MasterRead_TimeOut(I2C_TypeDef *I2Cx, uint8_t* pBuf, uint8_t len, uint32_t timeout_ms)
177 {
178     int32_t cnt = 0;
179     uint32_t InTimeoutCount = 0;
180 
181     /* read in the DR register the data to be received */
182     for(cnt = 0; cnt < len; cnt++) {
183         InTimeoutCount = timeout_ms*500;
184 
185         if(cnt >= len - 1) {
186             /* generate stop singal */
187             I2Cx->IC_DATA_CMD = 0x0003 << 8;
188         } else {
189             I2Cx->IC_DATA_CMD = 0x0001 << 8;
190         }
191 
192         /* wait for I2C_FLAG_RFNE flag */
193         while((I2C_CheckFlagState(I2Cx, BIT_IC_STATUS_RFNE)) == 0) {
194             if(I2C_GetRawINT(I2Cx) & BIT_IC_RAW_INTR_STAT_TX_ABRT) {
195                 I2C_ClearAllINT(I2Cx);
196                 return cnt;
197             }
198 
199             DelayUs(2);
200 
201             if (InTimeoutCount == 0) {
202                 printf("MasterRead_TimeOut\n");
203                 return cnt;
204             }
205             InTimeoutCount--;
206         }
207 
208         *pBuf++ = (uint8_t)I2Cx->IC_DATA_CMD;
209     }
210 
211     return cnt;
212 }
213 
214 /**
215   * @brief  Write data with special length in master mode through the I2Cx peripheral under in-house IP.
216   * @param  I2Cx: where I2Cx can be I2C0_DEV.
217   * @param  pBuf: point to the data to be transmitted.
218   * @param  len: the length of data that to be received.
219   * @param  timeout_ms: specifies timeout time, unit is ms.
220   * @retval the length of data send.
221   */
I2C_MasterWrite_TimeOut(I2C_TypeDef * I2Cx,uint8_t * pBuf,uint8_t len,uint32_t timeout_ms,int32_t stop)222 int32_t I2C_MasterWrite_TimeOut(I2C_TypeDef *I2Cx, uint8_t* pBuf, uint8_t len, uint32_t timeout_ms, int32_t stop)
223 {
224     int32_t cnt = 0;
225     uint32_t InTimeoutCount = 0;
226 
227     /* Write in the DR register the data to be sent */
228     for(cnt = 0; cnt < len; cnt++)
229     {
230         InTimeoutCount = timeout_ms*500;
231 
232         while((I2C_CheckFlagState(I2Cx, BIT_IC_STATUS_TFNF)) == 0);
233 
234         if(cnt >= len - 1)
235         {
236             if(stop == 1) {
237                 /*generate stop signal*/
238                 I2Cx->IC_DATA_CMD = (*pBuf++) | (1 << 9);
239             } else {
240                 /*generate restart signal*/
241                 I2Cx->IC_DATA_CMD = (*pBuf++) | (1 << 10);
242             }
243         }
244         else
245         {
246             I2Cx->IC_DATA_CMD = (*pBuf++);
247         }
248 
249         while((I2C_CheckFlagState(I2Cx, BIT_IC_STATUS_TFE)) == 0) {
250             if(I2C_GetRawINT(I2Cx) & BIT_IC_RAW_INTR_STAT_TX_ABRT) {
251                 printf(" TX_ABRT = %x\n", I2Cx->IC_TX_ABRT_SOURCE);
252                 I2C_ClearAllINT(I2Cx);
253                 return cnt;
254             }
255 
256             DelayUs(2);
257 
258             if (InTimeoutCount == 0) {
259                 printf("MasterWrite_TimeOut\n");
260                 return cnt;
261             }
262             InTimeoutCount--;
263         }
264     }
265 
266     return cnt;
267 }
268 
269 /**
270   * @brief  Master sends single byte through the I2Cx peripheral to detect slave device.
271   * @param  obj: i2c object defined in application software.
272   * @param  address: the address of slave that to be detected.
273   * @param  timeout_ms: specifies timeout time, unit is ms.
274   * @retval Slave ack condition:
275   *          - 0: Slave available
276   *          - -1: Slave not available
277   */
I2C_MasterSendNullData_TimeOut(I2C_TypeDef * I2Cx,int32_t address,uint32_t timeout_ms)278 int32_t I2C_MasterSendNullData_TimeOut(I2C_TypeDef *I2Cx, int32_t address, uint32_t timeout_ms)
279 {
280     uint8_t I2CTemp = (uint8_t)(address<<1);
281     I2C_MasterSendNullData(I2Cx, &I2CTemp, 0, 1, 0);
282 
283     DelayMs(timeout_ms);
284 
285     if(I2C_GetRawINT(I2Cx) & BIT_IC_RAW_INTR_STAT_TX_ABRT) {
286         I2C_ClearAllINT(I2Cx);
287 
288         /* Wait for i2c enter trap state from trap_stop state*/
289         DelayUs(100);
290         I2C_Cmd(I2Cx, DISABLE);
291         I2C_Cmd(I2Cx, ENABLE);
292 
293         return CSI_ERROR;
294     }
295     return CSI_OK;
296 }
297 
csi_iic_master_send(csi_iic_t * iic,uint32_t devaddr,const void * data,uint32_t size,uint32_t timeout)298 int32_t csi_iic_master_send(csi_iic_t *iic,uint32_t devaddr,const void *data,uint32_t size,uint32_t timeout)
299 {
300     uint32_t i2c_idx = iic->dev.idx;
301 
302     if(i2c_idx != 0)
303         return CSI_ERROR;
304 
305     I2C_TypeDef * I2Cx = I2C_DEV_TABLE[i2c_idx].I2Cx;
306     I2C_InitTypeDef *I2C_InitStruct = (I2C_InitTypeDef *)iic->priv;
307 
308     /* Check the parameters */
309     if(!IS_I2C_ALL_PERIPH(I2Cx))
310         return CSI_ERROR;
311 
312     if (I2C_InitStruct->I2CAckAddr != devaddr) {
313         /* Deinit I2C first */
314         I2C_Cmd(I2Cx, DISABLE);
315 
316         /* Load the user defined I2C target slave address */
317         I2C_InitStruct->I2CAckAddr = devaddr;
318 
319         /* Init I2C now */
320         I2C_Init(I2Cx, I2C_InitStruct);
321         I2C_Cmd(I2Cx, ENABLE);
322     }
323 
324     if(!size) {
325         return (I2C_MasterSendNullData_TimeOut(I2Cx, devaddr, timeout));
326     }
327 
328     return (I2C_MasterWrite_TimeOut(I2Cx, (uint8_t*)data, size,timeout, 1));
329 }
330 
csi_iic_master_receive(csi_iic_t * iic,uint32_t devaddr,void * data,uint32_t size,uint32_t timeout)331 int32_t csi_iic_master_receive(csi_iic_t *iic, uint32_t devaddr, void *data, uint32_t size, uint32_t timeout)
332 {
333     uint32_t i2c_idx = iic->dev.idx;
334 
335     if(i2c_idx != 0)
336         return CSI_ERROR;
337 
338     I2C_TypeDef * I2Cx = I2C_DEV_TABLE[i2c_idx].I2Cx;
339     I2C_InitTypeDef *I2C_InitStruct = (I2C_InitTypeDef *)iic->priv;
340 
341     /* Check the parameters */
342     if(!IS_I2C_ALL_PERIPH(I2Cx))
343         return CSI_ERROR;
344 
345     if (I2C_InitStruct->I2CAckAddr != devaddr) {
346         /* Deinit I2C first */
347         I2C_Cmd(I2Cx, DISABLE);
348 
349         /* Load the user defined I2C target slave address */
350         I2C_InitStruct->I2CAckAddr = devaddr;
351 
352         /* Init I2C now */
353         I2C_Init(I2Cx, I2C_InitStruct);
354         I2C_Cmd(I2Cx, ENABLE);
355     }
356     return (I2C_MasterRead_TimeOut(I2Cx, (uint8_t*)data, size,timeout));
357 }
358 
csi_iic_mem_send(csi_iic_t * iic,uint32_t devaddr,uint16_t memaddr,csi_iic_mem_addr_size_t memaddr_size,const void * data,uint32_t size,uint32_t timeout)359 int32_t csi_iic_mem_send(csi_iic_t *iic, uint32_t devaddr,uint16_t memaddr, csi_iic_mem_addr_size_t memaddr_size,const void *data,uint32_t size,uint32_t timeout)
360 {
361     uint32_t i = 0;
362     int cnt = 0;
363     uint32_t i2c_idx = iic->dev.idx;
364     uint32_t mem_size;
365     char *buf = NULL;
366 
367     if(i2c_idx != 0)
368         return CSI_ERROR;
369 
370     buf = malloc(memaddr_size + size);
371     if(!buf) {
372         printf("malloc for i2c mem send fail\r\n");
373         return CSI_ERROR;
374     }
375 
376     I2C_TypeDef * I2Cx = I2C_DEV_TABLE[i2c_idx].I2Cx;
377     I2C_InitTypeDef *I2C_InitStruct = (I2C_InitTypeDef *)iic->priv;
378 
379     switch(memaddr_size) {
380         case IIC_MEM_ADDR_SIZE_8BIT:
381             mem_size = 1;
382             break;
383         case IIC_MEM_ADDR_SIZE_16BIT:
384             mem_size = 2;
385             break;
386         default:
387             mem_size = 1;
388             break;
389     }
390 
391     /* Check the parameters */
392     if(!IS_I2C_ALL_PERIPH(I2Cx)) {
393         free(buf);
394         buf = NULL;
395         return CSI_ERROR;
396     }
397 
398     if (I2C_InitStruct->I2CAckAddr != devaddr) {
399         /* Deinit I2C first */
400         I2C_Cmd(I2Cx, DISABLE);
401 
402         /* Load the user defined I2C target slave address */
403         I2C_InitStruct->I2CAckAddr = devaddr;
404 
405         /* Init I2C now */
406         I2C_Init(I2Cx, I2C_InitStruct);
407         I2C_Cmd(I2Cx, ENABLE);
408     }
409 
410     if (mem_size == 1) {
411 	    buf[i++] = (memaddr) & 0xFF;
412     } else
413         buf[i++] = (memaddr >> 8) & 0xFF;
414 
415     memcpy(&buf[i], data, size);
416 
417     cnt = I2C_MasterWrite_TimeOut(I2Cx, (uint8_t*)buf, mem_size + size, timeout, 1);
418     free(buf);
419     buf = NULL;
420 
421     if (cnt == (mem_size + size))
422         return size;
423     else
424         return cnt;
425 }
426 
csi_iic_mem_receive(csi_iic_t * iic,uint32_t devaddr,uint16_t memaddr,csi_iic_mem_addr_size_t memaddr_size,void * data,uint32_t size,uint32_t timeout)427 int32_t csi_iic_mem_receive(csi_iic_t *iic,uint32_t devaddr, uint16_t memaddr,csi_iic_mem_addr_size_t memaddr_size,void *data,uint32_t size,uint32_t timeout)
428 {
429     int cnt = 0;
430     uint32_t i2c_idx = iic->dev.idx;
431     uint32_t mem_size;
432 
433     if(i2c_idx != 0)
434         return CSI_ERROR;
435 
436     I2C_TypeDef * I2Cx = I2C_DEV_TABLE[i2c_idx].I2Cx;
437     I2C_InitTypeDef *I2C_InitStruct = (I2C_InitTypeDef *)iic->priv;
438 
439     uint8_t memaddr_t[2];
440     memaddr_t[0] = (memaddr) & 0xFF;
441     memaddr_t[1] = (memaddr >> 8) & 0xFF;
442 
443     switch(memaddr_size) {
444         case IIC_MEM_ADDR_SIZE_8BIT:
445             mem_size = 1;
446             break;
447         case IIC_MEM_ADDR_SIZE_16BIT:
448             mem_size = 2;
449             break;
450         default:
451             mem_size = 1;
452             break;
453     }
454 
455     /* Check the parameters */
456     if(!IS_I2C_ALL_PERIPH(I2Cx))
457         return CSI_ERROR;
458 
459     if (I2C_InitStruct->I2CAckAddr != devaddr) {
460         /* Deinit I2C first */
461         I2C_Cmd(I2Cx, DISABLE);
462 
463         /* Load the user defined I2C target slave address */
464         I2C_InitStruct->I2CAckAddr = devaddr;
465 
466         /* Init I2C now */
467         I2C_Init(I2Cx, I2C_InitStruct);
468         I2C_Cmd(I2Cx, ENABLE);
469     }
470 
471     cnt = I2C_MasterWrite_TimeOut(I2Cx, memaddr_t, mem_size, timeout, 0);
472     cnt = I2C_MasterRead_TimeOut(I2Cx, (uint8_t *)data, size, timeout);
473     return cnt;
474 }
475