RK3399 i2c驱动及使用

RK3399 I2C驱动

ch423芯片为I2C转GPIO芯片,该芯片将所有的寄存器作为地址使用,和一般的I2C芯片有所不同。

驱动

ch423芯片驱动

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/err.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <asm/uaccess.h>

#define I2C_NAME "ch423"
static int major;
static struct class *class;
static struct i2c_client *iic_client=NULL;

static int ch423_open(struct inode *inode,struct file *fd)
{
	fd->private_data=(void*)iic_client;
	return 0;
}
static int ch423_write(const struct i2c_client * client,char reg, const char *buf, int len)
{
	int ret;	
	struct i2c_msg msg;
	char mbuf[8];
	memcpy(mbuf, buf, len);

	msg.addr = reg;//Ch423地址为其寄存器地址,不能使用 msg.addr = client->addr,; 
	msg.flags = 0;//写为0
	msg.len = len;
	msg.buf = &mbuf[0];
	ret=i2c_transfer(client->adapter, &msg, 1);//ret=1读写正常,返回-读写错误
	//printk(KERN_INFO"ch423 addr=%02x,date=%02x,return=%d\n",reg,mbuf[0],ret);
	return ret;
}
static ssize_t ch423_write_gpio(struct file *fd,const char *buf,size_t len,loff_t *opps)
{
	int ret,i;
	struct i2c_client *client = (struct i2c_client*) fd->private_data;
	char mbuf[8],buf1[8];
	if(len > sizeof(mbuf))
		len = sizeof(mbuf);
	memcpy(&mbuf[0], buf, len);
	for(i=0;i<len;i+=2){
		buf1[0]=mbuf[i+1];
		ret=ch423_write(client,mbuf[i],buf1,1);
	}
	return ret;
}

static struct file_operations iic_fops = {
	.owner = THIS_MODULE,
	.write = ch423_write_gpio,
	.open = ch423_open,
};

static struct of_device_id ch423_ids[] = {
	{.compatible = "ch423"},
	{}   
};
static const struct i2c_device_id ch423_id[] = { 
	{I2C_NAME, 0}, 
	{}   
};
MODULE_DEVICE_TABLE(i2c, ch423_id);
static int ch423_probe(struct i2c_client *client,const struct i2c_device_id *id)
{
	printk(KERN_INFO "%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
	major = register_chrdev(0, I2C_NAME, &iic_fops);
	class = class_create(THIS_MODULE, I2C_NAME);
	device_create(class,&client->dev, MKDEV(major, 0), NULL, I2C_NAME); 
	iic_client = client;
	return 0;
}
static int ch423_remove(struct i2c_client *client)
{
	printk(KERN_INFO "%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
	device_destroy(class, MKDEV(major, 0));
	class_destroy(class);
	unregister_chrdev(major, I2C_NAME);
	return 0;
}
static struct i2c_driver ch423_driver = { 
	.driver = { 
		.name = I2C_NAME, 
		.owner = THIS_MODULE, 
		.of_match_table = of_match_ptr(ch423_ids), 
		},   
	.probe      = ch423_probe, 
	.remove     = ch423_remove, 
	.id_table   = ch423_id,
};
static int __init ch423_init(void)
{
	printk(KERN_INFO "%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
	return i2c_add_driver(&ch423_driver);
}
static void __exit ch423_exit(void)
{
	i2c_del_driver(&ch423_driver);
}

MODULE_AUTHOR("who");
MODULE_DESCRIPTION("ch423 driver");
MODULE_LICENSE("GPL");

module_init(ch423_init);
module_exit(ch423_exit);

设备树 dts加入:

&i2c3 {
	status = "okay";
	ch423@40{
		status ="okay";
		compatible = "ch423";
		reg = <0x40>;
	};	
};

编译内核下载内核后,在/dev/下就产生ch423驱动.

 # echo -e -n "\x24\x01\x30\x20" >/dev/ch423

测量相应的管脚,有高电平输出。
注意:Linux i2c地址 0x48地址应该写0x24,因为linux i2c有相应的读写flag。

©️2020 CSDN 皮肤主题: 创作都市 设计师:CSDN官方博客 返回首页