diff options
Diffstat (limited to 'target/linux/generic')
-rw-r--r-- | target/linux/generic/files/Documentation/pwm.txt | 260 | ||||
-rw-r--r-- | target/linux/generic/files/include/linux/pwm/pwm.h | 165 |
2 files changed, 0 insertions, 425 deletions
diff --git a/target/linux/generic/files/Documentation/pwm.txt b/target/linux/generic/files/Documentation/pwm.txt deleted file mode 100644 index 2c41ca5867..0000000000 --- a/target/linux/generic/files/Documentation/pwm.txt +++ /dev/null @@ -1,260 +0,0 @@ - Generic PWM Device API - - February 1, 2010 - Bill Gatliff - <bgat@billgatliff.com> - - - -The code in drivers/pwm and include/linux/pwm/ implements an API for -applications involving pulse-width-modulation signals. This document -describes how the API implementation facilitates both PWM-generating -devices, and users of those devices. - - - -Motivation - -The primary goals for implementing the "generic PWM API" are to -consolidate the various PWM implementations within a consistent and -redundancy-reducing framework, and to facilitate the use of -hotpluggable PWM devices. - -Previous PWM-related implementations within the Linux kernel achieved -their consistency via cut-and-paste, but did not need to (and didn't) -facilitate more than one PWM-generating device within the system--- -hotplug or otherwise. The Generic PWM Device API might be most -appropriately viewed as an update to those implementations, rather -than a complete rewrite. - - - -Challenges - -One of the difficulties in implementing a generic PWM framework is the -fact that pulse-width-modulation applications involve real-world -signals, which often must be carefully managed to prevent destruction -of hardware that is linked to those signals. A DC motor that -experiences a brief interruption in the PWM signal controlling it -might destructively overheat; it could suddenly change speed, losing -synchronization with a sensor; it could even suddenly change direction -or torque, breaking the mechanical device connected to it. - -(A generic PWM device framework is not directly responsible for -preventing the above scenarios: that responsibility lies with the -hardware designer, and the application and driver authors. But it -must to the greatest extent possible make it easy to avoid such -problems). - -A generic PWM device framework must accommodate the substantial -differences between available PWM-generating hardware devices, without -becoming sub-optimal for any of them. - -Finally, a generic PWM device framework must be relatively -lightweight, computationally speaking. Some PWM users demand -high-speed outputs, plus the ability to regulate those outputs -quickly. A device framework must be able to "keep up" with such -hardware, while still leaving time to do real work. - -The Generic PWM Device API is an attempt to meet all of the above -requirements. At its initial publication, the API was already in use -managing small DC motors, sensors and solenoids through a -custom-designed, optically-isolated H-bridge driver. - - - -Functional Overview - -The Generic PWM Device API framework is implemented in -include/linux/pwm/pwm.h and drivers/pwm/pwm.c. The functions therein -use information from pwm_device, pwm_channel and pwm_channel_config -structures to invoke services in PWM peripheral device drivers. -Consult drivers/pwm/atmel-pwm.c for an example driver. - -There are two classes of adopters of the PWM framework: - - "Users" -- those wishing to employ the API merely to produce PWM - signals; once they have identified the appropriate physical output - on the platform in question, they don't care about the details of - the underlying hardware - - "Driver authors" -- those wishing to bind devices that can generate - PWM signals to the Generic PWM Device API, so that the services of - those devices become available to users. Assuming the hardware can - support the needs of a user, driver authors don't care about the - details of the user's application - -Generally speaking, users will first invoke pwm_request() to obtain a -handle to a PWM device. They will then pass that handle to functions -like pwm_duty_ns() and pwm_period_ns() to set the duty cycle and -period of the PWM signal, respectively. They will also invoke -pwm_start() and pwm_stop() to turn the signal on and off. - -The Generic PWM API framework also provides a sysfs interface to PWM -devices, which is adequate for basic application needs and testing. - -Driver authors fill out a pwm_device structure, which describes the -capabilities of the PWM hardware being constructed--- including the -number of distinct output "channels" the peripheral offers. They then -invoke pwm_register() (usually from within their device's probe() -handler) to make the PWM API aware of their device. The framework -will call back to the methods described in the pwm_device structure as -users begin to configure and utilize the hardware. - -Note that PWM signals can be produced by a variety of peripherals, -beyond the true "PWM hardware" offered by many system-on-chip devices. -Other possibilities include timer/counters with compare-match -capabilities, carefully-programmed synchronous serial ports -(e.g. SPI), and GPIO pins driven by kernel interval timers. With a -proper pwm_device structure, these devices and pseudo-devices can all -be accommodated by the Generic PWM Device API framework. - - - -Using the API to Generate PWM Signals -- Basic Functions for Users - - -pwm_request() -- Returns a pwm_channel pointer, which is subsequently -passed to the other user-related PWM functions. Once requested, a PWM -channel is marked as in-use and subsequent requests prior to -pwm_free() will fail. - -The names used to refer to PWM devices are defined by driver authors. -Typically they are platform device bus identifiers, and this -convention is encouraged for consistency. - - -pwm_free() -- Marks a PWM channel as no longer in use. The PWM device -is stopped before it is released by the API. - - -pwm_period_ns() -- Specifies the PWM signal's period, in nanoseconds. - - -pwm_duty_ns() -- Specifies the PWM signal's active duration, in nanoseconds. - - -pwm_duty_percent() -- Specifies the PWM signal's active duration, as a -percentage of the current period of the signal. NOTE: this value is -not recalculated if the period of the signal is subsequently changed. - - -pwm_start(), pwm_stop() -- Turns the PWM signal on and off. Except -where stated otherwise by a driver author, signals are stopped at the -end of the current period, at which time the output is set to its -inactive state. - - -pwm_polarity() -- Defines whether the PWM signal output's active -region is "1" or "0". A 10% duty-cycle, polarity=1 signal will -conventionally be at 5V (or 3.3V, or 1000V, or whatever the platform -hardware does) for 10% of the period. The same configuration of a -polarity=0 signal will be at 5V (or 3.3V, or ...) for 90% of the -period. - - - -Using the API to Generate PWM Signals -- Advanced Functions - - -pwm_config() -- Passes a pwm_channel_config structure to the -associated device driver. This function is invoked by pwm_start(), -pwm_duty_ns(), etc. and is one of two main entry points to the PWM -driver for the hardware being used. The configuration change is -guaranteed atomic if multiple configuration changes are specified. -This function might sleep, depending on what the device driver has to -do to satisfy the request. All PWM device drivers must support this -entry point. - - -pwm_config_nosleep() -- Passes a pwm_channel_config structure to the -associated device driver. If the driver must sleep in order to -implement the requested configuration change, -EWOULDBLOCK is -returned. Users may call this function from interrupt handlers, for -example. This is the other main entry point into the PWM hardware -driver, but not all device drivers support this entry point. - - -pwm_synchronize(), pwm_unsynchronize() -- "Synchronizes" two or more -PWM channels, if the underlying hardware permits. (If it doesn't, the -framework facilitates emulating this capability but it is not yet -implemented). Synchronized channels will start and stop -simultaneously when any single channel in the group is started or -stopped. Use pwm_unsynchronize(..., NULL) to completely detach a -channel from any other synchronized channels. By default, all PWM -channels are unsynchronized. - - -pwm_set_handler() -- Defines an end-of-period callback. The indicated -function will be invoked in a worker thread at the end of each PWM -period, and can subsequently invoke pwm_config(), etc. Must be used -with extreme care for high-speed PWM outputs. Set the handler -function to NULL to un-set the handler. - - - -Implementing a PWM Device API Driver -- Functions for Driver Authors - - -Fill out the appropriate fields in a pwm_device structure, and submit -to pwm_register(): - - -bus_id -- the plain-text name of the device. Users will bind to a -channel on the device using this name plus the channel number. For -example, the Atmel PWMC's bus_id is "atmel_pwmc", the same as used by -the platform device driver (recommended). The first device registered -thereby receives bus_id "atmel_pwmc.0", which is what you put in -pwm_device.bus_id. Channels are then named "atmel_pwmc.0:[0-3]". -(Hint: just use pdev->dev.bus_id in your probe() method). - - -nchan -- the number of distinct output channels provided by the device. - - -request -- (optional) Invoked each time a user requests a channel. -Use to turn on clocks, clean up register states, etc. The framework -takes care of device locking/unlocking; you will see only successful -requests. - - -free -- (optional) Callback for each time a user relinquishes a -channel. The framework will have already stopped, unsynchronized and -un-handled the channel. Use to turn off clocks, etc. as necessary. - - -synchronize, unsynchronize -- (optional) Callbacks to -synchronize/unsynchronize channels. Some devices provide this -capability in hardware; for others, it can be emulated (see -atmel_pwmc.c's sync_mask for an example). - - -set_callback -- (optional) Invoked when a user requests a handler. If -the hardware supports an end-of-period interrupt, invoke the function -indicated during your interrupt handler. The callback function itself -is always internal to the API, and does not map directly to the user's -callback function. - - -config -- Invoked to change the device configuration, always from a -sleep-capable context. All the changes indicated must be performed -atomically, ideally synchronized to an end-of-period event (so that -you avoid short or long output pulses). You may sleep, etc. as -necessary within this function. - - -config_nosleep -- (optional) Invoked to change device configuration -from within a context that is not allowed to sleep. If you cannot -perform the requested configuration changes without sleeping, return --EWOULDBLOCK. - - - -Acknowledgements - - -The author expresses his gratitude to the countless developers who -have reviewed and submitted feedback on the various versions of the -Generic PWM Device API code, and those who have submitted drivers and -applications that use the framework. You know who you are. ;) - diff --git a/target/linux/generic/files/include/linux/pwm/pwm.h b/target/linux/generic/files/include/linux/pwm/pwm.h deleted file mode 100644 index e01cca9036..0000000000 --- a/target/linux/generic/files/include/linux/pwm/pwm.h +++ /dev/null @@ -1,165 +0,0 @@ -/* - * include/linux/pwm.h - * - * Copyright (C) 2008 Bill Gatliff < bgat@billgatliff.com> - * - * This program is free software; you may redistribute and/or modify - * it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ -#ifndef __LINUX_PWM_H -#define __LINUX_PWM_H - -enum { - PWM_CONFIG_DUTY_TICKS = BIT(0), - PWM_CONFIG_PERIOD_TICKS = BIT(1), - PWM_CONFIG_POLARITY = BIT(2), - PWM_CONFIG_START = BIT(3), - PWM_CONFIG_STOP = BIT(4), - - PWM_CONFIG_HANDLER = BIT(5), - - PWM_CONFIG_DUTY_NS = BIT(6), - PWM_CONFIG_DUTY_PERCENT = BIT(7), - PWM_CONFIG_PERIOD_NS = BIT(8), -}; - -struct pwm_channel; -struct work_struct; - -typedef int (*pwm_handler_t)(struct pwm_channel *p, void *data); -typedef void (*pwm_callback_t)(struct pwm_channel *p); - -struct pwm_channel_config { - int config_mask; - unsigned long duty_ticks; - unsigned long period_ticks; - int polarity; - - pwm_handler_t handler; - - unsigned long duty_ns; - unsigned long period_ns; - int duty_percent; -}; - -struct pwm_device { - struct list_head list; - spinlock_t list_lock; - struct device *dev; - struct module *owner; - struct pwm_channel *channels; - - const char *bus_id; - int nchan; - - int (*request) (struct pwm_channel *p); - void (*free) (struct pwm_channel *p); - int (*config) (struct pwm_channel *p, - struct pwm_channel_config *c); - int (*config_nosleep)(struct pwm_channel *p, - struct pwm_channel_config *c); - int (*synchronize) (struct pwm_channel *p, - struct pwm_channel *to_p); - int (*unsynchronize)(struct pwm_channel *p, - struct pwm_channel *from_p); - int (*set_callback) (struct pwm_channel *p, - pwm_callback_t callback); -}; - -int pwm_register(struct pwm_device *pwm); -int pwm_unregister(struct pwm_device *pwm); - -enum { - FLAG_REQUESTED = 0, - FLAG_STOP = 1, -}; - -struct pwm_channel { - struct list_head list; - struct pwm_device *pwm; - const char *requester; - pid_t pid; - int chan; - unsigned long flags; - unsigned long tick_hz; - - spinlock_t lock; - struct completion complete; - - pwm_callback_t callback; - - struct work_struct handler_work; - pwm_handler_t handler; - void *handler_data; - - int active_high; - unsigned long period_ticks; - unsigned long duty_ticks; -}; - -struct gpio_pwm_platform_data { - int gpio; -}; - -struct pwm_channel * -pwm_request(const char *bus_id, int chan, - const char *requester); - -void pwm_free(struct pwm_channel *pwm); - -int pwm_config_nosleep(struct pwm_channel *pwm, - struct pwm_channel_config *c); - -int pwm_config(struct pwm_channel *pwm, - struct pwm_channel_config *c); - -unsigned long pwm_ns_to_ticks(struct pwm_channel *pwm, - unsigned long nsecs); - -unsigned long pwm_ticks_to_ns(struct pwm_channel *pwm, - unsigned long ticks); - -int pwm_set_period_ns(struct pwm_channel *pwm, - unsigned long period_ns); - -unsigned long int pwm_get_period_ns(struct pwm_channel *pwm); - -int pwm_set_duty_ns(struct pwm_channel *pwm, - unsigned long duty_ns); - -int pwm_set_duty_percent(struct pwm_channel *pwm, - int percent); - -unsigned long pwm_get_duty_ns(struct pwm_channel *pwm); - -int pwm_set_polarity(struct pwm_channel *pwm, - int active_high); - -int pwm_start(struct pwm_channel *pwm); - -int pwm_stop(struct pwm_channel *pwm); - -int pwm_set_handler(struct pwm_channel *pwm, - pwm_handler_t handler, - void *data); - -int pwm_synchronize(struct pwm_channel *p, - struct pwm_channel *to_p); - - -int pwm_unsynchronize(struct pwm_channel *p, - struct pwm_channel *from_p); - - -#endif /* __LINUX_PWM_H */ |