針對一款新的芯片,芯片廠商如何基於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/
公眾號:大魚嵌入式