2019-05-28 19:57:21 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2010-09-06 10:54:52 +04:00
/*
* Copyright ( C ) ST - Ericsson SA 2010
*
* Author : Arun R Murthy < arun . murthy @ stericsson . com >
2023-01-18 18:48:16 +03:00
* Datasheet : https : //web.archive.org/web/20130614115108/http://www.stericsson.com/developers/CD00291561_UM1031_AB8500_user_manual-rev5_CTDS_public.pdf
2010-09-06 10:54:52 +04:00
*/
# include <linux/err.h>
# include <linux/platform_device.h>
# include <linux/slab.h>
# include <linux/pwm.h>
# include <linux/mfd/abx500.h>
2011-12-02 17:16:33 +04:00
# include <linux/mfd/abx500/ab8500.h>
2011-07-03 23:14:56 +04:00
# include <linux/module.h>
2010-09-06 10:54:52 +04:00
/*
* PWM Out generators
* Bank : 0x10
*/
# define AB8500_PWM_OUT_CTRL1_REG 0x60
# define AB8500_PWM_OUT_CTRL2_REG 0x61
# define AB8500_PWM_OUT_CTRL7_REG 0x66
2023-01-18 18:48:16 +03:00
# define AB8500_PWM_CLKRATE 9600000
2012-08-31 13:46:24 +04:00
struct ab8500_pwm_chip {
struct pwm_chip chip ;
2021-07-05 19:55:10 +03:00
unsigned int hwid ;
2010-09-06 10:54:52 +04:00
} ;
2021-07-05 19:55:10 +03:00
static struct ab8500_pwm_chip * ab8500_pwm_from_chip ( struct pwm_chip * chip )
{
return container_of ( chip , struct ab8500_pwm_chip , chip ) ;
}
2021-03-01 21:45:37 +03:00
static int ab8500_pwm_apply ( struct pwm_chip * chip , struct pwm_device * pwm ,
const struct pwm_state * state )
2010-09-06 10:54:52 +04:00
{
2021-03-01 21:45:37 +03:00
int ret ;
2010-09-06 10:54:52 +04:00
u8 reg ;
2023-01-18 18:48:16 +03:00
u8 higher_val , lower_val ;
unsigned int duty_steps , div ;
2021-07-05 19:55:10 +03:00
struct ab8500_pwm_chip * ab8500 = ab8500_pwm_from_chip ( chip ) ;
2021-03-01 21:45:37 +03:00
if ( state - > polarity ! = PWM_POLARITY_NORMAL )
return - EINVAL ;
2023-01-18 18:48:16 +03:00
if ( state - > enabled ) {
/*
* A time quantum is
* q = ( 32 - FreqPWMOutx [ 3 : 0 ] ) / AB8500_PWM_CLKRATE
* The period is always 1024 q , duty_cycle is between 1 q and 1024 q .
*
* FreqPWMOutx [ 3 : 0 ] | output frequency | output frequency | 1024 q = period
* | ( from manual ) | ( 1 / 1024 q ) | = 1 / freq
* - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - -
* b0000 | 293 Hz | 292.968750 Hz | 3413333.33 ns
* b0001 | 302 Hz | 302.419355 Hz | 3306666.66 ns
* b0010 | 312 Hz | 312.500000 Hz | 3200000 ns
* b0011 | 323 Hz | 323.275862 Hz | 3093333.33 ns
* b0100 | 334 Hz | 334.821429 Hz | 2986666.66 ns
* b0101 | 347 Hz | 347.222222 Hz | 2880000 ns
* b0110 | 360 Hz | 360.576923 Hz | 2773333.33 ns
* b0111 | 375 Hz | 375.000000 Hz | 2666666.66 ns
* b1000 | 390 Hz | 390.625000 Hz | 2560000 ns
* b1001 | 407 Hz | 407.608696 Hz | 2453333.33 ns
* b1010 | 426 Hz | 426.136364 Hz | 2346666.66 ns
* b1011 | 446 Hz | 446.428571 Hz | 2240000 ns
* b1100 | 468 Hz | 468.750000 Hz | 2133333.33 ns
* b1101 | 493 Hz | 493.421053 Hz | 2026666.66 ns
* b1110 | 520 Hz | 520.833333 Hz | 1920000 ns
* b1111 | 551 Hz | 551.470588 Hz | 1813333.33 ns
*
*
* AB8500_PWM_CLKRATE is a multiple of 1024 , so the division by
* 1024 can be done in this factor without loss of precision .
*/
div = min_t ( u64 , mul_u64_u64_div_u64 ( state - > period ,
AB8500_PWM_CLKRATE > > 10 ,
NSEC_PER_SEC ) , 32 ) ; /* 32 - FreqPWMOutx[3:0] */
if ( div < = 16 )
/* requested period < 3413333.33 */
return - EINVAL ;
duty_steps = max_t ( u64 , mul_u64_u64_div_u64 ( state - > duty_cycle ,
AB8500_PWM_CLKRATE ,
( u64 ) NSEC_PER_SEC * div ) , 1024 ) ;
}
/*
* The hardware doesn ' t support duty_steps = 0 explicitly , but emits low
* when disabled .
*/
if ( ! state - > enabled | | duty_steps = = 0 ) {
2021-03-01 21:45:37 +03:00
ret = abx500_mask_and_set_register_interruptible ( chip - > dev ,
AB8500_MISC , AB8500_PWM_OUT_CTRL7_REG ,
2021-07-05 19:55:10 +03:00
1 < < ab8500 - > hwid , 0 ) ;
2021-03-01 21:45:37 +03:00
if ( ret < 0 )
dev_err ( chip - > dev , " %s: Failed to disable PWM, Error %d \n " ,
pwm - > label , ret ) ;
return ret ;
}
2010-09-06 10:54:52 +04:00
/*
2023-01-18 18:48:16 +03:00
* The lower 8 bits of duty_steps is written to . . .
2010-09-06 10:54:52 +04:00
* AB8500_PWM_OUT_CTRL1_REG [ 0 : 7 ]
*/
2023-01-18 18:48:16 +03:00
lower_val = ( duty_steps - 1 ) & 0x00ff ;
2010-09-06 10:54:52 +04:00
/*
2023-01-18 18:48:16 +03:00
* The two remaining high bits to
* AB8500_PWM_OUT_CTRL2_REG [ 0 : 1 ] ; together with FreqPWMOutx .
2010-09-06 10:54:52 +04:00
*/
2023-01-18 18:48:16 +03:00
higher_val = ( ( duty_steps - 1 ) & 0x0300 ) > > 8 | ( 32 - div ) < < 4 ;
2010-09-06 10:54:52 +04:00
2021-07-05 19:55:10 +03:00
reg = AB8500_PWM_OUT_CTRL1_REG + ( ab8500 - > hwid * 2 ) ;
2010-09-06 10:54:52 +04:00
2012-08-31 13:46:24 +04:00
ret = abx500_set_register_interruptible ( chip - > dev , AB8500_MISC ,
2023-01-18 18:48:16 +03:00
reg , lower_val ) ;
2010-09-06 10:54:52 +04:00
if ( ret < 0 )
return ret ;
2021-03-01 21:45:37 +03:00
2012-08-31 13:46:24 +04:00
ret = abx500_set_register_interruptible ( chip - > dev , AB8500_MISC ,
2023-01-18 18:48:16 +03:00
( reg + 1 ) , higher_val ) ;
2021-03-01 21:45:37 +03:00
if ( ret < 0 )
return ret ;
2010-09-06 10:54:52 +04:00
2023-01-18 18:48:16 +03:00
/* enable */
2012-08-31 13:46:24 +04:00
ret = abx500_mask_and_set_register_interruptible ( chip - > dev ,
2010-09-06 10:54:52 +04:00
AB8500_MISC , AB8500_PWM_OUT_CTRL7_REG ,
2021-07-05 19:55:10 +03:00
1 < < ab8500 - > hwid , 1 < < ab8500 - > hwid ) ;
2010-09-06 10:54:52 +04:00
if ( ret < 0 )
2013-03-26 18:34:50 +04:00
dev_err ( chip - > dev , " %s: Failed to enable PWM, Error %d \n " ,
2010-09-06 10:54:52 +04:00
pwm - > label , ret ) ;
2021-03-01 21:45:37 +03:00
return ret ;
2010-09-06 10:54:52 +04:00
}
2023-01-18 18:48:17 +03:00
static int ab8500_pwm_get_state ( struct pwm_chip * chip , struct pwm_device * pwm ,
struct pwm_state * state )
{
u8 ctrl7 , lower_val , higher_val ;
int ret ;
struct ab8500_pwm_chip * ab8500 = ab8500_pwm_from_chip ( chip ) ;
unsigned int div , duty_steps ;
ret = abx500_get_register_interruptible ( chip - > dev , AB8500_MISC ,
AB8500_PWM_OUT_CTRL7_REG ,
& ctrl7 ) ;
if ( ret )
return ret ;
state - > polarity = PWM_POLARITY_NORMAL ;
if ( ! ( ctrl7 & 1 < < ab8500 - > hwid ) ) {
state - > enabled = false ;
return 0 ;
}
ret = abx500_get_register_interruptible ( chip - > dev , AB8500_MISC ,
AB8500_PWM_OUT_CTRL1_REG + ( ab8500 - > hwid * 2 ) ,
& lower_val ) ;
if ( ret )
return ret ;
ret = abx500_get_register_interruptible ( chip - > dev , AB8500_MISC ,
AB8500_PWM_OUT_CTRL2_REG + ( ab8500 - > hwid * 2 ) ,
& higher_val ) ;
if ( ret )
return ret ;
div = 32 - ( ( higher_val & 0xf0 ) > > 4 ) ;
duty_steps = ( ( higher_val & 3 ) < < 8 | lower_val ) + 1 ;
state - > period = DIV64_U64_ROUND_UP ( ( u64 ) div < < 10 , AB8500_PWM_CLKRATE ) ;
state - > duty_cycle = DIV64_U64_ROUND_UP ( ( u64 ) div * duty_steps , AB8500_PWM_CLKRATE ) ;
return 0 ;
}
2012-08-31 13:46:24 +04:00
static const struct pwm_ops ab8500_pwm_ops = {
2021-03-01 21:45:37 +03:00
. apply = ab8500_pwm_apply ,
2023-01-18 18:48:17 +03:00
. get_state = ab8500_pwm_get_state ,
2012-08-31 13:46:24 +04:00
} ;
2010-09-06 10:54:52 +04:00
2012-11-19 22:23:14 +04:00
static int ab8500_pwm_probe ( struct platform_device * pdev )
2010-09-06 10:54:52 +04:00
{
2012-08-31 13:46:24 +04:00
struct ab8500_pwm_chip * ab8500 ;
int err ;
2021-07-05 19:55:10 +03:00
if ( pdev - > id < 1 | | pdev - > id > 31 )
2023-05-22 14:07:42 +03:00
return dev_err_probe ( & pdev - > dev , - EINVAL , " Invalid device id %d \n " , pdev - > id ) ;
2021-07-05 19:55:10 +03:00
2010-09-06 10:54:52 +04:00
/*
* Nothing to be done in probe , this is required to get the
* device which is required for ab8500 read and write
*/
2013-03-08 07:45:58 +04:00
ab8500 = devm_kzalloc ( & pdev - > dev , sizeof ( * ab8500 ) , GFP_KERNEL ) ;
2014-04-23 13:39:26 +04:00
if ( ab8500 = = NULL )
2010-09-06 10:54:52 +04:00
return - ENOMEM ;
2012-08-31 13:46:24 +04:00
ab8500 - > chip . dev = & pdev - > dev ;
ab8500 - > chip . ops = & ab8500_pwm_ops ;
ab8500 - > chip . npwm = 1 ;
2021-07-05 19:55:10 +03:00
ab8500 - > hwid = pdev - > id - 1 ;
2012-08-31 13:46:24 +04:00
2021-07-07 19:28:00 +03:00
err = devm_pwmchip_add ( & pdev - > dev , & ab8500 - > chip ) ;
2013-03-08 07:45:58 +04:00
if ( err < 0 )
2020-08-12 10:52:14 +03:00
return dev_err_probe ( & pdev - > dev , err , " Failed to add pwm chip \n " ) ;
2012-08-31 13:46:24 +04:00
dev_dbg ( & pdev - > dev , " pwm probe successful \n " ) ;
2010-09-06 10:54:52 +04:00
return 0 ;
}
static struct platform_driver ab8500_pwm_driver = {
. driver = {
. name = " ab8500-pwm " ,
} ,
. probe = ab8500_pwm_probe ,
} ;
2012-08-31 13:46:24 +04:00
module_platform_driver ( ab8500_pwm_driver ) ;
2010-09-06 10:54:52 +04:00
MODULE_AUTHOR ( " Arun MURTHY <arun.murthy@stericsson.com> " ) ;
MODULE_DESCRIPTION ( " AB8500 Pulse Width Modulation Driver " ) ;
2011-08-26 02:59:20 +04:00
MODULE_ALIAS ( " platform:ab8500-pwm " ) ;
2010-09-06 10:54:52 +04:00
MODULE_LICENSE ( " GPL v2 " ) ;