串行外围接口 (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_pre 和 spi_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_nbits 和 rx_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 设备
-
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()
分配的任何资源。
-
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}() 调用。
返回
成功时为零,否则为负错误代码。