26
26
* can get updated as below based on the current timer counter:
27
27
* - period for current cycle = current_period + new period
28
28
* - duty_cycle for current period = current period + new duty_cycle.
29
+ * - PWM OMAP DM timer cannot change the polarity when pwm is active. When
30
+ * user requests a change in polarity when in active state:
31
+ * - PWM is stopped abruptly(without completing the current cycle)
32
+ * - Polarity is changed
33
+ * - A fresh cycle is started.
29
34
*/
30
35
31
36
#include <linux/clk.h>
46
51
#define DM_TIMER_LOAD_MIN 0xfffffffe
47
52
#define DM_TIMER_MAX 0xffffffff
48
53
54
+ /**
55
+ * struct pwm_omap_dmtimer_chip - Structure representing a pwm chip
56
+ * corresponding to omap dmtimer.
57
+ * @chip: PWM chip structure representing PWM controller
58
+ * @mutex: Mutex to protect pwm apply state
59
+ * @dm_timer: Pointer to omap dm timer.
60
+ * @pdata: Pointer to omap dm timer ops.
61
+ * dm_timer_pdev: Pointer to omap dm timer platform device
62
+ */
49
63
struct pwm_omap_dmtimer_chip {
50
64
struct pwm_chip chip ;
65
+ /* Mutex to protect pwm apply state */
51
66
struct mutex mutex ;
52
67
struct omap_dm_timer * dm_timer ;
53
68
const struct omap_dm_timer_ops * pdata ;
@@ -60,11 +75,22 @@ to_pwm_omap_dmtimer_chip(struct pwm_chip *chip)
60
75
return container_of (chip , struct pwm_omap_dmtimer_chip , chip );
61
76
}
62
77
78
+ /**
79
+ * pwm_omap_dmtimer_get_clock_cycles() - Get clock cycles in a time frame
80
+ * @clk_rate: pwm timer clock rate
81
+ * @ns: time frame in nano seconds.
82
+ *
83
+ * Return number of clock cycles in a given period(ins ns).
84
+ */
63
85
static u32 pwm_omap_dmtimer_get_clock_cycles (unsigned long clk_rate , int ns )
64
86
{
65
87
return DIV_ROUND_CLOSEST_ULL ((u64 )clk_rate * ns , NSEC_PER_SEC );
66
88
}
67
89
90
+ /**
91
+ * pwm_omap_dmtimer_start() - Start the pwm omap dm timer in pwm mode
92
+ * @omap: Pointer to pwm omap dm timer chip
93
+ */
68
94
static void pwm_omap_dmtimer_start (struct pwm_omap_dmtimer_chip * omap )
69
95
{
70
96
/*
@@ -82,64 +108,73 @@ static void pwm_omap_dmtimer_start(struct pwm_omap_dmtimer_chip *omap)
82
108
omap -> pdata -> start (omap -> dm_timer );
83
109
}
84
110
85
- static int pwm_omap_dmtimer_enable (struct pwm_chip * chip ,
86
- struct pwm_device * pwm )
111
+ /**
112
+ * pwm_omap_dmtimer_is_enabled() - Detect if the pwm is enabled.
113
+ * @omap: Pointer to pwm omap dm timer chip
114
+ *
115
+ * Return true if pwm is enabled else false.
116
+ */
117
+ static bool pwm_omap_dmtimer_is_enabled (struct pwm_omap_dmtimer_chip * omap )
87
118
{
88
- struct pwm_omap_dmtimer_chip * omap = to_pwm_omap_dmtimer_chip ( chip ) ;
119
+ u32 status ;
89
120
90
- mutex_lock (& omap -> mutex );
91
- omap -> pdata -> set_pwm (omap -> dm_timer ,
92
- pwm_get_polarity (pwm ) == PWM_POLARITY_INVERSED ,
93
- true, OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE ,
94
- true);
95
-
96
- pwm_omap_dmtimer_start (omap );
97
- mutex_unlock (& omap -> mutex );
121
+ status = omap -> pdata -> get_pwm_status (omap -> dm_timer );
98
122
99
- return 0 ;
123
+ return !!( status & OMAP_TIMER_CTRL_ST ) ;
100
124
}
101
125
102
- static void pwm_omap_dmtimer_disable (struct pwm_chip * chip ,
103
- struct pwm_device * pwm )
126
+ /**
127
+ * pwm_omap_dmtimer_polarity() - Detect the polarity of pwm.
128
+ * @omap: Pointer to pwm omap dm timer chip
129
+ *
130
+ * Return the polarity of pwm.
131
+ */
132
+ static int pwm_omap_dmtimer_polarity (struct pwm_omap_dmtimer_chip * omap )
104
133
{
105
- struct pwm_omap_dmtimer_chip * omap = to_pwm_omap_dmtimer_chip ( chip ) ;
134
+ u32 status ;
106
135
107
- mutex_lock ( & omap -> mutex );
108
- omap -> pdata -> stop ( omap -> dm_timer );
109
- mutex_unlock ( & omap -> mutex );
136
+ status = omap -> pdata -> get_pwm_status ( omap -> dm_timer );
137
+
138
+ return !!( status & OMAP_TIMER_CTRL_SCPWM );
110
139
}
111
140
141
+ /**
142
+ * pwm_omap_dmtimer_config() - Update the configuration of pwm omap dm timer
143
+ * @chip: Pointer to PWM controller
144
+ * @pwm: Pointer to PWM channel
145
+ * @duty_ns: New duty cycle in nano seconds
146
+ * @period_ns: New period in nano seconds
147
+ *
148
+ * Return 0 if successfully changed the period/duty_cycle else appropriate
149
+ * error.
150
+ */
112
151
static int pwm_omap_dmtimer_config (struct pwm_chip * chip ,
113
152
struct pwm_device * pwm ,
114
153
int duty_ns , int period_ns )
115
154
{
116
155
struct pwm_omap_dmtimer_chip * omap = to_pwm_omap_dmtimer_chip (chip );
117
156
u32 period_cycles , duty_cycles ;
118
157
u32 load_value , match_value ;
119
- struct clk * fclk ;
120
158
unsigned long clk_rate ;
159
+ struct clk * fclk ;
121
160
122
161
dev_dbg (chip -> dev , "requested duty cycle: %d ns, period: %d ns\n" ,
123
162
duty_ns , period_ns );
124
163
125
- mutex_lock (& omap -> mutex );
126
164
if (duty_ns == pwm_get_duty_cycle (pwm ) &&
127
- period_ns == pwm_get_period (pwm )) {
128
- /* No change - don't cause any transients. */
129
- mutex_unlock (& omap -> mutex );
165
+ period_ns == pwm_get_period (pwm ))
130
166
return 0 ;
131
- }
132
167
133
168
fclk = omap -> pdata -> get_fclk (omap -> dm_timer );
134
169
if (!fclk ) {
135
170
dev_err (chip -> dev , "invalid pmtimer fclk\n" );
136
- goto err_einval ;
171
+ return - EINVAL ;
137
172
}
138
173
139
174
clk_rate = clk_get_rate (fclk );
140
175
if (!clk_rate ) {
141
176
dev_err (chip -> dev , "invalid pmtimer fclk rate\n" );
142
- goto err_einval ;
177
+ return - EINVAL ;
143
178
}
144
179
145
180
dev_dbg (chip -> dev , "clk rate: %luHz\n" , clk_rate );
@@ -167,7 +202,7 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip,
167
202
dev_info (chip -> dev ,
168
203
"period %d ns too short for clock rate %lu Hz\n" ,
169
204
period_ns , clk_rate );
170
- goto err_einval ;
205
+ return - EINVAL ;
171
206
}
172
207
173
208
if (duty_cycles < 1 ) {
@@ -199,55 +234,97 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip,
199
234
dev_dbg (chip -> dev , "load value: %#08x (%d), match value: %#08x (%d)\n" ,
200
235
load_value , load_value , match_value , match_value );
201
236
202
- mutex_unlock (& omap -> mutex );
203
-
204
237
return 0 ;
205
-
206
- err_einval :
207
- mutex_unlock (& omap -> mutex );
208
-
209
- return - EINVAL ;
210
238
}
211
239
212
- static int pwm_omap_dmtimer_set_polarity (struct pwm_chip * chip ,
213
- struct pwm_device * pwm ,
214
- enum pwm_polarity polarity )
240
+ /**
241
+ * pwm_omap_dmtimer_set_polarity() - Changes the polarity of the pwm dm timer.
242
+ * @chip: Pointer to PWM controller
243
+ * @pwm: Pointer to PWM channel
244
+ * @polarity: New pwm polarity to be set
245
+ */
246
+ static void pwm_omap_dmtimer_set_polarity (struct pwm_chip * chip ,
247
+ struct pwm_device * pwm ,
248
+ enum pwm_polarity polarity )
215
249
{
216
250
struct pwm_omap_dmtimer_chip * omap = to_pwm_omap_dmtimer_chip (chip );
251
+ bool enabled ;
252
+
253
+ /* Disable the PWM before changing the polarity. */
254
+ enabled = pwm_omap_dmtimer_is_enabled (omap );
255
+ if (enabled )
256
+ omap -> pdata -> stop (omap -> dm_timer );
217
257
218
- /*
219
- * PWM core will not call set_polarity while PWM is enabled so it's
220
- * safe to reconfigure the timer here without stopping it first.
221
- */
222
- mutex_lock (& omap -> mutex );
223
258
omap -> pdata -> set_pwm (omap -> dm_timer ,
224
259
polarity == PWM_POLARITY_INVERSED ,
225
260
true, OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE ,
226
261
true);
262
+
263
+ if (enabled )
264
+ pwm_omap_dmtimer_start (omap );
265
+ }
266
+
267
+ /**
268
+ * pwm_omap_dmtimer_apply() - Changes the state of the pwm omap dm timer.
269
+ * @chip: Pointer to PWM controller
270
+ * @pwm: Pointer to PWM channel
271
+ * @state: New state to apply
272
+ *
273
+ * Return 0 if successfully changed the state else appropriate error.
274
+ */
275
+ static int pwm_omap_dmtimer_apply (struct pwm_chip * chip ,
276
+ struct pwm_device * pwm ,
277
+ const struct pwm_state * state )
278
+ {
279
+ struct pwm_omap_dmtimer_chip * omap = to_pwm_omap_dmtimer_chip (chip );
280
+ int ret = 0 ;
281
+
282
+ mutex_lock (& omap -> mutex );
283
+
284
+ if (pwm_omap_dmtimer_is_enabled (omap ) && !state -> enabled ) {
285
+ omap -> pdata -> stop (omap -> dm_timer );
286
+ goto unlock_mutex ;
287
+ }
288
+
289
+ if (pwm_omap_dmtimer_polarity (omap ) != state -> polarity )
290
+ pwm_omap_dmtimer_set_polarity (chip , pwm , state -> polarity );
291
+
292
+ ret = pwm_omap_dmtimer_config (chip , pwm , state -> duty_cycle ,
293
+ state -> period );
294
+ if (ret )
295
+ goto unlock_mutex ;
296
+
297
+ if (!pwm_omap_dmtimer_is_enabled (omap ) && state -> enabled ) {
298
+ omap -> pdata -> set_pwm (omap -> dm_timer ,
299
+ state -> polarity == PWM_POLARITY_INVERSED ,
300
+ true,
301
+ OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE ,
302
+ true);
303
+ pwm_omap_dmtimer_start (omap );
304
+ }
305
+
306
+ unlock_mutex :
227
307
mutex_unlock (& omap -> mutex );
228
308
229
- return 0 ;
309
+ return ret ;
230
310
}
231
311
232
312
static const struct pwm_ops pwm_omap_dmtimer_ops = {
233
- .enable = pwm_omap_dmtimer_enable ,
234
- .disable = pwm_omap_dmtimer_disable ,
235
- .config = pwm_omap_dmtimer_config ,
236
- .set_polarity = pwm_omap_dmtimer_set_polarity ,
313
+ .apply = pwm_omap_dmtimer_apply ,
237
314
.owner = THIS_MODULE ,
238
315
};
239
316
240
317
static int pwm_omap_dmtimer_probe (struct platform_device * pdev )
241
318
{
242
319
struct device_node * np = pdev -> dev .of_node ;
243
- struct device_node * timer ;
244
- struct platform_device * timer_pdev ;
245
- struct pwm_omap_dmtimer_chip * omap ;
246
320
struct dmtimer_platform_data * timer_pdata ;
247
321
const struct omap_dm_timer_ops * pdata ;
322
+ struct platform_device * timer_pdev ;
323
+ struct pwm_omap_dmtimer_chip * omap ;
248
324
struct omap_dm_timer * dm_timer ;
249
- u32 v ;
325
+ struct device_node * timer ;
250
326
int ret = 0 ;
327
+ u32 v ;
251
328
252
329
timer = of_parse_phandle (np , "ti,timers" , 0 );
253
330
if (!timer )
@@ -280,6 +357,7 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev)
280
357
!pdata -> set_load ||
281
358
!pdata -> set_match ||
282
359
!pdata -> set_pwm ||
360
+ !pdata -> get_pwm_status ||
283
361
!pdata -> set_prescaler ||
284
362
!pdata -> write_counter ) {
285
363
dev_err (& pdev -> dev , "Incomplete dmtimer pdata structure\n" );
0 commit comments