diff options
-rw-r--r-- | drivers/regulator/anatop-regulator.c | 76 |
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 | |||
37 | struct anatop_regulator { | 39 | struct 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 | ||
53 | static int anatop_regmap_set_voltage_sel(struct regulator_dev *reg, | 56 | static 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 | ||
103 | static 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 | |||
110 | static int anatop_regmap_disable(struct regulator_dev *reg) | ||
111 | { | ||
112 | return regulator_set_voltage_sel_regmap(reg, LDO_POWER_GATE); | ||
113 | } | ||
114 | |||
115 | static int anatop_regmap_is_enabled(struct regulator_dev *reg) | ||
116 | { | ||
117 | return regulator_get_voltage_sel_regmap(reg) != LDO_POWER_GATE; | ||
118 | } | ||
119 | |||
120 | static 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 | |||
137 | static 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 | |||
100 | static struct regulator_ops anatop_rops = { | 147 | static 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 | ||
154 | static 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 | |||
108 | static int anatop_regulator_probe(struct platform_device *pdev) | 165 | static 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)) { |