本文基于linux 4.19 版本内核进行分析。
Linux内核很多驱动都使用到I2C子系统。EEPROM、RTC,电池,tp等。
inux内核的i2c-gpio是使用GPIO模拟I2C协议的驱动,在内核中已经实现了,我们要做的只需要配置2根GPIO即可。
GPIO模拟I2C协议的驱动位于drivers/i2c/busses目录。驱动名称为“i2c-gpio”,驱动文件为drivers/i2c/busses/i2c-gpio.c
1.1. GPIO支持要先保证是选上的
1.2. 先配置内核
Device Drivers-> I2C support ---> I2C Hardware Bus support ---> <*> GPIO-based bitbanging I2C
从配置中看到将驱动整合到内核中,而不是module形式。这样能保证在其它I2C板级信息注册之前,已经存在了i2c总线。
另外,还需要GPIO库支持:
[*] GPIO Support --->
否则无法不会出现选项“GPIO-based bitbanging I2C”。
首先需要在dtsi文件加上节点
i2c-gpio: i2c-gpio {
compatible = “i2c-gpio”;
status = “disabled”;
};
在dts文件加上器件描述:
&i2c-gpio {
pinctrl-names = “default”;
status = “okay”;
eeprom: m24c08@23 {
compatible = “st,m24512”;
reg = <0x23>;
status = “okay”;
};
};
i2c-gpio.c文件中提供的接口:
static void i2c_gpio_setsda_dir(void *data, int state) static void i2c_gpio_setsda_val(void *data, int state) static void i2c_gpio_setscl_dir(void *data, int state) static void i2c_gpio_setscl_val(void *data, int state) static int i2c_gpio_getsda(void *data) static int i2c_gpio_getscl(void *data)
跟普通的gpio模拟i2c所实现的接口一致,是实现的gpio的sda,scl的设置,仅此而已。
在kernel/driver/i2c/algos/i2c-algo-bit.c中是系统中默认提供的gpio模拟i2c的框架代码。
static inline void sdalo(struct i2c_algo_bit_data *adap) static inline void sdahi(struct i2c_algo_bit_data *adap) static inline void scllo(struct i2c_algo_bit_data *adap) static int sclhi(struct i2c_algo_bit_data *adap) static void i2c_start(struct i2c_algo_bit_data *adap) static void i2c_repstart(struct i2c_algo_bit_data *adap) static void i2c_stop(struct i2c_algo_bit_data *adap) static int i2c_outb(struct i2c_adapter *i2c_adap, unsigned char c) static int i2c_inb(struct i2c_adapter *i2c_adap) static int test_bus(struct i2c_algo_bit_data *adap, char *name) static int try_address(struct i2c_adapter *i2c_adap, unsigned char addr, int retries) static int sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) static int acknak(struct i2c_adapter *i2c_adap, int is_ack) static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) static int bit_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) /* -----exported algorithm data: ------------------------------------- */ static const struct i2c_algorithm i2c_bit_algo = { .master_xfer = bit_xfer, .functionality = bit_func, };
这里对于任何一个做过gpio模拟i2c模拟的童鞋来说都没有陌生的东西,不明白的可以看看i2c的协议,比我说的清楚。
这里说下出现的struct i2c_algorithm,其中的master_xfer就是我们调用i2c_master_send/i2c_master_recv的时候最终调用的接口。
参考:
[1]:https://blog.csdn.net/skywalkzf/article/details/6575773