1 /* 2 * Freescale SSI ALSA SoC Digital Audio Interface (DAI) debugging functions 3 * 4 * Copyright 2014 Markus Pargmann <mpa@pengutronix.de>, Pengutronix 5 * 6 * Splitted from fsl_ssi.c 7 * 8 * This file is licensed under the terms of the GNU General Public License 9 * version 2. This program is licensed "as is" without any warranty of any 10 * kind, whether express or implied. 11 */ 12 13 #include <linux/debugfs.h> 14 #include <linux/device.h> 15 #include <linux/kernel.h> 16 17 #include "fsl_ssi.h" 18 19 void fsl_ssi_dbg_isr(struct fsl_ssi_dbg *dbg, u32 sisr) 20 { 21 if (sisr & SSI_SISR_RFRC) 22 dbg->stats.rfrc++; 23 24 if (sisr & SSI_SISR_TFRC) 25 dbg->stats.tfrc++; 26 27 if (sisr & SSI_SISR_CMDAU) 28 dbg->stats.cmdau++; 29 30 if (sisr & SSI_SISR_CMDDU) 31 dbg->stats.cmddu++; 32 33 if (sisr & SSI_SISR_RXT) 34 dbg->stats.rxt++; 35 36 if (sisr & SSI_SISR_RDR1) 37 dbg->stats.rdr1++; 38 39 if (sisr & SSI_SISR_RDR0) 40 dbg->stats.rdr0++; 41 42 if (sisr & SSI_SISR_TDE1) 43 dbg->stats.tde1++; 44 45 if (sisr & SSI_SISR_TDE0) 46 dbg->stats.tde0++; 47 48 if (sisr & SSI_SISR_ROE1) 49 dbg->stats.roe1++; 50 51 if (sisr & SSI_SISR_ROE0) 52 dbg->stats.roe0++; 53 54 if (sisr & SSI_SISR_TUE1) 55 dbg->stats.tue1++; 56 57 if (sisr & SSI_SISR_TUE0) 58 dbg->stats.tue0++; 59 60 if (sisr & SSI_SISR_TFS) 61 dbg->stats.tfs++; 62 63 if (sisr & SSI_SISR_RFS) 64 dbg->stats.rfs++; 65 66 if (sisr & SSI_SISR_TLS) 67 dbg->stats.tls++; 68 69 if (sisr & SSI_SISR_RLS) 70 dbg->stats.rls++; 71 72 if (sisr & SSI_SISR_RFF1) 73 dbg->stats.rff1++; 74 75 if (sisr & SSI_SISR_RFF0) 76 dbg->stats.rff0++; 77 78 if (sisr & SSI_SISR_TFE1) 79 dbg->stats.tfe1++; 80 81 if (sisr & SSI_SISR_TFE0) 82 dbg->stats.tfe0++; 83 } 84 85 /** 86 * Show the statistics of a flag only if its interrupt is enabled 87 * 88 * Compilers will optimize it to a no-op if the interrupt is disabled 89 */ 90 #define SIER_SHOW(flag, name) \ 91 do { \ 92 if (SSI_SIER_##flag) \ 93 seq_printf(s, #name "=%u\n", ssi_dbg->stats.name); \ 94 } while (0) 95 96 97 /** 98 * Display the statistics for the current SSI device 99 * 100 * To avoid confusion, only show those counts that are enabled 101 */ 102 static int fsl_ssi_stats_show(struct seq_file *s, void *unused) 103 { 104 struct fsl_ssi_dbg *ssi_dbg = s->private; 105 106 SIER_SHOW(RFRC_EN, rfrc); 107 SIER_SHOW(TFRC_EN, tfrc); 108 SIER_SHOW(CMDAU_EN, cmdau); 109 SIER_SHOW(CMDDU_EN, cmddu); 110 SIER_SHOW(RXT_EN, rxt); 111 SIER_SHOW(RDR1_EN, rdr1); 112 SIER_SHOW(RDR0_EN, rdr0); 113 SIER_SHOW(TDE1_EN, tde1); 114 SIER_SHOW(TDE0_EN, tde0); 115 SIER_SHOW(ROE1_EN, roe1); 116 SIER_SHOW(ROE0_EN, roe0); 117 SIER_SHOW(TUE1_EN, tue1); 118 SIER_SHOW(TUE0_EN, tue0); 119 SIER_SHOW(TFS_EN, tfs); 120 SIER_SHOW(RFS_EN, rfs); 121 SIER_SHOW(TLS_EN, tls); 122 SIER_SHOW(RLS_EN, rls); 123 SIER_SHOW(RFF1_EN, rff1); 124 SIER_SHOW(RFF0_EN, rff0); 125 SIER_SHOW(TFE1_EN, tfe1); 126 SIER_SHOW(TFE0_EN, tfe0); 127 128 return 0; 129 } 130 131 static int fsl_ssi_stats_open(struct inode *inode, struct file *file) 132 { 133 return single_open(file, fsl_ssi_stats_show, inode->i_private); 134 } 135 136 static const struct file_operations fsl_ssi_stats_ops = { 137 .open = fsl_ssi_stats_open, 138 .read = seq_read, 139 .llseek = seq_lseek, 140 .release = single_release, 141 }; 142 143 int fsl_ssi_debugfs_create(struct fsl_ssi_dbg *ssi_dbg, struct device *dev) 144 { 145 ssi_dbg->dbg_dir = debugfs_create_dir(dev_name(dev), NULL); 146 if (!ssi_dbg->dbg_dir) 147 return -ENOMEM; 148 149 ssi_dbg->dbg_stats = debugfs_create_file("stats", S_IRUGO, 150 ssi_dbg->dbg_dir, ssi_dbg, 151 &fsl_ssi_stats_ops); 152 if (!ssi_dbg->dbg_stats) { 153 debugfs_remove(ssi_dbg->dbg_dir); 154 return -ENOMEM; 155 } 156 157 return 0; 158 } 159 160 void fsl_ssi_debugfs_remove(struct fsl_ssi_dbg *ssi_dbg) 161 { 162 debugfs_remove(ssi_dbg->dbg_stats); 163 debugfs_remove(ssi_dbg->dbg_dir); 164 } 165