**MTK平台安卓R/Q版本上如何写一份i2c接口驱动**

MTK平台安卓R/Q版本上如何写一份i2c接口驱动
1.LK阶段:
#define IML7525_BIAS_I2C_BUSNUM I2C3 //设备挂载在i2c3总线上
#define IML7525_SLAVE_ADDR_WRITE 0x3E //此处写七位地址即可,读写位会位移
static struct mt_i2c_t iml7525_i2c;//定义一个mt_i2c_t结构体
/*****************************************************************************/
int iml7525_write_bytes(char addr, char value)
{
int ret_code = I2C_OK;
char write_data[2];
char len;

   write_data[0]= addr;
   write_data[1] = value;

   iml7525_i2c.id = IML7525_BIAS_I2C_BUSNUM;
   /* Since i2c will left shift 1 bit, we need to set FAN5405 I2C address to >>1 */
   iml7525_i2c.addr = IML7525_SLAVE_ADDR_WRITE;
   iml7525_i2c.mode = ST_MODE;
   iml7525_i2c.speed = 100;
   len = 2;

   ret_code = i2c_write(&iml7525_i2c, write_data, len);
   if (ret_code<0)
           printf("%s: %d\n", __func__, ret_code);

   return ret_code;

}

int iml7525_read_byte(u8 addr,u8 *dataBuffer)
{
int ret_code = I2C_OK;
u16 len;
*dataBuffer = addr;
//u8 buffer[1], reg_value[1];
iml7525_i2c.id = IML7525_BIAS_I2C_BUSNUM;
iml7525_i2c.addr = IML7525_SLAVE_ADDR_WRITE;
//iml7525_i2c.addr = (IML7525_SLAVE_ADDR_WRITE >> 1);
iml7525_i2c.mode = ST_MODE;
iml7525_i2c.speed = 100;
len = 1;

   ret_code = i2c_write_read(&iml7525_i2c, dataBuffer, len, len);
   printf("%s: i2c_read: ret_code: %d\n", __func__, ret_code);
return ret_code;

}
/*****************************************************************************/

读写接口封装完成即可在其他模块进行i2c读写操作如下:
int index_7525 = 0,REG_NUM = 4;
unsigned char iml7525_reg[4];
iml7525_write_bytes(0x00,0x11);//VPOS 5.7
iml7525_write_bytes(0x01,0x11);//VNEG -5.7
for (index_7525 = 0; index_7525 < REG_NUM; index_7525++){
iml7525_read_byte(index_7525,&iml7525_reg[index_7525]);
printf("kzhkzh IML7525 [0x%x]=0x%x ", index_7525, iml7525_reg[index_7525]);
}
2.kernel部分添加一份i2c驱动:
①在对应dts里i2c3 bus节点里添加:
iml7525@3e {
compatible = “mid,iml7525”;
reg = <0x3e>;
status = “okay”;
};
需要添加的目录makefile添加:
obj -y += iml7525_bias.o ##编译自己需要写的i2c驱动,我这边命名为iml7525_bias.c

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>//mid add
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/i2c.h>
#include <linux/irq.h>
#include <linux/jiffies.h>
#include <linux/uaccess.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/miscdevice.h>
#include <linux/spinlock.h>
#include <asm/siginfo.h>
#include <linux/rcupdate.h>
#include <linux/sched.h>
#include <linux/sched/signal.h>
#include <linux/workqueue.h>

#ifdef CONFIG_OF
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>
#endif
#include <linux/timer.h>
//添加必要的头文件,这边暂时拷贝了一份tp i2c的头文件,去掉了一些不必要的头文件

//static DEFINE_MUTEX(mid_ctrl_mutex); //互斥锁,暂时不用,节点读写操作时可以使用一下

static const struct i2c_device_id iml7525_i2c_id[] = { {“iml7525”, 0}, {} };

static int iml7525_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id);

#ifdef CONFIG_OF
static const struct of_device_id iml7525_of_match[] = {
{.compatible = “mid,iml7525”,}, //和dts 节点compatible要一致匹配
{},
};

MODULE_DEVICE_TABLE(i2c, iml7525_of_match);
#endif

static struct i2c_driver iml7525_driver = {
.driver = {
.name = “iml7525”,
#ifdef CONFIG_OF
.of_match_table = iml7525_of_match,
#endif
},
.probe = iml7525_i2c_probe,
.id_table = iml7525_i2c_id,
};

struct i2c_client *iml7525_client = NULL;//定义一个全部变量i2c_client,以便后续封装读写全局的读写i2c接口

int iml7525_read(u8 addr, u8 *data)
{
u8 buf;
int ret = 0;
struct i2c_client *client = iml7525_client;
buf = addr;
//printk(“Kzhkzh %s:%d i2c->addr:0x%x\n”,func,LINE,iml7525_client->addr);
ret = i2c_master_send(client, (const char *)&buf, 1);
if (ret != 1) {
printk(“send command error!!\n”);
return -EFAULT;
}
ret = i2c_master_recv(client, (char *)&buf, 1);
if (ret != 1) {
printk(“reads data error!!\n”);
return -EFAULT;
}
else
printk("%s(0x%02X) = 0x%02X\n", func, addr, buf);
*data = buf;
return 0;
}
int iml7525_write(u8 reg, unsigned char value)
{
int ret;
u8 write_cmd[2] = {0};

    write_cmd[0] = reg;
    write_cmd[1] = value;

    ret = i2c_master_send(iml7525_client, write_cmd, 2);
    if (ret != 2) {
            printk("iml7525_write error->[REG=0x%02x,val=0x%02x,ret=%d]\n", reg, value, ret);
            return -1;
    }
            //printk("iml7525_write success->[REG=0x%02x,val=0x%02x,ret=%d]\n", reg, value, ret);
    return 0;

}//目前都是用linux原生的i2c_master_send和i2c_master_recv封装的8bit 寄存器i2c读写接口若是16 bit可以再封装一次即可
/**********************************************************
*

  • dump IML7525 all of register ,add by ROCO mid

*********************************************************/
void iml7525_dump_register(void)
{
//unsigned int IMl7525_REG_NUM 4;//0x00 to 0x03
unsigned char iml7525_reg[4];
int reg_index;
for (reg_index = 0; reg_index < 4; reg_index++) {
iml7525_read(reg_index, &iml7525_reg[reg_index]);
printk("Kzhkzh [0x%x]=0x%x ", reg_index, iml7525_reg[reg_index]);
}
return;
}

/**********************************************************
*

  • [Global Variable]

*********************************************************/

static int iml7525_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
{

   iml7525_client = i2c;//拷贝i2c_client数据到私有iml7525_client,方便后续封装
   
   printk("Kzhkzh %s:%d i2c->addr:0x%x\n",__func__,__LINE__,iml7525_client->addr);
   if(0x3e == iml7525_client->addr){//判断i2c地址是否为0x3e七位地址,若是,dump一下整个i2c寄存器,测试ok
           printk("Kzhkzh %s:%d enter iml7525_dump_register\n",__func__,__LINE__);
           iml7525_dump_register();
   }
   return 0;

}

/**********************************************************
*

  • [platform_driver API]

*********************************************************/

static int __init iml7525_init(void)
{
printk("******** iml7525_init! ********\n");
if (i2c_add_driver(&iml7525_driver) != 0) {
//i2c_add_driver会去匹配dts的compatible name和驱动里面iml7525_driver调用到.of_match_table = iml7525_of_match的
{.compatible = “mid,iml7525”,}, ,若i2c地址一致,且字符串一致,可以跑进probe
printk( “[iml7525_init] failed to register iml7525 i2c driver.\n”);
} else {
printk(
“[iml7525_init] Success to register iml7525 i2c driver.\n”);
}

   return 0;

}

static void __exit iml7525_exit(void)
{
i2c_del_driver(&iml7525_driver);//模块退出时记得delete掉iml7525_driver
printk("[iml7525] iml7525_exit !!! \n");

}

module_init(iml7525_init);//模块入口,开机时就会先加载module_init跑进iml7525_init,加载顺序我记得是6,同样较常见的还可以用
//late_initcall(iml7525_init);等看实际需要加载先后顺序
module_exit(iml7525_exit);
//模块退出时跑
MODULE_LICENSE(“GPL”);
MODULE_DESCRIPTION(“I2C iml7525 bias avdd avee Driver”);
MODULE_AUTHOR(“kuangzenghui@szroco.com”);

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值