/********************************************************/
static int eeprom_open(struct inode *inode,struct file *filp)
{
int ret;
printk("eeprom_open!\n");
filp->private_data =&eeprom_cdev;
/***********************************************
*PCLK CONFIG
************************************************/
/*control PCLK into i2c block*/
*S3C2440_CLKCON |= 1<<16;
printk("S3C2440_CLKCON=%X\n",*S3C2440_CLKCON);
/***********************************************
*GPE PORTS CONFIG
************************************************/
*GPECON |=0xA0000000; //引脚功能选择
*GPEUP |=0xC000; //禁止内部上拉
*GPEDAT |= (1<<15) | (1<<14);
/***********************************************
*I2C CONFIG
************************************************/
*IICCON = (1<<7) | (0<<6) | (1<<5) | (0XF);
*IICADD = 0X10;
*IICSTAT = 0x10;
*INTMASK &= ~(1<<27);
/***********************************************
*中断注册
************************************************/
ret = request_irq(IRQ_IIC, S3C24xx_I2CIntHandle, IRQF_DISABLED, "S3c24xx_i2c", NULL);
printk("irq_ret:%d\n", ret);
if(ret<0){
printk("Register irq fail!\n");
return ret;
}
//enable_irq(IRQ_IIC);
return 0;
}
static int eeprom_release(struct inode *inode,struct file *filp)
{
//free irq
//disable_irq(IRQ_IIC);
free_irq(IRQ_IIC, NULL);
printk("<1>eeprom_release\n");
return 0;
}
static ssize_t eeprom_read(struct file *filp,char __user *buf,size_t count,loff_t *f_ops)
{
char *kbuf;
printk("<1>eeprom read!\n");
kbuf = kmalloc(count, GFP_KERNEL);
kbuf[0]=START_ADDR;
S3C24xx_i2c_write(EEPROM_ADDR, kbuf, 1); //写入读取起始地址
S3C24xx_i2c_read(EEPROM_ADDR, kbuf, count);
if(copy_to_user(buf,kbuf,count))
return -1;
kfree(kbuf);
return count;
}
static ssize_t eeprom_write(struct file *filp,const char __user *buf,size_t count,loff_t *f_ops)
{
char *kbuf;
printk("<1>eeprom write!,count=%d\n",count);
kbuf=kmalloc(count,GFP_KERNEL);
if(copy_from_user(&kbuf[1],buf,count))
{
printk("no enough memory!\n");
return -1;
}
kbuf[0]=START_ADDR; //起始地址
S3C24xx_i2c_write(EEPROM_ADDR, kbuf, count+1);
printk("write 0x%02X!\n",*kbuf);
kfree(kbuf);
return count;
}
static ssize_t eeprom_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long data)
{
return 0;
}
static int __init eeprom_init(void)
{
int ret;
ret = alloc_chrdev_region(&devno, 0, 1, DEVICE_NAME);
if(ret<0){
printk(KERN_DEBUG "Can't apply to the device number!\n");
return ret;
}
eeprom_cdev = cdev_alloc();
cdev_init(eeprom_cdev, &eeprom_fops);
eeprom_cdev->owner = THIS_MODULE;
eeprom_cdev->ops = &eeprom_fops;
ret = cdev_add(eeprom_cdev, devno, 1);
if (ret<0) {
printk(KERN_NOTICE "Register %s fail\n", DEVICE_NAME);
return ret;
}
eeprom_class = class_create(THIS_MODULE, DEVICE_NAME);
device_create(eeprom_class, NULL, devno, NULL, "%s",DEVICE_NAME);
S3C2440_CLKCON = (int *)ioremap(0x4C00000c,3);
GPECON= (int *)ioremap (0x56000040,4);
GPEDAT= (int *)ioremap (0x56000044,2);
GPEUP= (int *)ioremap (0x56000048,2);
IICCON= (int *)ioremap (0x54000000,1);
IICSTAT= (int *)ioremap (0x54000004,1);
IICADD= (int *)ioremap (0x54000008,1);
IICDS= (int *)ioremap(0x5400000C,1);
IICLC= (int *)ioremap(0x54000010,1);
SRCPND= (int *)ioremap(0x4A000000,4);
INTMODE= (int *)ioremap(0x4A000004,4);
INTMASK= (int *)ioremap(0x4A000008,4);
INTPND= (int *)ioremap(0x4A000010,4);
printk("Register %s success!\n",DEVICE_NAME);
return ret;
}
static void __exit eeprom_exit(void)
{
cdev_del(eeprom_cdev);
unregister_chrdev_region(devno, 1);
device_destroy(eeprom_class, devno);
class_destroy(eeprom_class);
printk("<1>eeprom_exit!\n");
}
module_init(eeprom_init);
module_exit(eeprom_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("aguei");
MODULE_DESCRIPTION("eeprom driver for S3C2440"); |