2011-01-28 11:40:40 +03:00
/*
* Generic pwmlib implementation
*
* Copyright ( C ) 2011 Sascha Hauer < s . hauer @ pengutronix . de >
2011-12-14 14:12:23 +04:00
* Copyright ( C ) 2011 - 2012 Avionic Design GmbH
2011-01-28 11:40:40 +03:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 , or ( at your option )
* any later version .
*
* 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 ; see the file COPYING . If not , write to
* the Free Software Foundation , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include <linux/module.h>
# include <linux/pwm.h>
2011-12-14 14:12:23 +04:00
# include <linux/radix-tree.h>
2011-01-28 11:40:40 +03:00
# include <linux/list.h>
# include <linux/mutex.h>
# include <linux/err.h>
# include <linux/slab.h>
# include <linux/device.h>
2012-03-26 11:31:48 +04:00
# include <linux/debugfs.h>
# include <linux/seq_file.h>
2011-01-28 11:40:40 +03:00
2013-07-18 02:54:22 +04:00
# include <dt-bindings/pwm/pwm.h>
2011-01-28 11:40:40 +03:00
2013-07-18 02:54:22 +04:00
# define MAX_PWMS 1024
2012-11-21 11:40:44 +04:00
2012-03-26 10:42:48 +04:00
static DEFINE_MUTEX ( pwm_lookup_lock ) ;
static LIST_HEAD ( pwm_lookup_list ) ;
2011-01-28 11:40:40 +03:00
static DEFINE_MUTEX ( pwm_lock ) ;
2011-12-14 14:12:23 +04:00
static LIST_HEAD ( pwm_chips ) ;
static DECLARE_BITMAP ( allocated_pwms , MAX_PWMS ) ;
static RADIX_TREE ( pwm_tree , GFP_KERNEL ) ;
2011-01-28 11:40:40 +03:00
2011-12-14 14:12:23 +04:00
static struct pwm_device * pwm_to_device ( unsigned int pwm )
2011-01-28 11:40:40 +03:00
{
2011-12-14 14:12:23 +04:00
return radix_tree_lookup ( & pwm_tree , pwm ) ;
}
static int alloc_pwms ( int pwm , unsigned int count )
{
unsigned int from = 0 ;
unsigned int start ;
if ( pwm > = MAX_PWMS )
return - EINVAL ;
if ( pwm > = 0 )
from = pwm ;
2011-01-28 11:40:40 +03:00
2011-12-14 14:12:23 +04:00
start = bitmap_find_next_zero_area ( allocated_pwms , MAX_PWMS , from ,
count , 0 ) ;
if ( pwm > = 0 & & start ! = pwm )
return - EEXIST ;
if ( start + count > MAX_PWMS )
return - ENOSPC ;
return start ;
}
static void free_pwms ( struct pwm_chip * chip )
{
unsigned int i ;
for ( i = 0 ; i < chip - > npwm ; i + + ) {
struct pwm_device * pwm = & chip - > pwms [ i ] ;
2016-05-02 13:05:55 +03:00
2011-12-14 14:12:23 +04:00
radix_tree_delete ( & pwm_tree , pwm - > pwm ) ;
2011-01-28 11:40:40 +03:00
}
2011-12-14 14:12:23 +04:00
bitmap_clear ( allocated_pwms , chip - > base , chip - > npwm ) ;
kfree ( chip - > pwms ) ;
chip - > pwms = NULL ;
}
2012-03-26 10:42:48 +04:00
static struct pwm_chip * pwmchip_find_by_name ( const char * name )
{
struct pwm_chip * chip ;
if ( ! name )
return NULL ;
mutex_lock ( & pwm_lock ) ;
list_for_each_entry ( chip , & pwm_chips , list ) {
const char * chip_name = dev_name ( chip - > dev ) ;
if ( chip_name & & strcmp ( chip_name , name ) = = 0 ) {
mutex_unlock ( & pwm_lock ) ;
return chip ;
}
}
mutex_unlock ( & pwm_lock ) ;
return NULL ;
}
2011-12-14 14:12:23 +04:00
static int pwm_device_request ( struct pwm_device * pwm , const char * label )
{
int err ;
if ( test_bit ( PWMF_REQUESTED , & pwm - > flags ) )
return - EBUSY ;
if ( ! try_module_get ( pwm - > chip - > ops - > owner ) )
return - ENODEV ;
if ( pwm - > chip - > ops - > request ) {
err = pwm - > chip - > ops - > request ( pwm - > chip , pwm ) ;
if ( err ) {
module_put ( pwm - > chip - > ops - > owner ) ;
return err ;
}
}
set_bit ( PWMF_REQUESTED , & pwm - > flags ) ;
pwm - > label = label ;
return 0 ;
}
2012-11-21 11:40:44 +04:00
struct pwm_device *
of_pwm_xlate_with_flags ( struct pwm_chip * pc , const struct of_phandle_args * args )
{
struct pwm_device * pwm ;
if ( pc - > of_pwm_n_cells < 3 )
return ERR_PTR ( - EINVAL ) ;
if ( args - > args [ 0 ] > = pc - > npwm )
return ERR_PTR ( - EINVAL ) ;
pwm = pwm_request_from_chip ( pc , args - > args [ 0 ] , NULL ) ;
if ( IS_ERR ( pwm ) )
return pwm ;
2016-04-14 22:17:21 +03:00
pwm - > args . period = args - > args [ 1 ] ;
2012-11-21 11:40:44 +04:00
2013-07-18 02:54:22 +04:00
if ( args - > args [ 2 ] & PWM_POLARITY_INVERTED )
2016-04-14 22:17:21 +03:00
pwm - > args . polarity = PWM_POLARITY_INVERSED ;
2012-11-21 11:40:44 +04:00
else
2016-04-14 22:17:21 +03:00
pwm - > args . polarity = PWM_POLARITY_NORMAL ;
2012-11-21 11:40:44 +04:00
return pwm ;
}
2012-11-28 18:12:07 +04:00
EXPORT_SYMBOL_GPL ( of_pwm_xlate_with_flags ) ;
2012-11-21 11:40:44 +04:00
2012-08-10 15:11:13 +04:00
static struct pwm_device *
of_pwm_simple_xlate ( struct pwm_chip * pc , const struct of_phandle_args * args )
2011-12-14 14:10:32 +04:00
{
struct pwm_device * pwm ;
if ( pc - > of_pwm_n_cells < 2 )
return ERR_PTR ( - EINVAL ) ;
if ( args - > args [ 0 ] > = pc - > npwm )
return ERR_PTR ( - EINVAL ) ;
pwm = pwm_request_from_chip ( pc , args - > args [ 0 ] , NULL ) ;
if ( IS_ERR ( pwm ) )
return pwm ;
2016-04-14 22:17:21 +03:00
pwm - > args . period = args - > args [ 1 ] ;
2011-12-14 14:10:32 +04:00
return pwm ;
}
2012-08-02 11:02:42 +04:00
static void of_pwmchip_add ( struct pwm_chip * chip )
2011-12-14 14:10:32 +04:00
{
if ( ! chip - > dev | | ! chip - > dev - > of_node )
return ;
if ( ! chip - > of_xlate ) {
chip - > of_xlate = of_pwm_simple_xlate ;
chip - > of_pwm_n_cells = 2 ;
}
of_node_get ( chip - > dev - > of_node ) ;
}
2012-08-02 11:02:42 +04:00
static void of_pwmchip_remove ( struct pwm_chip * chip )
2011-12-14 14:10:32 +04:00
{
2015-02-03 13:54:28 +03:00
if ( chip - > dev )
2011-12-14 14:10:32 +04:00
of_node_put ( chip - > dev - > of_node ) ;
}
2011-12-14 14:12:23 +04:00
/**
* pwm_set_chip_data ( ) - set private chip data for a PWM
* @ pwm : PWM device
* @ data : pointer to chip - specific data
2015-07-27 12:58:32 +03:00
*
* Returns : 0 on success or a negative error code on failure .
2011-12-14 14:12:23 +04:00
*/
int pwm_set_chip_data ( struct pwm_device * pwm , void * data )
{
if ( ! pwm )
return - EINVAL ;
pwm - > chip_data = data ;
return 0 ;
}
2013-01-30 12:22:24 +04:00
EXPORT_SYMBOL_GPL ( pwm_set_chip_data ) ;
2011-12-14 14:12:23 +04:00
/**
* pwm_get_chip_data ( ) - get private chip data for a PWM
* @ pwm : PWM device
2015-07-27 12:58:32 +03:00
*
* Returns : A pointer to the chip - private data for the PWM device .
2011-12-14 14:12:23 +04:00
*/
void * pwm_get_chip_data ( struct pwm_device * pwm )
{
return pwm ? pwm - > chip_data : NULL ;
2011-01-28 11:40:40 +03:00
}
2013-01-30 12:22:24 +04:00
EXPORT_SYMBOL_GPL ( pwm_get_chip_data ) ;
2011-01-28 11:40:40 +03:00
2016-04-14 22:17:41 +03:00
static bool pwm_ops_check ( const struct pwm_ops * ops )
{
/* driver supports legacy, non-atomic operation */
if ( ops - > config & & ops - > enable & & ops - > disable )
return true ;
/* driver supports atomic operation */
if ( ops - > apply )
return true ;
return false ;
}
2011-01-28 11:40:40 +03:00
/**
2015-05-26 23:08:16 +03:00
* pwmchip_add_with_polarity ( ) - register a new PWM chip
2011-01-28 11:40:40 +03:00
* @ chip : the PWM chip to add
2015-05-26 23:08:16 +03:00
* @ polarity : initial polarity of PWM channels
2011-12-14 14:12:23 +04:00
*
* Register a new PWM chip . If chip - > base < 0 then a dynamically assigned base
2015-05-26 23:08:16 +03:00
* will be used . The initial polarity for all channels is specified by the
* @ polarity parameter .
2015-07-27 12:58:32 +03:00
*
* Returns : 0 on success or a negative error code on failure .
2011-01-28 11:40:40 +03:00
*/
2015-05-26 23:08:16 +03:00
int pwmchip_add_with_polarity ( struct pwm_chip * chip ,
enum pwm_polarity polarity )
2011-01-28 11:40:40 +03:00
{
struct pwm_device * pwm ;
2011-12-14 14:12:23 +04:00
unsigned int i ;
int ret ;
2011-01-28 11:40:40 +03:00
2016-04-14 22:17:41 +03:00
if ( ! chip | | ! chip - > dev | | ! chip - > ops | | ! chip - > npwm )
return - EINVAL ;
if ( ! pwm_ops_check ( chip - > ops ) )
2011-12-14 14:12:23 +04:00
return - EINVAL ;
2011-01-28 11:40:40 +03:00
mutex_lock ( & pwm_lock ) ;
2011-12-14 14:12:23 +04:00
ret = alloc_pwms ( chip - > base , chip - > npwm ) ;
if ( ret < 0 )
goto out ;
2016-05-02 13:07:34 +03:00
chip - > pwms = kcalloc ( chip - > npwm , sizeof ( * pwm ) , GFP_KERNEL ) ;
2011-12-14 14:12:23 +04:00
if ( ! chip - > pwms ) {
ret = - ENOMEM ;
2011-01-28 11:40:40 +03:00
goto out ;
}
2011-12-14 14:12:23 +04:00
chip - > base = ret ;
for ( i = 0 ; i < chip - > npwm ; i + + ) {
pwm = & chip - > pwms [ i ] ;
pwm - > chip = chip ;
pwm - > pwm = chip - > base + i ;
pwm - > hwpwm = i ;
2016-04-14 22:17:38 +03:00
pwm - > state . polarity = polarity ;
2011-01-28 11:40:40 +03:00
2016-04-14 22:17:40 +03:00
if ( chip - > ops - > get_state )
chip - > ops - > get_state ( chip , pwm , & pwm - > state ) ;
2011-01-28 11:40:40 +03:00
2011-12-14 14:12:23 +04:00
radix_tree_insert ( & pwm_tree , pwm - > pwm , pwm ) ;
}
bitmap_set ( allocated_pwms , chip - > base , chip - > npwm ) ;
INIT_LIST_HEAD ( & chip - > list ) ;
list_add ( & chip - > list , & pwm_chips ) ;
2011-01-28 11:40:40 +03:00
2011-12-14 14:12:23 +04:00
ret = 0 ;
2011-12-14 14:10:32 +04:00
if ( IS_ENABLED ( CONFIG_OF ) )
of_pwmchip_add ( chip ) ;
2013-06-11 21:38:59 +04:00
pwmchip_sysfs_export ( chip ) ;
2011-12-14 14:12:23 +04:00
out :
mutex_unlock ( & pwm_lock ) ;
2011-01-28 11:40:40 +03:00
return ret ;
}
2015-05-26 23:08:16 +03:00
EXPORT_SYMBOL_GPL ( pwmchip_add_with_polarity ) ;
/**
* pwmchip_add ( ) - register a new PWM chip
* @ chip : the PWM chip to add
*
* Register a new PWM chip . If chip - > base < 0 then a dynamically assigned base
* will be used . The initial polarity for all channels is normal .
2015-07-27 12:58:32 +03:00
*
* Returns : 0 on success or a negative error code on failure .
2015-05-26 23:08:16 +03:00
*/
int pwmchip_add ( struct pwm_chip * chip )
{
return pwmchip_add_with_polarity ( chip , PWM_POLARITY_NORMAL ) ;
}
2011-01-28 11:40:40 +03:00
EXPORT_SYMBOL_GPL ( pwmchip_add ) ;
/**
* pwmchip_remove ( ) - remove a PWM chip
* @ chip : the PWM chip to remove
*
* Removes a PWM chip . This function may return busy if the PWM chip provides
* a PWM device that is still requested .
2015-07-27 12:58:32 +03:00
*
* Returns : 0 on success or a negative error code on failure .
2011-01-28 11:40:40 +03:00
*/
int pwmchip_remove ( struct pwm_chip * chip )
{
2011-12-14 14:12:23 +04:00
unsigned int i ;
2011-01-28 11:40:40 +03:00
int ret = 0 ;
mutex_lock ( & pwm_lock ) ;
2011-12-14 14:12:23 +04:00
for ( i = 0 ; i < chip - > npwm ; i + + ) {
struct pwm_device * pwm = & chip - > pwms [ i ] ;
2011-01-28 11:40:40 +03:00
2011-12-14 14:12:23 +04:00
if ( test_bit ( PWMF_REQUESTED , & pwm - > flags ) ) {
ret = - EBUSY ;
goto out ;
}
2011-01-28 11:40:40 +03:00
}
2011-12-14 14:12:23 +04:00
list_del_init ( & chip - > list ) ;
2011-12-14 14:10:32 +04:00
if ( IS_ENABLED ( CONFIG_OF ) )
of_pwmchip_remove ( chip ) ;
2011-12-14 14:12:23 +04:00
free_pwms ( chip ) ;
2011-01-28 11:40:40 +03:00
2013-06-11 21:38:59 +04:00
pwmchip_sysfs_unexport ( chip ) ;
2011-01-28 11:40:40 +03:00
out :
mutex_unlock ( & pwm_lock ) ;
return ret ;
}
EXPORT_SYMBOL_GPL ( pwmchip_remove ) ;
/**
* pwm_request ( ) - request a PWM device
2015-07-27 12:58:32 +03:00
* @ pwm : global PWM device index
2011-01-28 11:40:40 +03:00
* @ label : PWM device label
2012-03-26 10:42:48 +04:00
*
* This function is deprecated , use pwm_get ( ) instead .
2015-07-27 12:58:32 +03:00
*
* Returns : A pointer to a PWM device or an ERR_PTR ( ) - encoded error code on
* failure .
2011-01-28 11:40:40 +03:00
*/
2011-12-14 14:12:23 +04:00
struct pwm_device * pwm_request ( int pwm , const char * label )
2011-01-28 11:40:40 +03:00
{
2011-12-14 14:12:23 +04:00
struct pwm_device * dev ;
int err ;
if ( pwm < 0 | | pwm > = MAX_PWMS )
return ERR_PTR ( - EINVAL ) ;
2011-01-28 11:40:40 +03:00
mutex_lock ( & pwm_lock ) ;
2011-12-14 14:12:23 +04:00
dev = pwm_to_device ( pwm ) ;
if ( ! dev ) {
dev = ERR_PTR ( - EPROBE_DEFER ) ;
2011-01-28 11:40:40 +03:00
goto out ;
}
2011-12-14 14:12:23 +04:00
err = pwm_device_request ( dev , label ) ;
if ( err < 0 )
dev = ERR_PTR ( err ) ;
2011-01-28 11:40:40 +03:00
2011-12-14 14:12:23 +04:00
out :
mutex_unlock ( & pwm_lock ) ;
2011-01-28 11:40:40 +03:00
2011-12-14 14:12:23 +04:00
return dev ;
}
EXPORT_SYMBOL_GPL ( pwm_request ) ;
2011-01-28 11:40:40 +03:00
2011-12-14 14:12:23 +04:00
/**
* pwm_request_from_chip ( ) - request a PWM device relative to a PWM chip
* @ chip : PWM chip
* @ index : per - chip index of the PWM to request
* @ label : a literal description string of this PWM
*
2015-07-27 12:58:32 +03:00
* Returns : A pointer to the PWM device at the given index of the given PWM
* chip . A negative error code is returned if the index is not valid for the
* specified PWM chip or if the PWM device cannot be requested .
2011-12-14 14:12:23 +04:00
*/
struct pwm_device * pwm_request_from_chip ( struct pwm_chip * chip ,
unsigned int index ,
const char * label )
{
struct pwm_device * pwm ;
int err ;
2011-01-28 11:40:40 +03:00
2011-12-14 14:12:23 +04:00
if ( ! chip | | index > = chip - > npwm )
return ERR_PTR ( - EINVAL ) ;
2011-01-28 11:40:40 +03:00
2011-12-14 14:12:23 +04:00
mutex_lock ( & pwm_lock ) ;
pwm = & chip - > pwms [ index ] ;
2011-01-28 11:40:40 +03:00
2011-12-14 14:12:23 +04:00
err = pwm_device_request ( pwm , label ) ;
if ( err < 0 )
pwm = ERR_PTR ( err ) ;
mutex_unlock ( & pwm_lock ) ;
2011-01-28 11:40:40 +03:00
return pwm ;
}
2011-12-14 14:12:23 +04:00
EXPORT_SYMBOL_GPL ( pwm_request_from_chip ) ;
2011-01-28 11:40:40 +03:00
/**
* pwm_free ( ) - free a PWM device
* @ pwm : PWM device
2012-03-26 10:42:48 +04:00
*
* This function is deprecated , use pwm_put ( ) instead .
2011-01-28 11:40:40 +03:00
*/
void pwm_free ( struct pwm_device * pwm )
{
2012-03-26 10:42:48 +04:00
pwm_put ( pwm ) ;
2011-01-28 11:40:40 +03:00
}
EXPORT_SYMBOL_GPL ( pwm_free ) ;
/**
2016-04-14 22:17:41 +03:00
* pwm_apply_state ( ) - atomically apply a new state to a PWM device
2011-01-28 11:40:40 +03:00
* @ pwm : PWM device
2016-04-14 22:17:41 +03:00
* @ state : new state to apply . This can be adjusted by the PWM driver
* if the requested config is not achievable , for example ,
* - > duty_cycle and - > period might be approximated .
2011-01-28 11:40:40 +03:00
*/
2016-04-14 22:17:41 +03:00
int pwm_apply_state ( struct pwm_device * pwm , struct pwm_state * state )
2011-01-28 11:40:40 +03:00
{
2013-06-11 21:38:59 +04:00
int err ;
2016-05-27 19:45:49 +03:00
if ( ! pwm | | ! state | | ! state - > period | |
state - > duty_cycle > state - > period )
2011-12-14 14:12:23 +04:00
return - EINVAL ;
2016-04-14 22:17:41 +03:00
if ( ! memcmp ( state , & pwm - > state , sizeof ( * state ) ) )
return 0 ;
2013-06-11 21:38:59 +04:00
2016-04-14 22:17:41 +03:00
if ( pwm - > chip - > ops - > apply ) {
err = pwm - > chip - > ops - > apply ( pwm - > chip , pwm , state ) ;
if ( err )
return err ;
2011-01-28 11:40:40 +03:00
2016-04-14 22:17:41 +03:00
pwm - > state = * state ;
} else {
/*
* FIXME : restore the initial state in case of error .
*/
if ( state - > polarity ! = pwm - > state . polarity ) {
if ( ! pwm - > chip - > ops - > set_polarity )
return - ENOTSUPP ;
/*
* Changing the polarity of a running PWM is
* only allowed when the PWM driver implements
* - > apply ( ) .
*/
if ( pwm - > state . enabled ) {
pwm - > chip - > ops - > disable ( pwm - > chip , pwm ) ;
pwm - > state . enabled = false ;
}
err = pwm - > chip - > ops - > set_polarity ( pwm - > chip , pwm ,
state - > polarity ) ;
if ( err )
return err ;
pwm - > state . polarity = state - > polarity ;
}
2013-06-11 21:38:59 +04:00
2016-04-14 22:17:41 +03:00
if ( state - > period ! = pwm - > state . period | |
state - > duty_cycle ! = pwm - > state . duty_cycle ) {
err = pwm - > chip - > ops - > config ( pwm - > chip , pwm ,
state - > duty_cycle ,
state - > period ) ;
if ( err )
return err ;
2012-07-24 18:05:32 +04:00
2016-04-14 22:17:41 +03:00
pwm - > state . duty_cycle = state - > duty_cycle ;
pwm - > state . period = state - > period ;
}
2012-07-24 18:05:32 +04:00
2016-04-14 22:17:41 +03:00
if ( state - > enabled ! = pwm - > state . enabled ) {
if ( state - > enabled ) {
err = pwm - > chip - > ops - > enable ( pwm - > chip , pwm ) ;
if ( err )
return err ;
} else {
pwm - > chip - > ops - > disable ( pwm - > chip , pwm ) ;
}
2015-10-17 03:40:58 +03:00
2016-04-14 22:17:41 +03:00
pwm - > state . enabled = state - > enabled ;
}
2015-10-17 03:40:58 +03:00
}
2012-07-24 18:05:32 +04:00
2016-03-30 23:03:27 +03:00
return 0 ;
2012-07-24 18:05:32 +04:00
}
2016-04-14 22:17:41 +03:00
EXPORT_SYMBOL_GPL ( pwm_apply_state ) ;
2012-07-24 18:05:32 +04:00
2016-06-08 12:21:23 +03:00
/**
* pwm_capture ( ) - capture and report a PWM signal
* @ pwm : PWM device
* @ result : structure to fill with capture result
* @ timeout : time to wait , in milliseconds , before giving up on capture
*
* Returns : 0 on success or a negative error code on failure .
*/
int pwm_capture ( struct pwm_device * pwm , struct pwm_capture * result ,
unsigned long timeout )
{
int err ;
if ( ! pwm | | ! pwm - > chip - > ops )
return - EINVAL ;
if ( ! pwm - > chip - > ops - > capture )
return - ENOSYS ;
mutex_lock ( & pwm_lock ) ;
err = pwm - > chip - > ops - > capture ( pwm - > chip , pwm , result , timeout ) ;
mutex_unlock ( & pwm_lock ) ;
return err ;
}
EXPORT_SYMBOL_GPL ( pwm_capture ) ;
2011-01-28 11:40:40 +03:00
/**
2016-04-14 22:17:41 +03:00
* pwm_adjust_config ( ) - adjust the current PWM config to the PWM arguments
2011-01-28 11:40:40 +03:00
* @ pwm : PWM device
2015-07-27 12:58:32 +03:00
*
2016-04-14 22:17:41 +03:00
* This function will adjust the PWM config to the PWM arguments provided
* by the DT or PWM lookup table . This is particularly useful to adapt
* the bootloader config to the Linux one .
2011-01-28 11:40:40 +03:00
*/
2016-04-14 22:17:41 +03:00
int pwm_adjust_config ( struct pwm_device * pwm )
2011-01-28 11:40:40 +03:00
{
2016-04-14 22:17:41 +03:00
struct pwm_state state ;
struct pwm_args pargs ;
2015-10-17 03:40:58 +03:00
2016-04-14 22:17:41 +03:00
pwm_get_args ( pwm , & pargs ) ;
pwm_get_state ( pwm , & state ) ;
2015-10-17 03:40:58 +03:00
2016-04-14 22:17:41 +03:00
/*
* If the current period is zero it means that either the PWM driver
* does not support initial state retrieval or the PWM has not yet
* been configured .
*
* In either case , we setup the new period and polarity , and assign a
* duty cycle of 0.
*/
if ( ! state . period ) {
state . duty_cycle = 0 ;
state . period = pargs . period ;
state . polarity = pargs . polarity ;
2015-10-17 03:40:58 +03:00
2016-04-14 22:17:41 +03:00
return pwm_apply_state ( pwm , & state ) ;
2015-10-17 03:40:58 +03:00
}
2016-04-14 22:17:41 +03:00
/*
* Adjust the PWM duty cycle / period based on the period value provided
* in PWM args .
*/
if ( pargs . period ! = state . period ) {
u64 dutycycle = ( u64 ) state . duty_cycle * pargs . period ;
2011-01-28 11:40:40 +03:00
2016-04-14 22:17:41 +03:00
do_div ( dutycycle , state . period ) ;
state . duty_cycle = dutycycle ;
state . period = pargs . period ;
}
2011-01-28 11:40:40 +03:00
2016-04-14 22:17:41 +03:00
/*
* If the polarity changed , we should also change the duty cycle .
*/
if ( pargs . polarity ! = state . polarity ) {
state . polarity = pargs . polarity ;
state . duty_cycle = state . period - state . duty_cycle ;
2016-04-14 22:17:39 +03:00
}
2016-04-14 22:17:41 +03:00
return pwm_apply_state ( pwm , & state ) ;
2011-01-28 11:40:40 +03:00
}
2016-04-14 22:17:41 +03:00
EXPORT_SYMBOL_GPL ( pwm_adjust_config ) ;
2012-03-26 11:31:48 +04:00
2011-12-14 14:10:32 +04:00
static struct pwm_chip * of_node_to_pwmchip ( struct device_node * np )
{
struct pwm_chip * chip ;
mutex_lock ( & pwm_lock ) ;
list_for_each_entry ( chip , & pwm_chips , list )
if ( chip - > dev & & chip - > dev - > of_node = = np ) {
mutex_unlock ( & pwm_lock ) ;
return chip ;
}
mutex_unlock ( & pwm_lock ) ;
return ERR_PTR ( - EPROBE_DEFER ) ;
}
/**
2012-12-21 13:43:58 +04:00
* of_pwm_get ( ) - request a PWM via the PWM framework
2011-12-14 14:10:32 +04:00
* @ np : device node to get the PWM from
* @ con_id : consumer name
*
* Returns the PWM device parsed from the phandle and index specified in the
* " pwms " property of a device tree node or a negative error - code on failure .
* Values parsed from the device tree are stored in the returned PWM device
* object .
*
* If con_id is NULL , the first PWM device listed in the " pwms " property will
* be requested . Otherwise the " pwm-names " property is used to do a reverse
* lookup of the PWM index . This also means that the " pwm-names " property
* becomes mandatory for devices that look up the PWM device via the con_id
* parameter .
2015-07-27 12:58:32 +03:00
*
* Returns : A pointer to the requested PWM device or an ERR_PTR ( ) - encoded
* error code on failure .
2011-12-14 14:10:32 +04:00
*/
2012-12-21 13:43:58 +04:00
struct pwm_device * of_pwm_get ( struct device_node * np , const char * con_id )
2011-12-14 14:10:32 +04:00
{
struct pwm_device * pwm = NULL ;
struct of_phandle_args args ;
struct pwm_chip * pc ;
int index = 0 ;
int err ;
if ( con_id ) {
index = of_property_match_string ( np , " pwm-names " , con_id ) ;
if ( index < 0 )
return ERR_PTR ( index ) ;
}
err = of_parse_phandle_with_args ( np , " pwms " , " #pwm-cells " , index ,
& args ) ;
if ( err ) {
pr_debug ( " %s(): can't parse \" pwms \" property \n " , __func__ ) ;
return ERR_PTR ( err ) ;
}
pc = of_node_to_pwmchip ( args . np ) ;
if ( IS_ERR ( pc ) ) {
pr_debug ( " %s(): PWM chip not found \n " , __func__ ) ;
pwm = ERR_CAST ( pc ) ;
goto put ;
}
if ( args . args_count ! = pc - > of_pwm_n_cells ) {
pr_debug ( " %s: wrong #pwm-cells for %s \n " , np - > full_name ,
args . np - > full_name ) ;
pwm = ERR_PTR ( - EINVAL ) ;
goto put ;
}
pwm = pc - > of_xlate ( pc , & args ) ;
if ( IS_ERR ( pwm ) )
goto put ;
/*
* If a consumer name was not given , try to look it up from the
* " pwm-names " property if it exists . Otherwise use the name of
* the user device node .
*/
if ( ! con_id ) {
err = of_property_read_string_index ( np , " pwm-names " , index ,
& con_id ) ;
if ( err < 0 )
con_id = np - > name ;
}
pwm - > label = con_id ;
put :
of_node_put ( args . np ) ;
return pwm ;
}
2012-12-21 13:43:58 +04:00
EXPORT_SYMBOL_GPL ( of_pwm_get ) ;
2011-12-14 14:10:32 +04:00
2012-03-26 10:42:48 +04:00
/**
* pwm_add_table ( ) - register PWM device consumers
* @ table : array of consumers to register
* @ num : number of consumers in table
*/
2015-03-12 19:31:31 +03:00
void pwm_add_table ( struct pwm_lookup * table , size_t num )
2012-03-26 10:42:48 +04:00
{
mutex_lock ( & pwm_lookup_lock ) ;
while ( num - - ) {
list_add_tail ( & table - > list , & pwm_lookup_list ) ;
table + + ;
}
mutex_unlock ( & pwm_lookup_lock ) ;
}
2015-05-05 12:34:18 +03:00
/**
* pwm_remove_table ( ) - unregister PWM device consumers
* @ table : array of consumers to unregister
* @ num : number of consumers in table
*/
void pwm_remove_table ( struct pwm_lookup * table , size_t num )
{
mutex_lock ( & pwm_lookup_lock ) ;
while ( num - - ) {
list_del ( & table - > list ) ;
table + + ;
}
mutex_unlock ( & pwm_lookup_lock ) ;
}
2012-03-26 10:42:48 +04:00
/**
* pwm_get ( ) - look up and request a PWM device
* @ dev : device for PWM consumer
* @ con_id : consumer name
*
2011-12-14 14:10:32 +04:00
* Lookup is first attempted using DT . If the device was not instantiated from
* a device tree , a PWM chip and a relative index is looked up via a table
* supplied by board setup code ( see pwm_add_table ( ) ) .
2012-03-26 10:42:48 +04:00
*
* Once a PWM chip has been found the specified PWM device will be requested
* and is ready to be used .
2015-07-27 12:58:32 +03:00
*
* Returns : A pointer to the requested PWM device or an ERR_PTR ( ) - encoded
* error code on failure .
2012-03-26 10:42:48 +04:00
*/
struct pwm_device * pwm_get ( struct device * dev , const char * con_id )
{
struct pwm_device * pwm = ERR_PTR ( - EPROBE_DEFER ) ;
2012-08-10 15:11:13 +04:00
const char * dev_id = dev ? dev_name ( dev ) : NULL ;
2012-03-26 10:42:48 +04:00
struct pwm_chip * chip = NULL ;
unsigned int best = 0 ;
2014-08-28 13:03:14 +04:00
struct pwm_lookup * p , * chosen = NULL ;
2012-03-26 10:42:48 +04:00
unsigned int match ;
2011-12-14 14:10:32 +04:00
/* look up via DT first */
if ( IS_ENABLED ( CONFIG_OF ) & & dev & & dev - > of_node )
2012-12-21 13:43:58 +04:00
return of_pwm_get ( dev - > of_node , con_id ) ;
2011-12-14 14:10:32 +04:00
2012-03-26 10:42:48 +04:00
/*
* We look up the provider in the static table typically provided by
* board setup code . We first try to lookup the consumer device by
* name . If the consumer device was passed in as NULL or if no match
* was found , we try to find the consumer by directly looking it up
* by name .
*
* If a match is found , the provider PWM chip is looked up by name
* and a PWM device is requested using the PWM device per - chip index .
*
* The lookup algorithm was shamelessly taken from the clock
* framework :
*
* We do slightly fuzzy matching here :
* An entry with a NULL ID is assumed to be a wildcard .
* If an entry has a device ID , it must match
* If an entry has a connection ID , it must match
* Then we take the most specific entry - with the following order
* of precedence : dev + con > dev only > con only .
*/
mutex_lock ( & pwm_lookup_lock ) ;
list_for_each_entry ( p , & pwm_lookup_list , list ) {
match = 0 ;
if ( p - > dev_id ) {
if ( ! dev_id | | strcmp ( p - > dev_id , dev_id ) )
continue ;
match + = 2 ;
}
if ( p - > con_id ) {
if ( ! con_id | | strcmp ( p - > con_id , con_id ) )
continue ;
match + = 1 ;
}
if ( match > best ) {
2014-08-28 13:03:14 +04:00
chosen = p ;
2012-03-26 10:42:48 +04:00
if ( match ! = 3 )
best = match ;
else
break ;
}
}
2015-10-05 15:38:32 +03:00
if ( ! chosen ) {
pwm = ERR_PTR ( - ENODEV ) ;
2014-08-28 13:03:14 +04:00
goto out ;
2015-10-05 15:38:32 +03:00
}
2014-05-20 00:42:32 +04:00
2014-08-28 13:03:14 +04:00
chip = pwmchip_find_by_name ( chosen - > provider ) ;
if ( ! chip )
goto out ;
2014-05-20 00:42:32 +04:00
2014-08-28 13:03:14 +04:00
pwm = pwm_request_from_chip ( chip , chosen - > index , con_id ? : dev_id ) ;
if ( IS_ERR ( pwm ) )
goto out ;
2012-03-26 10:42:48 +04:00
2016-05-17 15:27:25 +03:00
pwm - > args . period = chosen - > period ;
pwm - > args . polarity = chosen - > polarity ;
2014-08-28 13:03:14 +04:00
out :
mutex_unlock ( & pwm_lookup_lock ) ;
2012-03-26 10:42:48 +04:00
return pwm ;
}
EXPORT_SYMBOL_GPL ( pwm_get ) ;
/**
* pwm_put ( ) - release a PWM device
* @ pwm : PWM device
*/
void pwm_put ( struct pwm_device * pwm )
{
if ( ! pwm )
return ;
mutex_lock ( & pwm_lock ) ;
if ( ! test_and_clear_bit ( PWMF_REQUESTED , & pwm - > flags ) ) {
2012-08-10 15:11:13 +04:00
pr_warn ( " PWM device already freed \n " ) ;
2012-03-26 10:42:48 +04:00
goto out ;
}
if ( pwm - > chip - > ops - > free )
pwm - > chip - > ops - > free ( pwm - > chip , pwm ) ;
pwm - > label = NULL ;
module_put ( pwm - > chip - > ops - > owner ) ;
out :
mutex_unlock ( & pwm_lock ) ;
}
EXPORT_SYMBOL_GPL ( pwm_put ) ;
2012-08-01 14:20:58 +04:00
static void devm_pwm_release ( struct device * dev , void * res )
{
pwm_put ( * ( struct pwm_device * * ) res ) ;
}
/**
* devm_pwm_get ( ) - resource managed pwm_get ( )
* @ dev : device for PWM consumer
* @ con_id : consumer name
*
* This function performs like pwm_get ( ) but the acquired PWM device will
* automatically be released on driver detach .
2015-07-27 12:58:32 +03:00
*
* Returns : A pointer to the requested PWM device or an ERR_PTR ( ) - encoded
* error code on failure .
2012-08-01 14:20:58 +04:00
*/
struct pwm_device * devm_pwm_get ( struct device * dev , const char * con_id )
{
struct pwm_device * * ptr , * pwm ;
2013-06-04 00:27:17 +04:00
ptr = devres_alloc ( devm_pwm_release , sizeof ( * ptr ) , GFP_KERNEL ) ;
2012-08-01 14:20:58 +04:00
if ( ! ptr )
return ERR_PTR ( - ENOMEM ) ;
pwm = pwm_get ( dev , con_id ) ;
if ( ! IS_ERR ( pwm ) ) {
* ptr = pwm ;
devres_add ( dev , ptr ) ;
} else {
devres_free ( ptr ) ;
}
return pwm ;
}
EXPORT_SYMBOL_GPL ( devm_pwm_get ) ;
2012-12-21 13:43:59 +04:00
/**
* devm_of_pwm_get ( ) - resource managed of_pwm_get ( )
* @ dev : device for PWM consumer
* @ np : device node to get the PWM from
* @ con_id : consumer name
*
* This function performs like of_pwm_get ( ) but the acquired PWM device will
* automatically be released on driver detach .
2015-07-27 12:58:32 +03:00
*
* Returns : A pointer to the requested PWM device or an ERR_PTR ( ) - encoded
* error code on failure .
2012-12-21 13:43:59 +04:00
*/
struct pwm_device * devm_of_pwm_get ( struct device * dev , struct device_node * np ,
const char * con_id )
{
struct pwm_device * * ptr , * pwm ;
2013-06-04 00:27:17 +04:00
ptr = devres_alloc ( devm_pwm_release , sizeof ( * ptr ) , GFP_KERNEL ) ;
2012-12-21 13:43:59 +04:00
if ( ! ptr )
return ERR_PTR ( - ENOMEM ) ;
pwm = of_pwm_get ( np , con_id ) ;
if ( ! IS_ERR ( pwm ) ) {
* ptr = pwm ;
devres_add ( dev , ptr ) ;
} else {
devres_free ( ptr ) ;
}
return pwm ;
}
EXPORT_SYMBOL_GPL ( devm_of_pwm_get ) ;
2012-08-01 14:20:58 +04:00
static int devm_pwm_match ( struct device * dev , void * res , void * data )
{
struct pwm_device * * p = res ;
if ( WARN_ON ( ! p | | ! * p ) )
return 0 ;
return * p = = data ;
}
/**
* devm_pwm_put ( ) - resource managed pwm_put ( )
* @ dev : device for PWM consumer
* @ pwm : PWM device
*
* Release a PWM previously allocated using devm_pwm_get ( ) . Calling this
* function is usually not needed because devm - allocated resources are
* automatically released on driver detach .
*/
void devm_pwm_put ( struct device * dev , struct pwm_device * pwm )
{
WARN_ON ( devres_release ( dev , devm_pwm_release , devm_pwm_match , pwm ) ) ;
}
EXPORT_SYMBOL_GPL ( devm_pwm_put ) ;
2013-01-28 18:00:57 +04:00
/**
* pwm_can_sleep ( ) - report whether PWM access will sleep
* @ pwm : PWM device
*
2015-07-27 12:58:32 +03:00
* Returns : True if accessing the PWM can sleep , false otherwise .
2013-01-28 18:00:57 +04:00
*/
bool pwm_can_sleep ( struct pwm_device * pwm )
{
2016-01-21 17:04:59 +03:00
return true ;
2013-01-28 18:00:57 +04:00
}
EXPORT_SYMBOL_GPL ( pwm_can_sleep ) ;
2012-03-26 11:31:48 +04:00
# ifdef CONFIG_DEBUG_FS
static void pwm_dbg_show ( struct pwm_chip * chip , struct seq_file * s )
{
unsigned int i ;
for ( i = 0 ; i < chip - > npwm ; i + + ) {
struct pwm_device * pwm = & chip - > pwms [ i ] ;
2016-04-14 22:17:43 +03:00
struct pwm_state state ;
pwm_get_state ( pwm , & state ) ;
2012-03-26 11:31:48 +04:00
seq_printf ( s , " pwm-%-3d (%-20.20s): " , i , pwm - > label ) ;
if ( test_bit ( PWMF_REQUESTED , & pwm - > flags ) )
2013-12-19 08:31:24 +04:00
seq_puts ( s , " requested " ) ;
2012-03-26 11:31:48 +04:00
2016-04-14 22:17:43 +03:00
if ( state . enabled )
2013-12-19 08:31:24 +04:00
seq_puts ( s , " enabled " ) ;
2012-03-26 11:31:48 +04:00
2016-04-14 22:17:44 +03:00
seq_printf ( s , " period: %u ns " , state . period ) ;
seq_printf ( s , " duty: %u ns " , state . duty_cycle ) ;
seq_printf ( s , " polarity: %s " ,
state . polarity ? " inverse " : " normal " ) ;
2013-12-19 08:31:24 +04:00
seq_puts ( s , " \n " ) ;
2012-03-26 11:31:48 +04:00
}
}
static void * pwm_seq_start ( struct seq_file * s , loff_t * pos )
{
mutex_lock ( & pwm_lock ) ;
s - > private = " " ;
return seq_list_start ( & pwm_chips , * pos ) ;
}
static void * pwm_seq_next ( struct seq_file * s , void * v , loff_t * pos )
{
s - > private = " \n " ;
return seq_list_next ( v , & pwm_chips , pos ) ;
}
static void pwm_seq_stop ( struct seq_file * s , void * v )
{
mutex_unlock ( & pwm_lock ) ;
}
static int pwm_seq_show ( struct seq_file * s , void * v )
{
struct pwm_chip * chip = list_entry ( v , struct pwm_chip , list ) ;
seq_printf ( s , " %s%s/%s, %d PWM device%s \n " , ( char * ) s - > private ,
chip - > dev - > bus ? chip - > dev - > bus - > name : " no-bus " ,
dev_name ( chip - > dev ) , chip - > npwm ,
( chip - > npwm ! = 1 ) ? " s " : " " ) ;
if ( chip - > ops - > dbg_show )
chip - > ops - > dbg_show ( chip , s ) ;
else
pwm_dbg_show ( chip , s ) ;
return 0 ;
}
static const struct seq_operations pwm_seq_ops = {
. start = pwm_seq_start ,
. next = pwm_seq_next ,
. stop = pwm_seq_stop ,
. show = pwm_seq_show ,
} ;
static int pwm_seq_open ( struct inode * inode , struct file * file )
{
return seq_open ( file , & pwm_seq_ops ) ;
}
static const struct file_operations pwm_debugfs_ops = {
. owner = THIS_MODULE ,
. open = pwm_seq_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = seq_release ,
} ;
static int __init pwm_debugfs_init ( void )
{
debugfs_create_file ( " pwm " , S_IFREG | S_IRUGO , NULL , NULL ,
& pwm_debugfs_ops ) ;
return 0 ;
}
subsys_initcall ( pwm_debugfs_init ) ;
# endif /* CONFIG_DEBUG_FS */