1 /******************************************************************************
2 ** File Name: I2C_drv.c *
5 ** Copyright: 2010 Spreatrum, Incoporated. All Rights Reserved. *
6 ** Description: This file define the hal layer of I2C device. *
7 ******************************************************************************
9 ******************************************************************************
11 ** ------------------------------------------------------------------------- *
12 ** DATE NAME DESCRIPTION *
13 ** 06/28/2010 liuhao Create. *
14 ******************************************************************************/
16 /**---------------------------------------------------------------------------*
18 **---------------------------------------------------------------------------*/
19 #include "asm/arch/sci_types.h"
21 //#include "chip_plf_export.h"
22 #include "sp8830_i2c.h"
23 #include "sc8830_i2c_cfg.h"
25 /**---------------------------------------------------------------------------*
27 **---------------------------------------------------------------------------*/
29 /**---------------------------------------------------------------------------*
31 **---------------------------------------------------------------------------*/
37 /**---------------------------------------------------------------------------*
39 **---------------------------------------------------------------------------*/
42 //SCI_MUTEX_PTR mutex;
50 #define I2C_GetMutex(mutex) {\
51 uint32 ret = SCI_SUCCESS;\
54 return ERR_I2C_NO_MUTEX;\
56 if(SCI_InThreadContext())\
58 ret = SCI_GetMutex(mutex, SCI_INVALID_BLOCK_ID != SCI_IdentifyThread() ? SCI_WAIT_FOREVER : 0);\
60 SCI_ASSERT( ret == SCI_SUCCESS );//assert verified\
63 #define I2C_PutMutex(mutex) {\
64 uint32 ret = SCI_SUCCESS;\
67 return ERR_I2C_NO_MUTEX;\
69 if(SCI_InThreadContext())\
71 ret = SCI_PutMutex( mutex );\
73 SCI_ASSERT( ret == SCI_SUCCESS );//assert verified\
76 /**---------------------------------------------------------------------------*
78 **---------------------------------------------------------------------------*/
79 LOCAL I2C_DEV __i2c_dev[I2C_BUS_MAX *I2C_DEV_MAX];
81 /**---------------------------------------------------------------------------*
83 **---------------------------------------------------------------------------*/
84 I2C_BUS __i2c_bus[I2C_BUS_MAX];
85 extern const I2C_PHY_CFG __i2c_phy_cfg[I2C_ID_MAX];
87 /**---------------------------------------------------------------------------*
88 ** Function Definitions
89 **---------------------------------------------------------------------------*/
90 /*********************************************************************************************************
99 *********************************************************************************************************/
100 LOCAL uint32 I2C_Bus_CFG (uint32 logic_id)
102 uint32 bus_id = __i2c_phy_cfg[logic_id].phy_id;
103 /*config bus method*/
104 __i2c_bus[bus_id].phy_fun = __i2c_phy_cfg[logic_id].phy_fun;
107 /*********************************************************************************************************
114 ** output parameters:
116 *********************************************************************************************************/
117 LOCAL uint32 I2C_Bus_Init (uint32 logic_id, uint32 freq, uint32 port_id)
119 uint32 bus_id = __i2c_phy_cfg[logic_id].phy_id;
120 IIC_PRINT ("[IIC DRV:]I2C_Bus_Init");
121 /*config bus property*/
122 __i2c_bus[bus_id].current_freq = freq;
123 __i2c_bus[bus_id].current_port = port_id;
124 //__i2c_bus[bus_id].mutex = SCI_CreateMutex ("I2C SYNC MUTEX", SCI_INHERIT);
125 //SCI_PASSERT ( (NULL!= __i2c_bus[bus_id].mutex), ("I2C Great MUTEX fail!"));/*assert verified*/
126 /*config bus method*/
127 I2C_Bus_CFG (logic_id);
131 /*********************************************************************************************************
138 ** output parameters:
140 *********************************************************************************************************/
141 LOCAL uint32 I2C_Bus_Exit (uint32 bus_id)
143 uint32 status_val = 0;
144 __i2c_bus[bus_id].reference = 0;
147 if (NULL != __i2c_bus[bus_id].mutex)
149 status_val = SCI_DeleteMutex (__i2c_bus[bus_id].mutex);
150 //SCI_PASSERT((0 != status_val),("I2C delete MUTEX fail!"));
151 __i2c_bus[bus_id].mutex = NULL;
154 IIC_PRINT ("[IIC DRV:]I2C_Bus_Exit: status=%d", status_val);
155 /*release the bus method*/
156 __i2c_bus[bus_id].phy_fun = NULL;
160 /*********************************************************************************************************
161 ** Function name: I2C_HAL_Open
162 ** Descriptions: i2c bus open function
164 ** dev - pointer of i2c slave dev
167 ** output parameters: NONE
168 ** Returned value: handle
169 *********************************************************************************************************/
170 PUBLIC int32 I2C_HAL_Open (I2C_DEV *dev)
177 //SCI_ASSERT (NULL != dev);/*assert verified*/
178 /*check if use the wrong port number*/
179 //SCI_ASSERT ( ( (I2C_ID_MAX > dev->id) && (0 <= dev->id)));/*assert verified*/
180 /*now we should get the i2c bus id and the controller's port id*/
181 bus_id = __i2c_phy_cfg[dev->id].phy_id;
182 port_id = __i2c_phy_cfg[dev->id].port_id;
183 /*reference shouldn't larger than I2C_DEV_MAX*/
184 //SCI_ASSERT ( ( (I2C_DEV_MAX > __i2c_bus[bus_id].reference) && (0 <= __i2c_bus[bus_id].reference)));/*assert verified*/
186 /*look for the handle: return the 1st available array member*/
187 for (i=0; i< I2C_DEV_MAX; i++)
189 if (0 == __i2c_dev[idx + bus_id * I2C_DEV_MAX].freq)
196 if (I2C_DEV_MAX == idx)
203 handle = idx + bus_id * I2C_DEV_MAX;
204 /*set the parameters for i2c slave device*/
205 __i2c_dev[handle].id = dev->id;
206 __i2c_dev[handle].freq = dev->freq;
207 __i2c_dev[handle].bus = bus_id;
208 __i2c_dev[handle].slave_addr = dev->slave_addr;
209 __i2c_dev[handle].reg_addr_num = dev->reg_addr_num;
210 __i2c_dev[handle].check_ack = dev->check_ack;
211 __i2c_dev[handle].no_stop = dev->no_stop;
213 /*first open, than init i2c controller*/
214 if (0 == __i2c_bus[bus_id].reference)
216 I2C_Bus_Init (dev->id, dev->freq, port_id);
217 __i2c_bus[bus_id].phy_fun->init (bus_id, dev->freq, port_id);
220 __i2c_bus[bus_id].reference++;
222 IIC_PRINT ("[IIC DRV:]I2C_HAL_Open: handle=%d, ref=%d", handle, __i2c_bus[bus_id].reference);
227 /*********************************************************************************************************
234 ** output parameters:
236 *********************************************************************************************************/
237 PUBLIC int32 I2C_HAL_Close (uint32 handle)
240 /*handle shouldn't larger than I2C_BUS_MAX*I2C_DEV_MAX*/
241 //SCI_ASSERT ( ( (I2C_BUS_MAX * I2C_DEV_MAX > handle) && (0 <= handle)));/*assert verified*/
243 /*this handle is already closed*/
244 if (0 == __i2c_dev[handle].freq)
249 bus_id = __i2c_dev[handle].bus;
251 if (1 == __i2c_bus[bus_id].reference)
253 I2C_Bus_Exit (bus_id);
257 __i2c_bus[bus_id].reference--;
260 /*release the handle*/
261 __i2c_dev[handle].id = 0;
262 __i2c_dev[handle].freq = 0;
263 __i2c_dev[handle].slave_addr = 0;
264 __i2c_dev[handle].reg_addr_num = 0;
265 __i2c_dev[handle].check_ack = 0;
266 __i2c_dev[handle].no_stop = 0;
268 IIC_PRINT ("[IIC DRV:]I2C_HAL_Close: handle=%d, ref=%d", handle, __i2c_bus[bus_id].reference);
273 /*********************************************************************************************************
280 ** output parameters:
282 *********************************************************************************************************/
283 PUBLIC uint32 I2C_HAL_Read (uint32 handle, uint8 *reg_addr, uint8 *buffer, uint32 bytes)
289 /*handle shouldn't larger than I2C_BUS_MAX*I2C_DEV_MAX*/
290 //SCI_ASSERT ( ( (I2C_BUS_MAX * I2C_DEV_MAX > handle) && (0 <= handle)));/*assert verified*/
291 //SCI_ASSERT (NULL != buffer);/*assert verified*/
292 //SCI_ASSERT (0 < bytes);/*assert verified*/
293 /*the handle has destroied*/
294 //SCI_ASSERT (0 != __i2c_dev[handle].freq);/*assert verified*/
295 bus_id = __i2c_dev[handle].bus;
296 port_id = __i2c_phy_cfg[__i2c_dev[handle].id].port_id;
298 //I2C_GetMutex (__i2c_bus[bus_id].mutex);
300 /*set i2c controller*/
301 if ( (__i2c_bus[bus_id].current_freq != __i2c_dev[handle].freq) ||
302 (__i2c_bus[bus_id].current_port != port_id))
304 __i2c_bus[bus_id].phy_fun->init (bus_id, __i2c_dev[handle].freq, port_id);
305 __i2c_bus[bus_id].current_freq = __i2c_dev[handle].freq;
306 __i2c_bus[bus_id].current_port = port_id;
313 /*this is for combined format*/
314 if (0 < __i2c_dev[handle].reg_addr_num)
316 //SCI_ASSERT (NULL != reg_addr);/*assert verified*/
318 ret_val = __i2c_bus[bus_id].phy_fun->start (bus_id, __i2c_dev[handle].slave_addr, 0, __i2c_dev[handle].check_ack);
320 if (ERR_I2C_NONE != ret_val)
325 /*write i2c slave device's sub address*/
326 ret_val = __i2c_bus[bus_id].phy_fun->write (bus_id, reg_addr, __i2c_dev[handle].reg_addr_num, __i2c_dev[handle].check_ack, __i2c_dev[handle].no_stop);
328 if (ERR_I2C_NONE != ret_val)
335 ret_val = __i2c_bus[bus_id].phy_fun->start (bus_id, __i2c_dev[handle].slave_addr, 1, __i2c_dev[handle].check_ack);
337 if (ERR_I2C_NONE != ret_val)
342 /*read data and stop bus*/
343 ret_val = __i2c_bus[bus_id].phy_fun->read (bus_id, buffer, bytes, __i2c_dev[handle].check_ack);
345 if (ERR_I2C_NONE != ret_val)
355 //I2C_PutMutex (__i2c_bus[bus_id].mutex);
359 /*********************************************************************************************************
366 ** output parameters:
368 *********************************************************************************************************/
369 PUBLIC uint32 I2C_HAL_Write (uint32 handle, uint8 *reg_addr, uint8 *buffer, uint32 bytes)
375 /*handle shouldn't larger than I2C_BUS_MAX*I2C_DEV_MAX*/
376 //SCI_ASSERT ( ( (I2C_BUS_MAX * I2C_DEV_MAX > handle) && (0 <= handle)));/*assert verified*/
377 //SCI_ASSERT (NULL != buffer);/*assert verified*/
378 //SCI_ASSERT (0 < bytes);/*assert verified*/
379 /*the handle has destroied*/
380 //SCI_ASSERT (0 != __i2c_dev[handle].freq);/*assert verified*/
381 bus_id = __i2c_dev[handle].bus;
382 port_id = __i2c_phy_cfg[__i2c_dev[handle].id].port_id;
384 //I2C_GetMutex (__i2c_bus[bus_id].mutex);
386 /*set i2c controller*/
387 if ( (__i2c_bus[bus_id].current_freq != __i2c_dev[handle].freq) ||
388 (__i2c_bus[bus_id].current_port != port_id))
390 __i2c_bus[bus_id].phy_fun->init (bus_id, __i2c_dev[handle].freq, port_id);
391 __i2c_bus[bus_id].current_freq = __i2c_dev[handle].freq;
392 __i2c_bus[bus_id].current_port = port_id;
399 ret_val = __i2c_bus[bus_id].phy_fun->start (bus_id, __i2c_dev[handle].slave_addr, 0, __i2c_dev[handle].check_ack);
401 if (ERR_I2C_NONE != ret_val)
406 /*write i2c slave device's sub address*/
407 if (0 < __i2c_dev[handle].reg_addr_num)
409 //SCI_ASSERT (NULL != reg_addr);/*assert verified*/
410 ret_val = __i2c_bus[bus_id].phy_fun->write (bus_id, reg_addr, __i2c_dev[handle].reg_addr_num, __i2c_dev[handle].check_ack, 2);
412 if (ERR_I2C_NONE != ret_val)
418 /*write i2c slave device's data and stop bus*/
419 ret_val = __i2c_bus[bus_id].phy_fun->write (bus_id, buffer, bytes, __i2c_dev[handle].check_ack, 0);
421 if (ERR_I2C_NONE != ret_val)
431 //I2C_PutMutex (__i2c_bus[bus_id].mutex);
435 /*********************************************************************************************************
442 ** output parameters:
444 *********************************************************************************************************/
445 PUBLIC uint32 I2C_HAL_Ioctl (uint32 handle, uint32 cmd, uint32 *arg)
449 /*handle shouldn't larger than I2C_BUS_MAX*I2C_DEV_MAX*/
450 //SCI_ASSERT ( ( (I2C_BUS_MAX * I2C_DEV_MAX > handle) && (0 <= handle)));/*assert verified*/
451 //SCI_ASSERT (NULL != arg);/*assert verified*/
452 bus_id = __i2c_dev[handle].bus;
457 *arg = __i2c_dev[handle].freq;
460 __i2c_dev[handle].freq = *arg;
463 *arg = __i2c_dev[handle].id;
466 __i2c_dev[handle].id = *arg;
468 case I2C_CTL_STOP_BUS:
470 // I2C_GetMutex (__i2c_bus[bus_id].mutex);
471 ret_val = __i2c_bus[bus_id].phy_fun->stop (bus_id);
473 // I2C_PutMutex (__i2c_bus[bus_id].mutex);
482 /**---------------------------------------------------------------------------*
484 **---------------------------------------------------------------------------*/