1 | // SPDX-License-Identifier: GPL-2.0 |
2 | // |
3 | // Freescale SSI ALSA SoC Digital Audio Interface (DAI) debugging functions |
4 | // |
5 | // Copyright 2014 Markus Pargmann <mpa@pengutronix.de>, Pengutronix |
6 | // |
7 | // Split from fsl_ssi.c |
8 | |
9 | #include <linux/debugfs.h> |
10 | #include <linux/device.h> |
11 | #include <linux/kernel.h> |
12 | |
13 | #include "fsl_ssi.h" |
14 | |
15 | void fsl_ssi_dbg_isr(struct fsl_ssi_dbg *dbg, u32 sisr) |
16 | { |
17 | if (sisr & SSI_SISR_RFRC) |
18 | dbg->stats.rfrc++; |
19 | |
20 | if (sisr & SSI_SISR_TFRC) |
21 | dbg->stats.tfrc++; |
22 | |
23 | if (sisr & SSI_SISR_CMDAU) |
24 | dbg->stats.cmdau++; |
25 | |
26 | if (sisr & SSI_SISR_CMDDU) |
27 | dbg->stats.cmddu++; |
28 | |
29 | if (sisr & SSI_SISR_RXT) |
30 | dbg->stats.rxt++; |
31 | |
32 | if (sisr & SSI_SISR_RDR1) |
33 | dbg->stats.rdr1++; |
34 | |
35 | if (sisr & SSI_SISR_RDR0) |
36 | dbg->stats.rdr0++; |
37 | |
38 | if (sisr & SSI_SISR_TDE1) |
39 | dbg->stats.tde1++; |
40 | |
41 | if (sisr & SSI_SISR_TDE0) |
42 | dbg->stats.tde0++; |
43 | |
44 | if (sisr & SSI_SISR_ROE1) |
45 | dbg->stats.roe1++; |
46 | |
47 | if (sisr & SSI_SISR_ROE0) |
48 | dbg->stats.roe0++; |
49 | |
50 | if (sisr & SSI_SISR_TUE1) |
51 | dbg->stats.tue1++; |
52 | |
53 | if (sisr & SSI_SISR_TUE0) |
54 | dbg->stats.tue0++; |
55 | |
56 | if (sisr & SSI_SISR_TFS) |
57 | dbg->stats.tfs++; |
58 | |
59 | if (sisr & SSI_SISR_RFS) |
60 | dbg->stats.rfs++; |
61 | |
62 | if (sisr & SSI_SISR_TLS) |
63 | dbg->stats.tls++; |
64 | |
65 | if (sisr & SSI_SISR_RLS) |
66 | dbg->stats.rls++; |
67 | |
68 | if (sisr & SSI_SISR_RFF1) |
69 | dbg->stats.rff1++; |
70 | |
71 | if (sisr & SSI_SISR_RFF0) |
72 | dbg->stats.rff0++; |
73 | |
74 | if (sisr & SSI_SISR_TFE1) |
75 | dbg->stats.tfe1++; |
76 | |
77 | if (sisr & SSI_SISR_TFE0) |
78 | dbg->stats.tfe0++; |
79 | } |
80 | |
81 | /* |
82 | * Show the statistics of a flag only if its interrupt is enabled |
83 | * |
84 | * Compilers will optimize it to a no-op if the interrupt is disabled |
85 | */ |
86 | #define SIER_SHOW(flag, name) \ |
87 | do { \ |
88 | if (SSI_SIER_##flag) \ |
89 | seq_printf(s, #name "=%u\n", ssi_dbg->stats.name); \ |
90 | } while (0) |
91 | |
92 | |
93 | /* |
94 | * Display the statistics for the current SSI device |
95 | * |
96 | * To avoid confusion, only show those counts that are enabled |
97 | */ |
98 | static int fsl_ssi_stats_show(struct seq_file *s, void *unused) |
99 | { |
100 | struct fsl_ssi_dbg *ssi_dbg = s->private; |
101 | |
102 | SIER_SHOW(RFRC_EN, rfrc); |
103 | SIER_SHOW(TFRC_EN, tfrc); |
104 | SIER_SHOW(CMDAU_EN, cmdau); |
105 | SIER_SHOW(CMDDU_EN, cmddu); |
106 | SIER_SHOW(RXT_EN, rxt); |
107 | SIER_SHOW(RDR1_EN, rdr1); |
108 | SIER_SHOW(RDR0_EN, rdr0); |
109 | SIER_SHOW(TDE1_EN, tde1); |
110 | SIER_SHOW(TDE0_EN, tde0); |
111 | SIER_SHOW(ROE1_EN, roe1); |
112 | SIER_SHOW(ROE0_EN, roe0); |
113 | SIER_SHOW(TUE1_EN, tue1); |
114 | SIER_SHOW(TUE0_EN, tue0); |
115 | SIER_SHOW(TFS_EN, tfs); |
116 | SIER_SHOW(RFS_EN, rfs); |
117 | SIER_SHOW(TLS_EN, tls); |
118 | SIER_SHOW(RLS_EN, rls); |
119 | SIER_SHOW(RFF1_EN, rff1); |
120 | SIER_SHOW(RFF0_EN, rff0); |
121 | SIER_SHOW(TFE1_EN, tfe1); |
122 | SIER_SHOW(TFE0_EN, tfe0); |
123 | |
124 | return 0; |
125 | } |
126 | |
127 | DEFINE_SHOW_ATTRIBUTE(fsl_ssi_stats); |
128 | |
129 | void fsl_ssi_debugfs_create(struct fsl_ssi_dbg *ssi_dbg, struct device *dev) |
130 | { |
131 | ssi_dbg->dbg_dir = debugfs_create_dir(name: dev_name(dev), NULL); |
132 | |
133 | debugfs_create_file(name: "stats" , mode: 0444, parent: ssi_dbg->dbg_dir, data: ssi_dbg, |
134 | fops: &fsl_ssi_stats_fops); |
135 | } |
136 | |
137 | void fsl_ssi_debugfs_remove(struct fsl_ssi_dbg *ssi_dbg) |
138 | { |
139 | debugfs_remove_recursive(dentry: ssi_dbg->dbg_dir); |
140 | } |
141 | |