|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?注册
x
问题:
斑竹帮忙看一下我的iic驱动,根据demo改写,scl和sda一直保持为高。
当调用写函数的时候,根本没有中断产生,但是请求中断是成功的。
不知道是那里的原因。请大家帮我看一下。
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/io.h>
#include <linux/miscdevice.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/spinlock.h>
#include <linux/irq.h>
#include <asm/arch/irqs.h>
#include <asm/delay.h>
#include <asm/arch/S3C2410.h>
#include <asm/hardware.h>
#define DEVICE_NAME "IIC"
#define IIC_MAJOR 233
#define IICBUFSIZE 20
#define IICCON __REG2(0x54000000,4)
#define IICSTAT __REG2(0x54000004,4)
#define IICADD __REG2(0x54000008,4)
#define IICDS __REG2(0x5400000c,4)
#define WRDATA (1)
#define POLLACK (2)
#define RDDATA (3)
#define SETRDADDR (4)
#define BIT_IIC (0x1<<27)
#define IOCTL_SLAVE_ADDR 1
static DECLARE_WAIT_QUEUE_HEAD(iic_wait);
static char iic_Data[IICBUFSIZE];
static volatile int iic_DataCount;
static volatile int iic_Mode;
static volatile int iic_Status;
static int iic_Pt;
static unsigned int old_gpecon,old_gpeup; //use to save GPECON GPEUP
static int slave_addr=0xA0;
static void iic_port_init(void)
{
old_gpecon = GPECON;
old_gpeup = GPEUP;
printk("IIC INIT\nIICON=%x, IICSTAT=%x\n",IICCON,IICSTAT);
GPEUP |= 0xc000; //Pull-up disable
GPECON |= 0xa0000000; //GPE15:IICSDA , GPE14:IICSCL
INTMSK &= ~(BIT_IIC);
IICCON = (1<<7) | (0<<6) | (1<<5) | (0xf);
IICADD = 0x10; //2410 slave address = [7:1]
IICSTAT = 0x10; //IIC bus data output enable(Rx/Tx)
}
static void iic_irq(int irq, void *dev_id, struct pt_regs *reg)
{
int iicSt,i;
printk("IIC IRQ\n");
SRCPND = BIT_IIC; //Clear pending bit
INTPND = BIT_IIC;
iicSt =IICSTAT;
if(iicSt & 0x8){} //When bus arbitration is failed.
if(iicSt & 0x4){} //When a slave address is matched with IICADD
if(iicSt & 0x2){} //When a slave address is 0000000b
if(iicSt & 0x1){} //When ACK isn't received
switch(iic_Mode)
{
case POLLACK:
iic_Status = iicSt;
break;
case WRDATA:
if((iic_DataCount--)==0)
{
IICSTAT = 0xd0; //Stop MasTx condition
IICCON = 0xaf; //Resumes IIC operation.
udelay(1); //Wait until stop condtion is in effect.
//The pending bit will not be set after issuing stop condition.
break;
}
IICDS = iic_Data[iic_Pt++]; //iic_Data[0] has dummy.
for(i=0;i<10;i++); //for setup time until rising edge of IICSCL
IICCON = 0xaf; //resumes IIC operation.
break;
default:
break;
}
}
static int iic_write(struct file * file,const char * buffer, size_t count, loff_t *ppos)
{
printk("IIC WRITE\n");
iic_Mode = WRDATA;
iic_Pt = 1;
iic_DataCount = count-1;
copy_from_user(iic_Data,buffer,count);
IICDS = iic_Data[0];
IICSTAT = 0xf0; //MasTx,Start
//Clearing the pending bit isn't needed because the pending bit has been cleared.
printk("ready to cycle\n");
while(iic_DataCount!=-1)
{
printk("IICCON=%x,IICSTAT=%x\n",IICCON,IICSTAT);
}
iic_Mode = POLLACK;
while(1)
{
IICDS = iic_Data[0];
iic_Status = 0x100;
IICSTAT = 0xf0; //MasTx,Start
IICCON = 0xaf; //Resumes IIC operation.
while(iic_Status==0x100);
if(!(iic_Status&0x1))
break; //When ACK is received
}
IICSTAT = 0xd0; //Stop MasTx condition
IICCON = 0xaf; //Resumes IIC operation.
udelay(1); //Wait until stop condtion is in effect.
//Write is completed
return 0;
}
static int iic_open(struct inode *inode, struct file *file)
{
iic_port_init();
return 0;
}
static struct file_operations iic_fops =
{
owner: THIS_MODULE,
read: iic_read,
write: iic_write,
open: iic_open,
};
static devfs_handle_t devfs_handle;
static int __init iic_init(void)
{
int ret;
ret = register_chrdev(IIC_MAJOR, DEVICE_NAME, &iic_fops);
if (ret < 0) {
printk(DEVICE_NAME " can't register major number\n");
return ret;
}
set_external_irq(IRQ_IIC, EXT_FALLING_EDGE, GPIO_PULLUP_DIS);
ret = request_irq(IRQ_IIC, &iic_irq, SA_INTERRUPT, DEVICE_NAME, &iic_irq);
if (ret<0)
{
unregister_chrdev(IIC_MAJOR, DEVICE_NAME);
printk(DEVICE_NAME " can't request irq %d\n", IRQ_IIC);
return ret;
}
printk("request IIC IRQ success\n");
devfs_handle = devfs_register(NULL, DEVICE_NAME, DEVFS_FL_DEFAULT,IIC_MAJOR, 0, S_IFCHR | S_IRUSR | S_IWUSR,&iic_fops, NULL);
iic_port_init();
return 0;
}
static void __exit iic_exit(void)
{
INTMSK |= BIT_IIC;
GPEUP = old_gpeup;
GPECON = old_gpecon;
devfs_unregister(devfs_handle);
free_irq(IRQ_IIC, iic_irq);
unregister_chrdev(IIC_MAJOR, DEVICE_NAME);
}
module_init(iic_init);
module_exit(iic_exit);
|
|