Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

regulator: Add devres version of of_regulator_get_optional()

There are existing uses for a devres version of of_regulator_get_optional()
in power domain drivers. On MediaTek platforms, power domains may have
regulator supplies tied to them. The driver currently tries to use
devm_regulator_get() to not have to manage the lifecycle, but ends up
doing it in a very hacky way by replacing the device node of the power
domain controller device to the device node of the power domain that is
currently being registered, getting the supply, and reverting the device
node.

Provide a better API so that the hack can be replaced.

Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
Link: https://patch.msgid.link/20240925093807.1026949-3-wenst@chromium.org
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Chen-Yu Tsai and committed by
Mark Brown
36ec3f43 5441b697

+68 -8
+39
drivers/regulator/devres.c
··· 749 749 return ptr; 750 750 } 751 751 EXPORT_SYMBOL_GPL(devm_regulator_irq_helper); 752 + 753 + #if IS_ENABLED(CONFIG_OF) 754 + static struct regulator *_devm_of_regulator_get(struct device *dev, struct device_node *node, 755 + const char *id, int get_type) 756 + { 757 + struct regulator **ptr, *regulator; 758 + 759 + ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL); 760 + if (!ptr) 761 + return ERR_PTR(-ENOMEM); 762 + 763 + regulator = _of_regulator_get(dev, node, id, get_type); 764 + if (!IS_ERR(regulator)) { 765 + *ptr = regulator; 766 + devres_add(dev, ptr); 767 + } else { 768 + devres_free(ptr); 769 + } 770 + 771 + return regulator; 772 + } 773 + 774 + /** 775 + * devm_of_regulator_get_optional - Resource managed of_regulator_get_optional() 776 + * @dev: device used for dev_printk() messages and resource lifetime management 777 + * @node: device node for regulator "consumer" 778 + * @id: supply name or regulator ID. 779 + * 780 + * Managed regulator_get_optional(). Regulators returned from this 781 + * function are automatically regulator_put() on driver detach. See 782 + * of_regulator_get_optional() for more information. 783 + */ 784 + struct regulator *devm_of_regulator_get_optional(struct device *dev, struct device_node *node, 785 + const char *id) 786 + { 787 + return _devm_of_regulator_get(dev, node, id, OPTIONAL_GET); 788 + } 789 + EXPORT_SYMBOL_GPL(devm_of_regulator_get_optional); 790 + #endif
+10 -6
drivers/regulator/internal.h
··· 65 65 return container_of(dev, struct regulator_dev, dev); 66 66 } 67 67 68 + enum regulator_get_type { 69 + NORMAL_GET, 70 + EXCLUSIVE_GET, 71 + OPTIONAL_GET, 72 + MAX_GET_TYPE 73 + }; 74 + 68 75 #ifdef CONFIG_OF 69 76 struct regulator_dev *of_regulator_dev_lookup(struct device *dev, 70 77 struct device_node *np, ··· 80 73 const struct regulator_desc *desc, 81 74 struct regulator_config *config, 82 75 struct device_node **node); 76 + 77 + struct regulator *_of_regulator_get(struct device *dev, struct device_node *node, 78 + const char *id, enum regulator_get_type get_type); 83 79 84 80 struct regulator_dev *of_parse_coupled_regulator(struct regulator_dev *rdev, 85 81 int index); ··· 126 116 } 127 117 128 118 #endif 129 - enum regulator_get_type { 130 - NORMAL_GET, 131 - EXCLUSIVE_GET, 132 - OPTIONAL_GET, 133 - MAX_GET_TYPE 134 - }; 135 119 136 120 int _regulator_get_common_check(struct device *dev, const char *id, 137 121 enum regulator_get_type get_type);
+2 -2
drivers/regulator/of_regulator.c
··· 668 668 return ERR_PTR(-ENODEV); 669 669 } 670 670 671 - static struct regulator *_of_regulator_get(struct device *dev, struct device_node *node, 672 - const char *id, enum regulator_get_type get_type) 671 + struct regulator *_of_regulator_get(struct device *dev, struct device_node *node, 672 + const char *id, enum regulator_get_type get_type) 673 673 { 674 674 struct regulator_dev *r; 675 675 int ret;
+17
include/linux/regulator/consumer.h
··· 172 172 struct regulator *__must_check of_regulator_get_optional(struct device *dev, 173 173 struct device_node *node, 174 174 const char *id); 175 + struct regulator *__must_check devm_of_regulator_get_optional(struct device *dev, 176 + struct device_node *node, 177 + const char *id); 175 178 #else 176 179 static inline struct regulator *__must_check of_regulator_get_optional(struct device *dev, 177 180 struct device_node *node, 178 181 const char *id) 182 + { 183 + return ERR_PTR(-ENODEV); 184 + } 185 + 186 + static inline struct regulator *__must_check devm_of_regulator_get_optional(struct device *dev, 187 + struct device_node *node, 188 + const char *id) 179 189 { 180 190 return ERR_PTR(-ENODEV); 181 191 } ··· 376 366 static inline struct regulator *__must_check of_regulator_get_optional(struct device *dev, 377 367 struct device_node *node, 378 368 const char *id) 369 + { 370 + return ERR_PTR(-ENODEV); 371 + } 372 + 373 + static inline struct regulator *__must_check devm_of_regulator_get_optional(struct device *dev, 374 + struct device_node *node, 375 + const char *id) 379 376 { 380 377 return ERR_PTR(-ENODEV); 381 378 }