內核默認支持模擬i2c,那應該怎麼用呢,參考https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/i2c/i2c-gpio.txt?h=v4.14-rc6 是不是跟平常用的硬件i2c dts配置很類似呢
i2c@0 {
compatible = "i2c-gpio";
gpios = <&pioA 23 0 /* sda */
&pioA 24 0 /* scl */
>;
i2c-gpio,sda-open-drain;
i2c-gpio,scl-open-drain;
i2c-gpio,delay-us = <2>; /* ~100 kHz */
#address-cells = <1>;
#size-cells = <0>;
rv3029c2@56 {
compatible = "rv3029c2";
reg = <0x56>;
};
};
同時加上CONFIG_I2C_GPIO CONFIG_I2C_ALGOBIT
drivers/i2c/busses/i2c-gpio.c 註冊i2c總線
drivers/i2c/algos/i2c-algo-bit.c 實現模擬i2c協議
const struct i2c_algorithm i2c_bit_algo = {
.master_xfer = bit_xfer,
.functionality = bit_func,
};
static int __i2c_bit_add_bus(struct i2c_adapter *adap,int (*add_adapter)(struct i2c_adapter *))
{
adap->algo = &i2c_bit_algo;
ret = add_adapter(adap);
}
int i2c_bit_add_numbered_bus(struct i2c_adapter *adap)
{
return __i2c_bit_add_bus(adap, i2c_add_numbered_adapter);
}
EXPORT_SYMBOL(i2c_bit_add_numbered_bus);
我使用平臺的有點差異,要獲取sda的電平,先要設置成輸入狀態,按如下修改
static int i2c_gpio_getsda(void *data)
{
struct i2c_gpio_platform_data *pdata = data;
-
- return gpio_get_value(pdata->sda_pin);
+ int state;
+ gpio_direction_input(pdata->sda_pin);
+ state=gpio_get_value(pdata->sda_pin);
+ gpio_direction_output(pdata->sda_pin,1);
+ return state;
}
是不是瞬間就搞定了呢,i2c驅動用硬件的i2c驅動就行了。