thor: fix invalid larger device descriptor than requested
[profile/mobile/platform/kernel/u-boot-tm1.git] / drivers / i2c / sprd_i2c.c
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
10 \r
11  ******************************************************************************\r
12  **                        Edit History                                       *\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
21 \r
22 /**---------------------------------------------------------------------------*\r
23  **                         Dependencies                                      *\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
34 \r
35 //#include "dcam_fpga_misc.h"\r
36 \r
37 #ifndef TIGER_REG\r
38 #define TIGER_REG\r
39 #endif\r
40 \r
41 /**---------------------------------------------------------------------------*\r
42  **                         Debugging Flag                                    *\r
43  **---------------------------------------------------------------------------*/\r
44 /**---------------------------------------------------------------------------*\r
45  **                         Compiler Flag                                     *\r
46  **---------------------------------------------------------------------------*/\r
47 #ifdef   __cplusplus\r
48     extern   "C" \r
49     {\r
50 #endif\r
51 \r
52 \r
53 \r
54 /**---------------------------------------------------------------------------*\r
55  **                            Macro Define\r
56  **---------------------------------------------------------------------------*/\r
57 \r
58 #define I2C_TIMEOUT_FACTOR  500000  //the critical value is 10000\r
59 \r
60 #define ARM_CLK_13M         13000000\r
61 #define ARM_CLK_24M         24000000\r
62 \r
63 \r
64 #define I2C_READ_BIT        0x1\r
65 \r
66 //#define I2C_USE_INT\r
67 \r
68 #ifndef I2C_USE_INT \r
69 \r
70 #define I2C_WAIT_INT                                                  \\r
71 {                                                                     \\r
72     timetick = SYSTEM_CURRENT_CLOCK;                                  \\r
73     while(!(ptr->ctl & I2CCTL_INT))                                   \\r
74     {                                                                 \\r
75         if((SYSTEM_CURRENT_CLOCK - timetick) >= g_i2c_timeout)        \\r
76         {                                                             \\r
77             if(ERR_I2C_NONE == ret_value)                             \\r
78             {                                                         \\r
79                 ret_value = ERR_I2C_INT_TIMEOUT;                      \\r
80             }                                                         \\r
81             break;                                                    \\r
82         }                                                             \\r
83                                                                       \\r
84     }                                                                 \\r
85                                                                       \\r
86 }\r
87 \r
88 #else\r
89 \r
90 #define I2C_WAIT_INT                                                  \\r
91 {                                                                     \\r
92     timetick = SYSTEM_CURRENT_CLOCK;                                  \\r
93     while (g_wait_i2c_int_flag)                                       \\r
94     {                                                                 \\r
95         if ((SYSTEM_CURRENT_CLOCK - timetick) >= g_i2c_timeout)       \\r
96         {                                                             \\r
97             if(ERR_I2C_NONE == ret_value)                             \\r
98             {                                                         \\r
99                 ret_value = ERR_I2C_INT_TIMEOUT;                      \\r
100             }                                                         \\r
101             break;                                                    \\r
102         }                                                             \\r
103     }                                                                 \\r
104     g_wait_i2c_int_flag = 1;                                          \\r
105 }\r
106 \r
107 #endif \r
108        \r
109 #define I2C_WAIT_BUSY                                                 \\r
110 {                                                                     \\r
111     timetick = SYSTEM_CURRENT_CLOCK;                                  \\r
112     while(ptr->cmd & I2CCMD_BUS)                                      \\r
113     {                                                                 \\r
114         if ((SYSTEM_CURRENT_CLOCK - timetick) >= g_i2c_timeout)       \\r
115         {                                                             \\r
116             if(ERR_I2C_NONE == ret_value)                             \\r
117             {                                                         \\r
118                 ret_value = ERR_I2C_BUSY_TIMEOUT;                     \\r
119             }                                                         \\r
120             break;                                                    \\r
121         }                                                             \\r
122     }                                                                 \\r
123                                                                       \\r
124 }\r
125        \r
126 #define I2C_WAIT_ACK                                                  \\r
127 {                                                                     \\r
128     timetick = SYSTEM_CURRENT_CLOCK;                                  \\r
129     while(ptr->cmd & I2CCMD_ACK)                                      \\r
130     {                                                                 \\r
131         if ((SYSTEM_CURRENT_CLOCK - timetick) >= g_i2c_timeout)       \\r
132         {                                                             \\r
133             if(ERR_I2C_NONE == ret_value)                             \\r
134             {                                                         \\r
135                 ret_value = ERR_I2C_ACK_TIMEOUT;                      \\r
136             }                                                         \\r
137             break;                                                    \\r
138         }                                                             \\r
139     }                                                                 \\r
140 }\r
141 \r
142 #ifndef I2C_USE_INT\r
143 \r
144 #define I2C_CLEAR_INT                                                 \\r
145 {                                                                     \\r
146     I2C_WAIT_BUSY                                                     \\r
147     CHIP_REG_OR(I2C_CMD, I2CCMD_INT_ACK);                               \\r
148 }\r
149 \r
150 #else\r
151 \r
152 #define I2C_CLEAR_INT  \r
153 \r
154 #endif\r
155 \r
156 void ms_delay(uint32 ticks)\r
157 {\r
158         int i;\r
159         for(i=0; i<10*ticks; i++);\r
160 }       \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
170 \r
171 uint32 CHIP_GetAPBClk(void)\r
172 {\r
173     return ARM_CLK_26M;\r
174 }\r
175 \r
176 /*********************************************************************/\r
177 //  Description: i2c interrupt service \r
178 //  Input:\r
179 //      param         not use\r
180 //  Return:\r
181 //      None\r
182 //    Note: \r
183 //      None       \r
184 /*********************************************************************/\r
185 PUBLIC void I2C_Handler(uint32 param)\r
186 {\r
187     param = param; // avoid compiler warning\r
188 \r
189     /* set i2c flag  */    \r
190     g_wait_i2c_int_flag = FALSE;\r
191     \r
192     while((*(volatile uint32*)(I2C_CMD)) & I2CCMD_BUS);\r
193     \r
194     /* clear i2c int  */\r
195     CHIP_REG_OR(I2C_CMD, I2CCMD_INT_ACK);    \r
196 }\r
197 /*********************************************************************/\r
198 //  Description: i2c set SCL clock\r
199 //  Input:\r
200 //      freq     I2C SCL's frequency to be set\r
201 //  Return:\r
202 //      ERR_I2C_NONE    successfully\r
203 //    Note: \r
204 //      None       \r
205 /*********************************************************************/\r
206 PUBLIC ERR_I2C_E I2C_SetSCLclk(uint32 freq)\r
207 {\r
208     uint32 APB_clk,i2c_dvd;\r
209     \r
210     volatile I2C_CTL_REG_T *ptr = (volatile I2C_CTL_REG_T *)I2C_BASE;\r
211 \r
212     SCI_ASSERT(freq > 0);\r
213     SCI_ASSERT(g_i2c_open_flag);\r
214 \r
215     APB_clk= CHIP_GetAPBClk();\r
216     i2c_dvd=APB_clk/(4*freq)-1;\r
217 \r
218     ptr->div0=(uint16)(i2c_dvd & 0xffff);\r
219     ptr->div1=(uint16)(i2c_dvd>>16);\r
220 \r
221     g_i2c_timeout = I2C_TIMEOUT_FACTOR / (freq);\r
222     \r
223     if(g_i2c_timeout < 2)\r
224         g_i2c_timeout = 2;\r
225     //g_i2c_timeout will be changed according I2C frequency\r
226     \r
227     return ERR_I2C_NONE;\r
228      \r
229       \r
230 }\r
231 /*********************************************************************/\r
232 //  Description: i2c init fuction \r
233 //  Input:\r
234 //      freq     I2C SCL's frequency\r
235 //  Return:\r
236 //      ERR_I2C_NONE    successfully\r
237 //    Note: \r
238 //      None       \r
239 /*********************************************************************/\r
240 PUBLIC ERR_I2C_E I2C_Init(uint32 freq)\r
241 {    \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
244     */\r
245     volatile I2C_CTL_REG_T *ptr = (volatile I2C_CTL_REG_T *)I2C_BASE;\r
246 \r
247     freq*=1000;\r
248     SCI_ASSERT (freq > 0);\r
249 \r
250     g_wait_i2c_int_flag = TRUE;\r
251     g_i2c_open_flag=TRUE;\r
252 \r
253     // gen0, enable i2c device.\r
254 #if defined (CONFIG_SC8830) || defined(CONFIG_SC9630)\r
255     \r
256 #else\r
257     CHIP_REG_OR(GR_GEN0, GEN0_I2C_EN); //GEN0_I2C0_EN\r
258 #endif\r
259 \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
264 \r
265     I2C_SetSCLclk(freq);\r
266 \r
267     CHIP_REG_OR(I2C_CTL, (I2CCTL_IE | I2CCTL_EN));\r
268 \r
269      //Clear I2C int\r
270     CHIP_REG_OR(I2C_CMD, I2CCMD_INT_ACK); \r
271    \r
272     return ERR_I2C_NONE; \r
273 }\r
274 /*********************************************************************/\r
275 //  Description: get i2c SCL clock\r
276 //  Input:\r
277 //      None\r
278 //  Return:\r
279 //      the freq of i2c SCL clock\r
280 //    Note: \r
281 //      None       \r
282 /*********************************************************************/\r
283 PUBLIC uint32 I2C_GetSCLclk(void)\r
284 {\r
285     uint32 APB_clk,i2c_dvd,freq;\r
286     \r
287     volatile I2C_CTL_REG_T *ptr = (I2C_CTL_REG_T *)I2C_BASE;\r
288 \r
289     SCI_ASSERT(g_i2c_open_flag);\r
290 \r
291     APB_clk= CHIP_GetAPBClk();\r
292 \r
293     i2c_dvd=((ptr->div1)<<16)|(ptr->div0);\r
294 \r
295     freq=APB_clk/(4*(i2c_dvd+1));\r
296 \r
297 \r
298     return freq;\r
299 \r
300 }\r
301 /*********************************************************************/\r
302 //  Description: Write a command to a slave device\r
303 //  Input:\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
307 //  Return:\r
308 //      ERR_I2C_NONE    successfully\r
309 //    Note: \r
310 //      None       \r
311 /*********************************************************************/\r
312 PUBLIC ERR_I2C_E I2C_WriteCmd(uint8 addr,uint8 command, BOOLEAN ack_en)\r
313 {\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
318 \r
319     SCI_ASSERT(g_i2c_open_flag);\r
320     SCI_ASSERT(g_i2c_timeout > 0);\r
321     \r
322     cmd = ((uint32)addr)<<8;\r
323     cmd = cmd | I2CCMD_START | I2CCMD_WRITE;//send device address\r
324     ptr->cmd = cmd; \r
325 \r
326     I2C_WAIT_INT\r
327     \r
328     I2C_CLEAR_INT\r
329     \r
330     //check ACK\r
331     if(ack_en)\r
332     {\r
333         I2C_WAIT_ACK\r
334     }\r
335 \r
336     cmd = ((uint32)command)<<8;\r
337     cmd = cmd | I2CCMD_WRITE | I2CCMD_STOP;//send command\r
338     ptr->cmd = cmd; \r
339 \r
340     I2C_WAIT_INT\r
341        \r
342     I2C_CLEAR_INT  \r
343 \r
344     //check ACK\r
345     if(ack_en)\r
346     {\r
347         I2C_WAIT_ACK\r
348     }\r
349 \r
350     return ERR_I2C_NONE;\r
351             \r
352 }\r
353 \r
354 /*********************************************************************/\r
355 //  Description: Write a data to a slave device\r
356 //  Input:\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
360 //  Return:\r
361 //      ERR_I2C_NONE    successfully\r
362 //    Note: \r
363 //      None       \r
364 /*********************************************************************/\r
365 PUBLIC ERR_I2C_E I2C_WriteData(uint8 addr,uint8 data, BOOLEAN ack_en)\r
366 {\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
371 \r
372     SCI_ASSERT(g_i2c_open_flag);\r
373     SCI_ASSERT(g_i2c_timeout > 0);\r
374     \r
375     cmd = ((uint32)addr)<<8;\r
376     cmd = cmd | I2CCMD_START | I2CCMD_WRITE;//send device address\r
377     ptr->cmd = cmd; \r
378 \r
379     I2C_WAIT_INT\r
380     \r
381     I2C_CLEAR_INT\r
382     \r
383     //check ACK\r
384     if(ack_en)\r
385     {\r
386         I2C_WAIT_ACK\r
387     }\r
388 \r
389     data = ((uint32)data)<<8;\r
390     data = data | I2CCMD_WRITE | I2CCMD_STOP;//send command\r
391     ptr->cmd = data; \r
392 \r
393     I2C_WAIT_INT\r
394        \r
395     I2C_CLEAR_INT  \r
396 \r
397     //check ACK\r
398     if(ack_en)\r
399     {\r
400         I2C_WAIT_ACK\r
401     }\r
402 \r
403     return ERR_I2C_NONE;\r
404             \r
405 }\r
406 /*********************************************************************/\r
407 //  Description: read a command from the slave device\r
408 //  Input:\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
412 //  Return:\r
413 //      ERR_I2C_NONE    successfully\r
414 //    Note: \r
415 //      None       \r
416 /*********************************************************************/\r
417 PUBLIC ERR_I2C_E I2C_ReadCmd(uint8 addr,uint8 *pCmd, BOOLEAN ack_en)\r
418 {\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
423     \r
424     SCI_ASSERT(NULL != pCmd);\r
425     SCI_ASSERT(g_i2c_open_flag);\r
426     SCI_ASSERT(g_i2c_timeout > 0);\r
427 \r
428     cmd = ((uint32)(addr|I2C_READ_BIT))<<8;\r
429     cmd = cmd | I2CCMD_START | I2CCMD_WRITE;//send device address\r
430     ptr->cmd = cmd; \r
431 \r
432     I2C_WAIT_INT\r
433            \r
434     I2C_CLEAR_INT  \r
435 \r
436     //check ACK\r
437     if(ack_en)\r
438     {\r
439         I2C_WAIT_ACK\r
440     }\r
441 \r
442     cmd = I2CCMD_READ | I2CCMD_STOP | I2CCMD_TX_ACK;\r
443     ptr->cmd = cmd;\r
444      \r
445     I2C_WAIT_INT\r
446        \r
447     I2C_CLEAR_INT  \r
448 \r
449 \r
450     *pCmd=(uint8)((ptr->cmd)>>8);\r
451 \r
452     return ERR_I2C_NONE;\r
453 }\r
454 /*********************************************************************/\r
455 //  Description: Write the command array into the slave device \r
456 //  Input:\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
461 //  Return:\r
462 //      ERR_I2C_NONE    successfully\r
463 //    Note: \r
464 //      None       \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
469 {\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
473     \r
474     SCI_ASSERT(NULL != pCmd);\r
475     SCI_ASSERT(g_i2c_open_flag);\r
476     SCI_ASSERT(g_i2c_timeout > 0);\r
477     \r
478     cmd = ((uint32)addr)<<8;\r
479     cmd = cmd | I2CCMD_START | I2CCMD_WRITE ;//send device address 0x9824\r
480     ptr->cmd = cmd; \r
481 \r
482     I2C_WAIT_INT                \r
483     \r
484     I2C_CLEAR_INT   \r
485     \r
486     //check ACK\r
487     if(ack_en)\r
488     {\r
489         I2C_WAIT_ACK\r
490     }\r
491 \r
492     for(i=0;i<len;i++)\r
493     {\r
494         cmd = ((uint32)pCmd[i])<<8;\r
495         if(i== (len-1))     \r
496             cmd = cmd | I2CCMD_WRITE | I2CCMD_STOP;//send command\r
497         else\r
498             cmd = cmd | I2CCMD_WRITE ;\r
499 \r
500         ptr->cmd = cmd; \r
501 \r
502         I2C_WAIT_INT\r
503            \r
504         I2C_CLEAR_INT    \r
505 \r
506         //check ACK\r
507         if(ack_en)\r
508         {\r
509             I2C_WAIT_ACK\r
510         }\r
511 \r
512     }\r
513 \r
514     return ret_value;\r
515 }\r
516 /*********************************************************************/\r
517 //  Description: Read a command array from the slave device \r
518 //  Input:\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
523 //  Return:\r
524 //      ERR_I2C_NONE    successfully\r
525 //    Note: \r
526 //      None       \r
527 /*********************************************************************/\r
528 PUBLIC ERR_I2C_E I2C_ReadCmdArr(uint8 addr, uint8 *pCmd, uint32 len,BOOLEAN ack_en )\r
529 {\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
535     \r
536     SCI_ASSERT(NULL !=pCmd );\r
537     SCI_ASSERT(g_i2c_open_flag);\r
538     SCI_ASSERT(g_i2c_timeout > 0);\r
539 \r
540     cmd = ((uint32)(addr|I2C_READ_BIT))<<8;\r
541     cmd = cmd | I2CCMD_START | I2CCMD_WRITE;//send device address\r
542     ptr->cmd = cmd; \r
543 \r
544     I2C_WAIT_INT\r
545            \r
546     I2C_CLEAR_INT\r
547     \r
548     //check ACK\r
549     if(ack_en)\r
550     {\r
551         I2C_WAIT_ACK\r
552     }\r
553 \r
554     for(i=0;i<len;i++)\r
555     {\r
556         if(i<len-1)\r
557             cmd = I2CCMD_READ;  // I2CCMD_READ|I2CCMD_TX_ACK;\r
558         else\r
559             cmd = I2CCMD_READ|I2CCMD_STOP|I2CCMD_TX_ACK;\r
560 \r
561         ptr->cmd = cmd;\r
562 \r
563         I2C_WAIT_INT\r
564                    \r
565         I2C_CLEAR_INT   \r
566 \r
567         pCmd[i] = (uint8)((ptr->cmd)>>8);\r
568     }\r
569 \r
570     return ERR_I2C_NONE;\r
571 }\r
572 \r
573 \r
574 /**---------------------------------------------------------------------------*\r
575  **                         Compiler Flag                                     *\r
576  **---------------------------------------------------------------------------*/\r
577 \r
578 \r
579 #ifdef   __cplusplus\r
580     } \r
581 #endif\r
582 \r
583 /*  End Of File */\r