Loading Documentation/devicetree/bindings/regulator/qcom,refgen.txt 0 → 100644 +38 −0 Original line number Diff line number Diff line Qualcomm Technologies, Inc. REFGEN Regulator Some Qualcomm Technologies, Inc. SoCs utilize reference bias generators for various internal PHY blocks. These are called REFGENs. Supported properties: - compatible Usage: required Value type: <string> Definition: Must be "qcom,refgen-regulator". - reg Usage: required Value type: <prop-encoded-array> Definition: Address and size of the REFGEN registers. - regulator-name Usage: required Value type: <string> Definition: Specifies the name for this REFGEN regulator. - regulator-enable-ramp-delay Usage: optional Value type: <u32> Definition: REFGEN enable time in microseconds. - parent-supply Usage: optional Value type: <phandle> Definition: phandle to the parent supply/regulator node if one exists. Example: refgen-regulator@ff1000 { compatible = "qcom,refgen-regulator"; reg = <0xff1000 0x60>; regulator-name = "refgen"; }; arch/arm64/boot/dts/qcom/sdm855-regulator.dtsi +48 −0 Original line number Diff line number Diff line Loading @@ -764,4 +764,52 @@ qcom,init-mode = <RPMH_REGULATOR_MODE_AUTO>; }; }; rpmh-regulator-smpf2 { compatible = "qcom,rpmh-xob-regulator"; mboxes = <&apps_rsc 0>; qcom,resource-name = "smpf2"; pm8009_s2: regulator-pm8009-s2 { regulator-name = "pm8009_s2"; qcom,set = <RPMH_REGULATOR_SET_ALL>; regulator-min-microvolt = <2856000>; regulator-max-microvolt = <2856000>; }; }; rpmh-regulator-ldof2 { compatible = "qcom,rpmh-xob-regulator"; mboxes = <&apps_rsc 0>; qcom,resource-name = "ldof2"; pm8009_l2: regulator-pm8009-l2 { regulator-name = "pm8009_l2"; qcom,set = <RPMH_REGULATOR_SET_ALL>; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <1200000>; }; }; rpmh-regulator-ldof5 { compatible = "qcom,rpmh-xob-regulator"; mboxes = <&apps_rsc 0>; qcom,resource-name = "ldof5"; pm8009_l5: regulator-pm8009-l5 { regulator-name = "pm8009_l5"; qcom,set = <RPMH_REGULATOR_SET_ALL>; regulator-min-microvolt = <2800000>; regulator-max-microvolt = <2800000>; }; }; rpmh-regulator-ldof6 { compatible = "qcom,rpmh-xob-regulator"; mboxes = <&apps_rsc 0>; qcom,resource-name = "ldof6"; pm8009_l6: regulator-pm8009-l6 { regulator-name = "pm8009_l6"; qcom,set = <RPMH_REGULATOR_SET_ALL>; regulator-min-microvolt = <2856000>; regulator-max-microvolt = <2856000>; }; }; }; drivers/regulator/Kconfig +9 −0 Original line number Diff line number Diff line Loading @@ -997,6 +997,15 @@ config REGULATOR_WM8994 This driver provides support for the voltage regulators on the WM8994 CODEC. config REGULATOR_REFGEN tristate "Qualcomm Technologies, Inc. REFGEN regulator driver" depends on OF help This driver supports control of the REFGEN reference bias generator block found on some Qualcomm Technologies Inc. SoCs. A REFGEN it used by various PHY blocks found inside of the SoC. It supports enable/disable control. config REGULATOR_RPMH tristate "Qualcomm Technologies, Inc. RPMh regulator driver" depends on OF Loading drivers/regulator/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -126,6 +126,7 @@ obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o obj-$(CONFIG_REGULATOR_WM8994) += wm8994-regulator.o obj-$(CONFIG_REGULATOR_REFGEN) += refgen.o obj-$(CONFIG_REGULATOR_RPM_SMD) += rpm-smd-regulator.o obj-$(CONFIG_REGULATOR_SPM) += spm-regulator.o obj-$(CONFIG_REGULATOR_RPMH) += rpmh-regulator.o Loading drivers/regulator/refgen.c 0 → 100644 +182 −0 Original line number Diff line number Diff line /* * Copyright (c) 2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include <linux/bitops.h> #include <linux/err.h> #include <linux/io.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/types.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> #include <linux/regulator/of_regulator.h> #define REFGEN_REG_BIAS_EN 0x08 #define REFGEN_BIAS_EN_MASK GENMASK(2, 0) #define REFGEN_BIAS_EN_ENABLE 0x7 #define REFGEN_BIAS_EN_DISABLE 0x6 #define REFGEN_REG_BG_CTRL 0x14 #define REFGEN_BG_CTRL_MASK GENMASK(2, 0) #define REFGEN_BG_CTRL_ENABLE 0x6 #define REFGEN_BG_CTRL_DISABLE 0x4 struct refgen { struct regulator_desc rdesc; struct regulator_dev *rdev; void __iomem *addr; }; static int refgen_enable(struct regulator_dev *rdev) { struct refgen *vreg = rdev_get_drvdata(rdev); writel_relaxed(REFGEN_BG_CTRL_ENABLE, vreg->addr + REFGEN_REG_BG_CTRL); writel_relaxed(REFGEN_BIAS_EN_ENABLE, vreg->addr + REFGEN_REG_BIAS_EN); return 0; } static int refgen_disable(struct regulator_dev *rdev) { struct refgen *vreg = rdev_get_drvdata(rdev); writel_relaxed(REFGEN_BIAS_EN_DISABLE, vreg->addr + REFGEN_REG_BIAS_EN); writel_relaxed(REFGEN_BG_CTRL_DISABLE, vreg->addr + REFGEN_REG_BG_CTRL); return 0; } static int refgen_is_enabled(struct regulator_dev *rdev) { struct refgen *vreg = rdev_get_drvdata(rdev); u32 val; val = readl_relaxed(vreg->addr + REFGEN_REG_BG_CTRL); if ((val & REFGEN_BG_CTRL_MASK) != REFGEN_BG_CTRL_ENABLE) return 0; val = readl_relaxed(vreg->addr + REFGEN_REG_BIAS_EN); if ((val & REFGEN_BIAS_EN_MASK) != REFGEN_BIAS_EN_ENABLE) return 0; return 1; } static struct regulator_ops refgen_ops = { .enable = refgen_enable, .disable = refgen_disable, .is_enabled = refgen_is_enabled, }; static int refgen_probe(struct platform_device *pdev) { struct regulator_config config = {}; struct regulator_init_data *init_data = NULL; struct device *dev = &pdev->dev; struct regulator_desc *rdesc; struct resource *res; struct refgen *vreg; int rc; vreg = devm_kzalloc(dev, sizeof(*vreg), GFP_KERNEL); if (!vreg) return -ENOMEM; if (!dev->of_node) { dev_err(dev, "%s: device tree node missing\n", __func__); return -ENODEV; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res || !res->start) { dev_err(dev, "reg address is missing\n"); return -EINVAL; } vreg->addr = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(vreg->addr)) { rc = PTR_ERR(vreg->addr); dev_err(dev, "ioremap failed, rc=%d\n", rc); return rc; } init_data = of_get_regulator_init_data(dev, dev->of_node, &vreg->rdesc); if (!init_data) return -ENOMEM; if (init_data->constraints.name == NULL) { dev_err(dev, "%s: regulator-name not specified\n", __func__); return -EINVAL; } if (of_get_property(dev->of_node, "parent-supply", NULL)) init_data->supply_regulator = "parent"; rdesc = &vreg->rdesc; rdesc->name = "refgen"; rdesc->ops = &refgen_ops; rdesc->id = pdev->id; rdesc->owner = THIS_MODULE; rdesc->type = REGULATOR_VOLTAGE; config.dev = dev; config.init_data = init_data; config.driver_data = vreg; config.of_node = dev->of_node; vreg->rdev = devm_regulator_register(dev, rdesc, &config); if (IS_ERR(vreg->rdev)) { rc = PTR_ERR(vreg->rdev); if (rc != -EPROBE_DEFER) dev_err(dev, "%s: regulator register failed\n", __func__); return rc; } return 0; } static const struct of_device_id refgen_match_table[] = { { .compatible = "qcom,refgen-regulator", }, {} }; static struct platform_driver refgen_driver = { .probe = refgen_probe, .driver = { .name = "qcom,refgen-regulator", .owner = THIS_MODULE, .of_match_table = refgen_match_table, }, }; static int __init refgen_init(void) { return platform_driver_register(&refgen_driver); } arch_initcall(refgen_init); static void __exit refgen_exit(void) { platform_driver_unregister(&refgen_driver); } module_exit(refgen_exit); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("refgen regulator driver"); Loading
Documentation/devicetree/bindings/regulator/qcom,refgen.txt 0 → 100644 +38 −0 Original line number Diff line number Diff line Qualcomm Technologies, Inc. REFGEN Regulator Some Qualcomm Technologies, Inc. SoCs utilize reference bias generators for various internal PHY blocks. These are called REFGENs. Supported properties: - compatible Usage: required Value type: <string> Definition: Must be "qcom,refgen-regulator". - reg Usage: required Value type: <prop-encoded-array> Definition: Address and size of the REFGEN registers. - regulator-name Usage: required Value type: <string> Definition: Specifies the name for this REFGEN regulator. - regulator-enable-ramp-delay Usage: optional Value type: <u32> Definition: REFGEN enable time in microseconds. - parent-supply Usage: optional Value type: <phandle> Definition: phandle to the parent supply/regulator node if one exists. Example: refgen-regulator@ff1000 { compatible = "qcom,refgen-regulator"; reg = <0xff1000 0x60>; regulator-name = "refgen"; };
arch/arm64/boot/dts/qcom/sdm855-regulator.dtsi +48 −0 Original line number Diff line number Diff line Loading @@ -764,4 +764,52 @@ qcom,init-mode = <RPMH_REGULATOR_MODE_AUTO>; }; }; rpmh-regulator-smpf2 { compatible = "qcom,rpmh-xob-regulator"; mboxes = <&apps_rsc 0>; qcom,resource-name = "smpf2"; pm8009_s2: regulator-pm8009-s2 { regulator-name = "pm8009_s2"; qcom,set = <RPMH_REGULATOR_SET_ALL>; regulator-min-microvolt = <2856000>; regulator-max-microvolt = <2856000>; }; }; rpmh-regulator-ldof2 { compatible = "qcom,rpmh-xob-regulator"; mboxes = <&apps_rsc 0>; qcom,resource-name = "ldof2"; pm8009_l2: regulator-pm8009-l2 { regulator-name = "pm8009_l2"; qcom,set = <RPMH_REGULATOR_SET_ALL>; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <1200000>; }; }; rpmh-regulator-ldof5 { compatible = "qcom,rpmh-xob-regulator"; mboxes = <&apps_rsc 0>; qcom,resource-name = "ldof5"; pm8009_l5: regulator-pm8009-l5 { regulator-name = "pm8009_l5"; qcom,set = <RPMH_REGULATOR_SET_ALL>; regulator-min-microvolt = <2800000>; regulator-max-microvolt = <2800000>; }; }; rpmh-regulator-ldof6 { compatible = "qcom,rpmh-xob-regulator"; mboxes = <&apps_rsc 0>; qcom,resource-name = "ldof6"; pm8009_l6: regulator-pm8009-l6 { regulator-name = "pm8009_l6"; qcom,set = <RPMH_REGULATOR_SET_ALL>; regulator-min-microvolt = <2856000>; regulator-max-microvolt = <2856000>; }; }; };
drivers/regulator/Kconfig +9 −0 Original line number Diff line number Diff line Loading @@ -997,6 +997,15 @@ config REGULATOR_WM8994 This driver provides support for the voltage regulators on the WM8994 CODEC. config REGULATOR_REFGEN tristate "Qualcomm Technologies, Inc. REFGEN regulator driver" depends on OF help This driver supports control of the REFGEN reference bias generator block found on some Qualcomm Technologies Inc. SoCs. A REFGEN it used by various PHY blocks found inside of the SoC. It supports enable/disable control. config REGULATOR_RPMH tristate "Qualcomm Technologies, Inc. RPMh regulator driver" depends on OF Loading
drivers/regulator/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -126,6 +126,7 @@ obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o obj-$(CONFIG_REGULATOR_WM8994) += wm8994-regulator.o obj-$(CONFIG_REGULATOR_REFGEN) += refgen.o obj-$(CONFIG_REGULATOR_RPM_SMD) += rpm-smd-regulator.o obj-$(CONFIG_REGULATOR_SPM) += spm-regulator.o obj-$(CONFIG_REGULATOR_RPMH) += rpmh-regulator.o Loading
drivers/regulator/refgen.c 0 → 100644 +182 −0 Original line number Diff line number Diff line /* * Copyright (c) 2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include <linux/bitops.h> #include <linux/err.h> #include <linux/io.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/types.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> #include <linux/regulator/of_regulator.h> #define REFGEN_REG_BIAS_EN 0x08 #define REFGEN_BIAS_EN_MASK GENMASK(2, 0) #define REFGEN_BIAS_EN_ENABLE 0x7 #define REFGEN_BIAS_EN_DISABLE 0x6 #define REFGEN_REG_BG_CTRL 0x14 #define REFGEN_BG_CTRL_MASK GENMASK(2, 0) #define REFGEN_BG_CTRL_ENABLE 0x6 #define REFGEN_BG_CTRL_DISABLE 0x4 struct refgen { struct regulator_desc rdesc; struct regulator_dev *rdev; void __iomem *addr; }; static int refgen_enable(struct regulator_dev *rdev) { struct refgen *vreg = rdev_get_drvdata(rdev); writel_relaxed(REFGEN_BG_CTRL_ENABLE, vreg->addr + REFGEN_REG_BG_CTRL); writel_relaxed(REFGEN_BIAS_EN_ENABLE, vreg->addr + REFGEN_REG_BIAS_EN); return 0; } static int refgen_disable(struct regulator_dev *rdev) { struct refgen *vreg = rdev_get_drvdata(rdev); writel_relaxed(REFGEN_BIAS_EN_DISABLE, vreg->addr + REFGEN_REG_BIAS_EN); writel_relaxed(REFGEN_BG_CTRL_DISABLE, vreg->addr + REFGEN_REG_BG_CTRL); return 0; } static int refgen_is_enabled(struct regulator_dev *rdev) { struct refgen *vreg = rdev_get_drvdata(rdev); u32 val; val = readl_relaxed(vreg->addr + REFGEN_REG_BG_CTRL); if ((val & REFGEN_BG_CTRL_MASK) != REFGEN_BG_CTRL_ENABLE) return 0; val = readl_relaxed(vreg->addr + REFGEN_REG_BIAS_EN); if ((val & REFGEN_BIAS_EN_MASK) != REFGEN_BIAS_EN_ENABLE) return 0; return 1; } static struct regulator_ops refgen_ops = { .enable = refgen_enable, .disable = refgen_disable, .is_enabled = refgen_is_enabled, }; static int refgen_probe(struct platform_device *pdev) { struct regulator_config config = {}; struct regulator_init_data *init_data = NULL; struct device *dev = &pdev->dev; struct regulator_desc *rdesc; struct resource *res; struct refgen *vreg; int rc; vreg = devm_kzalloc(dev, sizeof(*vreg), GFP_KERNEL); if (!vreg) return -ENOMEM; if (!dev->of_node) { dev_err(dev, "%s: device tree node missing\n", __func__); return -ENODEV; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res || !res->start) { dev_err(dev, "reg address is missing\n"); return -EINVAL; } vreg->addr = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(vreg->addr)) { rc = PTR_ERR(vreg->addr); dev_err(dev, "ioremap failed, rc=%d\n", rc); return rc; } init_data = of_get_regulator_init_data(dev, dev->of_node, &vreg->rdesc); if (!init_data) return -ENOMEM; if (init_data->constraints.name == NULL) { dev_err(dev, "%s: regulator-name not specified\n", __func__); return -EINVAL; } if (of_get_property(dev->of_node, "parent-supply", NULL)) init_data->supply_regulator = "parent"; rdesc = &vreg->rdesc; rdesc->name = "refgen"; rdesc->ops = &refgen_ops; rdesc->id = pdev->id; rdesc->owner = THIS_MODULE; rdesc->type = REGULATOR_VOLTAGE; config.dev = dev; config.init_data = init_data; config.driver_data = vreg; config.of_node = dev->of_node; vreg->rdev = devm_regulator_register(dev, rdesc, &config); if (IS_ERR(vreg->rdev)) { rc = PTR_ERR(vreg->rdev); if (rc != -EPROBE_DEFER) dev_err(dev, "%s: regulator register failed\n", __func__); return rc; } return 0; } static const struct of_device_id refgen_match_table[] = { { .compatible = "qcom,refgen-regulator", }, {} }; static struct platform_driver refgen_driver = { .probe = refgen_probe, .driver = { .name = "qcom,refgen-regulator", .owner = THIS_MODULE, .of_match_table = refgen_match_table, }, }; static int __init refgen_init(void) { return platform_driver_register(&refgen_driver); } arch_initcall(refgen_init); static void __exit refgen_exit(void) { platform_driver_unregister(&refgen_driver); } module_exit(refgen_exit); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("refgen regulator driver");