xref: /openbmc/linux/drivers/regulator/qcom-refgen-regulator.c (revision b181f7029bd71238ac2754ce7052dffd69432085)
17cbfbe23SKonrad Dybcio // SPDX-License-Identifier: GPL-2.0-only
27cbfbe23SKonrad Dybcio // Copyright (c) 2017, 2019-2020, The Linux Foundation. All rights reserved.
37cbfbe23SKonrad Dybcio // Copyright (c) 2023, Linaro Limited
47cbfbe23SKonrad Dybcio 
57cbfbe23SKonrad Dybcio #include <linux/bitfield.h>
67cbfbe23SKonrad Dybcio #include <linux/module.h>
77cbfbe23SKonrad Dybcio #include <linux/of.h>
87cbfbe23SKonrad Dybcio #include <linux/platform_device.h>
97cbfbe23SKonrad Dybcio #include <linux/regmap.h>
107cbfbe23SKonrad Dybcio #include <linux/regulator/driver.h>
117cbfbe23SKonrad Dybcio #include <linux/regulator/machine.h>
127cbfbe23SKonrad Dybcio #include <linux/regulator/of_regulator.h>
137cbfbe23SKonrad Dybcio 
147cbfbe23SKonrad Dybcio #define REFGEN_REG_BIAS_EN		0x08
157cbfbe23SKonrad Dybcio #define REFGEN_BIAS_EN_MASK		GENMASK(2, 0)
167cbfbe23SKonrad Dybcio  #define REFGEN_BIAS_EN_ENABLE		0x7
177cbfbe23SKonrad Dybcio  #define REFGEN_BIAS_EN_DISABLE		0x6
187cbfbe23SKonrad Dybcio 
197cbfbe23SKonrad Dybcio #define REFGEN_REG_BG_CTRL		0x14
207cbfbe23SKonrad Dybcio #define REFGEN_BG_CTRL_MASK		GENMASK(2, 1)
217cbfbe23SKonrad Dybcio  #define REFGEN_BG_CTRL_ENABLE		0x3
227cbfbe23SKonrad Dybcio  #define REFGEN_BG_CTRL_DISABLE		0x2
237cbfbe23SKonrad Dybcio 
247cbfbe23SKonrad Dybcio #define REFGEN_REG_PWRDWN_CTRL5		0x80
257cbfbe23SKonrad Dybcio #define REFGEN_PWRDWN_CTRL5_MASK	BIT(0)
267cbfbe23SKonrad Dybcio  #define REFGEN_PWRDWN_CTRL5_ENABLE	0x1
277cbfbe23SKonrad Dybcio 
qcom_sdm845_refgen_enable(struct regulator_dev * rdev)287cbfbe23SKonrad Dybcio static int qcom_sdm845_refgen_enable(struct regulator_dev *rdev)
297cbfbe23SKonrad Dybcio {
307cbfbe23SKonrad Dybcio 	regmap_update_bits(rdev->regmap, REFGEN_REG_BG_CTRL, REFGEN_BG_CTRL_MASK,
317cbfbe23SKonrad Dybcio 			   FIELD_PREP(REFGEN_BG_CTRL_MASK, REFGEN_BG_CTRL_ENABLE));
327cbfbe23SKonrad Dybcio 
337cbfbe23SKonrad Dybcio 	regmap_write(rdev->regmap, REFGEN_REG_BIAS_EN,
347cbfbe23SKonrad Dybcio 		     FIELD_PREP(REFGEN_BIAS_EN_MASK, REFGEN_BIAS_EN_ENABLE));
357cbfbe23SKonrad Dybcio 
367cbfbe23SKonrad Dybcio 	return 0;
377cbfbe23SKonrad Dybcio }
387cbfbe23SKonrad Dybcio 
qcom_sdm845_refgen_disable(struct regulator_dev * rdev)397cbfbe23SKonrad Dybcio static int qcom_sdm845_refgen_disable(struct regulator_dev *rdev)
407cbfbe23SKonrad Dybcio {
417cbfbe23SKonrad Dybcio 	regmap_write(rdev->regmap, REFGEN_REG_BIAS_EN,
427cbfbe23SKonrad Dybcio 		     FIELD_PREP(REFGEN_BIAS_EN_MASK, REFGEN_BIAS_EN_DISABLE));
437cbfbe23SKonrad Dybcio 
447cbfbe23SKonrad Dybcio 	regmap_update_bits(rdev->regmap, REFGEN_REG_BG_CTRL, REFGEN_BG_CTRL_MASK,
457cbfbe23SKonrad Dybcio 			   FIELD_PREP(REFGEN_BG_CTRL_MASK, REFGEN_BG_CTRL_DISABLE));
467cbfbe23SKonrad Dybcio 
477cbfbe23SKonrad Dybcio 	return 0;
487cbfbe23SKonrad Dybcio }
497cbfbe23SKonrad Dybcio 
qcom_sdm845_refgen_is_enabled(struct regulator_dev * rdev)507cbfbe23SKonrad Dybcio static int qcom_sdm845_refgen_is_enabled(struct regulator_dev *rdev)
517cbfbe23SKonrad Dybcio {
527cbfbe23SKonrad Dybcio 	u32 val;
537cbfbe23SKonrad Dybcio 
547cbfbe23SKonrad Dybcio 	regmap_read(rdev->regmap, REFGEN_REG_BG_CTRL, &val);
557cbfbe23SKonrad Dybcio 	if (FIELD_GET(REFGEN_BG_CTRL_MASK, val) != REFGEN_BG_CTRL_ENABLE)
567cbfbe23SKonrad Dybcio 		return 0;
577cbfbe23SKonrad Dybcio 
587cbfbe23SKonrad Dybcio 	regmap_read(rdev->regmap, REFGEN_REG_BIAS_EN, &val);
597cbfbe23SKonrad Dybcio 	if (FIELD_GET(REFGEN_BIAS_EN_MASK, val) != REFGEN_BIAS_EN_ENABLE)
607cbfbe23SKonrad Dybcio 		return 0;
617cbfbe23SKonrad Dybcio 
627cbfbe23SKonrad Dybcio 	return 1;
637cbfbe23SKonrad Dybcio }
647cbfbe23SKonrad Dybcio 
657cbfbe23SKonrad Dybcio static struct regulator_desc sdm845_refgen_desc = {
667cbfbe23SKonrad Dybcio 	.enable_time = 5,
677cbfbe23SKonrad Dybcio 	.name = "refgen",
687cbfbe23SKonrad Dybcio 	.owner = THIS_MODULE,
697cbfbe23SKonrad Dybcio 	.type = REGULATOR_VOLTAGE,
707cbfbe23SKonrad Dybcio 	.ops = &(const struct regulator_ops) {
717cbfbe23SKonrad Dybcio 		.enable		= qcom_sdm845_refgen_enable,
727cbfbe23SKonrad Dybcio 		.disable	= qcom_sdm845_refgen_disable,
737cbfbe23SKonrad Dybcio 		.is_enabled	= qcom_sdm845_refgen_is_enabled,
747cbfbe23SKonrad Dybcio 	},
757cbfbe23SKonrad Dybcio };
767cbfbe23SKonrad Dybcio 
777cbfbe23SKonrad Dybcio static struct regulator_desc sm8250_refgen_desc = {
787cbfbe23SKonrad Dybcio 	.enable_reg = REFGEN_REG_PWRDWN_CTRL5,
797cbfbe23SKonrad Dybcio 	.enable_mask = REFGEN_PWRDWN_CTRL5_MASK,
807cbfbe23SKonrad Dybcio 	.enable_val = REFGEN_PWRDWN_CTRL5_ENABLE,
817cbfbe23SKonrad Dybcio 	.disable_val = 0,
827cbfbe23SKonrad Dybcio 	.enable_time = 5,
837cbfbe23SKonrad Dybcio 	.name = "refgen",
847cbfbe23SKonrad Dybcio 	.owner = THIS_MODULE,
857cbfbe23SKonrad Dybcio 	.type = REGULATOR_VOLTAGE,
867cbfbe23SKonrad Dybcio 	.ops = &(const struct regulator_ops) {
877cbfbe23SKonrad Dybcio 		.enable		= regulator_enable_regmap,
887cbfbe23SKonrad Dybcio 		.disable	= regulator_disable_regmap,
897cbfbe23SKonrad Dybcio 		.is_enabled	= regulator_is_enabled_regmap,
907cbfbe23SKonrad Dybcio 	},
917cbfbe23SKonrad Dybcio };
927cbfbe23SKonrad Dybcio 
937cbfbe23SKonrad Dybcio static const struct regmap_config qcom_refgen_regmap_config = {
947cbfbe23SKonrad Dybcio 	.reg_bits = 32,
957cbfbe23SKonrad Dybcio 	.reg_stride = 4,
967cbfbe23SKonrad Dybcio 	.val_bits = 32,
977cbfbe23SKonrad Dybcio 	.fast_io = true,
987cbfbe23SKonrad Dybcio };
997cbfbe23SKonrad Dybcio 
qcom_refgen_probe(struct platform_device * pdev)1007cbfbe23SKonrad Dybcio static int qcom_refgen_probe(struct platform_device *pdev)
1017cbfbe23SKonrad Dybcio {
1027cbfbe23SKonrad Dybcio 	struct regulator_init_data *init_data;
1037cbfbe23SKonrad Dybcio 	struct regulator_config config = {};
1047cbfbe23SKonrad Dybcio 	const struct regulator_desc *rdesc;
1057cbfbe23SKonrad Dybcio 	struct device *dev = &pdev->dev;
1067cbfbe23SKonrad Dybcio 	struct regulator_dev *rdev;
1077cbfbe23SKonrad Dybcio 	struct regmap *regmap;
1087cbfbe23SKonrad Dybcio 	void __iomem *base;
1097cbfbe23SKonrad Dybcio 
1107cbfbe23SKonrad Dybcio 	rdesc = of_device_get_match_data(dev);
1117cbfbe23SKonrad Dybcio 	if (!rdesc)
1127cbfbe23SKonrad Dybcio 		return -ENODATA;
1137cbfbe23SKonrad Dybcio 
1147cbfbe23SKonrad Dybcio 	base = devm_platform_ioremap_resource(pdev, 0);
1157cbfbe23SKonrad Dybcio 	if (IS_ERR(base))
1167cbfbe23SKonrad Dybcio 		return PTR_ERR(base);
1177cbfbe23SKonrad Dybcio 
1187cbfbe23SKonrad Dybcio 	regmap = devm_regmap_init_mmio(dev, base, &qcom_refgen_regmap_config);
1197cbfbe23SKonrad Dybcio 	if (IS_ERR(regmap))
1207cbfbe23SKonrad Dybcio 		return PTR_ERR(regmap);
1217cbfbe23SKonrad Dybcio 
1227cbfbe23SKonrad Dybcio 	init_data = of_get_regulator_init_data(dev, dev->of_node, rdesc);
1237cbfbe23SKonrad Dybcio 	if (!init_data)
1247cbfbe23SKonrad Dybcio 		return -ENOMEM;
1257cbfbe23SKonrad Dybcio 
1267cbfbe23SKonrad Dybcio 	config.dev = dev;
1277cbfbe23SKonrad Dybcio 	config.init_data = init_data;
1287cbfbe23SKonrad Dybcio 	config.of_node = dev->of_node;
1297cbfbe23SKonrad Dybcio 	config.regmap = regmap;
1307cbfbe23SKonrad Dybcio 
1317cbfbe23SKonrad Dybcio 	rdev = devm_regulator_register(dev, rdesc, &config);
1327cbfbe23SKonrad Dybcio 	if (IS_ERR(rdev))
1337cbfbe23SKonrad Dybcio 		return PTR_ERR(rdev);
1347cbfbe23SKonrad Dybcio 
1357cbfbe23SKonrad Dybcio 	return 0;
1367cbfbe23SKonrad Dybcio }
1377cbfbe23SKonrad Dybcio 
1387cbfbe23SKonrad Dybcio static const struct of_device_id qcom_refgen_match_table[] = {
1397cbfbe23SKonrad Dybcio 	{ .compatible = "qcom,sdm845-refgen-regulator", .data = &sdm845_refgen_desc },
1407cbfbe23SKonrad Dybcio 	{ .compatible = "qcom,sm8250-refgen-regulator", .data = &sm8250_refgen_desc },
1417cbfbe23SKonrad Dybcio 	{ }
1427cbfbe23SKonrad Dybcio };
143*5c0b06dcSKrzysztof Kozlowski MODULE_DEVICE_TABLE(of, qcom_refgen_match_table);
1447cbfbe23SKonrad Dybcio 
1457cbfbe23SKonrad Dybcio static struct platform_driver qcom_refgen_driver = {
1467cbfbe23SKonrad Dybcio 	.probe = qcom_refgen_probe,
1477cbfbe23SKonrad Dybcio 	.driver = {
1487cbfbe23SKonrad Dybcio 		.name = "qcom-refgen-regulator",
1497cbfbe23SKonrad Dybcio 		.of_match_table = qcom_refgen_match_table,
1507cbfbe23SKonrad Dybcio 	},
1517cbfbe23SKonrad Dybcio };
1527cbfbe23SKonrad Dybcio module_platform_driver(qcom_refgen_driver);
1537cbfbe23SKonrad Dybcio 
1547cbfbe23SKonrad Dybcio MODULE_LICENSE("GPL");
1557cbfbe23SKonrad Dybcio MODULE_DESCRIPTION("Qualcomm REFGEN regulator driver");
156