1.Linux主机驱动和外设驱动分离思想

外设驱动→API→主机驱动→板机逻辑--具体的i2c设备(camera,ts,eeprom等等)

 

2.主机驱动

根据控制器硬件手册,操作具体的寄存器,产生波形。

 

  • Linux应用工程师:屏蔽了驱动和硬件
  • Linux驱动工程师:屏蔽硬件,提供标准的主机驱动。驱动工程师需要完成“外设驱动”

 

  • 内核函数接口:(API)。主机驱动提供給外设驱动的函数接口
    1. 注册i2c设备:i2c_board_info
    2. 驱动注册和卸载函数以及结构体:i2c_del_driver/i2c_add_driver, i2c_driver
    3. 读写函数和结构体:i2c_transfer, i2c_msg

这些函数放之四海之内皆准

 

3.外设驱动

针对具体的外部器件的代码。

  • 摄像头以及声卡中i2c用来配置外部设备(声卡和摄像头)→地址和配置的内容都不一样!

 

4.板级逻辑

描述主机和外部设备是怎么连接的

 

5.设备-i2c设备注册以及设备注册之后的查询方法

  • 查询i2c设备地址:ls /sys/bus/i2c/devices/
  • 怎么和原理图以及外部设备对应:3-0038→I2C_3_SCL(addr:datasheet中查0x38)
  • 查询i2c设备名称:cat /sys/bus/i2c/devices/3-0038/name

 

menuconfig中去掉触摸的驱动

  • Device Drivers  --->
  • Input device support  --->
  • Touchscreens  --->
  • FT5X0X based touchscreens(去掉)

 

添加i2c设备:i2c_devs3[]中添加
        {
                I2C_BOARD_INFO("i2c_test", 0x70>>1),
        },
cat /sys/bus/i2c/devices/3-0038/name结果是i2c_test   

 

6.驱动-i2c驱动注册和卸载

i2c设备初始化完成-进入probe函数

i2c_del_driver/i2c_add_driver, i2c_driver

module_init和late_initcall:前面的优先加载,后面的延迟加载

 驱动代码:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>

#include <linux/regulator/consumer.h>

#include <mach/gpio.h>
#include <plat/gpio-cfg.h>
#include <plat/ft5x0x_touch.h>

#define I2C_TEST_NAME "i2c_test"

static int i2c_test_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
        printk("==%s: \n", __FUNCTION__);
        return 0;
}

static int __devexit i2c_test_remove(struct i2c_client *client)
{
        i2c_set_clientdata(client, NULL);               //设置client为NULL
        printk("==%s: \n", __FUNCTION__);
        return 0;
}

static const struct i2c_device_id i2c_test_id[] = {
        { "i2c_test", 0 },
        { }
};

static struct i2c_driver i2c_test_driver = {
        .probe = i2c_test_probe,
        .remove = __devexit_p(i2c_test_remove),
        .id_table = i2c_test_id,
        .driver = {
                .name  = I2C_TEST_NAME,
                .owner = THIS_MODULE,
        },
};

static void i2c_io_init()
{
        int ret;
        ret = gpio_request(EXYNOS4_GPL0(2), "TP1_EN");
        if(ret) {
                printk(KERN_ERR "failed to request TP1_EN for I2C control\n");
        }

        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("i2c_io_test: Fialed 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 __init i2c_test_init(void)
{
        printk("==%s: \n", __FUNCTION__);
        i2c_io_init();
        printk("==%s: \n", __FUNCTION__);
        return i2c_add_driver(&i2c_test_driver);
}

static void __exit i2c_test_exit(void)
{
        printk("==%s: \n", __FUNCTION__);
        i2c_del_driver(&i2c_test_driver);
}

late_initcall(i2c_test_init);
module_exit(i2c_test_exit);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("TSI2CTEST");
MODULE_AUTHOR("iTOP");
i2c.c

相关文章: