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 & CCSR_SSI_SISR_RFRC) 22 dbg->stats.rfrc++; 23 24 if (sisr & CCSR_SSI_SISR_TFRC) 25 dbg->stats.tfrc++; 26 27 if (sisr & CCSR_SSI_SISR_CMDAU) 28 dbg->stats.cmdau++; 29 30 if (sisr & CCSR_SSI_SISR_CMDDU) 31 dbg->stats.cmddu++; 32 33 if (sisr & CCSR_SSI_SISR_RXT) 34 dbg->stats.rxt++; 35 36 if (sisr & CCSR_SSI_SISR_RDR1) 37 dbg->stats.rdr1++; 38 39 if (sisr & CCSR_SSI_SISR_RDR0) 40 dbg->stats.rdr0++; 41 42 if (sisr & CCSR_SSI_SISR_TDE1) 43 dbg->stats.tde1++; 44 45 if (sisr & CCSR_SSI_SISR_TDE0) 46 dbg->stats.tde0++; 47 48 if (sisr & CCSR_SSI_SISR_ROE1) 49 dbg->stats.roe1++; 50 51 if (sisr & CCSR_SSI_SISR_ROE0) 52 dbg->stats.roe0++; 53 54 if (sisr & CCSR_SSI_SISR_TUE1) 55 dbg->stats.tue1++; 56 57 if (sisr & CCSR_SSI_SISR_TUE0) 58 dbg->stats.tue0++; 59 60 if (sisr & CCSR_SSI_SISR_TFS) 61 dbg->stats.tfs++; 62 63 if (sisr & CCSR_SSI_SISR_RFS) 64 dbg->stats.rfs++; 65 66 if (sisr & CCSR_SSI_SISR_TLS) 67 dbg->stats.tls++; 68 69 if (sisr & CCSR_SSI_SISR_RLS) 70 dbg->stats.rls++; 71 72 if (sisr & CCSR_SSI_SISR_RFF1) 73 dbg->stats.rff1++; 74 75 if (sisr & CCSR_SSI_SISR_RFF0) 76 dbg->stats.rff0++; 77 78 if (sisr & CCSR_SSI_SISR_TFE1) 79 dbg->stats.tfe1++; 80 81 if (sisr & CCSR_SSI_SISR_TFE0) 82 dbg->stats.tfe0++; 83 } 84 85 /* Show the statistics of a flag only if its interrupt is enabled. The 86 * compiler will optimze this code to a no-op if the interrupt is not 87 * enabled. 88 */ 89 #define SIER_SHOW(flag, name) \ 90 do { \ 91 if (CCSR_SSI_SIER_##flag) \ 92 seq_printf(s, #name "=%u\n", ssi_dbg->stats.name); \ 93 } while (0) 94 95 96 /** 97 * fsl_sysfs_ssi_show: display SSI statistics 98 * 99 * Display the statistics for the current SSI device. To avoid confusion, 100 * we 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, &fsl_ssi_stats_ops); 151 if (!ssi_dbg->dbg_stats) { 152 debugfs_remove(ssi_dbg->dbg_dir); 153 return -ENOMEM; 154 } 155 156 return 0; 157 } 158 159 void fsl_ssi_debugfs_remove(struct fsl_ssi_dbg *ssi_dbg) 160 { 161 debugfs_remove(ssi_dbg->dbg_stats); 162 debugfs_remove(ssi_dbg->dbg_dir); 163 } 164