本文將介紹SPI子系統。內核版本為2.6.30。如有錯誤歡迎指正。
預備知識要求:1.SPI總線
2. platfrom平台
3. sysfs子系統
4. 閱讀過LDD3第3,5,6,7,9,10,11章的內容。
NOTE:如果沒有看過LDD3的相關內容,直接看內核源碼將非常吃力!!!
PC主機:Ubuntu 和 RedHat 9.0
目標板:TQ2440開發板 cpu:s3c2440 linux內核:2.6.30
0.引言
本系列文章對Linux設備模型中的SPI子系統進行講解。SPI子系統的講解將分為4個部分。
第一部分,即本篇文章,將對SPI子系統整體進行描述,同時給出SPI的相關數據結構,最後描述SPI總線的注冊。
第二部分,該文將對SPI的主控制器(master)驅動進行描述。
基於S3C2440的嵌入式Linux驅動——SPI子系統解讀(二)http://www.linuxidc.com/Linux/2012-08/68404.htm
第三部分,該文將對SPI設備驅動,也稱protocol 驅動,進行講解。
基於S3C2440的嵌入式Linux驅動——SPI子系統解讀(三)http://www.linuxidc.com/Linux/2012-08/68405.htm
第四部分,通過SPI設備驅動留給用戶層的API,我們將從上到下描述數據是如何通過SPI的protocol 驅動,由bitbang中轉,最後由master驅動將數據傳輸出去。
基於S3C2440的嵌入式Linux驅動——SPI子系統解讀(四)http://www.linuxidc.com/Linux/2012-08/68406.htm
1.SPI子系統綜述
SPI子系統從上到下分為:spi設備驅動層,核心層和master驅動層。其中master驅動抽象出spi控制器的相關操作,而spi設備驅動層抽象出了用戶空間API。
platform_device結構中描述了SPI控制器的相關資源,同時在板級信息中將會添加spi設備的相關信息。master驅動將以platform_driver形式體現出來,也就是說
在主控制器(master)和主控制器驅動將掛載到platform總線上。platform_driver的probe函數中將注冊spi_master,同時將會獲取在板級信息中添加的spi設備,將該
信息轉換成spi_device,然後注冊spi_device到spi總線上。spi_driver結構用於描述spi設備驅動,也將掛載到spi總線上。連同spi_driver一起注冊的是字符設備,該
字符設備將提供5個API給用戶空間。通過API,用戶空間可以執行半雙工讀、半雙工寫和全雙工讀寫。
2. SPI的相關數據結構
這裡將介紹內核所用到的關鍵數據結構,還有些結構將在用到時加以說明。
2.1 spi_master
該結構用於描述SOC的SPI控制器,S3C2440共有兩個SPI控制器。
- /**
- * struct spi_master - interface to SPI master controller
- * @dev: device interface to this driver
- * @bus_num: board-specific (and often SOC-specific) identifier for a
- * given SPI controller.
- * @num_chipselect: chipselects are used to distinguish individual
- * SPI slaves, and are numbered from zero to num_chipselects.
- * each slave has a chipselect signal, but it's common that not
- * every chipselect is connected to a slave.
- * @dma_alignment: SPI controller constraint on DMA buffers alignment.
- * @setup: updates the device mode and clocking records used by a
- * device's SPI controller; protocol code may call this. This
- * must fail if an unrecognized or unsupported mode is requested.
- * It's always safe to call this unless transfers are pending on
- * the device whose settings are being modified.
- * @transfer: adds a message to the controller's transfer queue.
- * @cleanup: frees controller-specific state
- *
- * Each SPI master controller can communicate with one or more @spi_device
- * children. These make a small bus, sharing MOSI, MISO and SCK signals
- * but not chip select signals. Each device may be configured to use a
- * different clock rate, since those shared signals are ignored unless
- * the chip is selected.
- *
- * The driver for an SPI controller manages access to those devices through
- * a queue of spi_message transactions, copying data between CPU memory and
- * an SPI slave device. For each such message it queues, it calls the
- * message's completion function when the transaction completes.
- */
- struct spi_master {
- struct device 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; //該值不能為0,否則會注冊失敗
-
- /* some SPI controllers pose alignment requirements on DMAable
- * buffers; let protocol drivers know about these requirements.
- */
- u16 dma_alignment;
-
- /* 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);
- };