Commit | Line | Data |
---|---|---|
f138e621 MP |
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 | } |