串行外围接口 (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

在 32 位系统上,保护此结构中的成员进行每 CPU 更新的 seqcount

messages

已处理的 spi 消息数量

transfers

已处理的 spi_transfer 数量

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 chip_select[SPI_CS_CNT_MAX];
    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 gpio_desc        *cs_gpiod[SPI_CS_CNT_MAX];
    struct spi_delay        word_delay;
    struct spi_delay        cs_setup;
    struct spi_delay        cs_hold;
    struct spi_delay        cs_inactive;
    struct spi_statistics __percpu  *pcpu_statistics;
    u32 cs_index_mask : SPI_CS_CNT_MAX;
};

成员

dev

设备的驱动程序模型表示。

controller

与设备一起使用的 SPI 控制器。

max_speed_hz

与此芯片(在此板上)一起使用的最大时钟频率;可能会被设备的驱动程序更改。spi_transfer.speed_hz 可以覆盖每次传输的此值。

chip_select

物理片选数组,spi->chipselect[i] 给出逻辑 CS i 的相应物理 CS。

bits_per_word

数据传输涉及一个或多个字;常见的字大小为 8 位或 12 位。内存中的字大小是 2 字节的幂(例如,20 位采样使用 32 位)。这可能会被设备的驱动程序更改,或者保留为默认值 (0),表示协议字为 8 位字节。spi_transfer.bits_per_word 可以覆盖每次传输的此值。

rt

使泵线程具有实时优先级。

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() 来设置或清除它。

cs_gpiod

相应片选线的 GPIO 描述符数组(可选,不使用 GPIO 线时为 NULL)

word_delay

在传输的连续字之间插入的延迟

cs_setup

在片选信号置位后,由控制器引入的延迟

cs_hold

在片选信号取消置位前,由控制器引入的延迟

cs_inactive

在片选信号取消置位后,由控制器引入的延迟。 如果 spi_transfer 中使用了 cs_change_delay,则这两个延迟将相加。

pcpu_statistics

spi_device 的统计信息

cs_index_mask

片选数组中活动片选的位掩码

描述

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;
    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

支持的最高传输速度

flags

与此驱动程序相关的其他约束

devm_allocated

此结构的分配是否由 devres 管理

{unnamed_union}

匿名

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) 是否为真。

last_cs

set_cs 记录的最后一个 chip_select,如果未选择芯片,则为 -1

last_cs_index_mask

上次使用的芯片选择的位掩码

xfer_completion

由核心 transfer_one_message() 使用

max_dma_len

设备 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

控制器处理存储器操作的功能。

cs_gpiods

用作片选线的 GPIO 描述符数组;每个片选号一个。对于不是 GPIO(由 SPI 控制器本身驱动)的片选线,任何单个值都可以为 NULL。

use_gpio_descriptors

启用 SPI 核心中的代码来解析和获取 GPIO 描述符。这将填充 cs_gpiods,并且如果为片选找到 GPIO 线,则 SPI 设备将分配 cs_gpiod。

unused_native_cs

当使用 cs_gpiods 时,spi_register_controller() 将使用第一个未使用的本机片选来填充此字段,以便需要在使用 GPIO 片选时驱动本机片选的 SPI 控制器驱动程序使用。

max_native_cs

当使用 cs_gpiods 并且填充此字段时,spi_register_controller() 将根据此值验证所有本机片选(包括未使用的本机片选)。

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;
#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    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

如果为 true,则 tx_sg 已映射用于 DMA

rx_sg_mapped

如果为 true,则 rx_sg 已映射用于 DMA

tx_sg

用于发送的散列表,目前不供客户端使用

rx_sg

用于接收的散列表,目前不供客户端使用

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

如果传输已加时间戳,则为 true

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。

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) 并以 CPU 字节顺序保存 N 个 16 位字。

当 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) 设置传输模式以支持这三种传输。

将 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 list_head        resources;
};

成员

transfers

此事务中的传输段列表

spi

事务排队的 SPI 设备

pre_optimized

外围驱动程序预优化了消息

optimized

消息处于优化状态

prepared

已为此消息调用 spi_prepare_message

status

成功为零,否则为负 errno

complete

调用以报告事务完成

context

调用时 complete() 的参数

frame_length

消息中的总字节数

actual_length

所有成功段中传输的总字节数

queue

供当前拥有消息的任何驱动程序使用

state

供当前拥有消息的任何驱动程序使用

opt_state

供当前拥有消息的任何驱动程序使用

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

返回

如果支持 bpw,则为 True,否则为 False。

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

计算合适的超时值

参数

struct spi_controller *ctlr

SPI 设备

struct spi_transfer *xfer

传输描述符

描述

计算给定传输的相关超时值。我们推导出在单条数据线上所需的时间,并取两倍的时间,最小值为 500 毫秒,以避免在负载较重的系统上出现误报。

返回

以毫秒为单位的传输超时值。

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

已替换 replaced_transfers 的大小为 inserted 的 spi_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()

返回

成功时为零,否则为负错误代码。

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。仅可从可以休眠的上下文中调用。

返回

成功时为零,否则为负错误代码。

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

SPI 同步读取

参数

struct spi_device *spi

从中读取数据的设备

void *buf

数据缓冲区

size_t len

数据缓冲区大小

上下文

可以休眠

描述

此函数读取缓冲区 buf。只能从可以休眠的上下文调用。

返回

成功时为零,否则为负错误代码。

ssize_t spi_w8r8(struct spi_device *spi, u8 cmd)

SPI 同步 8 位写入,然后 8 位读取

参数

struct spi_device *spi

将与其交换数据的设备

u8 cmd

在读取数据之前要写入的命令

上下文

可以休眠

描述

只能从可以休眠的上下文调用。

返回

设备返回的(无符号)八位数字,否则返回负错误代码。

ssize_t spi_w8r16(struct spi_device *spi, u8 cmd)

SPI 同步 8 位写入,然后 16 位读取

参数

struct spi_device *spi

将与其交换数据的设备

u8 cmd

在读取数据之前要写入的命令

上下文

可以休眠

描述

该数字以线路顺序返回,至少有时是大端字节序。

只能从可以休眠的上下文调用。

返回

设备返回的(无符号)十六位数字,否则返回负错误代码。

ssize_t spi_w8r16be(struct spi_device *spi, u8 cmd)

SPI 同步 8 位写入,然后 16 位大端字节序读取

参数

struct spi_device *spi

将与其交换数据的设备

u8 cmd

在读取数据之前要写入的命令

上下文

可以休眠

描述

此函数类似于 spi_w8r16,区别在于它会将读取的 16 位数据字从大端字节序转换为本机字节序。

只能从可以休眠的上下文调用。

返回

设备返回的以 CPU 字节序表示的(无符号)十六位数字,否则返回负错误代码。

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 等),它们是按原样复制的。

返回

成功时为零,否则为负错误代码。

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

注册 SPI 驱动程序

参数

struct module *owner

要注册的驱动程序的拥有者模块

struct spi_driver *sdrv

要注册的驱动程序

上下文

可以休眠

返回

成功时为零,否则为负错误代码。

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()。

返回

指向新设备的指针,或者为 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 总线上。

返回

成功时返回 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 或 parport 的适配器驱动程序可以添加设备(它会带外了解这些设备)。

返回

新设备,或者为 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 频率也必须受控制(调速器)。

描述

这是一个辅助函数,用于驱动程序从 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

要检查排队消息的控制器

描述

如果队列中有更多消息,则此调用将返回下一条消息。

返回

队列中的下一条消息,如果队列为空,则返回 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 设备的探测例程中调用此函数。

返回

成功时返回 0;失败时返回负 errno

int acpi_spi_count_resources(struct acpi_device *adev)

计算 SpiSerialBus 资源的数量

参数

struct acpi_device *adev

ACPI 设备

返回

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。

返回

指向新设备的指针,如果出错,则返回 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 slave)

分配一个 SPI 主或从控制器

参数

struct device *dev

控制器,可能使用 platform_bus

unsigned int size

要分配多少个清零的驱动程序私有数据;指向此内存的指针位于返回设备的 driver_data 字段中,可以使用 spi_controller_get_devdata() 访问;内存是缓存行对齐的;驱动程序向其私有数据的部分授予 DMA 访问权限需要使用 ALIGN(size, dma_get_cache_alignment()) 来向上舍入 size

bool slave

标志,指示是分配 SPI 主控制器(false)还是 SPI 从控制器(true)

上下文

可以休眠

描述

此调用仅由 SPI 控制器驱动程序使用,这些驱动程序是唯一直接操作芯片寄存器的驱动程序。它是它们在调用 spi_register_controller() 之前分配 spi_controller 结构的方式。

必须从可以睡眠的上下文调用此函数。

调用者负责在调用 spi_register_controller() 之前分配总线号并初始化控制器的的方法;并且(在添加设备出错之后)调用 spi_controller_put() 以防止内存泄漏。

返回

成功时返回 SPI 控制器结构,否则返回 NULL。

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

资源管理的 __spi_alloc_controller()

参数

struct device *dev

SPI 控制器的物理设备

unsigned int size

要分配多少零初始化的驱动程序私有数据

bool slave

是否分配 SPI 主设备(false)或 SPI 从设备(true)

上下文

可以休眠

描述

分配一个 SPI 控制器,并在 dev 从其驱动程序解除绑定时自动释放对它的引用。这样可以避免驱动程序调用 spi_controller_put()。

此函数的参数与 __spi_alloc_controller() 相同。

返回

成功时返回 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()

返回

成功时为零,否则为负错误代码。

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 设备,该设备将自动注销和释放。

返回

成功时为零,否则为负错误代码。

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 回调中调用。

返回

转换状态

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 回调中调用。

返回

转换状态

int spi_setup(struct spi_device *spi)

设置 SPI 模式和时钟速率

参数

struct spi_device *spi

正在修改设置的设备

上下文

可以休眠,并且没有请求排队到设备

描述

如果设备无法使用其默认值,SPI 协议驱动程序可能需要更新传输模式。它们可能同样需要更新初始值的时钟速率或字大小。此函数会更改这些设置,并且必须从可以休眠的上下文中调用。除了立即生效的 SPI_CS_HIGH 之外,这些更改在下次选择设备并将数据传输到该设备或从该设备传输时生效。当此函数返回时,将取消选择 SPI 设备。

请注意,如果协议驱动程序指定了底层控制器或其驱动程序不支持的选项,则此调用将失败。例如,并非所有硬件都支持使用九位字、LSB 优先的线路编码或高电平有效片选的线路传输。

返回

成功时为零,否则为负错误代码。

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() 的调用保持平衡,以避免资源泄漏。

上下文

可以休眠

返回

成功时返回零,否则返回负错误代码

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

要优化的消息

返回

成功时返回零,否则返回负错误代码

描述

当设备被移除时,spi_unoptimize_message() 将被自动调用。

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

异步 SPI 传输。

参数

struct spi_device *spi

将与其交换数据的设备

struct spi_message *message

描述数据传输,包括完成回调。

上下文

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

描述

此调用可以在 irq 和其他不能休眠的上下文中使用,也可以在可以休眠的任务上下文中使用。

完成回调在不能休眠的上下文中调用。在该调用之前,message->status 的值是未定义的。当发出回调时,message->status 包含零(表示完全成功)或负错误代码。在该回调返回后,发出传输请求的驱动程序可以释放相关的内存;任何 SPI 核心或控制器驱动程序代码不再使用它。

请注意,尽管发送到 spi_device 的所有消息都按 FIFO 顺序处理,但消息可能会以其他顺序发送到不同的设备。例如,某些设备可能具有更高的优先级,或者具有各种“硬性”访问时间要求。

在传输过程中检测到任何故障时,整个消息的处理将被中止,并且设备将被取消选择。在从相关的消息完成回调返回之前,不会处理排队到该设备的任何其他 spi_message。(此规则同样适用于所有同步传输调用,这些调用是此核心异步原语的包装。)

返回

成功时为零,否则为负错误代码。

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

阻塞/同步 SPI 数据传输。

参数

struct spi_device *spi

将与其交换数据的设备

struct spi_message *message

描述数据传输。

上下文

可以休眠

描述

此调用只能从可以休眠的上下文中使用。休眠是不可中断的,并且没有超时。低开销控制器驱动程序可以将 DMA 直接放入和取出消息缓冲区。

请注意,SPI 设备的片选在消息期间处于活动状态,然后在消息之间通常被禁用。一些常用设备的驱动程序可能希望通过保持片选来最小化选择芯片的成本,以预期下一条消息将发送到同一芯片。(这可能会增加功耗。)

此外,调用者保证在调用返回之前不会释放与消息关联的内存。

返回

成功时为零,否则为负错误代码。

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

具有独占总线使用的 spi_sync 版本。

参数

struct spi_device *spi

将与其交换数据的设备

struct spi_message *message

描述数据传输。

上下文

可以休眠

描述

此调用只能从可以休眠的上下文中使用。休眠是不可中断的,并且没有超时。低开销控制器驱动程序可以将 DMA 直接放入和取出消息缓冲区。

需要独占访问 SPI 总线的驱动程序应使用此调用。它必须在 spi_bus_lock 调用之前。当独占访问结束时,必须通过 spi_bus_unlock 调用释放 SPI 总线。

返回

成功时为零,否则为负错误代码。

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 调用完成数据传输。

返回

始终为零。

int spi_bus_unlock(struct spi_controller *ctlr)

释放独占 SPI 总线使用的锁。

参数

struct spi_controller *ctlr

之前为独占总线访问锁定的 SPI 总线主设备。

上下文

可以休眠

描述

此调用只能从可以休眠的上下文中使用。休眠是不可中断的,并且没有超时。

此调用释放先前通过 spi_bus_lock 调用获得的 SPI 总线锁。

返回

始终为零。

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}() 调用。

返回

成功时为零,否则为负错误代码。