| 1 | Generic PWM Device API |
| 2 | |
| 3 | February 1, 2010 |
| 4 | Bill Gatliff |
| 5 | <bgat@billgatliff.com> |
| 6 | |
| 7 | |
| 8 | |
| 9 | The code in drivers/pwm and include/linux/pwm/ implements an API for |
| 10 | applications involving pulse-width-modulation signals. This document |
| 11 | describes how the API implementation facilitates both PWM-generating |
| 12 | devices, and users of those devices. |
| 13 | |
| 14 | |
| 15 | |
| 16 | Motivation |
| 17 | |
| 18 | The primary goals for implementing the "generic PWM API" are to |
| 19 | consolidate the various PWM implementations within a consistent and |
| 20 | redundancy-reducing framework, and to facilitate the use of |
| 21 | hotpluggable PWM devices. |
| 22 | |
| 23 | Previous PWM-related implementations within the Linux kernel achieved |
| 24 | their consistency via cut-and-paste, but did not need to (and didn't) |
| 25 | facilitate more than one PWM-generating device within the system--- |
| 26 | hotplug or otherwise. The Generic PWM Device API might be most |
| 27 | appropriately viewed as an update to those implementations, rather |
| 28 | than a complete rewrite. |
| 29 | |
| 30 | |
| 31 | |
| 32 | Challenges |
| 33 | |
| 34 | One of the difficulties in implementing a generic PWM framework is the |
| 35 | fact that pulse-width-modulation applications involve real-world |
| 36 | signals, which often must be carefully managed to prevent destruction |
| 37 | of hardware that is linked to those signals. A DC motor that |
| 38 | experiences a brief interruption in the PWM signal controlling it |
| 39 | might destructively overheat; it could suddenly change speed, losing |
| 40 | synchronization with a sensor; it could even suddenly change direction |
| 41 | or torque, breaking the mechanical device connected to it. |
| 42 | |
| 43 | (A generic PWM device framework is not directly responsible for |
| 44 | preventing the above scenarios: that responsibility lies with the |
| 45 | hardware designer, and the application and driver authors. But it |
| 46 | must to the greatest extent possible make it easy to avoid such |
| 47 | problems). |
| 48 | |
| 49 | A generic PWM device framework must accommodate the substantial |
| 50 | differences between available PWM-generating hardware devices, without |
| 51 | becoming sub-optimal for any of them. |
| 52 | |
| 53 | Finally, a generic PWM device framework must be relatively |
| 54 | lightweight, computationally speaking. Some PWM users demand |
| 55 | high-speed outputs, plus the ability to regulate those outputs |
| 56 | quickly. A device framework must be able to "keep up" with such |
| 57 | hardware, while still leaving time to do real work. |
| 58 | |
| 59 | The Generic PWM Device API is an attempt to meet all of the above |
| 60 | requirements. At its initial publication, the API was already in use |
| 61 | managing small DC motors, sensors and solenoids through a |
| 62 | custom-designed, optically-isolated H-bridge driver. |
| 63 | |
| 64 | |
| 65 | |
| 66 | Functional Overview |
| 67 | |
| 68 | The Generic PWM Device API framework is implemented in |
| 69 | include/linux/pwm/pwm.h and drivers/pwm/pwm.c. The functions therein |
| 70 | use information from pwm_device, pwm_channel and pwm_channel_config |
| 71 | structures to invoke services in PWM peripheral device drivers. |
| 72 | Consult drivers/pwm/atmel-pwm.c for an example driver. |
| 73 | |
| 74 | There are two classes of adopters of the PWM framework: |
| 75 | |
| 76 | "Users" -- those wishing to employ the API merely to produce PWM |
| 77 | signals; once they have identified the appropriate physical output |
| 78 | on the platform in question, they don't care about the details of |
| 79 | the underlying hardware |
| 80 | |
| 81 | "Driver authors" -- those wishing to bind devices that can generate |
| 82 | PWM signals to the Generic PWM Device API, so that the services of |
| 83 | those devices become available to users. Assuming the hardware can |
| 84 | support the needs of a user, driver authors don't care about the |
| 85 | details of the user's application |
| 86 | |
| 87 | Generally speaking, users will first invoke pwm_request() to obtain a |
| 88 | handle to a PWM device. They will then pass that handle to functions |
| 89 | like pwm_duty_ns() and pwm_period_ns() to set the duty cycle and |
| 90 | period of the PWM signal, respectively. They will also invoke |
| 91 | pwm_start() and pwm_stop() to turn the signal on and off. |
| 92 | |
| 93 | The Generic PWM API framework also provides a sysfs interface to PWM |
| 94 | devices, which is adequate for basic application needs and testing. |
| 95 | |
| 96 | Driver authors fill out a pwm_device structure, which describes the |
| 97 | capabilities of the PWM hardware being constructed--- including the |
| 98 | number of distinct output "channels" the peripheral offers. They then |
| 99 | invoke pwm_register() (usually from within their device's probe() |
| 100 | handler) to make the PWM API aware of their device. The framework |
| 101 | will call back to the methods described in the pwm_device structure as |
| 102 | users begin to configure and utilize the hardware. |
| 103 | |
| 104 | Note that PWM signals can be produced by a variety of peripherals, |
| 105 | beyond the true "PWM hardware" offered by many system-on-chip devices. |
| 106 | Other possibilities include timer/counters with compare-match |
| 107 | capabilities, carefully-programmed synchronous serial ports |
| 108 | (e.g. SPI), and GPIO pins driven by kernel interval timers. With a |
| 109 | proper pwm_device structure, these devices and pseudo-devices can all |
| 110 | be accommodated by the Generic PWM Device API framework. |
| 111 | |
| 112 | |
| 113 | |
| 114 | Using the API to Generate PWM Signals -- Basic Functions for Users |
| 115 | |
| 116 | |
| 117 | pwm_request() -- Returns a pwm_channel pointer, which is subsequently |
| 118 | passed to the other user-related PWM functions. Once requested, a PWM |
| 119 | channel is marked as in-use and subsequent requests prior to |
| 120 | pwm_free() will fail. |
| 121 | |
| 122 | The names used to refer to PWM devices are defined by driver authors. |
| 123 | Typically they are platform device bus identifiers, and this |
| 124 | convention is encouraged for consistency. |
| 125 | |
| 126 | |
| 127 | pwm_free() -- Marks a PWM channel as no longer in use. The PWM device |
| 128 | is stopped before it is released by the API. |
| 129 | |
| 130 | |
| 131 | pwm_period_ns() -- Specifies the PWM signal's period, in nanoseconds. |
| 132 | |
| 133 | |
| 134 | pwm_duty_ns() -- Specifies the PWM signal's active duration, in nanoseconds. |
| 135 | |
| 136 | |
| 137 | pwm_duty_percent() -- Specifies the PWM signal's active duration, as a |
| 138 | percentage of the current period of the signal. NOTE: this value is |
| 139 | not recalculated if the period of the signal is subsequently changed. |
| 140 | |
| 141 | |
| 142 | pwm_start(), pwm_stop() -- Turns the PWM signal on and off. Except |
| 143 | where stated otherwise by a driver author, signals are stopped at the |
| 144 | end of the current period, at which time the output is set to its |
| 145 | inactive state. |
| 146 | |
| 147 | |
| 148 | pwm_polarity() -- Defines whether the PWM signal output's active |
| 149 | region is "1" or "0". A 10% duty-cycle, polarity=1 signal will |
| 150 | conventionally be at 5V (or 3.3V, or 1000V, or whatever the platform |
| 151 | hardware does) for 10% of the period. The same configuration of a |
| 152 | polarity=0 signal will be at 5V (or 3.3V, or ...) for 90% of the |
| 153 | period. |
| 154 | |
| 155 | |
| 156 | |
| 157 | Using the API to Generate PWM Signals -- Advanced Functions |
| 158 | |
| 159 | |
| 160 | pwm_config() -- Passes a pwm_channel_config structure to the |
| 161 | associated device driver. This function is invoked by pwm_start(), |
| 162 | pwm_duty_ns(), etc. and is one of two main entry points to the PWM |
| 163 | driver for the hardware being used. The configuration change is |
| 164 | guaranteed atomic if multiple configuration changes are specified. |
| 165 | This function might sleep, depending on what the device driver has to |
| 166 | do to satisfy the request. All PWM device drivers must support this |
| 167 | entry point. |
| 168 | |
| 169 | |
| 170 | pwm_config_nosleep() -- Passes a pwm_channel_config structure to the |
| 171 | associated device driver. If the driver must sleep in order to |
| 172 | implement the requested configuration change, -EWOULDBLOCK is |
| 173 | returned. Users may call this function from interrupt handlers, for |
| 174 | example. This is the other main entry point into the PWM hardware |
| 175 | driver, but not all device drivers support this entry point. |
| 176 | |
| 177 | |
| 178 | pwm_synchronize(), pwm_unsynchronize() -- "Synchronizes" two or more |
| 179 | PWM channels, if the underlying hardware permits. (If it doesn't, the |
| 180 | framework facilitates emulating this capability but it is not yet |
| 181 | implemented). Synchronized channels will start and stop |
| 182 | simultaneously when any single channel in the group is started or |
| 183 | stopped. Use pwm_unsynchronize(..., NULL) to completely detach a |
| 184 | channel from any other synchronized channels. By default, all PWM |
| 185 | channels are unsynchronized. |
| 186 | |
| 187 | |
| 188 | pwm_set_handler() -- Defines an end-of-period callback. The indicated |
| 189 | function will be invoked in a worker thread at the end of each PWM |
| 190 | period, and can subsequently invoke pwm_config(), etc. Must be used |
| 191 | with extreme care for high-speed PWM outputs. Set the handler |
| 192 | function to NULL to un-set the handler. |
| 193 | |
| 194 | |
| 195 | |
| 196 | Implementing a PWM Device API Driver -- Functions for Driver Authors |
| 197 | |
| 198 | |
| 199 | Fill out the appropriate fields in a pwm_device structure, and submit |
| 200 | to pwm_register(): |
| 201 | |
| 202 | |
| 203 | bus_id -- the plain-text name of the device. Users will bind to a |
| 204 | channel on the device using this name plus the channel number. For |
| 205 | example, the Atmel PWMC's bus_id is "atmel_pwmc", the same as used by |
| 206 | the platform device driver (recommended). The first device registered |
| 207 | thereby receives bus_id "atmel_pwmc.0", which is what you put in |
| 208 | pwm_device.bus_id. Channels are then named "atmel_pwmc.0:[0-3]". |
| 209 | (Hint: just use pdev->dev.bus_id in your probe() method). |
| 210 | |
| 211 | |
| 212 | nchan -- the number of distinct output channels provided by the device. |
| 213 | |
| 214 | |
| 215 | request -- (optional) Invoked each time a user requests a channel. |
| 216 | Use to turn on clocks, clean up register states, etc. The framework |
| 217 | takes care of device locking/unlocking; you will see only successful |
| 218 | requests. |
| 219 | |
| 220 | |
| 221 | free -- (optional) Callback for each time a user relinquishes a |
| 222 | channel. The framework will have already stopped, unsynchronized and |
| 223 | un-handled the channel. Use to turn off clocks, etc. as necessary. |
| 224 | |
| 225 | |
| 226 | synchronize, unsynchronize -- (optional) Callbacks to |
| 227 | synchronize/unsynchronize channels. Some devices provide this |
| 228 | capability in hardware; for others, it can be emulated (see |
| 229 | atmel_pwmc.c's sync_mask for an example). |
| 230 | |
| 231 | |
| 232 | set_callback -- (optional) Invoked when a user requests a handler. If |
| 233 | the hardware supports an end-of-period interrupt, invoke the function |
| 234 | indicated during your interrupt handler. The callback function itself |
| 235 | is always internal to the API, and does not map directly to the user's |
| 236 | callback function. |
| 237 | |
| 238 | |
| 239 | config -- Invoked to change the device configuration, always from a |
| 240 | sleep-capable context. All the changes indicated must be performed |
| 241 | atomically, ideally synchronized to an end-of-period event (so that |
| 242 | you avoid short or long output pulses). You may sleep, etc. as |
| 243 | necessary within this function. |
| 244 | |
| 245 | |
| 246 | config_nosleep -- (optional) Invoked to change device configuration |
| 247 | from within a context that is not allowed to sleep. If you cannot |
| 248 | perform the requested configuration changes without sleeping, return |
| 249 | -EWOULDBLOCK. |
| 250 | |
| 251 | |
| 252 | |
| 253 | Acknowledgements |
| 254 | |
| 255 | |
| 256 | The author expresses his gratitude to the countless developers who |
| 257 | have reviewed and submitted feedback on the various versions of the |
| 258 | Generic PWM Device API code, and those who have submitted drivers and |
| 259 | applications that use the framework. You know who you are. ;) |
| 260 | |
| 261 | |