高速同步串行接口 (HSI)¶
简介¶
高速同步接口 (HSI) 是一种全双工、低延迟协议,专为应用处理器和基带芯片组之间的芯片级互连而优化。它已由 MIPI 联盟在 2003 年指定,此后由多家供应商实施。
HSI 接口支持通过多个通道(通常为 8 个)进行全双工通信,并且能够达到高达 200 Mbit/s 的速度。
串行协议使用两个信号 DATA 和 FLAG 作为组合的数据和时钟信号,并使用一个额外的 READY 信号进行流量控制。一个额外的 WAKE 信号可用于将芯片从待机模式唤醒。这些信号通常以 AC 为前缀表示从应用芯片到蜂窝芯片的信号,以 CA 为前缀表示反方向的信号。
+------------+ +---------------+
| Cellular | | Application |
| Die | | Die |
| | - - - - - - CAWAKE - - - - - - >| |
| T|------------ CADATA ------------>|R |
| X|------------ CAFLAG ------------>|X |
| |<----------- ACREADY ------------| |
| | | |
| | | |
| |< - - - - - ACWAKE - - - - - - -| |
| R|<----------- ACDATA -------------|T |
| X|<----------- ACFLAG -------------|X |
| |------------ CAREADY ----------->| |
| | | |
| | | |
+------------+ +---------------+
Linux 中的 HSI 子系统¶
在 Linux 内核中,hsi 子系统应该用于 HSI 设备。hsi 子系统包含 hsi 控制器的驱动程序,包括对多端口控制器的支持,并提供用于使用 HSI 端口的通用 API。
它还包含 HSI 客户端驱动程序,这些驱动程序利用通用 API 来实现 HSI 接口上使用的协议。这些客户端驱动程序可以使用任意数量的通道。
hsi-char 设备¶
每个端口都会自动注册一个名为 hsi_char 的通用客户端驱动程序,该驱动程序为表示 HSI 端口的用户空间提供字符设备。它可以用于从用户空间通过 HSI 进行通信。用户空间可以使用以下 ioctl 命令配置 hsi_char 设备
- HSC_RESET
刷新 HSI 端口
- HSC_SET_PM
启用或禁用客户端。
- HSC_SEND_BREAK
发送中断
- HSC_SET_RX
设置 RX 配置
- HSC_GET_RX
获取 RX 配置
- HSC_SET_TX
设置 TX 配置
- HSC_GET_TX
获取 TX 配置
内核 HSI API¶
-
struct hsi_channel¶
hsi 客户端使用的通道资源
定义:
struct hsi_channel {
unsigned int id;
const char *name;
};
成员
id
通道号
name
通道名称
-
struct hsi_config¶
用于 RX/TX HSI 模块的配置
定义:
struct hsi_config {
unsigned int mode;
struct hsi_channel *channels;
unsigned int num_channels;
unsigned int num_hw_channels;
unsigned int speed;
union {
unsigned int flow;
unsigned int arb_mode;
};
};
成员
mode
位传输模式(STREAM 或 FRAME)
channels
客户端使用的通道资源
num_channels
通道资源数量
num_hw_channels
收发器配置的通道数量 [1..16]
speed
最大位传输速度 (Kbit/s)
{unnamed_union}
匿名
flow
RX 流类型(SYNCHRONIZED 或 PIPELINE)
arb_mode
TX 帧的仲裁模式(轮循、优先级)
-
struct hsi_board_info¶
HSI 客户端板信息
定义:
struct hsi_board_info {
const char *name;
unsigned int hsi_id;
unsigned int port;
struct hsi_config tx_cfg;
struct hsi_config rx_cfg;
void *platform_data;
struct dev_archdata *archdata;
};
成员
name
HSI 设备的名称
hsi_id
客户端所在的 HSI 控制器 ID
port
客户端所在的控制器中的端口号
tx_cfg
HSI TX 配置
rx_cfg
HSI RX 配置
platform_data
平台相关数据
archdata
依赖于架构的设备数据
-
struct hsi_client¶
附加到 HSI 端口的 HSI 客户端
定义:
struct hsi_client {
struct device device;
struct hsi_config tx_cfg;
struct hsi_config rx_cfg;
};
成员
device
设备的驱动程序模型表示
tx_cfg
HSI TX 配置
rx_cfg
HSI RX 配置
-
struct hsi_client_driver¶
与 HSI 客户端关联的驱动程序
定义:
struct hsi_client_driver {
struct device_driver driver;
};
成员
driver
驱动程序的驱动程序模型表示
-
struct hsi_msg¶
HSI 消息描述符
定义:
struct hsi_msg {
struct list_head link;
struct hsi_client *cl;
struct sg_table sgt;
void *context;
void (*complete)(struct hsi_msg *msg);
void (*destructor)(struct hsi_msg *msg);
int status;
unsigned int actual_len;
unsigned int channel;
unsigned int ttype:1;
unsigned int break_frame:1;
};
成员
link
当前描述符所有者可以自由使用
cl
发出传输的 HSI 设备客户端
sgt
分散列表数组的头部
context
与传输关联的客户端上下文数据
complete
传输完成回调
destructor
刷新时释放资源的析构函数
status
完成时传输的状态
actual_len
完成时传输的实际数据长度
channel
要发送/接收消息的通道
ttype
传输类型(如果设置则为 TX,否则为 RX)
break_frame
如果为 true,HSI 将发送/接收中断帧。数据缓冲区在请求中被忽略。
-
struct hsi_port¶
HSI 端口设备
定义:
struct hsi_port {
struct device device;
struct hsi_config tx_cfg;
struct hsi_config rx_cfg;
unsigned int num;
unsigned int shared:1;
int claimed;
struct mutex lock;
int (*async)(struct hsi_msg *msg);
int (*setup)(struct hsi_client *cl);
int (*flush)(struct hsi_client *cl);
int (*start_tx)(struct hsi_client *cl);
int (*stop_tx)(struct hsi_client *cl);
int (*release)(struct hsi_client *cl);
struct blocking_notifier_head n_head;
};
成员
device
设备的驱动程序模型表示
tx_cfg
当前 TX 路径配置
rx_cfg
当前 RX 路径配置
num
端口号
shared
当端口可以由不同的客户端共享时设置
claimed
声明端口的客户端的引用计数
lock
序列化端口声明
async
异步传输回调
setup
设置 HSI 客户端配置的回调
flush
清除硬件状态并销毁所有挂起传输的回调
start_tx
通知客户端想要发送数据的回调
stop_tx
通知客户端不再希望发送数据的回调
release
通知客户端不再使用端口的回调
n_head
用于向客户端发出端口事件信号的通知程序链。
-
struct hsi_controller¶
HSI 控制器设备
定义:
struct hsi_controller {
struct device device;
struct module *owner;
unsigned int id;
unsigned int num_ports;
struct hsi_port **port;
};
成员
device
设备的驱动程序模型表示
owner
指向拥有控制器的模块的指针
id
HSI 控制器 ID
num_ports
HSI 控制器中的端口数
port
HSI 端口数组
-
unsigned int hsi_id(struct hsi_client *cl)¶
获取与客户端关联的 HSI 控制器 ID
参数
struct hsi_client *cl
指向 HSI 客户端的指针
描述
返回客户端所连接的控制器 ID
-
unsigned int hsi_port_id(struct hsi_client *cl)¶
获取客户端所连接的端口号
参数
struct hsi_client *cl
指向 HSI 客户端的指针
描述
返回与客户端关联的端口号
-
int hsi_setup(struct hsi_client *cl)¶
配置客户端的端口
参数
struct hsi_client *cl
指向 HSI 客户端的指针
描述
当共享端口时,客户端应依赖于单个客户端设置,或所有客户端具有相同的设置。
失败时返回 -errno,成功时返回 0
-
int hsi_flush(struct hsi_client *cl)¶
清除客户端端口上所有待处理的事务
参数
struct hsi_client *cl
指向 HSI 客户端的指针
描述
此函数将销毁端口中所有待处理的 hsi_msg,并重置硬件端口,使其可以从干净状态接收和传输。
失败时返回 -errno,成功时返回 0
-
int hsi_async_read(struct hsi_client *cl, struct hsi_msg *msg)¶
提交一个读取传输
参数
struct hsi_client *cl
指向 HSI 客户端的指针
struct hsi_msg *msg
传输的 HSI 消息描述符
描述
失败时返回 -errno,成功时返回 0
-
int hsi_async_write(struct hsi_client *cl, struct hsi_msg *msg)¶
提交一个写入传输
参数
struct hsi_client *cl
指向 HSI 客户端的指针
struct hsi_msg *msg
传输的 HSI 消息描述符
描述
失败时返回 -errno,成功时返回 0
-
int hsi_start_tx(struct hsi_client *cl)¶
通知端口客户端想要开始 TX
参数
struct hsi_client *cl
指向 HSI 客户端的指针
描述
失败时返回 -errno,成功时返回 0
-
int hsi_stop_tx(struct hsi_client *cl)¶
通知端口客户端不再想要传输
参数
struct hsi_client *cl
指向 HSI 客户端的指针
描述
失败时返回 -errno,成功时返回 0
参数
struct hsi_port *port
要注销的 HSI 端口
-
void hsi_unregister_controller(struct hsi_controller *hsi)¶
注销 HSI 控制器
参数
struct hsi_controller *hsi
要注销的 HSI 控制器
-
int hsi_register_controller(struct hsi_controller *hsi)¶
注册 HSI 控制器及其端口
参数
struct hsi_controller *hsi
要注销的 HSI 控制器
描述
失败时返回 -errno,成功时返回 0。
-
int hsi_register_client_driver(struct hsi_client_driver *drv)¶
向 HSI 总线注册 HSI 客户端
参数
struct hsi_client_driver *drv
要注册的 HSI 客户端驱动程序
描述
失败时返回 -errno,成功时返回 0。
-
void hsi_put_controller(struct hsi_controller *hsi)¶
释放 HSI 控制器
参数
struct hsi_controller *hsi
指向要释放的 HSI 控制器的指针
描述
HSI 控制器驱动程序只有在成功调用 hsi_register_controller 之前需要释放其分配的 hsi_controller 结构时才应使用此函数。不允许其他用法。
-
struct hsi_controller *hsi_alloc_controller(unsigned int n_ports, gfp_t flags)¶
分配 HSI 控制器及其端口
参数
unsigned int n_ports
HSI 控制器上的端口数
gfp_t flags
内核分配标志
描述
失败时返回 NULL,成功时返回指向 hsi_controller 的指针。
参数
struct hsi_msg *msg
指向 HSI 消息的指针
描述
客户端负责释放散列表指向的缓冲区。
参数
unsigned int nents
内存条目数
gfp_t flags
内核分配标志
描述
nents 可以为 0。这主要对读取传输有意义。在这种情况下,当有数据要读取但没有使用时,HSI 驱动程序将调用完成回调。
失败时返回 NULL,成功时返回指向 hsi_msg 的指针。
-
int hsi_async(struct hsi_client *cl, struct hsi_msg *msg)¶
向控制器提交 HSI 传输
参数
struct hsi_client *cl
发送传输的 HSI 客户端
struct hsi_msg *msg
传递给控制器的 HSI 传输
描述
HSI 消息必须预先设置 channel、ttype、complete 和 destructor 字段。如果 nents > 0,则客户端还必须初始化 scatterlists,使其指向要写入或读取的缓冲区。
HSI 控制器依赖于客户端预先分配的缓冲区,它们不会自行分配缓冲区。
一旦 HSI 消息传输完成,HSI 控制器会调用 complete 回调函数,并更新 HSI 消息的 status 和 actual_len 字段。complete 回调函数可以在 hsi_async 返回之前被调用。
失败时返回 -errno,成功时返回 0。
-
int hsi_claim_port(struct hsi_client *cl, unsigned int share)¶
声明 HSI 客户端的端口。
参数
struct hsi_client *cl
想要声明其端口的 HSI 客户端。
unsigned int share
标志,指示客户端是否想要共享端口。
描述
失败时返回 -errno,成功时返回 0。
-
void hsi_release_port(struct hsi_client *cl)¶
释放 HSI 客户端的端口。
参数
struct hsi_client *cl
之前声明过其端口的 HSI 客户端。
-
int hsi_register_port_event(struct hsi_client *cl, void (*handler)(struct hsi_client*, unsigned long))¶
注册客户端以接收端口事件。
参数
struct hsi_client *cl
想要接收端口事件的 HSI 客户端。
void (*handler)(struct hsi_client *, unsigned long)
事件处理回调函数。
描述
客户端应注册一个回调函数,以便能够接收来自端口的事件。注册应在声明端口后进行。处理程序可以在中断上下文中调用。
出错时返回 -errno,成功时返回 0。
-
int hsi_unregister_port_event(struct hsi_client *cl)¶
停止接收客户端的端口事件。
参数
struct hsi_client *cl
想要停止接收端口事件的 HSI 客户端。
描述
客户端应在释放其关联的端口之前调用此函数。
出错时返回 -errno,成功时返回 0。
参数
struct hsi_port *port
事件发生的端口。
unsigned long event
事件类型。
描述
客户端不应关心唤醒线行为。然而,由于 HSI HW 协议中的竞争条件,需要通知客户端唤醒线变化,以便他们可以实现针对此问题的解决方法。
事件:HSI_EVENT_START_RX - 输入唤醒线高电平,HSI_EVENT_STOP_RX - 输入唤醒线低电平。
出错时返回 -errno,成功时返回 0。
-
int hsi_get_channel_id_by_name(struct hsi_client *cl, char *name)¶
通过通道名称获取通道 ID。
参数
struct hsi_client *cl
使用通道的 HSI 客户端。
char *name
通道已知的名称。
描述
客户端可以调用此函数来获取 HSI 通道 ID,类似于通过名称请求 IRQ 或 GPIO。此函数假定 RX 和 TX 使用相同的通道配置。
出错时返回 -errno,成功时返回通道 ID。