1 // SPDX-License-Identifier: GPL-2.0-only
2 // Copyright (c) 2017, 2019-2020, The Linux Foundation. All rights reserved.
3 // Copyright (c) 2023, Linaro Limited
5 #include <linux/bitfield.h>
6 #include <linux/module.h>
8 #include <linux/platform_device.h>
9 #include <linux/regmap.h>
10 #include <linux/regulator/driver.h>
11 #include <linux/regulator/machine.h>
12 #include <linux/regulator/of_regulator.h>
14 #define REFGEN_REG_BIAS_EN 0x08
15 #define REFGEN_BIAS_EN_MASK GENMASK(2, 0)
16 #define REFGEN_BIAS_EN_ENABLE 0x7
17 #define REFGEN_BIAS_EN_DISABLE 0x6
19 #define REFGEN_REG_BG_CTRL 0x14
20 #define REFGEN_BG_CTRL_MASK GENMASK(2, 1)
21 #define REFGEN_BG_CTRL_ENABLE 0x3
22 #define REFGEN_BG_CTRL_DISABLE 0x2
24 #define REFGEN_REG_PWRDWN_CTRL5 0x80
25 #define REFGEN_PWRDWN_CTRL5_MASK BIT(0)
26 #define REFGEN_PWRDWN_CTRL5_ENABLE 0x1
28 static int qcom_sdm845_refgen_enable(struct regulator_dev
*rdev
)
30 regmap_update_bits(rdev
->regmap
, REFGEN_REG_BG_CTRL
, REFGEN_BG_CTRL_MASK
,
31 FIELD_PREP(REFGEN_BG_CTRL_MASK
, REFGEN_BG_CTRL_ENABLE
));
33 regmap_write(rdev
->regmap
, REFGEN_REG_BIAS_EN
,
34 FIELD_PREP(REFGEN_BIAS_EN_MASK
, REFGEN_BIAS_EN_ENABLE
));
39 static int qcom_sdm845_refgen_disable(struct regulator_dev
*rdev
)
41 regmap_write(rdev
->regmap
, REFGEN_REG_BIAS_EN
,
42 FIELD_PREP(REFGEN_BIAS_EN_MASK
, REFGEN_BIAS_EN_DISABLE
));
44 regmap_update_bits(rdev
->regmap
, REFGEN_REG_BG_CTRL
, REFGEN_BG_CTRL_MASK
,
45 FIELD_PREP(REFGEN_BG_CTRL_MASK
, REFGEN_BG_CTRL_DISABLE
));
50 static int qcom_sdm845_refgen_is_enabled(struct regulator_dev
*rdev
)
54 regmap_read(rdev
->regmap
, REFGEN_REG_BG_CTRL
, &val
);
55 if (FIELD_GET(REFGEN_BG_CTRL_MASK
, val
) != REFGEN_BG_CTRL_ENABLE
)
58 regmap_read(rdev
->regmap
, REFGEN_REG_BIAS_EN
, &val
);
59 if (FIELD_GET(REFGEN_BIAS_EN_MASK
, val
) != REFGEN_BIAS_EN_ENABLE
)
65 static const struct regulator_desc sdm845_refgen_desc
= {
69 .type
= REGULATOR_VOLTAGE
,
70 .ops
= &(const struct regulator_ops
) {
71 .enable
= qcom_sdm845_refgen_enable
,
72 .disable
= qcom_sdm845_refgen_disable
,
73 .is_enabled
= qcom_sdm845_refgen_is_enabled
,
77 static const struct regulator_desc sm8250_refgen_desc
= {
78 .enable_reg
= REFGEN_REG_PWRDWN_CTRL5
,
79 .enable_mask
= REFGEN_PWRDWN_CTRL5_MASK
,
80 .enable_val
= REFGEN_PWRDWN_CTRL5_ENABLE
,
85 .type
= REGULATOR_VOLTAGE
,
86 .ops
= &(const struct regulator_ops
) {
87 .enable
= regulator_enable_regmap
,
88 .disable
= regulator_disable_regmap
,
89 .is_enabled
= regulator_is_enabled_regmap
,
93 static const struct regmap_config qcom_refgen_regmap_config
= {
100 static int qcom_refgen_probe(struct platform_device
*pdev
)
102 struct regulator_init_data
*init_data
;
103 struct regulator_config config
= {};
104 const struct regulator_desc
*rdesc
;
105 struct device
*dev
= &pdev
->dev
;
106 struct regulator_dev
*rdev
;
107 struct regmap
*regmap
;
110 rdesc
= of_device_get_match_data(dev
);
114 base
= devm_platform_ioremap_resource(pdev
, 0);
116 return PTR_ERR(base
);
118 regmap
= devm_regmap_init_mmio(dev
, base
, &qcom_refgen_regmap_config
);
120 return PTR_ERR(regmap
);
122 init_data
= of_get_regulator_init_data(dev
, dev
->of_node
, rdesc
);
127 config
.init_data
= init_data
;
128 config
.of_node
= dev
->of_node
;
129 config
.regmap
= regmap
;
131 rdev
= devm_regulator_register(dev
, rdesc
, &config
);
133 return PTR_ERR(rdev
);
138 static const struct of_device_id qcom_refgen_match_table
[] = {
139 { .compatible
= "qcom,sdm845-refgen-regulator", .data
= &sdm845_refgen_desc
},
140 { .compatible
= "qcom,sm8250-refgen-regulator", .data
= &sm8250_refgen_desc
},
143 MODULE_DEVICE_TABLE(of
, qcom_refgen_match_table
);
145 static struct platform_driver qcom_refgen_driver
= {
146 .probe
= qcom_refgen_probe
,
148 .name
= "qcom-refgen-regulator",
149 .of_match_table
= qcom_refgen_match_table
,
152 module_platform_driver(qcom_refgen_driver
);
154 MODULE_LICENSE("GPL");
155 MODULE_DESCRIPTION("Qualcomm REFGEN regulator driver");