@@ -62,10 +62,13 @@ static int bd718xx_buck1234_set_ramp_delay(struct regulator_dev *rdev,
62
62
* is changed. Hence we return -EBUSY for these if voltage is changed
63
63
* when BUCK/LDO is enabled.
64
64
*
65
- * The LDO operation for BD71847 and BD71850 is icurrently unknown.
66
- * It's safer to still assume they can't be changed when enabled.
65
+ * On BD71847, BD71850, ... The LDO voltage can be changed when LDO is
66
+ * enabled. But if voltage is increased the LDO power-good monitoring
67
+ * must be disabled for the duration of changing + 1mS to ensure voltage
68
+ * has reached the higher level before HW does next under voltage detection
69
+ * cycle.
67
70
*/
68
- static int bd718xx_set_voltage_sel_restricted (struct regulator_dev * rdev ,
71
+ static int bd71837_set_voltage_sel_restricted (struct regulator_dev * rdev ,
69
72
unsigned int sel )
70
73
{
71
74
if (regulator_is_enabled_regmap (rdev ))
@@ -74,8 +77,123 @@ static int bd718xx_set_voltage_sel_restricted(struct regulator_dev *rdev,
74
77
return regulator_set_voltage_sel_regmap (rdev , sel );
75
78
}
76
79
80
+ static void voltage_change_done (struct regulator_dev * rdev , unsigned int sel ,
81
+ unsigned int * mask )
82
+ {
83
+ int ret ;
84
+
85
+ if (* mask ) {
86
+ /*
87
+ * Let's allow scheduling as we use I2C anyways. We just need to
88
+ * guarantee minimum of 1ms sleep - it shouldn't matter if we
89
+ * exceed it due to the scheduling.
90
+ */
91
+ msleep (1 );
92
+ /*
93
+ * Note for next hacker. The PWRGOOD should not be masked on
94
+ * BD71847 so we will just unconditionally enable detection
95
+ * when voltage is set.
96
+ * If someone want's to disable PWRGOOD he must implement
97
+ * caching and restoring the old value here. I am not
98
+ * aware of such use-cases so for the sake of the simplicity
99
+ * we just always enable PWRGOOD here.
100
+ */
101
+ ret = regmap_update_bits (rdev -> regmap , BD718XX_REG_MVRFLTMASK2 ,
102
+ * mask , 0 );
103
+ if (ret )
104
+ dev_err (& rdev -> dev ,
105
+ "Failed to re-enable voltage monitoring (%d)\n" ,
106
+ ret );
107
+ }
108
+ }
109
+
110
+ static int voltage_change_prepare (struct regulator_dev * rdev , unsigned int sel ,
111
+ unsigned int * mask )
112
+ {
113
+ int ret ;
114
+
115
+ * mask = 0 ;
116
+ if (regulator_is_enabled_regmap (rdev )) {
117
+ int now , new ;
118
+
119
+ now = rdev -> desc -> ops -> get_voltage_sel (rdev );
120
+ if (now < 0 )
121
+ return now ;
122
+
123
+ now = rdev -> desc -> ops -> list_voltage (rdev , now );
124
+ if (now < 0 )
125
+ return now ;
126
+
127
+ new = rdev -> desc -> ops -> list_voltage (rdev , sel );
128
+ if (new < 0 )
129
+ return new ;
130
+
131
+ /*
132
+ * If we increase LDO voltage when LDO is enabled we need to
133
+ * disable the power-good detection until voltage has reached
134
+ * the new level. According to HW colleagues the maximum time
135
+ * it takes is 1000us. I assume that on systems with light load
136
+ * this might be less - and we could probably use DT to give
137
+ * system specific delay value if performance matters.
138
+ *
139
+ * Well, knowing we use I2C here and can add scheduling delays
140
+ * I don't think it is worth the hassle and I just add fixed
141
+ * 1ms sleep here (and allow scheduling). If this turns out to
142
+ * be a problem we can change it to delay and make the delay
143
+ * time configurable.
144
+ */
145
+ if (new > now ) {
146
+ int ldo_offset = rdev -> desc -> id - BD718XX_LDO1 ;
147
+
148
+ * mask = BD718XX_LDO1_VRMON80 << ldo_offset ;
149
+ ret = regmap_update_bits (rdev -> regmap ,
150
+ BD718XX_REG_MVRFLTMASK2 ,
151
+ * mask , * mask );
152
+ if (ret ) {
153
+ dev_err (& rdev -> dev ,
154
+ "Failed to stop voltage monitoring\n" );
155
+ return ret ;
156
+ }
157
+ }
158
+ }
159
+
160
+ return 0 ;
161
+ }
162
+
163
+ static int bd718xx_set_voltage_sel_restricted (struct regulator_dev * rdev ,
164
+ unsigned int sel )
165
+ {
166
+ int ret ;
167
+ int mask ;
168
+
169
+ ret = voltage_change_prepare (rdev , sel , & mask );
170
+ if (ret )
171
+ return ret ;
172
+
173
+ ret = regulator_set_voltage_sel_regmap (rdev , sel );
174
+ voltage_change_done (rdev , sel , & mask );
175
+
176
+ return ret ;
177
+ }
178
+
77
179
static int bd718xx_set_voltage_sel_pickable_restricted (
78
180
struct regulator_dev * rdev , unsigned int sel )
181
+ {
182
+ int ret ;
183
+ int mask ;
184
+
185
+ ret = voltage_change_prepare (rdev , sel , & mask );
186
+ if (ret )
187
+ return ret ;
188
+
189
+ ret = regulator_set_voltage_sel_pickable_regmap (rdev , sel );
190
+ voltage_change_done (rdev , sel , & mask );
191
+
192
+ return ret ;
193
+ }
194
+
195
+ static int bd71837_set_voltage_sel_pickable_restricted (
196
+ struct regulator_dev * rdev , unsigned int sel )
79
197
{
80
198
if (regulator_is_enabled_regmap (rdev ))
81
199
return - EBUSY ;
@@ -90,6 +208,16 @@ static const struct regulator_ops bd718xx_pickable_range_ldo_ops = {
90
208
.list_voltage = regulator_list_voltage_pickable_linear_range ,
91
209
.set_voltage_sel = bd718xx_set_voltage_sel_pickable_restricted ,
92
210
.get_voltage_sel = regulator_get_voltage_sel_pickable_regmap ,
211
+
212
+ };
213
+
214
+ static const struct regulator_ops bd71837_pickable_range_ldo_ops = {
215
+ .enable = regulator_enable_regmap ,
216
+ .disable = regulator_disable_regmap ,
217
+ .is_enabled = regulator_is_enabled_regmap ,
218
+ .list_voltage = regulator_list_voltage_pickable_linear_range ,
219
+ .set_voltage_sel = bd71837_set_voltage_sel_pickable_restricted ,
220
+ .get_voltage_sel = regulator_get_voltage_sel_pickable_regmap ,
93
221
};
94
222
95
223
static const struct regulator_ops bd718xx_pickable_range_buck_ops = {
@@ -107,11 +235,20 @@ static const struct regulator_ops bd71837_pickable_range_buck_ops = {
107
235
.disable = regulator_disable_regmap ,
108
236
.is_enabled = regulator_is_enabled_regmap ,
109
237
.list_voltage = regulator_list_voltage_pickable_linear_range ,
110
- .set_voltage_sel = bd718xx_set_voltage_sel_pickable_restricted ,
238
+ .set_voltage_sel = bd71837_set_voltage_sel_pickable_restricted ,
111
239
.get_voltage_sel = regulator_get_voltage_sel_pickable_regmap ,
112
240
.set_voltage_time_sel = regulator_set_voltage_time_sel ,
113
241
};
114
242
243
+ static const struct regulator_ops bd71837_ldo_regulator_ops = {
244
+ .enable = regulator_enable_regmap ,
245
+ .disable = regulator_disable_regmap ,
246
+ .is_enabled = regulator_is_enabled_regmap ,
247
+ .list_voltage = regulator_list_voltage_linear_range ,
248
+ .set_voltage_sel = bd71837_set_voltage_sel_restricted ,
249
+ .get_voltage_sel = regulator_get_voltage_sel_regmap ,
250
+ };
251
+
115
252
static const struct regulator_ops bd718xx_ldo_regulator_ops = {
116
253
.enable = regulator_enable_regmap ,
117
254
.disable = regulator_disable_regmap ,
@@ -121,6 +258,15 @@ static const struct regulator_ops bd718xx_ldo_regulator_ops = {
121
258
.get_voltage_sel = regulator_get_voltage_sel_regmap ,
122
259
};
123
260
261
+ static const struct regulator_ops bd71837_ldo_regulator_nolinear_ops = {
262
+ .enable = regulator_enable_regmap ,
263
+ .disable = regulator_disable_regmap ,
264
+ .is_enabled = regulator_is_enabled_regmap ,
265
+ .list_voltage = regulator_list_voltage_table ,
266
+ .set_voltage_sel = bd71837_set_voltage_sel_restricted ,
267
+ .get_voltage_sel = regulator_get_voltage_sel_regmap ,
268
+ };
269
+
124
270
static const struct regulator_ops bd718xx_ldo_regulator_nolinear_ops = {
125
271
.enable = regulator_enable_regmap ,
126
272
.disable = regulator_disable_regmap ,
@@ -145,7 +291,7 @@ static const struct regulator_ops bd71837_buck_regulator_ops = {
145
291
.disable = regulator_disable_regmap ,
146
292
.is_enabled = regulator_is_enabled_regmap ,
147
293
.list_voltage = regulator_list_voltage_linear_range ,
148
- .set_voltage_sel = bd718xx_set_voltage_sel_restricted ,
294
+ .set_voltage_sel = bd71837_set_voltage_sel_restricted ,
149
295
.get_voltage_sel = regulator_get_voltage_sel_regmap ,
150
296
.set_voltage_time_sel = regulator_set_voltage_time_sel ,
151
297
};
@@ -938,7 +1084,7 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = {
938
1084
.of_match = of_match_ptr ("LDO1" ),
939
1085
.regulators_node = of_match_ptr ("regulators" ),
940
1086
.id = BD718XX_LDO1 ,
941
- .ops = & bd718xx_pickable_range_ldo_ops ,
1087
+ .ops = & bd71837_pickable_range_ldo_ops ,
942
1088
.type = REGULATOR_VOLTAGE ,
943
1089
.n_voltages = BD718XX_LDO1_VOLTAGE_NUM ,
944
1090
.linear_ranges = bd718xx_ldo1_volts ,
@@ -964,7 +1110,7 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = {
964
1110
.of_match = of_match_ptr ("LDO2" ),
965
1111
.regulators_node = of_match_ptr ("regulators" ),
966
1112
.id = BD718XX_LDO2 ,
967
- .ops = & bd718xx_ldo_regulator_nolinear_ops ,
1113
+ .ops = & bd71837_ldo_regulator_nolinear_ops ,
968
1114
.type = REGULATOR_VOLTAGE ,
969
1115
.volt_table = & ldo_2_volts [0 ],
970
1116
.vsel_reg = BD718XX_REG_LDO2_VOLT ,
@@ -986,7 +1132,7 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = {
986
1132
.of_match = of_match_ptr ("LDO3" ),
987
1133
.regulators_node = of_match_ptr ("regulators" ),
988
1134
.id = BD718XX_LDO3 ,
989
- .ops = & bd718xx_ldo_regulator_ops ,
1135
+ .ops = & bd71837_ldo_regulator_ops ,
990
1136
.type = REGULATOR_VOLTAGE ,
991
1137
.n_voltages = BD718XX_LDO3_VOLTAGE_NUM ,
992
1138
.linear_ranges = bd718xx_ldo3_volts ,
@@ -1009,7 +1155,7 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = {
1009
1155
.of_match = of_match_ptr ("LDO4" ),
1010
1156
.regulators_node = of_match_ptr ("regulators" ),
1011
1157
.id = BD718XX_LDO4 ,
1012
- .ops = & bd718xx_ldo_regulator_ops ,
1158
+ .ops = & bd71837_ldo_regulator_ops ,
1013
1159
.type = REGULATOR_VOLTAGE ,
1014
1160
.n_voltages = BD718XX_LDO4_VOLTAGE_NUM ,
1015
1161
.linear_ranges = bd718xx_ldo4_volts ,
@@ -1032,7 +1178,7 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = {
1032
1178
.of_match = of_match_ptr ("LDO5" ),
1033
1179
.regulators_node = of_match_ptr ("regulators" ),
1034
1180
.id = BD718XX_LDO5 ,
1035
- .ops = & bd718xx_ldo_regulator_ops ,
1181
+ .ops = & bd71837_ldo_regulator_ops ,
1036
1182
.type = REGULATOR_VOLTAGE ,
1037
1183
.n_voltages = BD71837_LDO5_VOLTAGE_NUM ,
1038
1184
.linear_ranges = bd71837_ldo5_volts ,
@@ -1059,7 +1205,7 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = {
1059
1205
.of_match = of_match_ptr ("LDO6" ),
1060
1206
.regulators_node = of_match_ptr ("regulators" ),
1061
1207
.id = BD718XX_LDO6 ,
1062
- .ops = & bd718xx_ldo_regulator_ops ,
1208
+ .ops = & bd71837_ldo_regulator_ops ,
1063
1209
.type = REGULATOR_VOLTAGE ,
1064
1210
.n_voltages = BD718XX_LDO6_VOLTAGE_NUM ,
1065
1211
.linear_ranges = bd718xx_ldo6_volts ,
@@ -1086,7 +1232,7 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = {
1086
1232
.of_match = of_match_ptr ("LDO7" ),
1087
1233
.regulators_node = of_match_ptr ("regulators" ),
1088
1234
.id = BD718XX_LDO7 ,
1089
- .ops = & bd718xx_ldo_regulator_ops ,
1235
+ .ops = & bd71837_ldo_regulator_ops ,
1090
1236
.type = REGULATOR_VOLTAGE ,
1091
1237
.n_voltages = BD71837_LDO7_VOLTAGE_NUM ,
1092
1238
.linear_ranges = bd71837_ldo7_volts ,
0 commit comments