2009-09-23 18:45:02 +04:00
/*
* arch / arm / mach - u300 / regulator . c
*
* Copyright ( C ) 2009 ST - Ericsson AB
* License terms : GNU General Public License ( GPL ) version 2
* Handle board - bound regulators and board power not related
* to any devices .
* Author : Linus Walleij < linus . walleij @ stericsson . com >
*/
# include <linux/device.h>
# include <linux/signal.h>
# include <linux/err.h>
2013-04-19 12:50:42 +04:00
# include <linux/of.h>
# include <linux/module.h>
# include <linux/platform_device.h>
# include <linux/regulator/machine.h>
2009-09-23 18:45:02 +04:00
# include <linux/regulator/consumer.h>
2013-06-13 23:21:31 +04:00
# include <linux/mfd/syscon.h>
# include <linux/regmap.h>
2013-05-02 18:56:15 +04:00
/* Power Management Control 16bit (R/W) */
# define U300_SYSCON_PMCR (0x50)
# define U300_SYSCON_PMCR_DCON_ENABLE (0x0002)
# define U300_SYSCON_PMCR_PWR_MGNT_ENABLE (0x0001)
2009-09-23 18:45:02 +04:00
/*
* Regulators that power the board and chip and which are
* not copuled to specific drivers are hogged in these
* instances .
*/
static struct regulator * main_power_15 ;
/*
* This function is used from pm . h to shut down the system by
* resetting all regulators in turn and then disable regulator
* LDO D ( main power ) .
*/
void u300_pm_poweroff ( void )
{
sigset_t old , all ;
sigfillset ( & all ) ;
if ( ! sigprocmask ( SIG_BLOCK , & all , & old ) ) {
/* Disable LDO D to shut down the system */
if ( main_power_15 )
regulator_disable ( main_power_15 ) ;
else
pr_err ( " regulator not available to shut down system \n " ) ;
( void ) sigprocmask ( SIG_SETMASK , & old , NULL ) ;
}
return ;
}
/*
* Hog the regulators needed to power up the board .
*/
2013-04-19 12:50:42 +04:00
static int __init __u300_init_boardpower ( struct platform_device * pdev )
2009-09-23 18:45:02 +04:00
{
2013-05-22 18:15:13 +04:00
struct device_node * np = pdev - > dev . of_node ;
struct device_node * syscon_np ;
2013-06-13 23:21:31 +04:00
struct regmap * regmap ;
2009-09-23 18:45:02 +04:00
int err ;
pr_info ( " U300: setting up board power \n " ) ;
2013-05-22 18:15:13 +04:00
syscon_np = of_parse_phandle ( np , " syscon " , 0 ) ;
if ( ! syscon_np ) {
pr_crit ( " U300: no syscon node \n " ) ;
return - ENODEV ;
}
2013-06-13 23:21:31 +04:00
regmap = syscon_node_to_regmap ( syscon_np ) ;
2013-07-04 17:51:31 +04:00
if ( IS_ERR ( regmap ) ) {
2013-06-13 23:21:31 +04:00
pr_crit ( " U300: could not locate syscon regmap \n " ) ;
2013-07-04 17:51:31 +04:00
return PTR_ERR ( regmap ) ;
2013-05-22 18:15:13 +04:00
}
2013-04-22 13:29:30 +04:00
main_power_15 = regulator_get ( & pdev - > dev , " vana15 " ) ;
2013-04-19 12:50:42 +04:00
2009-09-23 18:45:02 +04:00
if ( IS_ERR ( main_power_15 ) ) {
pr_err ( " could not get vana15 " ) ;
return PTR_ERR ( main_power_15 ) ;
}
err = regulator_enable ( main_power_15 ) ;
if ( err ) {
pr_err ( " could not enable vana15 \n " ) ;
return err ;
}
/*
* On U300 a special system controller register pulls up the DC
* until the vana15 ( LDO D ) regulator comes up . At this point , all
* regulators are set and we do not need power control via
* DC ON anymore . This function will likely be moved whenever
* the rest of the U300 power management is implemented .
*/
pr_info ( " U300: disable system controller pull-up \n " ) ;
2013-06-13 23:21:31 +04:00
regmap_update_bits ( regmap , U300_SYSCON_PMCR ,
U300_SYSCON_PMCR_DCON_ENABLE , 0 ) ;
2009-09-23 18:45:02 +04:00
/* Register globally exported PM poweroff hook */
pm_power_off = u300_pm_poweroff ;
return 0 ;
}
2013-04-19 12:50:42 +04:00
static int __init s365_board_probe ( struct platform_device * pdev )
{
return __u300_init_boardpower ( pdev ) ;
}
static const struct of_device_id s365_board_match [ ] = {
{ . compatible = " stericsson,s365 " } ,
{ } ,
} ;
static struct platform_driver s365_board_driver = {
. driver = {
. name = " s365-board " ,
. of_match_table = s365_board_match ,
} ,
} ;
2009-09-23 18:45:02 +04:00
/*
* So at module init time we hog the regulator !
*/
2013-04-19 12:50:42 +04:00
static int __init u300_init_boardpower ( void )
{
2013-04-22 13:29:30 +04:00
return platform_driver_probe ( & s365_board_driver ,
s365_board_probe ) ;
2013-04-19 12:50:42 +04:00
}
device_initcall ( u300_init_boardpower ) ;