概述
gpio_chip注册
int devm_gpiochip_add_data(struct device *dev, struct gpio_chip *chip,
void *data)
{
...
ret = gpiochip_add_data(chip, data);
if (ret < 0) {
devres_free(ptr);
return ret;
}
...
}
EXPORT_SYMBOL_GPL(devm_gpiochip_add_data);
- 实际调用gpiochip_add_data
int gpiochip_add_data(struct gpio_chip *chip, void *data)
{
......
/*
* First: allocate and populate the internal stat container, and
* set up the struct device.
*/
gdev = kzalloc(sizeof(*gdev), GFP_KERNEL);
if (!gdev)
return -ENOMEM;
gdev->dev.bus = &gpio_bus_type;
gdev->chip = chip;
chip->gpiodev = gdev;
if (chip->parent) {
gdev->dev.parent = chip->parent;
gdev->dev.of_node = chip->parent->of_node;
}
......
status = gpiodev_add_to_list(gdev);
if (status) {
spin_unlock_irqrestore(&gpio_lock, flags);
goto err_free_label;
}
......
status = of_gpiochip_add(chip);
......
}
- 创建并初始化gdev,然后调用gpiodev_add_to_list注册到链表
- 调用of_gpiochip_add,初始化设备树相关数据,比如of_xlate函数指针
通过设备树获取gpio流程
int of_get_named_gpio_flags(struct device_node *np, const char *list_name,
int index, enum of_gpio_flags *flags)
{
struct gpio_desc *desc;
desc = of_get_named_gpiod_flags(np, list_name, index, flags);
if (IS_ERR(desc))
return PTR_ERR(desc);
else
return desc_to_gpio(desc);
}
- 通过of_get_named_gpiod_flags得到gpio_desc
- 调用desc_to_gpio得到gpio编号
struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
const char *propname, int index, enum of_gpio_flags *flags)
{
struct of_phandle_args gpiospec;
struct gpio_chip *chip;
struct gpio_desc *desc;
int ret;
ret = of_parse_phandle_with_args(np, propname, "#gpio-cells", index,
&gpiospec);
if (ret) {
pr_debug("%s: can't parse '%s' property of node '%pOF[%d]'n",
__func__, propname, np, index);
return ERR_PTR(ret);
}
chip = of_find_gpiochip_by_xlate(&gpiospec);
if (!chip) {
desc = ERR_PTR(-EPROBE_DEFER);
goto out;
}
desc = of_xlate_and_get_gpiod_flags(chip, &gpiospec, flags);
if (IS_ERR(desc))
goto out;
pr_debug("%s: parsed '%s' property of node '%pOF[%d]' - status (%d)n",
__func__, propname, np, index,
PTR_ERR_OR_ZERO(desc));
out:
of_node_put(gpiospec.np);
return desc;
}
- 调用of_parse_phandle_with_args获取gpio相关参数gpiospec
- 根据gpiospec,调用of_find_gpiochip_by_xlate得到gpiochip
- 能过调用of_xlate_and_get_gpiod_flags得到gpio_desc
static int of_gpiochip_match_node_and_xlate(struct gpio_chip *chip, void *data)
{
struct of_phandle_args *gpiospec = data;
return chip->gpiodev->dev.of_node == gpiospec->np &&
chip->of_xlate &&
chip->of_xlate(chip, gpiospec, NULL) >= 0;
}
static struct gpio_chip *of_find_gpiochip_by_xlate(
struct of_phandle_args *gpiospec)
{
return gpiochip_find(gpiospec, of_gpiochip_match_node_and_xlate);
}
struct gpio_chip *gpiochip_find(void *data,
int (*match)(struct gpio_chip *chip,
void *data))
{
struct gpio_device *gdev;
struct gpio_chip *chip = NULL;
unsigned long flags;
spin_lock_irqsave(&gpio_lock, flags);
list_for_each_entry(gdev, &gpio_devices, list)
if (gdev->chip && match(gdev->chip, data)) {
chip = gdev->chip;
break;
}
spin_unlock_irqrestore(&gpio_lock, flags);
return chip;
}
- of_find_gpiochip_by_xlate调用gpiochip_find,传入参数of_gpiochip_match_node_and_xlate
- gpiochip_find函数中遍历gpio_devices,根据传入的匹配配置of_gpiochip_match_node_and_xlate,得到对应的chip
- of_gpiochip_match_node_and_xlate函数中调用chip->of_xlate函数指针,该指针在of_gpiochip_add赋值为of_gpio_simple_xlate
int of_gpio_simple_xlate(struct gpio_chip *gc,
const struct of_phandle_args *gpiospec, u32 *flags)
{
......
if (flags)
*flags = gpiospec->args[1];
return gpiospec->args[0];
}
- 该函数会得到设备树中指定的gpio flag
- 函数返回值为gpio的编号
static struct gpio_desc *of_xlate_and_get_gpiod_flags(struct gpio_chip *chip,
struct of_phandle_args *gpiospec,
enum of_gpio_flags *flags)
{
int ret;
if (chip->of_gpio_n_cells != gpiospec->args_count)
return ERR_PTR(-EINVAL);
ret = chip->of_xlate(chip, gpiospec, flags);
if (ret < 0)
return ERR_PTR(ret);
return gpiochip_get_desc(chip, ret);
}
- 通过调用chip->of_xlate得到硬件编号
- 调用函数gpiochip_get_desc根据chip和硬件编号得到gpio管脚号
转载于:https://www.cnblogs.com/qzhang1535/p/11573649.html
最后
以上就是犹豫犀牛为你收集整理的kernel - gpio子系统的全部内容,希望文章能够帮你解决kernel - gpio子系统所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复