序列外圍介面 (SPI)

SPI 是“序列外圍介面”,廣泛用於嵌入式系統,因為它是一個簡單而高效的介面:基本上是一個多路複用移位暫存器。它的三根訊號線分別承載時鐘 (SCK,通常在 1-20 MHz 範圍內)、“主輸出,從輸入” (MOSI) 資料線和“主輸入,從輸出” (MISO) 資料線。SPI 是一種全雙工協議;對於透過 MOSI 線移出的每個位(每個時鐘一個),都有一個透過 MISO 線移入的位。這些位被組合成各種大小的字,用於與系統記憶體的互動。通常還有一個片選線,通常是低電平有效 (nCS);通常每個外圍裝置使用四個訊號,有時還會使用中斷。

此處列出的 SPI 匯流排設施提供了一個通用的介面,用於宣告 SPI 匯流排和裝置,根據標準的 Linux 驅動程式模型對其進行管理,並執行輸入/輸出操作。目前,僅支援“主”端介面,即 Linux 與 SPI 外圍裝置通訊,而不實現此類外圍裝置本身。(支援實現 SPI 從裝置的介面必然看起來不同。)

程式設計介面圍繞兩種驅動程式和兩種裝置構建。“控制器驅動程式”抽象了控制器硬體,控制器硬體可能像一組 GPIO 引腳一樣簡單,也可能像連線到 SPI 移位暫存器另一側的雙 DMA 引擎的一對 FIFO 一樣複雜(最大限度地提高吞吐量)。此類驅動程式在它們所在的任何匯流排(通常是平臺匯流排)和 SPI 之間建立橋樑,並將裝置的 SPI 端公開為 struct spi_controller。SPI 裝置是該主裝置的子裝置,表示為 struct spi_device,並由通常由特定於板的初始化程式碼提供的 struct spi_board_info 描述符生成。struct spi_driver 被稱為“協議驅動程式”,並使用普通的驅動程式模型呼叫繫結到 spi_device。

I/O 模型是一組排隊的訊息。協議驅動程式提交一個或多個 struct spi_message 物件,這些物件會被非同步處理和完成。(但是,也有同步包裝器。)訊息由一個或多個 struct spi_transfer 物件構建,每個物件都包裝一個全雙工 SPI 傳輸。需要各種協議調整選項,因為不同的晶片對如何使用透過 SPI 傳輸的位採用了非常不同的策略。

struct spi_statistics

spi 傳輸的統計資訊

定義:

struct spi_statistics {
    struct u64_stats_sync   syncp;
    u64_stats_t messages;
    u64_stats_t transfers;
    u64_stats_t errors;
    u64_stats_t timedout;
    u64_stats_t spi_sync;
    u64_stats_t spi_sync_immediate;
    u64_stats_t spi_async;
    u64_stats_t bytes;
    u64_stats_t bytes_rx;
    u64_stats_t bytes_tx;
#define SPI_STATISTICS_HISTO_SIZE 17;
    u64_stats_t transfer_bytes_histo[SPI_STATISTICS_HISTO_SIZE];
    u64_stats_t transfers_split_maxsize;
};

成員

syncp

seqcount 用於在 32 位系統上保護此結構中的成員進行每 CPU 更新

messages

已處理的 spi 訊息數

transfers

已處理的 spi_transfers 數

errors

spi_transfer 期間的錯誤數

timedout

spi_transfer 期間的超時數

spi_sync

spi_sync 的使用次數

spi_sync_immediate

spi_sync 在呼叫上下文中立即執行而無需排隊和排程的次數

spi_async

spi_async 的使用次數

bytes

傳輸到/從裝置的位元組數

bytes_rx

從裝置接收的位元組數

bytes_tx

傳送到裝置的位元組數

transfer_bytes_histo

傳輸位元組直方圖

transfers_split_maxsize

由於 maxsize 限制而被拆分的傳輸數

struct spi_delay

SPI 延遲資訊

定義:

struct spi_delay {
#define SPI_DELAY_UNIT_USECS    0;
#define SPI_DELAY_UNIT_NSECS    1;
#define SPI_DELAY_UNIT_SCK      2;
    u16 value;
    u8 unit;
};

成員

value

延遲值

unit

延遲單位

struct spi_device

SPI 目標裝置的控制器端代理

定義:

struct spi_device {
    struct device           dev;
    struct spi_controller   *controller;
    u32 max_speed_hz;
    u8 bits_per_word;
    bool rt;
#define SPI_NO_TX               BIT(31)         ;
#define SPI_NO_RX               BIT(30)         ;
#define SPI_TPM_HW_FLOW         BIT(29)         ;
#define SPI_MODE_KERNEL_MASK    (~(BIT(29) - 1));
    u32 mode;
    int irq;
    void *controller_state;
    void *controller_data;
    char modalias[SPI_NAME_SIZE];
    const char              *driver_override;
    struct spi_statistics __percpu  *pcpu_statistics;
    struct spi_delay        word_delay;
    struct spi_delay        cs_setup;
    struct spi_delay        cs_hold;
    struct spi_delay        cs_inactive;
    u8 chip_select[SPI_CS_CNT_MAX];
    u32 cs_index_mask : SPI_CS_CNT_MAX;
    struct gpio_desc        *cs_gpiod[SPI_CS_CNT_MAX];
};

成員

dev

裝置的驅動程式模型表示。

controller

裝置使用的 SPI 控制器。

max_speed_hz

要與此晶片一起使用的最大時鐘速率(在此板上);可以由裝置的驅動程式更改。spi_transfer.speed_hz 可以覆蓋每次傳輸的此值。

bits_per_word

資料傳輸涉及一個或多個字;八位或 12 位等字大小很常見。記憶體中的字大小是兩個位元組的冪(例如,20 位取樣使用 32 位)。這可以由裝置的驅動程式更改,也可以保留為預設值 (0),表示協議字是八位位元組。spi_transfer.bits_per_word 可以覆蓋每次傳輸的此值。

rt

使 pump 執行緒具有即時優先順序。

mode

spi 模式定義了資料的時鐘輸出和輸入方式。這可以由裝置的驅動程式更改。“片選有效低電平”的預設模式可以被覆蓋(透過指定 SPI_CS_HIGH),同樣,傳輸中每個字的“MSB 優先”預設模式也可以被覆蓋(透過指定 SPI_LSB_FIRST)。

irq

負數,或者傳遞給 request_irq() 以接收來自此裝置的中斷的數字。

controller_state

控制器的執行時狀態

controller_data

控制器的特定於板的定義,例如 FIFO 初始化引數;來自 board_info.controller_data

modalias

要與此裝置一起使用的驅動程式的名稱,或該名稱的別名。這會顯示在 sysfs “modalias” 屬性中,用於驅動程式冷插拔,以及用於熱插拔的 uevent

driver_override

如果將驅動程式的名稱寫入此屬性,則裝置將繫結到指定的驅動程式,並且僅繫結到指定的驅動程式。不要直接設定,因為核心會釋放它;請使用 driver_set_override() 設定或清除它。

pcpu_statistics

spi_device 的統計資訊

word_delay

要在傳輸的連續字之間插入的延遲

cs_setup

控制器在斷言 CS 後引入的延遲

cs_hold

控制器在取消斷言 CS 之前引入的延遲

cs_inactive

控制器在取消斷言 CS 後引入的延遲。如果從 spi_transfer 中使用 cs_change_delay,則會將兩個延遲加起來。

chip_select

物理片選陣列,spi->chipselect[i] 提供邏輯 CS i 的相應物理 CS。

cs_index_mask

片選陣列中活動片選的位掩碼

cs_gpiod

相應片選線的 GPIO 描述符陣列(可選,不使用 GPIO 線時為 NULL)

描述

spi_device 用於在 SPI 目標裝置(通常是離散晶片)和 CPU 記憶體之間交換資料。

dev 中,platform_data 用於儲存有關此裝置的資訊,這些資訊對裝置的協議驅動程式有意義,但對其控制器沒有意義。一個示例可能是具有略微不同功能的晶片變體的識別符號;另一個示例可能是有關此特定板如何連線晶片引腳的資訊。

struct spi_driver

主機端“協議”驅動程式

定義:

struct spi_driver {
    const struct spi_device_id *id_table;
    int (*probe)(struct spi_device *spi);
    void (*remove)(struct spi_device *spi);
    void (*shutdown)(struct spi_device *spi);
    struct device_driver    driver;
};

成員

id_table

此驅動程式支援的 SPI 裝置列表

probe

將此驅動程式繫結到 SPI 裝置。驅動程式可以驗證裝置是否實際存在,並且可能需要配置在系統設定期間完成的初始配置不需要的特性(例如 bits_per_word)。

remove

從此 SPI 裝置解除繫結此驅動程式

shutdown

在系統狀態轉換期間(例如,斷電/停止和 kexec)使用的標準關閉回撥

driver

SPI 裝置驅動程式應初始化此結構的 name 和 owner 欄位。

描述

這表示一種裝置驅動程式,它使用 SPI 訊息與 SPI 鏈路另一端的硬體進行互動。它被稱為“協議”驅動程式,因為它透過訊息工作,而不是直接與 SPI 硬體對話(這是底層 SPI 控制器驅動程式傳遞這些訊息的方式)。這些協議在驅動程式支援的裝置規範中定義。

通常,這些裝置協議表示驅動程式支援的最低級別介面,並且它也將支援更高級別的介面。此類更高級別的示例包括 MTD、網路、MMC、RTC、檔案系統字元裝置節點和硬體監控等框架。

void spi_unregister_driver(struct spi_driver *sdrv)

spi_register_driver 的反向效果

引數

struct spi_driver *sdrv

要取消註冊的驅動程式

上下文

可以睡眠

module_spi_driver

module_spi_driver (__spi_driver)

用於註冊 SPI 驅動程式的輔助宏

引數

__spi_driver

spi_driver 結構

描述

用於在模組 init/exit 中不執行任何特殊操作的 SPI 驅動程式的輔助宏。這消除了大量樣板程式碼。每個模組只能使用此宏一次,並且呼叫它會替換 module_init()module_exit()

struct spi_controller

與 SPI 主機或目標控制器的介面

定義:

struct spi_controller {
    struct device   dev;
    struct list_head list;
    s16 bus_num;
    u16 num_chipselect;
    u16 dma_alignment;
    u32 mode_bits;
    u32 buswidth_override_bits;
    u32 bits_per_word_mask;
#define SPI_BPW_MASK(bits) BIT((bits) - 1);
#define SPI_BPW_RANGE_MASK(min, max) GENMASK((max) - 1, (min) - 1);
    u32 min_speed_hz;
    u32 max_speed_hz;
    u16 flags;
#define SPI_CONTROLLER_HALF_DUPLEX      BIT(0)  ;
#define SPI_CONTROLLER_NO_RX            BIT(1)  ;
#define SPI_CONTROLLER_NO_TX            BIT(2)  ;
#define SPI_CONTROLLER_MUST_RX          BIT(3)  ;
#define SPI_CONTROLLER_MUST_TX          BIT(4)  ;
#define SPI_CONTROLLER_GPIO_SS          BIT(5)  ;
#define SPI_CONTROLLER_SUSPENDED        BIT(6)  ;
#define SPI_CONTROLLER_MULTI_CS         BIT(7);
    bool devm_allocated;
    union {
        bool slave;
        bool target;
    };
    size_t (*max_transfer_size)(struct spi_device *spi);
    size_t (*max_message_size)(struct spi_device *spi);
    struct mutex            io_mutex;
    struct mutex            add_lock;
    spinlock_t bus_lock_spinlock;
    struct mutex            bus_lock_mutex;
    bool bus_lock_flag;
    int (*setup)(struct spi_device *spi);
    int (*set_cs_timing)(struct spi_device *spi);
    int (*transfer)(struct spi_device *spi, struct spi_message *mesg);
    void (*cleanup)(struct spi_device *spi);
    bool (*can_dma)(struct spi_controller *ctlr,struct spi_device *spi, struct spi_transfer *xfer);
    struct device *dma_map_dev;
    struct device *cur_rx_dma_dev;
    struct device *cur_tx_dma_dev;
    bool queued;
    struct kthread_worker           *kworker;
    struct kthread_work             pump_messages;
    spinlock_t queue_lock;
    struct list_head                queue;
    struct spi_message              *cur_msg;
    struct completion               cur_msg_completion;
    bool cur_msg_incomplete;
    bool cur_msg_need_completion;
    bool busy;
    bool running;
    bool rt;
    bool auto_runtime_pm;
    bool fallback;
    bool last_cs_mode_high;
    s8 last_cs[SPI_CS_CNT_MAX];
    u32 last_cs_index_mask : SPI_CS_CNT_MAX;
    struct completion               xfer_completion;
    size_t max_dma_len;
    int (*optimize_message)(struct spi_message *msg);
    int (*unoptimize_message)(struct spi_message *msg);
    int (*prepare_transfer_hardware)(struct spi_controller *ctlr);
    int (*transfer_one_message)(struct spi_controller *ctlr, struct spi_message *mesg);
    int (*unprepare_transfer_hardware)(struct spi_controller *ctlr);
    int (*prepare_message)(struct spi_controller *ctlr, struct spi_message *message);
    int (*unprepare_message)(struct spi_controller *ctlr, struct spi_message *message);
    int (*target_abort)(struct spi_controller *ctlr);
    void (*set_cs)(struct spi_device *spi, bool enable);
    int (*transfer_one)(struct spi_controller *ctlr, struct spi_device *spi, struct spi_transfer *transfer);
    void (*handle_err)(struct spi_controller *ctlr, struct spi_message *message);
    const struct spi_controller_mem_ops *mem_ops;
    const struct spi_controller_mem_caps *mem_caps;
    bool dtr_caps;
    struct spi_offload *(*get_offload)(struct spi_device *spi, const struct spi_offload_config *config);
    void (*put_offload)(struct spi_offload *offload);
    struct gpio_desc        **cs_gpiods;
    bool use_gpio_descriptors;
    s8 unused_native_cs;
    s8 max_native_cs;
    struct spi_statistics __percpu  *pcpu_statistics;
    struct dma_chan         *dma_tx;
    struct dma_chan         *dma_rx;
    void *dummy_rx;
    void *dummy_tx;
    int (*fw_translate_cs)(struct spi_controller *ctlr, unsigned cs);
    bool ptp_sts_supported;
    unsigned long           irq_flags;
    bool queue_empty;
    bool must_async;
    bool defer_optimize_message;
};

成員

dev

裝置與此驅動程式的介面

list

與全域性 spi_controller 列表的連結

bus_num

給定 SPI 控制器的特定於板(且通常特定於 SOC)的識別符號。

num_chipselect

片選用於區分各個 SPI 目標,編號從零到 num_chipselects。每個目標都有一個片選訊號,但並非每個片選都連線到目標是很常見的。

dma_alignment

SPI 控制器對 DMA 緩衝區對齊的約束。

mode_bits

此控制器驅動程式理解的標誌

buswidth_override_bits

要為此控制器驅動程式覆蓋的標誌

bits_per_word_mask

一個掩碼,指示驅動程式支援哪些 bits_per_word 值。位 n 表示支援 bits_per_word n+1。如果設定了此掩碼,則 SPI 核心將拒絕任何具有不支援的 bits_per_word 的傳輸。如果未設定此掩碼,則會忽略此值,並且由各個驅動程式執行任何驗證。

min_speed_hz

支援的最低傳輸速度

max_speed_hz

max_speed_hz

支援的最高傳輸速度

flags

與此驅動程式相關的其他約束

devm_allocated

此結構的分配是否由 devres 管理

{unnamed_union}

anonymous

slave

指示這是一個 SPI 從控制器

target

指示這是一個 SPI 目標控制器

max_transfer_size

返回 spi_device 的最大傳輸大小的函式;可以為 NULL,因此將使用預設的 SIZE_MAX

max_message_size

返回 spi_device 的最大訊息大小的函式;可以為 NULL,因此將使用預設的 SIZE_MAX

io_mutex

用於物理匯流排訪問的互斥鎖

add_lock

用於避免將裝置新增到同一片選的互斥鎖

bus_lock_spinlock

用於 SPI 匯流排鎖定的自旋鎖

bus_lock_mutex

用於排除多個呼叫者的互斥鎖

bus_lock_flag

指示 SPI 匯流排已鎖定以供獨佔使用

setup

更新裝置 SPI 控制器使用的裝置模式和時鐘記錄;協議程式碼可以呼叫此函式。如果請求了無法識別或不支援的模式,則此函式必須失敗。除非在正在修改設定的裝置上掛起傳輸,否則始終可以安全地呼叫此函式。

set_cs_timing

用於 SPI 裝置請求 SPI 控制器配置特定 CS 建立時間、保持時間和非活動延遲(以時鐘計數表示)的可選掛鉤

transfer

將訊息新增到控制器的傳輸佇列。

cleanup

釋放特定於控制器的狀態

can_dma

確定此控制器是否支援 DMA

dma_map_dev

可用於 DMA 對映的裝置

cur_rx_dma_dev

當前用於 RX DMA 對映的裝置

cur_tx_dma_dev

當前用於 TX DMA 對映的裝置

queued

此控制器是否提供內部訊息佇列

kworker

指向訊息泵的執行緒結構的指標

pump_messages

用於排程訊息泵工作的工件結構

queue_lock

用於同步訪問訊息佇列的自旋鎖

queue

訊息佇列

cur_msg

當前正在傳輸的訊息

cur_msg_completion

當前正在傳輸的訊息的完成

cur_msg_incomplete

在內部使用的標誌,用於伺機跳過 cur_msg_completion。此標誌用於檢查驅動程式是否已呼叫 spi_finalize_current_message()

cur_msg_need_completion

在內部使用的標誌,用於伺機跳過 cur_msg_completion。此標誌用於向正在執行 spi_finalize_current_message() 的上下文發出訊號,表明它需要 complete()

busy

訊息泵正忙

running

rt

訊息泵正在執行

此佇列是否設定為作為即時任務執行

auto_runtime_pm

核心應確保在準備硬體時保持執行時 PM 引用,將父裝置用於 spidev

fallback

如果 DMA 傳輸返回失敗,且出現 SPI_TRANS_FAIL_NO_START,則回退到 PIO。

last_cs_mode_high

上次呼叫 set_cs 時 (mode & SPI_CS_HIGH) 是否為 true。

last_cs

set_cs 記錄的最後一個 chip_select,未選擇片選時為 -1

last_cs_index_mask

使用的最後一個片選的位掩碼

xfer_completion

由核心 transfer_one_message() 使用

裝置 DMA 傳輸的最大長度。

optimize_message

最佳化訊息以供重用

unoptimize_message

釋放 optimize_message 分配的資源

prepare_transfer_hardware

佇列中即將收到一條訊息,因此子系統請求驅動程式透過發出此呼叫來準備傳輸硬體

transfer_one_message

子系統呼叫驅動程式來傳輸單個訊息,同時對同時到達的傳輸進行排隊。當驅動程式完成此訊息後,必須呼叫 spi_finalize_current_message(),以便子系統可以發出下一條訊息

unprepare_transfer_hardware

佇列中當前沒有更多訊息,因此子系統通知驅動程式可以透過發出此呼叫來放鬆硬體

prepare_message

設定控制器以傳輸單個訊息,例如進行 DMA 對映。從執行緒上下文中呼叫。

unprepare_message

撤消 prepare_message() 所做的任何工作。

target_abort

中止 SPI 目標控制器上正在進行的傳輸請求

set_cs

設定片選線的邏輯電平。可以從中斷上下文中呼叫。

transfer_one

傳輸單個 spi_transfer。

  • 如果傳輸完成,則返回 0,

  • 如果傳輸仍在進行中,則返回 1。當驅動程式完成此傳輸後,必須呼叫 spi_finalize_current_transfer(),以便子系統可以發出下一個傳輸。如果傳輸失敗,驅動程式必須首先將標誌 SPI_TRANS_FAIL_IO 設定為 spi_transfer->error,然後再呼叫 spi_finalize_current_transfer()

handle_err

子系統呼叫驅動程式來處理在 transfer_one_message() 的通用實現中發生的錯誤。

mem_ops

用於與 SPI 儲存器互動的最佳化/專用操作。此欄位是可選的,只有當控制器對類似儲存器的操作具有本機支援時才應實現。

mem_caps

控制器處理儲存器操作的能力。

dtr_caps

如果控制器具有 dtr(單/雙傳輸速率)能力,則為真。基於 QSPI 的控制器應根據控制器的能力填充此欄位。

get_offload

具有解除安裝支援的控制器的回撥,以獲取匹配的解除安裝例項。如果未找到匹配項,則實現應返回 -ENODEV。

put_offload

釋放由 get_offload 獲取的解除安裝例項。

cs_gpiods

要用作片選線的 GPIO 描述符陣列;每個 CS 編號一個。任何單個值對於非 GPIO 的 CS 線(由 SPI 控制器本身驅動)都可以為 NULL。

use_gpio_descriptors

啟用 SPI 核心中的程式碼以解析和獲取 GPIO 描述符。這將填充 cs_gpiods,如果為片選找到 GPIO 線,則 SPI 裝置將具有分配的 cs_gpiod。

unused_native_cs

當使用 cs_gpiods 時,spi_register_controller() 將使用第一個未使用的本機 CS 填充此欄位,以供在使用 GPIO CS 時需要驅動本機 CS 的 SPI 控制器驅動程式使用。

max_native_cs

當使用 cs_gpiods 且填充此欄位時,spi_register_controller() 將根據此值驗證所有本機 CS(包括未使用的本機 CS)。

pcpu_statistics

spi_controller 的統計資訊

dma_tx

DMA 傳輸通道

dma_rx

DMA 接收通道

dummy_rx

全雙工裝置的虛擬接收緩衝區

dummy_tx

全雙工裝置的虛擬傳輸緩衝區

fw_translate_cs

如果啟動韌體使用與 Linux 期望的不同的編號方案,則可以使用此可選鉤子在兩者之間進行轉換。

ptp_sts_supported

如果驅動程式將其設定為 true,則它必須在 spi_transfer->ptp_sts 中提供一個時間快照,該快照儘可能接近 spi_transfer->ptp_sts_word_prespi_transfer->ptp_sts_word_post 被傳輸的時刻。如果驅動程式未設定此值,則 SPI 核心將盡可能接近驅動程式交接的時間點進行快照。

irq_flags

PTP 系統時間戳期間的中斷啟用狀態

queue_empty

為機會性跳過 spi_sync 傳輸的佇列發出綠燈訊號。

must_async

停用核心中的所有快速路徑

defer_optimize_message

如果控制器無法預先最佳化訊息,並且需要將最佳化步驟推遲到實際傳輸訊息時,則設定為 true

注意

transfer_one 和 transfer_one_message 是相互

互斥的;當兩者都設定時,通用子系統不會呼叫您的 transfer_one 回撥。

描述

每個 SPI 控制器都可以與一個或多個 spi_device 子裝置通訊。這些子裝置構成一個小型匯流排,共享 MOSI、MISO 和 SCK 訊號,但不共享片選訊號。每個裝置都可以配置為使用不同的時鐘速率,因為除非選擇晶片,否則這些共享訊號將被忽略。

SPI 控制器的驅動程式透過 spi_message 事務佇列管理對這些裝置的訪問,在 CPU 記憶體和 SPI 目標裝置之間複製資料。對於它排隊的每個此類訊息,它會在事務完成時呼叫訊息的完成函式。

struct spi_res

SPI 資源管理結構

定義:

struct spi_res {
    struct list_head        entry;
    spi_res_release_t release;
    unsigned long long      data[];
};

成員

entry

列表條目

release

在釋放此資源之前呼叫的釋放程式碼

data

為特定用例分配的額外資料

描述

這是基於 devres 中的想法,但專注於 spi_message 處理期間的生命週期管理。

struct spi_transfer

讀取/寫入緩衝區對

定義:

struct spi_transfer {
    const void      *tx_buf;
    void *rx_buf;
    unsigned len;
#define SPI_TRANS_FAIL_NO_START BIT(0);
#define SPI_TRANS_FAIL_IO       BIT(1);
    u16 error;
    bool tx_sg_mapped;
    bool rx_sg_mapped;
    struct sg_table tx_sg;
    struct sg_table rx_sg;
    dma_addr_t tx_dma;
    dma_addr_t rx_dma;
    unsigned dummy_data:1;
    unsigned cs_off:1;
    unsigned cs_change:1;
    unsigned tx_nbits:4;
    unsigned rx_nbits:4;
    unsigned timestamped:1;
    bool dtr_mode;
#define SPI_NBITS_SINGLE        0x01 ;
#define SPI_NBITS_DUAL          0x02 ;
#define SPI_NBITS_QUAD          0x04 ;
#define SPI_NBITS_OCTAL 0x08 ;
    u8 bits_per_word;
    struct spi_delay        delay;
    struct spi_delay        cs_change_delay;
    struct spi_delay        word_delay;
    u32 speed_hz;
    u32 effective_speed_hz;
    unsigned int    offload_flags;
    unsigned int    ptp_sts_word_pre;
    unsigned int    ptp_sts_word_post;
    struct ptp_system_timestamp *ptp_sts;
    struct list_head transfer_list;
};

成員

tx_buf

要寫入的資料(DMA 安全的記憶體),或 NULL

rx_buf

要讀取的資料(DMA 安全的記憶體),或 NULL

len

rx 和 tx 緩衝區的大小(以位元組為單位)

error

SPI 控制器驅動程式記錄的錯誤狀態。

tx_sg_mapped

如果為真,則 tx_sg 被對映用於 DMA

rx_sg_mapped

如果為真,則 rx_sg 被對映用於 DMA

tx_sg

用於傳輸的 Scatterlist,目前不供客戶端使用

rx_sg

用於接收的 Scatterlist,目前不供客戶端使用

tx_dma

tx_buf 的 DMA 地址,目前不供客戶端使用

rx_dma

rx_buf 的 DMA 地址,目前不供客戶端使用

dummy_data

指示傳輸是虛擬位元組傳輸。

cs_off

在片選關閉的情況下執行傳輸。

cs_change

影響此傳輸完成後是否片選

tx_nbits

用於寫入的位數。如果為 0,則使用預設值 (SPI_NBITS_SINGLE)。

rx_nbits

用於讀取的位數。如果為 0,則使用預設值 (SPI_NBITS_SINGLE)。

timestamped

如果傳輸已新增時間戳,則為真

dtr_mode

如果支援雙倍傳輸速率,則為真。

bits_per_word

為此傳輸選擇除裝置預設值之外的 bits_per_word。如果為 0,則使用預設值(來自 spi_device)。

delay

在此傳輸之後引入的延遲,然後(可選)更改片選狀態,然後開始下一個傳輸或完成此 spi_message

cs_change_delay

當設定了 cs_change 並且 spi_transfer 不是 spi_message 中的最後一個時,片選取消斷言和斷言之間的延遲

word_delay

在每次字大小(由 bits_per_word 設定)傳輸後引入的字間延遲。

speed_hz

為此傳輸選擇除裝置預設值之外的速度。如果為 0,則使用預設值(來自 spi_device)。

effective_speed_hz

用於傳輸此傳輸的有效 SCK 速度。如果 SPI 匯流排驅動程式不支援,則設定為 0。

offload_flags

僅適用於專用 SPI 解除安裝傳輸的標誌。請參閱 spi-offload.h 中的 SPI_OFFLOAD_XFER_*

ptp_sts_word_pre

SPI 裝置請求其時間快照從此傳輸開始的 tx_buf 中的字(受 bits_per_word 語義的影響)偏移量。完成 SPI 傳輸後,此值可能與請求的值相比發生了變化,具體取決於可用的快照解析度(DMA 傳輸,ptp_sts_supported 為 false 等)。

ptp_sts_word_post

請參閱 ptp_sts_word_post。兩者可以相等(意味著應該對單個位元組進行快照)。如果核心負責時間戳(如果此控制器的 ptp_sts_supported 為 false),它會將 ptp_sts_word_pre 設定為 0,並將 ptp_sts_word_post 設定為傳輸的長度。這樣做是有目的的(而不是設定為 spi_transfer->len - 1)來表示從驅動程式內部獲取的傳輸級快照可能仍然具有更高的質量。

ptp_sts

指向 SPI 目標裝置儲存的記憶體位置的指標,PTP 系統時間戳結構可能位於該位置。如果驅動程式使用 PIO 或其硬體具有某種輔助功能來檢索確切的傳輸時間,它們可以(並且應該)斷言 ptp_sts_supported 並使用 ptp_read_system_*ts 輔助函式填充此結構。時間戳必須表示 SPI 目標裝置處理字的時間,即應在傳輸“pre”字之前獲取“pre”時間戳,並在從控制器收到“post”字的傳輸確認後獲取“post”時間戳。

transfer_list

傳輸透過 spi_message.transfers 進行排序

描述

SPI 傳輸總是寫入與讀取相同數量的位元組。協議驅動程式應始終提供 rx_buf 和/或 tx_buf。在某些情況下,他們可能還希望為傳輸的資料提供 DMA 地址;當底層驅動程式使用 DMA 時,這可以減少開銷。

如果傳輸緩衝區為 NULL,則在填充 rx_buf 時將移出零。如果接收緩衝區為 NULL,則移入的資料將被丟棄。只有 “len” 位元組移出(或移入)。嘗試移出部分字是一個錯誤。(例如,透過移出具有 16 位或 20 位字大小的三個位元組;前者每個字使用兩個位元組,後者每個字使用四個位元組。)

記憶體中的資料值始終採用本機 CPU 位元組順序,從線路位元組順序(大端序,除非使用 SPI_LSB_FIRST)轉換而來。因此,例如,當 bits_per_word 為 16 時,緩衝區為 2N 位元組長(len = 2N),並儲存 N 個 16 位字,按 CPU 位元組順序排列。

當 SPI 傳輸的字大小不是 8 位的 2 的冪倍數時,記憶體中的字包含額外的位。協議驅動程式始終將記憶體中的字視為右對齊,因此未定義 (rx) 或未使用 (tx) 的位始終是最高有效位。

所有 SPI 傳輸都以相關的片選啟用開始。通常,它會保持選定狀態,直到訊息中的最後一個傳輸之後。驅動程式可以使用 cs_change 影響片選訊號。

(i) 如果傳輸不是訊息中的最後一個傳輸,則使用此標誌使片選在訊息中間短暫變為非活動狀態。可能需要以這種方式切換片選來終止晶片命令,從而讓單個 spi_message 將所有晶片事務組合在一起執行。

(ii) 當傳輸是訊息中的最後一個傳輸時,晶片可能會保持選定狀態,直到下一個傳輸。在沒有阻止訊息傳送到其他裝置的多裝置 SPI 總線上,這只是一個性能提示;啟動到另一個裝置的訊息會取消選擇此裝置。但在其他情況下,這可以用於確保正確性。某些裝置需要透過一系列 spi_message 提交來構建協議事務,其中一個訊息的內容由先前訊息的結果決定,並且整個事務在片選變為非活動狀態時結束。

當 SPI 可以以 1x、2x 或 4x 的速度傳輸時。它可以從裝置透過 tx_nbitsrx_nbits 獲取此傳輸資訊。在雙向傳輸中,這兩個都應設定。使用者可以使用 SPI_NBITS_SINGLE(1x) SPI_NBITS_DUAL(2x) 和 SPI_NBITS_QUAD(4x) 設定傳輸模式來支援這三個傳輸。

如果需要,使用者還可以將 dtr_mode 設定為 true 以使用雙傳輸模式。如果未設定,則預設情況下視為單傳輸模式。

將 spi_message(及其 spi_transfers)提交到較低層的程式碼負責管理其記憶體。將您未顯式設定的每個欄位零初始化,以防止將來的 API 更新。在您提交訊息及其傳輸後,請忽略它們,直到其完成回撥。

struct spi_message

一個多段 SPI 事務

定義:

struct spi_message {
    struct list_head        transfers;
    struct spi_device       *spi;
    bool pre_optimized;
    bool optimized;
    bool prepared;
    int status;
    void (*complete)(void *context);
    void *context;
    unsigned frame_length;
    unsigned actual_length;
    struct list_head        queue;
    void *state;
    void *opt_state;
    struct spi_offload      *offload;
    struct list_head        resources;
};

成員

transfers

此事務中傳輸段的列表

spi

事務排隊的 SPI 裝置

pre_optimized

外圍驅動程式預先優化了訊息

optimized

訊息處於最佳化狀態

prepared

為此訊息呼叫了 spi_prepare_message

status

成功則為零,否則為負 errno

complete

呼叫以報告事務完成情況

context

呼叫 complete() 時的引數

frame_length

訊息中的總位元組數

actual_length

所有成功段中傳輸的總位元組數

用於同步訪問訊息佇列的自旋鎖

供當前擁有訊息的驅動程式使用

state

供當前擁有訊息的驅動程式使用

opt_state

供當前擁有訊息的驅動程式使用

offload

此訊息使用的(可選)解除安裝例項

resources

用於在處理 SPI 訊息時的資源管理

描述

spi_message 用於執行原子資料傳輸序列,每個資料傳輸由 struct spi_transfer 表示。該序列是“原子”的,因為在序列完成之前,沒有其他 spi_message 可以使用該 SPI 匯流排。在某些系統上,許多此類序列可以作為單個程式設計的 DMA 傳輸執行。在所有系統上,這些訊息都排隊,並且可能會在與其他裝置的事務之後完成。傳送到給定 spi_device 的訊息始終按 FIFO 順序執行。

將 spi_message(及其 spi_transfers)提交到較低層的程式碼負責管理其記憶體。將您未顯式設定的每個欄位零初始化,以防止將來的 API 更新。在您提交訊息及其傳輸後,請忽略它們,直到其完成回撥。

void spi_message_init_with_transfers(struct spi_message *m, struct spi_transfer *xfers, unsigned int num_xfers)

初始化 spi_message 並附加傳輸

引數

struct spi_message *m

要初始化的 spi_message

struct spi_transfer *xfers

SPI 傳輸陣列

unsigned int num_xfers

xfer 陣列中的專案數

描述

此函式初始化給定的 spi_message 並將給定陣列中的每個 spi_transfer 新增到訊息中。

bool spi_is_bpw_supported(struct spi_device *spi, u32 bpw)

檢查是否支援每字位數

引數

struct spi_device *spi

SPI 裝置

u32 bpw

每字位數

描述

此函式檢查 SPI 控制器是否支援 bpw

Return

如果支援 bpw,則為 true;否則為 false。

u32 spi_bpw_to_bytes(u32 bpw)

將每字位數轉換為位元組

引數

u32 bpw

每字位數

描述

此函式將給定的 bpw 轉換為位元組。結果始終是 2 的冪,例如,

輸入(以位為單位)

輸出(以位元組為單位)

5

1

9

2

21

4

37

8

它將為 0 輸入返回 0。

Return

給定 bpw 的位元組。

unsigned int spi_controller_xfer_timeout(struct spi_controller *ctlr, struct spi_transfer *xfer)

計算合適的超時值

引數

struct spi_controller *ctlr

SPI 裝置

struct spi_transfer *xfer

傳輸描述符

描述

計算給定傳輸的相關超時值。我們推匯出單條資料線上所需的時間,並使用該時間的兩倍,最小值為 500 毫秒,以避免在負載系統上出現誤報。

Return

以毫秒為單位的傳輸超時值。

struct spi_replaced_transfers

描述已發生的 spi_transfer 替換的結構,以便可以恢復它們

定義:

struct spi_replaced_transfers {
    spi_replaced_release_t release;
    void *extradata;
    struct list_head replaced_transfers;
    struct list_head *replaced_after;
    size_t inserted;
    struct spi_transfer inserted_transfers[];
};

成員

release

一些額外的釋放程式碼,以便在釋放此結構之前執行

extradata

如果請求或 NULL,則指向一些額外資料的指標

replaced_transfers

已被替換並且需要恢復的傳輸

replaced_after

replaced_transfers 將被重新插入後的傳輸

inserted

插入的傳輸數

inserted_transfers

陣列大小為 inserted 的 spi_transfers 陣列,已替換 replaced_transfers

注意

如果請求一些額外的分配,則 extradata 將指向 inserted_transfers**[**inserted],因此對齊方式將與 spi_transfers 相同。

int spi_sync_transfer(struct spi_device *spi, struct spi_transfer *xfers, unsigned int num_xfers)

同步 SPI 資料傳輸

引數

struct spi_device *spi

將與之交換資料的裝置

struct spi_transfer *xfers

spi_transfers 陣列

unsigned int num_xfers

xfer 陣列中的專案數

上下文

可以睡眠

描述

執行給定 spi_transfer 陣列的同步 SPI 資料傳輸。

有關更具體的語義,請參見 spi_sync()

Return

成功則為零,否則為負錯誤程式碼。

int spi_write(struct spi_device *spi, const void *buf, size_t len)

SPI同步寫入

引數

struct spi_device *spi

將資料寫入的裝置

const void *buf

資料緩衝區

size_t len

資料緩衝區大小

上下文

可以睡眠

描述

此函式寫入緩衝區 buf。只能從可以睡眠的上下文呼叫。

Return

成功則為零,否則為負錯誤程式碼。

int spi_read(struct spi_device *spi, void *buf, size_t len)

SPI同步讀取

引數

struct spi_device *spi

從中讀取資料的裝置

void *buf

資料緩衝區

size_t len

資料緩衝區大小

上下文

可以睡眠

描述

此函式讀取緩衝區 buf。只能從可以睡眠的上下文呼叫。

Return

成功則為零,否則為負錯誤程式碼。

ssize_t spi_w8r8(struct spi_device *spi, u8 cmd)

SPI同步8位寫入,然後進行8位讀取

引數

struct spi_device *spi

將與之交換資料的裝置

u8 cmd

在讀取資料之前要寫入的命令

上下文

可以睡眠

描述

只能從可以睡眠的上下文呼叫。

Return

裝置返回的(無符號)8位數字,或者一個負的錯誤程式碼。

ssize_t spi_w8r16(struct spi_device *spi, u8 cmd)

SPI同步8位寫入,然後進行16位讀取

引數

struct spi_device *spi

將與之交換資料的裝置

u8 cmd

在讀取資料之前要寫入的命令

上下文

可以睡眠

描述

數字以網路位元組序返回,至少有時是大端位元組序。

只能從可以睡眠的上下文呼叫。

Return

裝置返回的(無符號)16位數字,或者一個負的錯誤程式碼。

ssize_t spi_w8r16be(struct spi_device *spi, u8 cmd)

SPI同步8位寫入,然後進行16位大端位元組序讀取

引數

struct spi_device *spi

將與之交換資料的裝置

u8 cmd

在讀取資料之前要寫入的命令

上下文

可以睡眠

描述

此函式類似於 spi_w8r16,例外的是它會將讀取的16位資料字從大端位元組序轉換為本地位元組序。

只能從可以睡眠的上下文呼叫。

Return

裝置以CPU位元組序返回的(無符號)16位數字,或者一個負的錯誤程式碼。

struct spi_board_info

SPI裝置的板特定模板

定義:

struct spi_board_info {
    char modalias[SPI_NAME_SIZE];
    const void      *platform_data;
    const struct software_node *swnode;
    void *controller_data;
    int irq;
    u32 max_speed_hz;
    u16 bus_num;
    u16 chip_select;
    u32 mode;
};

成員

modalias

初始化 spi_device.modalias;標識驅動程式。

platform_data

初始化 spi_device.platform_data;儲存在那裡的特定資料是驅動程式特定的。

swnode

裝置的軟體節點。

controller_data

初始化 spi_device.controller_data;一些控制器需要硬體設定方面的提示,例如用於DMA。

irq

初始化 spi_device.irq;取決於電路板的接線方式。

max_speed_hz

初始化 spi_device.max_speed_hz;基於晶片資料手冊的限制和電路板特定的訊號質量問題。

bus_num

標識哪個 spi_controller 是 spi_device 的父級;spi_new_device() 未使用,否則取決於電路板的接線方式。

chip_select

初始化 spi_device.chip_select;取決於電路板的接線方式。

mode

初始化 spi_device.mode;基於晶片資料手冊、電路板接線方式(一些裝置支援3WIRE和標準模式)以及晶片選擇路徑中可能存在的反相器。

描述

當將新的SPI裝置新增到裝置樹時,這些結構用作部分裝置模板。它們儲存了驅動程式並不總是可以確定的資訊。 probe() 可以建立的資訊(例如預設傳輸字大小)不包括在此處。

這些結構在兩個地方使用。它們的主要作用是儲存在板特定的裝置描述符表中,這些描述符在板初始化早期宣告,然後在該控制器的驅動程式初始化後(稍後)用於填充控制器的裝置樹。次要(和非典型)的角色是作為 spi_new_device() 呼叫的引數,這發生在這些控制器驅動程式在一些動態板配置模型中處於活動狀態之後。

int spi_register_board_info(struct spi_board_info const *info, unsigned n)

為給定板註冊SPI裝置

引數

struct spi_board_info const *info

晶片描述符陣列

unsigned n

提供了多少描述符

上下文

可以睡眠

描述

板特定的早期初始化程式碼呼叫此函式(可能在 arch_initcall 期間),其中包含 SPI 裝置表的段。任何裝置節點都是稍後建立的,在相關的父 SPI 控制器 (bus_num) 定義之後。我們將此裝置表永久保留,以便重新載入控制器驅動程式不會使 Linux 忘記這些硬連線裝置。

其他程式碼也可以呼叫此函式,例如,特定的附加板可以透過其擴充套件聯結器提供 SPI 裝置,因此初始化該板的程式碼自然會宣告其 SPI 裝置。

傳遞的板資訊可以安全地為 __initdata ... 但要注意任何嵌入的指標(platform_data 等),它們會按原樣複製。

Return

成功則為零,否則為負錯誤程式碼。

int __spi_register_driver(struct module *owner, struct spi_driver *sdrv)

註冊一個 SPI 驅動程式

引數

struct module *owner

要註冊的驅動程式的擁有者模組

struct spi_driver *sdrv

要註冊的驅動程式

上下文

可以睡眠

Return

成功則為零,否則為負錯誤程式碼。

struct spi_device *spi_alloc_device(struct spi_controller *ctlr)

分配一個新的SPI裝置

引數

struct spi_controller *ctlr

裝置連線到的控制器

上下文

可以睡眠

描述

允許驅動程式分配和初始化 spi_device,而無需立即註冊它。這允許驅動程式在呼叫 spi_add_device() 之前直接使用裝置引數填充 spi_device。

呼叫者負責呼叫返回的 spi_device 結構上的 spi_add_device(),以將其新增到 SPI 控制器。如果呼叫者需要丟棄 spi_device 而不新增它,則應在其上呼叫 spi_dev_put()。

Return

指向新裝置的指標,如果出錯,則為 NULL。

int spi_add_device(struct spi_device *spi)

新增使用 spi_alloc_device 分配的 spi_device

引數

struct spi_device *spi

要註冊的spi_device

描述

spi_alloc_device 的配套函式。可以使用此函式將使用 spi_alloc_device 分配的裝置新增到 SPI 總線上。

Return

成功時返回 0;失敗時返回負的 errno

struct spi_device *spi_new_device(struct spi_controller *ctlr, struct spi_board_info *chip)

例項化一個新SPI裝置

引數

struct spi_controller *ctlr

裝置連線到的控制器

struct spi_board_info *chip

描述 SPI 裝置

上下文

可以睡眠

描述

在典型的主機板上,這純粹是內部的;並且在板初始化建立硬連線裝置後不需要它。但是,某些開發平臺可能無法使用 spi_register_board_info,並且匯出了此函式,以便例如基於 USB 或 並口 的介面卡驅動程式可以新增裝置(它會以帶外方式瞭解這些裝置)。

Return

新的裝置,如果出錯,則為 NULL。

void spi_unregister_device(struct spi_device *spi)

登出單個SPI裝置

引數

struct spi_device *spi

要登出的 spi_device

描述

開始使傳遞的 SPI 裝置消失。通常這由 spi_unregister_controller() 處理。

void spi_finalize_current_transfer(struct spi_controller *ctlr)

報告傳輸完成

引數

struct spi_controller *ctlr

報告完成的控制器

描述

由使用核心 transfer_one_message() 實現的 SPI 驅動程式呼叫,以通知它當前中斷驅動的傳輸已完成,可以排程下一個傳輸。

void spi_take_timestamp_pre(struct spi_controller *ctlr, struct spi_transfer *xfer, size_t progress, bool irqs_off)

輔助函式,用於收集 TX 時間戳的開頭

引數

struct spi_controller *ctlr

指向驅動程式的 spi_controller 結構的指標

struct spi_transfer *xfer

指向正在進行時間戳的傳輸的指標

size_t progress

到目前為止已傳輸了多少個字(不是位元組)

bool irqs_off

如果為 true,將在傳輸期間停用 IRQ 和搶佔,以減少時間測量中的抖動。僅與 PIO 驅動程式相容。如果為 true,則必須使用 spi_take_timestamp_post 繼續,否則系統將崩潰。警告:為了獲得完全可預測的結果,CPU 頻率也必須受到控制(governor)。

描述

這是驅動程式的一個輔助函式,用於從 SPI 傳輸中收集請求的位元組的 TX 時間戳的開頭。必須呼叫此函式的頻率(每個字一次、整個傳輸一次、每批字一次等等)是任意的,只要在呼叫時 tx 緩衝區偏移量大於或等於請求的位元組即可。時間戳只獲取一次,在第一次這樣的呼叫中。假定驅動程式單調地推進其 tx 緩衝區指標。

void spi_take_timestamp_post(struct spi_controller *ctlr, struct spi_transfer *xfer, size_t progress, bool irqs_off)

輔助函式,用於收集 TX 時間戳的結尾

引數

struct spi_controller *ctlr

指向驅動程式的 spi_controller 結構的指標

struct spi_transfer *xfer

指向正在進行時間戳的傳輸的指標

size_t progress

到目前為止已傳輸了多少個字(不是位元組)

bool irqs_off

如果為 true,將重新啟用本地 CPU 的 IRQ 和搶佔。

描述

這是驅動程式的一個輔助函式,用於從 SPI 傳輸中收集請求的位元組的 TX 時間戳的結尾。可以使用任意頻率呼叫:只有 tx 超過或等於請求的字的第一條呼叫將被加上時間戳。

struct spi_message *spi_get_next_queued_message(struct spi_controller *ctlr)

驅動程式呼叫以檢查排隊的訊息

引數

struct spi_controller *ctlr

要檢查排隊的訊息的控制器

描述

如果佇列中還有更多訊息,則從該呼叫返回下一條訊息。

Return

佇列中的下一條訊息,如果佇列為空,則為 NULL。

void spi_finalize_current_message(struct spi_controller *ctlr)

當前訊息已完成

引數

struct spi_controller *ctlr

要將訊息返回到的控制器

描述

驅動程式呼叫此函式來通知核心佇列前面的訊息已完成,可以從佇列中刪除。

struct spi_device *spi_new_ancillary_device(struct spi_device *spi, u8 chip_select)

註冊輔助 SPI 裝置

引數

struct spi_device *spi

指向註冊輔助裝置的主 SPI 裝置的指標

u8 chip_select

輔助裝置的片選

描述

註冊一個輔助 SPI 裝置;例如,一些晶片有一個用於正常裝置使用的片選,另一個用於設定/韌體上傳。

這隻能從主 SPI 裝置的探測例程中呼叫。

Return

成功時返回 0;失敗時返回負的 errno

int acpi_spi_count_resources(struct acpi_device *adev)

計算 SpiSerialBus 資源的數量

引數

struct acpi_device *adev

ACPI 裝置

Return

ACPI 裝置的資源列表中的 SpiSerialBus 資源數量;或一個負的錯誤程式碼。

struct spi_device *acpi_spi_device_alloc(struct spi_controller *ctlr, struct acpi_device *adev, int index)

分配一個 SPI 裝置,並使用 ACPI 資訊填充它。

引數

struct spi_controller *ctlr

SPI 裝置所屬的控制器。

struct acpi_device *adev

SPI 裝置的 ACPI 裝置。

int index

ACPI 節點內 SPI 資源的索引。

描述

這應該用於從 ACPI 裝置節點分配一個新的 SPI 裝置。呼叫者負責呼叫 spi_add_device 來註冊 SPI 裝置。

如果 ctlr 設定為 NULL,則將使用資源查詢 SPI 裝置的控制器。如果 index 設定為 -1,則不使用 index。

注意

如果 index 為 -1,則必須設定 ctlr。

Return

指向新裝置的指標,如果出錯,則為 ERR_PTR。

int spi_target_abort(struct spi_device *spi)

中止 SPI 目標控制器上正在進行的傳輸請求

引數

struct spi_device *spi

用於當前傳輸的裝置。

struct spi_controller *__spi_alloc_controller(struct device *dev, unsigned int size, bool target)

分配一個 SPI 主機或目標控制器。

引數

struct device *dev

控制器,可能使用 platform_bus。

unsigned int size

要分配多少個清零的驅動程式私有資料;指向此記憶體的指標位於返回裝置的 driver_data 欄位中,可以使用 spi_controller_get_devdata() 訪問; 記憶體是快取行對齊的; 驅動程式授予對其私有資料部分 DMA 訪問許可權需要使用 ALIGN(size, dma_get_cache_alignment()) 向上舍入 **size**。

bool target

標誌,指示是分配 SPI 主機 (false) 還是 SPI 目標 (true) 控制器

上下文

可以睡眠

描述

此呼叫僅由 SPI 控制器驅動程式使用,這些驅動程式是唯一直接接觸晶片暫存器的驅動程式。 這是它們在呼叫 spi_register_controller() 之前分配 spi_controller 結構的方式。

必須從可以休眠的上下文中呼叫此函式。

在呼叫 spi_register_controller() 之前,呼叫者負責分配匯流排編號並初始化控制器的方法; 並且(在新增裝置時出錯後)呼叫 spi_controller_put() 以防止記憶體洩漏。

Return

成功時返回 SPI 控制器結構,否則返回 NULL。

struct spi_controller *__devm_spi_alloc_controller(struct device *dev, unsigned int size, bool target)

資源管理的 __spi_alloc_controller()

引數

struct device *dev

SPI 控制器的物理裝置。

unsigned int size

要分配多少個清零的驅動程式私有資料。

bool target

是分配 SPI 主機 (false) 還是 SPI 目標 (true) 控制器。

上下文

可以睡眠

描述

分配一個 SPI 控制器,並在 **dev** 與其驅動程式解除繫結時自動釋放對其的引用。 因此,驅動程式無需呼叫 spi_controller_put()。

此函式的引數與 __spi_alloc_controller() 相同。

Return

成功時返回 SPI 控制器結構,否則返回 NULL。

int spi_register_controller(struct spi_controller *ctlr)

註冊 SPI 主機或目標控制器。

引數

struct spi_controller *ctlr

已初始化的控制器,最初來自 spi_alloc_host() 或 spi_alloc_target()。

上下文

可以睡眠

描述

SPI 控制器使用一些非 SPI 匯流排(例如平臺匯流排)連線到它們的驅動程式。 該程式碼中 probe() 的最後階段包括呼叫 spi_register_controller() 以連線到此 SPI 匯流排膠合。

SPI 控制器使用板特定的(通常是 SOC 特定的)匯流排編號,並且板特定的 SPI 裝置定址將這些編號與晶片選擇編號結合起來。 由於 SPI 不直接支援動態裝置識別,因此板需要配置表來告知哪個晶片位於哪個地址。

必須從可以休眠的上下文中呼叫此函式。 成功時返回零,否則返回一個負錯誤程式碼(刪除控制器的引用計數)。 成功返回後,呼叫者負責呼叫 spi_unregister_controller()

Return

成功則為零,否則為負錯誤程式碼。

int devm_spi_register_controller(struct device *dev, struct spi_controller *ctlr)

註冊託管的 SPI 主機或目標控制器。

引數

struct device *dev

管理 SPI 控制器的裝置。

struct spi_controller *ctlr

已初始化的控制器,最初來自 spi_alloc_host() 或 spi_alloc_target()。

上下文

可以睡眠

描述

使用 spi_register_controller() 註冊一個 SPI 裝置,它將被自動登出和釋放。

Return

成功則為零,否則為負錯誤程式碼。

void spi_unregister_controller(struct spi_controller *ctlr)

登出 SPI 主機或目標控制器。

引數

struct spi_controller *ctlr

要登出的控制器。

上下文

可以睡眠

描述

此呼叫僅由 SPI 控制器驅動程式使用,這些驅動程式是唯一直接接觸晶片暫存器的驅動程式。

必須從可以休眠的上下文中呼叫此函式。

請注意,此函式還會刪除對控制器的引用。

int spi_split_transfers_maxsize(struct spi_controller *ctlr, struct spi_message *msg, size_t maxsize)

當單個傳輸超過特定大小時,將 SPI 傳輸拆分為多個傳輸。

引數

struct spi_controller *ctlr

此傳輸的 **spi_controller**。

struct spi_message *msg

要轉換的 **spi_message**。

size_t maxsize

應用此函式的最大值。

描述

此函式分配的資源會在 spi 訊息取消最佳化階段自動釋放,因此此函式只能從 optimize_message 回撥中呼叫。

Return

轉換狀態。

int spi_split_transfers_maxwords(struct spi_controller *ctlr, struct spi_message *msg, size_t maxwords)

當單個傳輸超過特定數量的 SPI 字時,將 SPI 傳輸拆分為多個傳輸。

引數

struct spi_controller *ctlr

此傳輸的 **spi_controller**。

struct spi_message *msg

要轉換的 **spi_message**。

size_t maxwords

限制每個傳輸的字數。

描述

此函式分配的資源會在 spi 訊息取消最佳化階段自動釋放,因此此函式只能從 optimize_message 回撥中呼叫。

Return

轉換狀態。

int spi_setup(struct spi_device *spi)

設定 SPI 模式和時鐘頻率。

引數

struct spi_device *spi

其設定正在修改的裝置。

上下文

可以休眠,並且沒有請求排隊到裝置。

描述

如果裝置無法使用其預設模式,則 SPI 協議驅動程式可能需要更新傳輸模式。 它們可能同樣需要從初始值更新時鐘頻率或字大小。 此函式更改這些設定,並且必須從可以休眠的上下文中呼叫。 除了 SPI_CS_HIGH(立即生效)之外,這些更改將在下次選擇裝置並將資料傳輸到裝置或從裝置傳輸時生效。 當此函式返回時,將取消選擇 SPI 裝置。

請注意,如果協議驅動程式指定了底層控制器或其驅動程式不支援的選項,則此呼叫將失敗。 例如,並非所有硬體都支援使用九位字、LSB 優先線編碼或活動高電平晶片選擇的線傳輸。

Return

成功則為零,否則為負錯誤程式碼。

int spi_optimize_message(struct spi_device *spi, struct spi_message *msg)

對 SPI 訊息執行任何一次性驗證和設定。

引數

struct spi_device *spi

將用於訊息的裝置。

struct spi_message *msg

要最佳化的訊息。

描述

重複使用同一訊息的外圍裝置驅動程式可以呼叫此函式以儘可能多地執行一次訊息準備,而不是每次執行訊息傳輸時都重複執行訊息準備,以提高吞吐量並減少 CPU 使用率。

最佳化訊息後,無法修改它,但可以更新任何 xfer->tx_buf 的內容(不能更改指標,只能更改它指向的記憶體中的資料)。

對此函式的呼叫必須與對 spi_unoptimize_message() 的呼叫保持平衡,以避免洩漏資源。

上下文

可以睡眠

Return

成功時返回零,否則返回一個負錯誤程式碼。

void spi_unoptimize_message(struct spi_message *msg)

釋放由 spi_optimize_message() 分配的任何資源。

引數

struct spi_message *msg

要取消最佳化的訊息。

描述

對此函式的呼叫必須與對 spi_optimize_message() 的呼叫保持平衡。

上下文

可以睡眠

int devm_spi_optimize_message(struct device *dev, struct spi_device *spi, struct spi_message *msg)

spi_optimize_message() 的託管版本。

引數

struct device *dev

管理 **msg** 的裝置(通常為 **spi->dev**)。

struct spi_device *spi

將用於訊息的裝置。

struct spi_message *msg

要最佳化的訊息。

Return

成功時返回零,否則返回一個負錯誤程式碼。

描述

spi_unoptimize_message() 將在刪除裝置時自動呼叫。

int spi_async(struct spi_device *spi, struct spi_message *message)

非同步 SPI 傳輸。

引數

struct spi_device *spi

將與之交換資料的裝置

struct spi_message *message

描述資料傳輸,包括完成回撥。

上下文

任何上下文(可能阻止 IRQ 等)

描述

此呼叫可以在 in_irq 和其他無法休眠的上下文中,以及可以休眠的任務上下文中使用。

完成回撥是在無法休眠的上下文中呼叫的。 在該呼叫之前,message->status 的值是未定義的。 發出回撥時,message->status 包含零(表示完全成功)或一個負錯誤程式碼。 該回調返回後,發出傳輸請求的驅動程式可以釋放關聯的記憶體; SPI 核心或控制器驅動程式程式碼不再使用該記憶體。

請注意,儘管傳送到 spi_device 的所有訊息都按 FIFO 順序處理,但訊息可能會以其他順序傳送到不同的裝置。 例如,某些裝置可能具有更高的優先順序,或者具有各種“硬”訪問時間要求。

如果在傳輸期間檢測到任何故障,則會中止整個訊息的處理,並取消選擇裝置。 在從關聯的訊息完成回撥返回之前,將不會處理排隊到該裝置的任何其他 spi_message。 (此規則同樣適用於所有同步傳輸呼叫,這些呼叫是圍繞此核心非同步原語的包裝器。)

Return

成功則為零,否則為負錯誤程式碼。

int spi_sync(struct spi_device *spi, struct spi_message *message)

阻塞/同步 SPI 資料傳輸。

引數

struct spi_device *spi

將與之交換資料的裝置

struct spi_message *message

描述資料傳輸。

上下文

可以睡眠

描述

此呼叫只能從可以休眠的上下文中使用。 休眠是不可中斷的,並且沒有超時。 低開銷控制器驅動程式可以直接 DMA 到訊息緩衝區和從訊息緩衝區 DMA。

請注意,SPI 裝置的晶片選擇在訊息期間處於活動狀態,然後通常在訊息之間停用。 一些常用裝置的驅動程式可能希望透過保持晶片處於選定狀態來最大限度地降低選擇晶片的成本,以預期下一條訊息將傳送到同一晶片。 (這可能會增加功耗。)

此外,呼叫者保證與訊息關聯的記憶體不會在此呼叫返回之前釋放。

Return

成功則為零,否則為負錯誤程式碼。

int spi_sync_locked(struct spi_device *spi, struct spi_message *message)

具有獨佔匯流排使用許可權的 spi_sync 版本。

引數

struct spi_device *spi

將與之交換資料的裝置

struct spi_message *message

描述資料傳輸。

上下文

可以睡眠

描述

此呼叫只能從可以休眠的上下文中使用。 休眠是不可中斷的,並且沒有超時。 低開銷控制器驅動程式可以直接 DMA 到訊息緩衝區和從訊息緩衝區 DMA。

需要獨佔訪問 SPI 匯流排的驅動程式應使用此呼叫。 它必須以 spi_bus_lock 呼叫作為前導。 當獨佔訪問結束時,必須透過 spi_bus_unlock 呼叫釋放 SPI 匯流排。

Return

成功則為零,否則為負錯誤程式碼。

int spi_bus_lock(struct spi_controller *ctlr)

獲取鎖以獨佔使用 SPI 匯流排。

引數

struct spi_controller *ctlr

應鎖定以進行獨佔匯流排訪問的 SPI 匯流排控制器。

上下文

可以睡眠

描述

此呼叫只能從可以休眠的上下文中使用。 休眠是不可中斷的,並且沒有超時。

此呼叫應由需要獨佔訪問 SPI 匯流排的驅動程式使用。 當獨佔訪問結束後,必須透過 spi_bus_unlock 呼叫釋放 SPI 匯流排。 當 SPI 匯流排鎖被持有時,資料傳輸必須透過 spi_sync_locked 和 spi_async_locked 呼叫完成。

Return

始終為零。

int spi_bus_unlock(struct spi_controller *ctlr)

釋放用於獨佔 SPI 匯流排使用的鎖

引數

struct spi_controller *ctlr

已鎖定以進行獨佔匯流排訪問的 SPI 匯流排控制器

上下文

可以睡眠

描述

此呼叫只能從可以休眠的上下文中使用。 休眠是不可中斷的,並且沒有超時。

此呼叫釋放先前由 spi_bus_lock 呼叫獲取的 SPI 匯流排鎖。

Return

始終為零。

int spi_write_then_read(struct spi_device *spi, const void *txbuf, unsigned n_tx, void *rxbuf, unsigned n_rx)

SPI 同步寫後讀

引數

struct spi_device *spi

將與之交換資料的裝置

const void *txbuf

要寫入的資料(不必是 DMA 安全的)

unsigned n_tx

txbuf 的大小,以位元組為單位

void *rxbuf

將資料讀入的緩衝區(不必是 DMA 安全的)

unsigned n_rx

rxbuf 的大小,以位元組為單位

上下文

可以睡眠

描述

這使用裝置執行半雙工 MicroWire 樣式事務,傳送 txbuf 然後讀取 rxbuf。 返回值在成功時為零,否則為負 errno 狀態程式碼。 此呼叫只能從可以休眠的上下文中使用。

此例程的引數始終使用小緩衝區進行復制。 對效能敏感或批次傳輸程式碼應使用帶有 DMA 安全緩衝區的 spi_{async,sync}() 呼叫。

Return

成功則為零,否則為負錯誤程式碼。