问题描述
pinctrl设置引脚复用失败,没有调用到controller中的set_groups_function函数。
问题定位
- pinctrl如何注册dm节点
- 如何进行设备树中各个设备节点下的复用配置
- 为什么没调用到控制器实现的set_groups_function函数
&gpio0 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&gpioa15_pinctrl>;
};
&pinctrl {
gpioa15 {
gpioa15_pinctrl: gpioa15_grp {
ts,pins = <PB7>;
mux,val = <5>;
function = "gpioa15";
groups = "gpioa15_grp";
};
};
};
pinctrl如何注册dm节点
调用过程:
[uboot/drivers/core/device.c]
int device_probe(struct udevice *dev)
/* Process pinctrl for everything except the root device, and
* continue regardless of the result of pinctrl. Don't process pinctrl
* settings for pinctrl devices since the device may not yet be
* probed.
* */
pinctrl_select_state(dev, "default");
pinctrl_select_state_simple(dev);
/*
* Try full-implemented pinctrl first.
* If it fails or is not implemented, try simple one.
*/
if (pinctrl_select_state_full(dev, statename))
return pinctrl_select_state_simple(dev);
UCLASS_DRIVER(pinctrl) = {
.id = UCLASS_PINCTRL,
.post_bind = pinctrl_post_bind,
.flags = DM_UC_FLAG_SEQ_ALIAS,
.name = "pinctrl",
ret = uclass_pre_probe_device(dev);
ret = uclass_post_probe_device(dev);
uc_drv->post_probe
pinctrl_post_bind
return pinconfig_post_bind(dev);
pinctrl_select_state(dev, "default");
pinctrl_select_state_full(dev, statename)
ret = pinctrl_config_one(config);
ops = pinctrl_get_ops(pctldev);
/* this ops was set by controller */
return ops->set_state(pctldev, config);
};
上面的调用过程是通过加log找出来的,log如下:
__file:drivers/pinctrl/pinctrl-uclass.c __func:pinctrl_select_state_full __line:68
__file:drivers/core/device.c __func:device_probe __line:431
__file:drivers/core/device.c __func:device_probe __line:482
__file:drivers/core/device.c __func:device_probe __line:482
__file:drivers/core/device.c __func:device_probe __line:431
__file:drivers/core/device.c __func:device_probe __line:460
__file:drivers/core/device.c __func:device_probe __line:476
__file:drivers/core/device.c __func:device_probe __line:479
__file:drivers/pinctrl/pinctrl-uclass.c __func:pinctrl_select_state_full __line:68
__file:drivers/core/device.c __func:device_probe __line:431
__file:drivers/core/device.c __func:device_probe __line:482
initr_nand bypass
MMC: __file:drivers/core/device.c __func:device_probe __line:431
__file:drivers/core/device.c __func:device_probe __line:431
__file:drivers/core/device.c __func:device_probe __line:460
__file:drivers/core/device.c __func:device_probe __line:476
__file:drivers/core/device.c __func:device_probe __line:479
__file:drivers/pinctrl/pinctrl-uclass.c __func:pinctrl_select_state_full __line:68
__file:drivers/core/device.c __func:device_probe __line:431
__file:drivers/core/device.c __func:device_probe __line:482
dev 0x00000000bf741ec0, size 0xa0, name mmc@f0512000, ofnode 10c4, mmc@f0512000
__file:drivers/core/device.c __func:device_probe __line:431
__file:drivers/core/device.c __func:device_probe __line:431
__file:drivers/core/device.c __func:device_probe __line:431
__file:drivers/core/device.c __func:device_probe __line:460
__file:drivers/core/device.c __func:device_probe __line:476
__file:drivers/core/device.c __func:device_probe __line:479
__file:drivers/pinctrl/pinctrl-uclass.c __func:pinctrl_select_state_full __line:68
__file:drivers/core/device.c __func:device_probe __line:431
__file:drivers/core/device.c __func:device_probe __line:482
dev 0x00000000bf742260, size 0xa0, name mmc@f0513000, ofnode 1158, mmc@f0513000
__file:drivers/core/device.c __func:device_probe __line:431
看着就是在pinctrl_select_state_full 函数里出了问题:
每次进入pinctrl_select_state_full 函数只能打印到68行,下面的打印出不来,没有调到pinctrl_config_one,所以设备树里注册的gpioa15_pinctrl没有被配置。
/**
* pinctrl_select_state_full() - full implementation of pinctrl_select_state
*
* @dev: peripheral device
* @statename: state name, like "default"
* @return: 0 on success, or negative error code on failure
*/
static int pinctrl_select_state_full(struct udevice *dev, const char *statename)
{
char propname[32]; /* long enough */
const fdt32_t *list;
uint32_t phandle;
struct udevice *config;
int state, size, i, ret;
printf("__file:%s __func:%s __line:%d\n", __FILE__, __func__, __LINE__);
state = dev_read_stringlist_search(dev, "pinctrl-names", statename);
if (state < 0) {
char *end;
/*
* If statename is not found in "pinctrl-names",
* assume statename is just the integer state ID.
*/
state = simple_strtoul(statename, &end, 10);
if (*end)
return -EINVAL;
}
printf("__file:%s __func:%s __line:%d\n", __FILE__, __func__, __LINE__);
snprintf(propname, sizeof(propname), "pinctrl-%d", state);
list = dev_read_prop(dev, propname, &size);
if (!list)
return -EINVAL;
size /= sizeof(*list);
printf("__file:%s __func:%s __line:%d size:%d\n", __FILE__, __func__, __LINE__, size);
for (i = 0; i < size; i++) {
phandle = fdt32_to_cpu(*list++);
ret = uclass_get_device_by_phandle_id(UCLASS_PINCONFIG, phandle,
&config);
if (ret) {
dev_warn(dev, "%s: uclass_get_device_by_phandle_id: err=%d\n",
__func__, ret);
continue;
}
printf("__file:%s __func:%s __line:%d\n", __FILE__, __func__, __LINE__);
ret = pinctrl_config_one(config);
if (ret) {
dev_warn(dev, "%s: pinctrl_config_one: err=%d\n",
__func__, ret);
continue;
}
}
return 0;
}
初步怀疑是69行这里state = dev_read_stringlist_search(dev, "pinctrl-names", statename);
返回的state是个非法值。打印出来看看:
果然都是非法值,-61!!!
pinctrl_probe
reg_base:f0389000
npins : 78
nfuncs : 1
ngroups: 1
func:gpioa15, ngroups = 1
grp_index = 0
group[0] name gpioa15_grp
mux_val: 0x5
npins: 1
15
ts_pinctrl_parse_dt done
ts pinctrl initialized
__file:drivers/core/device.c __func:device_probe __line:523
__file:drivers/pinctrl/pinctrl-uclass.c __func:pinctrl_select_state_full __line:68
__file:drivers/pinctrl/pinctrl-uclass.c __func:pinctrl_select_state_full __line:70 state:-61
__file:drivers/core/device.c __func:device_probe __line:431
__file:drivers/core/device.c __func:device_probe __line:482
__file:drivers/core/device.c __func:device_probe __line:482
__file:drivers/core/device.c __func:device_probe __line:431
__file:drivers/core/device.c __func:device_probe __line:460
__file:drivers/core/device.c __func:device_probe __line:476
__file:drivers/core/device.c __func:device_probe __line:479
__file:drivers/pinctrl/pinctrl-uclass.c __func:pinctrl_select_state_full __line:68
__file:drivers/pinctrl/pinctrl-uclass.c __func:pinctrl_select_state_full __line:70 state:-61
__file:drivers/core/device.c __func:device_probe __line:431
__file:drivers/core/device.c __func:device_probe __line:482
initr_nand bypass
MMC: __file:drivers/core/device.c __func:device_probe __line:431
__file:drivers/core/device.c __func:device_probe __line:431
__file:drivers/core/device.c __func:device_probe __line:460
__file:drivers/core/device.c __func:device_probe __line:476
__file:drivers/core/device.c __func:device_probe __line:479
__file:drivers/pinctrl/pinctrl-uclass.c __func:pinctrl_select_state_full __line:68
__file:drivers/pinctrl/pinctrl-uclass.c __func:pinctrl_select_state_full __line:70 state:-61
__file:drivers/core/device.c __func:device_probe __line:431
__file:drivers/core/device.c __func:device_probe __line:482
dev 0x00000000bf741ec0, size 0xa0, name mmc@f0512000, ofnode 10c4, mmc@f0512000
__file:drivers/core/device.c __func:device_probe __line:431
__file:drivers/core/device.c __func:device_probe __line:431
__file:drivers/core/device.c __func:device_probe __line:431
__file:drivers/core/device.c __func:device_probe __line:460
__file:drivers/core/device.c __func:device_probe __line:476
__file:drivers/core/device.c __func:device_probe __line:479
__file:drivers/pinctrl/pinctrl-uclass.c __func:pinctrl_select_state_full __line:68
__file:drivers/pinctrl/pinctrl-uclass.c __func:pinctrl_select_state_full __line:70 state:-61
__file:drivers/core/device.c __func:device_probe __line:431
__file:drivers/core/device.c __func:device_probe __line:482
uboot的异常宏号码列表
uboot/include/linux/errno.h
#define EBFONT 59 /* Bad font file format */
#define ENOSTR 60 /* Device not a stream */
#define ENODATA 61 /* No data available */
dev_read_stringlist_search的定义:
static inline int dev_read_stringlist_search(const struct udevice *dev,
const char *propname,
const char *string)
{
return ofnode_stringlist_search(dev_ofnode(dev), propname, string);
}
int ofnode_stringlist_search(ofnode node, const char *property,
const char *string)
{
if (ofnode_is_np(node)) {
//maybe bug here?
return of_property_match_string(ofnode_to_np(node),
property, string);
} else {
int ret;
ret = fdt_stringlist_search(gd->fdt_blob,
ofnode_to_offset(node), property,
string);
if (ret == -FDT_ERR_NOTFOUND)
//maybe bug here?
return -ENODATA;
else if (ret < 0)
return -EINVAL;
return ret;
}
}
上面注释中有两个位置可能返回了ENODATA,此处已经开始怀疑是不是设备树描述地有问题了。回头看了一下dts中,pinctrl-names属性是存在的。。。
但是dts虽然有,编译出dtb到后不一定还是存在的,这里通过请教前辈,有哪些fdt的调试手段,前辈推荐了fdt命令,在uboot中可以用于显示设备树信息:
如何使用:
- 通过printenv,找到fdtcontroladdr属性的值,此为fdt所在地址
- 运行fdt fdtcontroladdr
- 运行fdt list
找到gpio和pinctrl节点所在:
可以看到gpio及其pinctrl配置,实际已经配置进去了。
从这里开始,我就觉得不对劲了,只能开始请神了,所以我找了原先的pinctrl mantainer。原先的mantainer说:
uboot中GPIO节点的pinctrl配置,是必须在gpio命令运行完毕之后,才会进行pinctrl的配置的!
恍然大悟,之前没有注意过这个特性,我运行了gpio set 15 1后:
=> gpio set 15 1
__file:drivers/core/device.c __func:device_probe __line:431
__file:drivers/core/device.c __func:device_probe __line:431
__file:drivers/core/device.c __func:device_probe __line:460
__file:drivers/core/device.c __func:device_probe __line:476
__file:drivers/core/device.c __func:device_probe __line:479
dev->name:gpio@f0390000
__file:drivers/pinctrl/pinctrl-uclass.c __func:pinctrl_select_state_full __line:70
fdt_stringlist_search len:8
__file:drivers/pinctrl/pinctrl-uclass.c __func:pinctrl_select_state_full __line:72 state:0 name:default
__file:drivers/pinctrl/pinctrl-uclass.c __func:pinctrl_select_state_full __line:83
__file:drivers/pinctrl/pinctrl-uclass.c __func:pinctrl_select_state_full __line:90 size:1
__file:drivers/core/device.c __func:device_probe __line:431
__file:drivers/core/device.c __func:device_probe __line:431
__file:drivers/core/device.c __func:device_probe __line:431
__file:drivers/core/device.c __func:device_probe __line:460
__file:drivers/core/device.c __func:device_probe __line:476
__file:drivers/core/device.c __func:device_probe __line:479
dev->name:gpioa15
__file:drivers/pinctrl/pinctrl-uclass.c __func:pinctrl_select_state_full __line:70
const fdt_stringlist_search == FDT_ERR_NOTFOUND
__file:drivers/pinctrl/pinctrl-uclass.c __func:pinctrl_select_state_full __line:72 state:-61 name:default
__file:drivers/core/device.c __func:device_probe __line:431
__file:drivers/core/device.c __func:device_probe __line:482
__file:drivers/core/device.c __func:device_probe __line:460
__file:drivers/core/device.c __func:device_probe __line:476
__file:drivers/core/device.c __func:device_probe __line:479
dev->name:gpioa15_grp
__file:drivers/pinctrl/pinctrl-uclass.c __func:pinctrl_select_state_full __line:70
const fdt_stringlist_search == FDT_ERR_NOTFOUND
__file:drivers/pinctrl/pinctrl-uclass.c __func:pinctrl_select_state_full __line:72 state:-61 name:default
__file:drivers/core/device.c __func:device_probe __line:431
__file:drivers/core/device.c __func:device_probe __line:482
__file:drivers/pinctrl/pinctrl-uclass.c __func:pinctrl_select_state_full __line:100
__file:drivers/pinctrl/pinctrl-uclass.c __func:pinctrl_config_one __line:32
__file:drivers/pinctrl/pinctrl-uclass.c __func:pinctrl_config_one __line:34
__file:drivers/pinctrl/pinctrl-uclass.c __func:pinctrl_config_one __line:36
__file:drivers/pinctrl/pinctrl-uclass.c __func:pinctrl_config_one __line:38
__file:drivers/pinctrl/pinctrl-uclass.c __func:pinctrl_config_one __line:44
__file:drivers/pinctrl/pinctrl-uclass.c __func:pinctrl_config_one __line:36
__file:drivers/pinctrl/pinctrl-uclass.c __func:pinctrl_config_one __line:38
__file:drivers/pinctrl/pinctrl-uclass.c __func:pinctrl_config_one __line:44
__file:drivers/pinctrl/pinctrl-uclass.c __func:pinctrl_config_one __line:50
__func:pinctrl_generic_set_state line:340
__func:pinctrl_generic_set_state_subnode line:301
>>>get group[0] gpioa15_grp
__func:pinctrl_generic_set_state_subnode line:326
__func:pinctrl_generic_set_state_one line:250
__func:pinctrl_generic_set_state_one line:261
__func:pinmux_enable_setting line:119
set_mux, function:0, group:0
group name:gpioa15_grp, func name:gpioa15 mux_val:5
pin15, wr 0x00000000f038912c, val 0x50000000
__file:drivers/core/device.c __func:device_probe __line:482
failed to get gpio clock
__file:drivers/core/device.c __func:device_probe __line:431
__file:drivers/core/device.c __func:device_probe __line:431
__file:drivers/core/device.c __func:device_probe __line:431
__file:drivers/core/device.c __func:device_probe __line:460
__file:drivers/core/device.c __func:device_probe __line:476
__file:drivers/core/device.c __func:device_probe __line:479
dev->name:pa
__file:drivers/pinctrl/pinctrl-uclass.c __func:pinctrl_select_state_full __line:70
const fdt_stringlist_search == FDT_ERR_NOTFOUND
__file:drivers/pinctrl/pinctrl-uclass.c __func:pinctrl_select_state_full __line:72 state:-61 name:default
__file:drivers/core/device.c __func:device_probe __line:431
__file:drivers/core/device.c __func:device_probe __line:482
__file:drivers/core/device.c __func:device_probe __line:431
__file:drivers/core/device.c __func:device_probe __line:431
gpio: pin 15 (gpio 15) value is 1
__file:drivers/core/device.c __func:device_probe __line:431
__file:drivers/core/device.c __func:device_probe __line:431
__file:drivers/core/device.c __func:device_probe __line:431
__file:drivers/core/device.c __func:device_probe __line:431
可以看到name:default已经找到了,再使用devmem查看pinctrl对应的B组寄存器值:
=> md 0xf038912c
f038912c: 50000000 00000000 00000000 00000000 ...P............
f038913c: 00000000 00000000 00000000 00000000 ................
f038914c: 00000000 00000000 00000000 00000000 ................
f038915c: 00000000 00000000 00000000 00000000 ................
f038916c: 00000000 00000000 00000000 00000000 ................
f038917c: 00000000 00000000 00000000 00000000 ................
f038918c: 00000000 00000000 00000000 00000000 ................
f038919c: 00000000 00000000 00000000 00000000 ................
f03891ac: 00000000 00000000 00000000 00000000 ................
f03891bc: 00000000 00000000 00000000 00000000 ................
f03891cc: 00000000 00000000 00000000 00000000 ................
f03891dc: 00000000 00000000 00000000 00000000 ................
f03891ec: 00000000 00000000 00000000 00000000 ................
f03891fc: 00000000 000000ff 00000000 00000000 ................
f038920c: 00000000 000000ff 00000000 00000000 ................
f038921c: 00000000 00000000 00000000 00000000 ................
=>
func5配置成功。
TODO:gpio中如何调用到pinctrl配置接口
推荐链接:
https://blog.csdn.net/ZHONGCAI0901/article/details/117986327