root/drivers/usb/musb/musb_debugfs.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. musb_regdump_show
  2. musb_test_mode_show
  3. musb_test_mode_open
  4. musb_test_mode_write
  5. musb_softconnect_show
  6. musb_softconnect_open
  7. musb_softconnect_write
  8. musb_init_debugfs
  9. musb_exit_debugfs

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * MUSB OTG driver debugfs support
   4  *
   5  * Copyright 2010 Nokia Corporation
   6  * Contact: Felipe Balbi <felipe.balbi@nokia.com>
   7  */
   8 
   9 #include <linux/module.h>
  10 #include <linux/kernel.h>
  11 #include <linux/init.h>
  12 #include <linux/debugfs.h>
  13 #include <linux/seq_file.h>
  14 
  15 #include <linux/uaccess.h>
  16 
  17 #include "musb_core.h"
  18 #include "musb_debug.h"
  19 
  20 struct musb_register_map {
  21         char                    *name;
  22         unsigned                offset;
  23         unsigned                size;
  24 };
  25 
  26 static const struct musb_register_map musb_regmap[] = {
  27         { "FAddr",      MUSB_FADDR,     8 },
  28         { "Power",      MUSB_POWER,     8 },
  29         { "Frame",      MUSB_FRAME,     16 },
  30         { "Index",      MUSB_INDEX,     8 },
  31         { "Testmode",   MUSB_TESTMODE,  8 },
  32         { "TxMaxPp",    MUSB_TXMAXP,    16 },
  33         { "TxCSRp",     MUSB_TXCSR,     16 },
  34         { "RxMaxPp",    MUSB_RXMAXP,    16 },
  35         { "RxCSR",      MUSB_RXCSR,     16 },
  36         { "RxCount",    MUSB_RXCOUNT,   16 },
  37         { "IntrRxE",    MUSB_INTRRXE,   16 },
  38         { "IntrTxE",    MUSB_INTRTXE,   16 },
  39         { "IntrUsbE",   MUSB_INTRUSBE,  8 },
  40         { "DevCtl",     MUSB_DEVCTL,    8 },
  41         { "VControl",   0x68,           32 },
  42         { "HWVers",     0x69,           16 },
  43         { "LinkInfo",   MUSB_LINKINFO,  8 },
  44         { "VPLen",      MUSB_VPLEN,     8 },
  45         { "HS_EOF1",    MUSB_HS_EOF1,   8 },
  46         { "FS_EOF1",    MUSB_FS_EOF1,   8 },
  47         { "LS_EOF1",    MUSB_LS_EOF1,   8 },
  48         { "SOFT_RST",   0x7F,           8 },
  49         { "DMA_CNTLch0",        0x204,  16 },
  50         { "DMA_ADDRch0",        0x208,  32 },
  51         { "DMA_COUNTch0",       0x20C,  32 },
  52         { "DMA_CNTLch1",        0x214,  16 },
  53         { "DMA_ADDRch1",        0x218,  32 },
  54         { "DMA_COUNTch1",       0x21C,  32 },
  55         { "DMA_CNTLch2",        0x224,  16 },
  56         { "DMA_ADDRch2",        0x228,  32 },
  57         { "DMA_COUNTch2",       0x22C,  32 },
  58         { "DMA_CNTLch3",        0x234,  16 },
  59         { "DMA_ADDRch3",        0x238,  32 },
  60         { "DMA_COUNTch3",       0x23C,  32 },
  61         { "DMA_CNTLch4",        0x244,  16 },
  62         { "DMA_ADDRch4",        0x248,  32 },
  63         { "DMA_COUNTch4",       0x24C,  32 },
  64         { "DMA_CNTLch5",        0x254,  16 },
  65         { "DMA_ADDRch5",        0x258,  32 },
  66         { "DMA_COUNTch5",       0x25C,  32 },
  67         { "DMA_CNTLch6",        0x264,  16 },
  68         { "DMA_ADDRch6",        0x268,  32 },
  69         { "DMA_COUNTch6",       0x26C,  32 },
  70         { "DMA_CNTLch7",        0x274,  16 },
  71         { "DMA_ADDRch7",        0x278,  32 },
  72         { "DMA_COUNTch7",       0x27C,  32 },
  73         { "ConfigData", MUSB_CONFIGDATA,8 },
  74         { "BabbleCtl",  MUSB_BABBLE_CTL,8 },
  75         { "TxFIFOsz",   MUSB_TXFIFOSZ,  8 },
  76         { "RxFIFOsz",   MUSB_RXFIFOSZ,  8 },
  77         { "TxFIFOadd",  MUSB_TXFIFOADD, 16 },
  78         { "RxFIFOadd",  MUSB_RXFIFOADD, 16 },
  79         { "EPInfo",     MUSB_EPINFO,    8 },
  80         { "RAMInfo",    MUSB_RAMINFO,   8 },
  81         {  }    /* Terminating Entry */
  82 };
  83 
  84 static int musb_regdump_show(struct seq_file *s, void *unused)
  85 {
  86         struct musb             *musb = s->private;
  87         unsigned                i;
  88 
  89         seq_printf(s, "MUSB (M)HDRC Register Dump\n");
  90         pm_runtime_get_sync(musb->controller);
  91 
  92         for (i = 0; i < ARRAY_SIZE(musb_regmap); i++) {
  93                 switch (musb_regmap[i].size) {
  94                 case 8:
  95                         seq_printf(s, "%-12s: %02x\n", musb_regmap[i].name,
  96                                         musb_readb(musb->mregs, musb_regmap[i].offset));
  97                         break;
  98                 case 16:
  99                         seq_printf(s, "%-12s: %04x\n", musb_regmap[i].name,
 100                                         musb_readw(musb->mregs, musb_regmap[i].offset));
 101                         break;
 102                 case 32:
 103                         seq_printf(s, "%-12s: %08x\n", musb_regmap[i].name,
 104                                         musb_readl(musb->mregs, musb_regmap[i].offset));
 105                         break;
 106                 }
 107         }
 108 
 109         pm_runtime_mark_last_busy(musb->controller);
 110         pm_runtime_put_autosuspend(musb->controller);
 111         return 0;
 112 }
 113 DEFINE_SHOW_ATTRIBUTE(musb_regdump);
 114 
 115 static int musb_test_mode_show(struct seq_file *s, void *unused)
 116 {
 117         struct musb             *musb = s->private;
 118         unsigned                test;
 119 
 120         pm_runtime_get_sync(musb->controller);
 121         test = musb_readb(musb->mregs, MUSB_TESTMODE);
 122         pm_runtime_mark_last_busy(musb->controller);
 123         pm_runtime_put_autosuspend(musb->controller);
 124 
 125         if (test == (MUSB_TEST_FORCE_HOST | MUSB_TEST_FORCE_FS))
 126                 seq_printf(s, "force host full-speed\n");
 127 
 128         else if (test == (MUSB_TEST_FORCE_HOST | MUSB_TEST_FORCE_HS))
 129                 seq_printf(s, "force host high-speed\n");
 130 
 131         else if (test == MUSB_TEST_FORCE_HOST)
 132                 seq_printf(s, "force host\n");
 133 
 134         else if (test == MUSB_TEST_FIFO_ACCESS)
 135                 seq_printf(s, "fifo access\n");
 136 
 137         else if (test == MUSB_TEST_FORCE_FS)
 138                 seq_printf(s, "force full-speed\n");
 139 
 140         else if (test == MUSB_TEST_FORCE_HS)
 141                 seq_printf(s, "force high-speed\n");
 142 
 143         else if (test == MUSB_TEST_PACKET)
 144                 seq_printf(s, "test packet\n");
 145 
 146         else if (test == MUSB_TEST_K)
 147                 seq_printf(s, "test K\n");
 148 
 149         else if (test == MUSB_TEST_J)
 150                 seq_printf(s, "test J\n");
 151 
 152         else if (test == MUSB_TEST_SE0_NAK)
 153                 seq_printf(s, "test SE0 NAK\n");
 154 
 155         return 0;
 156 }
 157 
 158 static int musb_test_mode_open(struct inode *inode, struct file *file)
 159 {
 160         return single_open(file, musb_test_mode_show, inode->i_private);
 161 }
 162 
 163 static ssize_t musb_test_mode_write(struct file *file,
 164                 const char __user *ubuf, size_t count, loff_t *ppos)
 165 {
 166         struct seq_file         *s = file->private_data;
 167         struct musb             *musb = s->private;
 168         u8                      test;
 169         char                    buf[24];
 170 
 171         memset(buf, 0x00, sizeof(buf));
 172 
 173         if (copy_from_user(buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
 174                 return -EFAULT;
 175 
 176         pm_runtime_get_sync(musb->controller);
 177         test = musb_readb(musb->mregs, MUSB_TESTMODE);
 178         if (test) {
 179                 dev_err(musb->controller, "Error: test mode is already set. "
 180                         "Please do USB Bus Reset to start a new test.\n");
 181                 goto ret;
 182         }
 183 
 184         if (strstarts(buf, "force host full-speed"))
 185                 test = MUSB_TEST_FORCE_HOST | MUSB_TEST_FORCE_FS;
 186 
 187         else if (strstarts(buf, "force host high-speed"))
 188                 test = MUSB_TEST_FORCE_HOST | MUSB_TEST_FORCE_HS;
 189 
 190         else if (strstarts(buf, "force host"))
 191                 test = MUSB_TEST_FORCE_HOST;
 192 
 193         else if (strstarts(buf, "fifo access"))
 194                 test = MUSB_TEST_FIFO_ACCESS;
 195 
 196         else if (strstarts(buf, "force full-speed"))
 197                 test = MUSB_TEST_FORCE_FS;
 198 
 199         else if (strstarts(buf, "force high-speed"))
 200                 test = MUSB_TEST_FORCE_HS;
 201 
 202         else if (strstarts(buf, "test packet")) {
 203                 test = MUSB_TEST_PACKET;
 204                 musb_load_testpacket(musb);
 205         }
 206 
 207         else if (strstarts(buf, "test K"))
 208                 test = MUSB_TEST_K;
 209 
 210         else if (strstarts(buf, "test J"))
 211                 test = MUSB_TEST_J;
 212 
 213         else if (strstarts(buf, "test SE0 NAK"))
 214                 test = MUSB_TEST_SE0_NAK;
 215 
 216         musb_writeb(musb->mregs, MUSB_TESTMODE, test);
 217 
 218 ret:
 219         pm_runtime_mark_last_busy(musb->controller);
 220         pm_runtime_put_autosuspend(musb->controller);
 221         return count;
 222 }
 223 
 224 static const struct file_operations musb_test_mode_fops = {
 225         .open                   = musb_test_mode_open,
 226         .write                  = musb_test_mode_write,
 227         .read                   = seq_read,
 228         .llseek                 = seq_lseek,
 229         .release                = single_release,
 230 };
 231 
 232 static int musb_softconnect_show(struct seq_file *s, void *unused)
 233 {
 234         struct musb     *musb = s->private;
 235         u8              reg;
 236         int             connect;
 237 
 238         switch (musb->xceiv->otg->state) {
 239         case OTG_STATE_A_HOST:
 240         case OTG_STATE_A_WAIT_BCON:
 241                 pm_runtime_get_sync(musb->controller);
 242 
 243                 reg = musb_readb(musb->mregs, MUSB_DEVCTL);
 244                 connect = reg & MUSB_DEVCTL_SESSION ? 1 : 0;
 245 
 246                 pm_runtime_mark_last_busy(musb->controller);
 247                 pm_runtime_put_autosuspend(musb->controller);
 248                 break;
 249         default:
 250                 connect = -1;
 251         }
 252 
 253         seq_printf(s, "%d\n", connect);
 254 
 255         return 0;
 256 }
 257 
 258 static int musb_softconnect_open(struct inode *inode, struct file *file)
 259 {
 260         return single_open(file, musb_softconnect_show, inode->i_private);
 261 }
 262 
 263 static ssize_t musb_softconnect_write(struct file *file,
 264                 const char __user *ubuf, size_t count, loff_t *ppos)
 265 {
 266         struct seq_file         *s = file->private_data;
 267         struct musb             *musb = s->private;
 268         char                    buf[2];
 269         u8                      reg;
 270 
 271         memset(buf, 0x00, sizeof(buf));
 272 
 273         if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
 274                 return -EFAULT;
 275 
 276         pm_runtime_get_sync(musb->controller);
 277         if (!strncmp(buf, "0", 1)) {
 278                 switch (musb->xceiv->otg->state) {
 279                 case OTG_STATE_A_HOST:
 280                         musb_root_disconnect(musb);
 281                         reg = musb_readb(musb->mregs, MUSB_DEVCTL);
 282                         reg &= ~MUSB_DEVCTL_SESSION;
 283                         musb_writeb(musb->mregs, MUSB_DEVCTL, reg);
 284                         break;
 285                 default:
 286                         break;
 287                 }
 288         } else if (!strncmp(buf, "1", 1)) {
 289                 switch (musb->xceiv->otg->state) {
 290                 case OTG_STATE_A_WAIT_BCON:
 291                         /*
 292                          * musb_save_context() called in musb_runtime_suspend()
 293                          * might cache devctl with SESSION bit cleared during
 294                          * soft-disconnect, so specifically set SESSION bit
 295                          * here to preserve it for musb_runtime_resume().
 296                          */
 297                         musb->context.devctl |= MUSB_DEVCTL_SESSION;
 298                         reg = musb_readb(musb->mregs, MUSB_DEVCTL);
 299                         reg |= MUSB_DEVCTL_SESSION;
 300                         musb_writeb(musb->mregs, MUSB_DEVCTL, reg);
 301                         break;
 302                 default:
 303                         break;
 304                 }
 305         }
 306 
 307         pm_runtime_mark_last_busy(musb->controller);
 308         pm_runtime_put_autosuspend(musb->controller);
 309         return count;
 310 }
 311 
 312 /*
 313  * In host mode, connect/disconnect the bus without physically
 314  * remove the devices.
 315  */
 316 static const struct file_operations musb_softconnect_fops = {
 317         .open                   = musb_softconnect_open,
 318         .write                  = musb_softconnect_write,
 319         .read                   = seq_read,
 320         .llseek                 = seq_lseek,
 321         .release                = single_release,
 322 };
 323 
 324 void musb_init_debugfs(struct musb *musb)
 325 {
 326         struct dentry *root;
 327 
 328         root = debugfs_create_dir(dev_name(musb->controller), NULL);
 329         musb->debugfs_root = root;
 330 
 331         debugfs_create_file("regdump", S_IRUGO, root, musb, &musb_regdump_fops);
 332         debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root, musb,
 333                             &musb_test_mode_fops);
 334         debugfs_create_file("softconnect", S_IRUGO | S_IWUSR, root, musb,
 335                             &musb_softconnect_fops);
 336 }
 337 
 338 void /* __init_or_exit */ musb_exit_debugfs(struct musb *musb)
 339 {
 340         debugfs_remove_recursive(musb->debugfs_root);
 341 }

/* [<][>][^][v][top][bottom][index][help] */