2011-02-14 13:17:12 +03:00
/*
* Copyright ( C ) ST - Ericsson SA 2010
* Author : Mattias Nilsson < mattias . i . nilsson @ stericsson . com > for ST Ericsson .
* License terms : GNU General Public License ( GPL ) version 2
*/
# include <linux/err.h>
2011-07-03 23:13:27 +04:00
# include <linux/module.h>
2011-02-14 13:17:12 +03:00
# include <linux/platform_device.h>
2013-01-14 17:26:15 +04:00
# include <linux/pm.h>
# include <linux/signal.h>
2011-02-14 13:17:12 +03:00
# include <linux/mfd/abx500.h>
2011-12-02 17:16:33 +04:00
# include <linux/mfd/abx500/ab8500.h>
# include <linux/mfd/abx500/ab8500-sysctrl.h>
2011-02-14 13:17:12 +03:00
static struct device * sysctrl_dev ;
2013-01-14 17:26:15 +04:00
void ab8500_power_off ( void )
{
sigset_t old ;
sigset_t all ;
sigfillset ( & all ) ;
if ( ! sigprocmask ( SIG_BLOCK , & all , & old ) ) {
( void ) ab8500_sysctrl_set ( AB8500_STW4500CTRL1 ,
AB8500_STW4500CTRL1_SWOFF |
AB8500_STW4500CTRL1_SWRESET4500N ) ;
( void ) sigprocmask ( SIG_SETMASK , & old , NULL ) ;
}
}
2011-02-14 13:17:12 +03:00
static inline bool valid_bank ( u8 bank )
{
return ( ( bank = = AB8500_SYS_CTRL1_BLOCK ) | |
( bank = = AB8500_SYS_CTRL2_BLOCK ) ) ;
}
int ab8500_sysctrl_read ( u16 reg , u8 * value )
{
u8 bank ;
if ( sysctrl_dev = = NULL )
return - EAGAIN ;
bank = ( reg > > 8 ) ;
if ( ! valid_bank ( bank ) )
return - EINVAL ;
return abx500_get_register_interruptible ( sysctrl_dev , bank ,
( u8 ) ( reg & 0xFF ) , value ) ;
}
int ab8500_sysctrl_write ( u16 reg , u8 mask , u8 value )
{
u8 bank ;
if ( sysctrl_dev = = NULL )
return - EAGAIN ;
bank = ( reg > > 8 ) ;
if ( ! valid_bank ( bank ) )
return - EINVAL ;
return abx500_mask_and_set_register_interruptible ( sysctrl_dev , bank ,
( u8 ) ( reg & 0xFF ) , mask , value ) ;
}
2012-11-19 22:23:04 +04:00
static int ab8500_sysctrl_probe ( struct platform_device * pdev )
2011-02-14 13:17:12 +03:00
{
2013-01-14 17:26:15 +04:00
struct ab8500_platform_data * plat ;
2011-02-14 13:17:12 +03:00
sysctrl_dev = & pdev - > dev ;
2013-01-14 17:26:15 +04:00
plat = dev_get_platdata ( pdev - > dev . parent ) ;
if ( plat - > pm_power_off )
pm_power_off = ab8500_power_off ;
2011-02-14 13:17:12 +03:00
return 0 ;
}
2012-11-19 22:26:01 +04:00
static int ab8500_sysctrl_remove ( struct platform_device * pdev )
2011-02-14 13:17:12 +03:00
{
sysctrl_dev = NULL ;
return 0 ;
}
static struct platform_driver ab8500_sysctrl_driver = {
. driver = {
. name = " ab8500-sysctrl " ,
. owner = THIS_MODULE ,
} ,
. probe = ab8500_sysctrl_probe ,
2012-11-19 22:20:24 +04:00
. remove = ab8500_sysctrl_remove ,
2011-02-14 13:17:12 +03:00
} ;
static int __init ab8500_sysctrl_init ( void )
{
return platform_driver_register ( & ab8500_sysctrl_driver ) ;
}
subsys_initcall ( ab8500_sysctrl_init ) ;
MODULE_AUTHOR ( " Mattias Nilsson <mattias.i.nilsson@stericsson.com " ) ;
MODULE_DESCRIPTION ( " AB8500 system control driver " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;