大概也是前年了,一直没有把那个i2c的子系统讲解完,这里偷个懒,把以前整理的i2c相关的知识再梳理一下,做个了结,然后再去学习timer子系统。
先看下i2c在内核中的代码分布:
obj-$(CONFIG_I2C_BOARDINFO) += i2c-boardinfo.o obj-$(CONFIG_I2C) += i2c-core.o obj-$(CONFIG_I2C_SMBUS) += i2c-smbus.o obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o obj-$(CONFIG_I2C_MUX) += i2c-mux.o obj-y += algos/ busses/ muxes/i2c的核心是i2c-core.c实现了i2c核心功能,i2c-dev.c实现了应用的交互接口。至于algos里面那主要实现的是总线适配,busses主要就是一些控制器相关的和gpio模拟的i2c,之后我们会详细介绍gpio模拟的i2c的代码。
既然看了代码分布,那么还是先要了解下i2c的框架了:
其中adaptor是i2c的总线驱动,dev和driver,client是i2c的设备驱动。一般如果要实现芯片的i2c驱动,那么就需要实现总线驱动,而设备驱动一般都是通用的。
好了,既然已经知道了i2c的基本框架,那么就来看看他的数据结构了:
struct i2c_msg; struct i2c_algorithm; struct i2c_adapter; struct i2c_client; struct i2c_driver; union i2c_smbus_data; struct i2c_board_info;I2C的driver
struct i2c_driver { unsigned int class;//I2C设备类型 /* Notifies the driver that a new bus has appeared or is about to be * removed. You should avoid using this, it will be removed in a * near future. */ int (*attach_adapter)(struct i2c_adapter *) __deprecated; int (*detach_adapter)(struct i2c_adapter *) __deprecated; /* Standard driver model interfaces */ int (*probe)(struct i2c_client *, const struct i2c_device_id *); int (*remove)(struct i2c_client *); /* driver model interfaces that don't relate to enumeration */ void (*shutdown)(struct i2c_client *); int (*suspend)(struct i2c_client *, pm_message_t mesg); int (*resume)(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"). */ void (*alert)(struct i2c_client *, unsigned int data); /* 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); struct device_driver driver; const struct i2c_device_id *id_table; /* 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; };
I2C的client
识别单个设备连接到一个总线上。
struct i2c_client { unsigned short flags; /* div., see below */ unsigned short addr; /* chip address - NOTE: 7bit */ /* addresses are stored in the */ /* _LOWER_ 7 bits */ char name[I2C_NAME_SIZE]; //设备名 struct i2c_adapter *adapter; /* the adapter we sit on *///I2C主控制器 struct i2c_driver *driver; /* and our access routines *///I2C设备驱动 struct device dev; /* the device structure */从机的驱动类型设备节点 int irq; /* irq issued by device */ //中断号 struct list_head detected; };
I2C的board_info
struct i2c_board_info { char type[I2C_NAME_SIZE]; //I2C设备名 unsigned short flags; //i2c_client.flags的初始化 unsigned short addr; //设备地址 void *platform_data; struct dev_archdata *archdata; struct device_node *of_node; int irq; //设备中断号 };
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); int (*smbus_xfer) (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 *); };
I2C的adapter
主控制器,用以鉴定i2c总线
struct i2c_adapter { struct module *owner; unsigned int class; /* classes to allow probing for */ const struct i2c_algorithm *algo; /* the algorithm to access the bus */ 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; char name[48]; struct completion dev_released; struct mutex userspace_clients_lock; struct list_head userspace_clients; };.
I2C的msg
在调用i2c_transfer的时候发送或者接收数据
struct i2c_msg { __u16 addr; /* slave address*/ __u16 flags; //读写等的标志 #define I2C_M_TEN 0x0010 /* this is a ten bit chip address */ #define I2C_M_RD 0x0001 /* read data, from slave to master */ #define I2C_M_NOSTART 0x4000 /* if I2C_FUNC_PROTOCOL_MANGLING */ #define I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */ #define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */ #define I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */ #define I2C_M_RECV_LEN 0x0400 /* length will be first received byte */ __u16 len; /* msg length *//发送和接收的buf的长度/ __u8 *buf; /* pointer to msg data*///发送或者接收的buf };
I2C的gpio模拟用的platform_data
struct i2c_gpio_platform_data { unsigned int sda_pin; unsigned int scl_pin; int udelay; int timeout; unsigned int sda_is_open_drain:1; unsigned int scl_is_open_drain:1; unsigned int scl_is_output_only:1; };主要数据结构就是这些,接下去的话在下一篇文章中简单介绍下gpio模拟的i2c的流程。