linux/drivers/usb/musb/musb_debugfs.c
<<
>>
Prefs
   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/init.h>
  37#include <linux/debugfs.h>
  38#include <linux/seq_file.h>
  39
  40#include <asm/uaccess.h>
  41
  42#include "musb_core.h"
  43#include "musb_debug.h"
  44
  45struct musb_register_map {
  46        char                    *name;
  47        unsigned                offset;
  48        unsigned                size;
  49};
  50
  51static const struct musb_register_map musb_regmap[] = {
  52        { "FAddr",              0x00,   8 },
  53        { "Power",              0x01,   8 },
  54        { "Frame",              0x0c,   16 },
  55        { "Index",              0x0e,   8 },
  56        { "Testmode",           0x0f,   8 },
  57        { "TxMaxPp",            0x10,   16 },
  58        { "TxCSRp",             0x12,   16 },
  59        { "RxMaxPp",            0x14,   16 },
  60        { "RxCSR",              0x16,   16 },
  61        { "RxCount",            0x18,   16 },
  62        { "ConfigData",         0x1f,   8 },
  63        { "DevCtl",             0x60,   8 },
  64        { "MISC",               0x61,   8 },
  65        { "TxFIFOsz",           0x62,   8 },
  66        { "RxFIFOsz",           0x63,   8 },
  67        { "TxFIFOadd",          0x64,   16 },
  68        { "RxFIFOadd",          0x66,   16 },
  69        { "VControl",           0x68,   32 },
  70        { "HWVers",             0x6C,   16 },
  71        { "EPInfo",             0x78,   8 },
  72        { "RAMInfo",            0x79,   8 },
  73        { "LinkInfo",           0x7A,   8 },
  74        { "VPLen",              0x7B,   8 },
  75        { "HS_EOF1",            0x7C,   8 },
  76        { "FS_EOF1",            0x7D,   8 },
  77        { "LS_EOF1",            0x7E,   8 },
  78        { "SOFT_RST",           0x7F,   8 },
  79        { "DMA_CNTLch0",        0x204,  16 },
  80        { "DMA_ADDRch0",        0x208,  32 },
  81        { "DMA_COUNTch0",       0x20C,  32 },
  82        { "DMA_CNTLch1",        0x214,  16 },
  83        { "DMA_ADDRch1",        0x218,  32 },
  84        { "DMA_COUNTch1",       0x21C,  32 },
  85        { "DMA_CNTLch2",        0x224,  16 },
  86        { "DMA_ADDRch2",        0x228,  32 },
  87        { "DMA_COUNTch2",       0x22C,  32 },
  88        { "DMA_CNTLch3",        0x234,  16 },
  89        { "DMA_ADDRch3",        0x238,  32 },
  90        { "DMA_COUNTch3",       0x23C,  32 },
  91        { "DMA_CNTLch4",        0x244,  16 },
  92        { "DMA_ADDRch4",        0x248,  32 },
  93        { "DMA_COUNTch4",       0x24C,  32 },
  94        { "DMA_CNTLch5",        0x254,  16 },
  95        { "DMA_ADDRch5",        0x258,  32 },
  96        { "DMA_COUNTch5",       0x25C,  32 },
  97        { "DMA_CNTLch6",        0x264,  16 },
  98        { "DMA_ADDRch6",        0x268,  32 },
  99        { "DMA_COUNTch6",       0x26C,  32 },
 100        { "DMA_CNTLch7",        0x274,  16 },
 101        { "DMA_ADDRch7",        0x278,  32 },
 102        { "DMA_COUNTch7",       0x27C,  32 },
 103        {  }    /* Terminating Entry */
 104};
 105
 106static int musb_regdump_show(struct seq_file *s, void *unused)
 107{
 108        struct musb             *musb = s->private;
 109        unsigned                i;
 110
 111        seq_printf(s, "MUSB (M)HDRC Register Dump\n");
 112
 113        for (i = 0; i < ARRAY_SIZE(musb_regmap); i++) {
 114                switch (musb_regmap[i].size) {
 115                case 8:
 116                        seq_printf(s, "%-12s: %02x\n", musb_regmap[i].name,
 117                                        musb_readb(musb->mregs, musb_regmap[i].offset));
 118                        break;
 119                case 16:
 120                        seq_printf(s, "%-12s: %04x\n", musb_regmap[i].name,
 121                                        musb_readw(musb->mregs, musb_regmap[i].offset));
 122                        break;
 123                case 32:
 124                        seq_printf(s, "%-12s: %08x\n", musb_regmap[i].name,
 125                                        musb_readl(musb->mregs, musb_regmap[i].offset));
 126                        break;
 127                }
 128        }
 129
 130        return 0;
 131}
 132
 133static int musb_regdump_open(struct inode *inode, struct file *file)
 134{
 135        return single_open(file, musb_regdump_show, inode->i_private);
 136}
 137
 138static int musb_test_mode_show(struct seq_file *s, void *unused)
 139{
 140        struct musb             *musb = s->private;
 141        unsigned                test;
 142
 143        test = musb_readb(musb->mregs, MUSB_TESTMODE);
 144
 145        if (test & MUSB_TEST_FORCE_HOST)
 146                seq_printf(s, "force host\n");
 147
 148        if (test & MUSB_TEST_FIFO_ACCESS)
 149                seq_printf(s, "fifo access\n");
 150
 151        if (test & MUSB_TEST_FORCE_FS)
 152                seq_printf(s, "force full-speed\n");
 153
 154        if (test & MUSB_TEST_FORCE_HS)
 155                seq_printf(s, "force high-speed\n");
 156
 157        if (test & MUSB_TEST_PACKET)
 158                seq_printf(s, "test packet\n");
 159
 160        if (test & MUSB_TEST_K)
 161                seq_printf(s, "test K\n");
 162
 163        if (test & MUSB_TEST_J)
 164                seq_printf(s, "test J\n");
 165
 166        if (test & MUSB_TEST_SE0_NAK)
 167                seq_printf(s, "test SE0 NAK\n");
 168
 169        return 0;
 170}
 171
 172static const struct file_operations musb_regdump_fops = {
 173        .open                   = musb_regdump_open,
 174        .read                   = seq_read,
 175        .llseek                 = seq_lseek,
 176        .release                = single_release,
 177};
 178
 179static int musb_test_mode_open(struct inode *inode, struct file *file)
 180{
 181        return single_open(file, musb_test_mode_show, inode->i_private);
 182}
 183
 184static ssize_t musb_test_mode_write(struct file *file,
 185                const char __user *ubuf, size_t count, loff_t *ppos)
 186{
 187        struct seq_file         *s = file->private_data;
 188        struct musb             *musb = s->private;
 189        u8                      test = 0;
 190        char                    buf[18];
 191
 192        memset(buf, 0x00, sizeof(buf));
 193
 194        if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
 195                return -EFAULT;
 196
 197        if (!strncmp(buf, "force host", 9))
 198                test = MUSB_TEST_FORCE_HOST;
 199
 200        if (!strncmp(buf, "fifo access", 11))
 201                test = MUSB_TEST_FIFO_ACCESS;
 202
 203        if (!strncmp(buf, "force full-speed", 15))
 204                test = MUSB_TEST_FORCE_FS;
 205
 206        if (!strncmp(buf, "force high-speed", 15))
 207                test = MUSB_TEST_FORCE_HS;
 208
 209        if (!strncmp(buf, "test packet", 10)) {
 210                test = MUSB_TEST_PACKET;
 211                musb_load_testpacket(musb);
 212        }
 213
 214        if (!strncmp(buf, "test K", 6))
 215                test = MUSB_TEST_K;
 216
 217        if (!strncmp(buf, "test J", 6))
 218                test = MUSB_TEST_J;
 219
 220        if (!strncmp(buf, "test SE0 NAK", 12))
 221                test = MUSB_TEST_SE0_NAK;
 222
 223        musb_writeb(musb->mregs, MUSB_TESTMODE, test);
 224
 225        return count;
 226}
 227
 228static const struct file_operations musb_test_mode_fops = {
 229        .open                   = musb_test_mode_open,
 230        .write                  = musb_test_mode_write,
 231        .read                   = seq_read,
 232        .llseek                 = seq_lseek,
 233        .release                = single_release,
 234};
 235
 236int musb_init_debugfs(struct musb *musb)
 237{
 238        struct dentry           *root;
 239        struct dentry           *file;
 240        int                     ret;
 241
 242        root = debugfs_create_dir(dev_name(musb->controller), NULL);
 243        if (!root) {
 244                ret = -ENOMEM;
 245                goto err0;
 246        }
 247
 248        file = debugfs_create_file("regdump", S_IRUGO, root, musb,
 249                        &musb_regdump_fops);
 250        if (!file) {
 251                ret = -ENOMEM;
 252                goto err1;
 253        }
 254
 255        file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR,
 256                        root, musb, &musb_test_mode_fops);
 257        if (!file) {
 258                ret = -ENOMEM;
 259                goto err1;
 260        }
 261
 262        musb->debugfs_root = root;
 263
 264        return 0;
 265
 266err1:
 267        debugfs_remove_recursive(root);
 268
 269err0:
 270        return ret;
 271}
 272
 273void /* __init_or_exit */ musb_exit_debugfs(struct musb *musb)
 274{
 275        debugfs_remove_recursive(musb->debugfs_root);
 276}
 277