diff options
author | Thierry Reding <thierry.reding@avionic-design.de> | 2011-12-14 05:12:23 -0500 |
---|---|---|
committer | Thierry Reding <thierry.reding@avionic-design.de> | 2012-06-15 06:56:52 -0400 |
commit | f051c466cf690ac661d713d3ceb56b4efcecc853 (patch) | |
tree | 15291a08d3ec44e8ab81c44370e1ac2bbb366ec5 /include/linux/pwm.h | |
parent | 0c2498f1660878339350bea8d18550b1b87ca055 (diff) |
pwm: Allow chips to support multiple PWMs
Many PWM controllers provide access to more than a single PWM output and
may even share some resource among them. Allowing a PWM chip to provide
multiple PWM devices enables better sharing of those resources. As a
side-effect this change allows easy integration with the device tree
where a given PWM can be looked up based on the PWM chip's phandle and a
corresponding index.
This commit modifies the PWM core to support multiple PWMs per struct
pwm_chip. It achieves this in a similar way to how gpiolib works, by
allowing PWM ranges to be requested dynamically (pwm_chip.base == -1) or
starting at a given offset (pwm_chip.base >= 0). A chip specifies how
many PWMs it controls using the npwm member. Each of the functions in
the pwm_ops structure gets an additional argument that specified the PWM
number (it can be converted to a per-chip index by subtracting the
chip's base).
The total maximum number of PWM devices is currently fixed to 1024 while
the data is actually stored in a radix tree, thus saving resources if
not all of them are used.
Reviewed-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Reviewed-by: Shawn Guo <shawn.guo@linaro.org>
[eric@eukrea.com: fix error handling in pwmchip_add]
Signed-off-by: Eric BĂ©nard <eric@eukrea.com>
Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
Diffstat (limited to 'include/linux/pwm.h')
-rw-r--r-- | include/linux/pwm.h | 71 |
1 files changed, 58 insertions, 13 deletions
diff --git a/include/linux/pwm.h b/include/linux/pwm.h index 1f308a13105f..57103911f4c7 100644 --- a/include/linux/pwm.h +++ b/include/linux/pwm.h | |||
@@ -31,6 +31,33 @@ void pwm_disable(struct pwm_device *pwm); | |||
31 | #ifdef CONFIG_PWM | 31 | #ifdef CONFIG_PWM |
32 | struct pwm_chip; | 32 | struct pwm_chip; |
33 | 33 | ||
34 | enum { | ||
35 | PWMF_REQUESTED = 1 << 0, | ||
36 | PWMF_ENABLED = 1 << 1, | ||
37 | }; | ||
38 | |||
39 | struct pwm_device { | ||
40 | const char *label; | ||
41 | unsigned long flags; | ||
42 | unsigned int hwpwm; | ||
43 | unsigned int pwm; | ||
44 | struct pwm_chip *chip; | ||
45 | void *chip_data; | ||
46 | |||
47 | unsigned int period; /* in nanoseconds */ | ||
48 | }; | ||
49 | |||
50 | static inline void pwm_set_period(struct pwm_device *pwm, unsigned int period) | ||
51 | { | ||
52 | if (pwm) | ||
53 | pwm->period = period; | ||
54 | } | ||
55 | |||
56 | static inline unsigned int pwm_get_period(struct pwm_device *pwm) | ||
57 | { | ||
58 | return pwm ? pwm->period : 0; | ||
59 | } | ||
60 | |||
34 | /** | 61 | /** |
35 | * struct pwm_ops - PWM controller operations | 62 | * struct pwm_ops - PWM controller operations |
36 | * @request: optional hook for requesting a PWM | 63 | * @request: optional hook for requesting a PWM |
@@ -41,29 +68,47 @@ struct pwm_chip; | |||
41 | * @owner: helps prevent removal of modules exporting active PWMs | 68 | * @owner: helps prevent removal of modules exporting active PWMs |
42 | */ | 69 | */ |
43 | struct pwm_ops { | 70 | struct pwm_ops { |
44 | int (*request)(struct pwm_chip *chip); | 71 | int (*request)(struct pwm_chip *chip, |
45 | void (*free)(struct pwm_chip *chip); | 72 | struct pwm_device *pwm); |
46 | int (*config)(struct pwm_chip *chip, int duty_ns, | 73 | void (*free)(struct pwm_chip *chip, |
47 | int period_ns); | 74 | struct pwm_device *pwm); |
48 | int (*enable)(struct pwm_chip *chip); | 75 | int (*config)(struct pwm_chip *chip, |
49 | void (*disable)(struct pwm_chip *chip); | 76 | struct pwm_device *pwm, |
77 | int duty_ns, int period_ns); | ||
78 | int (*enable)(struct pwm_chip *chip, | ||
79 | struct pwm_device *pwm); | ||
80 | void (*disable)(struct pwm_chip *chip, | ||
81 | struct pwm_device *pwm); | ||
50 | struct module *owner; | 82 | struct module *owner; |
51 | }; | 83 | }; |
52 | 84 | ||
53 | /** | 85 | /** |
54 | * struct pwm_chip - abstract a PWM | 86 | * struct pwm_chip - abstract a PWM controller |
55 | * @pwm_id: global PWM device index | 87 | * @dev: device providing the PWMs |
56 | * @label: PWM device label | 88 | * @list: list node for internal use |
57 | * @ops: controller operations | 89 | * @ops: callbacks for this PWM controller |
90 | * @base: number of first PWM controlled by this chip | ||
91 | * @npwm: number of PWMs controlled by this chip | ||
92 | * @pwms: array of PWM devices allocated by the framework | ||
58 | */ | 93 | */ |
59 | struct pwm_chip { | 94 | struct pwm_chip { |
60 | int pwm_id; | 95 | struct device *dev; |
61 | const char *label; | 96 | struct list_head list; |
62 | struct pwm_ops *ops; | 97 | const struct pwm_ops *ops; |
98 | int base; | ||
99 | unsigned int npwm; | ||
100 | |||
101 | struct pwm_device *pwms; | ||
63 | }; | 102 | }; |
64 | 103 | ||
104 | int pwm_set_chip_data(struct pwm_device *pwm, void *data); | ||
105 | void *pwm_get_chip_data(struct pwm_device *pwm); | ||
106 | |||
65 | int pwmchip_add(struct pwm_chip *chip); | 107 | int pwmchip_add(struct pwm_chip *chip); |
66 | int pwmchip_remove(struct pwm_chip *chip); | 108 | int pwmchip_remove(struct pwm_chip *chip); |
109 | struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip, | ||
110 | unsigned int index, | ||
111 | const char *label); | ||
67 | #endif | 112 | #endif |
68 | 113 | ||
69 | #endif /* __LINUX_PWM_H */ | 114 | #endif /* __LINUX_PWM_H */ |