版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wr132/article/details/78569817
编写I2C外设驱动步骤
- 注册I2C设备,一般在板级文件中,定义i2c_board_info
- 注册I2C驱动:i2c_register_driver,i2c_del_driver
- 利用i2c_client中的addr(设备地址)和adapter(主机驱动)实现I2C数据传输:填充i2c_msg并调用i2c_transfer
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <plat/gpio-cfg.h>
#include <mach/gpio.h>
#define DRIVER_NAME "i2c_test"
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("[email protected]");
static void i2c_io_init(void);
static struct i2c_device_id i2c_test_id_table[] = {
{"i2c_test", 0},
{},
};
static int i2c_test_probe(struct i2c_client *client, const struct i2c_device_id *id);
static int i2c_test_remove(struct i2c_client *client);
static struct i2c_driver i2c_test_driver = {
.probe = i2c_test_probe,
.remove = i2c_test_remove,
.id_table = i2c_test_id_table,
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
}
};
/* define i2c_driver callback functions */
static int i2c_test_read_fw(struct i2c_client *client);
static int i2c_test_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
printk("i2c test probe\n");
printk("touchscreen io init\n");
i2c_io_init();
i2c_test_read_fw(client);
return 0;
}
static int i2c_test_remove(struct i2c_client *client)
{
printk("i2c test remove\n");
return 0;
}
static int i2c_test_read_reg(struct i2c_client *client, u8 addr, u8 *data)
{
int error;
u8 buf[4] = {0};
struct i2c_msg msgs[] = {
{
.addr = client->addr,
.flags = 0,
.len = 1,
.buf = buf,
},
{
.addr = client->addr,
.flags = 1,
.len = 1,
.buf = buf,
},
};
buf[0] = addr;
error = i2c_transfer(client->adapter, msgs, 2);
if(error < 0)
goto err_i2c_trans;
*data = buf[0];
return 0;
err_i2c_trans:
printk("i2c transfer failed\n");
return error;
}
static int i2c_test_read_fw(struct i2c_client *client)
{
int error;
u8 val;
error = i2c_test_read_reg(client, 0xa6, &val);
if(error < 0)
goto err_read_i2c_reg;
printk("fw is %x\n", val);
return 0;
err_read_i2c_reg:
printk("read i2c reg failed\n");
return error;
}
static void i2c_io_init(void)
{
int ret;
ret = gpio_request(EXYNOS4_GPL0(2), "TP1_EN");
if (ret) {
printk(KERN_ERR "failed to request TP1_EN for "
"I2C control\n");
//return err;
}
gpio_direction_output(EXYNOS4_GPL0(2), 1);
s3c_gpio_cfgpin(EXYNOS4_GPL0(2), S3C_GPIO_OUTPUT);
gpio_free(EXYNOS4_GPL0(2));
mdelay(5);
ret = gpio_request(EXYNOS4_GPX0(3), "GPX0_3");
if (ret) {
gpio_free(EXYNOS4_GPX0(3));
ret = gpio_request(EXYNOS4_GPX0(3), "GPX0_3");
if(ret)
{
printk("ft5xox: Failed to request GPX0_3 \n");
}
}
gpio_direction_output(EXYNOS4_GPX0(3), 0);
mdelay(200);
gpio_direction_output(EXYNOS4_GPX0(3), 1);
s3c_gpio_cfgpin(EXYNOS4_GPX0(3), S3C_GPIO_OUTPUT);
gpio_free(EXYNOS4_GPX0(3));
msleep(300);
}
static int i2c_test_init(void)
{
int error;
printk("i2c test init\n");
printk("i2c register driver\n");
error = i2c_register_driver(THIS_MODULE, &i2c_test_driver);
if(error < 0)
goto err_reg_i2c_dri;
return 0;
err_reg_i2c_dri:
printk("fail to register i2c driver\n");
return error;
}
static void i2c_test_exit(void)
{
printk("i2c test exit\n");
printk("i2c del driver\n");
i2c_del_driver(&i2c_test_driver);
}
module_init(i2c_test_init);
module_exit(i2c_test_exit);