@@ -49,6 +49,30 @@ static void pwmchip_unlock(struct pwm_chip *chip)
4949
5050DEFINE_GUARD (pwmchip , struct pwm_chip * , pwmchip_lock (_T ), pwmchip_unlock (_T ))
5151
52+ static bool pwm_wf_valid (const struct pwm_waveform * wf )
53+ {
54+ /*
55+ * For now restrict waveforms to period_length_ns <= S64_MAX to provide
56+ * some space for future extensions. One possibility is to simplify
57+ * representing waveforms with inverted polarity using negative values
58+ * somehow.
59+ */
60+ if (wf -> period_length_ns > S64_MAX )
61+ return false;
62+
63+ if (wf -> duty_length_ns > wf -> period_length_ns )
64+ return false;
65+
66+ /*
67+ * .duty_offset_ns is supposed to be smaller than .period_length_ns, apart
68+ * from the corner case .duty_offset_ns == 0 && .period_length_ns == 0.
69+ */
70+ if (wf -> duty_offset_ns && wf -> duty_offset_ns >= wf -> period_length_ns )
71+ return false;
72+
73+ return true;
74+ }
75+
5276static void pwm_wf2state (const struct pwm_waveform * wf , struct pwm_state * state )
5377{
5478 if (wf -> period_length_ns ) {
@@ -95,6 +119,29 @@ static void pwm_state2wf(const struct pwm_state *state, struct pwm_waveform *wf)
95119 }
96120}
97121
122+ static int pwmwfcmp (const struct pwm_waveform * a , const struct pwm_waveform * b )
123+ {
124+ if (a -> period_length_ns > b -> period_length_ns )
125+ return 1 ;
126+
127+ if (a -> period_length_ns < b -> period_length_ns )
128+ return -1 ;
129+
130+ if (a -> duty_length_ns > b -> duty_length_ns )
131+ return 1 ;
132+
133+ if (a -> duty_length_ns < b -> duty_length_ns )
134+ return -1 ;
135+
136+ if (a -> duty_offset_ns > b -> duty_offset_ns )
137+ return 1 ;
138+
139+ if (a -> duty_offset_ns < b -> duty_offset_ns )
140+ return -1 ;
141+
142+ return 0 ;
143+ }
144+
98145static bool pwm_check_rounding (const struct pwm_waveform * wf ,
99146 const struct pwm_waveform * wf_rounded )
100147{
@@ -145,6 +192,220 @@ static int __pwm_write_waveform(struct pwm_chip *chip, struct pwm_device *pwm, c
145192
146193#define WFHWSIZE 20
147194
195+ /**
196+ * pwm_round_waveform_might_sleep - Query hardware capabilities
197+ * Cannot be used in atomic context.
198+ * @pwm: PWM device
199+ * @wf: waveform to round and output parameter
200+ *
201+ * Typically a given waveform cannot be implemented exactly by hardware, e.g.
202+ * because hardware only supports coarse period resolution or no duty_offset.
203+ * This function returns the actually implemented waveform if you pass wf to
204+ * pwm_set_waveform_might_sleep now.
205+ *
206+ * Note however that the world doesn't stop turning when you call it, so when
207+ * doing
208+ *
209+ * pwm_round_waveform_might_sleep(mypwm, &wf);
210+ * pwm_set_waveform_might_sleep(mypwm, &wf, true);
211+ *
212+ * the latter might fail, e.g. because an input clock changed its rate between
213+ * these two calls and the waveform determined by
214+ * pwm_round_waveform_might_sleep() cannot be implemented any more.
215+ *
216+ * Returns 0 on success, 1 if there is no valid hardware configuration matching
217+ * the input waveform under the PWM rounding rules or a negative errno.
218+ */
219+ int pwm_round_waveform_might_sleep (struct pwm_device * pwm , struct pwm_waveform * wf )
220+ {
221+ struct pwm_chip * chip = pwm -> chip ;
222+ const struct pwm_ops * ops = chip -> ops ;
223+ struct pwm_waveform wf_req = * wf ;
224+ char wfhw [WFHWSIZE ];
225+ int ret_tohw , ret_fromhw ;
226+
227+ BUG_ON (WFHWSIZE < ops -> sizeof_wfhw );
228+
229+ if (!pwm_wf_valid (wf ))
230+ return - EINVAL ;
231+
232+ guard (pwmchip )(chip );
233+
234+ if (!chip -> operational )
235+ return - ENODEV ;
236+
237+ ret_tohw = __pwm_round_waveform_tohw (chip , pwm , wf , wfhw );
238+ if (ret_tohw < 0 )
239+ return ret_tohw ;
240+
241+ if (IS_ENABLED (CONFIG_PWM_DEBUG ) && ret_tohw > 1 )
242+ dev_err (& chip -> dev , "Unexpected return value from __pwm_round_waveform_tohw: requested %llu/%llu [+%llu], return value %d\n" ,
243+ wf_req .duty_length_ns , wf_req .period_length_ns , wf_req .duty_offset_ns , ret_tohw );
244+
245+ ret_fromhw = __pwm_round_waveform_fromhw (chip , pwm , wfhw , wf );
246+ if (ret_fromhw < 0 )
247+ return ret_fromhw ;
248+
249+ if (IS_ENABLED (CONFIG_PWM_DEBUG ) && ret_fromhw > 0 )
250+ dev_err (& chip -> dev , "Unexpected return value from __pwm_round_waveform_fromhw: requested %llu/%llu [+%llu], return value %d\n" ,
251+ wf_req .duty_length_ns , wf_req .period_length_ns , wf_req .duty_offset_ns , ret_tohw );
252+
253+ if (IS_ENABLED (CONFIG_PWM_DEBUG ) &&
254+ ret_tohw == 0 && !pwm_check_rounding (& wf_req , wf ))
255+ dev_err (& chip -> dev , "Wrong rounding: requested %llu/%llu [+%llu], result %llu/%llu [+%llu]\n" ,
256+ wf_req .duty_length_ns , wf_req .period_length_ns , wf_req .duty_offset_ns ,
257+ wf -> duty_length_ns , wf -> period_length_ns , wf -> duty_offset_ns );
258+
259+ return ret_tohw ;
260+ }
261+ EXPORT_SYMBOL_GPL (pwm_round_waveform_might_sleep );
262+
263+ /**
264+ * pwm_get_waveform_might_sleep - Query hardware about current configuration
265+ * Cannot be used in atomic context.
266+ * @pwm: PWM device
267+ * @wf: output parameter
268+ *
269+ * Stores the current configuration of the PWM in @wf. Note this is the
270+ * equivalent of pwm_get_state_hw() (and not pwm_get_state()) for pwm_waveform.
271+ */
272+ int pwm_get_waveform_might_sleep (struct pwm_device * pwm , struct pwm_waveform * wf )
273+ {
274+ struct pwm_chip * chip = pwm -> chip ;
275+ const struct pwm_ops * ops = chip -> ops ;
276+ char wfhw [WFHWSIZE ];
277+ int err ;
278+
279+ BUG_ON (WFHWSIZE < ops -> sizeof_wfhw );
280+
281+ guard (pwmchip )(chip );
282+
283+ if (!chip -> operational )
284+ return - ENODEV ;
285+
286+ err = __pwm_read_waveform (chip , pwm , & wfhw );
287+ if (err )
288+ return err ;
289+
290+ return __pwm_round_waveform_fromhw (chip , pwm , & wfhw , wf );
291+ }
292+ EXPORT_SYMBOL_GPL (pwm_get_waveform_might_sleep );
293+
294+ /* Called with the pwmchip lock held */
295+ static int __pwm_set_waveform (struct pwm_device * pwm ,
296+ const struct pwm_waveform * wf ,
297+ bool exact )
298+ {
299+ struct pwm_chip * chip = pwm -> chip ;
300+ const struct pwm_ops * ops = chip -> ops ;
301+ char wfhw [WFHWSIZE ];
302+ struct pwm_waveform wf_rounded ;
303+ int err ;
304+
305+ BUG_ON (WFHWSIZE < ops -> sizeof_wfhw );
306+
307+ if (!pwm_wf_valid (wf ))
308+ return - EINVAL ;
309+
310+ err = __pwm_round_waveform_tohw (chip , pwm , wf , & wfhw );
311+ if (err )
312+ return err ;
313+
314+ if ((IS_ENABLED (CONFIG_PWM_DEBUG ) || exact ) && wf -> period_length_ns ) {
315+ err = __pwm_round_waveform_fromhw (chip , pwm , & wfhw , & wf_rounded );
316+ if (err )
317+ return err ;
318+
319+ if (IS_ENABLED (CONFIG_PWM_DEBUG ) && !pwm_check_rounding (wf , & wf_rounded ))
320+ dev_err (& chip -> dev , "Wrong rounding: requested %llu/%llu [+%llu], result %llu/%llu [+%llu]\n" ,
321+ wf -> duty_length_ns , wf -> period_length_ns , wf -> duty_offset_ns ,
322+ wf_rounded .duty_length_ns , wf_rounded .period_length_ns , wf_rounded .duty_offset_ns );
323+
324+ if (exact && pwmwfcmp (wf , & wf_rounded )) {
325+ dev_dbg (& chip -> dev , "Requested no rounding, but %llu/%llu [+%llu] -> %llu/%llu [+%llu]\n" ,
326+ wf -> duty_length_ns , wf -> period_length_ns , wf -> duty_offset_ns ,
327+ wf_rounded .duty_length_ns , wf_rounded .period_length_ns , wf_rounded .duty_offset_ns );
328+
329+ return 1 ;
330+ }
331+ }
332+
333+ err = __pwm_write_waveform (chip , pwm , & wfhw );
334+ if (err )
335+ return err ;
336+
337+ /* update .state */
338+ pwm_wf2state (wf , & pwm -> state );
339+
340+ if (IS_ENABLED (CONFIG_PWM_DEBUG ) && ops -> read_waveform && wf -> period_length_ns ) {
341+ struct pwm_waveform wf_set ;
342+
343+ err = __pwm_read_waveform (chip , pwm , & wfhw );
344+ if (err )
345+ /* maybe ignore? */
346+ return err ;
347+
348+ err = __pwm_round_waveform_fromhw (chip , pwm , & wfhw , & wf_set );
349+ if (err )
350+ /* maybe ignore? */
351+ return err ;
352+
353+ if (pwmwfcmp (& wf_set , & wf_rounded ) != 0 )
354+ dev_err (& chip -> dev ,
355+ "Unexpected setting: requested %llu/%llu [+%llu], expected %llu/%llu [+%llu], set %llu/%llu [+%llu]\n" ,
356+ wf -> duty_length_ns , wf -> period_length_ns , wf -> duty_offset_ns ,
357+ wf_rounded .duty_length_ns , wf_rounded .period_length_ns , wf_rounded .duty_offset_ns ,
358+ wf_set .duty_length_ns , wf_set .period_length_ns , wf_set .duty_offset_ns );
359+ }
360+ return 0 ;
361+ }
362+
363+ /**
364+ * pwm_set_waveform_might_sleep - Apply a new waveform
365+ * Cannot be used in atomic context.
366+ * @pwm: PWM device
367+ * @wf: The waveform to apply
368+ * @exact: If true no rounding is allowed
369+ *
370+ * Typically a requested waveform cannot be implemented exactly, e.g. because
371+ * you requested .period_length_ns = 100 ns, but the hardware can only set
372+ * periods that are a multiple of 8.5 ns. With that hardware passing exact =
373+ * true results in pwm_set_waveform_might_sleep() failing and returning 1. If
374+ * exact = false you get a period of 93.5 ns (i.e. the biggest period not bigger
375+ * than the requested value).
376+ * Note that even with exact = true, some rounding by less than 1 is
377+ * possible/needed. In the above example requesting .period_length_ns = 94 and
378+ * exact = true, you get the hardware configured with period = 93.5 ns.
379+ */
380+ int pwm_set_waveform_might_sleep (struct pwm_device * pwm ,
381+ const struct pwm_waveform * wf , bool exact )
382+ {
383+ struct pwm_chip * chip = pwm -> chip ;
384+ int err ;
385+
386+ might_sleep ();
387+
388+ guard (pwmchip )(chip );
389+
390+ if (!chip -> operational )
391+ return - ENODEV ;
392+
393+ if (IS_ENABLED (CONFIG_PWM_DEBUG ) && chip -> atomic ) {
394+ /*
395+ * Catch any drivers that have been marked as atomic but
396+ * that will sleep anyway.
397+ */
398+ non_block_start ();
399+ err = __pwm_set_waveform (pwm , wf , exact );
400+ non_block_end ();
401+ } else {
402+ err = __pwm_set_waveform (pwm , wf , exact );
403+ }
404+
405+ return err ;
406+ }
407+ EXPORT_SYMBOL_GPL (pwm_set_waveform_might_sleep );
408+
148409static void pwm_apply_debug (struct pwm_device * pwm ,
149410 const struct pwm_state * state )
150411{
0 commit comments