13d0407baSopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 23d0407baSopenharmony_ci#ifndef __LINUX_PWM_H 33d0407baSopenharmony_ci#define __LINUX_PWM_H 43d0407baSopenharmony_ci 53d0407baSopenharmony_ci#include <linux/err.h> 63d0407baSopenharmony_ci#include <linux/mutex.h> 73d0407baSopenharmony_ci#include <linux/of.h> 83d0407baSopenharmony_ci 93d0407baSopenharmony_cistruct pwm_capture; 103d0407baSopenharmony_cistruct seq_file; 113d0407baSopenharmony_ci 123d0407baSopenharmony_cistruct pwm_chip; 133d0407baSopenharmony_ci 143d0407baSopenharmony_ci/** 153d0407baSopenharmony_ci * enum pwm_polarity - polarity of a PWM signal 163d0407baSopenharmony_ci * @PWM_POLARITY_NORMAL: a high signal for the duration of the duty- 173d0407baSopenharmony_ci * cycle, followed by a low signal for the remainder of the pulse 183d0407baSopenharmony_ci * period 193d0407baSopenharmony_ci * @PWM_POLARITY_INVERSED: a low signal for the duration of the duty- 203d0407baSopenharmony_ci * cycle, followed by a high signal for the remainder of the pulse 213d0407baSopenharmony_ci * period 223d0407baSopenharmony_ci */ 233d0407baSopenharmony_cienum pwm_polarity { 243d0407baSopenharmony_ci PWM_POLARITY_NORMAL, 253d0407baSopenharmony_ci PWM_POLARITY_INVERSED, 263d0407baSopenharmony_ci}; 273d0407baSopenharmony_ci 283d0407baSopenharmony_ci/** 293d0407baSopenharmony_ci * struct pwm_args - board-dependent PWM arguments 303d0407baSopenharmony_ci * @period: reference period 313d0407baSopenharmony_ci * @polarity: reference polarity 323d0407baSopenharmony_ci * 333d0407baSopenharmony_ci * This structure describes board-dependent arguments attached to a PWM 343d0407baSopenharmony_ci * device. These arguments are usually retrieved from the PWM lookup table or 353d0407baSopenharmony_ci * device tree. 363d0407baSopenharmony_ci * 373d0407baSopenharmony_ci * Do not confuse this with the PWM state: PWM arguments represent the initial 383d0407baSopenharmony_ci * configuration that users want to use on this PWM device rather than the 393d0407baSopenharmony_ci * current PWM hardware state. 403d0407baSopenharmony_ci */ 413d0407baSopenharmony_cistruct pwm_args { 423d0407baSopenharmony_ci u64 period; 433d0407baSopenharmony_ci enum pwm_polarity polarity; 443d0407baSopenharmony_ci}; 453d0407baSopenharmony_ci 463d0407baSopenharmony_cienum { 473d0407baSopenharmony_ci PWMF_REQUESTED = 1 << 0, 483d0407baSopenharmony_ci PWMF_EXPORTED = 1 << 1, 493d0407baSopenharmony_ci}; 503d0407baSopenharmony_ci 513d0407baSopenharmony_ci/* 523d0407baSopenharmony_ci * struct pwm_state - state of a PWM channel 533d0407baSopenharmony_ci * @period: PWM period (in nanoseconds) 543d0407baSopenharmony_ci * @duty_cycle: PWM duty cycle (in nanoseconds) 553d0407baSopenharmony_ci * @polarity: PWM polarity 563d0407baSopenharmony_ci * @enabled: PWM enabled status 573d0407baSopenharmony_ci */ 583d0407baSopenharmony_cistruct pwm_state { 593d0407baSopenharmony_ci u64 period; 603d0407baSopenharmony_ci u64 duty_cycle; 613d0407baSopenharmony_ci enum pwm_polarity polarity; 623d0407baSopenharmony_ci#ifdef CONFIG_PWM_ROCKCHIP_ONESHOT 633d0407baSopenharmony_ci u64 oneshot_count; 643d0407baSopenharmony_ci#endif /* CONFIG_PWM_ROCKCHIP_ONESHOT */ 653d0407baSopenharmony_ci bool enabled; 663d0407baSopenharmony_ci}; 673d0407baSopenharmony_ci 683d0407baSopenharmony_ci/** 693d0407baSopenharmony_ci * struct pwm_device - PWM channel object 703d0407baSopenharmony_ci * @label: name of the PWM device 713d0407baSopenharmony_ci * @flags: flags associated with the PWM device 723d0407baSopenharmony_ci * @hwpwm: per-chip relative index of the PWM device 733d0407baSopenharmony_ci * @pwm: global index of the PWM device 743d0407baSopenharmony_ci * @chip: PWM chip providing this PWM device 753d0407baSopenharmony_ci * @chip_data: chip-private data associated with the PWM device 763d0407baSopenharmony_ci * @args: PWM arguments 773d0407baSopenharmony_ci * @state: last applied state 783d0407baSopenharmony_ci * @last: last implemented state (for PWM_DEBUG) 793d0407baSopenharmony_ci */ 803d0407baSopenharmony_cistruct pwm_device { 813d0407baSopenharmony_ci const char *label; 823d0407baSopenharmony_ci unsigned long flags; 833d0407baSopenharmony_ci unsigned int hwpwm; 843d0407baSopenharmony_ci unsigned int pwm; 853d0407baSopenharmony_ci struct pwm_chip *chip; 863d0407baSopenharmony_ci void *chip_data; 873d0407baSopenharmony_ci 883d0407baSopenharmony_ci struct pwm_args args; 893d0407baSopenharmony_ci struct pwm_state state; 903d0407baSopenharmony_ci struct pwm_state last; 913d0407baSopenharmony_ci}; 923d0407baSopenharmony_ci 933d0407baSopenharmony_ci/** 943d0407baSopenharmony_ci * pwm_get_state() - retrieve the current PWM state 953d0407baSopenharmony_ci * @pwm: PWM device 963d0407baSopenharmony_ci * @state: state to fill with the current PWM state 973d0407baSopenharmony_ci */ 983d0407baSopenharmony_cistatic inline void pwm_get_state(const struct pwm_device *pwm, struct pwm_state *state) 993d0407baSopenharmony_ci{ 1003d0407baSopenharmony_ci *state = pwm->state; 1013d0407baSopenharmony_ci} 1023d0407baSopenharmony_ci 1033d0407baSopenharmony_cistatic inline bool pwm_is_enabled(const struct pwm_device *pwm) 1043d0407baSopenharmony_ci{ 1053d0407baSopenharmony_ci struct pwm_state state; 1063d0407baSopenharmony_ci 1073d0407baSopenharmony_ci pwm_get_state(pwm, &state); 1083d0407baSopenharmony_ci 1093d0407baSopenharmony_ci return state.enabled; 1103d0407baSopenharmony_ci} 1113d0407baSopenharmony_ci 1123d0407baSopenharmony_cistatic inline void pwm_set_period(struct pwm_device *pwm, u64 period) 1133d0407baSopenharmony_ci{ 1143d0407baSopenharmony_ci if (pwm) { 1153d0407baSopenharmony_ci pwm->state.period = period; 1163d0407baSopenharmony_ci } 1173d0407baSopenharmony_ci} 1183d0407baSopenharmony_ci 1193d0407baSopenharmony_cistatic inline u64 pwm_get_period(const struct pwm_device *pwm) 1203d0407baSopenharmony_ci{ 1213d0407baSopenharmony_ci struct pwm_state state; 1223d0407baSopenharmony_ci 1233d0407baSopenharmony_ci pwm_get_state(pwm, &state); 1243d0407baSopenharmony_ci 1253d0407baSopenharmony_ci return state.period; 1263d0407baSopenharmony_ci} 1273d0407baSopenharmony_ci 1283d0407baSopenharmony_cistatic inline void pwm_set_duty_cycle(struct pwm_device *pwm, unsigned int duty) 1293d0407baSopenharmony_ci{ 1303d0407baSopenharmony_ci if (pwm) { 1313d0407baSopenharmony_ci pwm->state.duty_cycle = duty; 1323d0407baSopenharmony_ci } 1333d0407baSopenharmony_ci} 1343d0407baSopenharmony_ci 1353d0407baSopenharmony_cistatic inline u64 pwm_get_duty_cycle(const struct pwm_device *pwm) 1363d0407baSopenharmony_ci{ 1373d0407baSopenharmony_ci struct pwm_state state; 1383d0407baSopenharmony_ci 1393d0407baSopenharmony_ci pwm_get_state(pwm, &state); 1403d0407baSopenharmony_ci 1413d0407baSopenharmony_ci return state.duty_cycle; 1423d0407baSopenharmony_ci} 1433d0407baSopenharmony_ci 1443d0407baSopenharmony_cistatic inline enum pwm_polarity pwm_get_polarity(const struct pwm_device *pwm) 1453d0407baSopenharmony_ci{ 1463d0407baSopenharmony_ci struct pwm_state state; 1473d0407baSopenharmony_ci 1483d0407baSopenharmony_ci pwm_get_state(pwm, &state); 1493d0407baSopenharmony_ci 1503d0407baSopenharmony_ci return state.polarity; 1513d0407baSopenharmony_ci} 1523d0407baSopenharmony_ci 1533d0407baSopenharmony_cistatic inline void pwm_get_args(const struct pwm_device *pwm, struct pwm_args *args) 1543d0407baSopenharmony_ci{ 1553d0407baSopenharmony_ci *args = pwm->args; 1563d0407baSopenharmony_ci} 1573d0407baSopenharmony_ci 1583d0407baSopenharmony_ci/** 1593d0407baSopenharmony_ci * pwm_init_state() - prepare a new state to be applied with pwm_apply_state() 1603d0407baSopenharmony_ci * @pwm: PWM device 1613d0407baSopenharmony_ci * @state: state to fill with the prepared PWM state 1623d0407baSopenharmony_ci * 1633d0407baSopenharmony_ci * This functions prepares a state that can later be tweaked and applied 1643d0407baSopenharmony_ci * to the PWM device with pwm_apply_state(). This is a convenient function 1653d0407baSopenharmony_ci * that first retrieves the current PWM state and the replaces the period 1663d0407baSopenharmony_ci * and polarity fields with the reference values defined in pwm->args. 1673d0407baSopenharmony_ci * Once the function returns, you can adjust the ->enabled and ->duty_cycle 1683d0407baSopenharmony_ci * fields according to your needs before calling pwm_apply_state(). 1693d0407baSopenharmony_ci * 1703d0407baSopenharmony_ci * ->duty_cycle is initially set to zero to avoid cases where the current 1713d0407baSopenharmony_ci * ->duty_cycle value exceed the pwm_args->period one, which would trigger 1723d0407baSopenharmony_ci * an error if the user calls pwm_apply_state() without adjusting ->duty_cycle 1733d0407baSopenharmony_ci * first. 1743d0407baSopenharmony_ci */ 1753d0407baSopenharmony_cistatic inline void pwm_init_state(const struct pwm_device *pwm, struct pwm_state *state) 1763d0407baSopenharmony_ci{ 1773d0407baSopenharmony_ci struct pwm_args args; 1783d0407baSopenharmony_ci 1793d0407baSopenharmony_ci /* First get the current state. */ 1803d0407baSopenharmony_ci pwm_get_state(pwm, state); 1813d0407baSopenharmony_ci 1823d0407baSopenharmony_ci /* Then fill it with the reference config */ 1833d0407baSopenharmony_ci pwm_get_args(pwm, &args); 1843d0407baSopenharmony_ci 1853d0407baSopenharmony_ci state->period = args.period; 1863d0407baSopenharmony_ci state->polarity = args.polarity; 1873d0407baSopenharmony_ci state->duty_cycle = 0; 1883d0407baSopenharmony_ci} 1893d0407baSopenharmony_ci 1903d0407baSopenharmony_ci/** 1913d0407baSopenharmony_ci * pwm_get_relative_duty_cycle() - Get a relative duty cycle value 1923d0407baSopenharmony_ci * @state: PWM state to extract the duty cycle from 1933d0407baSopenharmony_ci * @scale: target scale of the relative duty cycle 1943d0407baSopenharmony_ci * 1953d0407baSopenharmony_ci * This functions converts the absolute duty cycle stored in @state (expressed 1963d0407baSopenharmony_ci * in nanosecond) into a value relative to the period. 1973d0407baSopenharmony_ci * 1983d0407baSopenharmony_ci * For example if you want to get the duty_cycle expressed in percent, call: 1993d0407baSopenharmony_ci * 2003d0407baSopenharmony_ci * pwm_get_state(pwm, &state); 2013d0407baSopenharmony_ci * duty = pwm_get_relative_duty_cycle(&state, 100); 2023d0407baSopenharmony_ci */ 2033d0407baSopenharmony_cistatic inline unsigned int pwm_get_relative_duty_cycle(const struct pwm_state *state, unsigned int scale) 2043d0407baSopenharmony_ci{ 2053d0407baSopenharmony_ci if (!state->period) { 2063d0407baSopenharmony_ci return 0; 2073d0407baSopenharmony_ci } 2083d0407baSopenharmony_ci 2093d0407baSopenharmony_ci return DIV_ROUND_CLOSEST_ULL((u64)state->duty_cycle * scale, state->period); 2103d0407baSopenharmony_ci} 2113d0407baSopenharmony_ci 2123d0407baSopenharmony_ci/** 2133d0407baSopenharmony_ci * pwm_set_relative_duty_cycle() - Set a relative duty cycle value 2143d0407baSopenharmony_ci * @state: PWM state to fill 2153d0407baSopenharmony_ci * @duty_cycle: relative duty cycle value 2163d0407baSopenharmony_ci * @scale: scale in which @duty_cycle is expressed 2173d0407baSopenharmony_ci * 2183d0407baSopenharmony_ci * This functions converts a relative into an absolute duty cycle (expressed 2193d0407baSopenharmony_ci * in nanoseconds), and puts the result in state->duty_cycle. 2203d0407baSopenharmony_ci * 2213d0407baSopenharmony_ci * For example if you want to configure a 50% duty cycle, call: 2223d0407baSopenharmony_ci * 2233d0407baSopenharmony_ci * pwm_init_state(pwm, &state); 2243d0407baSopenharmony_ci * pwm_set_relative_duty_cycle(&state, 50, 100); 2253d0407baSopenharmony_ci * pwm_apply_state(pwm, &state); 2263d0407baSopenharmony_ci * 2273d0407baSopenharmony_ci * This functions returns -EINVAL if @duty_cycle and/or @scale are 2283d0407baSopenharmony_ci * inconsistent (@scale == 0 or @duty_cycle > @scale). 2293d0407baSopenharmony_ci */ 2303d0407baSopenharmony_cistatic inline int pwm_set_relative_duty_cycle(struct pwm_state *state, unsigned int duty_cycle, unsigned int scale) 2313d0407baSopenharmony_ci{ 2323d0407baSopenharmony_ci if (!scale || duty_cycle > scale) { 2333d0407baSopenharmony_ci return -EINVAL; 2343d0407baSopenharmony_ci } 2353d0407baSopenharmony_ci 2363d0407baSopenharmony_ci state->duty_cycle = DIV_ROUND_CLOSEST_ULL((u64)duty_cycle * state->period, scale); 2373d0407baSopenharmony_ci 2383d0407baSopenharmony_ci return 0; 2393d0407baSopenharmony_ci} 2403d0407baSopenharmony_ci 2413d0407baSopenharmony_ci/** 2423d0407baSopenharmony_ci * struct pwm_ops - PWM controller operations 2433d0407baSopenharmony_ci * @request: optional hook for requesting a PWM 2443d0407baSopenharmony_ci * @free: optional hook for freeing a PWM 2453d0407baSopenharmony_ci * @capture: capture and report PWM signal 2463d0407baSopenharmony_ci * @apply: atomically apply a new PWM config 2473d0407baSopenharmony_ci * @get_state: get the current PWM state. This function is only 2483d0407baSopenharmony_ci * called once per PWM device when the PWM chip is 2493d0407baSopenharmony_ci * registered. 2503d0407baSopenharmony_ci * @owner: helps prevent removal of modules exporting active PWMs 2513d0407baSopenharmony_ci * @config: configure duty cycles and period length for this PWM 2523d0407baSopenharmony_ci * @set_polarity: configure the polarity of this PWM 2533d0407baSopenharmony_ci * @enable: enable PWM output toggling 2543d0407baSopenharmony_ci * @disable: disable PWM output toggling 2553d0407baSopenharmony_ci */ 2563d0407baSopenharmony_cistruct pwm_ops { 2573d0407baSopenharmony_ci int (*request)(struct pwm_chip *chip, struct pwm_device *pwm); 2583d0407baSopenharmony_ci void (*free)(struct pwm_chip *chip, struct pwm_device *pwm); 2593d0407baSopenharmony_ci int (*capture)(struct pwm_chip *chip, struct pwm_device *pwm, struct pwm_capture *result, unsigned long timeout); 2603d0407baSopenharmony_ci int (*apply)(struct pwm_chip *chip, struct pwm_device *pwm, const struct pwm_state *state); 2613d0407baSopenharmony_ci void (*get_state)(struct pwm_chip *chip, struct pwm_device *pwm, struct pwm_state *state); 2623d0407baSopenharmony_ci struct module *owner; 2633d0407baSopenharmony_ci 2643d0407baSopenharmony_ci /* Only used by legacy drivers */ 2653d0407baSopenharmony_ci int (*config)(struct pwm_chip *chip, struct pwm_device *pwm, int duty_ns, int period_ns); 2663d0407baSopenharmony_ci int (*set_polarity)(struct pwm_chip *chip, struct pwm_device *pwm, enum pwm_polarity polarity); 2673d0407baSopenharmony_ci int (*enable)(struct pwm_chip *chip, struct pwm_device *pwm); 2683d0407baSopenharmony_ci void (*disable)(struct pwm_chip *chip, struct pwm_device *pwm); 2693d0407baSopenharmony_ci}; 2703d0407baSopenharmony_ci 2713d0407baSopenharmony_ci/** 2723d0407baSopenharmony_ci * struct pwm_chip - abstract a PWM controller 2733d0407baSopenharmony_ci * @dev: device providing the PWMs 2743d0407baSopenharmony_ci * @ops: callbacks for this PWM controller 2753d0407baSopenharmony_ci * @base: number of first PWM controlled by this chip 2763d0407baSopenharmony_ci * @npwm: number of PWMs controlled by this chip 2773d0407baSopenharmony_ci * @of_xlate: request a PWM device given a device tree PWM specifier 2783d0407baSopenharmony_ci * @of_pwm_n_cells: number of cells expected in the device tree PWM specifier 2793d0407baSopenharmony_ci * @list: list node for internal use 2803d0407baSopenharmony_ci * @pwms: array of PWM devices allocated by the framework 2813d0407baSopenharmony_ci */ 2823d0407baSopenharmony_cistruct pwm_chip { 2833d0407baSopenharmony_ci struct device *dev; 2843d0407baSopenharmony_ci const struct pwm_ops *ops; 2853d0407baSopenharmony_ci int base; 2863d0407baSopenharmony_ci unsigned int npwm; 2873d0407baSopenharmony_ci 2883d0407baSopenharmony_ci struct pwm_device *(*of_xlate)(struct pwm_chip *pc, const struct of_phandle_args *args); 2893d0407baSopenharmony_ci unsigned int of_pwm_n_cells; 2903d0407baSopenharmony_ci 2913d0407baSopenharmony_ci /* only used internally by the PWM framework */ 2923d0407baSopenharmony_ci struct list_head list; 2933d0407baSopenharmony_ci struct pwm_device *pwms; 2943d0407baSopenharmony_ci}; 2953d0407baSopenharmony_ci 2963d0407baSopenharmony_ci/** 2973d0407baSopenharmony_ci * struct pwm_capture - PWM capture data 2983d0407baSopenharmony_ci * @period: period of the PWM signal (in nanoseconds) 2993d0407baSopenharmony_ci * @duty_cycle: duty cycle of the PWM signal (in nanoseconds) 3003d0407baSopenharmony_ci */ 3013d0407baSopenharmony_cistruct pwm_capture { 3023d0407baSopenharmony_ci unsigned int period; 3033d0407baSopenharmony_ci unsigned int duty_cycle; 3043d0407baSopenharmony_ci}; 3053d0407baSopenharmony_ci 3063d0407baSopenharmony_ci#if IS_ENABLED(CONFIG_PWM) 3073d0407baSopenharmony_ci/* PWM user APIs */ 3083d0407baSopenharmony_cistruct pwm_device *pwm_request(int pwm_id, const char *label); 3093d0407baSopenharmony_civoid pwm_free(struct pwm_device *pwm); 3103d0407baSopenharmony_ciint pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state); 3113d0407baSopenharmony_ciint pwm_adjust_config(struct pwm_device *pwm); 3123d0407baSopenharmony_ci 3133d0407baSopenharmony_ci/** 3143d0407baSopenharmony_ci * pwm_config() - change a PWM device configuration 3153d0407baSopenharmony_ci * @pwm: PWM device 3163d0407baSopenharmony_ci * @duty_ns: "on" time (in nanoseconds) 3173d0407baSopenharmony_ci * @period_ns: duration (in nanoseconds) of one cycle 3183d0407baSopenharmony_ci * 3193d0407baSopenharmony_ci * Returns: 0 on success or a negative error code on failure. 3203d0407baSopenharmony_ci */ 3213d0407baSopenharmony_cistatic inline int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) 3223d0407baSopenharmony_ci{ 3233d0407baSopenharmony_ci struct pwm_state state; 3243d0407baSopenharmony_ci 3253d0407baSopenharmony_ci if (!pwm) { 3263d0407baSopenharmony_ci return -EINVAL; 3273d0407baSopenharmony_ci } 3283d0407baSopenharmony_ci 3293d0407baSopenharmony_ci if (duty_ns < 0 || period_ns < 0) { 3303d0407baSopenharmony_ci return -EINVAL; 3313d0407baSopenharmony_ci } 3323d0407baSopenharmony_ci 3333d0407baSopenharmony_ci pwm_get_state(pwm, &state); 3343d0407baSopenharmony_ci if (state.duty_cycle == duty_ns && state.period == period_ns) { 3353d0407baSopenharmony_ci return 0; 3363d0407baSopenharmony_ci } 3373d0407baSopenharmony_ci 3383d0407baSopenharmony_ci state.duty_cycle = duty_ns; 3393d0407baSopenharmony_ci state.period = period_ns; 3403d0407baSopenharmony_ci return pwm_apply_state(pwm, &state); 3413d0407baSopenharmony_ci} 3423d0407baSopenharmony_ci 3433d0407baSopenharmony_ci/** 3443d0407baSopenharmony_ci * pwm_enable() - start a PWM output toggling 3453d0407baSopenharmony_ci * @pwm: PWM device 3463d0407baSopenharmony_ci * 3473d0407baSopenharmony_ci * Returns: 0 on success or a negative error code on failure. 3483d0407baSopenharmony_ci */ 3493d0407baSopenharmony_cistatic inline int pwm_enable(struct pwm_device *pwm) 3503d0407baSopenharmony_ci{ 3513d0407baSopenharmony_ci struct pwm_state state; 3523d0407baSopenharmony_ci 3533d0407baSopenharmony_ci if (!pwm) { 3543d0407baSopenharmony_ci return -EINVAL; 3553d0407baSopenharmony_ci } 3563d0407baSopenharmony_ci 3573d0407baSopenharmony_ci pwm_get_state(pwm, &state); 3583d0407baSopenharmony_ci if (state.enabled) { 3593d0407baSopenharmony_ci return 0; 3603d0407baSopenharmony_ci } 3613d0407baSopenharmony_ci 3623d0407baSopenharmony_ci state.enabled = true; 3633d0407baSopenharmony_ci return pwm_apply_state(pwm, &state); 3643d0407baSopenharmony_ci} 3653d0407baSopenharmony_ci 3663d0407baSopenharmony_ci/** 3673d0407baSopenharmony_ci * pwm_disable() - stop a PWM output toggling 3683d0407baSopenharmony_ci * @pwm: PWM device 3693d0407baSopenharmony_ci */ 3703d0407baSopenharmony_cistatic inline void pwm_disable(struct pwm_device *pwm) 3713d0407baSopenharmony_ci{ 3723d0407baSopenharmony_ci struct pwm_state state; 3733d0407baSopenharmony_ci 3743d0407baSopenharmony_ci if (!pwm) { 3753d0407baSopenharmony_ci return; 3763d0407baSopenharmony_ci } 3773d0407baSopenharmony_ci 3783d0407baSopenharmony_ci pwm_get_state(pwm, &state); 3793d0407baSopenharmony_ci if (!state.enabled) { 3803d0407baSopenharmony_ci return; 3813d0407baSopenharmony_ci } 3823d0407baSopenharmony_ci 3833d0407baSopenharmony_ci state.enabled = false; 3843d0407baSopenharmony_ci pwm_apply_state(pwm, &state); 3853d0407baSopenharmony_ci} 3863d0407baSopenharmony_ci 3873d0407baSopenharmony_ci/* PWM provider APIs */ 3883d0407baSopenharmony_ciint pwm_capture(struct pwm_device *pwm, struct pwm_capture *result, unsigned long timeout); 3893d0407baSopenharmony_ciint pwm_set_chip_data(struct pwm_device *pwm, void *data); 3903d0407baSopenharmony_civoid *pwm_get_chip_data(struct pwm_device *pwm); 3913d0407baSopenharmony_ci 3923d0407baSopenharmony_ciint pwmchip_add_with_polarity(struct pwm_chip *chip, enum pwm_polarity polarity); 3933d0407baSopenharmony_ciint pwmchip_add(struct pwm_chip *chip); 3943d0407baSopenharmony_ciint pwmchip_remove(struct pwm_chip *chip); 3953d0407baSopenharmony_cistruct pwm_device *pwm_request_from_chip(struct pwm_chip *chip, unsigned int index, const char *label); 3963d0407baSopenharmony_ci 3973d0407baSopenharmony_cistruct pwm_device *of_pwm_xlate_with_flags(struct pwm_chip *pc, const struct of_phandle_args *args); 3983d0407baSopenharmony_ci 3993d0407baSopenharmony_cistruct pwm_device *pwm_get(struct device *dev, const char *con_id); 4003d0407baSopenharmony_cistruct pwm_device *of_pwm_get(struct device *dev, struct device_node *np, const char *con_id); 4013d0407baSopenharmony_civoid pwm_put(struct pwm_device *pwm); 4023d0407baSopenharmony_ci 4033d0407baSopenharmony_cistruct pwm_device *devm_pwm_get(struct device *dev, const char *con_id); 4043d0407baSopenharmony_cistruct pwm_device *devm_of_pwm_get(struct device *dev, struct device_node *np, const char *con_id); 4053d0407baSopenharmony_cistruct pwm_device *devm_fwnode_pwm_get(struct device *dev, struct fwnode_handle *fwnode, const char *con_id); 4063d0407baSopenharmony_civoid devm_pwm_put(struct device *dev, struct pwm_device *pwm); 4073d0407baSopenharmony_ci#else 4083d0407baSopenharmony_cistatic inline struct pwm_device *pwm_request(int pwm_id, const char *label) 4093d0407baSopenharmony_ci{ 4103d0407baSopenharmony_ci return ERR_PTR(-ENODEV); 4113d0407baSopenharmony_ci} 4123d0407baSopenharmony_ci 4133d0407baSopenharmony_cistatic inline void pwm_free(struct pwm_device *pwm) 4143d0407baSopenharmony_ci{ 4153d0407baSopenharmony_ci} 4163d0407baSopenharmony_ci 4173d0407baSopenharmony_cistatic inline int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state) 4183d0407baSopenharmony_ci{ 4193d0407baSopenharmony_ci return -ENOTSUPP; 4203d0407baSopenharmony_ci} 4213d0407baSopenharmony_ci 4223d0407baSopenharmony_cistatic inline int pwm_adjust_config(struct pwm_device *pwm) 4233d0407baSopenharmony_ci{ 4243d0407baSopenharmony_ci return -ENOTSUPP; 4253d0407baSopenharmony_ci} 4263d0407baSopenharmony_ci 4273d0407baSopenharmony_cistatic inline int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) 4283d0407baSopenharmony_ci{ 4293d0407baSopenharmony_ci return -EINVAL; 4303d0407baSopenharmony_ci} 4313d0407baSopenharmony_ci 4323d0407baSopenharmony_cistatic inline int pwm_capture(struct pwm_device *pwm, struct pwm_capture *result, unsigned long timeout) 4333d0407baSopenharmony_ci{ 4343d0407baSopenharmony_ci return -EINVAL; 4353d0407baSopenharmony_ci} 4363d0407baSopenharmony_ci 4373d0407baSopenharmony_cistatic inline int pwm_enable(struct pwm_device *pwm) 4383d0407baSopenharmony_ci{ 4393d0407baSopenharmony_ci return -EINVAL; 4403d0407baSopenharmony_ci} 4413d0407baSopenharmony_ci 4423d0407baSopenharmony_cistatic inline void pwm_disable(struct pwm_device *pwm) 4433d0407baSopenharmony_ci{ 4443d0407baSopenharmony_ci} 4453d0407baSopenharmony_ci 4463d0407baSopenharmony_cistatic inline int pwm_set_chip_data(struct pwm_device *pwm, void *data) 4473d0407baSopenharmony_ci{ 4483d0407baSopenharmony_ci return -EINVAL; 4493d0407baSopenharmony_ci} 4503d0407baSopenharmony_ci 4513d0407baSopenharmony_cistatic inline void *pwm_get_chip_data(struct pwm_device *pwm) 4523d0407baSopenharmony_ci{ 4533d0407baSopenharmony_ci return NULL; 4543d0407baSopenharmony_ci} 4553d0407baSopenharmony_ci 4563d0407baSopenharmony_cistatic inline int pwmchip_add(struct pwm_chip *chip) 4573d0407baSopenharmony_ci{ 4583d0407baSopenharmony_ci return -EINVAL; 4593d0407baSopenharmony_ci} 4603d0407baSopenharmony_ci 4613d0407baSopenharmony_cistatic inline int pwmchip_add_inversed(struct pwm_chip *chip) 4623d0407baSopenharmony_ci{ 4633d0407baSopenharmony_ci return -EINVAL; 4643d0407baSopenharmony_ci} 4653d0407baSopenharmony_ci 4663d0407baSopenharmony_cistatic inline int pwmchip_remove(struct pwm_chip *chip) 4673d0407baSopenharmony_ci{ 4683d0407baSopenharmony_ci return -EINVAL; 4693d0407baSopenharmony_ci} 4703d0407baSopenharmony_ci 4713d0407baSopenharmony_cistatic inline struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip, unsigned int index, const char *label) 4723d0407baSopenharmony_ci{ 4733d0407baSopenharmony_ci return ERR_PTR(-ENODEV); 4743d0407baSopenharmony_ci} 4753d0407baSopenharmony_ci 4763d0407baSopenharmony_cistatic inline struct pwm_device *pwm_get(struct device *dev, const char *consumer) 4773d0407baSopenharmony_ci{ 4783d0407baSopenharmony_ci return ERR_PTR(-ENODEV); 4793d0407baSopenharmony_ci} 4803d0407baSopenharmony_ci 4813d0407baSopenharmony_cistatic inline struct pwm_device *of_pwm_get(struct device *dev, struct device_node *np, const char *con_id) 4823d0407baSopenharmony_ci{ 4833d0407baSopenharmony_ci return ERR_PTR(-ENODEV); 4843d0407baSopenharmony_ci} 4853d0407baSopenharmony_ci 4863d0407baSopenharmony_cistatic inline void pwm_put(struct pwm_device *pwm) 4873d0407baSopenharmony_ci{ 4883d0407baSopenharmony_ci} 4893d0407baSopenharmony_ci 4903d0407baSopenharmony_cistatic inline struct pwm_device *devm_pwm_get(struct device *dev, const char *consumer) 4913d0407baSopenharmony_ci{ 4923d0407baSopenharmony_ci return ERR_PTR(-ENODEV); 4933d0407baSopenharmony_ci} 4943d0407baSopenharmony_ci 4953d0407baSopenharmony_cistatic inline struct pwm_device *devm_of_pwm_get(struct device *dev, struct device_node *np, const char *con_id) 4963d0407baSopenharmony_ci{ 4973d0407baSopenharmony_ci return ERR_PTR(-ENODEV); 4983d0407baSopenharmony_ci} 4993d0407baSopenharmony_ci 5003d0407baSopenharmony_cistatic inline struct pwm_device *devm_fwnode_pwm_get(struct device *dev, struct fwnode_handle *fwnode, 5013d0407baSopenharmony_ci const char *con_id) 5023d0407baSopenharmony_ci{ 5033d0407baSopenharmony_ci return ERR_PTR(-ENODEV); 5043d0407baSopenharmony_ci} 5053d0407baSopenharmony_ci 5063d0407baSopenharmony_cistatic inline void devm_pwm_put(struct device *dev, struct pwm_device *pwm) 5073d0407baSopenharmony_ci{ 5083d0407baSopenharmony_ci} 5093d0407baSopenharmony_ci#endif 5103d0407baSopenharmony_ci 5113d0407baSopenharmony_cistatic inline void pwm_apply_args(struct pwm_device *pwm) 5123d0407baSopenharmony_ci{ 5133d0407baSopenharmony_ci struct pwm_state state = {}; 5143d0407baSopenharmony_ci 5153d0407baSopenharmony_ci /* 5163d0407baSopenharmony_ci * PWM users calling pwm_apply_args() expect to have a fresh config 5173d0407baSopenharmony_ci * where the polarity and period are set according to pwm_args info. 5183d0407baSopenharmony_ci * The problem is, polarity can only be changed when the PWM is 5193d0407baSopenharmony_ci * disabled. 5203d0407baSopenharmony_ci * 5213d0407baSopenharmony_ci * PWM drivers supporting hardware readout may declare the PWM device 5223d0407baSopenharmony_ci * as enabled, and prevent polarity setting, which changes from the 5233d0407baSopenharmony_ci * existing behavior, where all PWM devices are declared as disabled 5243d0407baSopenharmony_ci * at startup (even if they are actually enabled), thus authorizing 5253d0407baSopenharmony_ci * polarity setting. 5263d0407baSopenharmony_ci * 5273d0407baSopenharmony_ci * To fulfill this requirement, we apply a new state which disables 5283d0407baSopenharmony_ci * the PWM device and set the reference period and polarity config. 5293d0407baSopenharmony_ci * 5303d0407baSopenharmony_ci * Note that PWM users requiring a smooth handover between the 5313d0407baSopenharmony_ci * bootloader and the kernel (like critical regulators controlled by 5323d0407baSopenharmony_ci * PWM devices) will have to switch to the atomic API and avoid calling 5333d0407baSopenharmony_ci * pwm_apply_args(). 5343d0407baSopenharmony_ci */ 5353d0407baSopenharmony_ci 5363d0407baSopenharmony_ci state.enabled = false; 5373d0407baSopenharmony_ci state.polarity = pwm->args.polarity; 5383d0407baSopenharmony_ci state.period = pwm->args.period; 5393d0407baSopenharmony_ci 5403d0407baSopenharmony_ci pwm_apply_state(pwm, &state); 5413d0407baSopenharmony_ci} 5423d0407baSopenharmony_ci 5433d0407baSopenharmony_cistruct pwm_lookup { 5443d0407baSopenharmony_ci struct list_head list; 5453d0407baSopenharmony_ci const char *provider; 5463d0407baSopenharmony_ci unsigned int index; 5473d0407baSopenharmony_ci const char *dev_id; 5483d0407baSopenharmony_ci const char *con_id; 5493d0407baSopenharmony_ci unsigned int period; 5503d0407baSopenharmony_ci enum pwm_polarity polarity; 5513d0407baSopenharmony_ci const char *module; /* optional, may be NULL */ 5523d0407baSopenharmony_ci}; 5533d0407baSopenharmony_ci 5543d0407baSopenharmony_ci#define PWM_LOOKUP_WITH_MODULE(_provider, _index, _dev_id, _con_id, _period, _polarity, _module) \ 5553d0407baSopenharmony_ci { \ 5563d0407baSopenharmony_ci .provider = (_provider), .index = (_index), .dev_id = (_dev_id), .con_id = (_con_id), .period = (_period), \ 5573d0407baSopenharmony_ci .polarity = (_polarity), .module = (_module), \ 5583d0407baSopenharmony_ci } 5593d0407baSopenharmony_ci 5603d0407baSopenharmony_ci#define PWM_LOOKUP(_provider, _index, _dev_id, _con_id, _period, _polarity) \ 5613d0407baSopenharmony_ci PWM_LOOKUP_WITH_MODULE(_provider, _index, _dev_id, _con_id, _period, _polarity, NULL) 5623d0407baSopenharmony_ci 5633d0407baSopenharmony_ci#if IS_ENABLED(CONFIG_PWM) 5643d0407baSopenharmony_civoid pwm_add_table(struct pwm_lookup *table, size_t num); 5653d0407baSopenharmony_civoid pwm_remove_table(struct pwm_lookup *table, size_t num); 5663d0407baSopenharmony_ci#else 5673d0407baSopenharmony_cistatic inline void pwm_add_table(struct pwm_lookup *table, size_t num) 5683d0407baSopenharmony_ci{ 5693d0407baSopenharmony_ci} 5703d0407baSopenharmony_ci 5713d0407baSopenharmony_cistatic inline void pwm_remove_table(struct pwm_lookup *table, size_t num) 5723d0407baSopenharmony_ci{ 5733d0407baSopenharmony_ci} 5743d0407baSopenharmony_ci#endif 5753d0407baSopenharmony_ci 5763d0407baSopenharmony_ci#ifdef CONFIG_PWM_SYSFS 5773d0407baSopenharmony_civoid pwmchip_sysfs_export(struct pwm_chip *chip); 5783d0407baSopenharmony_civoid pwmchip_sysfs_unexport(struct pwm_chip *chip); 5793d0407baSopenharmony_ci#else 5803d0407baSopenharmony_cistatic inline void pwmchip_sysfs_export(struct pwm_chip *chip) 5813d0407baSopenharmony_ci{ 5823d0407baSopenharmony_ci} 5833d0407baSopenharmony_ci 5843d0407baSopenharmony_cistatic inline void pwmchip_sysfs_unexport(struct pwm_chip *chip) 5853d0407baSopenharmony_ci{ 5863d0407baSopenharmony_ci} 5873d0407baSopenharmony_ci#endif /* CONFIG_PWM_SYSFS */ 5883d0407baSopenharmony_ci 5893d0407baSopenharmony_ci#endif /* __LINUX_PWM_H */ 590