当前位置: 首页 > news >正文

【linux】regulartor-fixed

作用:创建一个固定的 regulator。一般是一个 GPIO 控制了一路电,只有开(enable) \ 关(disabled)两种操作。

device-tree node

io_vdd_en: regulator-JW5217DFND {compatible = "regulator-fixed";pinctrl-names = "default";pinctrl-0 = <&io_vdd_en_pins_default>;gpios = <&wkup_gpio0 69 GPIO_ACTIVE_HIGH>;regulator-name = "jw5217dfnd";regulator-min-microvolt = <3300000>;regulator-max-microvolt = <3300000>;regulator-always-on;regulator-boot-on;enable-active-high;vin-supply = <&vsys_3v3>;
};

解析:

compatible

compatible = “regulator-fixed”;

固定的 regulator。特点:不能控制电压,只能 enable 和 disabled,没设备用的时候自动关电(disabled)。相关代码如下:

// drivers/regulator/fixed.cstatic const struct regulator_ops fixed_voltage_ops = {
};static const struct regulator_ops fixed_voltage_clkenabled_ops = {.enable = reg_clock_enable,.disable = reg_clock_disable,.is_enabled = reg_clock_is_enabled,
};static const struct of_device_id fixed_of_match[] = {{.compatible = "regulator-fixed",.data = &fixed_voltage_data,},{.compatible = "regulator-fixed-clock",.data = &fixed_clkenable_data,},{},
};static struct platform_driver regulator_fixed_voltage_driver = {.probe		= reg_fixed_voltage_probe,.driver		= {.name		= "reg-fixed-voltage",.of_match_table = of_match_ptr(fixed_of_match),},
};static int reg_fixed_voltage_probe(struct platform_device *pdev)
{struct fixed_voltage_data *drvdata;drvdata = devm_kzalloc(&pdev->dev, sizeof(struct fixed_voltage_data),GFP_KERNEL);...if (drvtype && drvtype->has_enable_clock) {drvdata->desc.ops = &fixed_voltage_clkenabled_ops;drvdata->enable_clock = devm_clk_get(dev, NULL);if (IS_ERR(drvdata->enable_clock)) {dev_err(dev, "Can't get enable-clock from devicetree\n");return -ENOENT;}} else {drvdata->desc.ops = &fixed_voltage_ops;}...}

gpios

gpios = <&wkup_gpio0 69 GPIO_ACTIVE_HIGH>;
控制电的 GPIO。开电时(enabled)的将 GPIO 置为有效电平,关电时(disabled)置为无效电平。相关代码如下:

// drivers/regulator/fixed.cstatic int reg_fixed_voltage_probe(struct platform_device *pdev)
{...cfg.ena_gpiod = gpiod_get_optional(&pdev->dev, NULL, gflags);if (IS_ERR(cfg.ena_gpiod))return PTR_ERR(cfg.ena_gpiod);...
}
// drivers/regulator/core.creg_fixed_voltage_probe-> devm_regulator_register-> regulator_register-> regulator_ena_gpio_requeststatic int regulator_ena_gpio_request(struct regulator_dev *rdev,const struct regulator_config *config)
{struct regulator_enable_gpio *pin, *new_pin;struct gpio_desc *gpiod;gpiod = config->ena_gpiod;new_pin = kzalloc(sizeof(*new_pin), GFP_KERNEL);...pin = new_pin;pin->gpiod = gpiod;rdev->ena_pin = pin;...
}

regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator 最小及最大电压限制。对于 regulator-fixed 无实际意义。
regulator-always-on;
一直开电,防止因其他原因被关电,否则需要在其他驱动中获取此 regulator 来手动控制:regulator_enable() \ regulator_disable()。
当指定了此选项后,会有一个的虚拟设备一直在使用此 regulator,可通过如下命令查看到:

cat /sys/class/regulator/regulator.*/num_users      # 查看有多少个设备在使用此 regulator
cat /sys/class/regulator/regulator.*/state          # 查看此 regulator 的状态:enabled or disabled

regulator-boot-on;
开机时自动上电。注意:若一段时间内无设备在使用此 regulator,则会自动关电(猜测应该和系统低功耗有关),因此必须加上 regulator-always-on。

相关代码如下:

// drivers/regulator/of_regulator.creg_fixed_voltage_probe-> of_get_fixed_voltage_config-> of_get_regulator_init_data-> of_get_regulation_constraintsstatic int of_get_regulation_constraints(struct device *dev,struct device_node *np,struct regulator_init_data **init_data,const struct regulator_desc *desc)
{struct regulation_constraints *constraints = &(*init_data)->constraints;... constraints->boot_on = of_property_read_bool(np, "regulator-boot-on");constraints->always_on = of_property_read_bool(np, "regulator-always-on");...
}
// drivers/regulator/core.creg_fixed_voltage_probe-> devm_regulator_register-> regulator_register-> set_machine_constraintsstatic int set_machine_constraints(struct regulator_dev *rdev)
{...if (rdev->constraints->always_on || rdev->constraints->boot_on) {/* If we want to enable this regulator, make sure that we know* the supplying regulator.*/if (rdev->supply_name && !rdev->supply)return -EPROBE_DEFER;if (rdev->supply) {ret = regulator_enable(rdev->supply);if (ret < 0) {_regulator_put(rdev->supply);rdev->supply = NULL;return ret;}}ret = _regulator_do_enable(rdev);if (ret < 0 && ret != -EINVAL) {rdev_err(rdev, "failed to enable: %pe\n", ERR_PTR(ret));return ret;}if (rdev->constraints->always_on)rdev->use_count++;}...
}
// drivers/regulator/core.creg_fixed_voltage_probe-> devm_regulator_register-> regulator_register-> set_machine_constraints-> _regulator_do_enablestatic int _regulator_do_enable(struct regulator_dev *rdev)
{...if (rdev->ena_pin) {if (!rdev->ena_gpio_state) {ret = regulator_ena_gpio_ctrl(rdev, true);if (ret < 0)return ret;rdev->ena_gpio_state = 1;}} else if (rdev->desc->ops->enable) {ret = rdev->desc->ops->enable(rdev);if (ret < 0)return ret;} else {return -EINVAL;}...
}
// drivers/regulator/core.creg_fixed_voltage_probe-> devm_regulator_register-> regulator_register-> set_machine_constraints-> _regulator_do_enable-> regulator_ena_gpio_ctrlstatic int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable)
{struct regulator_enable_gpio *pin = rdev->ena_pin;if (!pin)return -EINVAL;if (enable) {/* Enable GPIO at initial use */if (pin->enable_count == 0)gpiod_set_value_cansleep(pin->gpiod, 1);pin->enable_count++;} else {if (pin->enable_count > 1) {pin->enable_count--;return 0;}/* Disable GPIO if not used */if (pin->enable_count <= 1) {gpiod_set_value_cansleep(pin->gpiod, 0);pin->enable_count = 0;}}return 0;
}

自动关电的代码:

// drivers/regulator/core.cregulator_init_complete_work_function-> regulator_late_cleanup-> _regulator_do_disable-> regulator_ena_gpio_ctrl-> gpiod_set_value_cansleepstatic void regulator_init_complete_work_function(struct work_struct *work)
{/** Regulators may had failed to resolve their input supplies* when were registered, either because the input supply was* not registered yet or because its parent device was not* bound yet. So attempt to resolve the input supplies for* pending regulators before trying to disable unused ones.*/class_for_each_device(&regulator_class, NULL, NULL,regulator_register_resolve_supply);/* If we have a full configuration then disable any regulators* we have permission to change the status for and which are* not in use or always_on.  This is effectively the default* for DT and ACPI as they have full constraints.*/class_for_each_device(&regulator_class, NULL, NULL,regulator_late_cleanup);
}static DECLARE_DELAYED_WORK(regulator_init_complete_work,regulator_init_complete_work_function);

enable-active-high;
指定 enable GPIO 的有效电平为高(默认为低),仅适用于 regulator。在这里,GPIO 属性中的 GPIO_ACTIVE_xxx 不起作用(建议两者设置成一致,否则会有警告)。相关代码如下:

// drivers/gpio/gpiolib-of.cstatic void of_gpio_flags_quirks(struct device_node *np,const char *propname,enum of_gpio_flags *flags,int index)
{/** Some GPIO fixed regulator quirks.* Note that active low is the default.*/if (IS_ENABLED(CONFIG_REGULATOR) &&(of_device_is_compatible(np, "regulator-fixed") ||of_device_is_compatible(np, "reg-fixed-voltage") ||(!(strcmp(propname, "enable-gpio") &&strcmp(propname, "enable-gpios")) &&of_device_is_compatible(np, "regulator-gpio")))) {bool active_low = !of_property_read_bool(np,"enable-active-high");/** The regulator GPIO handles are specified such that the* presence or absence of "enable-active-high" solely controls* the polarity of the GPIO line. Any phandle flags must* be actively ignored.*/if ((*flags & OF_GPIO_ACTIVE_LOW) && !active_low) {pr_warn("%s GPIO handle specifies active low - ignored\n",of_node_full_name(np));*flags &= ~OF_GPIO_ACTIVE_LOW;}if (active_low)*flags |= OF_GPIO_ACTIVE_LOW;}...
}

http://www.mrgr.cn/news/36058.html

相关文章:

  • Linux 常用操作指令大揭秘(下)
  • 数据库SQLite的使用
  • PET-文件包含-FINISHED
  • 关于我、重生到500年前凭借C语言改变世界科技vlog.18——内存函数
  • CRMEB Pro版v3.1源码全开源+PC端+Uniapp前端+搭建教程
  • 外呼系统的功能都有哪些,怎么去选择?
  • c语言实现:链表创建、插入、删除、翻转
  • p2p、分布式,区块链笔记(OrbitDB.ControlCenter 003) :数据库接口 src\database\index.js
  • 设备程序驱动框架
  • 【Linux】解锁文件描述符奥秘,高效缓存区的实战技巧
  • MySQL: 数据类型介绍
  • 只要孩子感兴趣,学什么都不会白学
  • 如何根据拍立淘API返回值进行商品数据分析
  • USB-CAN的使用说明
  • QT开发模式(二):QML/JS/C++混合编程
  • 初识C#(二)- 流程控制
  • 微积分复习笔记(1):单变量微积分
  • 提取出来的ip与我原本的ip是在同一个区吗
  • Icarus翼星求生教你使用服务器开服
  • 鸿萌数据恢复:如何降低 RAM 故障风险,以避免数据丢失?
  • WebGL与Web Workers
  • 用于扩展 微软Azure OpenAI 服务工作负载的全球预置托管部署
  • USB Micro-A、Micro-B 插头与 Micro-AB、Micro-B 插座,及其引脚定义
  • 一文理解AXI4-lite与AXI4-stream协议
  • GEE APP:基于gee开发一个在线监测Landsat5、7、8的云量面积和百分比的可视化应用
  • 戏曲多多 1.0.6.0 专为电视端设计的戏曲与生活内容APP,同样适用于安卓手机,方便老年人使用