summaryrefslogtreecommitdiffstats
path: root/include/pwm.h
blob: 2bd59fb8d3b66fd3664fc45c7018ffa8b9e11121 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef __PWM_H
#define __PWM_H

#include <dt-bindings/pwm/pwm.h>
#include <errno.h>

struct pwm_device;
struct device_d;

#define	PWM_POLARITY_NORMAL	0

/*
 * struct pwm_state - state of a PWM channel
 * @period_ns: PWM period (in nanoseconds)
 * @duty_ns: PWM duty cycle (in nanoseconds)
 * @polarity: PWM polarity
 * @p_enable: PWM enabled status
 */
struct pwm_state {
	unsigned int period_ns;
	unsigned int duty_ns;
	unsigned int polarity;
	unsigned int p_enable;
};

/*
 * pwm_request - request a PWM device
 */
struct pwm_device *pwm_request(const char *pwmname);

struct pwm_device *of_pwm_request(struct device_node *np, const char *con_id);

/*
 * pwm_free - free a PWM device
 */
void pwm_free(struct pwm_device *pwm);

/*
 * pwm_init_state - prepare a new state from device tree args
 */
void pwm_init_state(const struct pwm_device *pwm,
		    struct pwm_state *state);

/*
 * pwm_config - change a PWM device configuration
 */
int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state);

/*
 * pwm_config - change a PWM device configuration
 */
int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns);

/*
 * pwm_enable - start a PWM output toggling
 */
int pwm_enable(struct pwm_device *pwm);

/*
 * pwm_disable - stop a PWM output toggling
 */
void pwm_disable(struct pwm_device *pwm);

unsigned int pwm_get_period(struct pwm_device *pwm);

/**
 * pwm_set_relative_duty_cycle() - Set a relative duty cycle value
 * @state: PWM state to fill
 * @duty_cycle: relative duty cycle value
 * @scale: scale in which @duty_cycle is expressed
 *
 * This functions converts a relative into an absolute duty cycle (expressed
 * in nanoseconds), and puts the result in state->duty_cycle.
 *
 * For example if you want to configure a 50% duty cycle, call:
 *
 * pwm_init_state(pwm, &state);
 * pwm_set_relative_duty_cycle(&state, 50, 100);
 * pwm_apply_state(pwm, &state);
 *
 * This functions returns -EINVAL if @duty_cycle and/or @scale are
 * inconsistent (@scale == 0 or @duty_cycle > @scale).
 */
static inline int
pwm_set_relative_duty_cycle(struct pwm_state *state, unsigned int duty_cycle,
			    unsigned int scale)
{
	if (!scale || duty_cycle > scale)
		return -EINVAL;

	state->duty_ns = DIV_ROUND_CLOSEST_ULL((u64)duty_cycle *
					       state->period_ns,
					       scale);

	return 0;
}

struct pwm_chip;

/**
 * pwm_get_state() - retrieve the current PWM state
 * @pwm: PWM device
 * @state: state to fill with the current PWM state
 */
void pwm_get_state(const struct pwm_device *pwm, struct pwm_state *state);

/**
 * pwm_apply_state() - apply the passed PWM state
 * @pwm: PWM device
 * @state: state to apply to pwm device
 */
int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state);

/**
 * struct pwm_ops - PWM operations
 * @request: optional hook for requesting a PWM
 * @free: optional hook for freeing a PWM
 * @apply: apply specified pwm state
 */
struct pwm_ops {
	int (*request)(struct pwm_chip *chip);
	void (*free)(struct pwm_chip *chip);
	int (*apply)(struct pwm_chip *chip, const struct pwm_state *state);
};

/**
 * struct pwm_chip - abstract a PWM
 * @id: The id of this pwm
 * @devname: unique identifier for this pwm
 * @ops: The callbacks for this PWM
 * @state: current state of the PWM
 */
struct pwm_chip {
	int			id;
	const char		*devname;
	const struct pwm_ops	*ops;

	struct pwm_state	state;
};

int pwmchip_add(struct pwm_chip *chip, struct device_d *dev);
int pwmchip_remove(struct pwm_chip *chip);

#endif /* __PWM_H */