20
20
#include <linux/of.h>
21
21
#include <linux/of_device.h>
22
22
#include <linux/pwm.h>
23
+ #include <linux/gpio/consumer.h>
24
+
25
+ struct pwm_continuous_reg_data {
26
+ unsigned int min_uV_dutycycle ;
27
+ unsigned int max_uV_dutycycle ;
28
+ unsigned int dutycycle_unit ;
29
+ };
23
30
24
31
struct pwm_regulator_data {
25
32
/* Shared */
@@ -28,6 +35,9 @@ struct pwm_regulator_data {
28
35
/* Voltage table */
29
36
struct pwm_voltages * duty_cycle_table ;
30
37
38
+ /* Continuous mode info */
39
+ struct pwm_continuous_reg_data continuous ;
40
+
31
41
/* regulator descriptor */
32
42
struct regulator_desc desc ;
33
43
@@ -36,8 +46,8 @@ struct pwm_regulator_data {
36
46
37
47
int state ;
38
48
39
- /* Continuous voltage */
40
- int volt_uV ;
49
+ /* Enable GPIO */
50
+ struct gpio_desc * enb_gpio ;
41
51
};
42
52
43
53
struct pwm_voltages {
@@ -48,27 +58,46 @@ struct pwm_voltages {
48
58
/**
49
59
* Voltage table call-backs
50
60
*/
61
+ static void pwm_regulator_init_state (struct regulator_dev * rdev )
62
+ {
63
+ struct pwm_regulator_data * drvdata = rdev_get_drvdata (rdev );
64
+ struct pwm_state pwm_state ;
65
+ unsigned int dutycycle ;
66
+ int i ;
67
+
68
+ pwm_get_state (drvdata -> pwm , & pwm_state );
69
+ dutycycle = pwm_get_relative_duty_cycle (& pwm_state , 100 );
70
+
71
+ for (i = 0 ; i < rdev -> desc -> n_voltages ; i ++ ) {
72
+ if (dutycycle == drvdata -> duty_cycle_table [i ].dutycycle ) {
73
+ drvdata -> state = i ;
74
+ return ;
75
+ }
76
+ }
77
+ }
78
+
51
79
static int pwm_regulator_get_voltage_sel (struct regulator_dev * rdev )
52
80
{
53
81
struct pwm_regulator_data * drvdata = rdev_get_drvdata (rdev );
54
82
83
+ if (drvdata -> state < 0 )
84
+ pwm_regulator_init_state (rdev );
85
+
55
86
return drvdata -> state ;
56
87
}
57
88
58
89
static int pwm_regulator_set_voltage_sel (struct regulator_dev * rdev ,
59
90
unsigned selector )
60
91
{
61
92
struct pwm_regulator_data * drvdata = rdev_get_drvdata (rdev );
62
- struct pwm_args pargs ;
63
- int dutycycle ;
93
+ struct pwm_state pstate ;
64
94
int ret ;
65
95
66
- pwm_get_args (drvdata -> pwm , & pargs );
67
-
68
- dutycycle = (pargs .period *
69
- drvdata -> duty_cycle_table [selector ].dutycycle ) / 100 ;
96
+ pwm_init_state (drvdata -> pwm , & pstate );
97
+ pwm_set_relative_duty_cycle (& pstate ,
98
+ drvdata -> duty_cycle_table [selector ].dutycycle , 100 );
70
99
71
- ret = pwm_config (drvdata -> pwm , dutycycle , pargs . period );
100
+ ret = pwm_apply_state (drvdata -> pwm , & pstate );
72
101
if (ret ) {
73
102
dev_err (& rdev -> dev , "Failed to configure PWM: %d\n" , ret );
74
103
return ret ;
@@ -94,6 +123,9 @@ static int pwm_regulator_enable(struct regulator_dev *dev)
94
123
{
95
124
struct pwm_regulator_data * drvdata = rdev_get_drvdata (dev );
96
125
126
+ if (drvdata -> enb_gpio )
127
+ gpiod_set_value_cansleep (drvdata -> enb_gpio , 1 );
128
+
97
129
return pwm_enable (drvdata -> pwm );
98
130
}
99
131
@@ -103,71 +135,110 @@ static int pwm_regulator_disable(struct regulator_dev *dev)
103
135
104
136
pwm_disable (drvdata -> pwm );
105
137
138
+ if (drvdata -> enb_gpio )
139
+ gpiod_set_value_cansleep (drvdata -> enb_gpio , 0 );
140
+
106
141
return 0 ;
107
142
}
108
143
109
144
static int pwm_regulator_is_enabled (struct regulator_dev * dev )
110
145
{
111
146
struct pwm_regulator_data * drvdata = rdev_get_drvdata (dev );
112
147
148
+ if (drvdata -> enb_gpio && !gpiod_get_value_cansleep (drvdata -> enb_gpio ))
149
+ return false;
150
+
113
151
return pwm_is_enabled (drvdata -> pwm );
114
152
}
115
153
116
154
static int pwm_regulator_get_voltage (struct regulator_dev * rdev )
117
155
{
118
156
struct pwm_regulator_data * drvdata = rdev_get_drvdata (rdev );
157
+ unsigned int min_uV_duty = drvdata -> continuous .min_uV_dutycycle ;
158
+ unsigned int max_uV_duty = drvdata -> continuous .max_uV_dutycycle ;
159
+ unsigned int duty_unit = drvdata -> continuous .dutycycle_unit ;
160
+ int min_uV = rdev -> constraints -> min_uV ;
161
+ int max_uV = rdev -> constraints -> max_uV ;
162
+ int diff_uV = max_uV - min_uV ;
163
+ struct pwm_state pstate ;
164
+ unsigned int diff_duty ;
165
+ unsigned int voltage ;
166
+
167
+ pwm_get_state (drvdata -> pwm , & pstate );
168
+
169
+ voltage = pwm_get_relative_duty_cycle (& pstate , duty_unit );
170
+
171
+ /*
172
+ * The dutycycle for min_uV might be greater than the one for max_uV.
173
+ * This is happening when the user needs an inversed polarity, but the
174
+ * PWM device does not support inversing it in hardware.
175
+ */
176
+ if (max_uV_duty < min_uV_duty ) {
177
+ voltage = min_uV_duty - voltage ;
178
+ diff_duty = min_uV_duty - max_uV_duty ;
179
+ } else {
180
+ voltage = voltage - min_uV_duty ;
181
+ diff_duty = max_uV_duty - min_uV_duty ;
182
+ }
183
+
184
+ voltage = DIV_ROUND_CLOSEST_ULL ((u64 )voltage * diff_uV , diff_duty );
119
185
120
- return drvdata -> volt_uV ;
186
+ return voltage + min_uV ;
121
187
}
122
188
123
189
static int pwm_regulator_set_voltage (struct regulator_dev * rdev ,
124
- int min_uV , int max_uV ,
125
- unsigned * selector )
190
+ int req_min_uV , int req_max_uV ,
191
+ unsigned int * selector )
126
192
{
127
193
struct pwm_regulator_data * drvdata = rdev_get_drvdata (rdev );
194
+ unsigned int min_uV_duty = drvdata -> continuous .min_uV_dutycycle ;
195
+ unsigned int max_uV_duty = drvdata -> continuous .max_uV_dutycycle ;
196
+ unsigned int duty_unit = drvdata -> continuous .dutycycle_unit ;
128
197
unsigned int ramp_delay = rdev -> constraints -> ramp_delay ;
129
- struct pwm_args pargs ;
130
- unsigned int req_diff = min_uV - rdev -> constraints -> min_uV ;
131
- unsigned int diff ;
132
- unsigned int duty_pulse ;
133
- u64 req_period ;
134
- u32 rem ;
198
+ int min_uV = rdev -> constraints -> min_uV ;
199
+ int max_uV = rdev -> constraints -> max_uV ;
200
+ int diff_uV = max_uV - min_uV ;
201
+ struct pwm_state pstate ;
202
+ int old_uV = pwm_regulator_get_voltage (rdev );
203
+ unsigned int diff_duty ;
204
+ unsigned int dutycycle ;
135
205
int ret ;
136
206
137
- pwm_get_args (drvdata -> pwm , & pargs );
138
- diff = rdev -> constraints -> max_uV - rdev -> constraints -> min_uV ;
207
+ pwm_init_state (drvdata -> pwm , & pstate );
139
208
140
- /* First try to find out if we get the iduty cycle time which is
141
- * factor of PWM period time. If (request_diff_to_min * pwm_period)
142
- * is perfect divided by voltage_range_diff then it is possible to
143
- * get duty cycle time which is factor of PWM period. This will help
144
- * to get output voltage nearer to requested value as there is no
145
- * calculation loss.
209
+ /*
210
+ * The dutycycle for min_uV might be greater than the one for max_uV.
211
+ * This is happening when the user needs an inversed polarity, but the
212
+ * PWM device does not support inversing it in hardware.
146
213
*/
147
- req_period = req_diff * pargs .period ;
148
- div_u64_rem (req_period , diff , & rem );
149
- if (!rem ) {
150
- do_div (req_period , diff );
151
- duty_pulse = (unsigned int )req_period ;
152
- } else {
153
- duty_pulse = (pargs .period / 100 ) * ((req_diff * 100 ) / diff );
154
- }
214
+ if (max_uV_duty < min_uV_duty )
215
+ diff_duty = min_uV_duty - max_uV_duty ;
216
+ else
217
+ diff_duty = max_uV_duty - min_uV_duty ;
218
+
219
+ dutycycle = DIV_ROUND_CLOSEST_ULL ((u64 )(req_min_uV - min_uV ) *
220
+ diff_duty ,
221
+ diff_uV );
222
+
223
+ if (max_uV_duty < min_uV_duty )
224
+ dutycycle = min_uV_duty - dutycycle ;
225
+ else
226
+ dutycycle = min_uV_duty + dutycycle ;
227
+
228
+ pwm_set_relative_duty_cycle (& pstate , dutycycle , duty_unit );
155
229
156
- ret = pwm_config (drvdata -> pwm , duty_pulse , pargs . period );
230
+ ret = pwm_apply_state (drvdata -> pwm , & pstate );
157
231
if (ret ) {
158
232
dev_err (& rdev -> dev , "Failed to configure PWM: %d\n" , ret );
159
233
return ret ;
160
234
}
161
235
162
- ret = pwm_enable (drvdata -> pwm );
163
- if (ret ) {
164
- dev_err (& rdev -> dev , "Failed to enable PWM: %d\n" , ret );
165
- return ret ;
166
- }
167
- drvdata -> volt_uV = min_uV ;
236
+ if ((ramp_delay == 0 ) || !pwm_regulator_is_enabled (rdev ))
237
+ return 0 ;
168
238
169
- /* Delay required by PWM regulator to settle to the new voltage */
170
- usleep_range (ramp_delay , ramp_delay + 1000 );
239
+ /* Ramp delay is in uV/uS. Adjust to uS and delay */
240
+ ramp_delay = DIV_ROUND_UP (abs (req_min_uV - old_uV ), ramp_delay );
241
+ usleep_range (ramp_delay , ramp_delay + DIV_ROUND_UP (ramp_delay , 10 ));
171
242
172
243
return 0 ;
173
244
}
@@ -226,6 +297,7 @@ static int pwm_regulator_init_table(struct platform_device *pdev,
226
297
return ret ;
227
298
}
228
299
300
+ drvdata -> state = - EINVAL ;
229
301
drvdata -> duty_cycle_table = duty_cycle_table ;
230
302
memcpy (& drvdata -> ops , & pwm_regulator_voltage_table_ops ,
231
303
sizeof (drvdata -> ops ));
@@ -238,11 +310,28 @@ static int pwm_regulator_init_table(struct platform_device *pdev,
238
310
static int pwm_regulator_init_continuous (struct platform_device * pdev ,
239
311
struct pwm_regulator_data * drvdata )
240
312
{
313
+ u32 dutycycle_range [2 ] = { 0 , 100 };
314
+ u32 dutycycle_unit = 100 ;
315
+
241
316
memcpy (& drvdata -> ops , & pwm_regulator_voltage_continuous_ops ,
242
317
sizeof (drvdata -> ops ));
243
318
drvdata -> desc .ops = & drvdata -> ops ;
244
319
drvdata -> desc .continuous_voltage_range = true;
245
320
321
+ of_property_read_u32_array (pdev -> dev .of_node ,
322
+ "pwm-dutycycle-range" ,
323
+ dutycycle_range , 2 );
324
+ of_property_read_u32 (pdev -> dev .of_node , "pwm-dutycycle-unit" ,
325
+ & dutycycle_unit );
326
+
327
+ if (dutycycle_range [0 ] > dutycycle_unit ||
328
+ dutycycle_range [1 ] > dutycycle_unit )
329
+ return - EINVAL ;
330
+
331
+ drvdata -> continuous .dutycycle_unit = dutycycle_unit ;
332
+ drvdata -> continuous .min_uV_dutycycle = dutycycle_range [0 ];
333
+ drvdata -> continuous .max_uV_dutycycle = dutycycle_range [1 ];
334
+
246
335
return 0 ;
247
336
}
248
337
@@ -253,6 +342,7 @@ static int pwm_regulator_probe(struct platform_device *pdev)
253
342
struct regulator_dev * regulator ;
254
343
struct regulator_config config = { };
255
344
struct device_node * np = pdev -> dev .of_node ;
345
+ enum gpiod_flags gpio_flags ;
256
346
int ret ;
257
347
258
348
if (!np ) {
@@ -290,11 +380,21 @@ static int pwm_regulator_probe(struct platform_device *pdev)
290
380
return ret ;
291
381
}
292
382
293
- /*
294
- * FIXME: pwm_apply_args() should be removed when switching to the
295
- * atomic PWM API.
296
- */
297
- pwm_apply_args (drvdata -> pwm );
383
+ if (init_data -> constraints .boot_on || init_data -> constraints .always_on )
384
+ gpio_flags = GPIOD_OUT_HIGH ;
385
+ else
386
+ gpio_flags = GPIOD_OUT_LOW ;
387
+ drvdata -> enb_gpio = devm_gpiod_get_optional (& pdev -> dev , "enable" ,
388
+ gpio_flags );
389
+ if (IS_ERR (drvdata -> enb_gpio )) {
390
+ ret = PTR_ERR (drvdata -> enb_gpio );
391
+ dev_err (& pdev -> dev , "Failed to get enable GPIO: %d\n" , ret );
392
+ return ret ;
393
+ }
394
+
395
+ ret = pwm_adjust_config (drvdata -> pwm );
396
+ if (ret )
397
+ return ret ;
298
398
299
399
regulator = devm_regulator_register (& pdev -> dev ,
300
400
& drvdata -> desc , & config );
0 commit comments