6.I2C子系统(上)

I2C协议和时序

I2C驱动开发:
I2C从设备驱动开发
硬件芯片:从设备
cmos camera
ts :电容触摸屏
gsenor: 重力传感器
eeprom: 存储设备
HDMI:高清输出接口
在这里插入图片描述

Linux I2C驱动框架

在这里插入图片描述

Linux I2C总线和平台总线的结合

2,i2c子系统软件框架

应用
------------------------------------------
i2c driver:从设备驱动层
	 需要和应用层进行交互
	 封包数据,不知道数据是如何写入到硬件

------------------------------------------
i2c 核心层:维护i2c 总线,包括i2c driver, i2c client链表
drivers/i2c/i2c-core.c
---------------------------------------------------
i2c adapter层:i2c控制层,初始化i2c控制器
		完成将数据写入或读取-从设备硬件
		不知道数据具体是什么,但是知道如何操作从设备
drivers/i2c/busses/i2c-s3c2410.c
================================================================
确保i2c core和i2c adatper层必须编译进内核:

make menuconfig
	Device Drivers  --->
		-*- I2C support  ---> //编译i2c-core.c
			I2C Hardware Bus support  --->
				<*> S3C2410 I2C Driver // i2c-s3c2410.c


/sys/bus/i2c/
/sys/bus/i2c/devices/i2c-0 
			[root@farsight i2c-0]# cat name
					s3c2410-i2c

在这里插入图片描述

Linux I2C从设备的设备树信息的添加

3, I2c子系统中涉及到的设备树文件:
i2c控制器地址
0x1386_0000,
0x1387_0000,
0x1388_0000,
0x1389_0000,
0x138A_0000,
0x138B_0000, ------ MPU6050
0x138C_0000,
0x138D_0000,
0x138E_0000

MPU6050: 从设备地址是0x68
	soc GPB_3---	I2C_SCL5
		GPB_2---  I2C_SDA5
		GPX3_3--- GYRO_INT


在内核中默认就有了i2c0--13860000.i2c


模板:
	控制器对应的设备树:arch/arm/boot/dts/exynos4.dtsi
	  i2c_0: i2c@13860000 {
            #address-cells = <1>;
            #size-cells = <0>;
            compatible = "samsung,s3c2440-i2c";
            reg = <0x13860000 0x100>;
            interrupts = <0 58 0>;
            clocks = <&clock 317>;
            clock-names = "i2c";
            pinctrl-names = "default";
            pinctrl-0 = <&i2c0_bus>;
            status = "disabled";
    };

	  i2c_5: i2c@138B0000 {
            #address-cells = <1>;
            #size-cells = <0>;
            compatible = "samsung,s3c2440-i2c";
            reg = <0x138B0000 0x100>;
            interrupts = <0 63 0>;
            clocks = <&clock 322>;
            clock-names = "i2c";
            status = "disabled";


    };

描述从设备信息的设备树的模板
	arch/arm/boot/dts/exynos4412-fs4412.dts


	 i2c@13860000 {
            #address-cells = <1>;
            #size-cells = <0>;
            samsung,i2c-sda-delay = <100>;
            samsung,i2c-max-bus-freq = <20000>;
            pinctrl-0 = <&i2c0_bus>;
            pinctrl-names = "default";
            status = "okay";

            s5m8767_pmic@66 {
                    compatible = "samsung,s5m8767-pmic";
                    reg = <0x66>;
			}
				
	}

新增加i2c从设备,arch/arm/boot/dts/exynos4412-fs4412.dts增加i2c5控制和它包含了设备设备
    i2c@138B0000 {/*i2c adapter5信息*/
            #address-cells = <1>;
            #size-cells = <0>;
            samsung,i2c-sda-delay = <100>;
            samsung,i2c-max-bus-freq = <20000>;
            pinctrl-0 = <&i2c5_bus>;
            pinctrl-names = "default";
            status = "okay";

            mpu6050@68 { /*i2c client信息*/
                    compatible = "invensense,mpu6050";
                    reg = <0x68>;
			};
    };

	保存后make dtbs

	cp -raf arch/arm/boot/dts/exynos4412-fs4412.dtb /tftpboot/

Linux I2C client_driver_adapter_msg等对象的讲解

4,i2c driver驱动的编写:
a, 添加i2c client的信息,必须包含在控制器对应的节点中
b,直接编写i2c driver
1,构建i2c driver,并注册到i2c总线
2,实现probe:
|
申请设备号,实现fops
创建设备文件
通过i2c的接口去初始化i2c从设备

几个常用的对象:
struct i2c_driver {//表示是一个从设备的驱动对象
	int (*probe)(struct i2c_client *, const struct i2c_device_id *);
	int (*remove)(struct i2c_client *);
	struct device_driver driver; //继承了父类
				|
				const struct of_device_id	*of_match_table;
	const struct i2c_device_id *id_table;//用于做比对,非设备树的情况
}
注册和注销
	int i2c_add_driver( struct i2c_driver *driver);
	void i2c_del_driver(struct i2c_driver *);


struct i2c_client {//描述一个从设备的信息,不需要在代码中创建,因为是由i2c adapter帮我们创建
	unsigned short addr;		//从设备地址,来自于设备树中<reg>
	char name[I2C_NAME_SIZE]; //用于和i2c driver进行匹配,来自于设备树中compatible
	struct i2c_adapter *adapter;//指向当前从设备所存在的i2c adapter
	struct device dev;		// 继承了父类
};
创建i2c client的函数
struct i2c_client *i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)



struct i2c_adapter {//描述一个i2c控制器,也不是我们要构建,原厂的代码会帮我们构建
	const struct i2c_algorithm *algo; //算法
				|
				int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs,int num);
	
	struct device dev; //继承了父类,也会被加入到i2c bus
	int nr; //编号

}
注册和注销:
int i2c_add_adapter(struct i2c_adapter * adapter);
void i2c_del_adapter(struct i2c_adapter * adap);


struct i2c_msg {//描述一个从设备要发送的数据的数据包
	__u16 addr;	 //从设备地址,发送给那个从设备
	__u16 flags; //读1还是写0
	__u16 len;		//发送数据的长度
	__u8 *buf;		//指向数据的指针
};
//写从设备
int i2c_master_send(const struct i2c_client * client,const char * buf,int count)
//读从设备
int i2c_master_recv(const struct i2c_client * client,char * buf,int count)
以上两个函数都调用了:
int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值