I2C总线
I2C总线和 platform 总线非常类似,platform 总线初始化位置如下:
kernel_init(); kernel_init_freeable(); do_basic_setup(); driver_init(); platform_bus_init();
I2C总线是作为一个模块进行初始化
postcore_initcall(i2c_init);#define postcore_initcall(fn) __define_initcall(fn, 2)
由此可见,platform 总线不可或缺,I2C总线是可以被裁剪的。
I2C总线的全局变量如下:
I2C适配器
每一个soc上基本都会有一个或者多个I2C控制器,每一个I2C控制器下面接的就是SCL 和 SDA 两条线。I2C设备设备都是挂在这两条线下面的,这就是就硬件层的基本结构。
硬件层的上面就是Linux内核中的适配器驱动层,每一个soc厂家都会在Linux框架上实现自家IIC控制的的驱动程序,这部分是由soc厂家的bsp工程师提供的。其实就是根据I2C控制器的寄存器操作实现了如何将数据送到I2C总线下的设备中去,以及怎么读取数据。厂家将这一层封装好,驱动工程师写驱动的时候就只需要根据具体的I2C设备来读写数据,不需要自己来实现I2C时序。简单点就说设备驱动只负责准备要发的数据,告诉适配器就可以了。至于怎么发就是厂家自己去实现了,毕竟只有他们才最熟悉自家的芯片。
I2C适配器就是根据设备树提供的I2C控制器信息配置芯片,如下i2c1
i2c1: i2c@21a0000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx6ul-i2c", "fsl,imx21-i2c"; reg = <0x021a0000 0x4000>; interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clks IMX6UL_CLK_I2C1>; status = "disabled"; };
&i2c1 { clock-frequency = <100000>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2c1>; status = "okay"; magnetometer@e { compatible = "fsl,mag3110"; reg = <0x0e>; vdd-supply = <®_peri_3v3>; vddio-supply = <®_peri_3v3>; position = <2>; }; fxls8471@1e { compatible = "fsl,fxls8471"; reg = <0x1e>; position = <0>; interrupt-parent = <&gpio5>; interrupts = <0 8>; }; };
static const struct of_device_id i2c_imx_dt_ids[] = { { .compatible = "fsl,imx1-i2c", .data = &imx1_i2c_hwdata, }, { .compatible = "fsl,imx21-i2c", .data = &imx21_i2c_hwdata, }, { .compatible = "fsl,vf610-i2c", .data = &vf610_i2c_hwdata, }, { .compatible = "fsl,imx7d-i2c", .data = &imx7d_i2c_hwdata, }, { /* sentinel */ } }; static struct platform_driver i2c_imx_driver = { .probe = i2c_imx_probe, .remove = i2c_imx_remove, .driver = { .name = DRIVER_NAME, .pm = &i2c_imx_pm_ops, .of_match_table = i2c_imx_dt_ids, .acpi_match_table = i2c_imx_acpi_ids, }, .id_table = imx_i2c_devtype, };static int __init i2c_adap_imx_init(void) { return platform_driver_register(&i2c_imx_driver); } subsys_initcall(i2c_adap_imx_init);
i2c_adap_imx_init() 是芯片厂家提供的适配器驱动,设备和驱动匹配执行 i2c_imx_probe() ,内容有:
添加 i2c_adapter_type 类型设备到 I2C 总线 (bus_add_device)
添加 i2c_client_type 类型设备到 I2C 总线
至此,soc上的adapter就和client进行了一个一一对应的绑定,而且都注册进内核总线上了。有多少个硬件adapter就会在总线上注册多少个client。
标签:I2C,fsl,总线,驱动,init,imx,IC2,i2c From: https://www.cnblogs.com/god-of-death/p/17291278.html