2009-07-01 17:58:37 -07:00
/* arch/arm/mach-msm/smd_debug.c
*
* Copyright ( C ) 2007 Google , Inc .
* Author : Brian Swetland < swetland @ google . com >
*
* This software is licensed under the terms of the GNU General Public
* License version 2 , as published by the Free Software Foundation , and
* may be copied , distributed , and modified under those terms .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
*/
# include <linux/debugfs.h>
# include <linux/list.h>
# include <mach/msm_iomap.h>
# include "smd_private.h"
# if defined(CONFIG_DEBUG_FS)
static char * chstate ( unsigned n )
{
switch ( n ) {
case SMD_SS_CLOSED :
return " CLOSED " ;
case SMD_SS_OPENING :
return " OPENING " ;
case SMD_SS_OPENED :
return " OPENED " ;
case SMD_SS_FLUSHING :
return " FLUSHING " ;
case SMD_SS_CLOSING :
return " CLOSING " ;
case SMD_SS_RESET :
return " RESET " ;
case SMD_SS_RESET_OPENING :
return " ROPENING " ;
default :
return " UNKNOWN " ;
}
}
static int dump_ch ( char * buf , int max , struct smd_channel * ch )
{
volatile struct smd_half_channel * s = ch - > send ;
volatile struct smd_half_channel * r = ch - > recv ;
return scnprintf (
buf , max ,
" ch%02d: "
" %8s(%05d/%05d) %c%c%c%c%c%c%c <-> "
2009-07-01 18:30:47 -07:00
" %8s(%05d/%05d) %c%c%c%c%c%c%c '%s' \n " , ch - > n ,
2009-07-01 17:58:37 -07:00
chstate ( s - > state ) , s - > tail , s - > head ,
s - > fDSR ? ' D ' : ' d ' ,
s - > fCTS ? ' C ' : ' c ' ,
s - > fCD ? ' C ' : ' c ' ,
s - > fRI ? ' I ' : ' i ' ,
s - > fHEAD ? ' W ' : ' w ' ,
s - > fTAIL ? ' R ' : ' r ' ,
s - > fSTATE ? ' S ' : ' s ' ,
chstate ( r - > state ) , r - > tail , r - > head ,
r - > fDSR ? ' D ' : ' d ' ,
r - > fCTS ? ' R ' : ' r ' ,
r - > fCD ? ' C ' : ' c ' ,
r - > fRI ? ' I ' : ' i ' ,
r - > fHEAD ? ' W ' : ' w ' ,
r - > fTAIL ? ' R ' : ' r ' ,
2009-07-01 18:30:47 -07:00
r - > fSTATE ? ' S ' : ' s ' ,
ch - > name
2009-07-01 17:58:37 -07:00
) ;
}
static int debug_read_stat ( char * buf , int max )
{
char * msg ;
int i = 0 ;
msg = smem_find ( ID_DIAG_ERR_MSG , SZ_DIAG_ERR_MSG ) ;
if ( raw_smsm_get_state ( SMSM_STATE_MODEM ) & SMSM_RESET )
i + = scnprintf ( buf + i , max - i ,
" smsm: ARM9 HAS CRASHED \n " ) ;
i + = scnprintf ( buf + i , max - i , " smsm: a9: %08x a11: %08x \n " ,
raw_smsm_get_state ( SMSM_STATE_MODEM ) ,
raw_smsm_get_state ( SMSM_STATE_APPS ) ) ;
# ifdef CONFIG_ARCH_MSM_SCORPION
i + = scnprintf ( buf + i , max - i , " smsm dem: apps: %08x modem: %08x "
" qdsp6: %08x power: %08x time: %08x \n " ,
raw_smsm_get_state ( SMSM_STATE_APPS_DEM ) ,
raw_smsm_get_state ( SMSM_STATE_MODEM_DEM ) ,
raw_smsm_get_state ( SMSM_STATE_QDSP6_DEM ) ,
raw_smsm_get_state ( SMSM_STATE_POWER_MASTER_DEM ) ,
raw_smsm_get_state ( SMSM_STATE_TIME_MASTER_DEM ) ) ;
# endif
if ( msg ) {
msg [ SZ_DIAG_ERR_MSG - 1 ] = 0 ;
i + = scnprintf ( buf + i , max - i , " diag: '%s' \n " , msg ) ;
}
return i ;
}
static int debug_read_mem ( char * buf , int max )
{
unsigned n ;
struct smem_shared * shared = ( void * ) MSM_SHARED_RAM_BASE ;
struct smem_heap_entry * toc = shared - > heap_toc ;
int i = 0 ;
i + = scnprintf ( buf + i , max - i ,
" heap: init=%d free=%d remain=%d \n " ,
shared - > heap_info . initialized ,
shared - > heap_info . free_offset ,
shared - > heap_info . heap_remaining ) ;
for ( n = 0 ; n < SMEM_NUM_ITEMS ; n + + ) {
if ( toc [ n ] . allocated = = 0 )
continue ;
i + = scnprintf ( buf + i , max - i ,
" %04d: offset %08x size %08x \n " ,
n , toc [ n ] . offset , toc [ n ] . size ) ;
}
return i ;
}
static int debug_read_ch ( char * buf , int max )
{
struct smd_channel * ch ;
unsigned long flags ;
int i = 0 ;
spin_lock_irqsave ( & smd_lock , flags ) ;
2009-07-01 18:30:47 -07:00
list_for_each_entry ( ch , & smd_ch_list_dsp , ch_list )
i + = dump_ch ( buf + i , max - i , ch ) ;
list_for_each_entry ( ch , & smd_ch_list_modem , ch_list )
2009-07-01 17:58:37 -07:00
i + = dump_ch ( buf + i , max - i , ch ) ;
list_for_each_entry ( ch , & smd_ch_closed_list , ch_list )
i + = dump_ch ( buf + i , max - i , ch ) ;
spin_unlock_irqrestore ( & smd_lock , flags ) ;
return i ;
}
static int debug_read_version ( char * buf , int max )
{
struct smem_shared * shared = ( void * ) MSM_SHARED_RAM_BASE ;
unsigned version = shared - > version [ VERSION_MODEM ] ;
return sprintf ( buf , " %d.%d \n " , version > > 16 , version & 0xffff ) ;
}
static int debug_read_build_id ( char * buf , int max )
{
unsigned size ;
void * data ;
data = smem_item ( SMEM_HW_SW_BUILD_ID , & size ) ;
if ( ! data )
return 0 ;
if ( size > = max )
size = max ;
memcpy ( buf , data , size ) ;
return size ;
}
static int debug_read_alloc_tbl ( char * buf , int max )
{
struct smd_alloc_elm * shared ;
int n , i = 0 ;
shared = smem_find ( ID_CH_ALLOC_TBL , sizeof ( * shared ) * 64 ) ;
for ( n = 0 ; n < 64 ; n + + ) {
if ( shared [ n ] . ref_count = = 0 )
continue ;
i + = scnprintf ( buf + i , max - i ,
" %03d: %-20s cid=%02d type=%03d "
" kind=%02d ref_count=%d \n " ,
n , shared [ n ] . name , shared [ n ] . cid ,
shared [ n ] . ctype & 0xff ,
( shared [ n ] . ctype > > 8 ) & 0xf ,
shared [ n ] . ref_count ) ;
}
return i ;
}
# define DEBUG_BUFMAX 4096
static char debug_buffer [ DEBUG_BUFMAX ] ;
static ssize_t debug_read ( struct file * file , char __user * buf ,
size_t count , loff_t * ppos )
{
int ( * fill ) ( char * buf , int max ) = file - > private_data ;
int bsize = fill ( debug_buffer , DEBUG_BUFMAX ) ;
return simple_read_from_buffer ( buf , count , ppos , debug_buffer , bsize ) ;
}
static int debug_open ( struct inode * inode , struct file * file )
{
file - > private_data = inode - > i_private ;
return 0 ;
}
static const struct file_operations debug_ops = {
. read = debug_read ,
. open = debug_open ,
} ;
static void debug_create ( const char * name , mode_t mode ,
struct dentry * dent ,
int ( * fill ) ( char * buf , int max ) )
{
debugfs_create_file ( name , mode , dent , fill , & debug_ops ) ;
}
2010-04-23 11:04:14 -07:00
static int smd_debugfs_init ( void )
2009-07-01 17:58:37 -07:00
{
struct dentry * dent ;
dent = debugfs_create_dir ( " smd " , 0 ) ;
if ( IS_ERR ( dent ) )
2010-04-23 11:04:14 -07:00
return 1 ;
2009-07-01 17:58:37 -07:00
debug_create ( " ch " , 0444 , dent , debug_read_ch ) ;
debug_create ( " stat " , 0444 , dent , debug_read_stat ) ;
debug_create ( " mem " , 0444 , dent , debug_read_mem ) ;
debug_create ( " version " , 0444 , dent , debug_read_version ) ;
debug_create ( " tbl " , 0444 , dent , debug_read_alloc_tbl ) ;
debug_create ( " build " , 0444 , dent , debug_read_build_id ) ;
2010-04-23 11:04:14 -07:00
return 0 ;
2009-07-01 17:58:37 -07:00
}
late_initcall ( smd_debugfs_init ) ;
# endif
# define MAX_NUM_SLEEP_CLIENTS 64
# define MAX_SLEEP_NAME_LEN 8
# define NUM_GPIO_INT_REGISTERS 6
# define GPIO_SMEM_NUM_GROUPS 2
# define GPIO_SMEM_MAX_PC_INTERRUPTS 8
struct tramp_gpio_save {
unsigned int enable ;
unsigned int detect ;
unsigned int polarity ;
} ;
struct tramp_gpio_smem {
uint16_t num_fired [ GPIO_SMEM_NUM_GROUPS ] ;
uint16_t fired [ GPIO_SMEM_NUM_GROUPS ] [ GPIO_SMEM_MAX_PC_INTERRUPTS ] ;
uint32_t enabled [ NUM_GPIO_INT_REGISTERS ] ;
uint32_t detection [ NUM_GPIO_INT_REGISTERS ] ;
uint32_t polarity [ NUM_GPIO_INT_REGISTERS ] ;
} ;
void smsm_print_sleep_info ( void )
{
unsigned long flags ;
uint32_t * ptr ;
struct tramp_gpio_smem * gpio ;
struct smsm_interrupt_info * int_info ;
spin_lock_irqsave ( & smem_lock , flags ) ;
ptr = smem_alloc ( SMEM_SMSM_SLEEP_DELAY , sizeof ( * ptr ) ) ;
if ( ptr )
pr_info ( " SMEM_SMSM_SLEEP_DELAY: %x \n " , * ptr ) ;
ptr = smem_alloc ( SMEM_SMSM_LIMIT_SLEEP , sizeof ( * ptr ) ) ;
if ( ptr )
pr_info ( " SMEM_SMSM_LIMIT_SLEEP: %x \n " , * ptr ) ;
ptr = smem_alloc ( SMEM_SLEEP_POWER_COLLAPSE_DISABLED , sizeof ( * ptr ) ) ;
if ( ptr )
pr_info ( " SMEM_SLEEP_POWER_COLLAPSE_DISABLED: %x \n " , * ptr ) ;
# ifndef CONFIG_ARCH_MSM_SCORPION
int_info = smem_alloc ( SMEM_SMSM_INT_INFO , sizeof ( * int_info ) ) ;
if ( int_info )
pr_info ( " SMEM_SMSM_INT_INFO %x %x %x \n " ,
int_info - > interrupt_mask ,
int_info - > pending_interrupts ,
int_info - > wakeup_reason ) ;
gpio = smem_alloc ( SMEM_GPIO_INT , sizeof ( * gpio ) ) ;
if ( gpio ) {
int i ;
for ( i = 0 ; i < NUM_GPIO_INT_REGISTERS ; i + + )
pr_info ( " SMEM_GPIO_INT: %d: e %x d %x p %x \n " ,
i , gpio - > enabled [ i ] , gpio - > detection [ i ] ,
gpio - > polarity [ i ] ) ;
for ( i = 0 ; i < GPIO_SMEM_NUM_GROUPS ; i + + )
pr_info ( " SMEM_GPIO_INT: %d: f %d: %d %d... \n " ,
i , gpio - > num_fired [ i ] , gpio - > fired [ i ] [ 0 ] ,
gpio - > fired [ i ] [ 1 ] ) ;
}
# else
# endif
spin_unlock_irqrestore ( & smem_lock , flags ) ;
}