devm_gpio_request_one 函数

news/2024/10/18 8:20:15/

Linux version: 4.14

Code link: Linux source code (v4.14) - Bootlin


1  devm_gpio_request_one 函数

int devm_gpio_request_one(struct device *dev, unsigned gpio,unsigned long flags, const char *label)
{unsigned *dr;int rc;dr = devres_alloc(devm_gpio_release, sizeof(unsigned), GFP_KERNEL);if (!dr)return -ENOMEM;rc = gpio_request_one(gpio, flags, label);if (rc) {devres_free(dr);return rc;}*dr = gpio;devres_add(dev, dr);return 0;
}
EXPORT_SYMBOL(devm_gpio_request_one);

2  gpio_request_one 函数

int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
{struct gpio_desc *desc;int err;desc = gpio_to_desc(gpio);/* Compatibility: assume unavailable "valid" GPIOs will appear later */if (!desc && gpio_is_valid(gpio))return -EPROBE_DEFER;err = gpiod_request(desc, label);if (err)return err;if (flags & GPIOF_OPEN_DRAIN)set_bit(FLAG_OPEN_DRAIN, &desc->flags);if (flags & GPIOF_OPEN_SOURCE)set_bit(FLAG_OPEN_SOURCE, &desc->flags);if (flags & GPIOF_ACTIVE_LOW)set_bit(FLAG_ACTIVE_LOW, &desc->flags);if (flags & GPIOF_DIR_IN)err = gpiod_direction_input(desc);elseerr = gpiod_direction_output_raw(desc,(flags & GPIOF_INIT_HIGH) ? 1 : 0);if (err)goto free_gpio;if (flags & GPIOF_EXPORT) {err = gpiod_export(desc, flags & GPIOF_EXPORT_CHANGEABLE);if (err)goto free_gpio;}return 0;free_gpio:gpiod_free(desc);return err;
}
EXPORT_SYMBOL_GPL(gpio_request_one);

3 gpiod_request

int gpiod_request(struct gpio_desc *desc, const char *label)
{int status = -EPROBE_DEFER;struct gpio_device *gdev;VALIDATE_DESC(desc);gdev = desc->gdev;if (try_module_get(gdev->owner)) {status = __gpiod_request(desc, label);if (status < 0)module_put(gdev->owner);elseget_device(&gdev->dev);}if (status)gpiod_dbg(desc, "%s: status %d\n", __func__, status);return status;
}

4 gpiod_request

static int __gpiod_request(struct gpio_desc *desc, const char *label)
{struct gpio_chip	*chip = desc->gdev->chip;int			status;unsigned long		flags;spin_lock_irqsave(&gpio_lock, flags);/* NOTE:  gpio_request() can be called in early boot,* before IRQs are enabled, for non-sleeping (SOC) GPIOs.*/if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) {desc_set_label(desc, label ? : "?");status = 0;} else {status = -EBUSY;goto done;}if (chip->request) {/* chip->request may sleep */spin_unlock_irqrestore(&gpio_lock, flags);status = chip->request(chip, gpio_chip_hwgpio(desc));spin_lock_irqsave(&gpio_lock, flags);if (status < 0) {desc_set_label(desc, NULL);clear_bit(FLAG_REQUESTED, &desc->flags);goto done;}}if (chip->get_direction) {/* chip->get_direction may sleep */spin_unlock_irqrestore(&gpio_lock, flags);gpiod_get_direction(desc);spin_lock_irqsave(&gpio_lock, flags);}
done:spin_unlock_irqrestore(&gpio_lock, flags);return status;
}

5 补充:chip->request

(1)zynq 系列芯片中对 gpio_chip 赋值的函数,其中 chip->request 函数赋值为 zynq_gpio_request 函数。

static int zynq_gpio_probe(struct platform_device *pdev)
{int ret, bank_num;struct zynq_gpio *gpio;struct gpio_chip *chip;struct resource *res;const struct of_device_id *match;gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);if (!gpio)return -ENOMEM;match = of_match_node(zynq_gpio_of_match, pdev->dev.of_node);if (!match) {dev_err(&pdev->dev, "of_match_node() failed\n");return -EINVAL;}gpio->p_data = match->data;platform_set_drvdata(pdev, gpio);res = platform_get_resource(pdev, IORESOURCE_MEM, 0);gpio->base_addr = devm_ioremap_resource(&pdev->dev, res);if (IS_ERR(gpio->base_addr))return PTR_ERR(gpio->base_addr);gpio->irq = platform_get_irq(pdev, 0);if (gpio->irq < 0) {dev_err(&pdev->dev, "invalid IRQ\n");return gpio->irq;}/* configure the gpio chip */chip = &gpio->chip;chip->label = gpio->p_data->label;chip->owner = THIS_MODULE;chip->parent = &pdev->dev;chip->get = zynq_gpio_get_value;chip->set = zynq_gpio_set_value;chip->request = zynq_gpio_request;chip->free = zynq_gpio_free;chip->direction_input = zynq_gpio_dir_in;chip->direction_output = zynq_gpio_dir_out;chip->base = -1;chip->ngpio = gpio->p_data->ngpio;/* Retrieve GPIO clock */gpio->clk = devm_clk_get(&pdev->dev, NULL);if (IS_ERR(gpio->clk)) {dev_err(&pdev->dev, "input clock not found.\n");return PTR_ERR(gpio->clk);}ret = clk_prepare_enable(gpio->clk);if (ret) {dev_err(&pdev->dev, "Unable to enable clock.\n");return ret;}pm_runtime_set_active(&pdev->dev);pm_runtime_enable(&pdev->dev);ret = pm_runtime_get_sync(&pdev->dev);if (ret < 0)goto err_pm_dis;/* report a bug if gpio chip registration fails */ret = gpiochip_add_data(chip, gpio);if (ret) {dev_err(&pdev->dev, "Failed to add gpio chip\n");goto err_pm_put;}/* disable interrupts for all banks */for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++)writel_relaxed(ZYNQ_GPIO_IXR_DISABLE_ALL, gpio->base_addr +ZYNQ_GPIO_INTDIS_OFFSET(bank_num));ret = gpiochip_irqchip_add(chip, &zynq_gpio_edge_irqchip, 0,handle_level_irq, IRQ_TYPE_NONE);if (ret) {dev_err(&pdev->dev, "Failed to add irq chip\n");goto err_rm_gpiochip;}gpiochip_set_chained_irqchip(chip, &zynq_gpio_edge_irqchip, gpio->irq,zynq_gpio_irqhandler);pm_runtime_put(&pdev->dev);return 0;err_rm_gpiochip:gpiochip_remove(chip);
err_pm_put:pm_runtime_put(&pdev->dev);
err_pm_dis:pm_runtime_disable(&pdev->dev);clk_disable_unprepare(gpio->clk);return ret;
}

(2) zynq_gpio_request

static int zynq_gpio_request(struct gpio_chip *chip, unsigned int offset)
{int ret;ret = pm_runtime_get_sync(chip->parent);/** If the device is already active pm_runtime_get() will return 1 on* success, but gpio_request still needs to return 0.*/return ret < 0 ? ret : 0;
}

(3)pm_runtime_get_sync

static inline int pm_runtime_get_sync(struct device *dev)
{return __pm_runtime_resume(dev, RPM_GET_PUT);
}

(4)__pm_runtime_resume

int __pm_runtime_resume(struct device *dev, int rpmflags)
{unsigned long flags;int retval;might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe &&dev->power.runtime_status != RPM_ACTIVE);if (rpmflags & RPM_GET_PUT)atomic_inc(&dev->power.usage_count);spin_lock_irqsave(&dev->power.lock, flags);retval = rpm_resume(dev, rpmflags);spin_unlock_irqrestore(&dev->power.lock, flags);return retval;
}
EXPORT_SYMBOL_GPL(__pm_runtime_resume);

对于 rpm_resume 函数,通过查阅资料知道该函数用于激活 dev 设备,具体实现就不去分析了。

小结:gpio_chip 中的 request 函数用来激活设备模块的电源和时钟。

6 总结

int devm_gpio_request_one(struct device *dev, unsigned gpio,unsigned long flags, const char *label)

devm_gpio_request_one 函数用于激活 dev 设备的电源和时钟,设置 gpio 引脚的方向;并且设置相应的 flag。

7 gpio_to_desc 函数

struct gpio_desc *gpio_to_desc(unsigned gpio)
{struct gpio_device *gdev;unsigned long flags;spin_lock_irqsave(&gpio_lock, flags);list_for_each_entry(gdev, &gpio_devices, list) {if (gdev->base <= gpio &&gdev->base + gdev->ngpio > gpio) {spin_unlock_irqrestore(&gpio_lock, flags);return &gdev->descs[gpio - gdev->base];}}spin_unlock_irqrestore(&gpio_lock, flags);if (!gpio_is_valid(gpio))WARN(1, "invalid GPIO %d\n", gpio);return NULL;
}
EXPORT_SYMBOL_GPL(gpio_to_desc);

该函数通过 gpio 索引返回对应 gpio_desc 类型的引脚描述符。


http://www.ppmy.cn/news/64587.html

相关文章

【k8s】离线部署方案二:搭建自主可控的软件仓库和镜像仓库(repo节点)

离线部署的两种方法&#xff1a; 方法一&#xff1a;直接将相关安装依赖包上传到各个节点方法二&#xff1a;搭建自主可控的软件仓库和镜像仓库&#xff08;repo节点&#xff09; 此篇主要记录方法二的实现步骤&#xff0c;参考思路如下&#xff1a; k8S之Centos离线安装_k8s离…

小灰的基金,亏了67W。。。

2022年基金市场有多差&#xff1f;相信大家都有目共睹。小灰的基金在去年也赔得很惨&#xff0c;还每次写过几篇文章&#xff1a; 跌吧&#xff0c;继续跌吧&#xff0c;小灰的基金已亏损64万。。。 基金亏损84万&#xff0c;小灰反手把银行客户经理投诉了 今年是疫情结束的第一…

“裸奔”时代下该如何保护网络隐私

随着信息技术的普及和发展&#xff0c;个人隐私和数据安全问题也日益受到威胁。“裸奔”时代下&#xff0c;我们该如何有效应对网络攻击、数据泄露和隐私侵犯&#xff0c;有哪些实用的技巧和工具可以帮助我们呢。欢迎大家一起讨论保护网络隐私的方法与策略。 一、引言 随着互联…

招投标系统源码 java招投标系统 招投标系统简介 招投标系统功能设计

项目说明 随着公司的快速发展&#xff0c;企业人员和经营规模不断壮大&#xff0c;公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境&#xff0c;最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范&#xff0c;以及…

4.HIVE函数

1.hive函数 1.1 空值替换 两个输入&#xff1a;nvl(col,default_num) : 如果colum不为null&#xff0c;返回col.否则返回default_num 多个输入&#xff1a;coalesce(col1, col2, col3, ....) &#xff1a;从左到右找第一个不为null的值 例如&#xff1a;求所有员工的平均薪…

MySQL基础(十)创建和管理表

1. 基础知识 1.1 一条数据存储的过程 存储数据是处理数据的第一步。只有正确地把数据存储起来&#xff0c;我们才能进行有效的处理和分析。否则&#xff0c;只能是一团乱麻&#xff0c;无从下手。 那么&#xff0c;怎样才能把用户各种经营相关的、纷繁复杂的数据&#xff0c…

【LLM】LangChain基础使用(构建LLM应用)

note LangChain应用开发框架&#xff0c;支持python和typescript语言&#xff1b;可以帮助生成prompt模板&#xff0c;并通过代理充当其他组件&#xff08;如提示模板、其他大语言模型、外部数据和其他工具&#xff09;的中央接口。LangChain可以直接与 OpenAI 的 text-davinc…

unity航点寻径

一、游戏框架&#xff1a;设置了六个路标&#xff0c;角色会在这六个路标之间一次移动&#xff0c;当移动到第六个路标后又会返回第一个路标&#xff0c;继续依次移动。 road&#xff1a; 道路&#xff0c;由五个立方体组成 sign&#xff1a;路标&#xff0c;由六个胶囊组成 …