2017-11-03 13:28:30 +03:00
// SPDX-License-Identifier: GPL-2.0
2010-03-12 11:29:11 +03:00
/*
* MUSB OTG driver debugfs support
*
* Copyright 2010 Nokia Corporation
* Contact : Felipe Balbi < felipe . balbi @ nokia . com >
*/
# include <linux/module.h>
# include <linux/kernel.h>
# include <linux/init.h>
# include <linux/debugfs.h>
# include <linux/seq_file.h>
2016-12-24 22:46:01 +03:00
# include <linux/uaccess.h>
2010-03-12 11:29:11 +03:00
# include "musb_core.h"
# include "musb_debug.h"
struct musb_register_map {
char * name ;
unsigned offset ;
unsigned size ;
} ;
static const struct musb_register_map musb_regmap [ ] = {
2014-11-10 23:53:32 +03:00
{ " FAddr " , MUSB_FADDR , 8 } ,
{ " Power " , MUSB_POWER , 8 } ,
{ " Frame " , MUSB_FRAME , 16 } ,
{ " Index " , MUSB_INDEX , 8 } ,
{ " Testmode " , MUSB_TESTMODE , 8 } ,
{ " TxMaxPp " , MUSB_TXMAXP , 16 } ,
{ " TxCSRp " , MUSB_TXCSR , 16 } ,
{ " RxMaxPp " , MUSB_RXMAXP , 16 } ,
{ " RxCSR " , MUSB_RXCSR , 16 } ,
{ " RxCount " , MUSB_RXCOUNT , 16 } ,
{ " IntrRxE " , MUSB_INTRRXE , 16 } ,
{ " IntrTxE " , MUSB_INTRTXE , 16 } ,
{ " IntrUsbE " , MUSB_INTRUSBE , 8 } ,
{ " DevCtl " , MUSB_DEVCTL , 8 } ,
{ " VControl " , 0x68 , 32 } ,
{ " HWVers " , 0x69 , 16 } ,
{ " LinkInfo " , MUSB_LINKINFO , 8 } ,
{ " VPLen " , MUSB_VPLEN , 8 } ,
{ " HS_EOF1 " , MUSB_HS_EOF1 , 8 } ,
{ " FS_EOF1 " , MUSB_FS_EOF1 , 8 } ,
{ " LS_EOF1 " , MUSB_LS_EOF1 , 8 } ,
{ " SOFT_RST " , 0x7F , 8 } ,
2010-03-12 11:29:11 +03:00
{ " DMA_CNTLch0 " , 0x204 , 16 } ,
2010-07-08 12:32:59 +04:00
{ " DMA_ADDRch0 " , 0x208 , 32 } ,
{ " DMA_COUNTch0 " , 0x20C , 32 } ,
2010-03-12 11:29:11 +03:00
{ " DMA_CNTLch1 " , 0x214 , 16 } ,
2010-07-08 12:32:59 +04:00
{ " DMA_ADDRch1 " , 0x218 , 32 } ,
{ " DMA_COUNTch1 " , 0x21C , 32 } ,
2010-03-12 11:29:11 +03:00
{ " DMA_CNTLch2 " , 0x224 , 16 } ,
2010-07-08 12:32:59 +04:00
{ " DMA_ADDRch2 " , 0x228 , 32 } ,
{ " DMA_COUNTch2 " , 0x22C , 32 } ,
2010-03-12 11:29:11 +03:00
{ " DMA_CNTLch3 " , 0x234 , 16 } ,
2010-07-08 12:32:59 +04:00
{ " DMA_ADDRch3 " , 0x238 , 32 } ,
{ " DMA_COUNTch3 " , 0x23C , 32 } ,
2010-03-12 11:29:11 +03:00
{ " DMA_CNTLch4 " , 0x244 , 16 } ,
2010-07-08 12:32:59 +04:00
{ " DMA_ADDRch4 " , 0x248 , 32 } ,
{ " DMA_COUNTch4 " , 0x24C , 32 } ,
2010-03-12 11:29:11 +03:00
{ " DMA_CNTLch5 " , 0x254 , 16 } ,
2010-07-08 12:32:59 +04:00
{ " DMA_ADDRch5 " , 0x258 , 32 } ,
{ " DMA_COUNTch5 " , 0x25C , 32 } ,
2010-03-12 11:29:11 +03:00
{ " DMA_CNTLch6 " , 0x264 , 16 } ,
2010-07-08 12:32:59 +04:00
{ " DMA_ADDRch6 " , 0x268 , 32 } ,
{ " DMA_COUNTch6 " , 0x26C , 32 } ,
2010-03-12 11:29:11 +03:00
{ " DMA_CNTLch7 " , 0x274 , 16 } ,
2010-07-08 12:32:59 +04:00
{ " DMA_ADDRch7 " , 0x278 , 32 } ,
{ " DMA_COUNTch7 " , 0x27C , 32 } ,
2014-11-26 17:01:36 +03:00
{ " ConfigData " , MUSB_CONFIGDATA , 8 } ,
{ " BabbleCtl " , MUSB_BABBLE_CTL , 8 } ,
{ " TxFIFOsz " , MUSB_TXFIFOSZ , 8 } ,
{ " RxFIFOsz " , MUSB_RXFIFOSZ , 8 } ,
{ " TxFIFOadd " , MUSB_TXFIFOADD , 16 } ,
{ " RxFIFOadd " , MUSB_RXFIFOADD , 16 } ,
{ " EPInfo " , MUSB_EPINFO , 8 } ,
{ " RAMInfo " , MUSB_RAMINFO , 8 } ,
2010-03-12 11:29:11 +03:00
{ } /* Terminating Entry */
} ;
static int musb_regdump_show ( struct seq_file * s , void * unused )
{
struct musb * musb = s - > private ;
unsigned i ;
seq_printf ( s , " MUSB (M)HDRC Register Dump \n " ) ;
2017-01-10 19:46:00 +03:00
pm_runtime_get_sync ( musb - > controller ) ;
2010-03-12 11:29:11 +03:00
for ( i = 0 ; i < ARRAY_SIZE ( musb_regmap ) ; i + + ) {
switch ( musb_regmap [ i ] . size ) {
case 8 :
seq_printf ( s , " %-12s: %02x \n " , musb_regmap [ i ] . name ,
musb_readb ( musb - > mregs , musb_regmap [ i ] . offset ) ) ;
break ;
case 16 :
seq_printf ( s , " %-12s: %04x \n " , musb_regmap [ i ] . name ,
musb_readw ( musb - > mregs , musb_regmap [ i ] . offset ) ) ;
break ;
case 32 :
seq_printf ( s , " %-12s: %08x \n " , musb_regmap [ i ] . name ,
musb_readl ( musb - > mregs , musb_regmap [ i ] . offset ) ) ;
break ;
}
}
2017-01-10 19:46:00 +03:00
pm_runtime_mark_last_busy ( musb - > controller ) ;
pm_runtime_put_autosuspend ( musb - > controller ) ;
2010-03-12 11:29:11 +03:00
return 0 ;
}
2018-02-14 19:08:19 +03:00
DEFINE_SHOW_ATTRIBUTE ( musb_regdump ) ;
2010-03-12 11:29:11 +03:00
static int musb_test_mode_show ( struct seq_file * s , void * unused )
{
struct musb * musb = s - > private ;
unsigned test ;
2017-01-10 19:46:00 +03:00
pm_runtime_get_sync ( musb - > controller ) ;
2010-03-12 11:29:11 +03:00
test = musb_readb ( musb - > mregs , MUSB_TESTMODE ) ;
2017-01-10 19:46:00 +03:00
pm_runtime_mark_last_busy ( musb - > controller ) ;
pm_runtime_put_autosuspend ( musb - > controller ) ;
2010-03-12 11:29:11 +03:00
2017-02-02 06:30:22 +03:00
if ( test = = ( MUSB_TEST_FORCE_HOST | MUSB_TEST_FORCE_FS ) )
seq_printf ( s , " force host full-speed \n " ) ;
else if ( test = = ( MUSB_TEST_FORCE_HOST | MUSB_TEST_FORCE_HS ) )
seq_printf ( s , " force host high-speed \n " ) ;
else if ( test = = MUSB_TEST_FORCE_HOST )
2010-03-12 11:29:11 +03:00
seq_printf ( s , " force host \n " ) ;
2017-02-02 06:30:22 +03:00
else if ( test = = MUSB_TEST_FIFO_ACCESS )
2010-03-12 11:29:11 +03:00
seq_printf ( s , " fifo access \n " ) ;
2017-02-02 06:30:22 +03:00
else if ( test = = MUSB_TEST_FORCE_FS )
2010-03-12 11:29:11 +03:00
seq_printf ( s , " force full-speed \n " ) ;
2017-02-02 06:30:22 +03:00
else if ( test = = MUSB_TEST_FORCE_HS )
2010-03-12 11:29:11 +03:00
seq_printf ( s , " force high-speed \n " ) ;
2017-02-02 06:30:22 +03:00
else if ( test = = MUSB_TEST_PACKET )
2010-03-12 11:29:11 +03:00
seq_printf ( s , " test packet \n " ) ;
2017-02-02 06:30:22 +03:00
else if ( test = = MUSB_TEST_K )
2010-03-12 11:29:11 +03:00
seq_printf ( s , " test K \n " ) ;
2017-02-02 06:30:22 +03:00
else if ( test = = MUSB_TEST_J )
2010-03-12 11:29:11 +03:00
seq_printf ( s , " test J \n " ) ;
2017-02-02 06:30:22 +03:00
else if ( test = = MUSB_TEST_SE0_NAK )
2010-03-12 11:29:11 +03:00
seq_printf ( s , " test SE0 NAK \n " ) ;
return 0 ;
}
static int musb_test_mode_open ( struct inode * inode , struct file * file )
{
return single_open ( file , musb_test_mode_show , inode - > i_private ) ;
}
static ssize_t musb_test_mode_write ( struct file * file ,
const char __user * ubuf , size_t count , loff_t * ppos )
{
2010-09-06 14:52:01 +04:00
struct seq_file * s = file - > private_data ;
struct musb * musb = s - > private ;
2015-03-24 23:09:25 +03:00
u8 test ;
2017-02-02 06:30:22 +03:00
char buf [ 24 ] ;
2010-03-12 11:29:11 +03:00
2020-05-25 05:50:49 +03:00
memset ( buf , 0x00 , sizeof ( buf ) ) ;
if ( copy_from_user ( buf , ubuf , min_t ( size_t , sizeof ( buf ) - 1 , count ) ) )
return - EFAULT ;
2017-01-10 19:46:00 +03:00
pm_runtime_get_sync ( musb - > controller ) ;
2015-03-24 23:09:25 +03:00
test = musb_readb ( musb - > mregs , MUSB_TESTMODE ) ;
if ( test ) {
dev_err ( musb - > controller , " Error: test mode is already set. "
" Please do USB Bus Reset to start a new test. \n " ) ;
2017-01-10 19:46:00 +03:00
goto ret ;
2015-03-24 23:09:25 +03:00
}
2017-02-02 06:30:22 +03:00
if ( strstarts ( buf , " force host full-speed " ) )
test = MUSB_TEST_FORCE_HOST | MUSB_TEST_FORCE_FS ;
else if ( strstarts ( buf , " force host high-speed " ) )
test = MUSB_TEST_FORCE_HOST | MUSB_TEST_FORCE_HS ;
else if ( strstarts ( buf , " force host " ) )
2010-03-12 11:29:11 +03:00
test = MUSB_TEST_FORCE_HOST ;
2017-02-02 06:30:22 +03:00
else if ( strstarts ( buf , " fifo access " ) )
2010-03-12 11:29:11 +03:00
test = MUSB_TEST_FIFO_ACCESS ;
2017-02-02 06:30:22 +03:00
else if ( strstarts ( buf , " force full-speed " ) )
2010-03-12 11:29:11 +03:00
test = MUSB_TEST_FORCE_FS ;
2017-02-02 06:30:22 +03:00
else if ( strstarts ( buf , " force high-speed " ) )
2010-03-12 11:29:11 +03:00
test = MUSB_TEST_FORCE_HS ;
2017-02-02 06:30:22 +03:00
else if ( strstarts ( buf , " test packet " ) ) {
2010-03-12 11:29:11 +03:00
test = MUSB_TEST_PACKET ;
musb_load_testpacket ( musb ) ;
}
2017-02-02 06:30:22 +03:00
else if ( strstarts ( buf , " test K " ) )
2010-03-12 11:29:11 +03:00
test = MUSB_TEST_K ;
2017-02-02 06:30:22 +03:00
else if ( strstarts ( buf , " test J " ) )
2010-03-12 11:29:11 +03:00
test = MUSB_TEST_J ;
2017-02-02 06:30:22 +03:00
else if ( strstarts ( buf , " test SE0 NAK " ) )
2010-03-12 11:29:11 +03:00
test = MUSB_TEST_SE0_NAK ;
musb_writeb ( musb - > mregs , MUSB_TESTMODE , test ) ;
2017-01-10 19:46:00 +03:00
ret :
pm_runtime_mark_last_busy ( musb - > controller ) ;
pm_runtime_put_autosuspend ( musb - > controller ) ;
2010-03-12 11:29:11 +03:00
return count ;
}
static const struct file_operations musb_test_mode_fops = {
. open = musb_test_mode_open ,
. write = musb_test_mode_write ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
} ;
2015-03-24 23:19:56 +03:00
static int musb_softconnect_show ( struct seq_file * s , void * unused )
{
struct musb * musb = s - > private ;
u8 reg ;
int connect ;
switch ( musb - > xceiv - > otg - > state ) {
case OTG_STATE_A_HOST :
case OTG_STATE_A_WAIT_BCON :
2017-01-10 19:46:00 +03:00
pm_runtime_get_sync ( musb - > controller ) ;
2015-03-24 23:19:56 +03:00
reg = musb_readb ( musb - > mregs , MUSB_DEVCTL ) ;
connect = reg & MUSB_DEVCTL_SESSION ? 1 : 0 ;
2017-01-10 19:46:00 +03:00
pm_runtime_mark_last_busy ( musb - > controller ) ;
pm_runtime_put_autosuspend ( musb - > controller ) ;
2015-03-24 23:19:56 +03:00
break ;
default :
connect = - 1 ;
}
seq_printf ( s , " %d \n " , connect ) ;
return 0 ;
}
static int musb_softconnect_open ( struct inode * inode , struct file * file )
{
return single_open ( file , musb_softconnect_show , inode - > i_private ) ;
}
static ssize_t musb_softconnect_write ( struct file * file ,
const char __user * ubuf , size_t count , loff_t * ppos )
{
struct seq_file * s = file - > private_data ;
struct musb * musb = s - > private ;
char buf [ 2 ] ;
u8 reg ;
memset ( buf , 0x00 , sizeof ( buf ) ) ;
if ( copy_from_user ( & buf , ubuf , min_t ( size_t , sizeof ( buf ) - 1 , count ) ) )
return - EFAULT ;
2017-01-10 19:46:00 +03:00
pm_runtime_get_sync ( musb - > controller ) ;
2015-03-24 23:19:56 +03:00
if ( ! strncmp ( buf , " 0 " , 1 ) ) {
switch ( musb - > xceiv - > otg - > state ) {
case OTG_STATE_A_HOST :
musb_root_disconnect ( musb ) ;
reg = musb_readb ( musb - > mregs , MUSB_DEVCTL ) ;
reg & = ~ MUSB_DEVCTL_SESSION ;
musb_writeb ( musb - > mregs , MUSB_DEVCTL , reg ) ;
break ;
default :
break ;
}
} else if ( ! strncmp ( buf , " 1 " , 1 ) ) {
switch ( musb - > xceiv - > otg - > state ) {
case OTG_STATE_A_WAIT_BCON :
/*
* musb_save_context ( ) called in musb_runtime_suspend ( )
* might cache devctl with SESSION bit cleared during
* soft - disconnect , so specifically set SESSION bit
* here to preserve it for musb_runtime_resume ( ) .
*/
musb - > context . devctl | = MUSB_DEVCTL_SESSION ;
reg = musb_readb ( musb - > mregs , MUSB_DEVCTL ) ;
reg | = MUSB_DEVCTL_SESSION ;
musb_writeb ( musb - > mregs , MUSB_DEVCTL , reg ) ;
break ;
default :
break ;
}
}
2017-01-10 19:46:00 +03:00
pm_runtime_mark_last_busy ( musb - > controller ) ;
pm_runtime_put_autosuspend ( musb - > controller ) ;
2015-03-24 23:19:56 +03:00
return count ;
}
/*
* In host mode , connect / disconnect the bus without physically
* remove the devices .
*/
static const struct file_operations musb_softconnect_fops = {
. open = musb_softconnect_open ,
. write = musb_softconnect_write ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
} ;
2018-05-29 18:30:48 +03:00
void musb_init_debugfs ( struct musb * musb )
2010-03-12 11:29:11 +03:00
{
2018-05-29 18:30:48 +03:00
struct dentry * root ;
2010-03-12 11:29:11 +03:00
2019-11-20 09:43:01 +03:00
root = debugfs_create_dir ( dev_name ( musb - > controller ) , usb_debug_root ) ;
2012-08-31 15:09:50 +04:00
musb - > debugfs_root = root ;
2010-03-12 11:29:11 +03:00
2018-05-29 18:30:48 +03:00
debugfs_create_file ( " regdump " , S_IRUGO , root , musb , & musb_regdump_fops ) ;
debugfs_create_file ( " testmode " , S_IRUGO | S_IWUSR , root , musb ,
& musb_test_mode_fops ) ;
debugfs_create_file ( " softconnect " , S_IRUGO | S_IWUSR , root , musb ,
& musb_softconnect_fops ) ;
2010-03-12 11:29:11 +03:00
}
2010-03-25 14:25:18 +03:00
void /* __init_or_exit */ musb_exit_debugfs ( struct musb * musb )
2010-03-12 11:29:11 +03:00
{
2012-08-31 15:09:50 +04:00
debugfs_remove_recursive ( musb - > debugfs_root ) ;
2010-03-12 11:29:11 +03:00
}