2010-09-06 10:54:52 +04:00
/*
* Copyright ( C ) ST - Ericsson SA 2010
*
* Author : Arun R Murthy < arun . murthy @ stericsson . com >
* License terms : GNU General Public License ( GPL ) version 2
*/
# 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
/* backlight driver constants */
# define ENABLE_PWM 1
# define DISABLE_PWM 0
2012-08-31 13:46:24 +04:00
struct ab8500_pwm_chip {
struct pwm_chip chip ;
2010-09-06 10:54:52 +04:00
} ;
2012-08-31 13:46:24 +04:00
static int ab8500_pwm_config ( struct pwm_chip * chip , struct pwm_device * pwm ,
int duty_ns , int period_ns )
2010-09-06 10:54:52 +04:00
{
int ret = 0 ;
unsigned int higher_val , lower_val ;
u8 reg ;
/*
* get the first 8 bits that are be written to
* AB8500_PWM_OUT_CTRL1_REG [ 0 : 7 ]
*/
lower_val = duty_ns & 0x00FF ;
/*
* get bits [ 9 : 10 ] that are to be written to
* AB8500_PWM_OUT_CTRL2_REG [ 0 : 1 ]
*/
higher_val = ( ( duty_ns & 0x0300 ) > > 8 ) ;
2012-08-31 13:46:24 +04:00
reg = AB8500_PWM_OUT_CTRL1_REG + ( ( chip - > base - 1 ) * 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 ,
2010-09-06 10:54:52 +04:00
reg , ( u8 ) lower_val ) ;
if ( ret < 0 )
return ret ;
2012-08-31 13:46:24 +04:00
ret = abx500_set_register_interruptible ( chip - > dev , AB8500_MISC ,
2010-09-06 10:54:52 +04:00
( reg + 1 ) , ( u8 ) higher_val ) ;
return ret ;
}
2012-08-31 13:46:24 +04:00
static int ab8500_pwm_enable ( struct pwm_chip * chip , struct pwm_device * pwm )
2010-09-06 10:54:52 +04:00
{
int ret ;
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 ,
2012-08-31 13:46:24 +04:00
1 < < ( chip - > base - 1 ) , ENABLE_PWM ) ;
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 ) ;
return ret ;
}
2012-08-31 13:46:24 +04:00
static void ab8500_pwm_disable ( struct pwm_chip * chip , struct pwm_device * pwm )
2010-09-06 10:54:52 +04:00
{
int ret ;
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 ,
2012-08-31 13:46:24 +04:00
1 < < ( chip - > base - 1 ) , DISABLE_PWM ) ;
2010-09-06 10:54:52 +04:00
if ( ret < 0 )
2012-08-31 13:46:24 +04:00
dev_err ( chip - > dev , " %s: Failed to disable PWM, Error %d \n " ,
2010-09-06 10:54:52 +04:00
pwm - > label , ret ) ;
return ;
}
2012-08-31 13:46:24 +04:00
static const struct pwm_ops ab8500_pwm_ops = {
. config = ab8500_pwm_config ,
. enable = ab8500_pwm_enable ,
. disable = ab8500_pwm_disable ,
2013-03-31 07:14:02 +04:00
. owner = THIS_MODULE ,
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 ;
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 ) ;
2012-08-31 13:46:24 +04:00
if ( ab8500 = = NULL ) {
2010-09-06 10:54:52 +04:00
dev_err ( & pdev - > dev , " failed to allocate memory \n " ) ;
return - ENOMEM ;
}
2012-08-31 13:46:24 +04:00
ab8500 - > chip . dev = & pdev - > dev ;
ab8500 - > chip . ops = & ab8500_pwm_ops ;
ab8500 - > chip . base = pdev - > id ;
ab8500 - > chip . npwm = 1 ;
err = pwmchip_add ( & ab8500 - > chip ) ;
2013-03-08 07:45:58 +04:00
if ( err < 0 )
2012-08-31 13:46:24 +04:00
return err ;
dev_dbg ( & pdev - > dev , " pwm probe successful \n " ) ;
platform_set_drvdata ( pdev , ab8500 ) ;
2010-09-06 10:54:52 +04:00
return 0 ;
}
2012-11-19 22:26:09 +04:00
static int ab8500_pwm_remove ( 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 = platform_get_drvdata ( pdev ) ;
int err ;
err = pwmchip_remove ( & ab8500 - > chip ) ;
if ( err < 0 )
return err ;
2010-09-06 10:54:52 +04:00
dev_dbg ( & pdev - > dev , " pwm driver removed \n " ) ;
2012-08-31 13:46:24 +04:00
2010-09-06 10:54:52 +04:00
return 0 ;
}
static struct platform_driver ab8500_pwm_driver = {
. driver = {
. name = " ab8500-pwm " ,
. owner = THIS_MODULE ,
} ,
. probe = ab8500_pwm_probe ,
2012-11-19 22:21:28 +04:00
. remove = ab8500_pwm_remove ,
2010-09-06 10:54:52 +04:00
} ;
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 " ) ;