打印

2440 iic

[复制链接]
1455|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zcwlwlwl|  楼主 | 2012-1-5 13:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
/*//http://blog.csdn.net/beyondioi/article/details/6914935
分析:S3C2410的I2C为主设备,EEPROM的I2C为从设备,进行的操作为主设备写、和主设备读。
(1)设置I2C控制寄存器
1)收发传输:IICCON=0b 1 0 1 0 1111 = 0xAF
含义:应答使能、时钟分频为IICCLK = PCLK /16 、中断使能、清除中断标志、预分频值取15。
2)接收结束传输:IICCON=0b 0 0 1 0 1111 = 0x2F
含义:禁止应答(非应答)、时钟分频为IICCLK = PCLK /16 、中断使能、清除中断标志、预分频值取15。
(2)I2C控制状态寄存器
1)主模式发送、启动传输
IICSTAT=0b 11 1 1 0 0 0 0 = 0xF0
2)主模式发送、结束传输
IICSTAT=0b 11 0 1 0 0 0 0 = 0xD0
3)主模式接收、启动传输
IICSTAT=0b 10 1 1 0 0 0 0 = 0xB0
4)主模式接收、结束传输
IICSTAT=0b 10 0 1 0 0 0 0 = 0x90*/
#include <linux/module.h>   
#include <linux/kernel.h>   
#include <linux/init.h>     
#include <linux/sched.h>   
#include <asm/hardware.h>   
#include <asm/semaphore.h>   
#include <asm/uaccess.h>   
#include <linux/kernel.h>   /* printk() */   
#include <linux/slab.h>   /* kmalloc() */   
#include <linux/fs.h>       /* everything... */   
#include <linux/errno.h>    /* error codes */   
#include <linux/types.h>    /* size_t */   
#include <linux/mm.h>   
#include <linux/kdev_t.h>   
#include <linux/cdev.h>   
#include <linux/delay.h>   
//#include <linux/device.h>   
#include <asm/io.h>   
#include <asm/uaccess.h>   
#include <linux/errno.h>   
#include <linux/kernel.h>   
#include <linux/module.h>   
#include <linux/slab.h>   
#include <linux/input.h>   
#include <linux/init.h>   
#include <linux/serio.h>   
#include <asm/irq.h>   
//#include <asm/arch/regs-adc.h>   
#include <asm/arch/map.h>   
#include <asm/arch/regs-gpio.h>   
#include <asm/arch/regs-irq.h>   
#include <asm/arch/regs-clock.h>   
//#include <asm/arch/regs-iic.h>  
#define I2C_MAGIC 'k'     
#define I2C_set _IO(I2C_MAGIC,1)     
#define I2C_MAJOR 259   
#define DEVICE_NAME "s3c2410_I2C"
volatile int f_nGetACK;  
MODULE_LICENSE("GPL");
MODULE_AUTHOR("XIAOLEI");
MODULE_DESCRIPTION("S3C2410_IC");
char data[128]="\0";
#define rGPFCON *(volatile unsigned int *)S3C2410_GPECON;
#if 0   
#define S3C2410_I2C(x) (S3C2410_IICREG(x))   
#define S3C2410_IICCON    S3C2410_I2C(0x00)   
#define S3C2410_IICSTAT    S3C2410_I2C(0x04)   
#define S3C2410_IICADD    S3C2410_I2C(0x08)   
#define S3C2410_IICDS    S3C2410_I2C(0x0c)   
  
#define rIICCON  *(volatile unsigned int *)S3C2410_IICCON   
#define rIICSTAT *(volatile unsigned int *)S3C2410_IICSTAT   
#define rIICADD  *(volatile unsigned int *)S3C2410_IICADD   
#define rIICDS   *(volatile unsigned int *)S3C2410_IICDS   
#define rGPECON  *(volatile unsigned int *)S3C2410_GPECON   
#else   
#define rIICCON  *(volatile unsigned int *)i2c_base   
#define rIICSTAT *(volatile unsigned int *)((unsigned int)i2c_base + 4)   
#define rIICADD *(volatile unsigned int *)((unsigned int)i2c_base + 8)   
#define rIICDS *(volatile unsigned int *)((unsigned int)i2c_base + 0xc)?/IICDS寄存器  
static volatile void __iomem *i2c_base;
static struct resource *area=NULL;
#endif
static int i2c_major=I2C_MAJOR;
static volatile unsigned int *clkcon;  
#define CLKCON 0x4C00000C;
static struct cdev *I2C_cdev;
static irqreturn_t iic_int_24c04(int irq,void *dev_id,struct pt_regs *regs)
{
f_nGetACK=1;
return IRQ_HANDLED;
}
static iic_write_24c04(unsigned int unslaveaddr,unsigned int unaddr,unsigned int ucdata)
{
f_nGetACK=0;
rIICDS=unslaveaddr;//地址0XA0   
rIICSTAT=0xf0;
//rIICCON&=~0x10;//清中断标志,特别注意这条语句的位置,不能放到上条的前面
while(f_nGetACK==0);

f_nGetACK=0;
rIICDS=unaddr;
rIICCON=0xaf;//义:应答使能、时钟分频为IICCLK = PCLK /16 、中断使能、清除中断标志、预分频值取15。

//rIICCON&=~0x10;
while(f_nGetACK==0);

f_nGetACK=0;
rIICDS=ucdata;
rIICCON=0xaf;
//rIICCON&=~0x10;
while(f_nGetACK==0)
  
f_nGetACK=0;
rIICSTAT=0xd0;
rIICCON=0xaf;
mdelay(10);
}
/*void wr24c02(u32 slvaddr,u32 addr,u8 data)
{
flag=1;
rIICDS=slvaddr;
rIICSTAT=0XF0;//主设备启动
rIICCON&=~0x10;
while(flag==1);//当发送从地址完成之后会收到ACK信号,在中断处理函数中将该标志置为0
delay(1);

flag=1;
rIICDS=addr;
rIICCON&=~0x10;
while(flag==1);
delay(1);
flag=1;
rIICDS=data;
rIICCON&=~0x10;
while(flag==1);//当发送从地址完成之后会收到ACK信号,在中断处理函数中将该标志置为
delay(1);
rIICSTAT=0xd0;
rIICCON=0xaf;
delay(1);
}*/
void iic_read_24c02(unsigned int slvaddr,unsigned int addr,unsigned char *pdata)
{
char temp;
f_nGetACK=0;
rIICDS=slvaddr;
rIICSTAT=0xf0;//TX
//rIICCON&=~0x10;
while(f_nGetACK==0);
f_nGetACK=0;
rIICDS=addr;
rIICCON=0xaf;
//rIICCON&=~0x10;
while(f_nGetACK==0);
f_nGetACK=0;
rIICDS=slvaddr;
rIICSTAT=0xb0;//RX
rIICCON=0xaf;
mdelay(100);
while(f_nGetACK==0);
f_nGetACK=0;
rIICCON=0x2F;
mdelay(1);
temp=rIICDS;
rIICSTAT=0x90;
rIICCON=0xaf;
mdelay(10);
*pdata=temp;
}
ssize_t I2C_read(struct file *filp,char *buff,size_t count,loff_t *offp)
{
ssize_t result=0;
int i;
for(i=0;i<count;i++)
  data[i]=0;
for(i=0;i<count;i++)
  {
  iic_read_24c02(0xa0,i,&(data[i]));//
  }
data[count]='\0';
if(copy_to_user(buff,data,count))
  result=-EFAULT;
result=count;
return result;
}
ssize_t I2C_write(struct file *filp,const char __user *buf,size_t count, loff_t *f_pos)
{
int i;
ssize_t ret=0;
if (count>127) return -ENOMEM;
if (count<0) return -EINVAL;
if (copy_from_user (data, buf, count))  //注意 copy_from_user
  {  
   ret = -EFAULT;  
}
else
  {
  data[127]='\0';
  for(i=0;i<count;i++)
   {
    iic_write_24c04(0xa0,i,data[i]);
   }
  ret=count;
  }
return ret;
}
static int I2C_open(struct inode *inode,struct file *filp)
{
int result;
rIICADD=0x10;//2440 slave address = [7:1]
rIICCON=0xaf;
rIICSTAT=0x10;//IIC bus data output enable(Rx/Tx)   
rGPFCON=(rGPFCON&(~0xf)<<28)+(0xa<<28);
printk("init i2c/n");
result=request_irq(IRQ_IIC,iic_int_24c04,SA_INTERRUPT,DEVICE_NAME,NULL);
if(result)
  {
  printk(KERN_INFO "I2C CANOT get irq\n");
  }
return 0;
}
static int I2C_release(struct inode *inode,struct file *filp)
{
free_irq(IRQ_IIC,NULL);
return 0;
}
static int I2C_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg)
{
return 0;
}
static void I2C_setup_dev(struct cdev *dev,int minor,struct file_operations *fops)
{
int err;
int devno=MKDEV(i2c_major,minor);
cdev_init(dev,fops);
dev->owner=THIS_MODULE;
dev->ops=fops;
err=cdev_add(dev,devno,1);
if(err)
  printk(KER_INFO "Error %d adding i2c %d\n",err,minor);
}
static struct file_operations I2C_remap_ops={
.owner=THIS_MODULE,
.open=I2C_open,
.write=I2C_write,
.read=I2C_read,
.release=I2C_release,
.ioctl=I2C_ioctl,
};
static int __init s3c2410_I2C_init(void)
{
int result;
dev_t dev=MKDEV(i2c_major,0);//通过mkdev获得32位设备驱动号
if(i2c_major)
  {
   result=register_chrdev_region(dev,1,DEVICE_NAME);
   //int register_chrdev_region(dev_t first,unsigned int count,char *name)
  }
else
  {
  result=alloc_chrdev_region(&dev,0,1,DEVICE_NAME);//起始设备号未指定,就要动态申请
  i2c_major=MAJOR(dev);
  }
if(result<0)
  {
  printk(KER_WARNING "I2C:unable to get major %d\n",i2c_major);
  return result;
  }
if(i2c_major==0)
  i2c_major=result;
  printk(KERN_NOTICE"[DEBUG] I2C device major is %d\n",I2C_major);
  __raw_writel( (__raw_readl(S3C2410_CLKCON) | (1 << 16)), S3C2410_CLKCON);
  #if 0   
  printk("\n  S3C2410_CLKCON = %x \n", __raw_readl(S3C2410_CLKCON));  
area = request_mem_region(0x54000000, 16,"I2C");  
#endif   
i2c_base=ioremap(0x54000000,16);
clkcon=ioremap(CLKCON,0x4);
printk(KERN_INFO"i2c clock = %d\n", *clkcon & (0x1 << 16));
*clkcon |= 0x1 << 16;
I2C_setup_dev(&I2C_cdev,0,&I2C_remap_ops);
return 0;
}
static void s3c2410_I2C_exit(void)  
{  
#if 0   
if (area) {  
  release_resource(area);  
  kfree(area);  
    }  
#endif   
cdev_del(&I2C_cdev);  
unregister_chrdev_region(MKDEV(I2C_major,0),1);  
printk("I2C device uninstalled\n");  
}
module_init(s3c2410_I2C_init);
module_exit(s3c2410_I2C_exit);
#include <stdio.h>
#include<stdlib.h>
#include <sys/types.h>
#include<unistd.h>
#include<fcntl.h>
#include<time.h>
#include<sysy/ioctl.h>
#define WATCHDOG_MAGIC 'k'
#define FEED_DOG _IO(WATCHDOG_MAGIC,1)
int main(int argc,char **argv)
{
int fd;
char buff[]="farsight";
fd=open("/dev/i2c",O_RDWR);
if(fd<0)
  {
   printf("cannot open the i2c device \n");
   return -1;
  }
sleep(1);
printf("buff_write=%s\n",buff);
write(fd,buff,sizeof(buff));
memset(buff,'\0',sizeof(buff));
read(fd,buff,sizeof(buff));
printf("buff_read=%s",buff);
close(fd);
return 0;
}

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

6

帖子

1

粉丝