1.概要
目的:确认两个结构体的关系。
rockchip_pin_group谁对引脚的定义。
rockchip_pmx_func是对功能的定义,一个功能有一组引脚共同构成。
2.内容
在瑞芯微RK3588的pinctrl驱动中,struct rockchip_pin_group 和 struct rockchip_pmx_func 是核心数据结构,用于描述引脚复用(Pinmux)和功能配置。以下是它们的详细解析:
1. struct rockchip_pin_group
作用:
表示一组物理引脚的集合,通常对应某个外设功能(如SPI、I2C)的引脚配置。
关键成员:
struct rockchip_pin_group {
const char *name; // 引脚组名称(如 "spi0_sck")
const unsigned int *pins; // 引脚编号数组(如 GPIO0_A0, GPIO0_A1)
const unsigned int num_pins; // 引脚数量
const unsigned int *funcs; // 每个引脚对应的复用功能索引
const unsigned int *drive; // 驱动强度配置(可选)
const unsigned int *pull; // 上拉/下拉配置(可选)
const unsigned int *schmitt; // 施密特触发器配置(可选)
};
示例:
定义SPI0的SCK引脚组:
static const unsigned int spi0_sck_pins[] = { RK_PD0 };
static const unsigned int spi0_sck_funcs[] = { RK_FUNC_SPI0 };
struct rockchip_pin_group spi0_sck_group = {
.name = "spi0_sck",
.pins = spi0_sck_pins,
.num_pins = ARRAY_SIZE(spi0_sck_pins),
.funcs = spi0_sck_funcs,
};
2. struct rockchip_pmx_func
作用:
描述一个逻辑功能(如SPI0),包含该功能所需的引脚组及配置。
关键成员:
struct rockchip_pmx_func {
const char *name; // 功能名称(如 "spi0")
const char * const *groups; // 关联的引脚组数组(如 "spi0_sck", "spi0_mosi")
const unsigned int num_groups; // 引脚组数量
const unsigned int *ctrl; // 额外控制配置(如时钟使能)
};
示例:
定义SPI0功能:
static const char * const spi0_groups[] = {
"spi0_sck",
"spi0_mosi",
"spi0_miso",
"spi0_cs0",
};
struct rockchip_pmx_func spi0_func = {
.name = "spi0",
.groups = spi0_groups,
.num_groups = ARRAY_SIZE(spi0_groups),
};
3. 两者关系
-
功能与引脚组的绑定:
一个功能(pmx_func)由多个引脚组(pin_group)组成。例如,SPI0功能需要SCK、MOSI、MISO、CS等引脚组。 -
配置流程:
- 在设备树(DTS)中定义引脚组和功能:
pinctrl_spi0: spi0@0 { rockchip,pins = < RK_PD0 RK_FUNC_SPI0 &pcfg_pull_none, RK_PD1 RK_FUNC_SPI0 &pcfg_pull_none, /* ... */ >; rockchip,function = "spi0"; }; - 驱动解析DTS,填充
rockchip_pin_group和rockchip_pmx_func结构体。 - 当外设(如SPI控制器)请求
pinctrl_select_state()时,系统根据功能名称找到对应的pmx_func,并配置所有关联的pin_group。
- 在设备树(DTS)中定义引脚组和功能:
4. 高级配置
-
电气参数:
通过drive、pull、schmitt等成员可配置引脚的驱动强度、上拉/下拉电阻、施密特触发器等。 -
动态切换:
支持运行时切换功能(如从UART切换到GPIO),通过pinctrl_lookup_state()和pinctrl_select_state()实现。
5. 调试建议
-
检查DTS配置:
确保引脚组和功能名称与驱动代码一致。 -
查看pinctrl日志:
启用CONFIG_DEBUG_PINCTRL,通过dmesg查看引脚配置过程。 -
硬件手册:
参考《RK3588 TRM》的GPIO和Pinmux章节,确认引脚复用编号和电气参数。
通过这两个结构体,RK3588的pinctrl驱动实现了灵活的引脚复用管理,支持外设动态配置和硬件抽象。
3.关联链接
4.关联知识
1.解析设备树
pinctrl_spi0: spi0@0 {
rockchip,pins = <
RK_PD0 RK_FUNC_SPI0 &pcfg_pull_none,
RK_PD1 RK_FUNC_SPI0 &pcfg_pull_none,
/* ... */
>;
rockchip,function = "spi0";
};
在瑞芯微RK3588的pinctrl驱动中,解析用户提供的设备树节点 pinctrl_spi0 后,生成的 struct rockchip_pin_group 和 struct rockchip_pmx_func 结构体如下:
1. struct rockchip_pin_group 解析
设备树中的 rockchip,pins 数组每个条目对应一个引脚组。假设条目为:
rockchip,pins = <
RK_PD0 RK_FUNC_SPI0 &pcfg_pull_none,
RK_PD1 RK_FUNC_SPI0 &pcfg_pull_none,
RK_PD2 RK_FUNC_SPI0 &pcfg_pull_none,
RK_PD3 RK_FUNC_SPI0 &pcfg_pull_none
>;
生成的引脚组:
每个条目生成一个 rockchip_pin_group,名称自动生成(如 spi0_pd0, spi0_pd1 等):
/* 引脚组 1: PD0 */
static const unsigned int spi0_pd0_pins[] = { RK_PD0 };
static const unsigned int spi0_pd0_funcs[] = { RK_FUNC_SPI0 };
static const unsigned int spi0_pd0_pull[] = { PULL_NONE };
struct rockchip_pin_group spi0_pd0_group = {
.name = "spi0_pd0",
.pins = spi0_pd0_pins,
.num_pins = 1,
.funcs = spi0_pd0_funcs,
.pull = spi0_pd0_pull,
};
/* 引脚组 2: PD1 */
static const unsigned int spi0_pd1_pins[] = { RK_PD1 };
static const unsigned int spi0_pd1_funcs[] = { RK_FUNC_SPI0 };
static const unsigned int spi0_pd1_pull[] = { PULL_NONE };
struct rockchip_pin_group spi0_pd1_group = {
.name = "spi0_pd1",
.pins = spi0_pd1_pins,
.num_pins = 1,
.funcs = spi0_pd1_funcs,
.pull = spi0_pd1_pull,
};
/* 后续引脚组(PD2, PD3)结构类似,名称依次为 spi0_pd2, spi0_pd3 */
2. struct rockchip_pmx_func 解析
设备树中的 rockchip,function = "spi0" 关联到功能名称,生成的 pmx_func 结构体如下:
/* 定义所有引脚组名称 */
static const char * const spi0_groups[] = {
"spi0_pd0", /* 对应 PD0 */
"spi0_pd1", /* 对应 PD1 */
"spi0_pd2", /* 对应 PD2 */
"spi0_pd3", /* 对应 PD3 */
};
/* 生成功能结构体 */
struct rockchip_pmx_func spi0_func = {
.name = "spi0",
.groups = spi0_groups,
.num_groups = ARRAY_SIZE(spi0_groups),
};
3. 关键解析逻辑
- 引脚组生成:
- 每个
rockchip,pins条目生成一个rockchip_pin_group。 - 组名自动生成(如
功能名_引脚名,如spi0_pd0)。 - 引脚编号、功能、电气参数(如上拉)从设备树解析。
- 每个
- 功能关联:
rockchip,function属性匹配pmx_func的name。- 所有关联的引脚组名称存入
pmx_func.groups数组。
4. 实际应用场景
当外设(如SPI控制器)请求配置 pinctrl_spi0 状态时:
- 驱动通过
rockchip,function = "spi0"找到spi0_func。 - 遍历
spi0_func.groups中的所有引脚组(如spi0_pd0,spi0_pd1)。 - 对每个引脚组调用
pinctrl_set_mux()和pinctrl_set_bias(),完成引脚复用和电气配置。
5. 验证方法
-
查看DTS映射:
确保设备树中的引脚编号(如RK_PD0)和功能(RK_FUNC_SPI0)与硬件手册一致。 -
调试日志:
启用CONFIG_DEBUG_PINCTRL,通过dmesg观察引脚配置过程,例如:pinctrl: group spi0_pd0 set to func SPI0 pinctrl: group spi0_pd1 set to func SPI0 -
代码检查:
在驱动源码中搜索spi0_func和spi0_pd0_group,确认结构体定义与解析逻辑一致。
通过这种方式,RK3588的pinctrl驱动实现了引脚复用的灵活配置,支持外设动态切换功能(如从UART切换到SPI)。
6.关系分析
2.rockchip,pins中的rockchip和pins是表示两个东西,还是一个东西就叫rockchip,pins
在设备树(DTS)语法中,rockchip,pins 是一个复合属性名,由两部分组成:
rockchip:厂商前缀(Vendor Prefix),表示这是瑞芯微(Rockchip)自定义的属性。pins:属性名称(Property Name),表示该属性用于描述引脚(Pin)配置。
具体解析
-
语法规则:
设备树属性名通常采用厂商前缀, 属性名的格式(如rockchip,function、fsl,pinctrl),目的是避免不同厂商的属性命名冲突。 -
rockchip,pins的作用:
该属性定义了一组引脚的复用(Pinmux)和电气配置(如上拉/下拉、驱动强度等)。每个条目(Entry)的格式为:<引脚编号> <功能选择> <电气配置1> <电气配置2> ...
示例解析
以您的代码为例:
rockchip,pins = <
RK_PD0 RK_FUNC_SPI0 &pcfg_pull_none,
RK_PD1 RK_FUNC_SPI0 &pcfg_pull_none,
RK_PD2 RK_FUNC_SPI0 &pcfg_pull_none,
RK_PD3 RK_FUNC_SPI0 &pcfg_pull_none
>;
每个条目的含义:
-
RK_PD0:
引脚编号(Pin Number),表示物理引脚(如 GPIO0 的第 0 号引脚)。 -
RK_FUNC_SPI0:
功能选择(Function Select),表示将引脚配置为 SPI0 的某个信号(如 SCK、MOSI 等)。 -
&pcfg_pull_none:
电气配置(Electrical Configuration),此处表示禁用上拉/下拉电阻(Pull-Up/Pull-Down)。
驱动解析逻辑
在瑞芯微的 pinctrl 驱动中,rockchip,pins 属性会被解析为:
-
引脚组(
struct rockchip_pin_group):
每个条目生成一个引脚组,包含引脚编号、功能选择和电气配置。 -
功能(
struct rockchip_pmx_func):
所有引脚组通过rockchip,function属性关联到一个逻辑功能(如"spi0")。
总结
rockchip,pins是一个整体属性名,由厂商前缀rockchip和属性名pins组成。- 每个条目定义了一个引脚的复用和电气配置,驱动会将其解析为
rockchip_pin_group结构体。 - 所有引脚组通过
rockchip,function属性绑定到一个逻辑功能(如"spi0"),生成rockchip_pmx_func结构体。
3.rockchip_pmx_func中的groups和rockchip_pin_group是什么关系
在瑞芯微RK3588的pinctrl驱动中,struct rockchip_pmx_func 的 groups 成员与 struct rockchip_pin_group 的关系是功能与引脚组的绑定关系,具体如下:
1. 核心关系
rockchip_pmx_func.groups是一个字符串数组,存储了该功能(如SPI0)依赖的所有引脚组的名称(如"spi0_sck","spi0_mosi")。rockchip_pin_group是具体的引脚配置实例,每个实例对应一个物理引脚或一组引脚的复用和电气参数。
驱动通过 groups 中的名称找到对应的 rockchip_pin_group 实例,完成功能配置。
2. 示例解析
假设设备树中定义了一个SPI0功能:
pinctrl_spi0: spi0@0 {
rockchip,pins = <
RK_PD0 RK_FUNC_SPI0 &pcfg_pull_none, /* 引脚组1: SCK */
RK_PD1 RK_FUNC_SPI0 &pcfg_pull_none, /* 引脚组2: MOSI */
RK_PD2 RK_FUNC_SPI0 &pcfg_pull_none, /* 引脚组3: MISO */
RK_PD3 RK_FUNC_SPI0 &pcfg_pull_none /* 引脚组4: CS0 */
>;
rockchip,function = "spi0";
};
生成的 rockchip_pmx_func:
/* 定义所有引脚组名称 */
static const char * const spi0_groups[] = {
"spi0_sck", /* 对应 SCK 引脚组 */
"spi0_mosi", /* 对应 MOSI 引脚组 */
"spi0_miso", /* 对应 MISO 引脚组 */
"spi0_cs0", /* 对应 CS0 引脚组 */
};
/* 生成功能结构体 */
struct rockchip_pmx_func spi0_func = {
.name = "spi0",
.groups = spi0_groups, /* 绑定引脚组名称 */
.num_groups = ARRAY_SIZE(spi0_groups),
};
生成的 rockchip_pin_group 示例(以SCK为例):
struct rockchip_pin_group spi0_sck_group = {
.name = "spi0_sck", /* 与 groups 中的名称匹配 */
.pins = &rk_pd0, /* 物理引脚 PD0 */
.funcs = &rk_func_spi0, /* 复用功能 SPI0 */
.pull = &pull_none, /* 电气配置:无上拉 */
};
3. 配置流程
当外设(如SPI控制器)请求配置 pinctrl_spi0 状态时:
- 驱动通过
rockchip,function = "spi0"找到spi0_func。 - 遍历
spi0_func.groups中的每个引脚组名称(如"spi0_sck")。 - 根据名称找到对应的
rockchip_pin_group实例(如spi0_sck_group)。 - 对每个引脚组调用底层函数(如
rockchip_pin_config()),配置引脚复用和电气参数。
4. 设计意义
- 模块化:
将功能(如SPI0)与引脚组解耦,便于复用引脚组配置(如多个功能共享同一引脚组)。 - 可扩展性:
新增功能只需定义新的rockchip_pmx_func并关联现有引脚组,无需修改底层驱动。 - 动态配置:
支持运行时切换功能(如从UART切换到GPIO),通过替换groups数组实现。
5. 验证方法
-
设备树检查:
确保rockchip,function名称与rockchip_pmx_func.name一致,且rockchip,pins条目生成的引脚组名称存在于groups数组中。 -
驱动调试:
启用CONFIG_DEBUG_PINCTRL,观察日志中引脚组和功能的绑定关系:pinctrl: func spi0 requires groups: spi0_sck, spi0_mosi, spi0_miso, spi0_cs0 pinctrl: group spi0_sck configured for func SPI0
通过这种设计,RK3588的pinctrl驱动实现了引脚复用的高度灵活性和可维护性。


被折叠的 条评论
为什么被折叠?



