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/sprd_reg_global.h>
\r
32 #include <asm/arch/sprd_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 LOCAL volatile uint32 g_i2c_timeout = 10; //unit is ms
167 /**---------------------------------------------------------------------------*
\r
168 ** Function Definitions
\r
169 **---------------------------------------------------------------------------*/
\r
171 uint32 CHIP_GetAPBClk(void)
\r
173 return ARM_CLK_26M;
\r
176 /*********************************************************************/
\r
177 // Description: i2c interrupt service
\r
184 /*********************************************************************/
\r
185 PUBLIC void I2C_Handler(uint32 param)
\r
187 param = param; // avoid compiler warning
\r
189 /* set i2c flag */
\r
190 g_wait_i2c_int_flag = FALSE;
\r
192 while((*(volatile uint32*)(I2C_CMD)) & I2CCMD_BUS);
\r
194 /* clear i2c int */
\r
195 CHIP_REG_OR(I2C_CMD, I2CCMD_INT_ACK);
\r
197 /*********************************************************************/
\r
198 // Description: i2c set SCL clock
\r
200 // freq I2C SCL's frequency to be set
\r
202 // ERR_I2C_NONE successfully
\r
205 /*********************************************************************/
\r
206 PUBLIC ERR_I2C_E I2C_SetSCLclk(uint32 freq)
\r
208 uint32 APB_clk,i2c_dvd;
\r
210 volatile I2C_CTL_REG_T *ptr = (volatile I2C_CTL_REG_T *)I2C_BASE;
\r
212 SCI_ASSERT(freq > 0);
\r
213 SCI_ASSERT(g_i2c_open_flag);
\r
215 APB_clk= CHIP_GetAPBClk();
\r
216 i2c_dvd=APB_clk/(4*freq)-1;
\r
218 ptr->div0=(uint16)(i2c_dvd & 0xffff);
\r
219 ptr->div1=(uint16)(i2c_dvd>>16);
\r
221 g_i2c_timeout = I2C_TIMEOUT_FACTOR / (freq);
\r
223 if(g_i2c_timeout < 2)
\r
225 //g_i2c_timeout will be changed according I2C frequency
\r
227 return ERR_I2C_NONE;
\r
231 /*********************************************************************/
\r
232 // Description: i2c init fuction
\r
234 // freq I2C SCL's frequency
\r
236 // ERR_I2C_NONE successfully
\r
239 /*********************************************************************/
\r
240 PUBLIC ERR_I2C_E I2C_Init(uint32 freq)
\r
242 /*SC8810 use IIC1 for sensor init, but befoe SC8810 all chip use
\r
243 IIC0 for sensor init. IIC1 use bit29 for Clock enable.
\r
245 volatile I2C_CTL_REG_T *ptr = (volatile I2C_CTL_REG_T *)I2C_BASE;
\r
248 SCI_ASSERT (freq > 0);
\r
250 g_wait_i2c_int_flag = TRUE;
\r
251 g_i2c_open_flag=TRUE;
\r
253 // gen0, enable i2c device.
\r
254 #if defined (CONFIG_SC8830) || defined(CONFIG_SC9630)
\r
257 CHIP_REG_OR(GR_GEN0, GEN0_I2C_EN); //GEN0_I2C0_EN
\r
260 ptr->rst = BIT_0;//why reset
\r
261 ptr->ctl &= ~(I2CCTL_EN);//you must first disable i2c module then change clock
\r
262 ptr->ctl &= ~(I2CCTL_IE);
\r
263 ptr->ctl &= ~(I2CCTL_CMDBUF_EN);
\r
265 I2C_SetSCLclk(freq);
\r
267 CHIP_REG_OR(I2C_CTL, (I2CCTL_IE | I2CCTL_EN));
\r
270 CHIP_REG_OR(I2C_CMD, I2CCMD_INT_ACK);
\r
272 return ERR_I2C_NONE;
\r
274 /*********************************************************************/
\r
275 // Description: get i2c SCL clock
\r
279 // the freq of i2c SCL clock
\r
282 /*********************************************************************/
\r
283 PUBLIC uint32 I2C_GetSCLclk(void)
\r
285 uint32 APB_clk,i2c_dvd,freq;
\r
287 volatile I2C_CTL_REG_T *ptr = (I2C_CTL_REG_T *)I2C_BASE;
\r
289 SCI_ASSERT(g_i2c_open_flag);
\r
291 APB_clk= CHIP_GetAPBClk();
\r
293 i2c_dvd=((ptr->div1)<<16)|(ptr->div0);
\r
295 freq=APB_clk/(4*(i2c_dvd+1));
\r
301 /*********************************************************************/
\r
302 // Description: Write a command to a slave device
\r
304 // addr the slave device's address
\r
305 // command the command to be set into the slave device's address
\r
306 // ack_en Enable/Disable check the slave device rsp ACK
\r
308 // ERR_I2C_NONE successfully
\r
311 /*********************************************************************/
\r
312 PUBLIC ERR_I2C_E I2C_WriteCmd(uint8 addr,uint8 command, BOOLEAN ack_en)
\r
314 volatile uint32 timetick = 0;
\r
315 volatile uint32 cmd = 0;
\r
316 volatile I2C_CTL_REG_T * ptr = (volatile I2C_CTL_REG_T *)I2C_BASE;
\r
317 uint32 ret_value = ERR_I2C_NONE;
\r
319 SCI_ASSERT(g_i2c_open_flag);
\r
320 SCI_ASSERT(g_i2c_timeout > 0);
\r
322 cmd = ((uint32)addr)<<8;
\r
323 cmd = cmd | I2CCMD_START | I2CCMD_WRITE;//send device address
\r
336 cmd = ((uint32)command)<<8;
\r
337 cmd = cmd | I2CCMD_WRITE | I2CCMD_STOP;//send command
\r
350 return ERR_I2C_NONE;
\r
354 /*********************************************************************/
\r
355 // Description: Write a data to a slave device
\r
357 // addr the slave device's address
\r
358 // command the command to be set into the slave device's address
\r
359 // ack_en Enable/Disable check the slave device rsp ACK
\r
361 // ERR_I2C_NONE successfully
\r
364 /*********************************************************************/
\r
365 PUBLIC ERR_I2C_E I2C_WriteData(uint8 addr,uint8 data, BOOLEAN ack_en)
\r
367 volatile uint32 timetick = 0;
\r
368 volatile uint32 cmd = 0;
\r
369 volatile I2C_CTL_REG_T * ptr = (volatile I2C_CTL_REG_T *)I2C_BASE;
\r
370 uint32 ret_value = ERR_I2C_NONE;
\r
372 SCI_ASSERT(g_i2c_open_flag);
\r
373 SCI_ASSERT(g_i2c_timeout > 0);
\r
375 cmd = ((uint32)addr)<<8;
\r
376 cmd = cmd | I2CCMD_START | I2CCMD_WRITE;//send device address
\r
389 data = ((uint32)data)<<8;
\r
390 data = data | I2CCMD_WRITE | I2CCMD_STOP;//send command
\r
403 return ERR_I2C_NONE;
\r
406 /*********************************************************************/
\r
407 // Description: read a command from the slave device
\r
409 // addr the slave device's address
\r
410 // pCmd the command's pointer
\r
411 // ack_en Enable/Disable check the slave device rsp ACK
\r
413 // ERR_I2C_NONE successfully
\r
416 /*********************************************************************/
\r
417 PUBLIC ERR_I2C_E I2C_ReadCmd(uint8 addr,uint8 *pCmd, BOOLEAN ack_en)
\r
419 volatile uint32 timetick = 0;
\r
420 volatile uint32 cmd = 0;
\r
421 volatile I2C_CTL_REG_T * ptr = (volatile I2C_CTL_REG_T *)I2C_BASE;
\r
422 uint32 ret_value = ERR_I2C_NONE;
\r
424 SCI_ASSERT(NULL != pCmd);
\r
425 SCI_ASSERT(g_i2c_open_flag);
\r
426 SCI_ASSERT(g_i2c_timeout > 0);
\r
428 cmd = ((uint32)(addr|I2C_READ_BIT))<<8;
\r
429 cmd = cmd | I2CCMD_START | I2CCMD_WRITE;//send device address
\r
442 cmd = I2CCMD_READ | I2CCMD_STOP | I2CCMD_TX_ACK;
\r
450 *pCmd=(uint8)((ptr->cmd)>>8);
\r
452 return ERR_I2C_NONE;
\r
454 /*********************************************************************/
\r
455 // Description: Write the command array into the slave device
\r
457 // addr the slave device's address
\r
458 // pCmd the command array's pointer
\r
459 // len the length of the command array
\r
460 // ack_en Enable/Disable check the slave device rsp ACK
\r
462 // ERR_I2C_NONE successfully
\r
465 /*********************************************************************/
\r
466 uint32 ret_value = ERR_I2C_NONE;
\r
467 volatile uint32 timetick = 0;
\r
468 PUBLIC ERR_I2C_E I2C_WriteCmdArr(uint8 addr, uint8 *pCmd, uint32 len, BOOLEAN ack_en)
\r
470 volatile uint32 i = 0;
\r
471 volatile uint32 cmd = 0;
\r
472 volatile I2C_CTL_REG_T * ptr = (volatile I2C_CTL_REG_T *)I2C_BASE;
\r
474 SCI_ASSERT(NULL != pCmd);
\r
475 SCI_ASSERT(g_i2c_open_flag);
\r
476 SCI_ASSERT(g_i2c_timeout > 0);
\r
478 cmd = ((uint32)addr)<<8;
\r
479 cmd = cmd | I2CCMD_START | I2CCMD_WRITE ;//send device address 0x9824
\r
494 cmd = ((uint32)pCmd[i])<<8;
\r
496 cmd = cmd | I2CCMD_WRITE | I2CCMD_STOP;//send command
\r
498 cmd = cmd | I2CCMD_WRITE ;
\r
516 /*********************************************************************/
\r
517 // Description: Read a command array from the slave device
\r
519 // addr the slave device's address
\r
520 // pCmd the command array's pointer
\r
521 // len the length of command array
\r
522 // ack_en Enable/Disable check the slave device rsp ACK
\r
524 // ERR_I2C_NONE successfully
\r
527 /*********************************************************************/
\r
528 PUBLIC ERR_I2C_E I2C_ReadCmdArr(uint8 addr, uint8 *pCmd, uint32 len,BOOLEAN ack_en )
\r
530 volatile uint32 timetick = 0;
\r
531 volatile uint32 i = 0;
\r
532 volatile uint32 cmd = 0;
\r
533 volatile I2C_CTL_REG_T * ptr = (volatile I2C_CTL_REG_T *)I2C_BASE;
\r
534 uint32 ret_value = ERR_I2C_NONE;
\r
536 SCI_ASSERT(NULL !=pCmd );
\r
537 SCI_ASSERT(g_i2c_open_flag);
\r
538 SCI_ASSERT(g_i2c_timeout > 0);
\r
540 cmd = ((uint32)(addr|I2C_READ_BIT))<<8;
\r
541 cmd = cmd | I2CCMD_START | I2CCMD_WRITE;//send device address
\r
557 cmd = I2CCMD_READ; // I2CCMD_READ|I2CCMD_TX_ACK;
\r
559 cmd = I2CCMD_READ|I2CCMD_STOP|I2CCMD_TX_ACK;
\r
567 pCmd[i] = (uint8)((ptr->cmd)>>8);
\r
570 return ERR_I2C_NONE;
\r
574 /**---------------------------------------------------------------------------*
\r
576 **---------------------------------------------------------------------------*/
\r