change source file mode to 0644 instead of 0755
[profile/mobile/platform/kernel/u-boot-tm1.git] / drivers / i2c / v0 / i2c_phy_v0.c
1 /******************************************************************************
2  ** File Name:      I2C_phy_v0.c                                                 *
3  ** Author:         liuhao                                                   *
4  ** DATE:           06/28/2010                                                *
5  ** Copyright:      2010 Spreatrum, Incoporated. All Rights Reserved.         *
6  ** Description:    This file define the physical layer of I2C device.      *
7  ******************************************************************************
8
9  ******************************************************************************
10  **                        Edit History                                       *
11  ** ------------------------------------------------------------------------- *
12  ** DATE           NAME             DESCRIPTION                               *
13  ** 06/28/2010     liuhao     Create.                                   *
14  ******************************************************************************/
15
16 /**---------------------------------------------------------------------------*
17  **                         Dependencies                                      *
18  **---------------------------------------------------------------------------*/
19 //#include "os_api.h"
20 //#include "chip_plf_export.h"
21 //#include "timer_drvapi.h"
22 #include "i2c_reg_v0.h"
23 #include "asm/arch/sys_timer_reg_v0.h"
24 //#include "sci_types.h"
25 #include <asm/arch/chip_drv_common_io.h>
26
27 #include "../sc8830_i2c_cfg.h"
28 #include "../i2c_phy.h"
29
30 /**---------------------------------------------------------------------------*
31  **                         Debugging Flag                                    *
32  **---------------------------------------------------------------------------*/
33
34 /**---------------------------------------------------------------------------*
35  **                         Compiler Flag                                     *
36  **---------------------------------------------------------------------------*/
37 #ifdef   __cplusplus
38 extern   "C"
39 {
40 #endif
41
42 /**---------------------------------------------------------------------------*
43  **                            Macro Define
44  **---------------------------------------------------------------------------*/
45 //extern uint32 TIMER_GetSystemCounterReg (void);
46 //extern void SyscntEnable (void);
47
48 #define I2C_TIMEOUT_FACTOR  500000  //the critical value is 10000
49
50 #define I2C_WAIT_INT                                                  \
51     {                                                                     \
52         timetick = SYSTEM_CURRENT_CLOCK;                                  \
53         while(!(ptr->ctl & I2CCTL_INT))                                   \
54         {                                                                 \
55             uint32 wait_counter=0x00;   \
56             for(wait_counter=0x00; wait_counter<0xff;wait_counter++)    \
57             {                                                   \
58                 wait_counter++;                         \
59             }                                                    \
60             if((SYSTEM_CURRENT_CLOCK - timetick) >= g_i2c_timeout)        \
61             {                                                             \
62                 if(ERR_I2C_NONE == ret_value)                             \
63                 {                                                         \
64                     ret_value = ERR_I2C_INT_TIMEOUT;                      \
65                 }                                                         \
66                 break;                                                    \
67             }                                                             \
68             \
69         }                                                                 \
70         \
71     }
72
73 #define I2C_WAIT_BUSY                                                 \
74     {                                                                     \
75         timetick = SYSTEM_CURRENT_CLOCK;                                  \
76         while(ptr->cmd & I2CCMD_BUS)                                      \
77         {                                                                 \
78             if ((SYSTEM_CURRENT_CLOCK - timetick) >= g_i2c_timeout)       \
79             {                                                             \
80                 if(ERR_I2C_NONE == ret_value)                             \
81                 {                                                         \
82                     ret_value = ERR_I2C_BUSY_TIMEOUT;                     \
83                 }                                                         \
84                 break;                                                    \
85             }                                                             \
86         }                                                                 \
87         \
88     }
89
90 #define I2C_WAIT_ACK                                                  \
91     {                                                                     \
92         timetick = SYSTEM_CURRENT_CLOCK;                                  \
93         while(ptr->cmd & I2CCMD_ACK)                                      \
94         {                                                                 \
95             if ((SYSTEM_CURRENT_CLOCK - timetick) >= g_i2c_timeout)       \
96             {                                                             \
97                 if(ERR_I2C_NONE == ret_value)                             \
98                 {                                                         \
99                     ret_value = ERR_I2C_ACK_TIMEOUT;                      \
100                 }                                                         \
101                 break;                                                    \
102             }                                                             \
103         }                                                                 \
104     }
105
106
107 #define I2C_CLEAR_INT                                                 \
108     {                                                                     \
109         I2C_WAIT_BUSY                                                     \
110         ptr->cmd |= I2CCMD_INT_ACK; \
111     }
112
113 /**---------------------------------------------------------------------------*
114  **                            Local Variables
115  **---------------------------------------------------------------------------*/
116
117 /**---------------------------------------------------------------------------*
118  **                            Global Variables
119  **---------------------------------------------------------------------------*/
120 LOCAL volatile uint32     g_i2c_timeout = 2; //unit is ms
121 extern const I2C_BASE_INFO __i2c_base_info[I2C_BUS_MAX];
122
123 /*********************************************************************************************************
124 ** Function name:
125 ** Descriptions:
126 ** input parameters:
127 **
128 **
129 **
130 ** output parameters:
131 ** Returned value:
132 *********************************************************************************************************/
133 LOCAL uint32  __I2C_PHY_GetBase (uint32 phy_id)
134 {
135     int32 i;
136     uint32 ret = 0;
137
138     //SyscntEnable();
139
140     for (i = 0; i < I2C_BUS_MAX; i++)
141     {
142         if (phy_id == (uint32) __i2c_base_info[i].phy_id)
143         {
144             ret = (uint32) __i2c_base_info[i].base_addr;
145             
146             switch(phy_id)
147             {
148                 case 0:
149                         CHIP_REG_OR (GR_GEN0, (GEN0_I2C0_EN));
150                         break;  
151                 case 1:
152                         CHIP_REG_OR (GR_GEN0, (GEN0_I2C1_EN));
153                         break;  
154                 case 2:
155                         CHIP_REG_OR (GR_GEN0, (GEN0_I2C2_EN));
156                         break;
157                 case 3:
158                         CHIP_REG_OR (GR_GEN0, (GEN0_I2C3_EN));
159                         break;  
160                 case 4:
161                         CHIP_REG_OR (GR_GEN0, (GEN0_I2C4_EN));
162                         break;
163                 case 5:
164                         CHIP_REG_OR (AON_APB_EB0, (AON_I2C_EN));
165                         break;
166             }
167             break;
168         }
169     }
170
171     //SCI_PASSERT ( (0 != ret), ("get I2C controller base address fail!"));/*assert verified*/
172     return ret;
173 }
174 /*********************************************************************************************************
175 ** Function name:
176 ** Descriptions:
177 ** input parameters:
178 **
179 **
180 **
181 ** output parameters:
182 ** Returned value:
183 *********************************************************************************************************/
184 LOCAL ERR_I2C_E __I2C_PHY_SetSCL (uint32 phy_id, uint32 freq)
185 {
186     uint32 APB_clk,i2c_dvd;
187     volatile I2C_CTL_REG_T *ptr = (volatile I2C_CTL_REG_T *) __I2C_PHY_GetBase (phy_id);
188     APB_clk= 26*1000*1000;//CHIP_GetAPBClk();
189     i2c_dvd=APB_clk/ (4*freq)-1;
190     ptr->div0= (uint16) (i2c_dvd & 0xffff);
191     ptr->div1= (uint16) (i2c_dvd>>16);
192     g_i2c_timeout = I2C_TIMEOUT_FACTOR / (freq);
193
194     if (g_i2c_timeout < 2)
195     {
196         g_i2c_timeout = 2;
197     }
198
199     return ERR_I2C_NONE;
200 }
201
202 /*********************************************************************************************************
203 ** Function name:
204 ** Descriptions:
205 ** input parameters:
206 **
207 **
208 **
209 ** output parameters:
210 ** Returned value:
211 *********************************************************************************************************/
212 LOCAL ERR_I2C_E __I2C_PHY_SetPort (uint32 port)
213 {
214     return ERR_I2C_NONE;
215 }
216
217 /*********************************************************************************************************
218 ** Function name:
219 ** Descriptions:
220 ** input parameters:
221 **
222 **
223 **
224 ** output parameters:
225 ** Returned value:
226 *********************************************************************************************************/
227 LOCAL ERR_I2C_E I2C_PHY_ControlInit_V0 (uint32 phy_id, uint32 freq, uint32 port)
228 {
229     volatile I2C_CTL_REG_T *ptr = (volatile I2C_CTL_REG_T *) __I2C_PHY_GetBase (phy_id);
230
231     ptr->rst = BIT_0;//why reset
232     ptr->ctl &= ~ (I2CCTL_EN); //you must first disable i2c module then change clock
233     ptr->ctl &= ~ (I2CCTL_IE);
234     //ptr->ctl &= ~ (I2CCTL_CMDBUF_EN);
235     __I2C_PHY_SetSCL (phy_id, freq);
236
237     if (I2C_PORT_NUM < port)
238     {
239         //SCI_ASSERT (0);/*assert to do*/
240     }
241
242     __I2C_PHY_SetPort (port);
243
244     //CHIP_REG_OR (I2C_CTL, (I2CCTL_IE | I2CCTL_EN));
245     ptr->ctl |=  (I2CCTL_IE | I2CCTL_EN);
246     //Clear I2C int
247     //CHIP_REG_OR (I2C_CMD, I2CCMD_INT_ACK);
248     ptr->cmd &= ~ (I2CCMD_INT_ACK);
249         
250     IIC_PRINT ("[IIC DRV:]I2C_PHY_ControlInit_V0: freq=%d, port=%d", freq, port);
251     return ERR_I2C_NONE;
252 }
253
254 /*********************************************************************************************************
255 ** Function name:
256 ** Descriptions:
257 ** input parameters:
258 **
259 **
260 **
261 ** output parameters:
262 ** Returned value:
263 *********************************************************************************************************/
264 LOCAL ERR_I2C_E I2C_PHY_StartBus_V0 (uint32 phy_id, uint8 addr, BOOLEAN rw, BOOLEAN ack_en)
265 {
266     uint32 timetick = 0;
267     uint32 cmd = 0;
268     volatile I2C_CTL_REG_T *ptr = (volatile I2C_CTL_REG_T *) __I2C_PHY_GetBase (phy_id);
269     uint32   ret_value = ERR_I2C_NONE;
270
271     if (rw)
272     {
273         /*read cmd*/
274         cmd = ( (uint32) (addr |0x1)) <<8;
275     }
276     else
277     {
278         /*write cmd*/
279         cmd = ( (uint32) addr) <<8;
280     }
281
282     cmd = cmd | I2CCMD_START | I2CCMD_WRITE;
283     IIC_PRINT ("[IIC DRV:]I2C_PHY_StartBus_V0: cmd=%x", cmd);
284     ptr->cmd = cmd;
285     I2C_WAIT_INT
286     I2C_CLEAR_INT
287
288     //check ACK
289     if (ack_en)
290     {
291         I2C_WAIT_ACK
292     }
293
294     return ERR_I2C_NONE;
295 }
296
297 /*********************************************************************************************************
298 ** Function name:
299 ** Descriptions:
300 ** input parameters:
301 **
302 **
303 **
304 ** output parameters:
305 ** Returned value:
306 *********************************************************************************************************/
307 LOCAL ERR_I2C_E I2C_PHY_WriteBytes_V0 (uint32 phy_id, uint8 *pCmd, uint32 len, BOOLEAN ack_en, BOOLEAN no_stop)
308 {
309     uint32 timetick = 0;
310     uint32 i = 0;
311     uint32 cmd = 0;
312     volatile I2C_CTL_REG_T *ptr = (volatile I2C_CTL_REG_T *) __I2C_PHY_GetBase (phy_id);
313     uint32   ret_value = ERR_I2C_NONE;
314
315     for (i=0; i<len; i++)
316     {
317         cmd = ( (uint32) pCmd[i]) <<8;
318         cmd = cmd | I2CCMD_WRITE ;
319
320         if ( (i== (len-1)) && (!no_stop))
321         {
322             cmd = cmd | I2CCMD_STOP;
323         }
324
325         ptr->cmd = cmd;
326         IIC_PRINT ("[IIC DRV:]I2C_PHY_WriteBytes_V0: cmd=%x", cmd);
327         I2C_WAIT_INT
328         I2C_CLEAR_INT
329
330         //check ACK
331         if (ack_en)
332         {
333             I2C_WAIT_ACK
334         }
335     }
336
337     return ret_value;
338 }
339
340
341 /*********************************************************************************************************
342 ** Function name:
343 ** Descriptions:
344 ** input parameters:
345 **
346 **
347 **
348 ** output parameters:
349 ** Returned value:
350 *********************************************************************************************************/
351 LOCAL ERR_I2C_E I2C_PHY_ReadBytes_V0 (uint32 phy_id, uint8 *pCmd, uint32 len, BOOLEAN ack_en)
352 {
353     uint32 timetick = 0;
354     uint32 i = 0;
355     uint32 cmd = 0;
356     volatile I2C_CTL_REG_T *ptr = (volatile I2C_CTL_REG_T *) __I2C_PHY_GetBase (phy_id);
357     uint32   ret_value = ERR_I2C_NONE;
358
359     for (i=0; i<len; i++)
360     {
361         cmd = I2CCMD_READ; /*FIXME |I2CCMD_TX_ACK;*/
362
363         if (i== (len-1))
364         {
365             cmd = cmd |I2CCMD_STOP |I2CCMD_TX_ACK;
366         }
367
368         ptr->cmd = cmd;
369         IIC_PRINT ("[IIC DRV:]I2C_PHY_ReadBytes_V0: cmd=%x", cmd);
370         I2C_WAIT_INT
371         I2C_CLEAR_INT
372         pCmd[i] = (uint8) ( (ptr->cmd) >>8);
373     }
374
375     return ret_value;
376 }
377
378 /*********************************************************************************************************
379 ** Function name:
380 ** Descriptions:
381 ** input parameters:
382 **
383 **
384 **
385 ** output parameters:
386 ** Returned value:
387 *********************************************************************************************************/
388 LOCAL ERR_I2C_E I2C_PHY_StopBus_V0 (uint32 phy_id)
389 {
390     uint32 timetick = 0;
391     uint32 cmd = 0;
392     volatile I2C_CTL_REG_T *ptr = (volatile I2C_CTL_REG_T *) __I2C_PHY_GetBase (phy_id);
393     uint32   ret_value = ERR_I2C_NONE;
394     cmd = I2CCMD_STOP;
395     ptr->cmd = cmd;
396     I2C_WAIT_INT
397     I2C_CLEAR_INT
398     return ERR_I2C_NONE;
399 }
400
401 /*********************************************************************************************************
402 ** Function name:
403 ** Descriptions:
404 ** input parameters:
405 **
406 **
407 **
408 ** output parameters:
409 ** Returned value:
410 *********************************************************************************************************/
411 LOCAL ERR_I2C_E I2C_PHY_SendACK_V0 (uint32 phy_id)
412 {
413     return ERR_I2C_NONE;
414 }
415
416 /*********************************************************************************************************
417 ** Function name:
418 ** Descriptions:
419 ** input parameters:
420 **
421 **
422 **
423 ** output parameters:
424 ** Returned value:
425 *********************************************************************************************************/
426 LOCAL ERR_I2C_E I2C_PHY_GetACK_V0 (uint32 phy_id)
427 {
428     return ERR_I2C_NONE;
429 }
430
431 /*this version armcc can not support this method :(*/
432 #if 0
433 PUBLIC I2C_PHY_FUN phy_fun_v0 = {
434         .init = I2C_PHY_ControlInit_V0,
435         .start = I2C_PHY_StartBus_V0,
436         .stop = I2C_PHY_StopBus_V0,
437         .read = I2C_PHY_ReadBytes_V0,
438         .write = I2C_PHY_WriteBytes_V0,
439         .sendack = I2C_PHY_SendACK_V0,
440         .getack = I2C_PHY_GetACK_V0,
441 };
442
443 #else
444
445 PUBLIC I2C_PHY_FUN phy_fun_v0 =
446 {
447     I2C_PHY_ControlInit_V0,
448     I2C_PHY_StartBus_V0,
449     I2C_PHY_WriteBytes_V0,
450     I2C_PHY_ReadBytes_V0,
451     I2C_PHY_StopBus_V0,
452     I2C_PHY_SendACK_V0,
453     I2C_PHY_GetACK_V0
454 };
455 #endif
456 /**---------------------------------------------------------------------------*
457  **                         Compiler Flag                                     *
458  **---------------------------------------------------------------------------*/
459
460
461 #ifdef   __cplusplus
462 }
463 #endif
464
465 /*  End Of File */