0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/module.h>
0010 #include <linux/kernel.h>
0011 #include <linux/init.h>
0012 #include <linux/debugfs.h>
0013 #include <linux/seq_file.h>
0014
0015 #include <linux/uaccess.h>
0016
0017 #include "musb_core.h"
0018 #include "musb_debug.h"
0019
0020 struct musb_register_map {
0021 char *name;
0022 unsigned offset;
0023 unsigned size;
0024 };
0025
0026 static const struct musb_register_map musb_regmap[] = {
0027 { "FAddr", MUSB_FADDR, 8 },
0028 { "Power", MUSB_POWER, 8 },
0029 { "Frame", MUSB_FRAME, 16 },
0030 { "Index", MUSB_INDEX, 8 },
0031 { "Testmode", MUSB_TESTMODE, 8 },
0032 { "TxMaxPp", MUSB_TXMAXP, 16 },
0033 { "TxCSRp", MUSB_TXCSR, 16 },
0034 { "RxMaxPp", MUSB_RXMAXP, 16 },
0035 { "RxCSR", MUSB_RXCSR, 16 },
0036 { "RxCount", MUSB_RXCOUNT, 16 },
0037 { "IntrRxE", MUSB_INTRRXE, 16 },
0038 { "IntrTxE", MUSB_INTRTXE, 16 },
0039 { "IntrUsbE", MUSB_INTRUSBE, 8 },
0040 { "DevCtl", MUSB_DEVCTL, 8 },
0041 { "VControl", 0x68, 32 },
0042 { "HWVers", 0x69, 16 },
0043 { "LinkInfo", MUSB_LINKINFO, 8 },
0044 { "VPLen", MUSB_VPLEN, 8 },
0045 { "HS_EOF1", MUSB_HS_EOF1, 8 },
0046 { "FS_EOF1", MUSB_FS_EOF1, 8 },
0047 { "LS_EOF1", MUSB_LS_EOF1, 8 },
0048 { "SOFT_RST", 0x7F, 8 },
0049 { "DMA_CNTLch0", 0x204, 16 },
0050 { "DMA_ADDRch0", 0x208, 32 },
0051 { "DMA_COUNTch0", 0x20C, 32 },
0052 { "DMA_CNTLch1", 0x214, 16 },
0053 { "DMA_ADDRch1", 0x218, 32 },
0054 { "DMA_COUNTch1", 0x21C, 32 },
0055 { "DMA_CNTLch2", 0x224, 16 },
0056 { "DMA_ADDRch2", 0x228, 32 },
0057 { "DMA_COUNTch2", 0x22C, 32 },
0058 { "DMA_CNTLch3", 0x234, 16 },
0059 { "DMA_ADDRch3", 0x238, 32 },
0060 { "DMA_COUNTch3", 0x23C, 32 },
0061 { "DMA_CNTLch4", 0x244, 16 },
0062 { "DMA_ADDRch4", 0x248, 32 },
0063 { "DMA_COUNTch4", 0x24C, 32 },
0064 { "DMA_CNTLch5", 0x254, 16 },
0065 { "DMA_ADDRch5", 0x258, 32 },
0066 { "DMA_COUNTch5", 0x25C, 32 },
0067 { "DMA_CNTLch6", 0x264, 16 },
0068 { "DMA_ADDRch6", 0x268, 32 },
0069 { "DMA_COUNTch6", 0x26C, 32 },
0070 { "DMA_CNTLch7", 0x274, 16 },
0071 { "DMA_ADDRch7", 0x278, 32 },
0072 { "DMA_COUNTch7", 0x27C, 32 },
0073 { "ConfigData", MUSB_CONFIGDATA,8 },
0074 { "BabbleCtl", MUSB_BABBLE_CTL,8 },
0075 { "TxFIFOsz", MUSB_TXFIFOSZ, 8 },
0076 { "RxFIFOsz", MUSB_RXFIFOSZ, 8 },
0077 { "TxFIFOadd", MUSB_TXFIFOADD, 16 },
0078 { "RxFIFOadd", MUSB_RXFIFOADD, 16 },
0079 { "EPInfo", MUSB_EPINFO, 8 },
0080 { "RAMInfo", MUSB_RAMINFO, 8 },
0081 { }
0082 };
0083
0084 static int musb_regdump_show(struct seq_file *s, void *unused)
0085 {
0086 struct musb *musb = s->private;
0087 unsigned i;
0088
0089 seq_printf(s, "MUSB (M)HDRC Register Dump\n");
0090 pm_runtime_get_sync(musb->controller);
0091
0092 for (i = 0; i < ARRAY_SIZE(musb_regmap); i++) {
0093 switch (musb_regmap[i].size) {
0094 case 8:
0095 seq_printf(s, "%-12s: %02x\n", musb_regmap[i].name,
0096 musb_readb(musb->mregs, musb_regmap[i].offset));
0097 break;
0098 case 16:
0099 seq_printf(s, "%-12s: %04x\n", musb_regmap[i].name,
0100 musb_readw(musb->mregs, musb_regmap[i].offset));
0101 break;
0102 case 32:
0103 seq_printf(s, "%-12s: %08x\n", musb_regmap[i].name,
0104 musb_readl(musb->mregs, musb_regmap[i].offset));
0105 break;
0106 }
0107 }
0108
0109 pm_runtime_mark_last_busy(musb->controller);
0110 pm_runtime_put_autosuspend(musb->controller);
0111 return 0;
0112 }
0113 DEFINE_SHOW_ATTRIBUTE(musb_regdump);
0114
0115 static int musb_test_mode_show(struct seq_file *s, void *unused)
0116 {
0117 struct musb *musb = s->private;
0118 unsigned test;
0119
0120 pm_runtime_get_sync(musb->controller);
0121 test = musb_readb(musb->mregs, MUSB_TESTMODE);
0122 pm_runtime_mark_last_busy(musb->controller);
0123 pm_runtime_put_autosuspend(musb->controller);
0124
0125 if (test == (MUSB_TEST_FORCE_HOST | MUSB_TEST_FORCE_FS))
0126 seq_printf(s, "force host full-speed\n");
0127
0128 else if (test == (MUSB_TEST_FORCE_HOST | MUSB_TEST_FORCE_HS))
0129 seq_printf(s, "force host high-speed\n");
0130
0131 else if (test == MUSB_TEST_FORCE_HOST)
0132 seq_printf(s, "force host\n");
0133
0134 else if (test == MUSB_TEST_FIFO_ACCESS)
0135 seq_printf(s, "fifo access\n");
0136
0137 else if (test == MUSB_TEST_FORCE_FS)
0138 seq_printf(s, "force full-speed\n");
0139
0140 else if (test == MUSB_TEST_FORCE_HS)
0141 seq_printf(s, "force high-speed\n");
0142
0143 else if (test == MUSB_TEST_PACKET)
0144 seq_printf(s, "test packet\n");
0145
0146 else if (test == MUSB_TEST_K)
0147 seq_printf(s, "test K\n");
0148
0149 else if (test == MUSB_TEST_J)
0150 seq_printf(s, "test J\n");
0151
0152 else if (test == MUSB_TEST_SE0_NAK)
0153 seq_printf(s, "test SE0 NAK\n");
0154
0155 return 0;
0156 }
0157
0158 static int musb_test_mode_open(struct inode *inode, struct file *file)
0159 {
0160 return single_open(file, musb_test_mode_show, inode->i_private);
0161 }
0162
0163 static ssize_t musb_test_mode_write(struct file *file,
0164 const char __user *ubuf, size_t count, loff_t *ppos)
0165 {
0166 struct seq_file *s = file->private_data;
0167 struct musb *musb = s->private;
0168 u8 test;
0169 char buf[24];
0170
0171 memset(buf, 0x00, sizeof(buf));
0172
0173 if (copy_from_user(buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
0174 return -EFAULT;
0175
0176 pm_runtime_get_sync(musb->controller);
0177 test = musb_readb(musb->mregs, MUSB_TESTMODE);
0178 if (test) {
0179 dev_err(musb->controller, "Error: test mode is already set. "
0180 "Please do USB Bus Reset to start a new test.\n");
0181 goto ret;
0182 }
0183
0184 if (strstarts(buf, "force host full-speed"))
0185 test = MUSB_TEST_FORCE_HOST | MUSB_TEST_FORCE_FS;
0186
0187 else if (strstarts(buf, "force host high-speed"))
0188 test = MUSB_TEST_FORCE_HOST | MUSB_TEST_FORCE_HS;
0189
0190 else if (strstarts(buf, "force host"))
0191 test = MUSB_TEST_FORCE_HOST;
0192
0193 else if (strstarts(buf, "fifo access"))
0194 test = MUSB_TEST_FIFO_ACCESS;
0195
0196 else if (strstarts(buf, "force full-speed"))
0197 test = MUSB_TEST_FORCE_FS;
0198
0199 else if (strstarts(buf, "force high-speed"))
0200 test = MUSB_TEST_FORCE_HS;
0201
0202 else if (strstarts(buf, "test packet")) {
0203 test = MUSB_TEST_PACKET;
0204 musb_load_testpacket(musb);
0205 }
0206
0207 else if (strstarts(buf, "test K"))
0208 test = MUSB_TEST_K;
0209
0210 else if (strstarts(buf, "test J"))
0211 test = MUSB_TEST_J;
0212
0213 else if (strstarts(buf, "test SE0 NAK"))
0214 test = MUSB_TEST_SE0_NAK;
0215
0216 musb_writeb(musb->mregs, MUSB_TESTMODE, test);
0217
0218 ret:
0219 pm_runtime_mark_last_busy(musb->controller);
0220 pm_runtime_put_autosuspend(musb->controller);
0221 return count;
0222 }
0223
0224 static const struct file_operations musb_test_mode_fops = {
0225 .open = musb_test_mode_open,
0226 .write = musb_test_mode_write,
0227 .read = seq_read,
0228 .llseek = seq_lseek,
0229 .release = single_release,
0230 };
0231
0232 static int musb_softconnect_show(struct seq_file *s, void *unused)
0233 {
0234 struct musb *musb = s->private;
0235 u8 reg;
0236 int connect;
0237
0238 switch (musb->xceiv->otg->state) {
0239 case OTG_STATE_A_HOST:
0240 case OTG_STATE_A_WAIT_BCON:
0241 pm_runtime_get_sync(musb->controller);
0242
0243 reg = musb_readb(musb->mregs, MUSB_DEVCTL);
0244 connect = reg & MUSB_DEVCTL_SESSION ? 1 : 0;
0245
0246 pm_runtime_mark_last_busy(musb->controller);
0247 pm_runtime_put_autosuspend(musb->controller);
0248 break;
0249 default:
0250 connect = -1;
0251 }
0252
0253 seq_printf(s, "%d\n", connect);
0254
0255 return 0;
0256 }
0257
0258 static int musb_softconnect_open(struct inode *inode, struct file *file)
0259 {
0260 return single_open(file, musb_softconnect_show, inode->i_private);
0261 }
0262
0263 static ssize_t musb_softconnect_write(struct file *file,
0264 const char __user *ubuf, size_t count, loff_t *ppos)
0265 {
0266 struct seq_file *s = file->private_data;
0267 struct musb *musb = s->private;
0268 char buf[2];
0269 u8 reg;
0270
0271 memset(buf, 0x00, sizeof(buf));
0272
0273 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
0274 return -EFAULT;
0275
0276 pm_runtime_get_sync(musb->controller);
0277 if (!strncmp(buf, "0", 1)) {
0278 switch (musb->xceiv->otg->state) {
0279 case OTG_STATE_A_HOST:
0280 musb_root_disconnect(musb);
0281 reg = musb_readb(musb->mregs, MUSB_DEVCTL);
0282 reg &= ~MUSB_DEVCTL_SESSION;
0283 musb_writeb(musb->mregs, MUSB_DEVCTL, reg);
0284 break;
0285 default:
0286 break;
0287 }
0288 } else if (!strncmp(buf, "1", 1)) {
0289 switch (musb->xceiv->otg->state) {
0290 case OTG_STATE_A_WAIT_BCON:
0291
0292
0293
0294
0295
0296
0297 musb->context.devctl |= MUSB_DEVCTL_SESSION;
0298 reg = musb_readb(musb->mregs, MUSB_DEVCTL);
0299 reg |= MUSB_DEVCTL_SESSION;
0300 musb_writeb(musb->mregs, MUSB_DEVCTL, reg);
0301 break;
0302 default:
0303 break;
0304 }
0305 }
0306
0307 pm_runtime_mark_last_busy(musb->controller);
0308 pm_runtime_put_autosuspend(musb->controller);
0309 return count;
0310 }
0311
0312
0313
0314
0315
0316 static const struct file_operations musb_softconnect_fops = {
0317 .open = musb_softconnect_open,
0318 .write = musb_softconnect_write,
0319 .read = seq_read,
0320 .llseek = seq_lseek,
0321 .release = single_release,
0322 };
0323
0324 void musb_init_debugfs(struct musb *musb)
0325 {
0326 struct dentry *root;
0327
0328 root = debugfs_create_dir(dev_name(musb->controller), usb_debug_root);
0329 musb->debugfs_root = root;
0330
0331 debugfs_create_file("regdump", S_IRUGO, root, musb, &musb_regdump_fops);
0332 debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root, musb,
0333 &musb_test_mode_fops);
0334 debugfs_create_file("softconnect", S_IRUGO | S_IWUSR, root, musb,
0335 &musb_softconnect_fops);
0336 }
0337
0338 void musb_exit_debugfs(struct musb *musb)
0339 {
0340 debugfs_remove_recursive(musb->debugfs_root);
0341 }