aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/musb
diff options
context:
space:
mode:
authorFelipe Balbi <felipe.balbi@nokia.com>2010-03-12 03:29:11 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2010-05-20 16:21:32 -0400
commit7f7f9e2a5af9e30c6a0c6743ac874f67e2ef4b72 (patch)
tree3d7fae6e559868e3ac110b3973650198458a815e /drivers/usb/musb
parent6ddc6dae4ab559b648bc348e3a48e113e92ab4a2 (diff)
usb: musb: add debugfs support
for now only a simple register dump entry (which can be rather useful on debugging) and a way to start test modes. Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/musb')
-rw-r--r--drivers/usb/musb/Makefile4
-rw-r--r--drivers/usb/musb/musb_core.c5
-rw-r--r--drivers/usb/musb/musb_debug.h13
-rw-r--r--drivers/usb/musb/musb_debugfs.c295
4 files changed, 317 insertions, 0 deletions
diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile
index db7933de17b5..a1677f9955aa 100644
--- a/drivers/usb/musb/Makefile
+++ b/drivers/usb/musb/Makefile
@@ -42,6 +42,10 @@ ifeq ($(CONFIG_USB_MUSB_HDRC_HCD),y)
42 musb_hdrc-objs += musb_virthub.o musb_host.o 42 musb_hdrc-objs += musb_virthub.o musb_host.o
43endif 43endif
44 44
45ifeq ($(CONFIG_DEBUG_FS),y)
46 musb_hdrc-objs += musb_debugfs.o
47endif
48
45# the kconfig must guarantee that only one of the 49# the kconfig must guarantee that only one of the
46# possible I/O schemes will be enabled at a time ... 50# possible I/O schemes will be enabled at a time ...
47# PIO only, or DMA (several potential schemes). 51# PIO only, or DMA (several potential schemes).
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 28ff0330bcea..3466cd53e9c8 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -2054,6 +2054,10 @@ bad_config:
2054 if (status < 0) 2054 if (status < 0)
2055 goto fail3; 2055 goto fail3;
2056 2056
2057 status = musb_init_debugfs(musb);
2058 if (status < 0)
2059 goto fail2;
2060
2057#ifdef CONFIG_SYSFS 2061#ifdef CONFIG_SYSFS
2058 status = sysfs_create_group(&musb->controller->kobj, &musb_attr_group); 2062 status = sysfs_create_group(&musb->controller->kobj, &musb_attr_group);
2059 if (status) 2063 if (status)
@@ -2150,6 +2154,7 @@ static int __exit musb_remove(struct platform_device *pdev)
2150 * - Peripheral mode: peripheral is deactivated (or never-activated) 2154 * - Peripheral mode: peripheral is deactivated (or never-activated)
2151 * - OTG mode: both roles are deactivated (or never-activated) 2155 * - OTG mode: both roles are deactivated (or never-activated)
2152 */ 2156 */
2157 musb_exit_debugfs(musb);
2153 musb_shutdown(pdev); 2158 musb_shutdown(pdev);
2154#ifdef CONFIG_USB_MUSB_HDRC_HCD 2159#ifdef CONFIG_USB_MUSB_HDRC_HCD
2155 if (musb->board_mode == MUSB_HOST) 2160 if (musb->board_mode == MUSB_HOST)
diff --git a/drivers/usb/musb/musb_debug.h b/drivers/usb/musb/musb_debug.h
index 9fc1db44c72c..d73afdbde3ee 100644
--- a/drivers/usb/musb/musb_debug.h
+++ b/drivers/usb/musb/musb_debug.h
@@ -59,4 +59,17 @@ static inline int _dbg_level(unsigned l)
59 59
60extern const char *otg_state_string(struct musb *); 60extern const char *otg_state_string(struct musb *);
61 61
62#ifdef CONFIG_DEBUG_FS
63extern int musb_init_debugfs(struct musb *musb);
64extern void musb_exit_debugfs(struct musb *musb);
65#else
66static inline int musb_init_debugfs(struct musb *musb)
67{
68 return 0;
69}
70static inline void musb_exit_debugfs(struct musb *musb)
71{
72}
73#endif
74
62#endif /* __MUSB_LINUX_DEBUG_H__ */ 75#endif /* __MUSB_LINUX_DEBUG_H__ */
diff --git a/drivers/usb/musb/musb_debugfs.c b/drivers/usb/musb/musb_debugfs.c
new file mode 100644
index 000000000000..b6a27bab223a
--- /dev/null
+++ b/drivers/usb/musb/musb_debugfs.c
@@ -0,0 +1,295 @@
1/*
2 * MUSB OTG driver debugfs support
3 *
4 * Copyright 2010 Nokia Corporation
5 * Contact: Felipe Balbi <felipe.balbi@nokia.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * version 2 as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
19 * 02110-1301 USA
20 *
21 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
22 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
24 * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
27 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
28 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
34#include <linux/module.h>
35#include <linux/kernel.h>
36#include <linux/sched.h>
37#include <linux/slab.h>
38#include <linux/init.h>
39#include <linux/list.h>
40#include <linux/kobject.h>
41#include <linux/platform_device.h>
42#include <linux/io.h>
43#include <linux/debugfs.h>
44#include <linux/seq_file.h>
45
46#ifdef CONFIG_ARM
47#include <mach/hardware.h>
48#include <mach/memory.h>
49#include <asm/mach-types.h>
50#endif
51
52#include <asm/uaccess.h>
53
54#include "musb_core.h"
55#include "musb_debug.h"
56
57#ifdef CONFIG_ARCH_DAVINCI
58#include "davinci.h"
59#endif
60
61struct musb_register_map {
62 char *name;
63 unsigned offset;
64 unsigned size;
65};
66
67static const struct musb_register_map musb_regmap[] = {
68 { "FAddr", 0x00, 8 },
69 { "Power", 0x01, 8 },
70 { "Frame", 0x0c, 16 },
71 { "Index", 0x0e, 8 },
72 { "Testmode", 0x0f, 8 },
73 { "TxMaxPp", 0x10, 16 },
74 { "TxCSRp", 0x12, 16 },
75 { "RxMaxPp", 0x14, 16 },
76 { "RxCSR", 0x16, 16 },
77 { "RxCount", 0x18, 16 },
78 { "ConfigData", 0x1f, 8 },
79 { "DevCtl", 0x60, 8 },
80 { "MISC", 0x61, 8 },
81 { "TxFIFOsz", 0x62, 8 },
82 { "RxFIFOsz", 0x63, 8 },
83 { "TxFIFOadd", 0x64, 16 },
84 { "RxFIFOadd", 0x66, 16 },
85 { "VControl", 0x68, 32 },
86 { "HWVers", 0x6C, 16 },
87 { "EPInfo", 0x78, 8 },
88 { "RAMInfo", 0x79, 8 },
89 { "LinkInfo", 0x7A, 8 },
90 { "VPLen", 0x7B, 8 },
91 { "HS_EOF1", 0x7C, 8 },
92 { "FS_EOF1", 0x7D, 8 },
93 { "LS_EOF1", 0x7E, 8 },
94 { "SOFT_RST", 0x7F, 8 },
95 { "DMA_CNTLch0", 0x204, 16 },
96 { "DMA_ADDRch0", 0x208, 16 },
97 { "DMA_COUNTch0", 0x20C, 16 },
98 { "DMA_CNTLch1", 0x214, 16 },
99 { "DMA_ADDRch1", 0x218, 16 },
100 { "DMA_COUNTch1", 0x21C, 16 },
101 { "DMA_CNTLch2", 0x224, 16 },
102 { "DMA_ADDRch2", 0x228, 16 },
103 { "DMA_COUNTch2", 0x22C, 16 },
104 { "DMA_CNTLch3", 0x234, 16 },
105 { "DMA_ADDRch3", 0x238, 16 },
106 { "DMA_COUNTch3", 0x23C, 16 },
107 { "DMA_CNTLch4", 0x244, 16 },
108 { "DMA_ADDRch4", 0x248, 16 },
109 { "DMA_COUNTch4", 0x24C, 16 },
110 { "DMA_CNTLch5", 0x254, 16 },
111 { "DMA_ADDRch5", 0x258, 16 },
112 { "DMA_COUNTch5", 0x25C, 16 },
113 { "DMA_CNTLch6", 0x264, 16 },
114 { "DMA_ADDRch6", 0x268, 16 },
115 { "DMA_COUNTch6", 0x26C, 16 },
116 { "DMA_CNTLch7", 0x274, 16 },
117 { "DMA_ADDRch7", 0x278, 16 },
118 { "DMA_COUNTch7", 0x27C, 16 },
119 { } /* Terminating Entry */
120};
121
122static struct dentry *musb_debugfs_root;
123
124static int musb_regdump_show(struct seq_file *s, void *unused)
125{
126 struct musb *musb = s->private;
127 unsigned i;
128
129 seq_printf(s, "MUSB (M)HDRC Register Dump\n");
130
131 for (i = 0; i < ARRAY_SIZE(musb_regmap); i++) {
132 switch (musb_regmap[i].size) {
133 case 8:
134 seq_printf(s, "%-12s: %02x\n", musb_regmap[i].name,
135 musb_readb(musb->mregs, musb_regmap[i].offset));
136 break;
137 case 16:
138 seq_printf(s, "%-12s: %04x\n", musb_regmap[i].name,
139 musb_readw(musb->mregs, musb_regmap[i].offset));
140 break;
141 case 32:
142 seq_printf(s, "%-12s: %08x\n", musb_regmap[i].name,
143 musb_readl(musb->mregs, musb_regmap[i].offset));
144 break;
145 }
146 }
147
148 return 0;
149}
150
151static int musb_regdump_open(struct inode *inode, struct file *file)
152{
153 return single_open(file, musb_regdump_show, inode->i_private);
154}
155
156static int musb_test_mode_show(struct seq_file *s, void *unused)
157{
158 struct musb *musb = s->private;
159 unsigned test;
160
161 test = musb_readb(musb->mregs, MUSB_TESTMODE);
162
163 if (test & MUSB_TEST_FORCE_HOST)
164 seq_printf(s, "force host\n");
165
166 if (test & MUSB_TEST_FIFO_ACCESS)
167 seq_printf(s, "fifo access\n");
168
169 if (test & MUSB_TEST_FORCE_FS)
170 seq_printf(s, "force full-speed\n");
171
172 if (test & MUSB_TEST_FORCE_HS)
173 seq_printf(s, "force high-speed\n");
174
175 if (test & MUSB_TEST_PACKET)
176 seq_printf(s, "test packet\n");
177
178 if (test & MUSB_TEST_K)
179 seq_printf(s, "test K\n");
180
181 if (test & MUSB_TEST_J)
182 seq_printf(s, "test J\n");
183
184 if (test & MUSB_TEST_SE0_NAK)
185 seq_printf(s, "test SE0 NAK\n");
186
187 return 0;
188}
189
190static const struct file_operations musb_regdump_fops = {
191 .open = musb_regdump_open,
192 .read = seq_read,
193 .llseek = seq_lseek,
194 .release = single_release,
195};
196
197static int musb_test_mode_open(struct inode *inode, struct file *file)
198{
199 file->private_data = inode->i_private;
200
201 return single_open(file, musb_test_mode_show, inode->i_private);
202}
203
204static ssize_t musb_test_mode_write(struct file *file,
205 const char __user *ubuf, size_t count, loff_t *ppos)
206{
207 struct musb *musb = file->private_data;
208 u8 test = 0;
209 char buf[18];
210
211 memset(buf, 0x00, sizeof(buf));
212
213 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
214 return -EFAULT;
215
216 if (!strncmp(buf, "force host", 9))
217 test = MUSB_TEST_FORCE_HOST;
218
219 if (!strncmp(buf, "fifo access", 11))
220 test = MUSB_TEST_FIFO_ACCESS;
221
222 if (!strncmp(buf, "force full-speed", 15))
223 test = MUSB_TEST_FORCE_FS;
224
225 if (!strncmp(buf, "force high-speed", 15))
226 test = MUSB_TEST_FORCE_HS;
227
228 if (!strncmp(buf, "test packet", 10)) {
229 test = MUSB_TEST_PACKET;
230 musb_load_testpacket(musb);
231 }
232
233 if (!strncmp(buf, "test K", 6))
234 test = MUSB_TEST_K;
235
236 if (!strncmp(buf, "test J", 6))
237 test = MUSB_TEST_J;
238
239 if (!strncmp(buf, "test SE0 NAK", 12))
240 test = MUSB_TEST_SE0_NAK;
241
242 musb_writeb(musb->mregs, MUSB_TESTMODE, test);
243
244 return count;
245}
246
247static const struct file_operations musb_test_mode_fops = {
248 .open = musb_test_mode_open,
249 .write = musb_test_mode_write,
250 .read = seq_read,
251 .llseek = seq_lseek,
252 .release = single_release,
253};
254
255int __init musb_init_debugfs(struct musb *musb)
256{
257 struct dentry *root;
258 struct dentry *file;
259 int ret;
260
261 root = debugfs_create_dir("musb", NULL);
262 if (IS_ERR(root)) {
263 ret = PTR_ERR(root);
264 goto err0;
265 }
266
267 file = debugfs_create_file("regdump", S_IRUGO, root, musb,
268 &musb_regdump_fops);
269 if (IS_ERR(file)) {
270 ret = PTR_ERR(file);
271 goto err1;
272 }
273
274 file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR,
275 root, musb, &musb_test_mode_fops);
276 if (IS_ERR(file)) {
277 ret = PTR_ERR(file);
278 goto err1;
279 }
280
281 musb_debugfs_root = root;
282
283 return 0;
284
285err1:
286 debugfs_remove_recursive(root);
287
288err0:
289 return ret;
290}
291
292void __exit musb_exit_debugfs(struct musb *musb)
293{
294 debugfs_remove_recursive(musb_debugfs_root);
295}