【Linux 驱动】IMX6ULL eLCDIF驱动

1. I2C设备树

i2c1: i2c@021a0000 {
	#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";

	mag3110@0e {
		compatible = "fsl,mag3110";
		reg = <0x0e>;
		position = <2>;
	};

	fxls8471@1e {
		compatible = "fsl,fxls8471";
		reg = <0x1e>;
		position = <0>;
		interrupt-parent = <&gpio5>;
		interrupts = <0 8>;
	};
};
Device-Tree bindings for i2c gpio driver
Required properties:
	- compatible = "i2c-gpio";
	- gpios: sda and scl gpio
Optional properties:
	- i2c-gpio,sda-open-drain: sda as open drain
	- i2c-gpio,scl-open-drain: scl as open drain
	- i2c-gpio,scl-output-only: scl as output only
	- i2c-gpio,delay-us: delay between GPIO operations (may depend on each platform)
	- i2c-gpio,timeout-ms: timeout to get data
Example nodes:
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>; }; }; 

2. 相关数据结构体

2.1 i2c_adapter-控制器

I2C 适配器,也就是 SOC 的 I2C 控制器。i2c_adapter 结构体定义在 include/linux/i2c.h

/*
 * i2c_adapter is the structure used to identify a physical i2c bus along
 * with the access algorithms necessary to access it.
 */
struct i2c_adapter {
	struct module *owner;
     /* 适配器的类类型,在一些口I2C设备驱动中会检查该成员,以判断设备能否被该适配器操作 */
	unsigned int class;		  /* classes to allow probing for */   
     /* 适配器的类类型,在一些口I2C设备驱动中会检查该成员,以判断设备能否被该适配器操作 */
	const struct i2c_algorithm *algo; /* the algorithm to access the bus */
    指向通信方法数据的指针,该成员不会被I2C核心层修改,仅供具体的 i2c_algorithm使用
	void *algo_data;
 
	/* data fields that are valid for all devices	*/
	struct rt_mutex bus_lock;
    /* 传输超时时间 */
	int timeout;			/* in jiffies */
    /* 传输超时的重试次数 */
	int retries;
	struct device dev;		/* the adapter device */
	int nr;   /*总线编号(也是适配器编号),同时对应设备节点/dev/i2c-x (x=0,1,2 …)中的 x */
    /* 适配器名称,该名称可以通过sys/bus/i2c/devices/i2c-x/name (x=0,1,2 … )来访问 */
	char name[48];
	struct completion dev_released;
	struct mutex userspace_clients_lock;
	struct list_head userspace_clients;
	struct i2c_bus_recovery_info *bus_recovery_info;
	const struct i2c_adapter_quirks *quirks;
};

2.2 i2c_algorithm-通信方法

struct i2c_algorithm {
	/*
	 * If an adapter algorithm can't do I2C-level access, set master_xfer
	 * to NULL. If an adapter algorithm can do SMBus access, set
	 * smbus_xfer. If set to NULL, the SMBus protocol is simulated
	 * using common I2C messages.
	 *
	 * master_xfer should return the number of messages successfully
	 * processed, or a negative value on error
	 */
	int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs,
			   int num);    //I2C 适配器的传输函数,可以通过此函数来完成与 IIC 设备之 间的通信
	int (*master_xfer_atomic)(struct i2c_adapter *adap,
				   struct i2c_msg *msgs, int num);
	int (*smbus_xfer)(struct i2c_adapter *adap, u16 addr,
			  unsigned short flags, char read_write,
			  u8 command, int size, union i2c_smbus_data *data);    //SMBUS 总线协议的传输函数
	int (*smbus_xfer_atomic)(struct i2c_adapter *adap, u16 addr,
				 unsigned short flags, char read_write,
				 u8 command, int size, union i2c_smbus_data *data);
	/* To determine what the adapter supports */
	u32 (*functionality)(struct i2c_adapter *adap);    //查看适配的能力。这些功能都是以宏定义的方式表示,定义在include/linux/i2c.h中,以I2C_FUNC开头:
#if IS_ENABLED(CONFIG_I2C_SLAVE)
	int (*reg_slave)(struct i2c_client *client);
	int (*unreg_slave)(struct i2c_client *client);
#endif
};



/* To determine what functionality is present */
#define I2C_FUNC_I2C			0x00000001
#define I2C_FUNC_10BIT_ADDR		0x00000002
#define I2C_FUNC_PROTOCOL_MANGLING	0x00000004 /* I2C_M_IGNORE_NAK etc. */
#define I2C_FUNC_SMBUS_PEC		0x00000008
#define I2C_FUNC_NOSTART		0x00000010 /* I2C_M_NOSTART */
#define I2C_FUNC_SLAVE			0x00000020
#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL	0x00008000 /* SMBus 2.0 */
#define I2C_FUNC_SMBUS_QUICK		0x00010000
#define I2C_FUNC_SMBUS_READ_BYTE	0x00020000
#define I2C_FUNC_SMBUS_WRITE_BYTE	0x00040000
#define I2C_FUNC_SMBUS_READ_BYTE_DATA	0x00080000
#define I2C_FUNC_SMBUS_WRITE_BYTE_DATA	0x00100000
#define I2C_FUNC_SMBUS_READ_WORD_DATA	0x00200000
#define I2C_FUNC_SMBUS_WRITE_WORD_DATA	0x00400000
#define I2C_FUNC_SMBUS_PROC_CALL	0x00800000
#define I2C_FUNC_SMBUS_READ_BLOCK_DATA	0x01000000
#define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA 0x02000000
#define I2C_FUNC_SMBUS_READ_I2C_BLOCK	0x04000000 /* I2C-like block xfer  */
#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK	0x08000000 /* w/ 1-byte reg. addr. */
#define I2C_FUNC_SMBUS_HOST_NOTIFY	0x10000000
#define I2C_FUNC_SMBUS_BYTE		(I2C_FUNC_SMBUS_READ_BYTE | \
					 I2C_FUNC_SMBUS_WRITE_BYTE)
#define I2C_FUNC_SMBUS_BYTE_DATA	(I2C_FUNC_SMBUS_READ_BYTE_DATA | \
					 I2C_FUNC_SMBUS_WRITE_BYTE_DATA)
#define I2C_FUNC_SMBUS_WORD_DATA	(I2C_FUNC_SMBUS_READ_WORD_DATA | \
					 I2C_FUNC_SMBUS_WRITE_WORD_DATA)
#define I2C_FUNC_SMBUS_BLOCK_DATA	(I2C_FUNC_SMBUS_READ_BLOCK_DATA | \
					 I2C_FUNC_SMBUS_WRITE_BLOCK_DATA)
#define I2C_FUNC_SMBUS_I2C_BLOCK	(I2C_FUNC_SMBUS_READ_I2C_BLOCK | \
					 I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)

2.3  i2c_driver-I从设备驱动

struct i2c_driver {
	unsigned int class;
	/* Notifies the driver that a new bus has appeared. You should avoid
	 * using this, it will be removed in a near future.
	 */
	int (*attach_adapter)(struct i2c_adapter *) __deprecated;   

	/* Standard driver model interfaces */
	int (*probe)(struct i2c_client *, const struct i2c_device_id *);    //设备和驱动匹配时调用
	int (*remove)(struct i2c_client *);

	/* New driver model interface to aid the seamless removal of the
	 * current probe()'s, more commonly unused than used second parameter.
	 */
	int (*probe_new)(struct i2c_client *);

	/* driver model interfaces that don't relate to enumeration  */
	void (*shutdown)(struct i2c_client *);

	/* Alert callback, for example for the SMBus alert protocol.
	 * The format and meaning of the data value depends on the protocol.
	 * For the SMBus alert protocol, there is a single bit of data passed
	 * as the alert response's low bit ("event flag").
	 * For the SMBus Host Notify protocol, the data corresponds to the
	 * 16-bit payload data reported by the slave device acting as master.
	 */
	void (*alert)(struct i2c_client *, enum i2c_alert_protocol protocol,
		      unsigned int data); // 警告回调函数(例如SMBus警报协议)

	/* a ioctl like command that can be used to perform specific functions
	 * with the device.
	 */
	int (*command)(struct i2c_client *client, unsigned int cmd, void *arg); // 类似于ioctl 的命令控制函数    
	struct device_driver driver;    //在注册i2c_driver对象时,i2c_driver->driver的总线类型被指定为i2c_bus_type
	const struct i2c_device_id *id_table; // 这个i2c驱动支持的设备链表

	/* Device detection callback for automatic device creation */
	int (*detect)(struct i2c_client *, struct i2c_board_info *); // 检测设备的回调函数;
	const unsigned short *address_list; // 要探测的I2C地址(用于检测)
	struct list_head clients;     //探测到的设备列表
	bool disable_i2c_core_irq_mapping;
};

2.4 i2c_client-从设备

struct i2c_client{
 	unsigned short flags;   //描述从设备的一些特性,如I2C_CLIENT_TEN---使用的10位地址
 	unsigned short addr;   //设备的i2c地址,7位地址用低7位,10位地址用低10位。
 	char name[I2C_NAME_SIZE]; // 设备的名字;

 	struct i2c_adapter *adapter;   //所属的适配器i2c_adapter,挂载在哪条i2c物理总线上
	struct i2c_driver  *driver;    //匹配成功的i2c_driver
    int irq;
};

3. I2C子系统API

3.1 注册控制器

int i2c_add_adapter(struct i2c_adapter *adapter);//include/linux/i2c.h
int i2c_add_numbered_adapter(struct i2c_adapter *adap);

3.2 注销控制器

void i2c_del_adapter(struct i2c_adapter * adap);

3.3 添加i2c设备驱动

int i2c_register_driver(struct module *owner, struct i2c_driver *driver);//include/linux/i2c.h
/* use a define to avoid include chaining to get THIS_MODULE */
#define i2c_add_driver(driver) \
	i2c_register_driver(THIS_MODULE, driver);

 3.4 删除i2c设备驱动

void i2c_del_driver(struct i2c_driver *driver);

3.5 I2C数据传输

Int i2c_transfer(struct i2c_adapter *adap,struct i2c_msg *msgs, int num);

3.6 smbus输出传输

s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags,
		   char read_write, u8 command, int protocol,
		   union i2c_smbus_data *data)

s32 i2c_smbus_write_byte(const struct i2c_client *client, u8 value)

s32 i2c_smbus_read_byte_data(const struct i2c_client *client, u8 command)

s32 i2c_smbus_write_byte_data(const struct i2c_client *client, u8 command, u8 value)

s32 i2c_smbus_read_word_data(const struct i2c_client *client, u8 command)

s32 i2c_smbus_write_word_data(const struct i2c_client *client, u8 command, u16 value)

s32 i2c_smbus_read_block_data(const struct i2c_client *client, u8 command, u8 *values)

s32 i2c_smbus_write_block_data(const struct i2c_client *client, u8 command, u8 length, const u8 *values)

s32 i2c_smbus_write_block_data(const struct i2c_client *client, u8 command, u8 length, const u8 *values)

s32 i2c_smbus_write_i2c_block_data(const struct i2c_client *client, u8 command, u8 length, const u8 *values)

 4. I2C驱动

I2C驱动模型大概可以分为四层:
  1. 第一层是应用层,应用层可以使用默写具体设备的驱动程序,也可以通过i2c-dev.c使用原始的I2C通讯方式
  2. 第二层就是具体设备的应用程序,还有直接控制i2c控制器的控制程序
  3. I2C Core是对I2C控制器的API的封装
  4. I2C Controller Driver是对I2C控制器的驱动程序

4.1 核心core层注册

         i2c_bus_type的匹配过程与platform_bus_type大概一致

4.2 i2c-dev.c

i2c-dev.c的使用:

i2c-dev.c驱动分析:

 4.3 i2c控制器驱动

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值