iic驱动程序(基于itop4412)

2018-08-09  本文已影响0人  嵌入式工作

iic驱动

1主机驱动:根据控制器硬件手册,操作具体的寄存器,产生波形,cpu厂家提供

2我们需要做的是

1在cpu平台的datasheet中找到对应的iic编号,这里我们是驱动触摸ic,使用的iic3
2由于iic驱动已经被编译到了内核,我们要先取消
menuconfig中去掉触摸的驱动
Device Drivers --->
Input device support --->
Touchscreens --->
FT5X0X based touchscreens(去掉)

3设备-i2c设备注册以及设备注册之后的查询方法
查询i2c设备地址:ls /sys/bus/i2c/devices/
怎么和原理图以及外部设备对应:3-0038→I2C_3_SCL(addr:datasheet中查0x38)
查询i2c设备名称:cat /sys/bus/i2c/devices/3-0038/name
3
修改vim arch/arm/mach-exynos/mach-itop4412.c 加入#else的内容

        /* add by cym 20130318 support for FT5X0X TouchScreen */
#if defined(CONFIG_TOUCHSCREEN_FT5X0X)
        {       I2C_BOARD_INFO("ft5x0x_ts", 0x70>>1),
                .irq = IRQ_EINT(4),
                .platform_data = &ft5x0x_pdata,
        },
#else

        {
        I2C_BOARD_INFO("i2c3_test",0x70>>1),
        },
#endif
        /* end add */
};

4 I2C函数接口(API):
设备注册:i2c_board_info
驱动注册函数和结构体:i2c_del_driver/i2c_add_driver,i2c_driver
读写函数和结构体:i2c_transfer,i2c_msg

3实现代码






#include <asm/uaccess.h>


#include <linux/init.h>
#include <linux/module.h>
#include <linux/i2c.h>


#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/slab.h>

#include <linux/input.h>
#include <linux/delay.h>

#include <linux/init.h>
#include <linux/module.h>

#include <linux/kernel.h>
#include <linux/fs.h>
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>
#include <linux/miscdevice.h>
#include <linux/platform_device.h>
//#include <mach/gpio-bank.h>
#include <mach/regs-gpio.h>
#include <asm/io.h>
#include <linux/regulator/consumer.h>
//#include "gps.h"
#include <linux/delay.h>

#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>
#ifdef CONFIG_HAS_EARLYSUSPEND
#include <linux/earlysuspend.h>
#endif

#include <linux/regulator/consumer.h>

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


#define IIC_NAME "i2c3_test"
#define DEVICE_NAME "tp_77"
struct i2c_client *p_mclient;

static int ft5x0x_read_reg(u8 addr, u8 *pdata) 
{
    u8 buf[4] = { 0 };
    struct i2c_msg msgs[] = {
        {
            .addr   = p_mclient->addr,
            .flags  = 0,
            .len    = 1,
            .buf    = buf,
        },
        {
            .addr   = p_mclient->addr,
            .flags  = I2C_M_RD,
            .len    = 1,
            .buf    = buf,
        },
    };
    int ret;

    buf[0] = addr;
    ret = i2c_transfer(p_mclient->adapter, msgs, 2);
    if (ret < 0) {
        pr_err("read reg (0x%02x) error, %d\n", addr, ret);
    } else {
        *pdata = buf[0];
    }

    return ret;
}

static int ft5x0x_read_fw_ver(unsigned char *val)
{
    int ret;

    *val = 0xff;
    ret = ft5x0x_read_reg(0xa6, val);
    if (*val == 0x06) {
printk("fw ver ok %d %s\n", *val,__FUNCTION__);
    } else {
    printk("fw ver err %d %s\n", *val,__FUNCTION__);
    }

    return ret;
}

static int i2c_open_func(struct file *filp)
{
    return 0;
}

static int i2c_release_func(struct file *filp)
{
    return 0;
}

static ssize_t i2c_read_func(struct file *filp, char __user *buffer, size_t count, loff_t *ppos){
    int ret;
    u8 reg_data;
    
    ret = copy_from_user(&reg_data,buffer,1);
    
    struct i2c_msg msgs[] = {
        {
            .addr   = p_mclient->addr,  //0x38
            .flags  = 0,    //写
            .len    = 1,    //要写的数据的长度
            .buf    = &reg_data,
        },
        {
            .addr   = p_mclient->addr,
            .flags  = I2C_M_RD,
            .len    = 1,
            .buf    = &reg_data,
        },
    };
    ret = i2c_transfer(p_mclient->adapter, msgs, 2);
    if (ret < 0) {
        pr_err("read reg error!\n");
    }
    ret = copy_to_user(buffer,&reg_data,1);
    
    return ret;
}

static ssize_t i2c_write_func(struct file *filp, char __user *buffer, size_t count, loff_t *ppos){
    int ret;
    u8 buf[2];
    struct i2c_msg msgs[1];
    
    ret = copy_from_user(&buf,buffer,2);
    
    msgs[0].addr    = p_mclient->addr;  //0x38
    msgs[0].flags   = 0;    //写
    msgs[0].len = 2;    //第一个是要写的寄存器地址,第二个是要写的内容
    msgs[0].buf = buf;

    ret = i2c_transfer(p_mclient->adapter, msgs, 1);
    if (ret < 0) {
        pr_err("write reg 0x%02x error!\n",buf[0]);
    }
    ret = copy_to_user(buffer,buf,1);
    
    return ret;
}


static struct file_operations i2c_ops = {
    .owner  = THIS_MODULE,
    .open   = i2c_open_func,
    .release= i2c_release_func,
    .write  = i2c_write_func,
    .read   = i2c_read_func,
};



static struct miscdevice iic3_dev = {
    .minor  = MISC_DYNAMIC_MINOR,
    .fops   = &i2c_ops,
    .name   = DEVICE_NAME,
};




static int __devinit tp_probe(struct i2c_client *client,const struct i2c_device_id *id)
{
    unsigned char val;
    p_mclient=client;
      printk(KERN_EMERG"tp_prob\n");
    ft5x0x_read_fw_ver(&val);
    misc_register(&iic3_dev);
    return 0;
}


static int __devexit tp_remove(struct i2c_client *client)
{
  
    i2c_set_clientdata(client, NULL);
     misc_deregister(&iic3_dev);
    return 0;
}

static const struct i2c_device_id tp_id_table[] = {
    { IIC_NAME, 0 },
    { }
};



struct i2c_driver i2c3_driver=
{
    .driver = {
        .name   = "driver_name_iic",
        .owner  = THIS_MODULE,
    },
    .probe      = tp_probe,
    .remove     = __devexit_p(tp_remove),
    .id_table   = tp_id_table,
};



static int iic_init(void)
{
    int ret;
            //TP1_EN
    printk("==%s: TP1_EN==\n", __FUNCTION__);
    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);



        printk("==%s: reset==\n", __FUNCTION__);
        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);
        
    return i2c_add_driver(&i2c3_driver); 
    
}

static void iic_exit(void)
{
    
   i2c_del_driver(&i2c3_driver); 
    
}


MODULE_AUTHOR("kerwin");
MODULE_LICENSE("GPL");

late_initcall(iic_init);
module_exit(iic_exit);




















上一篇 下一篇

猜你喜欢

热点阅读