| /*   | 
 |  * (C) Copyright 2016, ZIXC Corporation. | 
 |  * | 
 |  */ | 
 |  | 
 | #include <common.h> | 
 | #include <command.h> | 
 | #include <malloc.h> | 
 | #include <asm/io.h>  | 
 | #include <i2c.h>  | 
 | #include <drvs_gpio.h> | 
 | #include <asm/arch/i2c.h>  | 
 | #include <asm/arch/hardware.h> | 
 | #include <asm/arch/uart.h> | 
 | #include <asm/arch/lsp_crpm.h> | 
 | #include <config.h> | 
 |  | 
 |  | 
 |  | 
 | T_I2C_Regs *p_i2c_reg[2] = {NULL}; | 
 | static uint retries = 3;            /* ÖØ¸´²Ù×÷´ÎÊý */ | 
 |  | 
 | #define REG32(x)			    (*(volatile u32*)(x)) | 
 |  | 
 |  | 
 | /******************************************************************************* | 
 |  * Function: | 
 |  * Description: | 
 |  * Parameters: | 
 |  *   Input: | 
 |  * | 
 |  *   Output: | 
 |  * | 
 |  * Returns: | 
 |  * | 
 |  * | 
 |  * Others: 1. ÔÚ100KHZƵÂÊÏ£¬Ê¹Óà zDrvI2c_DevRead_ByteStream ¶Á 32 ×Ö½Úʱ£¬(ÔÚU207ÊÖ»úÉÏ) | 
 |                                                            Ô¼ÏûºÄ tempTimeOut = 600 | 
 |            2. ÓÉÓÚCPUƵÂʲ»¶¨£¬bsp_udelayº¯ÊýÑÓʱ²»Ì«Çå³þ£¬¹ÊʹÓôó²ÎÊý | 
 |                                                            tempTimeOut = 0x20000; | 
 |  ********************************************************************************/ | 
 |  static int i2c_WaitTransferOver( T_I2C_Regs *i2c_reg ) | 
 | { | 
 |     uint tempTimeOut = 0x20000; | 
 |     uint tempStatus = 0x0; | 
 |  | 
 |     while( tempTimeOut ) | 
 |     { | 
 |         tempStatus = i2c_reg->I2C_STATUS; | 
 |         if(tempStatus & 0x1) | 
 |         { | 
 |             break; | 
 |         } | 
 |         else | 
 |         { | 
 |             tempTimeOut--; | 
 |         } | 
 |     } | 
 |     if( 0 == tempTimeOut ) | 
 |     { | 
 |         i2c_reg->I2C_STATUS |= I2C_IRQ_ACK; | 
 |         return DRV_I2C_ERROR_TIMEOUT;       /* ³¬Ê±´íÎó */ | 
 |     } | 
 |  | 
 |     if (tempStatus & I2C_IRQ_ERR_DEVICE) | 
 |     { | 
 |         i2c_reg->I2C_STATUS |= I2C_IRQ_ACK; | 
 |         return DRV_I2C_ERROR_DEVICE;        /* Æ÷¼þµØÖ·´«ÊäÆÚ¼äÓдíÎó·¢Éú */ | 
 |     } | 
 |     if (tempStatus & I2C_IRQ_ERR_DATA) | 
 |     { | 
 |         i2c_reg->I2C_STATUS |= I2C_IRQ_ACK; | 
 |         return DRV_I2C_ERROR_DATA;          /* ×ÓµØÖ·´«Êä»òÊý¾Ý´«Êä¹ý³ÌÖÐÓдíÎó·¢Éú */ | 
 |     } | 
 |  | 
 |     if (tempStatus & I2C_IRQ_TIME_OUT) | 
 |     { | 
 |         i2c_reg->I2C_STATUS |= I2C_IRQ_ACK; | 
 |         return DRV_I2C_ERROR_TIMEOUTSELF;   /* ³¬Ê±´íÎó */ | 
 |     } | 
 |  | 
 |     if (tempStatus & I2C_IRQ_TRANS_DONE) | 
 |     { | 
 |         i2c_reg->I2C_STATUS |= I2C_IRQ_ACK; | 
 |         return 0;                 /* Õý³£Íê³É */ | 
 |     } | 
 |     return 0; | 
 | } | 
 |  | 
 |  | 
 | /******************************************************************************* | 
 |  * Function: | 
 |  * Description: | 
 |  * Parameters: | 
 |  *   Input: | 
 |  * | 
 |  *   Output: | 
 |  * | 
 |  * Returns: | 
 |  * | 
 |  * | 
 |  * Others: ----------------------------- | 
 |  ********************************************************************************/ | 
 |  void i2c_Start( T_I2C_Regs *i2c_reg ) | 
 | { | 
 |     i2c_reg->CMD |= I2C_CMD_START;     /* ²úÉú¿ªÊ¼Ìõ¼þ£¬¿ªÊ¼´«Êä */ | 
 | } | 
 |  | 
 |  | 
 | /******************************************************************************* | 
 |  * Function: | 
 |  * Description: | 
 |  * Parameters: | 
 |  *   Input: | 
 |  * | 
 |  *   Output: | 
 |  * | 
 |  * Returns: | 
 |  * | 
 |  * | 
 |  * Others: | 
 |  ********************************************************************************/ | 
 |  static int i2c_ReadFifoData( T_I2C_Regs *i2c_reg, uchar *read_buf, uint read_len ) | 
 | { | 
 |     if( i2c_reg->RXF_STATUS & I2C_RX_FIFO_FULL ) | 
 |     { | 
 |         do | 
 |         { | 
 |             *read_buf++ = i2c_reg->DATA; | 
 |         } while( --read_len ); | 
 |     } | 
 |     else | 
 |     { | 
 |         return DRV_I2C_RECV_NOT_COMPLETE; | 
 |     } | 
 |     return 0; | 
 | } | 
 |  | 
 | /******************************************************************************* | 
 |  * Function: | 
 |  * Description: | 
 |  * Parameters: | 
 |  *   Input: | 
 |  * | 
 |  *   Output: | 
 |  * | 
 |  * Returns: | 
 |  * | 
 |  * | 
 |  * Others: ÕâÀïÖ±½ÓÈ϶¨ дµÄ¾ßÌåÊý¾Ý×î´ó¸öÊýΪ 30 £¬ÆäʵÔÚ 8λ¼Ä´æÆ÷ģʽÏÂ×î¶à¿ÉÒÔ 31¸ö | 
 |  ********************************************************************************/ | 
 |   void i2c_WriteFifoData( T_I2C_Regs *i2c_reg, uchar *writeBuf, uint writerNum ) | 
 | { | 
 |     do | 
 |     { | 
 |         i2c_reg->DATA = *writeBuf++;  /* дÊý¾Ý */ | 
 |     }while(--writerNum != 0); | 
 | } | 
 |  | 
 |  | 
 | /******************************************************************************* | 
 |  * Function: | 
 |  * Description: | 
 |  * Parameters: | 
 |  *   Input: | 
 |  * | 
 |  *   Output: | 
 |  * | 
 |  * Returns: | 
 |  * | 
 |  * | 
 |  * Others:   ÔÚÐ´ÕæÕýµÄÊý¾ÝǰдÈë¼Ä´æÆ÷µØÖ·µ½ FIFO | 
 |               1.8λ¼Ä´æÆ÷µØÖ· | 
 |               2.16λ¼Ä´æÆ÷µØÖ· | 
 |  ********************************************************************************/ | 
 |  static void i2c_WriteFifoRegAddr( T_I2C_Regs *i2c_reg, ushort reg_addr, uint reg_len ) | 
 | { | 
 |     ushort tempRegAddr = 0; | 
 |     if( reg_len == 16 )      // Èç¹ûλ16λ¼Ä´æÆ÷µØÖ·£¬ÏÈд--¸ß8λ--; ºóд -µÍ8λ-- | 
 |     { | 
 |             tempRegAddr = reg_addr; | 
 |             i2c_reg->DATA = tempRegAddr >> 8; | 
 |     } | 
 |     i2c_reg->DATA = reg_addr; | 
 | } | 
 |  | 
 | /******************************************************************************* | 
 |  * Function: | 
 |  * Description: | 
 |  * Parameters: | 
 |  *   Input: | 
 |  * | 
 |  *   Output: | 
 |  * | 
 |  * Returns: | 
 |  * | 
 |  * | 
 |  * Others: ÔÚ¼òµ¥Ð´Ä£Ê½ÏÂ( 8λ¼Ä´æÆ÷ºÍ16λ¼Ä´æÆ÷ )£¬ÉèÖà FifoDepth | 
 |                 1.¸´Î» ½ÓÊÕFIFO ºÍ ·¢ËÍFIFO | 
 |                 2.ÅжÏÊÇ·ñΪ16λ¼Ä´æÆ÷µØÖ·£¬ÈçÊÇ£¬Ôò writerNum +2; | 
 |                   ²»È»Îª 8 λ¼Ä´æÆ÷µØÖ·£¬            writerNum +1; | 
 |                 3.дÈë·¢Ë͸öÊýµ½ÏàÓ¦µÄ¼Ä´æÆ÷¡£ | 
 |  ********************************************************************************/ | 
 |  static void i2c_SetFifoDepthSimpleWrite( T_I2C_Regs *i2c_reg, uint write_len, uint reg_len ) | 
 | { | 
 |     uint tempWriterNum = write_len; | 
 |     //¸´Î»WRITE(read)_FIFO_SOFT_RESET | 
 |     i2c_reg->TXF_CTRL |= I2C_TX_FIFO_RST; | 
 |     i2c_reg->RXF_CTRL |= I2C_RX_FIFO_RST; | 
 |  | 
 |     if( reg_len == 16 )                 //ʹÓà 16λ¼Ä´æÆ÷µØÖ· | 
 |     { | 
 |         tempWriterNum++;                        //writerNum = writerNum + 2 - 1;                                             //ÕâÀï¼õÈ¥ÁËд¼Ä´æÆ÷ʱÐèÒª½«È¥µÄ 1 | 
 |     } | 
 |     i2c_reg->TXF_CTRL = tempWriterNum; | 
 |     i2c_reg->RXF_CTRL = 0; | 
 | } | 
 |  | 
 |  | 
 | /******************************************************************************* | 
 |  * Function: | 
 |  * Description: | 
 |  * Parameters: | 
 |  *   Input: | 
 |  * | 
 |  *   Output: | 
 |  * | 
 |  * Returns: | 
 |  * | 
 |  * | 
 |  * Others: | 
 |  ********************************************************************************/ | 
 |  static void i2c_SetFifoDepthCombineRead( T_I2C_Regs *i2c_reg, uint read_len, uint reg_len ) | 
 | { | 
 |     uint tempWriterNum = 0; | 
 |     //¸´Î»WRITE(read)_FIFO_SOFT_RESET | 
 |     i2c_reg->TXF_CTRL |= I2C_TX_FIFO_RST; | 
 |     i2c_reg->RXF_CTRL |= I2C_RX_FIFO_RST; | 
 |  | 
 |     if( reg_len == 16 )                   //ʹÓà 16λ¼Ä´æÆ÷µØÖ· | 
 |     { | 
 |         tempWriterNum++;                        //tempWriterNum = tempWriterNum + 2 - 1; | 
 |                                                 //ÕâÀï¼õÈ¥ÁËд¼Ä´æÆ÷ʱÐèÒª½«È¥µÄ 1 | 
 |     } | 
 |     i2c_reg->TXF_CTRL = tempWriterNum; | 
 |     i2c_reg->RXF_CTRL = --read_len; | 
 | } | 
 |  | 
 | /******************************************************************************* | 
 |  * Function:    i2c_SetFifoDepthSimpleRead | 
 |  * Description: | 
 |  * Parameters: | 
 |  *   Input: | 
 |  * | 
 |  *   Output: | 
 |  * | 
 |  * Returns: | 
 |  * | 
 |  * | 
 |  * Others: | 
 |  ********************************************************************************/ | 
 |  static void i2c_SetFifoDepthSimpleRead( T_I2C_Regs *pi2cReg, uint readNum ) | 
 | { | 
 |     //¸´Î»WRITE(read)_FIFO_SOFT_RESET | 
 |     pi2cReg->TXF_CTRL |= I2C_TX_FIFO_RST; | 
 |     pi2cReg->RXF_CTRL |= I2C_RX_FIFO_RST; | 
 |  | 
 |     pi2cReg->TXF_CTRL = 0; | 
 |     pi2cReg->RXF_CTRL = --readNum; | 
 | } | 
 |  | 
 | /******************************************************************************* | 
 |  * Function:    i2c_SetFifoDepthSimpleWriteWithoutReg | 
 |  * Description: | 
 |  * Parameters: | 
 |  *   Input: | 
 |  * | 
 |  *   Output: | 
 |  * | 
 |  * Returns: | 
 |  * | 
 |  * | 
 |  * Others: | 
 |  ********************************************************************************/ | 
 |  static void i2c_SetFifoDepthSimpleWriteWithoutReg( T_I2C_Regs *pi2cReg, uint writerNum ) | 
 | { | 
 |     //¸´Î»WRITE(read)_FIFO_SOFT_RESET | 
 |     pi2cReg->TXF_CTRL |= I2C_TX_FIFO_RST; | 
 |     pi2cReg->RXF_CTRL |= I2C_RX_FIFO_RST; | 
 |  | 
 |     pi2cReg->TXF_CTRL = writerNum - 1; | 
 |     pi2cReg->RXF_CTRL = 0; | 
 | } | 
 |  | 
 |  | 
 | /******************************************************************************* | 
 |  * Function:    i2c_SetFreq | 
 |  * Description: | 
 |  * Parameters: | 
 |  *   Input: | 
 |  * | 
 |  *   Output: | 
 |  * | 
 |  * Returns: | 
 |  * | 
 |  * | 
 |  * Others:      ÉèÖÃi2c×ÜÏߵįµÂÊ£¬CLK = Fref_clk/( (CLK_DIV_FS+1)*4 ) | 
 |                 Fref_clk = 26M | 
 |                ²ÎÊý:  I2C_FREQ_ONE_HUNDRED_KILO_HZ   100kHz  CLK_DIV_FS = 64 | 
 |                ²ÎÊý:  I2C_FREQ_THREE_HUNDRED_KILO_HZ 300kHz  CLK_DIV_FS = 21 | 
 |                ²ÎÊý:  I2C_FREQ_FOUR_HUNDRED_KILO_HZ  400kHz  CLK_DIV_FS = 16 | 
 |  ********************************************************************************/ | 
 |  static void i2c_SetFreq( T_I2C_Regs *pi2cReg, T_ZDrvI2c_BusFreq devFreq ) | 
 | { | 
 |     pi2cReg->CMD &= (~I2C_CMD_SPEED_MODE);  /* ʹÓÿìËÙģʽ */ | 
 |  | 
 |     switch( devFreq ) | 
 |     { | 
 |         case I2C_FREQ_ONE_HUNDRED_KILO_HZ: | 
 |             pi2cReg->CLK_DIV_FS = 64; | 
 |             break; | 
 |         case I2C_FREQ_THREE_HUNDRED_KILO_HZ: | 
 |             pi2cReg->CLK_DIV_FS = 21; | 
 |             break; | 
 |         case I2C_FREQ_FOUR_HUNDRED_KILO_HZ: | 
 |             pi2cReg->CLK_DIV_FS = 16; | 
 |             break; | 
 |         default: | 
 |             pi2cReg->CLK_DIV_FS = 64; | 
 |             break; | 
 |     } | 
 | } | 
 |  | 
 | /******************************************************************************* | 
 |  * Function: | 
 |  * Description: | 
 |  * Parameters: | 
 |  *   Input: | 
 |  * | 
 |  *   Output: | 
 |  * | 
 |  * Returns: | 
 |  * | 
 |  * | 
 |  * Others: ÉèÖÃI2C×ÜÏߵĶÁд·½Ê½£¬ÕâÀïĬÈÏΪÖ÷»úģʽ£¬²»Ê¹ÓÃÖÐ¶Ï | 
 |            ·ÖΪ ¼òµ¥Ð´¡¢¼òµ¥¶Á¡¢ ---×éºÏ¶Á--- ÈýÖÖģʽ | 
 |  ********************************************************************************/ | 
 | static void i2c_SetMode( T_I2C_Regs *i2c_reg, T_I2C_Mode mode ) | 
 | { | 
 |     uint cmd_reg = 0x0; | 
 |  | 
 |     cmd_reg |= I2C_IRQ_ACK;            //Çå³ýÖжϼ°ÆäËû´íÎó¼°×´Ì¬ | 
 |                                                     /* ÕâÀï·ÀÖ¹Çå³ýÉϴδ«Êä¿ÉÄܲúÉúµÄ´íÎó״̬ */ | 
 |     cmd_reg |= I2C_CMD_MS_SEL;             //Ö÷»úģʽ | 
 |     cmd_reg &= (~I2C_CMD_IRQ_EN);          //ÖжÏÇëÇ󹨱Õ; | 
 |  | 
 |     switch( mode ) | 
 |     { | 
 |         case I2C_SIMPLE_WRITE:                      //²ÉÓüòµ¥Ð´Ä£Ê½ | 
 |             cmd_reg &= (~(I2C_CMD_CMB_RW | I2C_CMD_RW)); | 
 |             break; | 
 |         case I2C_COMBINE_READ: | 
 |             cmd_reg |= I2C_CMD_CMB_RW;     //---²ÉÓÃ×éºÏ¶Á--- | 
 |             cmd_reg &= (~I2C_CMD_RW);      //0:w 1:r | 
 |             break; | 
 |         default: | 
 |             cmd_reg &= (~I2C_CMD_CMB_RW);  //²ÉÓüòµ¥¶Á | 
 |             cmd_reg |= I2C_CMD_RW; | 
 |             break; | 
 |     } | 
 |  | 
 |     i2c_reg->CMD = cmd_reg; | 
 | } | 
 |  | 
 |  | 
 | /******************************************************************************* | 
 |  * Function: | 
 |  * Description: д´Ó»úµØÖ· | 
 |  * Parameters: | 
 |  *   Input: | 
 |  * | 
 |  *   Output: | 
 |  * | 
 |  * Returns: | 
 |  * | 
 |  * | 
 |  * Others:        дÈë´Ó»úµØÖ·£¬ÕâÀïµÄ´Ó»úµØÖ·Ö§³Ö  --7λ--10λ--- ´Ó»úµØÖ· | 
 |                 1.7λ´Ó»úµØÖ·£¬²»Ê¹ÄÜ10λµØÖ·£¬Ö±½ÓдÈë´Ó»úµØÖ·¼Ä´æÆ÷¡£¸üе±Ç°×ÜÏߵĴӻúµØÖ· | 
 |                 2.10λ´Ó»úµØÖ·£¬Ê¹ÄÜ10λµØÖ·£¬·Ö±ðдÈëÏàÓ¦¼Ä´æÆ÷¡£ ¸üе±Ç°×ÜÏߵĴӻúµØÖ· | 
 |  ********************************************************************************/ | 
 | static void i2c_SetSlaveAddress( T_I2C_Regs *i2c_reg, ushort slaveAddr ) | 
 | { | 
 |     if( (slaveAddr & 0xf700) == 0 )                 /* 7λ´Ó»úµØÖ· */ | 
 |     { | 
 |         i2c_reg->CMD &= (~I2C_CMD_ADDR_MODE); | 
 |         i2c_reg->DEVICE_L = slaveAddr; | 
 |     } | 
 |     else | 
 |     { | 
 |         i2c_reg->CMD |= I2C_CMD_ADDR_MODE; | 
 |         i2c_reg->DEVICE_L = slaveAddr; | 
 |         i2c_reg->DEVICE_H = slaveAddr >> 7; | 
 |     } | 
 |  | 
 | } | 
 |  | 
 |  | 
 | /* ================================================================================ | 
 |  *  i2c_read: | 
 |  */ | 
 | int i2c_read(uint i2c_bus, ushort slave_addr, ushort reg_addr, uint reg_len, | 
 |                                                     uchar *read_buf, uint read_len) | 
 | { | 
 | 	int ret = 0; | 
 | 	T_I2C_Regs *i2c_Reg = p_i2c_reg[i2c_bus]; | 
 |  | 
 | 	do                                  //¿ªÊ¼´«Êä | 
 | 	{ | 
 | 		i2c_SetFreq(i2c_Reg, I2C_FREQ_ONE_HUNDRED_KILO_HZ);			//ÉèÖÃ×ÜÏ߯µÂÊ | 
 | 		i2c_SetSlaveAddress(i2c_Reg, slave_addr);                   //д´Ó»úµØÖ· | 
 | 		i2c_SetMode(i2c_Reg, I2C_COMBINE_READ);                     //×éºÏ¶Áģʽ | 
 | 		i2c_SetFifoDepthCombineRead(i2c_Reg, read_len, reg_len);    //ÉèÖÃFIFOµÄÉî¶È | 
 | 		i2c_WriteFifoRegAddr(i2c_Reg, reg_addr, reg_len);           //ÍùFIFOÖÐдÈë¼Ä´æÆ÷µØÖ· | 
 | 		i2c_Start(i2c_Reg);                                         //²úÉú¿ªÊ¼Ìõ¼þ£¬¿ªÊ¼´«Êä | 
 | 		ret = i2c_WaitTransferOver(i2c_Reg);                        //µÈ´ý´«Êä½áÊø | 
 | 		if( ret != 0 ) | 
 | 		{ | 
 | 			continue;                   //´«Êäʧ°Ü£¬½áÊø±¾´ÎÑ»·²¢ÖØ´« | 
 | 		} | 
 | 		ret = i2c_ReadFifoData(i2c_Reg, read_buf, read_len );       //¶ÁÈ¡Êý¾Ý | 
 | 		if( ret != 0 ) | 
 | 		{ | 
 | 			continue;                   //´«Êäʧ°Ü£¬½áÊø±¾´ÎÑ»·²¢ÖØ´« | 
 | 		} | 
 | 		break;                          //´«Êä³É¹¦£¬Ìø³öÑ»· | 
 | 	} while( --retries != 0 ); | 
 | 	retries = 3; | 
 |  | 
 | 	return ret; | 
 | } | 
 |  | 
 | /* ================================================================================ | 
 |  *  i2c_write: | 
 |  */ | 
 | int i2c_write(uint i2c_bus, ushort slave_addr, ushort reg_addr, uint reg_len, | 
 |                                                 uchar *write_buf, uint write_len) | 
 | { | 
 |     int ret = 0; | 
 |     T_I2C_Regs *i2c_Reg = p_i2c_reg[i2c_bus]; | 
 |  | 
 |     do                                  //¿ªÊ¼´«Êä | 
 |     { | 
 | 		i2c_SetFreq(i2c_Reg, I2C_FREQ_ONE_HUNDRED_KILO_HZ);								//ÉèÖÃ×ÜÏ߯µÂÊ | 
 |         i2c_SetSlaveAddress(i2c_Reg, slave_addr);                   //д´Ó»úµØÖ· | 
 |         i2c_SetMode(i2c_Reg, I2C_SIMPLE_WRITE);                     //×éºÏ¶Áģʽ | 
 |         i2c_SetFifoDepthSimpleWrite(i2c_Reg, write_len, reg_len);   //ÉèÖÃFIFOµÄÉî¶È | 
 |         i2c_WriteFifoRegAddr(i2c_Reg, reg_addr, reg_len);           //ÍùFIFOÖÐдÈë¼Ä´æÆ÷µØÖ· | 
 |         i2c_WriteFifoData(i2c_Reg, write_buf, write_len);           //ÍùFIFOдÈëÊý¾Ý | 
 |         i2c_Start(i2c_Reg);                                         //²úÉú¿ªÊ¼Ìõ¼þ£¬¿ªÊ¼´«Êä | 
 |         ret = i2c_WaitTransferOver(i2c_Reg);                        //µÈ´ý´«Êä½áÊø | 
 |         if( ret != 0 ) | 
 |         { | 
 |             continue;                   //´«Êäʧ°Ü£¬½áÊø±¾´ÎÑ»·²¢ÖØ´« | 
 |         } | 
 |         break;                          //´«Êä³É¹¦£¬Ìø³öÑ»· | 
 |     } while( --retries != 0 ); | 
 | 	retries = 3; | 
 |  | 
 |     return ret; | 
 | } | 
 |  | 
 | /* ================================================================================ | 
 |  *  i2c_simple_read: | 
 |  */ | 
 | int i2c_simple_read(uint i2c_bus, ushort slave_addr, uchar *read_buf, uint read_len) | 
 | { | 
 |     int ret = 0; | 
 |     T_I2C_Regs *i2c_Reg = p_i2c_reg[i2c_bus]; | 
 |  | 
 |     if ( (i2c_Reg == NULL) || (read_buf == NULL) || (read_len > 33))//×î¶àд 32 ¸ö×Ö½Ú | 
 |     { | 
 |         return -1; | 
 |     } | 
 |  | 
 |     do                                  //¿ªÊ¼´«Êä | 
 |     { | 
 | 		i2c_SetFreq(i2c_Reg, I2C_FREQ_FOUR_HUNDRED_KILO_HZ);								//ÉèÖÃ×ÜÏ߯µÂÊ | 
 |         i2c_SetSlaveAddress(i2c_Reg, slave_addr);                   //д´Ó»úµØÖ· | 
 |         i2c_SetMode(i2c_Reg, I2C_SIMPLE_READ);                     //×éºÏ¶Áģʽ | 
 |         i2c_SetFifoDepthSimpleRead(i2c_Reg, read_len);    //ÉèÖÃFIFOµÄÉî¶È | 
 |         i2c_Start(i2c_Reg);                                         //²úÉú¿ªÊ¼Ìõ¼þ£¬¿ªÊ¼´«Êä | 
 |         ret = i2c_WaitTransferOver(i2c_Reg);                        //µÈ´ý´«Êä½áÊø | 
 |         if( ret != 0 ) | 
 |         { | 
 |             continue;                   //´«Êäʧ°Ü£¬½áÊø±¾´ÎÑ»·²¢ÖØ´« | 
 |         } | 
 |         ret = i2c_ReadFifoData(i2c_Reg, read_buf, read_len );       //¶ÁÈ¡Êý¾Ý | 
 |         if( ret != 0 ) | 
 |         { | 
 |             continue;                   //´«Êäʧ°Ü£¬½áÊø±¾´ÎÑ»·²¢ÖØ´« | 
 |         } | 
 |         break;                          //´«Êä³É¹¦£¬Ìø³öÑ»· | 
 |     } while( --retries != 0 ); | 
 | 	retries = 3; | 
 |  | 
 |     return ret; | 
 | } | 
 |  | 
 | /* ================================================================================ | 
 |  *  i2c_simple_write: | 
 |  */ | 
 | int i2c_simple_write(uint i2c_bus, ushort slave_addr,uchar *write_buf, uint write_len) | 
 | { | 
 |     int ret = 0; | 
 |     T_I2C_Regs *i2c_Reg = p_i2c_reg[i2c_bus]; | 
 |  | 
 |     if ( (i2c_Reg == NULL) || (write_buf == NULL) || (write_len > 33))//×î¶àд 32 ¸ö×Ö½Ú | 
 |     { | 
 |         return -1; | 
 |     } | 
 |  | 
 |     do                                  //¿ªÊ¼´«Êä | 
 |     { | 
 | 		i2c_SetFreq(i2c_Reg, I2C_FREQ_FOUR_HUNDRED_KILO_HZ);								//ÉèÖÃ×ÜÏ߯µÂÊ | 
 |         i2c_SetSlaveAddress(i2c_Reg, slave_addr);                   //д´Ó»úµØÖ· | 
 |         i2c_SetMode(i2c_Reg, I2C_SIMPLE_WRITE);                     //×éºÏ¶Áģʽ | 
 |         i2c_SetFifoDepthSimpleWriteWithoutReg(i2c_Reg, write_len);   //ÉèÖÃFIFOµÄÉî¶È | 
 |         i2c_WriteFifoData(i2c_Reg, write_buf, write_len);           //ÍùFIFOдÈëÊý¾Ý | 
 |         i2c_Start(i2c_Reg);                                         //²úÉú¿ªÊ¼Ìõ¼þ£¬¿ªÊ¼´«Êä | 
 |         ret = i2c_WaitTransferOver(i2c_Reg);                        //µÈ´ý´«Êä½áÊø | 
 |         if( ret != 0 ) | 
 |         { | 
 |             continue;                   //´«Êäʧ°Ü£¬½áÊø±¾´ÎÑ»·²¢ÖØ´« | 
 |         } | 
 |         break;                          //´«Êä³É¹¦£¬Ìø³öÑ»· | 
 |     } while( --retries != 0 ); | 
 | 	retries = 3; | 
 |  | 
 |     return ret; | 
 | } | 
 |  | 
 | /* ================================================================================ | 
 |  *  i2c_init: | 
 |  */ | 
 | int i2c_init(void) | 
 | { | 
 | 	p_i2c_reg[0] = (T_I2C_Regs *)ARM_I2C0_BASE; | 
 | 	p_i2c_reg[1] = (T_I2C_Regs *)ARM_I2C1_BASE; | 
 | 	/* p_i2c_reg[2] = (T_I2C_Regs *)ARM_PMICI2C_BASE; */ | 
 |  | 
 | 	/* gpio config */ | 
 | 	//gpio_set_reuse(GPIO_I2C0_CLK, 0x0); | 
 | 	zDrvGpio_SetFunc(GPIO43, GPIO43_SCL0); | 
 | 	zDrvGpio_SetDirection(GPIO43, GPIO_OUT); | 
 | 	//gpio_set_reuse(GPIO_I2C0_DATA, 0x0); | 
 | 	zDrvGpio_SetFunc(GPIO44, GPIO44_SDA0);	 | 
 | 	zDrvGpio_SetDirection(GPIO44, GPIO_OUT); | 
 | 	//gpio_set_reuse(GPIO_I2C1_CLK, 0x0); | 
 | 	zDrvGpio_SetFunc(GPIO45, GPIO45_SCL1); | 
 | 	zDrvGpio_SetDirection(GPIO45, GPIO_OUT); | 
 | 	//gpio_set_reuse(GPIO_I2C1_DATA, 0x0); | 
 | 	zDrvGpio_SetFunc(GPIO46, GPIO46_SDA1);	 | 
 | 	zDrvGpio_SetDirection(GPIO46, GPIO_OUT); | 
 |  | 
 | 	/* i2c1 new clk config */ | 
 | 	REG32(0x140002c) &= ~(0x1<<4);//i2c1 select 26M | 
 | 	REG32(0x140002c) &= ~(0x1<<8);//reset on  i2c1 apb clk | 
 | 	REG32(0x140002c) |= (0x1<<8);//reset off  i2c1 apb clk | 
 | 	REG32(0x140002c) &= ~(0x1<<9);//reset on i2c1 work clk | 
 | 	REG32(0x140002c) |= (0x1<<9);//reset off i2c1 work clk | 
 | 	REG32(0x140002c) |= (0x1<<0);//enable i2c1 apb clk | 
 | 	REG32(0x140002c) |= (0x1<<1);//enable i2c1 work clk | 
 |  | 
 | 	/* pmic i2c clk config */ | 
 | 	REG32(0x13b03c) &= ~(0x1<<1);//pmici2c select 26M | 
 | 	REG32(0x13b074) &= ~(0x1<<8);//reset on  pmici2c apb clk | 
 | 	REG32(0x13b074) |= (0x1<<8);//reset off  pmici2c apb clk | 
 | 	REG32(0x13b074) &= ~(0x1<<9);//reset on pmici2c work clk | 
 | 	REG32(0x13b074) |= (0x1<<9);//reset off pmici2c work clk | 
 | 	REG32(0x13b054) |= (0x1<<8);//enable pmici2c apb clk | 
 | 	REG32(0x13b054) |= (0x1<<9);//enable pmici2c work clk | 
 |  | 
 | 	return 0; | 
 | } | 
 |  |