相比於前面介紹的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
- * - ...
- */
- };