2012-01-13 19:30:31 +04:00
/*
* Copyright ( C ) ST - Ericsson SA 2010
*
* License Terms : GNU General Public License v2
* Authors : Sundar Iyer < sundar . iyer @ stericsson . com > for ST - Ericsson
* Bengt Jonsson < bengt . g . jonsson @ stericsson . com > for ST - Ericsson
*
* UX500 common part of Power domain regulators
*/
# include <linux/kernel.h>
# include <linux/err.h>
# include <linux/regulator/driver.h>
# include <linux/debugfs.h>
# include <linux/seq_file.h>
# include <linux/slab.h>
2013-01-24 19:29:26 +04:00
# include <linux/module.h>
2012-01-13 19:30:31 +04:00
# include "dbx500-prcmu.h"
/*
* power state reference count
*/
static int power_state_active_cnt ; /* will initialize to zero */
static DEFINE_SPINLOCK ( power_state_active_lock ) ;
void power_state_active_enable ( void )
{
unsigned long flags ;
spin_lock_irqsave ( & power_state_active_lock , flags ) ;
power_state_active_cnt + + ;
spin_unlock_irqrestore ( & power_state_active_lock , flags ) ;
}
int power_state_active_disable ( void )
{
int ret = 0 ;
unsigned long flags ;
spin_lock_irqsave ( & power_state_active_lock , flags ) ;
if ( power_state_active_cnt < = 0 ) {
pr_err ( " power state: unbalanced enable/disable calls \n " ) ;
ret = - EINVAL ;
goto out ;
}
power_state_active_cnt - - ;
out :
spin_unlock_irqrestore ( & power_state_active_lock , flags ) ;
return ret ;
}
# ifdef CONFIG_REGULATOR_DEBUG
2013-05-08 15:05:10 +04:00
static int power_state_active_get ( void )
{
unsigned long flags ;
int cnt ;
spin_lock_irqsave ( & power_state_active_lock , flags ) ;
cnt = power_state_active_cnt ;
spin_unlock_irqrestore ( & power_state_active_lock , flags ) ;
return cnt ;
}
2012-01-13 19:30:31 +04:00
static struct ux500_regulator_debug {
struct dentry * dir ;
struct dentry * status_file ;
struct dentry * power_state_cnt_file ;
struct dbx500_regulator_info * regulator_array ;
int num_regulators ;
u8 * state_before_suspend ;
u8 * state_after_suspend ;
} rdebug ;
2018-12-15 11:21:48 +03:00
static int ux500_regulator_power_state_cnt_show ( struct seq_file * s , void * p )
2012-01-13 19:30:31 +04:00
{
/* print power state count */
2015-02-22 05:53:54 +03:00
seq_printf ( s , " ux500-regulator power state count: %i \n " ,
power_state_active_get ( ) ) ;
2012-01-13 19:30:31 +04:00
return 0 ;
}
2018-12-15 11:21:48 +03:00
DEFINE_SHOW_ATTRIBUTE ( ux500_regulator_power_state_cnt ) ;
2012-01-13 19:30:31 +04:00
2018-12-15 11:21:48 +03:00
static int ux500_regulator_status_show ( struct seq_file * s , void * p )
2012-01-13 19:30:31 +04:00
{
int i ;
/* print dump header */
2015-02-22 05:53:54 +03:00
seq_puts ( s , " ux500-regulator status: \n " ) ;
seq_printf ( s , " %31s : %8s : %8s \n " , " current " , " before " , " after " ) ;
2012-01-13 19:30:31 +04:00
for ( i = 0 ; i < rdebug . num_regulators ; i + + ) {
struct dbx500_regulator_info * info ;
/* Access per-regulator data */
info = & rdebug . regulator_array [ i ] ;
/* print status */
2015-02-22 05:53:54 +03:00
seq_printf ( s , " %20s : %8s : %8s : %8s \n " ,
info - > desc . name ,
info - > is_enabled ? " enabled " : " disabled " ,
rdebug . state_before_suspend [ i ] ? " enabled " : " disabled " ,
rdebug . state_after_suspend [ i ] ? " enabled " : " disabled " ) ;
2012-01-13 19:30:31 +04:00
}
return 0 ;
}
2018-12-15 11:21:48 +03:00
DEFINE_SHOW_ATTRIBUTE ( ux500_regulator_status ) ;
2012-01-13 19:30:31 +04:00
int __attribute__ ( ( weak ) ) dbx500_regulator_testcase (
struct dbx500_regulator_info * regulator_info ,
int num_regulators )
{
return 0 ;
}
2012-11-19 22:22:22 +04:00
int
2012-01-13 19:30:31 +04:00
ux500_regulator_debug_init ( struct platform_device * pdev ,
struct dbx500_regulator_info * regulator_info ,
int num_regulators )
{
/* create directory */
rdebug . dir = debugfs_create_dir ( " ux500-regulator " , NULL ) ;
if ( ! rdebug . dir )
goto exit_no_debugfs ;
/* create "status" file */
rdebug . status_file = debugfs_create_file ( " status " ,
S_IRUGO , rdebug . dir , & pdev - > dev ,
& ux500_regulator_status_fops ) ;
if ( ! rdebug . status_file )
goto exit_destroy_dir ;
/* create "power-state-count" file */
rdebug . power_state_cnt_file = debugfs_create_file ( " power-state-count " ,
S_IRUGO , rdebug . dir , & pdev - > dev ,
& ux500_regulator_power_state_cnt_fops ) ;
if ( ! rdebug . power_state_cnt_file )
goto exit_destroy_status ;
rdebug . regulator_array = regulator_info ;
rdebug . num_regulators = num_regulators ;
rdebug . state_before_suspend = kzalloc ( num_regulators , GFP_KERNEL ) ;
2014-02-20 12:53:03 +04:00
if ( ! rdebug . state_before_suspend )
2012-01-13 19:30:31 +04:00
goto exit_destroy_power_state ;
rdebug . state_after_suspend = kzalloc ( num_regulators , GFP_KERNEL ) ;
2014-02-20 12:53:03 +04:00
if ( ! rdebug . state_after_suspend )
2012-01-13 19:30:31 +04:00
goto exit_free ;
dbx500_regulator_testcase ( regulator_info , num_regulators ) ;
return 0 ;
exit_free :
kfree ( rdebug . state_before_suspend ) ;
exit_destroy_power_state :
debugfs_remove ( rdebug . power_state_cnt_file ) ;
exit_destroy_status :
debugfs_remove ( rdebug . status_file ) ;
exit_destroy_dir :
debugfs_remove ( rdebug . dir ) ;
exit_no_debugfs :
dev_err ( & pdev - > dev , " failed to create debugfs entries. \n " ) ;
return - ENOMEM ;
}
2012-11-19 22:26:10 +04:00
int ux500_regulator_debug_exit ( void )
2012-01-13 19:30:31 +04:00
{
debugfs_remove_recursive ( rdebug . dir ) ;
kfree ( rdebug . state_after_suspend ) ;
kfree ( rdebug . state_before_suspend ) ;
return 0 ;
}
# endif