288 lines
7.4 KiB
C
288 lines
7.4 KiB
C
|
/*
|
|||
|
*********************************************************************************************************
|
|||
|
* LINUX-KERNEL
|
|||
|
* AllWinner Linux Platform Develop Kits
|
|||
|
* Kernel Module
|
|||
|
*
|
|||
|
* (c) Copyright 2006-2011, kevin.z China
|
|||
|
* All Rights Reserved
|
|||
|
*
|
|||
|
* File : standby_twi.c
|
|||
|
* By : kevin.z
|
|||
|
* Version : v1.0
|
|||
|
* Date : 2011-5-31 15:22
|
|||
|
* Descript:
|
|||
|
* Update : date auther ver notes
|
|||
|
*********************************************************************************************************
|
|||
|
*/
|
|||
|
#include "standby_i.h"
|
|||
|
|
|||
|
#define TWI_CHECK_TIMEOUT (0x2ff)
|
|||
|
|
|||
|
static __twic_reg_t* TWI_REG_BASE[3] = {
|
|||
|
(__twic_reg_t*)IO_ADDRESS(AW_TWI0_BASE),
|
|||
|
(__twic_reg_t*)IO_ADDRESS(AW_TWI1_BASE),
|
|||
|
(__twic_reg_t*)IO_ADDRESS(AW_TWI2_BASE)
|
|||
|
};
|
|||
|
|
|||
|
static __u32 TwiClkRegBak = 0;
|
|||
|
static __u32 TwiCtlRegBak = 0;
|
|||
|
static __twic_reg_t *twi_reg = (__twic_reg_t *)(0);
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
*********************************************************************************************************
|
|||
|
* standby_twi_init
|
|||
|
*
|
|||
|
*Description: init twi transfer.
|
|||
|
*
|
|||
|
*Arguments :
|
|||
|
*
|
|||
|
*Return :
|
|||
|
*
|
|||
|
*********************************************************************************************************
|
|||
|
*/
|
|||
|
__s32 standby_twi_init(int group)
|
|||
|
{
|
|||
|
twi_reg = TWI_REG_BASE[group];
|
|||
|
TwiClkRegBak = twi_reg->reg_clkr;
|
|||
|
TwiCtlRegBak = 0x80&twi_reg->reg_ctl;/* backup INT_EN;no need for BUS_EN(0xc0) */
|
|||
|
//twi_reg->reg_clkr = (2<<3)|3; //100k
|
|||
|
twi_reg->reg_clkr = (5<<3)|0; //400k, M = 5, N=0;
|
|||
|
|
|||
|
twi_reg->reg_reset |= 0x1;
|
|||
|
while(twi_reg->reg_reset&0x1);
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
*********************************************************************************************************
|
|||
|
* standby_twi_exit
|
|||
|
*
|
|||
|
*Description: exit twi transfer.
|
|||
|
*
|
|||
|
*Arguments :
|
|||
|
*
|
|||
|
*Return :
|
|||
|
*
|
|||
|
*********************************************************************************************************
|
|||
|
*/
|
|||
|
__s32 standby_twi_exit(void)
|
|||
|
{
|
|||
|
/* softreset twi module */
|
|||
|
twi_reg->reg_reset |= 0x1;
|
|||
|
/* delay */
|
|||
|
//change_runtime_env();
|
|||
|
//delay_ms(10);
|
|||
|
|
|||
|
/* restore clock division */
|
|||
|
twi_reg->reg_clkr = TwiClkRegBak;
|
|||
|
/* restore INT_EN */
|
|||
|
twi_reg->reg_ctl |= TwiCtlRegBak;
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
*********************************************************************************************************
|
|||
|
* _standby_twi_stop
|
|||
|
*
|
|||
|
*Description: stop current twi transfer.
|
|||
|
*
|
|||
|
*Arguments :
|
|||
|
*
|
|||
|
*Return :
|
|||
|
*
|
|||
|
*********************************************************************************************************
|
|||
|
*/
|
|||
|
static int _standby_twi_stop(void)
|
|||
|
{
|
|||
|
unsigned int nop_read;
|
|||
|
unsigned int timeout = TWI_CHECK_TIMEOUT;
|
|||
|
|
|||
|
twi_reg->reg_ctl = (twi_reg->reg_ctl & 0xc0) | 0x10 | 0x08;/* set stop+clear int flag */
|
|||
|
|
|||
|
nop_read = twi_reg->reg_ctl;
|
|||
|
nop_read = nop_read;
|
|||
|
// 1. stop bit is zero.
|
|||
|
while((twi_reg->reg_ctl & 0x10)&&(timeout--));
|
|||
|
if(timeout == 0)
|
|||
|
{
|
|||
|
return -1;
|
|||
|
}
|
|||
|
// 2. twi fsm is idle(0xf8).
|
|||
|
timeout = TWI_CHECK_TIMEOUT;
|
|||
|
while((0xf8 != twi_reg->reg_status)&&(timeout--));
|
|||
|
if(timeout == 0)
|
|||
|
{
|
|||
|
return -1;
|
|||
|
}
|
|||
|
// 3. twi scl & sda must high level.
|
|||
|
timeout = TWI_CHECK_TIMEOUT;
|
|||
|
while((0x3a != twi_reg->reg_lctl)&&(timeout--));
|
|||
|
if(timeout == 0)
|
|||
|
{
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
*********************************************************************************************************
|
|||
|
* twi_byte_rw
|
|||
|
*
|
|||
|
*Description: twi byte read and write.
|
|||
|
*
|
|||
|
*Arguments : op operation read or write;
|
|||
|
* saddr slave address;
|
|||
|
* baddr byte address;
|
|||
|
* data pointer to the data to be read or write;
|
|||
|
*
|
|||
|
*Return : result;
|
|||
|
* = EPDK_OK, byte read or write successed;
|
|||
|
* = EPDK_FAIL, btye read or write failed!
|
|||
|
*********************************************************************************************************
|
|||
|
*/
|
|||
|
__s32 twi_byte_rw(enum twi_op_type_e op, __u8 saddr, __u8 baddr, __u8 *data)
|
|||
|
{
|
|||
|
unsigned char state_tmp;
|
|||
|
unsigned int timeout;
|
|||
|
int ret = -1;
|
|||
|
|
|||
|
twi_reg->reg_efr = 0;/* <20><><EFBFBD><D7BC>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0 */
|
|||
|
|
|||
|
state_tmp = twi_reg->reg_status;
|
|||
|
if(state_tmp != 0xf8)
|
|||
|
{
|
|||
|
goto stop_out;
|
|||
|
}
|
|||
|
|
|||
|
/* control registser bitmap
|
|||
|
7 6 5 4 3 2 1 0
|
|||
|
INT_EN BUS_EN START STOP INT_FLAG ACK NOT NOT
|
|||
|
*/
|
|||
|
|
|||
|
//1.Send Start
|
|||
|
twi_reg->reg_ctl |= 0x20;
|
|||
|
timeout = TWI_CHECK_TIMEOUT;
|
|||
|
while((!(twi_reg->reg_ctl & 0x08))&&(timeout--));
|
|||
|
if(timeout == 0)
|
|||
|
{
|
|||
|
goto stop_out;
|
|||
|
}
|
|||
|
state_tmp = twi_reg->reg_status;
|
|||
|
if(state_tmp != 0x08)
|
|||
|
{
|
|||
|
goto stop_out;
|
|||
|
}
|
|||
|
|
|||
|
//2.Send Slave Address
|
|||
|
twi_reg->reg_data = ((saddr<<1)&0xfe) | 0; /* slave address + write */
|
|||
|
twi_reg->reg_ctl &= 0xCF;
|
|||
|
timeout = TWI_CHECK_TIMEOUT;
|
|||
|
while((!(twi_reg->reg_ctl & 0x08))&&(timeout--));
|
|||
|
if(timeout == 0)
|
|||
|
{
|
|||
|
goto stop_out;
|
|||
|
}
|
|||
|
state_tmp = twi_reg->reg_status;
|
|||
|
if(state_tmp != 0x18)
|
|||
|
{
|
|||
|
goto stop_out;
|
|||
|
}
|
|||
|
|
|||
|
//3.Send Byte Address
|
|||
|
twi_reg->reg_data = baddr;
|
|||
|
twi_reg->reg_ctl &= 0xCF;
|
|||
|
timeout = TWI_CHECK_TIMEOUT;
|
|||
|
while((!(twi_reg->reg_ctl & 0x08))&&(timeout--));
|
|||
|
if(timeout == 0)
|
|||
|
{
|
|||
|
goto stop_out;
|
|||
|
}
|
|||
|
state_tmp = twi_reg->reg_status;
|
|||
|
if(state_tmp != 0x28)
|
|||
|
{
|
|||
|
goto stop_out;
|
|||
|
}
|
|||
|
|
|||
|
if(op == TWI_OP_WR)
|
|||
|
{
|
|||
|
//4.Send Data to be write
|
|||
|
twi_reg->reg_data = *data;
|
|||
|
twi_reg->reg_ctl &= 0xCF;
|
|||
|
timeout = TWI_CHECK_TIMEOUT;
|
|||
|
while((!(twi_reg->reg_ctl & 0x08))&&(timeout--));
|
|||
|
if(timeout == 0)
|
|||
|
{
|
|||
|
goto stop_out;
|
|||
|
}
|
|||
|
state_tmp = twi_reg->reg_status;
|
|||
|
if(state_tmp != 0x28)
|
|||
|
{
|
|||
|
goto stop_out;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
//4. Send restart for read
|
|||
|
twi_reg->reg_ctl = (twi_reg->reg_ctl & 0xc0) | 0x20 | 0x08; /* set start+clear int flag */
|
|||
|
timeout = TWI_CHECK_TIMEOUT;
|
|||
|
while((!(twi_reg->reg_ctl & 0x08))&&(timeout--));
|
|||
|
if(timeout == 0)
|
|||
|
{
|
|||
|
goto stop_out;
|
|||
|
}
|
|||
|
state_tmp = twi_reg->reg_status;
|
|||
|
if(state_tmp != 0x10)
|
|||
|
{
|
|||
|
goto stop_out;
|
|||
|
}
|
|||
|
|
|||
|
//5.Send Slave Address
|
|||
|
twi_reg->reg_data = (saddr<<1) | 1;/* slave address+ read */
|
|||
|
twi_reg->reg_ctl &= 0xCF; /* clear int flag then 0x40 come in */
|
|||
|
timeout = TWI_CHECK_TIMEOUT;
|
|||
|
while((!(twi_reg->reg_ctl & 0x08))&&(timeout--));
|
|||
|
if(timeout == 0)
|
|||
|
{
|
|||
|
goto stop_out;
|
|||
|
}
|
|||
|
state_tmp = twi_reg->reg_status;
|
|||
|
if(state_tmp != 0x40)
|
|||
|
{
|
|||
|
goto stop_out;
|
|||
|
}
|
|||
|
|
|||
|
//6.Get data
|
|||
|
twi_reg->reg_ctl &= 0xCF; /* clear int flag then data come in */
|
|||
|
timeout = TWI_CHECK_TIMEOUT;
|
|||
|
while((!(twi_reg->reg_ctl & 0x08))&&(timeout--));
|
|||
|
if(timeout == 0)
|
|||
|
{
|
|||
|
goto stop_out;
|
|||
|
}
|
|||
|
*data = twi_reg->reg_data;
|
|||
|
state_tmp = twi_reg->reg_status;
|
|||
|
if(state_tmp != 0x58)
|
|||
|
{
|
|||
|
goto stop_out;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
ret = 0;
|
|||
|
|
|||
|
stop_out:
|
|||
|
//WRITE: step 5; READ: step 7
|
|||
|
//Send Stop
|
|||
|
_standby_twi_stop();
|
|||
|
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|