相比于前面介绍的i2c子系统(见 http://www.linuxidc.com/Linux/2012-01/52782.htm ),spi子系统相对简单,和i2c的结构也很相似,这里主要介绍一下平台无关部分的代码。先概括的说一下,spi总线或者说是spi控制器用结构体struct spi_master来表述,而一般不会明显的主动实现这个结构而是借助板级的一些信息结构,利用spi的模型填充,存在板级信息的一条链表board_list,上面挂接着板级spi设备的描述信息,其挂接的结构是struct boardinfo,这个结构内部嵌入了具体的板级spi设备所需信息结构struct spi_board_info,对于要操控的spi设备,用struct spidev_data来描述,内嵌了具体设备信息结构struct spi_device,并通过struct spi_device->device_entry成员挂接到全局spi设备链表device_list,结构struct spi_device就是根据前面board_list上所挂的信息填充的,而driver端比较简单,用struct spi_driver来描述,一会儿会看到该结构和标准的platform非常相似,总括的说下一般编写流程:对于soc,spi控制器一般注册成platform,当driver匹配后,会根据platform_device等信息构造出spi_master,一般发生在driver的probe函数,并且注册该master,在master的注册过程中会去遍历board_list找到bus号相同的spi设备信息,并实例化它,好了先就说这么多,下面先看一下具体的数据结构。 一、spi相关的数据结构 先看一下spi设备的板级信息填充的结构:
[cpp] - struct boardinfo {
- struct list_head list; //用于挂接到链表头board_list上
- unsigned n_board_info; //设备信息号,spi_board_info成员的编号
- struct spi_board_info board_info[0]; //内嵌的spi_board_info结构
- };
- //其中内嵌的描述spi设备的具体信息的结构struct spi_board_info为:
- struct spi_board_info {
- /* the device name and module name are coupled, like platform_bus;
- * "modalias" is normally the driver name.
- *
- * platform_data goes to spi_device.dev.platform_data,
- * controller_data goes to spi_device.controller_data,
- * irq is copied too
- */
- char modalias[SPI_NAME_SIZE]; //名字
- const void *platform_data; //如同注释写的指向spi_device.dev.platform_data
- void *controller_data; //指向spi_device.controller_data
- int irq; //中断号
- /* slower signaling on noisy or low voltage boards */
- u32 max_speed_hz; //时钟速率
- /* bus_num is board specific and matches the bus_num of some
- * spi_master that will probably be registered later.
- *
- * chip_select reflects how this chip is wired to that master;
- * it"s less than num_chipselect.
- */
- u16 bus_num; //所在的spi总线编号
- u16 chip_select;
- /* mode becomes spi_device.mode, and is essential for chips
- * where the default of SPI_CS_HIGH = 0 is wrong.
- */
- u8 mode; //模式
- /* ... may need additional spi_device chip config data here.
- * avoid stuff protocol drivers can set; but include stuff
- * needed to behave without being bound to a driver:
- * - quirks like clock rate mattering when not selected
- */
- };
利用boardinfo->list成员会将自身挂接到全局的board_list链表上。 再来看一下spi控制器的表述结构:
[cpp] - struct spi_master {
- struct device dev; //内嵌的标准dev结构
- /* other than negative (== assign one dynamically), bus_num is fully
- * board-specific. usually that simplifies to being SOC-specific.
- * example: one SOC has three SPI controllers, numbered 0..2,
- * and one board"s schematics might show it using SPI-2. software
- * would normally use bus_num=2 for that controller.
- */
- s16 bus_num; //标识的总线号
- /* chipselects will be integral to many controllers; some others
- * might use board-specific GPIOs.
- */
- u16 num_chipselect;
- /* some SPI controllers pose alignment requirements on DMAable
- * buffers; let protocol drivers know about these requirements.
- */
- u16 dma_alignment; //dma对其要求
- /* spi_device.mode flags understood by this controller driver */
- u16 mode_bits; //代表操作的spi_device.mode
- /* other constraints relevant to this driver */
- u16 flags; //另外的一些标志
- #define SPI_MASTER_HALF_DUPLEX BIT(0) /* can"t do full duplex */
- #define SPI_MASTER_NO_RX BIT(1) /* can"t do buffer read */
- #define SPI_MASTER_NO_TX BIT(2) /* can"t do buffer write */
- /* lock and mutex for SPI bus locking */
- spinlock_t bus_lock_spinlock;
- struct mutex bus_lock_mutex;
- /* flag indicating that the SPI bus is locked for exclusive use */
- bool bus_lock_flag;
- /* Setup mode and clock, etc (spi driver may call many times).
- *
- * IMPORTANT: this may be called when transfers to another
- * device are active. DO NOT UPDATE SHARED REGISTERS in ways
- * which could break those transfers.
- */
- int (*setup)(struct spi_device *spi); //设置模式
- /* bidirectional bulk transfers
- *
- * + The transfer() method may not sleep; its main role is
- * just to add the message to the queue.
- * + For now there"s no remove-from-queue operation, or
- * any other request management
- * + To a given spi_device, message queueing is pure fifo
- *
- * + The master"s main job is to process its message queue,
- * selecting a chip then transferring data
- * + If there are multiple spi_device children, the i/o queue
- * arbitration algorithm is unspecified (round robin, fifo,
- * priority, reservations, preemption, etc)
- *
- * + Chipselect stays active during the entire message
- * (unless modified by spi_transfer.cs_change != 0).
- * + The message transfers use clock and SPI mode parameters
- * previously established by setup() for this device
- */
- int (*transfer)(struct spi_device *spi, //传输函数
- struct spi_message *mesg);
- /* called on release() to free memory provided by spi_master */
- void (*cleanup)(struct spi_device *spi);
- };
而对于要操控的spi总线上的设备,其表述结构为:
[cpp] - struct spi_device {
- struct device dev; //内嵌标准device结构体
- struct spi_master *master; //spi主控制器
- u32 max_speed_hz; //时钟速率
- u8 chip_select; //设备编号
- u8 mode; //模式
- #define SPI_CPHA 0x01 /* clock phase */
- #define SPI_CPOL 0x02 /* clock polarity */
- #define SPI_MODE_0 (0|0) /* (original MicroWire) */
- #define SPI_MODE_1 (0|SPI_CPHA)
- #define SPI_MODE_2 (SPI_CPOL|0)
- #define SPI_MODE_3 (SPI_CPOL|SPI_CPHA)
- #define SPI_CS_HIGH 0x04 /* chipselect active high? */
- #define SPI_LSB_FIRST 0x08 /* per-word bits-on-wire */
- #define SPI_3WIRE 0x10 /* SI/SO signals shared */
- #define SPI_LOOP 0x20 /* loopback mode */
- #define SPI_NO_CS 0x40 /* 1 dev/bus, no chipselect */
- #define SPI_READY 0x80 /* slave pulls low to pause */
- u8 bits_per_word;
- int irq; //中断号
- void *controller_state; //控制状态
- void *controller_data; //私有数据
- char modalias[SPI_NAME_SIZE]; //名字
- /*
- * likely need more hooks for more protocol options affecting how
- * the controller talks to each chip, like:
- * - memory packing (12 bit samples into low bits, others zeroed)
- * - priority
- * - drop chipselect after each word
- * - chipselect delays
- * - ...
- */
- };
Linux设备模型之i2c子系统Linux设备模型之led子系统相关资讯 Linux基础知识
- Linux基础知识之文件权限详解 (08月09日)
- Linux基础知识之ls与文件名通配详 (08月01日)
- Linux基础知识之history的详细说明 (07月31日)
| - Linux基础知识之文件管理命令(cp、 (08月09日)
- Linux基础知识之man手册的使用 (07月31日)
- Linux基础知识之文件的时间戳及 (07月31日)
|
本文评论 查看全部评论 (0)