免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1375 | 回复: 0
打印 上一主题 下一主题

at24c512 linux下设备驱动 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-05-29 11:29 |只看该作者 |倒序浏览

                    这两天挺累的,频繁的应酬,都有点受不了了,下了班也不敢加班,赶紧跑回家,结果发现,跑回家也没有作用。。。
    放出一个atmel24c512的设备驱动框架。可以使用,但是使用这要对read和write进行一些修改,需要能指定地址的访问。。。
    感谢网上的某位兄弟放出的部分源码,linux开源的力量无穷!!!
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
static unsigned short normal_i2c[] = { 0x50,I2C_CLIENT_END };
#define EEPROM_SIZE    65536
#define    DEVICE_NAME     "at24c512"
#define    AT24C512_EEPROM_MAJOR 251
#define    SEEK_END    2
#define    SEEK_CUR    1
#define    SEEK_SET    0
static DECLARE_MUTEX(at24c512_eeprom_read_sem);
static DECLARE_MUTEX(at24c512_eeprom_write_sem);
struct i2c_client *new_client;
/* possible types of eeprom devices */
enum eeprom_nature {
    UNKNOWN,
    VAIO,
};
/* Module parameters */
/*这一句很重要得,不然的addr_data会找不到,因为i2c.h文件只是定义了几种宏,这里才真正定义这个变量,今天才真正理解了这个addr_data如何产生的,
每个i2c设备都有一个addr_data结构,这样就好理解i2c的框架(i2c_probe)驱动为何这样写,*/
I2C_CLIENT_INSMOD;
static ssize_t eeprom_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
{
memset(buf,0x88,10);
return 10;
}
static ssize_t eeprom_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
{
return 10;
}
static struct i2c_driver eeprom_driver;
static struct bin_attribute eeprom_attr = {
    .attr = {
        .name = "at24c512",
        .mode = S_IRUGO,
        .owner = THIS_MODULE,
    },
    .size = EEPROM_SIZE,
    .read = eeprom_read,
    .write=eeprom_write,
};
struct eeprom_data {
    struct i2c_client client;
    struct mutex update_lock;
    unsigned char valid;            /* bitfield, bit!=0 if slice is valid */
    unsigned long last_updated[8];    /* In jiffies, 8 slices */
    unsigned char data[EEPROM_SIZE];        /* Register values */
    enum eeprom_nature nature;
};
/* This function is called by i2c_probe */
static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
{
    struct eeprom_data *data;
    int err = 0;
    printk("eeprom_detect!\n");   
    if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
        err = -ENODEV;
        goto exit;
    }
    if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) {
        err = -ENOMEM;
        goto exit;
    }
    new_client = &data->client;
    memset(data->data, 0xff, EEPROM_SIZE);
    i2c_set_clientdata(new_client, data);
    new_client->addr = address;
    printk("address==%x\n",new_client->addr);
    new_client->adapter = adapter;
    new_client->driver = &eeprom_driver;
    new_client->flags = 0;
    /* Fill in the remaining client fields */
    strlcpy(new_client->name, eeprom_driver.driver.name, I2C_NAME_SIZE);
    data->valid = 0;
    mutex_init(&data->update_lock);
    data->nature = UNKNOWN;
    /* Tell the I2C layer a new client has arrived */
    if ((err = i2c_attach_client(new_client)))
        goto exit_kfree;
    /* Detect the Vaio nature of EEPROMs.
       We use the "PCG-" prefix as the signature. */
    /*
    if (address == 0x57) {
        if (i2c_smbus_read_byte_data(new_client, 0x80) == 'P'
         && i2c_smbus_read_byte(new_client) == 'C'
         && i2c_smbus_read_byte(new_client) == 'G'
         && i2c_smbus_read_byte(new_client) == '-') {
            dev_info(&new_client->dev, "Vaio EEPROM detected, "
                "enabling password protection\n");
            data->nature = VAIO;
        }
    }
    */
    /* create the sysfs eeprom file */
    err = sysfs_create_bin_file(&new_client->dev.kobj, &eeprom_attr);
    if (err)
        goto exit_detach;
   
    printk("eeprom_detect ok!\n");        
    return 0;
exit_detach:
    i2c_detach_client(new_client);
exit_kfree:
    kfree(data);
exit:
    return err;
}
static int eeprom_attach_adapter(struct i2c_adapter *adapter)
{
    return i2c_probe(adapter, &addr_data, eeprom_detect);
}
static int eeprom_detach_client(struct i2c_client *client)
{
    int err;
    sysfs_remove_bin_file(&client->dev.kobj, &eeprom_attr);
    err = i2c_detach_client(client);
    if (err)
        return err;
    kfree(i2c_get_clientdata(client));
    return 0;
}
/* This is the driver that will be inserted */
static struct i2c_driver eeprom_driver = {
    .driver = {
        .name    = "at24c512",
    },
    .id        = I2C_DRIVERID_EEPROM,
    .attach_adapter    = eeprom_attach_adapter,
    .detach_client    = eeprom_detach_client,
};
static int  at24c512_eeprom_open(struct inode * inode, struct file * filp)
{
    filp->private_data = new_client;
    printk("at24c512 open success!\n");
    return 0;
}
static int  at24c512_eeprom_release(struct inode * inode, struct file * filp)
{
    printk("at24c512 realse success!\n");
    return 0;
}
static loff_t  at24c512_eeprom_llseek (struct file *filp, loff_t off, int whence)
{
     //struct i2c_dev *dev = filp->private_data;
     loff_t newpos=-1;

     filp->private_data=new_client;
     switch(whence)
     {  
          case SEEK_SET:   
       newpos = off;  
       break;  
   
          case SEEK_CUR:   
       newpos = filp->f_pos + off;  
       break;  
   
          case SEEK_END:   
       //newpos = (filp->private_data)->size + off;  
       break;  
   
          default: /* can't happen */  
       return -EINVAL;
    }
   
        
    if (newpos f_pos = newpos;
    return newpos;
}
static ssize_t at24c512_eeprom_read(struct file * file, char * buffer, size_t count, loff_t *ppos)
{
    ssize_t ret;
int result;
struct i2c_client *client = new_client;
struct i2c_msg msg[1];
char *tmp;
printk("this is in reading!\n");
if(down_interruptible(&at24c512_eeprom_read_sem))
  goto out;

if (!(tmp = kzalloc(count, GFP_KERNEL)))
        return  - ENOMEM;
    printk("the number is %d\n",count);
  result=i2c_master_recv(client, tmp ,count);
  printk("read result===%x\n",result);
        ret = copy_to_user(buffer, tmp, count);
  if(ret != 0)
  {
   kfree(tmp);
  return -EFAULT;
  }
  
out:
{
  up(&at24c512_eeprom_read_sem);
  return 0;
}
kfree(tmp);
return ret;
}
static ssize_t at24c512_eeprom_write(struct file * file, char * buffer, size_t count, loff_t *ppos)
{
ssize_t ret;
int result,i;
struct i2c_client *client=new_client;
     struct i2c_msg msg[1];
    char *tmp;
if(down_interruptible(&at24c512_eeprom_write_sem))
  goto out;
printk("this is in writting!\n");
if (!(tmp = kzalloc(count, GFP_KERNEL)))
        return  - ENOMEM;
  ret = copy_from_user(tmp, buffer, count);
  if(ret != 0)
  {
   kfree(tmp);
  return -EFAULT;
  }

  result=i2c_master_send(client,tmp ,count);
  printk("write result===%x\n",result);
out:
{
  up(&at24c512_eeprom_write_sem);
  return 0;
}
kfree(tmp);
return result;
}
/*to user*/
static struct file_operations at24c512_eeprom_fops = {
.owner = THIS_MODULE,
.open=at24c512_eeprom_open,
//.poll = tsmb_eeprom_select,
.read = at24c512_eeprom_read,
.write = at24c512_eeprom_write,
.llseek = at24c512_eeprom_llseek,
.release=at24c512_eeprom_release,
};
static int __init eeprom_init(void)
{
    int ret,result;   
    result = register_chrdev(AT24C512_EEPROM_MAJOR, DEVICE_NAME,  &at24c512_eeprom_fops);
    if (result eeprom_detect ok!
at24c512: init OK
at24c512 open success!
this is in reading!
the number is 8192
i2c_adapter i2c-0: master_xfer[0] R, addr=0x50, len=8192
i2c_adapter i2c-0: at91_xfer: processing 1 messages:
i2c_adapter i2c-0:  #0: reading 8192 bytes from 0x50
i2c_adapter i2c-0: transfer complete
read result===2000
at24c512 realse success!
说明通信成功。。。
               
               
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/38038/showart_715294.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP