針對一款新的晶片,晶片廠商如何基於Linux編寫對應的 SPI controller 驅動?
我們先看看 Linux SPI 的整體框架:
可以看到,最底層是硬體層,對應晶片內部 SPI controller 和 掛在 SPI 匯流排上的外部裝置;中間層是核心層,對應 SPI 驅動;最頂層是使用者空間的應用程式。
位於核心層的 SPI 驅動,Linux kernel 抽象出了 spi core,遮蔽掉各廠商 spi controller 的差異,對上為 spi device driver 提供統一介面,對下為各晶片廠商實現 spi controller driver 接入spi core 提供統一介面。
為了使用者空間應用程式能直接操作 spi,kernel 除了抽象出 spi core,還實現了 spidev 程式。spidev 主要有兩部分構成:虛擬的 spi 裝置驅動 + 字元裝置,前者利用 spi core 提供的介面操作 spi,後者提供 read/write/ioctl 介面給使用者空間。
與 spidev 同一層的 specific spi device driver,指的是各個 spi 外設在核心空間實現的驅動程式,也是利用 spi core 提供的介面操作 spi。也就是說,如果要在使用者空間驅動 spi 外設,那可以使用 spidev 提供的介面;如果是在核心空間驅動 spi 外設,那就無需用到 spidev,直接在核心空間編寫驅動即可。
作為晶片廠商,如果晶片內建了 spi controller,那麼就需要實現 spi contorller driver。結合某晶片平臺示例,編寫 spi controller driver 的主要步驟如下:
1、定義 platform device 和 platform driver,並註冊到 platform。
2、定義 spi_controller(又稱 spi_master) 並註冊到 spi core。下圖程式碼經過精簡。如紅色箭頭所示,1是分配一個 spi_controller(spi_master) 例項,2是定義 controller 的一些屬性和函式操作,3是註冊到 spi core 中。
3、實現 spi_controller 的 ops (operations)。
最關鍵的 operations 有兩個,如上圖中紅色箭頭2所示,set_cs 函式和 transfer_one 函式。set_cs 是操作 spi cs 腳;transfer_one 是操作 spi controller 完成一次 spi transfer。什麼是 spi transfer?spi transfer 和 spi message 是 spi core 定義的概念,spi transfer 簡單地說就是一次spi讀或者寫的操作,而一個 spi message 可由一個或者多個 spi transfer 組成。spi transfer 不控制 spi cs腳,而 spi message 控制 spi cs 腳。
下圖是set_cs的實現,可以看到有操作晶片 spi controller 的 IO_CONTROL 暫存器的 CS 位。
下圖是transfer_one的實現。紅色箭頭處,就是呼叫實際 spi 傳輸的函式,而且區分了DMA和非DMA兩種情況。這兩個函式的具體實現,與該晶片平臺 spi controller 的設計緊密相關,相關操作邏輯和暫存器定義需要查閱晶片Spec。
作者:bigfish99
部落格:https://www.cnblogs.com/bigfish0506/
公眾號:大魚嵌入式