1 /******************************************************************************
\r
2 ** File Name: i2c_drv.c *
\r
3 ** Author: Richard Yang *
\r
4 ** DATE: 01/16/2001 *
\r
5 ** Copyright: 2002 Spreatrum, Incoporated. All Rights Reserved. *
\r
6 ** Description: This file defines the basic operation interfaces of *
\r
7 ** serrial device. It manages create, send, receive *
\r
8 ** interface of serrial port. *
\r
9 ******************************************************************************
\r
11 ******************************************************************************
\r
13 ** ------------------------------------------------------------------------- *
\r
14 ** DATE NAME DESCRIPTION *
\r
15 ** 01/16/2001 Richard.Yang Create. *
\r
16 ** 04/02/2002 Lin.Liu Code *
\r
17 ** 04/22/2002 Lin.liu Set CPC_ZD_WPU after change clock. *
\r
18 ** 04/23/2002 Lin.liu 1. Remove i2c_clk to i2c_drv.h *
\r
19 ** 2. Remove i2c_inited flag *
\r
20 ******************************************************************************/
\r
22 /**---------------------------------------------------------------------------*
\r
24 **---------------------------------------------------------------------------*/
\r
25 #include <asm/arch/sci_types.h>
\r
26 #include <asm/arch/os_api.h>
\r
27 #include <asm/arch/i2c_phy.h>
\r
28 #include <asm/arch/i2c_reg_v0.h>
\r
29 #include <asm/arch/chip_drvapi.h>
\r
30 #include <asm/arch/chip_plf_export.h>
\r
31 #include <asm/arch/sc8810_reg_global.h>
\r
32 #include <asm/arch/sc8810_reg_base.h>
\r
33 //#define I2C_BASE I2C0_BASE
\r
35 //#include "dcam_fpga_misc.h"
\r
41 /**---------------------------------------------------------------------------*
\r
43 **---------------------------------------------------------------------------*/
\r
44 /**---------------------------------------------------------------------------*
\r
46 **---------------------------------------------------------------------------*/
\r
54 /**---------------------------------------------------------------------------*
\r
56 **---------------------------------------------------------------------------*/
\r
58 #define I2C_TIMEOUT_FACTOR 500000 //the critical value is 10000
\r
60 #define ARM_CLK_13M 13000000
\r
61 #define ARM_CLK_24M 24000000
\r
64 #define I2C_READ_BIT 0x1
\r
66 //#define I2C_USE_INT
\r
68 #ifndef I2C_USE_INT
\r
70 #define I2C_WAIT_INT \
\r
72 timetick = SYSTEM_CURRENT_CLOCK; \
\r
73 while(!(ptr->ctl & I2CCTL_INT)) \
\r
75 if((SYSTEM_CURRENT_CLOCK - timetick) >= g_i2c_timeout) \
\r
77 if(ERR_I2C_NONE == ret_value) \
\r
79 ret_value = ERR_I2C_INT_TIMEOUT; \
\r
90 #define I2C_WAIT_INT \
\r
92 timetick = SYSTEM_CURRENT_CLOCK; \
\r
93 while (g_wait_i2c_int_flag) \
\r
95 if ((SYSTEM_CURRENT_CLOCK - timetick) >= g_i2c_timeout) \
\r
97 if(ERR_I2C_NONE == ret_value) \
\r
99 ret_value = ERR_I2C_INT_TIMEOUT; \
\r
104 g_wait_i2c_int_flag = 1; \
\r
109 #define I2C_WAIT_BUSY \
\r
111 timetick = SYSTEM_CURRENT_CLOCK; \
\r
112 while(ptr->cmd & I2CCMD_BUS) \
\r
114 if ((SYSTEM_CURRENT_CLOCK - timetick) >= g_i2c_timeout) \
\r
116 if(ERR_I2C_NONE == ret_value) \
\r
118 ret_value = ERR_I2C_BUSY_TIMEOUT; \
\r
126 #define I2C_WAIT_ACK \
\r
128 timetick = SYSTEM_CURRENT_CLOCK; \
\r
129 while(ptr->cmd & I2CCMD_ACK) \
\r
131 if ((SYSTEM_CURRENT_CLOCK - timetick) >= g_i2c_timeout) \
\r
133 if(ERR_I2C_NONE == ret_value) \
\r
135 ret_value = ERR_I2C_ACK_TIMEOUT; \
\r
142 #ifndef I2C_USE_INT
\r
144 #define I2C_CLEAR_INT \
\r
147 CHIP_REG_OR(I2C_CMD, I2CCMD_INT_ACK); \
\r
152 #define I2C_CLEAR_INT
\r
156 void ms_delay(uint32 ticks)
\r
159 for(i=0; i<10*ticks; i++);
\r
161 /**---------------------------------------------------------------------------*
\r
162 ** Global Variables
\r
163 **---------------------------------------------------------------------------*/
\r
164 volatile BOOLEAN g_wait_i2c_int_flag;
\r
165 volatile BOOLEAN g_i2c_open_flag=FALSE;
\r
166 volatile uint32 g_i2c_timeout = 10; //unit is ms
\r
168 /**---------------------------------------------------------------------------*
\r
169 ** Function Definitions
\r
170 **---------------------------------------------------------------------------*/
\r
172 uint32 CHIP_GetAPBClk(void)
\r
174 return ARM_CLK_26M;
\r
177 /*********************************************************************/
\r
178 // Description: i2c interrupt service
\r
185 /*********************************************************************/
\r
186 PUBLIC void I2C_Handler(uint32 param)
\r
188 param = param; // avoid compiler warning
\r
190 /* set i2c flag */
\r
191 g_wait_i2c_int_flag = FALSE;
\r
193 while((*(volatile uint32*)(I2C_CMD)) & I2CCMD_BUS);
\r
195 /* clear i2c int */
\r
196 CHIP_REG_OR(I2C_CMD, I2CCMD_INT_ACK);
\r
198 /*********************************************************************/
\r
199 // Description: i2c set SCL clock
\r
201 // freq I2C SCL's frequency to be set
\r
203 // ERR_I2C_NONE successfully
\r
206 /*********************************************************************/
\r
207 PUBLIC ERR_I2C_E I2C_SetSCLclk(uint32 freq)
\r
209 uint32 APB_clk,i2c_dvd;
\r
211 volatile I2C_CTL_REG_T *ptr = (volatile I2C_CTL_REG_T *)I2C_BASE;
\r
213 SCI_ASSERT(freq > 0);
\r
214 SCI_ASSERT(g_i2c_open_flag);
\r
216 APB_clk= CHIP_GetAPBClk();
\r
217 i2c_dvd=APB_clk/(4*freq)-1;
\r
219 ptr->div0=(uint16)(i2c_dvd & 0xffff);
\r
220 ptr->div1=(uint16)(i2c_dvd>>16);
\r
222 g_i2c_timeout = I2C_TIMEOUT_FACTOR / (freq);
\r
224 if(g_i2c_timeout < 2)
\r
226 //g_i2c_timeout will be changed according I2C frequency
\r
228 return ERR_I2C_NONE;
\r
232 /*********************************************************************/
\r
233 // Description: i2c init fuction
\r
235 // freq I2C SCL's frequency
\r
237 // ERR_I2C_NONE successfully
\r
240 /*********************************************************************/
\r
241 PUBLIC ERR_I2C_E I2C_Init(uint32 freq)
\r
243 /*SC8810 use IIC1 for sensor init, but befoe SC8810 all chip use
\r
244 IIC0 for sensor init. IIC1 use bit29 for Clock enable.
\r
246 volatile I2C_CTL_REG_T *ptr = (volatile I2C_CTL_REG_T *)I2C_BASE;
\r
249 SCI_ASSERT (freq > 0);
\r
251 g_wait_i2c_int_flag = TRUE;
\r
252 g_i2c_open_flag=TRUE;
\r
254 // gen0, enable i2c device.
\r
256 CHIP_REG_OR(GR_GEN0, APB_I2C1_EB); //GEN0_I2C1_EN
\r
258 CHIP_REG_OR(GR_GEN0, GEN0_I2C_EN); //GEN0_I2C0_EN
\r
261 ptr->rst = BIT_0;//why reset
\r
262 ptr->ctl &= ~(I2CCTL_EN);//you must first disable i2c module then change clock
\r
263 ptr->ctl &= ~(I2CCTL_IE);
\r
264 ptr->ctl &= ~(I2CCTL_CMDBUF_EN);
\r
266 I2C_SetSCLclk(freq);
\r
268 CHIP_REG_OR(I2C_CTL, (I2CCTL_IE | I2CCTL_EN));
\r
271 CHIP_REG_OR(I2C_CMD, I2CCMD_INT_ACK);
\r
273 return ERR_I2C_NONE;
\r
276 volatile I2C_CTL_REG_T *ptr = (I2C_CTL_REG_T *)I2C_BASE;
\r
279 SCI_ASSERT (freq > 0);
\r
281 g_wait_i2c_int_flag = TRUE;
\r
282 g_i2c_open_flag=TRUE;
\r
284 // gen0, enable i2c device.
\r
285 CHIP_REG_OR(GR_GEN0, GEN0_I2C_EN);
\r
287 ptr->rst = BIT_0;//why reset
\r
288 ptr->ctl &= ~(I2CCTL_EN);//you must first disable i2c module then change clock
\r
289 ptr->ctl &= ~(I2CCTL_IE);
\r
290 ptr->ctl &= ~(I2CCTL_CMDBUF_EN);
\r
292 I2C_SetSCLclk(freq);
\r
294 CHIP_REG_OR(I2C_CTL, (I2CCTL_IE | I2CCTL_EN));
\r
297 CHIP_REG_OR(I2C_CMD, I2CCMD_INT_ACK);
\r
299 return ERR_I2C_NONE;
\r
302 /*********************************************************************/
\r
303 // Description: get i2c SCL clock
\r
307 // the freq of i2c SCL clock
\r
310 /*********************************************************************/
\r
311 PUBLIC uint32 I2C_GetSCLclk()
\r
313 uint32 APB_clk,i2c_dvd,freq;
\r
315 volatile I2C_CTL_REG_T *ptr = (I2C_CTL_REG_T *)I2C_BASE;
\r
317 SCI_ASSERT(g_i2c_open_flag);
\r
319 APB_clk= CHIP_GetAPBClk();
\r
321 i2c_dvd=((ptr->div1)<<16)|(ptr->div0);
\r
323 freq=APB_clk/(4*(i2c_dvd+1));
\r
329 /*********************************************************************/
\r
330 // Description: Write a command to a slave device
\r
332 // addr the slave device's address
\r
333 // command the command to be set into the slave device's address
\r
334 // ack_en Enable/Disable check the slave device rsp ACK
\r
336 // ERR_I2C_NONE successfully
\r
339 /*********************************************************************/
\r
340 PUBLIC ERR_I2C_E I2C_WriteCmd(uint8 addr,uint8 command, BOOLEAN ack_en)
\r
342 volatile uint32 timetick = 0;
\r
343 volatile uint32 cmd = 0;
\r
344 volatile I2C_CTL_REG_T * ptr = (volatile I2C_CTL_REG_T *)I2C_BASE;
\r
345 uint32 ret_value = ERR_I2C_NONE;
\r
347 SCI_ASSERT(g_i2c_open_flag);
\r
348 SCI_ASSERT(g_i2c_timeout > 0);
\r
350 cmd = ((uint32)addr)<<8;
\r
351 cmd = cmd | I2CCMD_START | I2CCMD_WRITE;//send device address
\r
364 cmd = ((uint32)command)<<8;
\r
365 cmd = cmd | I2CCMD_WRITE | I2CCMD_STOP;//send command
\r
378 return ERR_I2C_NONE;
\r
382 /*********************************************************************/
\r
383 // Description: Write a data to a slave device
\r
385 // addr the slave device's address
\r
386 // command the command to be set into the slave device's address
\r
387 // ack_en Enable/Disable check the slave device rsp ACK
\r
389 // ERR_I2C_NONE successfully
\r
392 /*********************************************************************/
\r
393 PUBLIC ERR_I2C_E I2C_WriteData(uint8 addr,uint8 data, BOOLEAN ack_en)
\r
395 volatile uint32 timetick = 0;
\r
396 volatile uint32 cmd = 0;
\r
397 volatile I2C_CTL_REG_T * ptr = (volatile I2C_CTL_REG_T *)I2C_BASE;
\r
398 uint32 ret_value = ERR_I2C_NONE;
\r
400 SCI_ASSERT(g_i2c_open_flag);
\r
401 SCI_ASSERT(g_i2c_timeout > 0);
\r
403 cmd = ((uint32)addr)<<8;
\r
404 cmd = cmd | I2CCMD_START | I2CCMD_WRITE;//send device address
\r
417 data = ((uint32)data)<<8;
\r
418 data = data | I2CCMD_WRITE | I2CCMD_STOP;//send command
\r
431 return ERR_I2C_NONE;
\r
434 /*********************************************************************/
\r
435 // Description: read a command from the slave device
\r
437 // addr the slave device's address
\r
438 // pCmd the command's pointer
\r
439 // ack_en Enable/Disable check the slave device rsp ACK
\r
441 // ERR_I2C_NONE successfully
\r
444 /*********************************************************************/
\r
445 PUBLIC ERR_I2C_E I2C_ReadCmd(uint8 addr,uint8 *pCmd, BOOLEAN ack_en)
\r
447 volatile uint32 timetick = 0;
\r
448 volatile uint32 cmd = 0;
\r
449 volatile I2C_CTL_REG_T * ptr = (volatile I2C_CTL_REG_T *)I2C_BASE;
\r
450 uint32 ret_value = ERR_I2C_NONE;
\r
452 SCI_ASSERT(NULL != pCmd);
\r
453 SCI_ASSERT(g_i2c_open_flag);
\r
454 SCI_ASSERT(g_i2c_timeout > 0);
\r
456 cmd = ((uint32)(addr|I2C_READ_BIT))<<8;
\r
457 cmd = cmd | I2CCMD_START | I2CCMD_WRITE;//send device address
\r
470 cmd = I2CCMD_READ | I2CCMD_STOP | I2CCMD_TX_ACK;
\r
478 *pCmd=(uint8)((ptr->cmd)>>8);
\r
480 return ERR_I2C_NONE;
\r
482 /*********************************************************************/
\r
483 // Description: Write the command array into the slave device
\r
485 // addr the slave device's address
\r
486 // pCmd the command array's pointer
\r
487 // len the length of the command array
\r
488 // ack_en Enable/Disable check the slave device rsp ACK
\r
490 // ERR_I2C_NONE successfully
\r
493 /*********************************************************************/
\r
494 uint32 ret_value = ERR_I2C_NONE;
\r
495 volatile uint32 timetick = 0;
\r
496 PUBLIC ERR_I2C_E I2C_WriteCmdArr(uint8 addr, uint8 *pCmd, uint32 len, BOOLEAN ack_en)
\r
498 volatile uint32 curtime = 0;
\r
499 volatile uint32 i = 0;
\r
500 volatile uint32 cmd = 0;
\r
501 volatile I2C_CTL_REG_T * ptr = (volatile I2C_CTL_REG_T *)I2C_BASE;
\r
503 SCI_ASSERT(NULL != pCmd);
\r
504 SCI_ASSERT(g_i2c_open_flag);
\r
505 SCI_ASSERT(g_i2c_timeout > 0);
\r
507 cmd = ((uint32)addr)<<8;
\r
508 cmd = cmd | I2CCMD_START | I2CCMD_WRITE ;//send device address 0x9824
\r
523 cmd = ((uint32)pCmd[i])<<8;
\r
525 cmd = cmd | I2CCMD_WRITE | I2CCMD_STOP;//send command
\r
527 cmd = cmd | I2CCMD_WRITE ;
\r
545 /*********************************************************************/
\r
546 // Description: Read a command array from the slave device
\r
548 // addr the slave device's address
\r
549 // pCmd the command array's pointer
\r
550 // len the length of command array
\r
551 // ack_en Enable/Disable check the slave device rsp ACK
\r
553 // ERR_I2C_NONE successfully
\r
556 /*********************************************************************/
\r
557 PUBLIC ERR_I2C_E I2C_ReadCmdArr(uint8 addr, uint8 *pCmd, uint32 len,BOOLEAN ack_en )
\r
559 volatile uint32 timetick = 0;
\r
560 volatile uint32 i = 0;
\r
561 volatile uint32 cmd = 0;
\r
562 volatile I2C_CTL_REG_T * ptr = (volatile I2C_CTL_REG_T *)I2C_BASE;
\r
563 uint32 ret_value = ERR_I2C_NONE;
\r
565 SCI_ASSERT(NULL !=pCmd );
\r
566 SCI_ASSERT(g_i2c_open_flag);
\r
567 SCI_ASSERT(g_i2c_timeout > 0);
\r
569 cmd = ((uint32)(addr|I2C_READ_BIT))<<8;
\r
570 cmd = cmd | I2CCMD_START | I2CCMD_WRITE;//send device address
\r
586 cmd = I2CCMD_READ; // I2CCMD_READ|I2CCMD_TX_ACK;
\r
588 cmd = I2CCMD_READ|I2CCMD_STOP|I2CCMD_TX_ACK;
\r
596 pCmd[i] = (uint8)((ptr->cmd)>>8);
\r
599 return ERR_I2C_NONE;
\r
603 /**---------------------------------------------------------------------------*
\r
605 **---------------------------------------------------------------------------*/
\r