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

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