2019-05-19 15:51:48 +02:00
// SPDX-License-Identifier: GPL-2.0-or-later
2011-01-28 09:40:40 +01:00
/*
* Generic pwmlib implementation
*
* Copyright ( C ) 2011 Sascha Hauer < s . hauer @ pengutronix . de >
2011-12-14 11:12:23 +01:00
* Copyright ( C ) 2011 - 2012 Avionic Design GmbH
2011-01-28 09:40:40 +01:00
*/
2019-06-12 10:36:07 +02:00
# include <linux/acpi.h>
2011-01-28 09:40:40 +01:00
# include <linux/module.h>
2023-11-14 12:20:12 +01:00
# include <linux/idr.h>
2023-07-14 11:48:50 -06:00
# include <linux/of.h>
2011-01-28 09:40:40 +01:00
# include <linux/pwm.h>
# include <linux/list.h>
# include <linux/mutex.h>
# include <linux/err.h>
# include <linux/slab.h>
# include <linux/device.h>
2012-03-26 09:31:48 +02:00
# include <linux/debugfs.h>
# include <linux/seq_file.h>
2011-01-28 09:40:40 +01:00
2013-07-18 00:54:22 +02:00
# include <dt-bindings/pwm/pwm.h>
2011-01-28 09:40:40 +01:00
2019-10-24 10:08:29 +02:00
# define CREATE_TRACE_POINTS
# include <trace/events/pwm.h>
2023-11-14 12:20:12 +01:00
/* protects access to pwm_chips */
2011-01-28 09:40:40 +01:00
static DEFINE_MUTEX ( pwm_lock ) ;
2022-12-02 19:35:09 +01:00
2023-11-14 12:20:12 +01:00
static DEFINE_IDR ( pwm_chips ) ;
2011-12-14 11:12:23 +01:00
2024-01-25 13:08:23 +01:00
static void pwm_apply_debug ( struct pwm_device * pwm ,
const struct pwm_state * state )
2012-03-26 08:42:48 +02:00
{
2024-01-25 13:08:23 +01:00
struct pwm_state * last = & pwm - > last ;
struct pwm_chip * chip = pwm - > chip ;
struct pwm_state s1 = { 0 } , s2 = { 0 } ;
int err ;
2012-03-26 08:42:48 +02:00
2024-01-25 13:08:23 +01:00
if ( ! IS_ENABLED ( CONFIG_PWM_DEBUG ) )
return ;
2012-03-26 08:42:48 +02:00
2024-01-25 13:08:23 +01:00
/* No reasonable diagnosis possible without .get_state() */
if ( ! chip - > ops - > get_state )
return ;
2012-03-26 08:42:48 +02:00
2024-01-25 13:08:23 +01:00
/*
* * state was just applied . Read out the hardware state and do some
* checks .
*/
2012-03-26 08:42:48 +02:00
2024-01-25 13:08:23 +01:00
err = chip - > ops - > get_state ( chip , pwm , & s1 ) ;
trace_pwm_get ( pwm , & s1 , err ) ;
if ( err )
/* If that failed there isn't much to debug */
return ;
2012-03-26 08:42:48 +02:00
2024-01-25 13:08:23 +01:00
/*
* The lowlevel driver either ignored . polarity ( which is a bug ) or as
* best effort inverted . polarity and fixed . duty_cycle respectively .
* Undo this inversion and fixup for further tests .
*/
if ( s1 . enabled & & s1 . polarity ! = state - > polarity ) {
s2 . polarity = state - > polarity ;
s2 . duty_cycle = s1 . period - s1 . duty_cycle ;
s2 . period = s1 . period ;
s2 . enabled = s1 . enabled ;
} else {
s2 = s1 ;
}
2011-12-14 11:12:23 +01:00
2024-01-25 13:08:23 +01:00
if ( s2 . polarity ! = state - > polarity & &
state - > duty_cycle < state - > period )
2024-02-14 10:30:48 +01:00
dev_warn ( pwmchip_parent ( chip ) , " .apply ignored .polarity \n " ) ;
2011-12-14 11:12:23 +01:00
2024-01-25 13:08:23 +01:00
if ( state - > enabled & &
last - > polarity = = state - > polarity & &
last - > period > s2 . period & &
last - > period < = state - > period )
2024-02-14 10:30:48 +01:00
dev_warn ( pwmchip_parent ( chip ) ,
2024-01-25 13:08:23 +01:00
" .apply didn't pick the best available period (requested: %llu, applied: %llu, possible: %llu) \n " ,
state - > period , s2 . period , last - > period ) ;
2011-12-14 11:12:23 +01:00
2024-01-25 13:08:23 +01:00
if ( state - > enabled & & state - > period < s2 . period )
2024-02-14 10:30:48 +01:00
dev_warn ( pwmchip_parent ( chip ) ,
2024-01-25 13:08:23 +01:00
" .apply is supposed to round down period (requested: %llu, applied: %llu) \n " ,
state - > period , s2 . period ) ;
2011-12-14 11:12:23 +01:00
2024-01-25 13:08:23 +01:00
if ( state - > enabled & &
last - > polarity = = state - > polarity & &
last - > period = = s2 . period & &
last - > duty_cycle > s2 . duty_cycle & &
last - > duty_cycle < = state - > duty_cycle )
2024-02-14 10:30:48 +01:00
dev_warn ( pwmchip_parent ( chip ) ,
2024-01-25 13:08:23 +01:00
" .apply didn't pick the best available duty cycle (requested: %llu/%llu, applied: %llu/%llu, possible: %llu/%llu) \n " ,
state - > duty_cycle , state - > period ,
s2 . duty_cycle , s2 . period ,
last - > duty_cycle , last - > period ) ;
2022-12-02 19:35:36 +01:00
2024-01-25 13:08:23 +01:00
if ( state - > enabled & & state - > duty_cycle < s2 . duty_cycle )
2024-02-14 10:30:48 +01:00
dev_warn ( pwmchip_parent ( chip ) ,
2024-01-25 13:08:23 +01:00
" .apply is supposed to round down duty_cycle (requested: %llu/%llu, applied: %llu/%llu) \n " ,
state - > duty_cycle , state - > period ,
s2 . duty_cycle , s2 . period ) ;
2022-12-02 19:35:36 +01:00
2024-01-25 13:08:23 +01:00
if ( ! state - > enabled & & s2 . enabled & & s2 . duty_cycle > 0 )
2024-02-14 10:30:48 +01:00
dev_warn ( pwmchip_parent ( chip ) ,
2024-01-25 13:08:23 +01:00
" requested disabled, but yielded enabled with duty > 0 \n " ) ;
2020-02-10 22:35:18 +01:00
2024-01-25 13:08:23 +01:00
/* reapply the state that the driver reported being configured. */
err = chip - > ops - > apply ( chip , pwm , & s1 ) ;
trace_pwm_apply ( pwm , & s1 , err ) ;
if ( err ) {
* last = s1 ;
2024-02-14 10:30:48 +01:00
dev_err ( pwmchip_parent ( chip ) , " failed to reapply current setting \n " ) ;
2024-01-25 13:08:23 +01:00
return ;
2019-10-24 10:08:29 +02:00
}
2019-10-21 12:51:56 +02:00
2024-01-25 13:08:23 +01:00
* last = ( struct pwm_state ) { 0 } ;
err = chip - > ops - > get_state ( chip , pwm , last ) ;
trace_pwm_get ( pwm , last , err ) ;
if ( err )
return ;
2011-12-14 11:12:23 +01:00
2024-01-25 13:08:23 +01:00
/* reapplication of the current state should give an exact match */
if ( s1 . enabled ! = last - > enabled | |
s1 . polarity ! = last - > polarity | |
( s1 . enabled & & s1 . period ! = last - > period ) | |
( s1 . enabled & & s1 . duty_cycle ! = last - > duty_cycle ) ) {
2024-02-14 10:30:48 +01:00
dev_err ( pwmchip_parent ( chip ) ,
2024-01-25 13:08:23 +01:00
" .apply is not idempotent (ena=%d pol=%d %llu/%llu) -> (ena=%d pol=%d %llu/%llu) \n " ,
s1 . enabled , s1 . polarity , s1 . duty_cycle , s1 . period ,
last - > enabled , last - > polarity , last - > duty_cycle ,
last - > period ) ;
}
2011-12-14 11:12:23 +01:00
}
2024-01-25 13:08:23 +01:00
/**
* __pwm_apply ( ) - atomically apply a new state to a PWM device
* @ pwm : PWM device
* @ state : new state to apply
*/
static int __pwm_apply ( struct pwm_device * pwm , const struct pwm_state * state )
2012-11-21 13:10:44 +05:30
{
2024-01-25 13:08:23 +01:00
struct pwm_chip * chip ;
int err ;
2012-11-21 13:10:44 +05:30
2024-01-25 13:08:23 +01:00
if ( ! pwm | | ! state | | ! state - > period | |
state - > duty_cycle > state - > period )
return - EINVAL ;
2017-01-29 22:54:13 +01:00
2024-01-25 13:08:23 +01:00
chip = pwm - > chip ;
2012-11-21 13:10:44 +05:30
2024-01-25 13:08:23 +01:00
if ( state - > period = = pwm - > state . period & &
state - > duty_cycle = = pwm - > state . duty_cycle & &
state - > polarity = = pwm - > state . polarity & &
state - > enabled = = pwm - > state . enabled & &
state - > usage_power = = pwm - > state . usage_power )
return 0 ;
2012-11-21 13:10:44 +05:30
2024-01-25 13:08:23 +01:00
err = chip - > ops - > apply ( chip , pwm , state ) ;
trace_pwm_apply ( pwm , state , err ) ;
if ( err )
return err ;
2012-11-21 13:10:44 +05:30
2024-01-25 13:08:23 +01:00
pwm - > state = * state ;
/*
* only do this after pwm - > state was applied as some
* implementations of . get_state depend on this
*/
pwm_apply_debug ( pwm , state ) ;
return 0 ;
2012-11-21 13:10:44 +05:30
}
2024-01-25 13:08:23 +01:00
/**
* pwm_apply_might_sleep ( ) - atomically apply a new state to a PWM device
* Cannot be used in atomic context .
* @ pwm : PWM device
* @ state : new state to apply
*/
int pwm_apply_might_sleep ( struct pwm_device * pwm , const struct pwm_state * state )
2021-10-25 10:09:23 -07:00
{
2024-01-25 13:08:23 +01:00
int err ;
2021-10-25 10:09:23 -07:00
2024-01-25 13:08:23 +01:00
/*
* Some lowlevel driver ' s implementations of . apply ( ) make use of
* mutexes , also with some drivers only returning when the new
* configuration is active calling pwm_apply_might_sleep ( ) from atomic context
* is a bad idea . So make it explicit that calling this function might
* sleep .
*/
might_sleep ( ) ;
2021-10-25 10:09:23 -07:00
2024-01-25 13:08:23 +01:00
if ( IS_ENABLED ( CONFIG_PWM_DEBUG ) & & pwm - > chip - > atomic ) {
/*
* Catch any drivers that have been marked as atomic but
* that will sleep anyway .
*/
non_block_start ( ) ;
err = __pwm_apply ( pwm , state ) ;
non_block_end ( ) ;
} else {
err = __pwm_apply ( pwm , state ) ;
}
2021-10-25 10:09:23 -07:00
2024-01-25 13:08:23 +01:00
return err ;
2021-10-25 10:09:23 -07:00
}
2024-01-25 13:08:23 +01:00
EXPORT_SYMBOL_GPL ( pwm_apply_might_sleep ) ;
2021-10-25 10:09:23 -07:00
2024-01-25 13:08:23 +01:00
/**
* pwm_apply_atomic ( ) - apply a new state to a PWM device from atomic context
* Not all PWM devices support this function , check with pwm_might_sleep ( ) .
* @ pwm : PWM device
* @ state : new state to apply
*/
int pwm_apply_atomic ( struct pwm_device * pwm , const struct pwm_state * state )
2011-12-14 11:10:32 +01:00
{
2024-01-25 13:08:23 +01:00
WARN_ONCE ( ! pwm - > chip - > atomic ,
" sleeping PWM driver used in atomic context \n " ) ;
2011-12-14 11:10:32 +01:00
2024-01-25 13:08:23 +01:00
return __pwm_apply ( pwm , state ) ;
2011-12-14 11:10:32 +01:00
}
2024-01-25 13:08:23 +01:00
EXPORT_SYMBOL_GPL ( pwm_apply_atomic ) ;
2011-12-14 11:10:32 +01:00
2024-01-25 13:08:23 +01:00
/**
* pwm_adjust_config ( ) - adjust the current PWM config to the PWM arguments
* @ pwm : PWM device
*
* 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 .
*/
int pwm_adjust_config ( struct pwm_device * pwm )
2011-12-14 11:10:32 +01:00
{
2024-01-25 13:08:23 +01:00
struct pwm_state state ;
struct pwm_args pargs ;
2011-12-14 11:10:32 +01:00
2024-01-25 13:08:23 +01:00
pwm_get_args ( pwm , & pargs ) ;
pwm_get_state ( pwm , & state ) ;
2020-02-10 22:35:18 +01:00
2024-01-25 13:08:23 +01: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 ;
2020-02-10 22:35:18 +01:00
2024-01-25 13:08:23 +01:00
return pwm_apply_might_sleep ( pwm , & state ) ;
}
2016-04-14 21:17:41 +02:00
2024-01-25 13:08:23 +01: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 ;
do_div ( dutycycle , state . period ) ;
state . duty_cycle = dutycycle ;
state . period = pargs . period ;
}
/*
* 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 ;
}
return pwm_apply_might_sleep ( pwm , & state ) ;
2016-04-14 21:17:41 +02:00
}
2024-01-25 13:08:23 +01:00
EXPORT_SYMBOL_GPL ( pwm_adjust_config ) ;
2016-04-14 21:17:41 +02:00
2011-01-28 09:40:40 +01:00
/**
2024-01-25 13:08:23 +01: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
2015-07-27 11:58:32 +02:00
*
* Returns : 0 on success or a negative error code on failure .
2011-01-28 09:40:40 +01:00
*/
2024-01-25 13:08:23 +01:00
int pwm_capture ( struct pwm_device * pwm , struct pwm_capture * result ,
unsigned long timeout )
2011-01-28 09:40:40 +01:00
{
2024-01-25 13:08:23 +01:00
int err ;
2011-01-28 09:40:40 +01:00
2024-01-25 13:08:23 +01:00
if ( ! pwm | | ! pwm - > chip - > ops )
2016-04-14 21:17:41 +02:00
return - EINVAL ;
2024-01-25 13:08:23 +01:00
if ( ! pwm - > chip - > ops - > capture )
return - ENOSYS ;
2011-01-28 09:40:40 +01:00
2024-01-25 13:08:23 +01:00
mutex_lock ( & pwm_lock ) ;
err = pwm - > chip - > ops - > capture ( pwm - > chip , pwm , result , timeout ) ;
mutex_unlock ( & pwm_lock ) ;
2023-08-04 16:27:06 +02:00
2024-01-25 13:08:23 +01:00
return err ;
}
EXPORT_SYMBOL_GPL ( pwm_capture ) ;
2022-12-02 19:35:10 +01:00
2024-01-25 13:08:23 +01:00
static struct pwm_chip * pwmchip_find_by_name ( const char * name )
{
struct pwm_chip * chip ;
unsigned long id , tmp ;
2011-01-28 09:40:40 +01:00
2024-01-25 13:08:23 +01:00
if ( ! name )
return NULL ;
2011-12-14 11:12:23 +01:00
2024-01-25 13:08:23 +01:00
mutex_lock ( & pwm_lock ) ;
2021-03-01 19:57:19 +01:00
2024-01-25 13:08:23 +01:00
idr_for_each_entry_ul ( & pwm_chips , chip , tmp , id ) {
2024-02-14 10:30:48 +01:00
const char * chip_name = dev_name ( pwmchip_parent ( chip ) ) ;
2011-12-14 11:12:23 +01:00
2024-01-25 13:08:23 +01:00
if ( chip_name & & strcmp ( chip_name , name ) = = 0 ) {
mutex_unlock ( & pwm_lock ) ;
return chip ;
}
2011-12-14 11:12:23 +01:00
}
2022-12-02 19:35:10 +01:00
mutex_unlock ( & pwm_lock ) ;
2011-12-14 11:12:23 +01:00
2024-01-25 13:08:23 +01:00
return NULL ;
2011-01-28 09:40:40 +01:00
}
2024-01-25 13:08:23 +01:00
static int pwm_device_request ( struct pwm_device * pwm , const char * label )
2011-01-28 09:40:40 +01:00
{
2024-01-25 13:08:23 +01:00
int err ;
struct pwm_chip * chip = pwm - > chip ;
const struct pwm_ops * ops = chip - > ops ;
2023-07-25 10:10:04 +02:00
2024-01-25 13:08:23 +01:00
if ( test_bit ( PWMF_REQUESTED , & pwm - > flags ) )
return - EBUSY ;
2011-01-28 09:40:40 +01:00
2024-01-25 13:08:23 +01:00
if ( ! try_module_get ( chip - > owner ) )
return - ENODEV ;
2011-01-28 09:40:40 +01:00
2024-03-17 11:40:36 +01:00
if ( ! get_device ( & chip - > dev ) ) {
err = - ENODEV ;
goto err_get_device ;
}
2024-01-25 13:08:23 +01:00
if ( ops - > request ) {
err = ops - > request ( chip , pwm ) ;
if ( err ) {
2024-03-17 11:40:36 +01:00
put_device ( & chip - > dev ) ;
err_get_device :
2024-01-25 13:08:23 +01:00
module_put ( chip - > owner ) ;
return err ;
}
}
2023-11-14 12:20:12 +01:00
2024-01-25 13:08:23 +01:00
if ( ops - > get_state ) {
/*
* Zero - initialize state because most drivers are unaware of
* . usage_power . The other members of state are supposed to be
* set by lowlevel drivers . We still initialize the whole
* structure for simplicity even though this might paper over
* faulty implementations of . get_state ( ) .
*/
struct pwm_state state = { 0 , } ;
2011-01-28 09:40:40 +01:00
2024-01-25 13:08:23 +01:00
err = ops - > get_state ( chip , pwm , & state ) ;
trace_pwm_get ( pwm , & state , err ) ;
2021-04-07 10:01:54 +02:00
2024-01-25 13:08:23 +01:00
if ( ! err )
pwm - > state = state ;
2021-04-07 10:01:54 +02:00
2024-01-25 13:08:23 +01:00
if ( IS_ENABLED ( CONFIG_PWM_DEBUG ) )
pwm - > last = pwm - > state ;
}
2021-04-07 10:01:54 +02:00
2024-01-25 13:08:23 +01:00
set_bit ( PWMF_REQUESTED , & pwm - > flags ) ;
pwm - > label = label ;
2021-04-07 10:01:54 +02:00
2024-01-25 13:08:23 +01:00
return 0 ;
2021-04-07 10:01:54 +02:00
}
2011-12-14 11:12:23 +01: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 11:58:32 +02: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 11:12:23 +01: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 09:40:40 +01:00
2011-12-14 11:12:23 +01:00
if ( ! chip | | index > = chip - > npwm )
return ERR_PTR ( - EINVAL ) ;
2011-01-28 09:40:40 +01:00
2011-12-14 11:12:23 +01:00
mutex_lock ( & pwm_lock ) ;
pwm = & chip - > pwms [ index ] ;
2011-01-28 09:40:40 +01:00
2011-12-14 11:12:23 +01:00
err = pwm_device_request ( pwm , label ) ;
if ( err < 0 )
pwm = ERR_PTR ( err ) ;
mutex_unlock ( & pwm_lock ) ;
2011-01-28 09:40:40 +01:00
return pwm ;
}
2011-12-14 11:12:23 +01:00
EXPORT_SYMBOL_GPL ( pwm_request_from_chip ) ;
2011-01-28 09:40:40 +01:00
2020-02-10 22:35:18 +01:00
2024-01-25 13:08:23 +01:00
struct pwm_device *
of_pwm_xlate_with_flags ( struct pwm_chip * chip , const struct of_phandle_args * args )
{
struct pwm_device * pwm ;
2020-02-10 22:35:18 +01:00
2024-01-25 13:08:23 +01:00
/* period in the second cell and flags in the third cell are optional */
if ( args - > args_count < 1 )
return ERR_PTR ( - EINVAL ) ;
2020-02-10 22:35:18 +01:00
2024-01-25 13:08:23 +01:00
pwm = pwm_request_from_chip ( chip , args - > args [ 0 ] , NULL ) ;
if ( IS_ERR ( pwm ) )
return pwm ;
2013-06-11 10:38:59 -07:00
2024-01-25 13:08:23 +01:00
if ( args - > args_count > 1 )
pwm - > args . period = args - > args [ 1 ] ;
2011-12-14 11:12:23 +01:00
2024-01-25 13:08:23 +01:00
pwm - > args . polarity = PWM_POLARITY_NORMAL ;
if ( args - > args_count > 2 & & args - > args [ 2 ] & PWM_POLARITY_INVERTED )
pwm - > args . polarity = PWM_POLARITY_INVERSED ;
2019-08-24 17:37:02 +02:00
2024-01-25 13:08:23 +01:00
return pwm ;
}
EXPORT_SYMBOL_GPL ( of_pwm_xlate_with_flags ) ;
2013-06-11 10:38:59 -07:00
2024-01-25 13:08:23 +01:00
struct pwm_device *
of_pwm_single_xlate ( struct pwm_chip * chip , const struct of_phandle_args * args )
{
struct pwm_device * pwm ;
2016-04-14 21:17:41 +02:00
2024-01-25 13:08:23 +01:00
pwm = pwm_request_from_chip ( chip , 0 , NULL ) ;
if ( IS_ERR ( pwm ) )
return pwm ;
2016-04-14 21:17:41 +02:00
2024-03-29 11:35:40 +01:00
if ( args - > args_count > 0 )
2024-01-25 13:08:23 +01:00
pwm - > args . period = args - > args [ 0 ] ;
2012-07-24 19:35:32 +05:30
2024-01-25 13:08:23 +01:00
pwm - > args . polarity = PWM_POLARITY_NORMAL ;
if ( args - > args_count > 1 & & args - > args [ 1 ] & PWM_POLARITY_INVERTED )
pwm - > args . polarity = PWM_POLARITY_INVERSED ;
return pwm ;
2012-07-24 19:35:32 +05:30
}
2024-01-25 13:08:23 +01:00
EXPORT_SYMBOL_GPL ( of_pwm_single_xlate ) ;
2023-12-19 16:30:27 +00:00
2024-03-17 11:40:34 +01:00
struct pwm_export {
struct device pwm_dev ;
struct pwm_device * pwm ;
struct mutex lock ;
struct pwm_state suspend ;
} ;
static inline struct pwm_chip * pwmchip_from_dev ( struct device * pwmchip_dev )
{
2024-03-17 11:40:36 +01:00
return container_of ( pwmchip_dev , struct pwm_chip , dev ) ;
2024-03-17 11:40:34 +01:00
}
static inline struct pwm_export * pwmexport_from_dev ( struct device * pwm_dev )
{
return container_of ( pwm_dev , struct pwm_export , pwm_dev ) ;
}
static inline struct pwm_device * pwm_from_dev ( struct device * pwm_dev )
{
struct pwm_export * export = pwmexport_from_dev ( pwm_dev ) ;
return export - > pwm ;
}
static ssize_t period_show ( struct device * pwm_dev ,
struct device_attribute * attr ,
char * buf )
{
const struct pwm_device * pwm = pwm_from_dev ( pwm_dev ) ;
struct pwm_state state ;
pwm_get_state ( pwm , & state ) ;
return sysfs_emit ( buf , " %llu \n " , state . period ) ;
}
static ssize_t period_store ( struct device * pwm_dev ,
struct device_attribute * attr ,
const char * buf , size_t size )
{
struct pwm_export * export = pwmexport_from_dev ( pwm_dev ) ;
struct pwm_device * pwm = export - > pwm ;
struct pwm_state state ;
u64 val ;
int ret ;
ret = kstrtou64 ( buf , 0 , & val ) ;
if ( ret )
return ret ;
mutex_lock ( & export - > lock ) ;
pwm_get_state ( pwm , & state ) ;
state . period = val ;
ret = pwm_apply_might_sleep ( pwm , & state ) ;
mutex_unlock ( & export - > lock ) ;
return ret ? : size ;
}
static ssize_t duty_cycle_show ( struct device * pwm_dev ,
struct device_attribute * attr ,
char * buf )
{
const struct pwm_device * pwm = pwm_from_dev ( pwm_dev ) ;
struct pwm_state state ;
pwm_get_state ( pwm , & state ) ;
return sysfs_emit ( buf , " %llu \n " , state . duty_cycle ) ;
}
static ssize_t duty_cycle_store ( struct device * pwm_dev ,
struct device_attribute * attr ,
const char * buf , size_t size )
{
struct pwm_export * export = pwmexport_from_dev ( pwm_dev ) ;
struct pwm_device * pwm = export - > pwm ;
struct pwm_state state ;
u64 val ;
int ret ;
ret = kstrtou64 ( buf , 0 , & val ) ;
if ( ret )
return ret ;
mutex_lock ( & export - > lock ) ;
pwm_get_state ( pwm , & state ) ;
state . duty_cycle = val ;
ret = pwm_apply_might_sleep ( pwm , & state ) ;
mutex_unlock ( & export - > lock ) ;
return ret ? : size ;
}
static ssize_t enable_show ( struct device * pwm_dev ,
struct device_attribute * attr ,
char * buf )
{
const struct pwm_device * pwm = pwm_from_dev ( pwm_dev ) ;
struct pwm_state state ;
pwm_get_state ( pwm , & state ) ;
return sysfs_emit ( buf , " %d \n " , state . enabled ) ;
}
static ssize_t enable_store ( struct device * pwm_dev ,
struct device_attribute * attr ,
const char * buf , size_t size )
{
struct pwm_export * export = pwmexport_from_dev ( pwm_dev ) ;
struct pwm_device * pwm = export - > pwm ;
struct pwm_state state ;
int val , ret ;
ret = kstrtoint ( buf , 0 , & val ) ;
if ( ret )
return ret ;
mutex_lock ( & export - > lock ) ;
pwm_get_state ( pwm , & state ) ;
switch ( val ) {
case 0 :
state . enabled = false ;
break ;
case 1 :
state . enabled = true ;
break ;
default :
ret = - EINVAL ;
goto unlock ;
}
ret = pwm_apply_might_sleep ( pwm , & state ) ;
unlock :
mutex_unlock ( & export - > lock ) ;
return ret ? : size ;
}
static ssize_t polarity_show ( struct device * pwm_dev ,
struct device_attribute * attr ,
char * buf )
{
const struct pwm_device * pwm = pwm_from_dev ( pwm_dev ) ;
const char * polarity = " unknown " ;
struct pwm_state state ;
pwm_get_state ( pwm , & state ) ;
switch ( state . polarity ) {
case PWM_POLARITY_NORMAL :
polarity = " normal " ;
break ;
case PWM_POLARITY_INVERSED :
polarity = " inversed " ;
break ;
}
return sysfs_emit ( buf , " %s \n " , polarity ) ;
}
static ssize_t polarity_store ( struct device * pwm_dev ,
struct device_attribute * attr ,
const char * buf , size_t size )
{
struct pwm_export * export = pwmexport_from_dev ( pwm_dev ) ;
struct pwm_device * pwm = export - > pwm ;
enum pwm_polarity polarity ;
struct pwm_state state ;
int ret ;
if ( sysfs_streq ( buf , " normal " ) )
polarity = PWM_POLARITY_NORMAL ;
else if ( sysfs_streq ( buf , " inversed " ) )
polarity = PWM_POLARITY_INVERSED ;
else
return - EINVAL ;
mutex_lock ( & export - > lock ) ;
pwm_get_state ( pwm , & state ) ;
state . polarity = polarity ;
ret = pwm_apply_might_sleep ( pwm , & state ) ;
mutex_unlock ( & export - > lock ) ;
return ret ? : size ;
}
static ssize_t capture_show ( struct device * pwm_dev ,
struct device_attribute * attr ,
char * buf )
{
struct pwm_device * pwm = pwm_from_dev ( pwm_dev ) ;
struct pwm_capture result ;
int ret ;
ret = pwm_capture ( pwm , & result , jiffies_to_msecs ( HZ ) ) ;
if ( ret )
return ret ;
return sysfs_emit ( buf , " %u %u \n " , result . period , result . duty_cycle ) ;
}
static DEVICE_ATTR_RW ( period ) ;
static DEVICE_ATTR_RW ( duty_cycle ) ;
static DEVICE_ATTR_RW ( enable ) ;
static DEVICE_ATTR_RW ( polarity ) ;
static DEVICE_ATTR_RO ( capture ) ;
static struct attribute * pwm_attrs [ ] = {
& dev_attr_period . attr ,
& dev_attr_duty_cycle . attr ,
& dev_attr_enable . attr ,
& dev_attr_polarity . attr ,
& dev_attr_capture . attr ,
NULL
} ;
ATTRIBUTE_GROUPS ( pwm ) ;
static void pwm_export_release ( struct device * pwm_dev )
{
struct pwm_export * export = pwmexport_from_dev ( pwm_dev ) ;
kfree ( export ) ;
}
static int pwm_export_child ( struct device * pwmchip_dev , struct pwm_device * pwm )
{
struct pwm_export * export ;
char * pwm_prop [ 2 ] ;
int ret ;
if ( test_and_set_bit ( PWMF_EXPORTED , & pwm - > flags ) )
return - EBUSY ;
export = kzalloc ( sizeof ( * export ) , GFP_KERNEL ) ;
if ( ! export ) {
clear_bit ( PWMF_EXPORTED , & pwm - > flags ) ;
return - ENOMEM ;
}
export - > pwm = pwm ;
mutex_init ( & export - > lock ) ;
export - > pwm_dev . release = pwm_export_release ;
export - > pwm_dev . parent = pwmchip_dev ;
export - > pwm_dev . devt = MKDEV ( 0 , 0 ) ;
export - > pwm_dev . groups = pwm_groups ;
dev_set_name ( & export - > pwm_dev , " pwm%u " , pwm - > hwpwm ) ;
ret = device_register ( & export - > pwm_dev ) ;
if ( ret ) {
clear_bit ( PWMF_EXPORTED , & pwm - > flags ) ;
put_device ( & export - > pwm_dev ) ;
export = NULL ;
return ret ;
}
pwm_prop [ 0 ] = kasprintf ( GFP_KERNEL , " EXPORT=pwm%u " , pwm - > hwpwm ) ;
pwm_prop [ 1 ] = NULL ;
kobject_uevent_env ( & pwmchip_dev - > kobj , KOBJ_CHANGE , pwm_prop ) ;
kfree ( pwm_prop [ 0 ] ) ;
return 0 ;
}
static int pwm_unexport_match ( struct device * pwm_dev , void * data )
{
return pwm_from_dev ( pwm_dev ) = = data ;
}
static int pwm_unexport_child ( struct device * pwmchip_dev , struct pwm_device * pwm )
{
struct device * pwm_dev ;
char * pwm_prop [ 2 ] ;
if ( ! test_and_clear_bit ( PWMF_EXPORTED , & pwm - > flags ) )
return - ENODEV ;
pwm_dev = device_find_child ( pwmchip_dev , pwm , pwm_unexport_match ) ;
if ( ! pwm_dev )
return - ENODEV ;
pwm_prop [ 0 ] = kasprintf ( GFP_KERNEL , " UNEXPORT=pwm%u " , pwm - > hwpwm ) ;
pwm_prop [ 1 ] = NULL ;
kobject_uevent_env ( & pwmchip_dev - > kobj , KOBJ_CHANGE , pwm_prop ) ;
kfree ( pwm_prop [ 0 ] ) ;
/* for device_find_child() */
put_device ( pwm_dev ) ;
device_unregister ( pwm_dev ) ;
pwm_put ( pwm ) ;
return 0 ;
}
static ssize_t export_store ( struct device * pwmchip_dev ,
struct device_attribute * attr ,
const char * buf , size_t len )
{
struct pwm_chip * chip = pwmchip_from_dev ( pwmchip_dev ) ;
struct pwm_device * pwm ;
unsigned int hwpwm ;
int ret ;
ret = kstrtouint ( buf , 0 , & hwpwm ) ;
if ( ret < 0 )
return ret ;
if ( hwpwm > = chip - > npwm )
return - ENODEV ;
pwm = pwm_request_from_chip ( chip , hwpwm , " sysfs " ) ;
if ( IS_ERR ( pwm ) )
return PTR_ERR ( pwm ) ;
ret = pwm_export_child ( pwmchip_dev , pwm ) ;
if ( ret < 0 )
pwm_put ( pwm ) ;
return ret ? : len ;
}
static DEVICE_ATTR_WO ( export ) ;
static ssize_t unexport_store ( struct device * pwmchip_dev ,
struct device_attribute * attr ,
const char * buf , size_t len )
{
struct pwm_chip * chip = pwmchip_from_dev ( pwmchip_dev ) ;
unsigned int hwpwm ;
int ret ;
ret = kstrtouint ( buf , 0 , & hwpwm ) ;
if ( ret < 0 )
return ret ;
if ( hwpwm > = chip - > npwm )
return - ENODEV ;
ret = pwm_unexport_child ( pwmchip_dev , & chip - > pwms [ hwpwm ] ) ;
return ret ? : len ;
}
static DEVICE_ATTR_WO ( unexport ) ;
static ssize_t npwm_show ( struct device * pwmchip_dev , struct device_attribute * attr ,
char * buf )
{
const struct pwm_chip * chip = pwmchip_from_dev ( pwmchip_dev ) ;
return sysfs_emit ( buf , " %u \n " , chip - > npwm ) ;
}
static DEVICE_ATTR_RO ( npwm ) ;
static struct attribute * pwm_chip_attrs [ ] = {
& dev_attr_export . attr ,
& dev_attr_unexport . attr ,
& dev_attr_npwm . attr ,
NULL ,
} ;
ATTRIBUTE_GROUPS ( pwm_chip ) ;
/* takes export->lock on success */
static struct pwm_export * pwm_class_get_state ( struct device * pwmchip_dev ,
struct pwm_device * pwm ,
struct pwm_state * state )
{
struct device * pwm_dev ;
struct pwm_export * export ;
if ( ! test_bit ( PWMF_EXPORTED , & pwm - > flags ) )
return NULL ;
pwm_dev = device_find_child ( pwmchip_dev , pwm , pwm_unexport_match ) ;
if ( ! pwm_dev )
return NULL ;
export = pwmexport_from_dev ( pwm_dev ) ;
put_device ( pwm_dev ) ; /* for device_find_child() */
mutex_lock ( & export - > lock ) ;
pwm_get_state ( pwm , state ) ;
return export ;
}
static int pwm_class_apply_state ( struct pwm_export * export ,
struct pwm_device * pwm ,
struct pwm_state * state )
{
int ret = pwm_apply_might_sleep ( pwm , state ) ;
/* release lock taken in pwm_class_get_state */
mutex_unlock ( & export - > lock ) ;
return ret ;
}
static int pwm_class_resume_npwm ( struct device * pwmchip_dev , unsigned int npwm )
{
struct pwm_chip * chip = pwmchip_from_dev ( pwmchip_dev ) ;
unsigned int i ;
int ret = 0 ;
for ( i = 0 ; i < npwm ; i + + ) {
struct pwm_device * pwm = & chip - > pwms [ i ] ;
struct pwm_state state ;
struct pwm_export * export ;
export = pwm_class_get_state ( pwmchip_dev , pwm , & state ) ;
if ( ! export )
continue ;
/* If pwmchip was not enabled before suspend, do nothing. */
if ( ! export - > suspend . enabled ) {
/* release lock taken in pwm_class_get_state */
mutex_unlock ( & export - > lock ) ;
continue ;
}
state . enabled = export - > suspend . enabled ;
ret = pwm_class_apply_state ( export , pwm , & state ) ;
if ( ret < 0 )
break ;
}
return ret ;
}
static int pwm_class_suspend ( struct device * pwmchip_dev )
{
struct pwm_chip * chip = pwmchip_from_dev ( pwmchip_dev ) ;
unsigned int i ;
int ret = 0 ;
for ( i = 0 ; i < chip - > npwm ; i + + ) {
struct pwm_device * pwm = & chip - > pwms [ i ] ;
struct pwm_state state ;
struct pwm_export * export ;
export = pwm_class_get_state ( pwmchip_dev , pwm , & state ) ;
if ( ! export )
continue ;
/*
* If pwmchip was not enabled before suspend , save
* state for resume time and do nothing else .
*/
export - > suspend = state ;
if ( ! state . enabled ) {
/* release lock taken in pwm_class_get_state */
mutex_unlock ( & export - > lock ) ;
continue ;
}
state . enabled = false ;
ret = pwm_class_apply_state ( export , pwm , & state ) ;
if ( ret < 0 ) {
/*
* roll back the PWM devices that were disabled by
* this suspend function .
*/
pwm_class_resume_npwm ( pwmchip_dev , i ) ;
break ;
}
}
return ret ;
}
static int pwm_class_resume ( struct device * pwmchip_dev )
{
struct pwm_chip * chip = pwmchip_from_dev ( pwmchip_dev ) ;
return pwm_class_resume_npwm ( pwmchip_dev , chip - > npwm ) ;
}
static DEFINE_SIMPLE_DEV_PM_OPS ( pwm_class_pm_ops , pwm_class_suspend , pwm_class_resume ) ;
static struct class pwm_class = {
. name = " pwm " ,
. dev_groups = pwm_chip_groups ,
. pm = pm_sleep_ptr ( & pwm_class_pm_ops ) ,
} ;
static void pwmchip_sysfs_unexport ( struct pwm_chip * chip )
{
unsigned int i ;
for ( i = 0 ; i < chip - > npwm ; i + + ) {
struct pwm_device * pwm = & chip - > pwms [ i ] ;
if ( test_bit ( PWMF_EXPORTED , & pwm - > flags ) )
2024-03-17 11:40:36 +01:00
pwm_unexport_child ( & chip - > dev , pwm ) ;
2024-03-17 11:40:34 +01:00
}
}
2024-02-14 10:30:50 +01:00
# define PWMCHIP_ALIGN ARCH_DMA_MINALIGN
static void * pwmchip_priv ( struct pwm_chip * chip )
{
2024-03-17 11:40:35 +01:00
return ( void * ) chip + ALIGN ( struct_size ( chip , pwms , chip - > npwm ) , PWMCHIP_ALIGN ) ;
2024-02-14 10:30:50 +01:00
}
/* This is the counterpart to pwmchip_alloc() */
void pwmchip_put ( struct pwm_chip * chip )
{
2024-03-17 11:40:36 +01:00
put_device ( & chip - > dev ) ;
2024-02-14 10:30:50 +01:00
}
EXPORT_SYMBOL_GPL ( pwmchip_put ) ;
2024-03-17 11:40:36 +01:00
static void pwmchip_release ( struct device * pwmchip_dev )
{
struct pwm_chip * chip = pwmchip_from_dev ( pwmchip_dev ) ;
kfree ( chip ) ;
}
2024-02-14 10:30:50 +01:00
struct pwm_chip * pwmchip_alloc ( struct device * parent , unsigned int npwm , size_t sizeof_priv )
{
struct pwm_chip * chip ;
2024-03-17 11:40:36 +01:00
struct device * pwmchip_dev ;
2024-02-14 10:30:50 +01:00
size_t alloc_size ;
2024-03-17 11:40:35 +01:00
unsigned int i ;
2024-02-14 10:30:50 +01:00
2024-03-17 11:40:35 +01:00
alloc_size = size_add ( ALIGN ( struct_size ( chip , pwms , npwm ) , PWMCHIP_ALIGN ) ,
sizeof_priv ) ;
2024-02-14 10:30:50 +01:00
chip = kzalloc ( alloc_size , GFP_KERNEL ) ;
if ( ! chip )
return ERR_PTR ( - ENOMEM ) ;
chip - > npwm = npwm ;
2024-02-14 10:33:28 +01:00
chip - > uses_pwmchip_alloc = true ;
2024-02-14 10:30:50 +01:00
2024-03-17 11:40:36 +01:00
pwmchip_dev = & chip - > dev ;
device_initialize ( pwmchip_dev ) ;
pwmchip_dev - > class = & pwm_class ;
pwmchip_dev - > parent = parent ;
pwmchip_dev - > release = pwmchip_release ;
2024-02-14 10:30:50 +01:00
pwmchip_set_drvdata ( chip , pwmchip_priv ( chip ) ) ;
2024-03-17 11:40:35 +01:00
for ( i = 0 ; i < chip - > npwm ; i + + ) {
struct pwm_device * pwm = & chip - > pwms [ i ] ;
pwm - > chip = chip ;
pwm - > hwpwm = i ;
}
2024-02-14 10:30:50 +01:00
return chip ;
}
EXPORT_SYMBOL_GPL ( pwmchip_alloc ) ;
static void devm_pwmchip_put ( void * data )
{
struct pwm_chip * chip = data ;
pwmchip_put ( chip ) ;
}
struct pwm_chip * devm_pwmchip_alloc ( struct device * parent , unsigned int npwm , size_t sizeof_priv )
{
struct pwm_chip * chip ;
int ret ;
chip = pwmchip_alloc ( parent , npwm , sizeof_priv ) ;
if ( IS_ERR ( chip ) )
return chip ;
ret = devm_add_action_or_reset ( parent , devm_pwmchip_put , chip ) ;
if ( ret )
return ERR_PTR ( ret ) ;
return chip ;
}
EXPORT_SYMBOL_GPL ( devm_pwmchip_alloc ) ;
2024-01-25 13:08:23 +01:00
static void of_pwmchip_add ( struct pwm_chip * chip )
2023-12-19 16:30:27 +00:00
{
2024-02-14 10:30:48 +01:00
if ( ! pwmchip_parent ( chip ) | | ! pwmchip_parent ( chip ) - > of_node )
2024-01-25 13:08:23 +01:00
return ;
2023-12-19 16:30:27 +00:00
2024-01-25 13:08:23 +01:00
if ( ! chip - > of_xlate )
chip - > of_xlate = of_pwm_xlate_with_flags ;
2023-12-19 16:30:27 +00:00
2024-02-14 10:30:48 +01:00
of_node_get ( pwmchip_parent ( chip ) - > of_node ) ;
2024-01-25 13:08:23 +01:00
}
2023-12-19 16:30:27 +00:00
2024-01-25 13:08:23 +01:00
static void of_pwmchip_remove ( struct pwm_chip * chip )
{
2024-02-14 10:30:48 +01:00
if ( pwmchip_parent ( chip ) )
of_node_put ( pwmchip_parent ( chip ) - > of_node ) ;
2023-12-19 16:30:27 +00:00
}
2012-07-24 19:35:32 +05:30
2024-01-25 13:08:23 +01:00
static bool pwm_ops_check ( const struct pwm_chip * chip )
2023-12-19 16:30:27 +00:00
{
2024-01-25 13:08:23 +01:00
const struct pwm_ops * ops = chip - > ops ;
2023-12-19 16:30:27 +00:00
2024-01-25 13:08:23 +01:00
if ( ! ops - > apply )
return false ;
if ( IS_ENABLED ( CONFIG_PWM_DEBUG ) & & ! ops - > get_state )
2024-02-14 10:30:48 +01:00
dev_warn ( pwmchip_parent ( chip ) ,
2024-01-25 13:08:23 +01:00
" Please implement the .get_state() callback \n " ) ;
return true ;
2023-12-19 16:30:27 +00:00
}
2016-06-08 10:21:23 +01:00
/**
2024-01-25 13:08:23 +01:00
* __pwmchip_add ( ) - register a new PWM chip
* @ chip : the PWM chip to add
* @ owner : reference to the module providing the chip .
*
* Register a new PWM chip . @ owner is supposed to be THIS_MODULE , use the
* pwmchip_add wrapper to do this right .
2016-06-08 10:21:23 +01:00
*
* Returns : 0 on success or a negative error code on failure .
*/
2024-01-25 13:08:23 +01:00
int __pwmchip_add ( struct pwm_chip * chip , struct module * owner )
2016-06-08 10:21:23 +01:00
{
2024-01-25 13:08:23 +01:00
int ret ;
2016-06-08 10:21:23 +01:00
2024-02-14 10:30:48 +01:00
if ( ! chip | | ! pwmchip_parent ( chip ) | | ! chip - > ops | | ! chip - > npwm )
2016-06-08 10:21:23 +01:00
return - EINVAL ;
2024-02-14 10:33:28 +01:00
/*
* a struct pwm_chip must be allocated using ( devm_ ) pwmchip_alloc ,
* otherwise the embedded struct device might disappear too early
* resulting in memory corruption .
* Catch drivers that were not converted appropriately .
*/
if ( ! chip - > uses_pwmchip_alloc )
return - EINVAL ;
2024-01-25 13:08:23 +01:00
if ( ! pwm_ops_check ( chip ) )
return - EINVAL ;
chip - > owner = owner ;
2016-06-08 10:21:23 +01:00
mutex_lock ( & pwm_lock ) ;
2024-01-25 13:08:23 +01:00
ret = idr_alloc ( & pwm_chips , chip , 0 , 0 , GFP_KERNEL ) ;
2024-03-17 11:40:36 +01:00
if ( ret < 0 )
goto err_idr_alloc ;
2024-01-25 13:08:23 +01:00
chip - > id = ret ;
2024-03-17 11:40:36 +01:00
dev_set_name ( & chip - > dev , " pwmchip%u " , chip - > id ) ;
2016-06-08 10:21:23 +01:00
2024-01-25 13:08:23 +01:00
if ( IS_ENABLED ( CONFIG_OF ) )
of_pwmchip_add ( chip ) ;
2024-03-17 11:40:36 +01:00
ret = device_add ( & chip - > dev ) ;
if ( ret )
goto err_device_add ;
mutex_unlock ( & pwm_lock ) ;
2024-01-25 13:08:23 +01:00
return 0 ;
2024-03-17 11:40:36 +01:00
err_device_add :
if ( IS_ENABLED ( CONFIG_OF ) )
of_pwmchip_remove ( chip ) ;
idr_remove ( & pwm_chips , chip - > id ) ;
err_idr_alloc :
mutex_unlock ( & pwm_lock ) ;
return ret ;
2016-06-08 10:21:23 +01:00
}
2024-01-25 13:08:23 +01:00
EXPORT_SYMBOL_GPL ( __pwmchip_add ) ;
2016-06-08 10:21:23 +01:00
2011-01-28 09:40:40 +01:00
/**
2024-01-25 13:08:23 +01:00
* pwmchip_remove ( ) - remove a PWM chip
* @ chip : the PWM chip to remove
2015-07-27 11:58:32 +02:00
*
2024-01-25 13:08:23 +01:00
* Removes a PWM chip .
2011-01-28 09:40:40 +01:00
*/
2024-01-25 13:08:23 +01:00
void pwmchip_remove ( struct pwm_chip * chip )
2011-01-28 09:40:40 +01:00
{
2024-01-25 13:08:23 +01:00
pwmchip_sysfs_unexport ( chip ) ;
2015-10-16 17:40:58 -07:00
2024-01-25 13:08:23 +01:00
if ( IS_ENABLED ( CONFIG_OF ) )
of_pwmchip_remove ( chip ) ;
2015-10-16 17:40:58 -07:00
2024-01-25 13:08:23 +01:00
mutex_lock ( & pwm_lock ) ;
2011-01-28 09:40:40 +01:00
2024-01-25 13:08:23 +01:00
idr_remove ( & pwm_chips , chip - > id ) ;
2011-01-28 09:40:40 +01:00
2024-01-25 13:08:23 +01:00
mutex_unlock ( & pwm_lock ) ;
2024-03-17 11:40:36 +01:00
device_del ( & chip - > dev ) ;
2011-01-28 09:40:40 +01:00
}
2024-01-25 13:08:23 +01:00
EXPORT_SYMBOL_GPL ( pwmchip_remove ) ;
2012-03-26 09:31:48 +02:00
2024-01-25 13:08:23 +01:00
static void devm_pwmchip_remove ( void * data )
2011-12-14 11:10:32 +01:00
{
2024-01-25 13:08:23 +01:00
struct pwm_chip * chip = data ;
2011-12-14 11:10:32 +01:00
2024-01-25 13:08:23 +01:00
pwmchip_remove ( chip ) ;
}
2011-12-14 11:10:32 +01:00
2024-01-25 13:08:23 +01:00
int __devm_pwmchip_add ( struct device * dev , struct pwm_chip * chip , struct module * owner )
{
int ret ;
2011-12-14 11:10:32 +01:00
2024-01-25 13:08:23 +01:00
ret = __pwmchip_add ( chip , owner ) ;
if ( ret )
return ret ;
2011-12-14 11:10:32 +01:00
2024-01-25 13:08:23 +01:00
return devm_add_action_or_reset ( dev , devm_pwmchip_remove , chip ) ;
2011-12-14 11:10:32 +01:00
}
2024-01-25 13:08:23 +01:00
EXPORT_SYMBOL_GPL ( __devm_pwmchip_add ) ;
2011-12-14 11:10:32 +01:00
2019-04-18 11:37:47 +02:00
static struct device_link * pwm_device_link_add ( struct device * dev ,
struct pwm_device * pwm )
{
struct device_link * dl ;
if ( ! dev ) {
/*
* No device for the PWM consumer has been provided . It may
* impact the PM sequence ordering : the PWM supplier may get
* suspended before the consumer .
*/
2024-02-14 10:30:48 +01:00
dev_warn ( pwmchip_parent ( pwm - > chip ) ,
2019-04-18 11:37:47 +02:00
" No consumer device specified to create a link to \n " ) ;
return NULL ;
}
2024-02-14 10:30:48 +01:00
dl = device_link_add ( dev , pwmchip_parent ( pwm - > chip ) , DL_FLAG_AUTOREMOVE_CONSUMER ) ;
2019-04-18 11:37:47 +02:00
if ( ! dl ) {
dev_err ( dev , " failed to create device link to %s \n " ,
2024-02-14 10:30:48 +01:00
dev_name ( pwmchip_parent ( pwm - > chip ) ) ) ;
2019-04-18 11:37:47 +02:00
return ERR_PTR ( - EINVAL ) ;
}
return dl ;
}
2024-01-25 13:08:23 +01:00
static struct pwm_chip * fwnode_to_pwmchip ( struct fwnode_handle * fwnode )
{
struct pwm_chip * chip ;
unsigned long id , tmp ;
mutex_lock ( & pwm_lock ) ;
idr_for_each_entry_ul ( & pwm_chips , chip , tmp , id )
2024-02-14 10:30:48 +01:00
if ( pwmchip_parent ( chip ) & & device_match_fwnode ( pwmchip_parent ( chip ) , fwnode ) ) {
2024-01-25 13:08:23 +01:00
mutex_unlock ( & pwm_lock ) ;
return chip ;
}
mutex_unlock ( & pwm_lock ) ;
return ERR_PTR ( - EPROBE_DEFER ) ;
}
2011-12-14 11:10:32 +01:00
/**
2012-12-21 01:43:58 -08:00
* of_pwm_get ( ) - request a PWM via the PWM framework
2019-04-18 11:37:47 +02:00
* @ dev : device for PWM consumer
2011-12-14 11:10:32 +01: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 11:58:32 +02:00
*
* Returns : A pointer to the requested PWM device or an ERR_PTR ( ) - encoded
* error code on failure .
2011-12-14 11:10:32 +01:00
*/
2022-08-26 20:26:42 +03:00
static struct pwm_device * of_pwm_get ( struct device * dev , struct device_node * np ,
const char * con_id )
2011-12-14 11:10:32 +01:00
{
struct pwm_device * pwm = NULL ;
struct of_phandle_args args ;
2019-04-18 11:37:47 +02:00
struct device_link * dl ;
2023-07-14 22:56:14 +02:00
struct pwm_chip * chip ;
2011-12-14 11:10:32 +01:00
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 ) {
2017-01-29 22:54:05 +01:00
pr_err ( " %s(): can't parse \" pwms \" property \n " , __func__ ) ;
2011-12-14 11:10:32 +01:00
return ERR_PTR ( err ) ;
}
2023-07-14 22:56:14 +02:00
chip = fwnode_to_pwmchip ( of_fwnode_handle ( args . np ) ) ;
if ( IS_ERR ( chip ) ) {
if ( PTR_ERR ( chip ) ! = - EPROBE_DEFER )
2017-05-23 18:05:03 +02:00
pr_err ( " %s(): PWM chip not found \n " , __func__ ) ;
2023-07-14 22:56:14 +02:00
pwm = ERR_CAST ( chip ) ;
2011-12-14 11:10:32 +01:00
goto put ;
}
2023-07-14 22:56:14 +02:00
pwm = chip - > of_xlate ( chip , & args ) ;
2011-12-14 11:10:32 +01:00
if ( IS_ERR ( pwm ) )
goto put ;
2019-04-18 11:37:47 +02:00
dl = pwm_device_link_add ( dev , pwm ) ;
if ( IS_ERR ( dl ) ) {
/* of_xlate ended up calling pwm_request_from_chip() */
2023-04-12 13:56:36 +02:00
pwm_put ( pwm ) ;
2019-04-18 11:37:47 +02:00
pwm = ERR_CAST ( dl ) ;
goto put ;
}
2011-12-14 11:10:32 +01:00
/*
* 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 ;
}
2019-06-12 10:36:07 +02:00
/**
* acpi_pwm_get ( ) - request a PWM via parsing " pwms " property in ACPI
2021-06-07 15:24:56 +03:00
* @ fwnode : firmware node to get the " pwms " property from
2019-06-12 10:36:07 +02:00
*
* Returns the PWM device parsed from the fwnode and index specified in the
* " pwms " property or a negative error - code on failure .
* Values parsed from the device tree are stored in the returned PWM device
* object .
*
* This is analogous to of_pwm_get ( ) except con_id is not yet supported .
* ACPI entries must look like
* Package ( ) { " pwms " , Package ( )
* { < PWM device reference > , < PWM index > , < PWM period > [ , < PWM flags > ] } }
*
* Returns : A pointer to the requested PWM device or an ERR_PTR ( ) - encoded
* error code on failure .
*/
2021-06-07 15:24:56 +03:00
static struct pwm_device * acpi_pwm_get ( const struct fwnode_handle * fwnode )
2019-06-12 10:36:07 +02:00
{
2021-07-06 16:11:32 +01:00
struct pwm_device * pwm ;
2019-06-12 10:36:07 +02:00
struct fwnode_reference_args args ;
struct pwm_chip * chip ;
int ret ;
memset ( & args , 0 , sizeof ( args ) ) ;
ret = __acpi_node_get_property_reference ( fwnode , " pwms " , 0 , 3 , & args ) ;
if ( ret < 0 )
return ERR_PTR ( ret ) ;
if ( args . nargs < 2 )
return ERR_PTR ( - EPROTO ) ;
2021-06-07 15:24:55 +03:00
chip = fwnode_to_pwmchip ( args . fwnode ) ;
2019-06-12 10:36:07 +02:00
if ( IS_ERR ( chip ) )
return ERR_CAST ( chip ) ;
pwm = pwm_request_from_chip ( chip , args . args [ 0 ] , NULL ) ;
if ( IS_ERR ( pwm ) )
return pwm ;
pwm - > args . period = args . args [ 1 ] ;
pwm - > args . polarity = PWM_POLARITY_NORMAL ;
if ( args . nargs > 2 & & args . args [ 2 ] & PWM_POLARITY_INVERTED )
pwm - > args . polarity = PWM_POLARITY_INVERSED ;
return pwm ;
}
2024-01-25 13:08:23 +01:00
static DEFINE_MUTEX ( pwm_lookup_lock ) ;
static LIST_HEAD ( pwm_lookup_list ) ;
2012-03-26 08:42:48 +02:00
/**
* pwm_add_table ( ) - register PWM device consumers
* @ table : array of consumers to register
* @ num : number of consumers in table
*/
2015-03-12 22:01:31 +05:30
void pwm_add_table ( struct pwm_lookup * table , size_t num )
2012-03-26 08:42:48 +02: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 15:04:18 +05:30
/**
* 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 08:42:48 +02:00
/**
* pwm_get ( ) - look up and request a PWM device
* @ dev : device for PWM consumer
* @ con_id : consumer name
*
2011-12-14 11:10:32 +01: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 08:42:48 +02:00
*
* Once a PWM chip has been found the specified PWM device will be requested
* and is ready to be used .
2015-07-27 11:58:32 +02:00
*
* Returns : A pointer to the requested PWM device or an ERR_PTR ( ) - encoded
* error code on failure .
2012-03-26 08:42:48 +02:00
*/
struct pwm_device * pwm_get ( struct device * dev , const char * con_id )
{
2021-06-07 15:24:56 +03:00
const struct fwnode_handle * fwnode = dev ? dev_fwnode ( dev ) : NULL ;
2012-08-10 16:41:13 +05:30
const char * dev_id = dev ? dev_name ( dev ) : NULL ;
2017-01-22 17:14:07 +01:00
struct pwm_device * pwm ;
struct pwm_chip * chip ;
2019-04-18 11:37:47 +02:00
struct device_link * dl ;
2012-03-26 08:42:48 +02:00
unsigned int best = 0 ;
2014-08-28 11:03:14 +02:00
struct pwm_lookup * p , * chosen = NULL ;
2012-03-26 08:42:48 +02:00
unsigned int match ;
2017-01-22 17:14:08 +01:00
int err ;
2012-03-26 08:42:48 +02:00
2011-12-14 11:10:32 +01:00
/* look up via DT first */
2021-06-07 15:24:56 +03:00
if ( is_of_node ( fwnode ) )
return of_pwm_get ( dev , to_of_node ( fwnode ) , con_id ) ;
2011-12-14 11:10:32 +01:00
2019-06-12 10:36:07 +02:00
/* then lookup via ACPI */
2021-06-07 15:24:56 +03:00
if ( is_acpi_node ( fwnode ) ) {
pwm = acpi_pwm_get ( fwnode ) ;
2019-07-30 17:48:48 +02:00
if ( ! IS_ERR ( pwm ) | | PTR_ERR ( pwm ) ! = - ENOENT )
return pwm ;
}
2011-12-14 11:10:32 +01:00
2012-03-26 08:42:48 +02: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 11:03:14 +02:00
chosen = p ;
2012-03-26 08:42:48 +02:00
if ( match ! = 3 )
best = match ;
else
break ;
}
}
2017-01-22 17:14:07 +01:00
mutex_unlock ( & pwm_lookup_lock ) ;
if ( ! chosen )
return ERR_PTR ( - ENODEV ) ;
2014-05-19 22:42:32 +02:00
2014-08-28 11:03:14 +02:00
chip = pwmchip_find_by_name ( chosen - > provider ) ;
2017-01-22 17:14:08 +01:00
/*
* If the lookup entry specifies a module , load the module and retry
* the PWM chip lookup . This can be used to work around driver load
* ordering issues if driver ' s can ' t be made to properly support the
* deferred probe mechanism .
*/
if ( ! chip & & chosen - > module ) {
err = request_module ( chosen - > module ) ;
if ( err = = 0 )
chip = pwmchip_find_by_name ( chosen - > provider ) ;
}
2014-08-28 11:03:14 +02:00
if ( ! chip )
2017-01-22 17:14:07 +01:00
return ERR_PTR ( - EPROBE_DEFER ) ;
2014-05-19 22:42:32 +02:00
2014-08-28 11:03:14 +02:00
pwm = pwm_request_from_chip ( chip , chosen - > index , con_id ? : dev_id ) ;
if ( IS_ERR ( pwm ) )
2017-01-22 17:14:07 +01:00
return pwm ;
2012-03-26 08:42:48 +02:00
2019-04-18 11:37:47 +02:00
dl = pwm_device_link_add ( dev , pwm ) ;
if ( IS_ERR ( dl ) ) {
2023-04-12 13:56:36 +02:00
pwm_put ( pwm ) ;
2019-04-18 11:37:47 +02:00
return ERR_CAST ( dl ) ;
}
2016-05-17 14:27:25 +02:00
pwm - > args . period = chosen - > period ;
pwm - > args . polarity = chosen - > polarity ;
2012-03-26 08:42:48 +02:00
return pwm ;
}
EXPORT_SYMBOL_GPL ( pwm_get ) ;
/**
* pwm_put ( ) - release a PWM device
* @ pwm : PWM device
*/
void pwm_put ( struct pwm_device * pwm )
{
2024-03-29 11:07:56 +01:00
struct pwm_chip * chip ;
2024-03-17 11:40:36 +01:00
2012-03-26 08:42:48 +02:00
if ( ! pwm )
return ;
2024-03-29 11:07:56 +01:00
chip = pwm - > chip ;
2012-03-26 08:42:48 +02:00
mutex_lock ( & pwm_lock ) ;
if ( ! test_and_clear_bit ( PWMF_REQUESTED , & pwm - > flags ) ) {
2012-08-10 16:41:13 +05:30
pr_warn ( " PWM device already freed \n " ) ;
2012-03-26 08:42:48 +02:00
goto out ;
}
2024-03-17 11:40:36 +01:00
if ( chip - > ops - > free )
2012-03-26 08:42:48 +02:00
pwm - > chip - > ops - > free ( pwm - > chip , pwm ) ;
pwm - > label = NULL ;
2024-03-17 11:40:36 +01:00
put_device ( & chip - > dev ) ;
module_put ( chip - > owner ) ;
2012-03-26 08:42:48 +02:00
out :
mutex_unlock ( & pwm_lock ) ;
}
EXPORT_SYMBOL_GPL ( pwm_put ) ;
2021-06-07 15:24:58 +03:00
static void devm_pwm_release ( void * pwm )
2012-08-01 19:20:58 +09:00
{
2021-06-07 15:24:58 +03:00
pwm_put ( pwm ) ;
2012-08-01 19:20:58 +09:00
}
/**
* 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 11:58:32 +02:00
*
* Returns : A pointer to the requested PWM device or an ERR_PTR ( ) - encoded
* error code on failure .
2012-08-01 19:20:58 +09:00
*/
struct pwm_device * devm_pwm_get ( struct device * dev , const char * con_id )
{
2021-06-07 15:24:58 +03:00
struct pwm_device * pwm ;
int ret ;
2012-08-01 19:20:58 +09:00
pwm = pwm_get ( dev , con_id ) ;
2021-06-07 15:24:58 +03:00
if ( IS_ERR ( pwm ) )
return pwm ;
ret = devm_add_action_or_reset ( dev , devm_pwm_release , pwm ) ;
if ( ret )
return ERR_PTR ( ret ) ;
2012-08-01 19:20:58 +09:00
return pwm ;
}
EXPORT_SYMBOL_GPL ( devm_pwm_get ) ;
2019-06-12 10:36:07 +02:00
/**
* devm_fwnode_pwm_get ( ) - request a resource managed PWM from firmware node
* @ dev : device for PWM consumer
* @ fwnode : firmware node to get the PWM from
* @ con_id : consumer name
*
* Returns the PWM device parsed from the firmware node . See of_pwm_get ( ) and
* acpi_pwm_get ( ) for a detailed description .
*
* Returns : A pointer to the requested PWM device or an ERR_PTR ( ) - encoded
* error code on failure .
*/
struct pwm_device * devm_fwnode_pwm_get ( struct device * dev ,
struct fwnode_handle * fwnode ,
const char * con_id )
{
2021-06-07 15:24:58 +03:00
struct pwm_device * pwm = ERR_PTR ( - ENODEV ) ;
int ret ;
2019-06-12 10:36:07 +02:00
if ( is_of_node ( fwnode ) )
pwm = of_pwm_get ( dev , to_of_node ( fwnode ) , con_id ) ;
else if ( is_acpi_node ( fwnode ) )
pwm = acpi_pwm_get ( fwnode ) ;
2021-06-07 15:24:58 +03:00
if ( IS_ERR ( pwm ) )
return pwm ;
2019-06-12 10:36:07 +02:00
2021-06-07 15:24:58 +03:00
ret = devm_add_action_or_reset ( dev , devm_pwm_release , pwm ) ;
if ( ret )
return ERR_PTR ( ret ) ;
2019-06-12 10:36:07 +02:00
return pwm ;
}
EXPORT_SYMBOL_GPL ( devm_fwnode_pwm_get ) ;
2012-03-26 09:31:48 +02:00
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 21:17:43 +02:00
struct pwm_state state ;
pwm_get_state ( pwm , & state ) ;
2012-03-26 09:31:48 +02:00
seq_printf ( s , " pwm-%-3d (%-20.20s): " , i , pwm - > label ) ;
if ( test_bit ( PWMF_REQUESTED , & pwm - > flags ) )
2013-12-19 13:31:24 +09:00
seq_puts ( s , " requested " ) ;
2012-03-26 09:31:48 +02:00
2016-04-14 21:17:43 +02:00
if ( state . enabled )
2013-12-19 13:31:24 +09:00
seq_puts ( s , " enabled " ) ;
2012-03-26 09:31:48 +02:00
2020-06-02 15:31:16 -07:00
seq_printf ( s , " period: %llu ns " , state . period ) ;
seq_printf ( s , " duty: %llu ns " , state . duty_cycle ) ;
2016-04-14 21:17:44 +02:00
seq_printf ( s , " polarity: %s " ,
state . polarity ? " inverse " : " normal " ) ;
2021-05-07 15:18:42 +02:00
if ( state . usage_power )
seq_puts ( s , " usage_power " ) ;
2013-12-19 13:31:24 +09:00
seq_puts ( s , " \n " ) ;
2012-03-26 09:31:48 +02:00
}
}
static void * pwm_seq_start ( struct seq_file * s , loff_t * pos )
{
2023-11-14 12:20:12 +01:00
unsigned long id = * pos ;
void * ret ;
2012-03-26 09:31:48 +02:00
mutex_lock ( & pwm_lock ) ;
s - > private = " " ;
2023-11-14 12:20:12 +01:00
ret = idr_get_next_ul ( & pwm_chips , & id ) ;
* pos = id ;
return ret ;
2012-03-26 09:31:48 +02:00
}
static void * pwm_seq_next ( struct seq_file * s , void * v , loff_t * pos )
{
2023-11-14 12:20:12 +01:00
unsigned long id = * pos + 1 ;
void * ret ;
2012-03-26 09:31:48 +02:00
s - > private = " \n " ;
2023-11-14 12:20:12 +01:00
ret = idr_get_next_ul ( & pwm_chips , & id ) ;
* pos = id ;
return ret ;
2012-03-26 09:31:48 +02:00
}
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 )
{
2023-11-14 12:20:12 +01:00
struct pwm_chip * chip = v ;
2012-03-26 09:31:48 +02:00
2023-11-14 12:20:13 +01:00
seq_printf ( s , " %s%d: %s/%s, %d PWM device%s \n " ,
( char * ) s - > private , chip - > id ,
2024-02-14 10:30:48 +01:00
pwmchip_parent ( chip ) - > bus ? pwmchip_parent ( chip ) - > bus - > name : " no-bus " ,
dev_name ( pwmchip_parent ( chip ) ) , chip - > npwm ,
2012-03-26 09:31:48 +02:00
( chip - > npwm ! = 1 ) ? " s " : " " ) ;
2019-01-07 20:49:39 +01:00
pwm_dbg_show ( chip , s ) ;
2012-03-26 09:31:48 +02:00
return 0 ;
}
2020-09-16 10:50:28 +08:00
static const struct seq_operations pwm_debugfs_sops = {
2012-03-26 09:31:48 +02:00
. start = pwm_seq_start ,
. next = pwm_seq_next ,
. stop = pwm_seq_stop ,
. show = pwm_seq_show ,
} ;
2020-09-16 10:50:28 +08:00
DEFINE_SEQ_ATTRIBUTE ( pwm_debugfs ) ;
2012-03-26 09:31:48 +02:00
2024-03-17 11:40:34 +01:00
static int __init pwm_init ( void )
2012-03-26 09:31:48 +02:00
{
2024-03-17 11:40:34 +01:00
if ( IS_ENABLED ( CONFIG_DEBUG_FS ) )
debugfs_create_file ( " pwm " , 0444 , NULL , NULL , & pwm_debugfs_fops ) ;
2012-03-26 09:31:48 +02:00
2024-03-17 11:40:34 +01:00
return class_register ( & pwm_class ) ;
2012-03-26 09:31:48 +02:00
}
2024-03-17 11:40:34 +01:00
subsys_initcall ( pwm_init ) ;