s5pv210 ltc2451 驱动

1,ltc2451_i2c_drv.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/miscdevice.h>
#include <linux/slab.h>
#include <linux/fs.h>

#include <asm/uaccess.h>

//设计一个驱动针对不同的设备的不同数据(私有)
struct LTC2451_Private{
    char *name; //描述
    int version;//版本
};

//设计一个全局的设备对象
struct i2c_ltc2451_global{
    struct i2c_client *client;//描述了一个从设备的信息---从设备地址,名字
    struct LTC2451_Private *private;
    struct miscdevice i2c_misc;
};

//全局的指针
struct i2c_ltc2451_global *ltc2451_dev;



int ltc2451_i2c_recv(const struct i2c_client * client, char * buf, int count)
{
    int ret;
    struct i2c_adapter *adapter = client->adapter;//描述控制器, 比如编号,算法

    struct i2c_msg msg;//传输的数据包 

    msg.addr = client->addr;//数据包传输給哪个从设备
    msg.flags = I2C_M_RD; //读还是写--  1读,0写
    msg.len = count;//数据大小bytes
    msg.buf = buf;

    //参数1--适配器,来自于client
    //参数2--传输的消息体--数据包
    //参数3--消息体的个数
    //返回值--正确为消息的个数,错误为负数
    //i2c_transfer(struct i2c_adapter * adap, struct i2c_msg * msgs, int num)
    ret = i2c_transfer(adapter,  &msg,  1);

    return ret==1?count:ret;

}



ssize_t ltc2451_i2c_read (struct file *filp, char __user *buf, size_t count, loff_t *fops)
{
    
    int ret;
	char *temp = NULL;

	
	printk("------%s--------\n", __FUNCTION__);

    //简单的参数判断
    if(count != 2 )
    {
		printk("------count:%d--------\n",count);
        return -EINVAL;
    }
    //动态的分配一个空间,用于存放从硬件获取到的数据
    temp = kzalloc(count, GFP_KERNEL);

    //i2c_master_recv(const struct i2c_client * client, char * buf, int count);
    //i2c_master_send(const struct i2c_client * client, const char * buf, int count);
    // 1,从硬件中获取数据
    ret = ltc2451_i2c_recv(ltc2451_dev->client,  temp,  count);
	printk("ret:%d, temp[0]:%x, temp[1]:%x\n",ret, temp[0], temp[1]);
    if(ret < 0)
    {
        printk("ltc2451_dev_i2c_recv error\n");
        goto err_free;
    }


    // 2, 将数据传递给用户
    ret = copy_to_user(buf, temp, count);
    if(ret > 0)
        {
            printk("copy to user error\n");
            ret = -EFAULT;
            goto err_free;

        }
    kfree(temp);

    return count;
err_free:
    kfree(temp);
    return ret;

}


int ltc2451_i2c_open (struct inode *inode, struct file *filp)
{
    printk("------%s--------\n", __FUNCTION__);
    //一般也是做初始化

    return 0;
}

int ltc2451_i2c_close (struct inode *inode, struct file *flip)
{
    printk("------%s--------\n", __FUNCTION__);
    return 0;   
}

const struct file_operations ltc2451_i2c_fops = {
    .open = ltc2451_i2c_open,
    .read = ltc2451_i2c_read,
    .release = ltc2451_i2c_close,
};

int ltc2451_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)//为什么是id
{ 
	struct LTC2451_Private *p = (struct LTC2451_Private *)id->driver_data;
	printk("-------%s-------\n",__FUNCTION__);
    printk("client name = %s\n", id->name);//
	printk("client addr = %X\n", client->addr);
    

    printk("name descriptoin : %s \n", p->name);
    printk("verison  : 0x%x \n", p->version);

    ltc2451_dev = kzalloc(sizeof(struct i2c_ltc2451_global), GFP_KERNEL);//GFP_KERNEL

    //记录当前匹配之后的i2c client
    ltc2451_dev->client = client;
    ltc2451_dev->private = (struct LTC2451_Private *)id->driver_data;

    //实现fops
    ltc2451_dev->i2c_misc.fops = &ltc2451_i2c_fops;
    ltc2451_dev->i2c_misc.minor = 200;           //MISC_DYNAMIC_MINOR,
    ltc2451_dev->i2c_misc.name = "i2c_ltc2451"; //指定设备节点的名字 /dev/i2c_ltc2451

    //注册一个混杂设备驱动,函数里面已经封装了申请设备号,创建设备文件等过程
    misc_register(&ltc2451_dev->i2c_misc);

    // 4,根据实际情况去初始化从设备硬件---at24 上电就可以工作

    return 0;

}



int ltc2451_i2c_remove(struct i2c_client *client)
{
    printk("------%s--------\n", __FUNCTION__);
    misc_deregister(&ltc2451_dev->i2c_misc);
    kfree(ltc2451_dev);

    return 0;
}



struct LTC2451_Private ltc2451_private = {
    .name = "ltc2451 test ",
    .version = 0x1234,
};


//名字必须与内核中的arch/arm/mach-s5pv210/mach-smdkv210.c中i2c_board_info结构体对应 
const struct i2c_device_id ltc2451_i2c_id_table[] = {
    {"ltc2451",(unsigned long)&ltc2451_private},//注意

};


//描述了一个从设备的操作方法
struct i2c_driver ltc2451_i2c_drv = {
    .probe = ltc2451_i2c_probe,
    .remove = ltc2451_i2c_remove,
    .driver = {                     //父类,一定要初始化
        .name = "ltc2451_drv",     //该名字不会用于进行匹配#
    },                              //主要的作用是用来产生一个文件 /sys/bus/i2c/drivers/at24_drv
    .id_table = ltc2451_i2c_id_table,  //用于和i2c client进行匹配的名字列表
};

static int __init ltc2451_drv_init(void)
{
    //注册一个i2c driver
    return i2c_add_driver(&ltc2451_i2c_drv);

}

static void __exit ltc2451_drv_exit(void)
{
    i2c_del_driver(&ltc2451_i2c_drv);
}



module_init(ltc2451_drv_init);
module_exit(ltc2451_drv_exit);
MODULE_LICENSE("GPL");				// 描述模块的许可证
MODULE_AUTHOR("aston");				// 描述模块的作者
MODULE_DESCRIPTION("module test");	// 描述模块的介绍信息
MODULE_ALIAS("alias xxx");			// 描述模块的别名信息

2,mach-x210.c

/* I2C0 */
static struct i2c_board_info i2c_devs0[] __initdata = {
#ifdef CONFIG_SND_SOC_WM8580
	{
		I2C_BOARD_INFO("wm8580", 0x1b),
	},
#endif

#ifdef CONFIG_EEPROM_at240cxx
{
	I2C_BOARD_INFO("at240c64", (0xa0>>1)),
},
#endif
#ifdef CONFIG_LTC2451_I2C

{
	I2C_BOARD_INFO("ltc2451", (0x28>>1)),
},
#endif

};

3,\drivers\misc\ltc2451\Kconfig

menu "LTC2451 support"

config LTC2451_I2C
	tristate "LTC2451 I2C support"
	help
	  16bit ADC

	  If unsure, say N. 
	  
endmenu

4,\drivers\misc\ltc2451\Makefile

obj-$(CONFIG_LTC2451_I2C)	+= ltc2451_i2c_drv.o

5,\drivers\misc\Kconfig

source "drivers/misc/ltc2451/Kconfig"

6,\drivers\misc\Makefile

obj-y				+= ltc2451/

7,make menuconfig 

Device Drivers —> 

                     [*] Misc devices  ---> 

                                 LTC2451 support  ---> 

                                         <*> LTC2451 I2C support 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值