【Linux内核驱动】编写I2C外设驱动读取触摸屏固件版本

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wr132/article/details/78569817

编写I2C外设驱动步骤

  1. 注册I2C设备,一般在板级文件中,定义i2c_board_info
  2. 注册I2C驱动:i2c_register_driver,i2c_del_driver
  3. 利用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);

猜你喜欢

转载自blog.csdn.net/wr132/article/details/78569817