我们先来参考一下内核中自带的驱动程序,看看别人怎么写的
我们可以对内核进行make menuconfIg 看看它对应于哪一个文件
这里有个S3C2410 I2C Driver
然后按下H可以看到它依赖于那个配置
这里是依赖于我们的CONFIG_I2C_S3C2410这个配置的
我们在driver/i2c目录下搜索,CONFIG_I2C_S3C2410,看看它对应哪个文件
对应于我们的i2c-s3c2410.c这个文件,于是我们去内核源码中看这个文件是怎么实现的,从入口函数开始看起
注册一个平台driver,调用probe函数
i2c_adap,分配设置构造这个i2c_adap,
然后通过上面这个函数注册adapter,先不管,这个驱动复杂主要复杂在下面这个成员
algo算法,进去看一下有什么算法
算法里面有个功能,看看这个函数
返回我们适配器支持的功能,还有一个主的传输函数
里面主要是调用doxfer,应该就是去实现I2C最底层的那些操作,比如说发出start信号,发出设备地址,读写数据等等等等这些操作。重点就在这个函数
现在我们反过来,我们以前写的驱动程序,
我们驱动里面调用i2c_smbus_wrire_byte_data等类似于这样的接口的,是怎么找到适配器,调用你适配器里面的传输函数
进入i2c_smbus_wrire_byte_data这个函数里面看一下
调用了i2c_smbus_xfer,进去看一眼
里面调用了adapter里面的算法里面的传输函数,我们的是master_xfer,我们没有设置smbus_xfer这个函数,他会调用这个函数,这个函数应该最终会调用到master_xfer这个函数,
我们现在开始写代码,记得三要素,分配,设置注册,三要素
我们肯定也是仿照内核中的代码来实现这个功能,在内核中搜索i2c_add_adapter函数来注册i2c_adapter,我们在内核中收索这个函数,这里说明一下
2440里面用的i2c_add_numbered_adapater,这个只是编号的然后在再注册,这里我们用i2c_add_adapter让系统自己帮我们编号
一大堆,我们就参考最后一个把
人家是这么定义的,我们把它拿过来
框架如下
static int s3c_xfer(struct i2c_adapter *adap,struct i2c_msg *msgs, int num)
{
}
static u32 s3c_func(struct i2c_adapter *adap)
{
//I2C_FUNC_I2C什么意思,我也不知道
//I2C_FUNC_SMBUS_EMUL 是什么意思呢,你不是说smbus不是i2c里面的一个
//小子集吗,smbus应该是在algo里面的smbus_xfer来做的,你可以看内核中
//i2c_algorithm这个结构体,其中就有一个成员变量是smbus_xfer
//如果你适配器直接支持smbus_xfer的话,你下面那个i2c_algorithm里面写一个
//函数,如果不支持的话,没关系,你也可以用master_xfer来支持它,来模拟它
//I2C_FUNC_PROTOCOL_MANGLING 这个暂时也不知道是什么意思
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_PROTOCOL_MANGLING;
}
static const struct i2c_algorithm s3c_algo = {
//主要的传输函数,怎么写,我们也是仿照
.master_xfer = s3c_xfer,
//功能,这里我们可以仿照2410的
.functionality = s3c_func,
};
/*
1.分配/设置i2c_adapter结构体
2.注册i2c_adapter结构体
*/
static struct i2c_adapter s3c_i2c_adapter = {
//名字不重要
.name = "S3c I2C bus",
//算法才是最重要的,这个我们也参考被人的代码
.algo = &s3c_algo,
//这个不需要
//.algo_data = &i2c_sgi_vino_data,
.owner = THIS_MODULE,
};
static int i2c_bus_s5pv210_init(void)
{
i2c_add_adapter(s3c_i2c_adapter);
return 0;
}
static void i2c_bus_s5pv210_exit(void)
{
i2c_del_adapter(s3c_i2c_adapter);
}
module_init(i2c_bus_s5pv210_init);
module_exit(i2c_bus_s5pv210_exit);
.master_xfer = s3c_xfer,这个才是难点中的难点,框架已经出来了,重要的,你这个框架你可以拿过去用到任何地方,主要是.master_xfer = s3c_xfer,这个文件
怎么发出I2C数据,这个才是单板相关的,
我们来看i2c_msg里面有什么东西,