?? i2c_final_ok_080804_pass1sttest.c
字號:
/* *********I2c Driver Test Program***************************************
Program Name:IIC Driver Test Program
Function:test IIC based MCU writing & reading function
Designer:Donglei (ICL of Peking Uni.)
Description:Not using kernel's driver,new driver for MCU read operation test
Edition:2.0 8_5_08 Moring
Problem:
In addition:
***************************************************************************/
#include <linux/mm.h>#include <linux/config.h>
#include <linux/spinlock.h>#include <linux/miscdevice.h>#include <linux/delay.h>
#include <asm/uaccess.h>#include <linux/slab.h>#include <linux/clocks.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/poll.h>
#include <linux/wait.h>
#include <asm/io.h>
#include <linux/interrupt.h>
#include <linux/sched.h>#include <asm/irq.h>
#include <asm/arch/irqs.h>#define bWTCOM(Nb) __REG(0x53000000+(Nb))
#define WTCON bWTCON(0)
#define WTDAT bWTCON(4)
#define WTCTN bWTCON(8)
#define VA_IIC_BASE io_p2v(0x54000000)
#define S3C_IICCON (VA_IIC_BASE + 0x0)
#define S3C_IICSTAT (VA_IIC_BASE + 0x4)
#define S3C_IICADD (VA_IIC_BASE + 0x8)
#define S3C_IICDS (VA_IIC_BASE + 0xc)
#define __REG_B(x) (*(volatile unsigned char *)(x))
#define IICCON __REG_B(VA_IIC_BASE + 0x0)
#define IICSTAT __REG_B(VA_IIC_BASE + 0x4)
#define IICADD __REG_B(VA_IIC_BASE + 0x8)
#define IICDS __REG_B(VA_IIC_BASE + 0xc)
#define S3C_IICLC (VA_IIC_BASE + 0x10)
#define IICLC __REG_B(VA_IIC_BASE + 0x10)
#define DEVICE_NAME "i2c_test"
#define POLLACK 0 //Test ACK signal received or not
#define SETRDADDR 3 #define UNIT (1000*1000) //clock transunit define for PCLK
#define HIGHSCALE 0x40 //PCLK's 512 prescale for IICCLK set
#define LOWSCALE 0x00 //PCLK's 16 prescale for IICCLK set
static volatile unsigned long PCLK; //PC clock
static volatile int iicMode;//Operation mode select flag
static volatile int iicStatus;//IIC status flag
static volatile int NoAckF;//ACK signal get flag
static volatile int iicDataCount;//Data trans Number
static volatile int iicRDTransNum;//The data number of READ transforation
static volatile int iicWRTransNum;//The data number of WRITE transforation
static volatile int delayLoopCount; //for the Delay() function
static volatile int writedataF; //Write data start flag
static volatile int readdataF; //Read data start flag
__u16 SaveGPECON; //For GPECON register save
__u16 SaveGPEUP; //For GPEUP register save
__u8 slaveAddr; //Slave device address
__u8 SCALE_Base; //Prescale for IICCLK base number
__u8 ConSet; //The Backup of IICCON set
char *page; //IIC device Data buffer
static int IIC_test_open(struct inode *inode,struct file *filp)
{
MOD_INC_USE_COUNT;
return 0;
}
static int IIC_test_release(struct inode *inode,struct file *filp)
{
MOD_DEC_USE_COUNT;
return 0;
}/****************************Delay Function**********************************************/
void Delay(int time)
{
// time=0: adjust the Delay function by WatchDog timer.
// time>0: the number of loop time
// resolution of time is 100us.
int i, adjust=0;
if(time==0)
{
time = 200;
adjust = 1;
delayLoopCount = 800;
//PCLK/1M,Watch-dog disable,1/64,interrupt disable,reset disable
WTCON = ((PCLK/1000000-1)<<8)|(2<<3);
WTDAT = 0xffff; //for first update
WTCNT = 0xffff; //resolution=64us @any PCLK
WTCON = ((PCLK/1000000-1)<<8)|(2<<3)|(1<<5); //Watch-dog timer start
}
for(;time>0;time--)
for(i=0;i<delayLoopCount;i++);
if(adjust==1)
{
WTCON = ((PCLK/1000000-1)<<8)|(2<<3); //Watch-dog timer stop
i = 0xffff - WTCNT; //1count->64us, 200*800 cycle runtime = 64*i us
delayLoopCount = 16000000/(i*64); //200*800:64*i=1*x:100 -> x=160000*100/(64*i)
}
}
/****************************i2c bus release(for MasRx & MasTx mode)**********************************/
void ReleaseRXBus(void)
{ IICSTAT=0x90;
Delay(1); //Wait until stop condtion is in effect.
//GPECON=SaveGPECON;
//GPEUP=SaveGPEUP;
}
void ReleaseTXBus(void)
{ IICSTAT=0xd0;
Delay(1); //Wait until stop condtion is in effect.
//GPECON=SaveGPECON;
//GPEUP=SaveGPEUP;
}
/****************************IRQ serve segment********************************/
static void i2c_isr(int irq,void *dev_id, struct pt_regs *regs)
{ __u32 delayF;
__u32 iicSt; int i;
INTMSK=INTMSK|(0x01<<27); //Disable IIC interrupts,when ioctl cmd takes effect mask set to 0
iicSt = IICSTAT; //When some errors happen wait until the stop condition takes effect
if(iicSt & 0x1)
{ NoAckF=1; //When ACK isn't received
if((writedataF==1)||(readdataF==1))
{
NoAckF=0; }
}
if(iicMode==POLLACK) //if interrupt polled out the ack signal the operation will stop test,then into the send data step
{
if(NoAckF)
{
NoAckF =0;
}
else
{
iicStatus = 1;
}
}
SRCPND=SRCPND&~(0x1<<27); //clear pending
INTPND=INTPND&~(0x1<<27);
INTMSK = INTMSK&~(0x1<<27); //open IIC Interrupt
}
/****************************Initialization segment******************************************************/
static int i2c_Initialization(void)
{
int ret; int i;
NoAckF = 0; writedataF=0;
readdataF=0; /*field protection has fetal problem.If add following 2 statments, system can't wake up the second interrupt. I don't know why. It needs consideration & experiment*/
//SaveGPECON = GPECON; //Save the GPE pin settment
//SaveGPEUP = GPEUP; //Save the GPE pin statment SRCPND = SRCPND&~(0x01<<27);
INTPND = INTPND&~(0x01<<27);
INTPND ;
INTMSK = INTMSK&~(0x01<<27);
free_irq(IRQ_IIC,NULL);
Delay(1);
ret = request_irq(IRQ_IIC, i2c_isr, SA_INTERRUPT, "i2c_test", NULL);
if (ret)
{
printk (KERN_ERR "i2c_test: IRQ %d is already in use.\n",IRQ_IIC);
}
printk("i2c_isr is set!\n"); PCLK=elfin_get_bus_clk(GET_PCLK); PCLK/=UNIT; printk("%03ld Mhz\n",PCLK);
GPEUP |= 0xc000; //Pull-up disable
GPECON |= 0xa00000; //GPE15:IICSDA , GPE14:IICSCL
/**Enable ACK, Prescaler IICCLK=PCLK/16, Enable interrupt, Transmit clock value Tx clock=IICCLK/16
If PCLK 50.7MHz, IICCLK = 3.17MHz, Tx Clock = 0.198MHz**/
IICCON = (1<<7) | (1<<5) | (0xf)|SCALE_Base; //prescaler 16 TCV set
ConSet=IICCON;
IICSTAT = 0x10; //IIC bus data output enable(Rx/Tx); clear status flag
IICADD = 0x00; //IIC Master address
IICLC = (1<<2)|(1); // Filter enable, 15 clocks SDA output delay
IICDS = 0x00;
printk("Initialized!\n") ;
return 0;
}
/*****************************Read system call for i2c_test*****************************************/
static int i2c_test_read(struct file *filp, const char *buf,size_t count,loff_t *ppos)
{
int i,j,n;
__u32 k,m;
k=0;
m=0;
n=0;
iicStatus = 0;
iicMode = POLLACK;
i2c_Initialization(); //Initialization for i2c bus operation
iicDataCount = 1;
IICSTAT =0x90; //Set MasRx Mode
IICDS = slaveAddr;
IICSTAT = 0xb0; //MasTx,Start
//Clearing the pending bit isn't needed because the pending bit has been cleared.
while(iicStatus!=1) {
if(m==400000)
{
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -