cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pwm.h (17077B)


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