Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/usb/musb/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 8 kB image not shown  

Quelle  musb_debugfs.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 * MUSB OTG driver debugfs support
 *
 * Copyright 2010 Nokia Corporation
 * Contact: Felipe Balbi <felipe.balbi@nokia.com>
 */


#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>

#include <linux/uaccess.h>

#include "musb_core.h"
#include "musb_debug.h"

struct musb_register_map {
 char   *name;
 unsigned  offset;
 unsigned  size;
};

static const struct musb_register_map musb_regmap[] = {
 { "FAddr", MUSB_FADDR, 8 },
 { "Power", MUSB_POWER, 8 },
 { "Frame", MUSB_FRAME, 16 },
 { "Index", MUSB_INDEX, 8 },
 { "Testmode", MUSB_TESTMODE, 8 },
 { "TxMaxPp", MUSB_TXMAXP, 16 },
 { "TxCSRp", MUSB_TXCSR, 16 },
 { "RxMaxPp", MUSB_RXMAXP, 16 },
 { "RxCSR", MUSB_RXCSR, 16 },
 { "RxCount", MUSB_RXCOUNT, 16 },
 { "IntrRxE", MUSB_INTRRXE, 16 },
 { "IntrTxE", MUSB_INTRTXE, 16 },
 { "IntrUsbE", MUSB_INTRUSBE, 8 },
 { "DevCtl", MUSB_DEVCTL, 8 },
 { "VControl", 0x68,  32 },
 { "HWVers", MUSB_HWVERS, 16 },
 { "LinkInfo", MUSB_LINKINFO, 8 },
 { "VPLen", MUSB_VPLEN, 8 },
 { "HS_EOF1", MUSB_HS_EOF1, 8 },
 { "FS_EOF1", MUSB_FS_EOF1, 8 },
 { "LS_EOF1", MUSB_LS_EOF1, 8 },
 { "SOFT_RST", 0x7F,  8 },
 { "DMA_CNTLch0", 0x204, 16 },
 { "DMA_ADDRch0", 0x208, 32 },
 { "DMA_COUNTch0", 0x20C, 32 },
 { "DMA_CNTLch1", 0x214, 16 },
 { "DMA_ADDRch1", 0x218, 32 },
 { "DMA_COUNTch1", 0x21C, 32 },
 { "DMA_CNTLch2", 0x224, 16 },
 { "DMA_ADDRch2", 0x228, 32 },
 { "DMA_COUNTch2", 0x22C, 32 },
 { "DMA_CNTLch3", 0x234, 16 },
 { "DMA_ADDRch3", 0x238, 32 },
 { "DMA_COUNTch3", 0x23C, 32 },
 { "DMA_CNTLch4", 0x244, 16 },
 { "DMA_ADDRch4", 0x248, 32 },
 { "DMA_COUNTch4", 0x24C, 32 },
 { "DMA_CNTLch5", 0x254, 16 },
 { "DMA_ADDRch5", 0x258, 32 },
 { "DMA_COUNTch5", 0x25C, 32 },
 { "DMA_CNTLch6", 0x264, 16 },
 { "DMA_ADDRch6", 0x268, 32 },
 { "DMA_COUNTch6", 0x26C, 32 },
 { "DMA_CNTLch7", 0x274, 16 },
 { "DMA_ADDRch7", 0x278, 32 },
 { "DMA_COUNTch7", 0x27C, 32 },
 { "ConfigData", MUSB_CONFIGDATA,8 },
 { "BabbleCtl", MUSB_BABBLE_CTL,8 },
 { "TxFIFOsz", MUSB_TXFIFOSZ, 8 },
 { "RxFIFOsz", MUSB_RXFIFOSZ, 8 },
 { "TxFIFOadd", MUSB_TXFIFOADD, 16 },
 { "RxFIFOadd", MUSB_RXFIFOADD, 16 },
 { "EPInfo", MUSB_EPINFO, 8 },
 { "RAMInfo", MUSB_RAMINFO, 8 },
 {  } /* Terminating Entry */
};

static int musb_regdump_show(struct seq_file *s, void *unused)
{
 struct musb  *musb = s->private;
 unsigned  i;

 seq_printf(s, "MUSB (M)HDRC Register Dump\n");
 pm_runtime_get_sync(musb->controller);

 for (i = 0; i < ARRAY_SIZE(musb_regmap); i++) {
  switch (musb_regmap[i].size) {
  case 8:
   seq_printf(s, "%-12s: %02x\n", musb_regmap[i].name,
     musb_readb(musb->mregs, musb_regmap[i].offset));
   break;
  case 16:
   seq_printf(s, "%-12s: %04x\n", musb_regmap[i].name,
     musb_readw(musb->mregs, musb_regmap[i].offset));
   break;
  case 32:
   seq_printf(s, "%-12s: %08x\n", musb_regmap[i].name,
     musb_readl(musb->mregs, musb_regmap[i].offset));
   break;
  }
 }

 pm_runtime_mark_last_busy(musb->controller);
 pm_runtime_put_autosuspend(musb->controller);
 return 0;
}
DEFINE_SHOW_ATTRIBUTE(musb_regdump);

static int musb_test_mode_show(struct seq_file *s, void *unused)
{
 struct musb  *musb = s->private;
 unsigned  test;

 pm_runtime_get_sync(musb->controller);
 test = musb_readb(musb->mregs, MUSB_TESTMODE);
 pm_runtime_mark_last_busy(musb->controller);
 pm_runtime_put_autosuspend(musb->controller);

 if (test == (MUSB_TEST_FORCE_HOST | MUSB_TEST_FORCE_FS))
  seq_printf(s, "force host full-speed\n");

 else if (test == (MUSB_TEST_FORCE_HOST | MUSB_TEST_FORCE_HS))
  seq_printf(s, "force host high-speed\n");

 else if (test == MUSB_TEST_FORCE_HOST)
  seq_printf(s, "force host\n");

 else if (test == MUSB_TEST_FIFO_ACCESS)
  seq_printf(s, "fifo access\n");

 else if (test == MUSB_TEST_FORCE_FS)
  seq_printf(s, "force full-speed\n");

 else if (test == MUSB_TEST_FORCE_HS)
  seq_printf(s, "force high-speed\n");

 else if (test == MUSB_TEST_PACKET)
  seq_printf(s, "test packet\n");

 else if (test == MUSB_TEST_K)
  seq_printf(s, "test K\n");

 else if (test == MUSB_TEST_J)
  seq_printf(s, "test J\n");

 else if (test == MUSB_TEST_SE0_NAK)
  seq_printf(s, "test SE0 NAK\n");

 return 0;
}

static int musb_test_mode_open(struct inode *inode, struct file *file)
{
 return single_open(file, musb_test_mode_show, inode->i_private);
}

static ssize_t musb_test_mode_write(struct file *file,
  const char __user *ubuf, size_t count, loff_t *ppos)
{
 struct seq_file  *s = file->private_data;
 struct musb  *musb = s->private;
 u8   test;
 char   buf[24];

 memset(buf, 0x00, sizeof(buf));

 if (copy_from_user(buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
  return -EFAULT;

 pm_runtime_get_sync(musb->controller);
 test = musb_readb(musb->mregs, MUSB_TESTMODE);
 if (test) {
  dev_err(musb->controller, "Error: test mode is already set. "
   "Please do USB Bus Reset to start a new test.\n");
  goto ret;
 }

 if (strstarts(buf, "force host full-speed"))
  test = MUSB_TEST_FORCE_HOST | MUSB_TEST_FORCE_FS;

 else if (strstarts(buf, "force host high-speed"))
  test = MUSB_TEST_FORCE_HOST | MUSB_TEST_FORCE_HS;

 else if (strstarts(buf, "force host"))
  test = MUSB_TEST_FORCE_HOST;

 else if (strstarts(buf, "fifo access"))
  test = MUSB_TEST_FIFO_ACCESS;

 else if (strstarts(buf, "force full-speed"))
  test = MUSB_TEST_FORCE_FS;

 else if (strstarts(buf, "force high-speed"))
  test = MUSB_TEST_FORCE_HS;

 else if (strstarts(buf, "test packet")) {
  test = MUSB_TEST_PACKET;
  musb_load_testpacket(musb);
 }

 else if (strstarts(buf, "test K"))
  test = MUSB_TEST_K;

 else if (strstarts(buf, "test J"))
  test = MUSB_TEST_J;

 else if (strstarts(buf, "test SE0 NAK"))
  test = MUSB_TEST_SE0_NAK;

 musb_writeb(musb->mregs, MUSB_TESTMODE, test);

ret:
 pm_runtime_mark_last_busy(musb->controller);
 pm_runtime_put_autosuspend(musb->controller);
 return count;
}

static const struct file_operations musb_test_mode_fops = {
 .open   = musb_test_mode_open,
 .write   = musb_test_mode_write,
 .read   = seq_read,
 .llseek   = seq_lseek,
 .release  = single_release,
};

static int musb_softconnect_show(struct seq_file *s, void *unused)
{
 struct musb *musb = s->private;
 u8  reg;
 int  connect;

 switch (musb_get_state(musb)) {
 case OTG_STATE_A_HOST:
 case OTG_STATE_A_WAIT_BCON:
  pm_runtime_get_sync(musb->controller);

  reg = musb_readb(musb->mregs, MUSB_DEVCTL);
  connect = reg & MUSB_DEVCTL_SESSION ? 1 : 0;

  pm_runtime_mark_last_busy(musb->controller);
  pm_runtime_put_autosuspend(musb->controller);
  break;
 default:
  connect = -1;
 }

 seq_printf(s, "%d\n", connect);

 return 0;
}

static int musb_softconnect_open(struct inode *inode, struct file *file)
{
 return single_open(file, musb_softconnect_show, inode->i_private);
}

static ssize_t musb_softconnect_write(struct file *file,
  const char __user *ubuf, size_t count, loff_t *ppos)
{
 struct seq_file  *s = file->private_data;
 struct musb  *musb = s->private;
 char   buf[2];
 u8   reg;

 memset(buf, 0x00, sizeof(buf));

 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
  return -EFAULT;

 pm_runtime_get_sync(musb->controller);
 if (!strncmp(buf, "0", 1)) {
  switch (musb_get_state(musb)) {
  case OTG_STATE_A_HOST:
   musb_root_disconnect(musb);
   reg = musb_readb(musb->mregs, MUSB_DEVCTL);
   reg &= ~MUSB_DEVCTL_SESSION;
   musb_writeb(musb->mregs, MUSB_DEVCTL, reg);
   break;
  default:
   break;
  }
 } else if (!strncmp(buf, "1", 1)) {
  switch (musb_get_state(musb)) {
  case OTG_STATE_A_WAIT_BCON:
   /*
 * musb_save_context() called in musb_runtime_suspend()
 * might cache devctl with SESSION bit cleared during
 * soft-disconnect, so specifically set SESSION bit
 * here to preserve it for musb_runtime_resume().
 */

   musb->context.devctl |= MUSB_DEVCTL_SESSION;
   reg = musb_readb(musb->mregs, MUSB_DEVCTL);
   reg |= MUSB_DEVCTL_SESSION;
   musb_writeb(musb->mregs, MUSB_DEVCTL, reg);
   break;
  default:
   break;
  }
 }

 pm_runtime_mark_last_busy(musb->controller);
 pm_runtime_put_autosuspend(musb->controller);
 return count;
}

/*
 * In host mode, connect/disconnect the bus without physically
 * remove the devices.
 */

static const struct file_operations musb_softconnect_fops = {
 .open   = musb_softconnect_open,
 .write   = musb_softconnect_write,
 .read   = seq_read,
 .llseek   = seq_lseek,
 .release  = single_release,
};

void musb_init_debugfs(struct musb *musb)
{
 struct dentry *root;

 root = debugfs_create_dir(dev_name(musb->controller), usb_debug_root);
 musb->debugfs_root = root;

 debugfs_create_file("regdump", S_IRUGO, root, musb, &musb_regdump_fops);
 debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root, musb,
       &musb_test_mode_fops);
 debugfs_create_file("softconnect", S_IRUGO | S_IWUSR, root, musb,
       &musb_softconnect_fops);
}

void /* __init_or_exit */ musb_exit_debugfs(struct musb *musb)
{
 debugfs_remove_recursive(musb->debugfs_root);
}

Messung V0.5
C=91 H=97 G=93

¤ Dauer der Verarbeitung: 0.3 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.