Merge tag 'drm-fixes-2024-06-22' of https://gitlab.freedesktop.org/drm/kernel
[linux-2.6-block.git] / include / linux / pwm.h
CommitLineData
b2441318 1/* SPDX-License-Identifier: GPL-2.0 */
1a189b97
RK
2#ifndef __LINUX_PWM_H
3#define __LINUX_PWM_H
4
4c56b143 5#include <linux/device.h>
0bcf168b 6#include <linux/err.h>
d1cd2142 7#include <linux/mutex.h>
7299ab70
TR
8#include <linux/of.h>
9
0c2498f1
SH
10struct pwm_chip;
11
0aa0869c
PA
12/**
13 * enum pwm_polarity - polarity of a PWM signal
14 * @PWM_POLARITY_NORMAL: a high signal for the duration of the duty-
15 * cycle, followed by a low signal for the remainder of the pulse
16 * period
17 * @PWM_POLARITY_INVERSED: a low signal for the duration of the duty-
18 * cycle, followed by a high signal for the remainder of the pulse
19 * period
20 */
21enum pwm_polarity {
22 PWM_POLARITY_NORMAL,
23 PWM_POLARITY_INVERSED,
24};
25
e39c0df1
BB
26/**
27 * struct pwm_args - board-dependent PWM arguments
28 * @period: reference period
29 * @polarity: reference polarity
30 *
31 * This structure describes board-dependent arguments attached to a PWM
32 * device. These arguments are usually retrieved from the PWM lookup table or
33 * device tree.
34 *
35 * Do not confuse this with the PWM state: PWM arguments represent the initial
36 * configuration that users want to use on this PWM device rather than the
37 * current PWM hardware state.
38 */
39struct pwm_args {
a9d887dc 40 u64 period;
e39c0df1
BB
41 enum pwm_polarity polarity;
42};
43
f051c466 44enum {
d27abbfd
DC
45 PWMF_REQUESTED = 0,
46 PWMF_EXPORTED = 1,
f051c466
TR
47};
48
43a276b0
BB
49/*
50 * struct pwm_state - state of a PWM channel
51 * @period: PWM period (in nanoseconds)
52 * @duty_cycle: PWM duty cycle (in nanoseconds)
53 * @polarity: PWM polarity
09a7e4a3 54 * @enabled: PWM enabled status
9e40ee18
CG
55 * @usage_power: If set, the PWM driver is only required to maintain the power
56 * output but has more freedom regarding signal form.
57 * If supported, the signal can be optimized, for example to
58 * improve EMI by phase shifting individual channels.
43a276b0
BB
59 */
60struct pwm_state {
a9d887dc
GDS
61 u64 period;
62 u64 duty_cycle;
43a276b0 63 enum pwm_polarity polarity;
09a7e4a3 64 bool enabled;
9e40ee18 65 bool usage_power;
43a276b0
BB
66};
67
04883802
TR
68/**
69 * struct pwm_device - PWM channel object
70 * @label: name of the PWM device
71 * @flags: flags associated with the PWM device
72 * @hwpwm: per-chip relative index of the PWM device
04883802 73 * @chip: PWM chip providing this PWM device
e39c0df1 74 * @args: PWM arguments
3ad1f3a3
UKK
75 * @state: last applied state
76 * @last: last implemented state (for PWM_DEBUG)
04883802 77 */
f051c466 78struct pwm_device {
6bc7064a
TR
79 const char *label;
80 unsigned long flags;
81 unsigned int hwpwm;
6bc7064a 82 struct pwm_chip *chip;
6bc7064a 83
e39c0df1 84 struct pwm_args args;
43a276b0 85 struct pwm_state state;
3ad1f3a3 86 struct pwm_state last;
f051c466
TR
87};
88
43a276b0
BB
89/**
90 * pwm_get_state() - retrieve the current PWM state
91 * @pwm: PWM device
92 * @state: state to fill with the current PWM state
1a7a6e80
UKK
93 *
94 * The returned PWM state represents the state that was applied by a previous call to
c748a6d7
SY
95 * pwm_apply_might_sleep(). Drivers may have to slightly tweak that state before programming it to
96 * hardware. If pwm_apply_might_sleep() was never called, this returns either the current hardware
1a7a6e80 97 * state (if supported) or the default settings.
43a276b0
BB
98 */
99static inline void pwm_get_state(const struct pwm_device *pwm,
100 struct pwm_state *state)
101{
102 *state = pwm->state;
103}
104
5c31252c
BB
105static inline bool pwm_is_enabled(const struct pwm_device *pwm)
106{
09a7e4a3
BB
107 struct pwm_state state;
108
109 pwm_get_state(pwm, &state);
110
111 return state.enabled;
5c31252c
BB
112}
113
a9d887dc 114static inline u64 pwm_get_period(const struct pwm_device *pwm)
f051c466 115{
43a276b0
BB
116 struct pwm_state state;
117
118 pwm_get_state(pwm, &state);
119
120 return state.period;
f051c466
TR
121}
122
a9d887dc 123static inline u64 pwm_get_duty_cycle(const struct pwm_device *pwm)
76abbdde 124{
43a276b0
BB
125 struct pwm_state state;
126
127 pwm_get_state(pwm, &state);
128
129 return state.duty_cycle;
76abbdde
HS
130}
131
011e7631
BB
132static inline enum pwm_polarity pwm_get_polarity(const struct pwm_device *pwm)
133{
43a276b0
BB
134 struct pwm_state state;
135
136 pwm_get_state(pwm, &state);
137
138 return state.polarity;
011e7631
BB
139}
140
e39c0df1
BB
141static inline void pwm_get_args(const struct pwm_device *pwm,
142 struct pwm_args *args)
143{
144 *args = pwm->args;
145}
146
a6a0dbbc 147/**
c748a6d7 148 * pwm_init_state() - prepare a new state to be applied with pwm_apply_might_sleep()
a6a0dbbc
BB
149 * @pwm: PWM device
150 * @state: state to fill with the prepared PWM state
151 *
152 * This functions prepares a state that can later be tweaked and applied
c748a6d7 153 * to the PWM device with pwm_apply_might_sleep(). This is a convenient function
a6a0dbbc
BB
154 * that first retrieves the current PWM state and the replaces the period
155 * and polarity fields with the reference values defined in pwm->args.
156 * Once the function returns, you can adjust the ->enabled and ->duty_cycle
c748a6d7 157 * fields according to your needs before calling pwm_apply_might_sleep().
a6a0dbbc
BB
158 *
159 * ->duty_cycle is initially set to zero to avoid cases where the current
160 * ->duty_cycle value exceed the pwm_args->period one, which would trigger
c748a6d7 161 * an error if the user calls pwm_apply_might_sleep() without adjusting ->duty_cycle
a6a0dbbc
BB
162 * first.
163 */
164static inline void pwm_init_state(const struct pwm_device *pwm,
165 struct pwm_state *state)
166{
167 struct pwm_args args;
168
169 /* First get the current state. */
170 pwm_get_state(pwm, state);
171
172 /* Then fill it with the reference config */
173 pwm_get_args(pwm, &args);
174
175 state->period = args.period;
176 state->polarity = args.polarity;
177 state->duty_cycle = 0;
9e40ee18 178 state->usage_power = false;
a6a0dbbc
BB
179}
180
f6f3bddf
BB
181/**
182 * pwm_get_relative_duty_cycle() - Get a relative duty cycle value
183 * @state: PWM state to extract the duty cycle from
184 * @scale: target scale of the relative duty cycle
185 *
186 * This functions converts the absolute duty cycle stored in @state (expressed
187 * in nanosecond) into a value relative to the period.
188 *
189 * For example if you want to get the duty_cycle expressed in percent, call:
190 *
191 * pwm_get_state(pwm, &state);
192 * duty = pwm_get_relative_duty_cycle(&state, 100);
193 */
194static inline unsigned int
195pwm_get_relative_duty_cycle(const struct pwm_state *state, unsigned int scale)
196{
197 if (!state->period)
198 return 0;
199
200 return DIV_ROUND_CLOSEST_ULL((u64)state->duty_cycle * scale,
201 state->period);
202}
203
204/**
205 * pwm_set_relative_duty_cycle() - Set a relative duty cycle value
206 * @state: PWM state to fill
207 * @duty_cycle: relative duty cycle value
208 * @scale: scale in which @duty_cycle is expressed
209 *
210 * This functions converts a relative into an absolute duty cycle (expressed
211 * in nanoseconds), and puts the result in state->duty_cycle.
212 *
213 * For example if you want to configure a 50% duty cycle, call:
214 *
215 * pwm_init_state(pwm, &state);
216 * pwm_set_relative_duty_cycle(&state, 50, 100);
c748a6d7 217 * pwm_apply_might_sleep(pwm, &state);
f6f3bddf
BB
218 *
219 * This functions returns -EINVAL if @duty_cycle and/or @scale are
220 * inconsistent (@scale == 0 or @duty_cycle > @scale).
221 */
222static inline int
223pwm_set_relative_duty_cycle(struct pwm_state *state, unsigned int duty_cycle,
224 unsigned int scale)
225{
226 if (!scale || duty_cycle > scale)
227 return -EINVAL;
228
229 state->duty_cycle = DIV_ROUND_CLOSEST_ULL((u64)duty_cycle *
230 state->period,
231 scale);
232
233 return 0;
234}
235
ef2e35d9
UKK
236/**
237 * struct pwm_capture - PWM capture data
238 * @period: period of the PWM signal (in nanoseconds)
239 * @duty_cycle: duty cycle of the PWM signal (in nanoseconds)
240 */
241struct pwm_capture {
242 unsigned int period;
243 unsigned int duty_cycle;
244};
245
0c2498f1
SH
246/**
247 * struct pwm_ops - PWM controller operations
248 * @request: optional hook for requesting a PWM
249 * @free: optional hook for freeing a PWM
3a3d1a4e 250 * @capture: capture and report PWM signal
27938fd8 251 * @apply: atomically apply a new PWM config
15fa8a43
BB
252 * @get_state: get the current PWM state. This function is only
253 * called once per PWM device when the PWM chip is
254 * registered.
0c2498f1
SH
255 */
256struct pwm_ops {
6bc7064a
TR
257 int (*request)(struct pwm_chip *chip, struct pwm_device *pwm);
258 void (*free)(struct pwm_chip *chip, struct pwm_device *pwm);
3a3d1a4e
LJ
259 int (*capture)(struct pwm_chip *chip, struct pwm_device *pwm,
260 struct pwm_capture *result, unsigned long timeout);
5ec803ed 261 int (*apply)(struct pwm_chip *chip, struct pwm_device *pwm,
71523d18 262 const struct pwm_state *state);
6c452cff
UKK
263 int (*get_state)(struct pwm_chip *chip, struct pwm_device *pwm,
264 struct pwm_state *state);
0c2498f1
SH
265};
266
267/**
f051c466
TR
268 * struct pwm_chip - abstract a PWM controller
269 * @dev: device providing the PWMs
f051c466 270 * @ops: callbacks for this PWM controller
384461ab 271 * @owner: module providing this chip
2d91123a 272 * @id: unique number of this PWM chip
f051c466 273 * @npwm: number of PWMs controlled by this chip
04883802 274 * @of_xlate: request a PWM device given a device tree PWM specifier
7170d3be 275 * @atomic: can the driver's ->apply() be called in atomic context
05947224 276 * @uses_pwmchip_alloc: signals if pwmchip_allow was used to allocate this chip
5d0a4c11 277 * @pwms: array of PWM devices allocated by the framework
0c2498f1
SH
278 */
279struct pwm_chip {
4c56b143 280 struct device dev;
6bc7064a 281 const struct pwm_ops *ops;
384461ab 282 struct module *owner;
54c86dd2 283 unsigned int id;
6bc7064a
TR
284 unsigned int npwm;
285
b4f78ff7 286 struct pwm_device * (*of_xlate)(struct pwm_chip *chip,
6bc7064a 287 const struct of_phandle_args *args);
7170d3be 288 bool atomic;
5d0a4c11
UKK
289
290 /* only used internally by the PWM framework */
05947224 291 bool uses_pwmchip_alloc;
ee37bf50 292 struct pwm_device pwms[] __counted_by(npwm);
0c2498f1
SH
293};
294
4e59267c
UKK
295static inline struct device *pwmchip_parent(const struct pwm_chip *chip)
296{
4c56b143 297 return chip->dev.parent;
4e59267c
UKK
298}
299
24003d50
UKK
300static inline void *pwmchip_get_drvdata(struct pwm_chip *chip)
301{
38ae7142 302 return dev_get_drvdata(&chip->dev);
24003d50
UKK
303}
304
305static inline void pwmchip_set_drvdata(struct pwm_chip *chip, void *data)
306{
38ae7142 307 dev_set_drvdata(&chip->dev, data);
24003d50
UKK
308}
309
0bcf168b 310#if IS_ENABLED(CONFIG_PWM)
5ec803ed 311/* PWM user APIs */
c748a6d7 312int pwm_apply_might_sleep(struct pwm_device *pwm, const struct pwm_state *state);
7170d3be 313int pwm_apply_atomic(struct pwm_device *pwm, const struct pwm_state *state);
5ec803ed
BB
314int pwm_adjust_config(struct pwm_device *pwm);
315
316/**
317 * pwm_config() - change a PWM device configuration
318 * @pwm: PWM device
319 * @duty_ns: "on" time (in nanoseconds)
320 * @period_ns: duration (in nanoseconds) of one cycle
321 *
322 * Returns: 0 on success or a negative error code on failure.
323 */
324static inline int pwm_config(struct pwm_device *pwm, int duty_ns,
325 int period_ns)
326{
327 struct pwm_state state;
328
329 if (!pwm)
330 return -EINVAL;
331
ef2bf499
BN
332 if (duty_ns < 0 || period_ns < 0)
333 return -EINVAL;
334
5ec803ed
BB
335 pwm_get_state(pwm, &state);
336 if (state.duty_cycle == duty_ns && state.period == period_ns)
337 return 0;
338
339 state.duty_cycle = duty_ns;
340 state.period = period_ns;
c748a6d7 341 return pwm_apply_might_sleep(pwm, &state);
5ec803ed
BB
342}
343
5ec803ed
BB
344/**
345 * pwm_enable() - start a PWM output toggling
346 * @pwm: PWM device
347 *
348 * Returns: 0 on success or a negative error code on failure.
349 */
350static inline int pwm_enable(struct pwm_device *pwm)
351{
352 struct pwm_state state;
353
354 if (!pwm)
355 return -EINVAL;
356
357 pwm_get_state(pwm, &state);
358 if (state.enabled)
359 return 0;
360
361 state.enabled = true;
c748a6d7 362 return pwm_apply_might_sleep(pwm, &state);
5ec803ed
BB
363}
364
365/**
366 * pwm_disable() - stop a PWM output toggling
367 * @pwm: PWM device
368 */
369static inline void pwm_disable(struct pwm_device *pwm)
370{
371 struct pwm_state state;
372
373 if (!pwm)
374 return;
375
376 pwm_get_state(pwm, &state);
377 if (!state.enabled)
378 return;
379
380 state.enabled = false;
c748a6d7 381 pwm_apply_might_sleep(pwm, &state);
5ec803ed
BB
382}
383
7170d3be
SY
384/**
385 * pwm_might_sleep() - is pwm_apply_atomic() supported?
386 * @pwm: PWM device
387 *
388 * Returns: false if pwm_apply_atomic() can be called from atomic context.
389 */
390static inline bool pwm_might_sleep(struct pwm_device *pwm)
391{
392 return !pwm->chip->atomic;
393}
394
5ec803ed 395/* PWM provider APIs */
3a3d1a4e
LJ
396int pwm_capture(struct pwm_device *pwm, struct pwm_capture *result,
397 unsigned long timeout);
f051c466 398
024913db
UKK
399void pwmchip_put(struct pwm_chip *chip);
400struct pwm_chip *pwmchip_alloc(struct device *parent, unsigned int npwm, size_t sizeof_priv);
401struct pwm_chip *devm_pwmchip_alloc(struct device *parent, unsigned int npwm, size_t sizeof_priv);
402
384461ab
UKK
403int __pwmchip_add(struct pwm_chip *chip, struct module *owner);
404#define pwmchip_add(chip) __pwmchip_add(chip, THIS_MODULE)
8083f58d 405void pwmchip_remove(struct pwm_chip *chip);
bcda91bf 406
384461ab
UKK
407int __devm_pwmchip_add(struct device *dev, struct pwm_chip *chip, struct module *owner);
408#define devm_pwmchip_add(dev, chip) __devm_pwmchip_add(dev, chip, THIS_MODULE)
bcda91bf 409
f051c466
TR
410struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip,
411 unsigned int index,
412 const char *label);
8138d2dd 413
b4f78ff7 414struct pwm_device *of_pwm_xlate_with_flags(struct pwm_chip *chip,
83af2402 415 const struct of_phandle_args *args);
b4f78ff7 416struct pwm_device *of_pwm_single_xlate(struct pwm_chip *chip,
3ab7b6ac 417 const struct of_phandle_args *args);
83af2402 418
d4c0c470 419struct pwm_device *pwm_get(struct device *dev, const char *con_id);
8138d2dd
TR
420void pwm_put(struct pwm_device *pwm);
421
d4c0c470 422struct pwm_device *devm_pwm_get(struct device *dev, const char *con_id);
4a6ef8e3
NV
423struct pwm_device *devm_fwnode_pwm_get(struct device *dev,
424 struct fwnode_handle *fwnode,
425 const char *con_id);
0bcf168b 426#else
7170d3be
SY
427static inline bool pwm_might_sleep(struct pwm_device *pwm)
428{
429 return true;
430}
431
c748a6d7
SY
432static inline int pwm_apply_might_sleep(struct pwm_device *pwm,
433 const struct pwm_state *state)
5ec803ed 434{
4ad91a22 435 might_sleep();
dc518b37 436 return -EOPNOTSUPP;
5ec803ed
BB
437}
438
7170d3be
SY
439static inline int pwm_apply_atomic(struct pwm_device *pwm,
440 const struct pwm_state *state)
441{
442 return -EOPNOTSUPP;
443}
444
5ec803ed
BB
445static inline int pwm_adjust_config(struct pwm_device *pwm)
446{
dc518b37 447 return -EOPNOTSUPP;
5ec803ed
BB
448}
449
450static inline int pwm_config(struct pwm_device *pwm, int duty_ns,
451 int period_ns)
452{
4ad91a22 453 might_sleep();
5ec803ed
BB
454 return -EINVAL;
455}
456
5ec803ed
BB
457static inline int pwm_enable(struct pwm_device *pwm)
458{
4ad91a22 459 might_sleep();
5ec803ed
BB
460 return -EINVAL;
461}
462
463static inline void pwm_disable(struct pwm_device *pwm)
464{
4ad91a22 465 might_sleep();
5ec803ed
BB
466}
467
b3c650ad
GU
468static inline int pwm_capture(struct pwm_device *pwm,
469 struct pwm_capture *result,
470 unsigned long timeout)
471{
472 return -EINVAL;
473}
474
024913db
UKK
475static inline void pwmchip_put(struct pwm_chip *chip)
476{
477}
478
479static inline struct pwm_chip *pwmchip_alloc(struct device *parent,
480 unsigned int npwm,
481 size_t sizeof_priv)
482{
483 return ERR_PTR(-EINVAL);
484}
485
486static inline struct pwm_chip *devm_pwmchip_alloc(struct device *parent,
487 unsigned int npwm,
488 size_t sizeof_priv)
489{
490 return pwmchip_alloc(parent, npwm, sizeof_priv);
491}
492
0bcf168b
TB
493static inline int pwmchip_add(struct pwm_chip *chip)
494{
495 return -EINVAL;
496}
497
498static inline int pwmchip_remove(struct pwm_chip *chip)
499{
500 return -EINVAL;
501}
502
88da4e81
AS
503static inline int devm_pwmchip_add(struct device *dev, struct pwm_chip *chip)
504{
505 return -EINVAL;
506}
507
0bcf168b
TB
508static inline struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip,
509 unsigned int index,
510 const char *label)
511{
27d9a4d6 512 might_sleep();
0bcf168b
TB
513 return ERR_PTR(-ENODEV);
514}
515
516static inline struct pwm_device *pwm_get(struct device *dev,
517 const char *consumer)
518{
27d9a4d6 519 might_sleep();
0bcf168b
TB
520 return ERR_PTR(-ENODEV);
521}
522
523static inline void pwm_put(struct pwm_device *pwm)
524{
27d9a4d6 525 might_sleep();
0bcf168b
TB
526}
527
528static inline struct pwm_device *devm_pwm_get(struct device *dev,
529 const char *consumer)
530{
27d9a4d6 531 might_sleep();
0bcf168b
TB
532 return ERR_PTR(-ENODEV);
533}
534
4a6ef8e3
NV
535static inline struct pwm_device *
536devm_fwnode_pwm_get(struct device *dev, struct fwnode_handle *fwnode,
537 const char *con_id)
538{
27d9a4d6 539 might_sleep();
4a6ef8e3
NV
540 return ERR_PTR(-ENODEV);
541}
0bcf168b 542#endif
6354316d 543
5ec803ed
BB
544static inline void pwm_apply_args(struct pwm_device *pwm)
545{
33cdcee0
BB
546 struct pwm_state state = { };
547
5ec803ed
BB
548 /*
549 * PWM users calling pwm_apply_args() expect to have a fresh config
550 * where the polarity and period are set according to pwm_args info.
551 * The problem is, polarity can only be changed when the PWM is
552 * disabled.
553 *
554 * PWM drivers supporting hardware readout may declare the PWM device
555 * as enabled, and prevent polarity setting, which changes from the
556 * existing behavior, where all PWM devices are declared as disabled
557 * at startup (even if they are actually enabled), thus authorizing
558 * polarity setting.
559 *
33cdcee0
BB
560 * To fulfill this requirement, we apply a new state which disables
561 * the PWM device and set the reference period and polarity config.
5ec803ed
BB
562 *
563 * Note that PWM users requiring a smooth handover between the
564 * bootloader and the kernel (like critical regulators controlled by
565 * PWM devices) will have to switch to the atomic API and avoid calling
566 * pwm_apply_args().
567 */
33cdcee0
BB
568
569 state.enabled = false;
570 state.polarity = pwm->args.polarity;
571 state.period = pwm->args.period;
9e40ee18 572 state.usage_power = false;
33cdcee0 573
c748a6d7 574 pwm_apply_might_sleep(pwm, &state);
5ec803ed
BB
575}
576
c2e64baa
TR
577/* only for backwards-compatibility, new code should not use this */
578static inline int pwm_apply_state(struct pwm_device *pwm,
579 const struct pwm_state *state)
580{
581 return pwm_apply_might_sleep(pwm, state);
582}
583
8138d2dd
TR
584struct pwm_lookup {
585 struct list_head list;
586 const char *provider;
587 unsigned int index;
588 const char *dev_id;
589 const char *con_id;
3796ce1d
AB
590 unsigned int period;
591 enum pwm_polarity polarity;
b526a314 592 const char *module; /* optional, may be NULL */
8138d2dd
TR
593};
594
b526a314
HG
595#define PWM_LOOKUP_WITH_MODULE(_provider, _index, _dev_id, _con_id, \
596 _period, _polarity, _module) \
597 { \
598 .provider = _provider, \
599 .index = _index, \
600 .dev_id = _dev_id, \
601 .con_id = _con_id, \
602 .period = _period, \
603 .polarity = _polarity, \
604 .module = _module, \
8138d2dd
TR
605 }
606
b526a314
HG
607#define PWM_LOOKUP(_provider, _index, _dev_id, _con_id, _period, _polarity) \
608 PWM_LOOKUP_WITH_MODULE(_provider, _index, _dev_id, _con_id, _period, \
609 _polarity, NULL)
610
0bcf168b 611#if IS_ENABLED(CONFIG_PWM)
8138d2dd 612void pwm_add_table(struct pwm_lookup *table, size_t num);
efb0de55 613void pwm_remove_table(struct pwm_lookup *table, size_t num);
0bcf168b
TB
614#else
615static inline void pwm_add_table(struct pwm_lookup *table, size_t num)
616{
617}
efb0de55
SK
618
619static inline void pwm_remove_table(struct pwm_lookup *table, size_t num)
620{
621}
0c2498f1
SH
622#endif
623
5243ef8b 624#endif /* __LINUX_PWM_H */