aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/regulator/anatop-regulator.c76
1 files changed, 74 insertions, 2 deletions
diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c
index 862e63e451d0..dff120a38e40 100644
--- a/drivers/regulator/anatop-regulator.c
+++ b/drivers/regulator/anatop-regulator.c
@@ -34,6 +34,8 @@
34#define LDO_RAMP_UP_UNIT_IN_CYCLES 64 /* 64 cycles per step */ 34#define LDO_RAMP_UP_UNIT_IN_CYCLES 64 /* 64 cycles per step */
35#define LDO_RAMP_UP_FREQ_IN_MHZ 24 /* cycle based on 24M OSC */ 35#define LDO_RAMP_UP_FREQ_IN_MHZ 24 /* cycle based on 24M OSC */
36 36
37#define LDO_POWER_GATE 0x00
38
37struct anatop_regulator { 39struct anatop_regulator {
38 const char *name; 40 const char *name;
39 u32 control_reg; 41 u32 control_reg;
@@ -48,6 +50,7 @@ struct anatop_regulator {
48 int max_voltage; 50 int max_voltage;
49 struct regulator_desc rdesc; 51 struct regulator_desc rdesc;
50 struct regulator_init_data *initdata; 52 struct regulator_init_data *initdata;
53 int sel;
51}; 54};
52 55
53static int anatop_regmap_set_voltage_sel(struct regulator_dev *reg, 56static int anatop_regmap_set_voltage_sel(struct regulator_dev *reg,
@@ -97,14 +100,68 @@ static int anatop_regmap_get_voltage_sel(struct regulator_dev *reg)
97 return regulator_get_voltage_sel_regmap(reg); 100 return regulator_get_voltage_sel_regmap(reg);
98} 101}
99 102
103static int anatop_regmap_enable(struct regulator_dev *reg)
104{
105 struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
106
107 return regulator_set_voltage_sel_regmap(reg, anatop_reg->sel);
108}
109
110static int anatop_regmap_disable(struct regulator_dev *reg)
111{
112 return regulator_set_voltage_sel_regmap(reg, LDO_POWER_GATE);
113}
114
115static int anatop_regmap_is_enabled(struct regulator_dev *reg)
116{
117 return regulator_get_voltage_sel_regmap(reg) != LDO_POWER_GATE;
118}
119
120static int anatop_regmap_core_set_voltage_sel(struct regulator_dev *reg,
121 unsigned selector)
122{
123 struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
124 int ret;
125
126 if (!anatop_regmap_is_enabled(reg)) {
127 anatop_reg->sel = selector;
128 return 0;
129 }
130
131 ret = regulator_set_voltage_sel_regmap(reg, selector);
132 if (!ret)
133 anatop_reg->sel = selector;
134 return ret;
135}
136
137static int anatop_regmap_core_get_voltage_sel(struct regulator_dev *reg)
138{
139 struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
140
141 if (!anatop_regmap_is_enabled(reg))
142 return anatop_reg->sel;
143
144 return regulator_get_voltage_sel_regmap(reg);
145}
146
100static struct regulator_ops anatop_rops = { 147static struct regulator_ops anatop_rops = {
101 .set_voltage_sel = anatop_regmap_set_voltage_sel, 148 .set_voltage_sel = anatop_regmap_set_voltage_sel,
102 .set_voltage_time_sel = anatop_regmap_set_voltage_time_sel,
103 .get_voltage_sel = anatop_regmap_get_voltage_sel, 149 .get_voltage_sel = anatop_regmap_get_voltage_sel,
104 .list_voltage = regulator_list_voltage_linear, 150 .list_voltage = regulator_list_voltage_linear,
105 .map_voltage = regulator_map_voltage_linear, 151 .map_voltage = regulator_map_voltage_linear,
106}; 152};
107 153
154static struct regulator_ops anatop_core_rops = {
155 .enable = anatop_regmap_enable,
156 .disable = anatop_regmap_disable,
157 .is_enabled = anatop_regmap_is_enabled,
158 .set_voltage_sel = anatop_regmap_core_set_voltage_sel,
159 .set_voltage_time_sel = anatop_regmap_set_voltage_time_sel,
160 .get_voltage_sel = anatop_regmap_core_get_voltage_sel,
161 .list_voltage = regulator_list_voltage_linear,
162 .map_voltage = regulator_map_voltage_linear,
163};
164
108static int anatop_regulator_probe(struct platform_device *pdev) 165static int anatop_regulator_probe(struct platform_device *pdev)
109{ 166{
110 struct device *dev = &pdev->dev; 167 struct device *dev = &pdev->dev;
@@ -116,6 +173,7 @@ static int anatop_regulator_probe(struct platform_device *pdev)
116 struct regulator_init_data *initdata; 173 struct regulator_init_data *initdata;
117 struct regulator_config config = { }; 174 struct regulator_config config = { };
118 int ret = 0; 175 int ret = 0;
176 u32 val;
119 177
120 initdata = of_get_regulator_init_data(dev, np); 178 initdata = of_get_regulator_init_data(dev, np);
121 sreg = devm_kzalloc(dev, sizeof(*sreg), GFP_KERNEL); 179 sreg = devm_kzalloc(dev, sizeof(*sreg), GFP_KERNEL);
@@ -125,7 +183,6 @@ static int anatop_regulator_probe(struct platform_device *pdev)
125 sreg->name = of_get_property(np, "regulator-name", NULL); 183 sreg->name = of_get_property(np, "regulator-name", NULL);
126 rdesc = &sreg->rdesc; 184 rdesc = &sreg->rdesc;
127 rdesc->name = sreg->name; 185 rdesc->name = sreg->name;
128 rdesc->ops = &anatop_rops;
129 rdesc->type = REGULATOR_VOLTAGE; 186 rdesc->type = REGULATOR_VOLTAGE;
130 rdesc->owner = THIS_MODULE; 187 rdesc->owner = THIS_MODULE;
131 188
@@ -197,6 +254,21 @@ static int anatop_regulator_probe(struct platform_device *pdev)
197 config.of_node = pdev->dev.of_node; 254 config.of_node = pdev->dev.of_node;
198 config.regmap = sreg->anatop; 255 config.regmap = sreg->anatop;
199 256
257 /* Only core regulators have the ramp up delay configuration. */
258 if (sreg->control_reg && sreg->delay_bit_width) {
259 rdesc->ops = &anatop_core_rops;
260
261 ret = regmap_read(config.regmap, rdesc->vsel_reg, &val);
262 if (ret) {
263 dev_err(dev, "failed to read initial state\n");
264 return ret;
265 }
266
267 sreg->sel = (val & rdesc->vsel_mask) >> sreg->vol_bit_shift;
268 } else {
269 rdesc->ops = &anatop_rops;
270 }
271
200 /* register regulator */ 272 /* register regulator */
201 rdev = devm_regulator_register(dev, rdesc, &config); 273 rdev = devm_regulator_register(dev, rdesc, &config);
202 if (IS_ERR(rdev)) { 274 if (IS_ERR(rdev)) {