zhoujb99
驱动牛犊
驱动牛犊
  • 注册日期2004-03-12
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分26分
  • 威望6点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:2268回复:0

帮忙看一下我的iic驱动,根据demo改写,scl和sda一直保持为高

楼主#
更多 发布于:2005-07-16 22:25
  我用的是2410的板子
 问题:
当调用写函数的时候,根本没有中断产生,但是请求中断是成功的。
不知道是那里的原因。请大家帮我看一下。

#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);
游客

返回顶部