2019-06-04 15:29:24 +02:00
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright ( c ) 2018 - 2019 Synopsys , Inc . and / or its affiliates .
* Synopsys DesignWare eDMA v0 core
*
* Author : Gustavo Pimentel < gustavo . pimentel @ synopsys . com >
*/
# include <linux/debugfs.h>
# include <linux/bitfield.h>
# include "dw-edma-v0-debugfs.h"
# include "dw-edma-v0-regs.h"
# include "dw-edma-core.h"
# define REGS_ADDR(name) \
2023-01-13 20:13:52 +03:00
( ( void __iomem * ) & regs - > name )
2019-06-04 15:29:24 +02:00
# define REGISTER(name) \
{ # name , REGS_ADDR ( name ) }
# define WR_REGISTER(name) \
{ # name , REGS_ADDR ( wr_ # # name ) }
# define RD_REGISTER(name) \
{ # name , REGS_ADDR ( rd_ # # name ) }
# define WR_REGISTER_LEGACY(name) \
{ # name , REGS_ADDR ( type . legacy . wr_ # # name ) }
# define RD_REGISTER_LEGACY(name) \
{ # name , REGS_ADDR ( type . legacy . rd_ # # name ) }
# define WR_REGISTER_UNROLL(name) \
{ # name , REGS_ADDR ( type . unroll . wr_ # # name ) }
# define RD_REGISTER_UNROLL(name) \
{ # name , REGS_ADDR ( type . unroll . rd_ # # name ) }
# define WRITE_STR "write"
# define READ_STR "read"
# define CHANNEL_STR "channel"
# define REGISTERS_STR "registers"
static struct dw_edma * dw ;
2019-07-22 14:44:44 +02:00
static struct dw_edma_v0_regs __iomem * regs ;
2019-06-04 15:29:24 +02:00
static struct {
2019-07-22 14:44:44 +02:00
void __iomem * start ;
void __iomem * end ;
2019-06-04 15:29:24 +02:00
} lim [ 2 ] [ EDMA_V0_MAX_NR_CH ] ;
2023-01-13 20:13:54 +03:00
struct dw_edma_debugfs_entry {
2019-07-22 14:44:43 +02:00
const char * name ;
2023-01-13 20:13:52 +03:00
void __iomem * reg ;
2019-06-04 15:29:24 +02:00
} ;
static int dw_edma_debugfs_u32_get ( void * data , u64 * val )
{
2023-01-13 20:13:55 +03:00
struct dw_edma_debugfs_entry * entry = data ;
void __iomem * reg = entry - > reg ;
2023-01-13 20:13:52 +03:00
2022-05-24 10:21:53 -05:00
if ( dw - > chip - > mf = = EDMA_MF_EDMA_LEGACY & &
2019-07-22 14:44:44 +02:00
reg > = ( void __iomem * ) & regs - > type . legacy . ch ) {
void __iomem * ptr = & regs - > type . legacy . ch ;
2019-06-04 15:29:24 +02:00
u32 viewport_sel = 0 ;
unsigned long flags ;
u16 ch ;
for ( ch = 0 ; ch < dw - > wr_ch_cnt ; ch + + )
2019-07-22 14:44:44 +02:00
if ( lim [ 0 ] [ ch ] . start > = reg & & reg < lim [ 0 ] [ ch ] . end ) {
ptr + = ( reg - lim [ 0 ] [ ch ] . start ) ;
2019-06-04 15:29:24 +02:00
goto legacy_sel_wr ;
}
for ( ch = 0 ; ch < dw - > rd_ch_cnt ; ch + + )
2019-07-22 14:44:44 +02:00
if ( lim [ 1 ] [ ch ] . start > = reg & & reg < lim [ 1 ] [ ch ] . end ) {
ptr + = ( reg - lim [ 1 ] [ ch ] . start ) ;
2019-06-04 15:29:24 +02:00
goto legacy_sel_rd ;
}
return 0 ;
legacy_sel_rd :
viewport_sel = BIT ( 31 ) ;
legacy_sel_wr :
viewport_sel | = FIELD_PREP ( EDMA_V0_VIEWPORT_MASK , ch ) ;
raw_spin_lock_irqsave ( & dw - > lock , flags ) ;
writel ( viewport_sel , & regs - > type . legacy . viewport_sel ) ;
* val = readl ( ptr ) ;
raw_spin_unlock_irqrestore ( & dw - > lock , flags ) ;
} else {
2019-07-22 14:44:44 +02:00
* val = readl ( reg ) ;
2019-06-04 15:29:24 +02:00
}
return 0 ;
}
DEFINE_DEBUGFS_ATTRIBUTE ( fops_x32 , dw_edma_debugfs_u32_get , NULL , " 0x%08llx \n " ) ;
2023-01-13 20:13:55 +03:00
static void dw_edma_debugfs_create_x32 ( const struct dw_edma_debugfs_entry ini [ ] ,
2023-01-13 20:13:56 +03:00
int nr_entries , struct dentry * dent )
2019-06-04 15:29:24 +02:00
{
2023-01-13 20:13:55 +03:00
struct dw_edma_debugfs_entry * entries ;
2019-06-04 15:29:24 +02:00
int i ;
2023-01-13 20:13:55 +03:00
entries = devm_kcalloc ( dw - > chip - > dev , nr_entries , sizeof ( * entries ) ,
GFP_KERNEL ) ;
if ( ! entries )
return ;
2019-06-04 15:29:24 +02:00
for ( i = 0 ; i < nr_entries ; i + + ) {
2023-01-13 20:13:55 +03:00
entries [ i ] = ini [ i ] ;
2023-01-13 20:13:56 +03:00
debugfs_create_file_unsafe ( entries [ i ] . name , 0444 , dent ,
2023-01-13 20:13:55 +03:00
& entries [ i ] , & fops_x32 ) ;
2019-06-04 15:29:24 +02:00
}
}
2019-07-22 14:44:44 +02:00
static void dw_edma_debugfs_regs_ch ( struct dw_edma_v0_ch_regs __iomem * regs ,
2023-01-13 20:13:56 +03:00
struct dentry * dent )
2019-06-04 15:29:24 +02:00
{
2023-01-13 20:13:54 +03:00
const struct dw_edma_debugfs_entry debugfs_regs [ ] = {
2019-06-04 15:29:24 +02:00
REGISTER ( ch_control1 ) ,
REGISTER ( ch_control2 ) ,
REGISTER ( transfer_size ) ,
2021-02-18 20:03:55 +01:00
REGISTER ( sar . lsb ) ,
REGISTER ( sar . msb ) ,
REGISTER ( dar . lsb ) ,
REGISTER ( dar . msb ) ,
REGISTER ( llp . lsb ) ,
REGISTER ( llp . msb ) ,
2019-06-04 15:29:24 +02:00
} ;
2023-01-13 20:13:54 +03:00
int nr_entries ;
2019-06-04 15:29:24 +02:00
nr_entries = ARRAY_SIZE ( debugfs_regs ) ;
2023-01-13 20:13:56 +03:00
dw_edma_debugfs_create_x32 ( debugfs_regs , nr_entries , dent ) ;
2019-06-04 15:29:24 +02:00
}
2023-01-13 20:13:56 +03:00
static void dw_edma_debugfs_regs_wr ( struct dentry * dent )
2019-06-04 15:29:24 +02:00
{
2023-01-13 20:13:54 +03:00
const struct dw_edma_debugfs_entry debugfs_regs [ ] = {
2019-06-04 15:29:24 +02:00
/* eDMA global registers */
WR_REGISTER ( engine_en ) ,
WR_REGISTER ( doorbell ) ,
2021-02-18 20:03:55 +01:00
WR_REGISTER ( ch_arb_weight . lsb ) ,
WR_REGISTER ( ch_arb_weight . msb ) ,
2019-06-04 15:29:24 +02:00
/* eDMA interrupts registers */
WR_REGISTER ( int_status ) ,
WR_REGISTER ( int_mask ) ,
WR_REGISTER ( int_clear ) ,
WR_REGISTER ( err_status ) ,
2021-02-18 20:03:55 +01:00
WR_REGISTER ( done_imwr . lsb ) ,
WR_REGISTER ( done_imwr . msb ) ,
WR_REGISTER ( abort_imwr . lsb ) ,
WR_REGISTER ( abort_imwr . msb ) ,
2019-06-04 15:29:24 +02:00
WR_REGISTER ( ch01_imwr_data ) ,
WR_REGISTER ( ch23_imwr_data ) ,
WR_REGISTER ( ch45_imwr_data ) ,
WR_REGISTER ( ch67_imwr_data ) ,
WR_REGISTER ( linked_list_err_en ) ,
} ;
2023-01-13 20:13:54 +03:00
const struct dw_edma_debugfs_entry debugfs_unroll_regs [ ] = {
2019-06-04 15:29:24 +02:00
/* eDMA channel context grouping */
WR_REGISTER_UNROLL ( engine_chgroup ) ,
2021-02-18 20:03:55 +01:00
WR_REGISTER_UNROLL ( engine_hshake_cnt . lsb ) ,
WR_REGISTER_UNROLL ( engine_hshake_cnt . msb ) ,
2019-06-04 15:29:24 +02:00
WR_REGISTER_UNROLL ( ch0_pwr_en ) ,
WR_REGISTER_UNROLL ( ch1_pwr_en ) ,
WR_REGISTER_UNROLL ( ch2_pwr_en ) ,
WR_REGISTER_UNROLL ( ch3_pwr_en ) ,
WR_REGISTER_UNROLL ( ch4_pwr_en ) ,
WR_REGISTER_UNROLL ( ch5_pwr_en ) ,
WR_REGISTER_UNROLL ( ch6_pwr_en ) ,
WR_REGISTER_UNROLL ( ch7_pwr_en ) ,
} ;
2023-01-13 20:13:56 +03:00
struct dentry * regs_dent , * ch_dent ;
2019-06-04 15:29:24 +02:00
int nr_entries , i ;
char name [ 16 ] ;
2023-01-13 20:13:56 +03:00
regs_dent = debugfs_create_dir ( WRITE_STR , dent ) ;
2019-06-04 15:29:24 +02:00
nr_entries = ARRAY_SIZE ( debugfs_regs ) ;
2023-01-13 20:13:56 +03:00
dw_edma_debugfs_create_x32 ( debugfs_regs , nr_entries , regs_dent ) ;
2019-06-04 15:29:24 +02:00
2022-05-24 10:21:53 -05:00
if ( dw - > chip - > mf = = EDMA_MF_HDMA_COMPAT ) {
2019-06-04 15:29:24 +02:00
nr_entries = ARRAY_SIZE ( debugfs_unroll_regs ) ;
dw_edma_debugfs_create_x32 ( debugfs_unroll_regs , nr_entries ,
2023-01-13 20:13:56 +03:00
regs_dent ) ;
2019-06-04 15:29:24 +02:00
}
for ( i = 0 ; i < dw - > wr_ch_cnt ; i + + ) {
snprintf ( name , sizeof ( name ) , " %s:%d " , CHANNEL_STR , i ) ;
2023-01-13 20:13:56 +03:00
ch_dent = debugfs_create_dir ( name , regs_dent ) ;
2019-06-04 15:29:24 +02:00
2023-01-13 20:13:56 +03:00
dw_edma_debugfs_regs_ch ( & regs - > type . unroll . ch [ i ] . wr , ch_dent ) ;
2019-06-04 15:29:24 +02:00
lim [ 0 ] [ i ] . start = & regs - > type . unroll . ch [ i ] . wr ;
lim [ 0 ] [ i ] . end = & regs - > type . unroll . ch [ i ] . padding_1 [ 0 ] ;
}
}
2023-01-13 20:13:56 +03:00
static void dw_edma_debugfs_regs_rd ( struct dentry * dent )
2019-06-04 15:29:24 +02:00
{
2023-01-13 20:13:54 +03:00
const struct dw_edma_debugfs_entry debugfs_regs [ ] = {
2019-06-04 15:29:24 +02:00
/* eDMA global registers */
RD_REGISTER ( engine_en ) ,
RD_REGISTER ( doorbell ) ,
2021-02-18 20:03:55 +01:00
RD_REGISTER ( ch_arb_weight . lsb ) ,
RD_REGISTER ( ch_arb_weight . msb ) ,
2019-06-04 15:29:24 +02:00
/* eDMA interrupts registers */
RD_REGISTER ( int_status ) ,
RD_REGISTER ( int_mask ) ,
RD_REGISTER ( int_clear ) ,
2021-02-18 20:03:55 +01:00
RD_REGISTER ( err_status . lsb ) ,
RD_REGISTER ( err_status . msb ) ,
2019-06-04 15:29:24 +02:00
RD_REGISTER ( linked_list_err_en ) ,
2021-02-18 20:03:55 +01:00
RD_REGISTER ( done_imwr . lsb ) ,
RD_REGISTER ( done_imwr . msb ) ,
RD_REGISTER ( abort_imwr . lsb ) ,
RD_REGISTER ( abort_imwr . msb ) ,
2019-06-04 15:29:24 +02:00
RD_REGISTER ( ch01_imwr_data ) ,
RD_REGISTER ( ch23_imwr_data ) ,
RD_REGISTER ( ch45_imwr_data ) ,
RD_REGISTER ( ch67_imwr_data ) ,
} ;
2023-01-13 20:13:54 +03:00
const struct dw_edma_debugfs_entry debugfs_unroll_regs [ ] = {
2019-06-04 15:29:24 +02:00
/* eDMA channel context grouping */
RD_REGISTER_UNROLL ( engine_chgroup ) ,
2021-02-18 20:03:55 +01:00
RD_REGISTER_UNROLL ( engine_hshake_cnt . lsb ) ,
RD_REGISTER_UNROLL ( engine_hshake_cnt . msb ) ,
2019-06-04 15:29:24 +02:00
RD_REGISTER_UNROLL ( ch0_pwr_en ) ,
RD_REGISTER_UNROLL ( ch1_pwr_en ) ,
RD_REGISTER_UNROLL ( ch2_pwr_en ) ,
RD_REGISTER_UNROLL ( ch3_pwr_en ) ,
RD_REGISTER_UNROLL ( ch4_pwr_en ) ,
RD_REGISTER_UNROLL ( ch5_pwr_en ) ,
RD_REGISTER_UNROLL ( ch6_pwr_en ) ,
RD_REGISTER_UNROLL ( ch7_pwr_en ) ,
} ;
2023-01-13 20:13:56 +03:00
struct dentry * regs_dent , * ch_dent ;
2019-06-04 15:29:24 +02:00
int nr_entries , i ;
char name [ 16 ] ;
2023-01-13 20:13:56 +03:00
regs_dent = debugfs_create_dir ( READ_STR , dent ) ;
2019-06-04 15:29:24 +02:00
nr_entries = ARRAY_SIZE ( debugfs_regs ) ;
2023-01-13 20:13:56 +03:00
dw_edma_debugfs_create_x32 ( debugfs_regs , nr_entries , regs_dent ) ;
2019-06-04 15:29:24 +02:00
2022-05-24 10:21:53 -05:00
if ( dw - > chip - > mf = = EDMA_MF_HDMA_COMPAT ) {
2019-06-04 15:29:24 +02:00
nr_entries = ARRAY_SIZE ( debugfs_unroll_regs ) ;
dw_edma_debugfs_create_x32 ( debugfs_unroll_regs , nr_entries ,
2023-01-13 20:13:56 +03:00
regs_dent ) ;
2019-06-04 15:29:24 +02:00
}
for ( i = 0 ; i < dw - > rd_ch_cnt ; i + + ) {
snprintf ( name , sizeof ( name ) , " %s:%d " , CHANNEL_STR , i ) ;
2023-01-13 20:13:56 +03:00
ch_dent = debugfs_create_dir ( name , regs_dent ) ;
2019-06-04 15:29:24 +02:00
2023-01-13 20:13:56 +03:00
dw_edma_debugfs_regs_ch ( & regs - > type . unroll . ch [ i ] . rd , ch_dent ) ;
2019-06-04 15:29:24 +02:00
lim [ 1 ] [ i ] . start = & regs - > type . unroll . ch [ i ] . rd ;
lim [ 1 ] [ i ] . end = & regs - > type . unroll . ch [ i ] . padding_2 [ 0 ] ;
}
}
static void dw_edma_debugfs_regs ( void )
{
2023-01-13 20:13:54 +03:00
const struct dw_edma_debugfs_entry debugfs_regs [ ] = {
2019-06-04 15:29:24 +02:00
REGISTER ( ctrl_data_arb_prior ) ,
REGISTER ( ctrl ) ,
} ;
2023-01-13 20:13:56 +03:00
struct dentry * regs_dent ;
2019-06-04 15:29:24 +02:00
int nr_entries ;
2023-01-13 20:13:56 +03:00
regs_dent = debugfs_create_dir ( REGISTERS_STR , dw - > debugfs ) ;
2019-06-04 15:29:24 +02:00
nr_entries = ARRAY_SIZE ( debugfs_regs ) ;
2023-01-13 20:13:56 +03:00
dw_edma_debugfs_create_x32 ( debugfs_regs , nr_entries , regs_dent ) ;
2019-06-04 15:29:24 +02:00
2023-01-13 20:13:56 +03:00
dw_edma_debugfs_regs_wr ( regs_dent ) ;
dw_edma_debugfs_regs_rd ( regs_dent ) ;
2019-06-04 15:29:24 +02:00
}
2022-05-24 10:21:53 -05:00
void dw_edma_v0_debugfs_on ( struct dw_edma * _dw )
2019-06-04 15:29:24 +02:00
{
2023-01-13 20:13:53 +03:00
if ( ! debugfs_initialized ( ) )
return ;
2022-05-24 10:21:53 -05:00
dw = _dw ;
2019-06-04 15:29:24 +02:00
if ( ! dw )
return ;
2022-05-24 10:21:54 -05:00
regs = dw - > chip - > reg_base ;
2019-06-04 15:29:24 +02:00
if ( ! regs )
return ;
2021-02-18 20:04:05 +01:00
dw - > debugfs = debugfs_create_dir ( dw - > name , NULL ) ;
2019-06-04 15:29:24 +02:00
2022-05-24 10:21:53 -05:00
debugfs_create_u32 ( " mf " , 0444 , dw - > debugfs , & dw - > chip - > mf ) ;
2021-02-18 20:04:05 +01:00
debugfs_create_u16 ( " wr_ch_cnt " , 0444 , dw - > debugfs , & dw - > wr_ch_cnt ) ;
debugfs_create_u16 ( " rd_ch_cnt " , 0444 , dw - > debugfs , & dw - > rd_ch_cnt ) ;
2019-06-04 15:29:24 +02:00
dw_edma_debugfs_regs ( ) ;
}
2022-05-24 10:21:53 -05:00
void dw_edma_v0_debugfs_off ( struct dw_edma * _dw )
2019-06-04 15:29:24 +02:00
{
2022-05-24 10:21:53 -05:00
dw = _dw ;
2021-02-18 20:04:05 +01:00
if ( ! dw )
return ;
debugfs_remove_recursive ( dw - > debugfs ) ;
dw - > debugfs = NULL ;
2019-06-04 15:29:24 +02:00
}