forked from Minki/linux
USB: MXC: Add i.MX21 specific USB host controller driver.
This driver is a Full / Low speed only USB host for the i.MX21. Signed-off-by: Martin Fuzzey <mfuzzey@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
13dda80e48
commit
23d3e7a659
38
arch/arm/plat-mxc/include/mach/mx21-usbhost.h
Normal file
38
arch/arm/plat-mxc/include/mach/mx21-usbhost.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2009 Martin Fuzzey <mfuzzey@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __ASM_ARCH_MX21_USBH
|
||||
#define __ASM_ARCH_MX21_USBH
|
||||
|
||||
enum mx21_usbh_xcvr {
|
||||
/* Values below as used by hardware (HWMODE register) */
|
||||
MX21_USBXCVR_TXDIF_RXDIF = 0,
|
||||
MX21_USBXCVR_TXDIF_RXSE = 1,
|
||||
MX21_USBXCVR_TXSE_RXDIF = 2,
|
||||
MX21_USBXCVR_TXSE_RXSE = 3,
|
||||
};
|
||||
|
||||
struct mx21_usbh_platform_data {
|
||||
enum mx21_usbh_xcvr host_xcvr; /* tranceiver mode host 1,2 ports */
|
||||
enum mx21_usbh_xcvr otg_xcvr; /* tranceiver mode otg (as host) port */
|
||||
u16 enable_host1:1,
|
||||
enable_host2:1,
|
||||
enable_otg_host:1, /* enable "OTG" port (as host) */
|
||||
host1_xcverless:1, /* traceiverless host1 port */
|
||||
host1_txenoe:1, /* output enable host1 transmit enable */
|
||||
otg_ext_xcvr:1, /* external tranceiver for OTG port */
|
||||
unused:10;
|
||||
};
|
||||
|
||||
#endif /* __ASM_ARCH_MX21_USBH */
|
@ -21,6 +21,7 @@ obj-$(CONFIG_USB_U132_HCD) += host/
|
||||
obj-$(CONFIG_USB_R8A66597_HCD) += host/
|
||||
obj-$(CONFIG_USB_HWA_HCD) += host/
|
||||
obj-$(CONFIG_USB_ISP1760_HCD) += host/
|
||||
obj-$(CONFIG_USB_IMX21_HCD) += host/
|
||||
|
||||
obj-$(CONFIG_USB_C67X00_HCD) += c67x00/
|
||||
|
||||
|
@ -399,3 +399,14 @@ config USB_HWA_HCD
|
||||
|
||||
To compile this driver a module, choose M here: the module
|
||||
will be called "hwa-hc".
|
||||
|
||||
config USB_IMX21_HCD
|
||||
tristate "iMX21 HCD support"
|
||||
depends on USB && ARM && MACH_MX21
|
||||
help
|
||||
This driver enables support for the on-chip USB host in the
|
||||
iMX21 processor.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called "imx21-hcd".
|
||||
|
||||
|
@ -32,3 +32,5 @@ obj-$(CONFIG_USB_U132_HCD) += u132-hcd.o
|
||||
obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o
|
||||
obj-$(CONFIG_USB_ISP1760_HCD) += isp1760.o
|
||||
obj-$(CONFIG_USB_HWA_HCD) += hwa-hc.o
|
||||
obj-$(CONFIG_USB_IMX21_HCD) += imx21-hcd.o
|
||||
|
||||
|
527
drivers/usb/host/imx21-dbg.c
Normal file
527
drivers/usb/host/imx21-dbg.c
Normal file
@ -0,0 +1,527 @@
|
||||
/*
|
||||
* Copyright (c) 2009 by Martin Fuzzey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/* this file is part of imx21-hcd.c */
|
||||
|
||||
#ifndef DEBUG
|
||||
|
||||
static inline void create_debug_files(struct imx21 *imx21) { }
|
||||
static inline void remove_debug_files(struct imx21 *imx21) { }
|
||||
static inline void debug_urb_submitted(struct imx21 *imx21, struct urb *urb) {}
|
||||
static inline void debug_urb_completed(struct imx21 *imx21, struct urb *urb,
|
||||
int status) {}
|
||||
static inline void debug_urb_unlinked(struct imx21 *imx21, struct urb *urb) {}
|
||||
static inline void debug_urb_queued_for_etd(struct imx21 *imx21,
|
||||
struct urb *urb) {}
|
||||
static inline void debug_urb_queued_for_dmem(struct imx21 *imx21,
|
||||
struct urb *urb) {}
|
||||
static inline void debug_etd_allocated(struct imx21 *imx21) {}
|
||||
static inline void debug_etd_freed(struct imx21 *imx21) {}
|
||||
static inline void debug_dmem_allocated(struct imx21 *imx21, int size) {}
|
||||
static inline void debug_dmem_freed(struct imx21 *imx21, int size) {}
|
||||
static inline void debug_isoc_submitted(struct imx21 *imx21,
|
||||
int frame, struct td *td) {}
|
||||
static inline void debug_isoc_completed(struct imx21 *imx21,
|
||||
int frame, struct td *td, int cc, int len) {}
|
||||
|
||||
#else
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
static const char *dir_labels[] = {
|
||||
"TD 0",
|
||||
"OUT",
|
||||
"IN",
|
||||
"TD 1"
|
||||
};
|
||||
|
||||
static const char *speed_labels[] = {
|
||||
"Full",
|
||||
"Low"
|
||||
};
|
||||
|
||||
static const char *format_labels[] = {
|
||||
"Control",
|
||||
"ISO",
|
||||
"Bulk",
|
||||
"Interrupt"
|
||||
};
|
||||
|
||||
static inline struct debug_stats *stats_for_urb(struct imx21 *imx21,
|
||||
struct urb *urb)
|
||||
{
|
||||
return usb_pipeisoc(urb->pipe) ?
|
||||
&imx21->isoc_stats : &imx21->nonisoc_stats;
|
||||
}
|
||||
|
||||
static void debug_urb_submitted(struct imx21 *imx21, struct urb *urb)
|
||||
{
|
||||
stats_for_urb(imx21, urb)->submitted++;
|
||||
}
|
||||
|
||||
static void debug_urb_completed(struct imx21 *imx21, struct urb *urb, int st)
|
||||
{
|
||||
if (st)
|
||||
stats_for_urb(imx21, urb)->completed_failed++;
|
||||
else
|
||||
stats_for_urb(imx21, urb)->completed_ok++;
|
||||
}
|
||||
|
||||
static void debug_urb_unlinked(struct imx21 *imx21, struct urb *urb)
|
||||
{
|
||||
stats_for_urb(imx21, urb)->unlinked++;
|
||||
}
|
||||
|
||||
static void debug_urb_queued_for_etd(struct imx21 *imx21, struct urb *urb)
|
||||
{
|
||||
stats_for_urb(imx21, urb)->queue_etd++;
|
||||
}
|
||||
|
||||
static void debug_urb_queued_for_dmem(struct imx21 *imx21, struct urb *urb)
|
||||
{
|
||||
stats_for_urb(imx21, urb)->queue_dmem++;
|
||||
}
|
||||
|
||||
static inline void debug_etd_allocated(struct imx21 *imx21)
|
||||
{
|
||||
imx21->etd_usage.maximum = max(
|
||||
++(imx21->etd_usage.value),
|
||||
imx21->etd_usage.maximum);
|
||||
}
|
||||
|
||||
static inline void debug_etd_freed(struct imx21 *imx21)
|
||||
{
|
||||
imx21->etd_usage.value--;
|
||||
}
|
||||
|
||||
static inline void debug_dmem_allocated(struct imx21 *imx21, int size)
|
||||
{
|
||||
imx21->dmem_usage.value += size;
|
||||
imx21->dmem_usage.maximum = max(
|
||||
imx21->dmem_usage.value,
|
||||
imx21->dmem_usage.maximum);
|
||||
}
|
||||
|
||||
static inline void debug_dmem_freed(struct imx21 *imx21, int size)
|
||||
{
|
||||
imx21->dmem_usage.value -= size;
|
||||
}
|
||||
|
||||
|
||||
static void debug_isoc_submitted(struct imx21 *imx21,
|
||||
int frame, struct td *td)
|
||||
{
|
||||
struct debug_isoc_trace *trace = &imx21->isoc_trace[
|
||||
imx21->isoc_trace_index++];
|
||||
|
||||
imx21->isoc_trace_index %= ARRAY_SIZE(imx21->isoc_trace);
|
||||
trace->schedule_frame = td->frame;
|
||||
trace->submit_frame = frame;
|
||||
trace->request_len = td->len;
|
||||
trace->td = td;
|
||||
}
|
||||
|
||||
static inline void debug_isoc_completed(struct imx21 *imx21,
|
||||
int frame, struct td *td, int cc, int len)
|
||||
{
|
||||
struct debug_isoc_trace *trace, *trace_failed;
|
||||
int i;
|
||||
int found = 0;
|
||||
|
||||
trace = imx21->isoc_trace;
|
||||
for (i = 0; i < ARRAY_SIZE(imx21->isoc_trace); i++, trace++) {
|
||||
if (trace->td == td) {
|
||||
trace->done_frame = frame;
|
||||
trace->done_len = len;
|
||||
trace->cc = cc;
|
||||
trace->td = NULL;
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found && cc) {
|
||||
trace_failed = &imx21->isoc_trace_failed[
|
||||
imx21->isoc_trace_index_failed++];
|
||||
|
||||
imx21->isoc_trace_index_failed %= ARRAY_SIZE(
|
||||
imx21->isoc_trace_failed);
|
||||
*trace_failed = *trace;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static char *format_ep(struct usb_host_endpoint *ep, char *buf, int bufsize)
|
||||
{
|
||||
if (ep)
|
||||
snprintf(buf, bufsize, "ep_%02x (type:%02X kaddr:%p)",
|
||||
ep->desc.bEndpointAddress,
|
||||
usb_endpoint_type(&ep->desc),
|
||||
ep);
|
||||
else
|
||||
snprintf(buf, bufsize, "none");
|
||||
return buf;
|
||||
}
|
||||
|
||||
static char *format_etd_dword0(u32 value, char *buf, int bufsize)
|
||||
{
|
||||
snprintf(buf, bufsize,
|
||||
"addr=%d ep=%d dir=%s speed=%s format=%s halted=%d",
|
||||
value & 0x7F,
|
||||
(value >> DW0_ENDPNT) & 0x0F,
|
||||
dir_labels[(value >> DW0_DIRECT) & 0x03],
|
||||
speed_labels[(value >> DW0_SPEED) & 0x01],
|
||||
format_labels[(value >> DW0_FORMAT) & 0x03],
|
||||
(value >> DW0_HALTED) & 0x01);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static int debug_status_show(struct seq_file *s, void *v)
|
||||
{
|
||||
struct imx21 *imx21 = s->private;
|
||||
int etds_allocated = 0;
|
||||
int etds_sw_busy = 0;
|
||||
int etds_hw_busy = 0;
|
||||
int dmem_blocks = 0;
|
||||
int queued_for_etd = 0;
|
||||
int queued_for_dmem = 0;
|
||||
unsigned int dmem_bytes = 0;
|
||||
int i;
|
||||
struct etd_priv *etd;
|
||||
u32 etd_enable_mask;
|
||||
unsigned long flags;
|
||||
struct imx21_dmem_area *dmem;
|
||||
struct ep_priv *ep_priv;
|
||||
|
||||
spin_lock_irqsave(&imx21->lock, flags);
|
||||
|
||||
etd_enable_mask = readl(imx21->regs + USBH_ETDENSET);
|
||||
for (i = 0, etd = imx21->etd; i < USB_NUM_ETD; i++, etd++) {
|
||||
if (etd->alloc)
|
||||
etds_allocated++;
|
||||
if (etd->urb)
|
||||
etds_sw_busy++;
|
||||
if (etd_enable_mask & (1<<i))
|
||||
etds_hw_busy++;
|
||||
}
|
||||
|
||||
list_for_each_entry(dmem, &imx21->dmem_list, list) {
|
||||
dmem_bytes += dmem->size;
|
||||
dmem_blocks++;
|
||||
}
|
||||
|
||||
list_for_each_entry(ep_priv, &imx21->queue_for_etd, queue)
|
||||
queued_for_etd++;
|
||||
|
||||
list_for_each_entry(etd, &imx21->queue_for_dmem, queue)
|
||||
queued_for_dmem++;
|
||||
|
||||
spin_unlock_irqrestore(&imx21->lock, flags);
|
||||
|
||||
seq_printf(s,
|
||||
"Frame: %d\n"
|
||||
"ETDs allocated: %d/%d (max=%d)\n"
|
||||
"ETDs in use sw: %d\n"
|
||||
"ETDs in use hw: %d\n"
|
||||
"DMEM alocated: %d/%d (max=%d)\n"
|
||||
"DMEM blocks: %d\n"
|
||||
"Queued waiting for ETD: %d\n"
|
||||
"Queued waiting for DMEM: %d\n",
|
||||
readl(imx21->regs + USBH_FRMNUB) & 0xFFFF,
|
||||
etds_allocated, USB_NUM_ETD, imx21->etd_usage.maximum,
|
||||
etds_sw_busy,
|
||||
etds_hw_busy,
|
||||
dmem_bytes, DMEM_SIZE, imx21->dmem_usage.maximum,
|
||||
dmem_blocks,
|
||||
queued_for_etd,
|
||||
queued_for_dmem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int debug_dmem_show(struct seq_file *s, void *v)
|
||||
{
|
||||
struct imx21 *imx21 = s->private;
|
||||
struct imx21_dmem_area *dmem;
|
||||
unsigned long flags;
|
||||
char ep_text[40];
|
||||
|
||||
spin_lock_irqsave(&imx21->lock, flags);
|
||||
|
||||
list_for_each_entry(dmem, &imx21->dmem_list, list)
|
||||
seq_printf(s,
|
||||
"%04X: size=0x%X "
|
||||
"ep=%s\n",
|
||||
dmem->offset, dmem->size,
|
||||
format_ep(dmem->ep, ep_text, sizeof(ep_text)));
|
||||
|
||||
spin_unlock_irqrestore(&imx21->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int debug_etd_show(struct seq_file *s, void *v)
|
||||
{
|
||||
struct imx21 *imx21 = s->private;
|
||||
struct etd_priv *etd;
|
||||
char buf[60];
|
||||
u32 dword;
|
||||
int i, j;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&imx21->lock, flags);
|
||||
|
||||
for (i = 0, etd = imx21->etd; i < USB_NUM_ETD; i++, etd++) {
|
||||
int state = -1;
|
||||
struct urb_priv *urb_priv;
|
||||
if (etd->urb) {
|
||||
urb_priv = etd->urb->hcpriv;
|
||||
if (urb_priv)
|
||||
state = urb_priv->state;
|
||||
}
|
||||
|
||||
seq_printf(s,
|
||||
"etd_num: %d\n"
|
||||
"ep: %s\n"
|
||||
"alloc: %d\n"
|
||||
"len: %d\n"
|
||||
"busy sw: %d\n"
|
||||
"busy hw: %d\n"
|
||||
"urb state: %d\n"
|
||||
"current urb: %p\n",
|
||||
|
||||
i,
|
||||
format_ep(etd->ep, buf, sizeof(buf)),
|
||||
etd->alloc,
|
||||
etd->len,
|
||||
etd->urb != NULL,
|
||||
(readl(imx21->regs + USBH_ETDENSET) & (1 << i)) > 0,
|
||||
state,
|
||||
etd->urb);
|
||||
|
||||
for (j = 0; j < 4; j++) {
|
||||
dword = etd_readl(imx21, i, j);
|
||||
switch (j) {
|
||||
case 0:
|
||||
format_etd_dword0(dword, buf, sizeof(buf));
|
||||
break;
|
||||
case 2:
|
||||
snprintf(buf, sizeof(buf),
|
||||
"cc=0X%02X", dword >> DW2_COMPCODE);
|
||||
break;
|
||||
default:
|
||||
*buf = 0;
|
||||
break;
|
||||
}
|
||||
seq_printf(s,
|
||||
"dword %d: submitted=%08X cur=%08X [%s]\n",
|
||||
j,
|
||||
etd->submitted_dwords[j],
|
||||
dword,
|
||||
buf);
|
||||
}
|
||||
seq_printf(s, "\n");
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&imx21->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void debug_statistics_show_one(struct seq_file *s,
|
||||
const char *name, struct debug_stats *stats)
|
||||
{
|
||||
seq_printf(s, "%s:\n"
|
||||
"submitted URBs: %lu\n"
|
||||
"completed OK: %lu\n"
|
||||
"completed failed: %lu\n"
|
||||
"unlinked: %lu\n"
|
||||
"queued for ETD: %lu\n"
|
||||
"queued for DMEM: %lu\n\n",
|
||||
name,
|
||||
stats->submitted,
|
||||
stats->completed_ok,
|
||||
stats->completed_failed,
|
||||
stats->unlinked,
|
||||
stats->queue_etd,
|
||||
stats->queue_dmem);
|
||||
}
|
||||
|
||||
static int debug_statistics_show(struct seq_file *s, void *v)
|
||||
{
|
||||
struct imx21 *imx21 = s->private;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&imx21->lock, flags);
|
||||
|
||||
debug_statistics_show_one(s, "nonisoc", &imx21->nonisoc_stats);
|
||||
debug_statistics_show_one(s, "isoc", &imx21->isoc_stats);
|
||||
seq_printf(s, "unblock kludge triggers: %lu\n", imx21->debug_unblocks);
|
||||
spin_unlock_irqrestore(&imx21->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void debug_isoc_show_one(struct seq_file *s,
|
||||
const char *name, int index, struct debug_isoc_trace *trace)
|
||||
{
|
||||
seq_printf(s, "%s %d:\n"
|
||||
"cc=0X%02X\n"
|
||||
"scheduled frame %d (%d)\n"
|
||||
"submittted frame %d (%d)\n"
|
||||
"completed frame %d (%d)\n"
|
||||
"requested length=%d\n"
|
||||
"completed length=%d\n\n",
|
||||
name, index,
|
||||
trace->cc,
|
||||
trace->schedule_frame, trace->schedule_frame & 0xFFFF,
|
||||
trace->submit_frame, trace->submit_frame & 0xFFFF,
|
||||
trace->done_frame, trace->done_frame & 0xFFFF,
|
||||
trace->request_len,
|
||||
trace->done_len);
|
||||
}
|
||||
|
||||
static int debug_isoc_show(struct seq_file *s, void *v)
|
||||
{
|
||||
struct imx21 *imx21 = s->private;
|
||||
struct debug_isoc_trace *trace;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
spin_lock_irqsave(&imx21->lock, flags);
|
||||
|
||||
trace = imx21->isoc_trace_failed;
|
||||
for (i = 0; i < ARRAY_SIZE(imx21->isoc_trace_failed); i++, trace++)
|
||||
debug_isoc_show_one(s, "isoc failed", i, trace);
|
||||
|
||||
trace = imx21->isoc_trace;
|
||||
for (i = 0; i < ARRAY_SIZE(imx21->isoc_trace); i++, trace++)
|
||||
debug_isoc_show_one(s, "isoc", i, trace);
|
||||
|
||||
spin_unlock_irqrestore(&imx21->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int debug_status_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, debug_status_show, inode->i_private);
|
||||
}
|
||||
|
||||
static int debug_dmem_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, debug_dmem_show, inode->i_private);
|
||||
}
|
||||
|
||||
static int debug_etd_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, debug_etd_show, inode->i_private);
|
||||
}
|
||||
|
||||
static int debug_statistics_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, debug_statistics_show, inode->i_private);
|
||||
}
|
||||
|
||||
static int debug_isoc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, debug_isoc_show, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations debug_status_fops = {
|
||||
.open = debug_status_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static const struct file_operations debug_dmem_fops = {
|
||||
.open = debug_dmem_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static const struct file_operations debug_etd_fops = {
|
||||
.open = debug_etd_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static const struct file_operations debug_statistics_fops = {
|
||||
.open = debug_statistics_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static const struct file_operations debug_isoc_fops = {
|
||||
.open = debug_isoc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static void create_debug_files(struct imx21 *imx21)
|
||||
{
|
||||
imx21->debug_root = debugfs_create_dir(dev_name(imx21->dev), NULL);
|
||||
if (!imx21->debug_root)
|
||||
goto failed_create_rootdir;
|
||||
|
||||
if (!debugfs_create_file("status", S_IRUGO,
|
||||
imx21->debug_root, imx21, &debug_status_fops))
|
||||
goto failed_create;
|
||||
|
||||
if (!debugfs_create_file("dmem", S_IRUGO,
|
||||
imx21->debug_root, imx21, &debug_dmem_fops))
|
||||
goto failed_create;
|
||||
|
||||
if (!debugfs_create_file("etd", S_IRUGO,
|
||||
imx21->debug_root, imx21, &debug_etd_fops))
|
||||
goto failed_create;
|
||||
|
||||
if (!debugfs_create_file("statistics", S_IRUGO,
|
||||
imx21->debug_root, imx21, &debug_statistics_fops))
|
||||
goto failed_create;
|
||||
|
||||
if (!debugfs_create_file("isoc", S_IRUGO,
|
||||
imx21->debug_root, imx21, &debug_isoc_fops))
|
||||
goto failed_create;
|
||||
|
||||
return;
|
||||
|
||||
failed_create:
|
||||
debugfs_remove_recursive(imx21->debug_root);
|
||||
|
||||
failed_create_rootdir:
|
||||
imx21->debug_root = NULL;
|
||||
}
|
||||
|
||||
|
||||
static void remove_debug_files(struct imx21 *imx21)
|
||||
{
|
||||
if (imx21->debug_root) {
|
||||
debugfs_remove_recursive(imx21->debug_root);
|
||||
imx21->debug_root = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
1789
drivers/usb/host/imx21-hcd.c
Normal file
1789
drivers/usb/host/imx21-hcd.c
Normal file
File diff suppressed because it is too large
Load Diff
436
drivers/usb/host/imx21-hcd.h
Normal file
436
drivers/usb/host/imx21-hcd.h
Normal file
@ -0,0 +1,436 @@
|
||||
/*
|
||||
* Macros and prototypes for i.MX21
|
||||
*
|
||||
* Copyright (C) 2006 Loping Dog Embedded Systems
|
||||
* Copyright (C) 2009 Martin Fuzzey
|
||||
* Originally written by Jay Monkman <jtm@lopingdog.com>
|
||||
* Ported to 2.6.30, debugged and enhanced by Martin Fuzzey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_IMX21_HCD_H__
|
||||
#define __LINUX_IMX21_HCD_H__
|
||||
|
||||
#include <mach/mx21-usbhost.h>
|
||||
|
||||
#define NUM_ISO_ETDS 2
|
||||
#define USB_NUM_ETD 32
|
||||
#define DMEM_SIZE 4096
|
||||
|
||||
/* Register definitions */
|
||||
#define USBOTG_HWMODE 0x00
|
||||
#define USBOTG_HWMODE_ANASDBEN (1 << 14)
|
||||
#define USBOTG_HWMODE_OTGXCVR_SHIFT 6
|
||||
#define USBOTG_HWMODE_OTGXCVR_MASK (3 << 6)
|
||||
#define USBOTG_HWMODE_OTGXCVR_TD_RD (0 << 6)
|
||||
#define USBOTG_HWMODE_OTGXCVR_TS_RD (2 << 6)
|
||||
#define USBOTG_HWMODE_OTGXCVR_TD_RS (1 << 6)
|
||||
#define USBOTG_HWMODE_OTGXCVR_TS_RS (3 << 6)
|
||||
#define USBOTG_HWMODE_HOSTXCVR_SHIFT 4
|
||||
#define USBOTG_HWMODE_HOSTXCVR_MASK (3 << 4)
|
||||
#define USBOTG_HWMODE_HOSTXCVR_TD_RD (0 << 4)
|
||||
#define USBOTG_HWMODE_HOSTXCVR_TS_RD (2 << 4)
|
||||
#define USBOTG_HWMODE_HOSTXCVR_TD_RS (1 << 4)
|
||||
#define USBOTG_HWMODE_HOSTXCVR_TS_RS (3 << 4)
|
||||
#define USBOTG_HWMODE_CRECFG_MASK (3 << 0)
|
||||
#define USBOTG_HWMODE_CRECFG_HOST (1 << 0)
|
||||
#define USBOTG_HWMODE_CRECFG_FUNC (2 << 0)
|
||||
#define USBOTG_HWMODE_CRECFG_HNP (3 << 0)
|
||||
|
||||
#define USBOTG_CINT_STAT 0x04
|
||||
#define USBOTG_CINT_STEN 0x08
|
||||
#define USBOTG_ASHNPINT (1 << 5)
|
||||
#define USBOTG_ASFCINT (1 << 4)
|
||||
#define USBOTG_ASHCINT (1 << 3)
|
||||
#define USBOTG_SHNPINT (1 << 2)
|
||||
#define USBOTG_FCINT (1 << 1)
|
||||
#define USBOTG_HCINT (1 << 0)
|
||||
|
||||
#define USBOTG_CLK_CTRL 0x0c
|
||||
#define USBOTG_CLK_CTRL_FUNC (1 << 2)
|
||||
#define USBOTG_CLK_CTRL_HST (1 << 1)
|
||||
#define USBOTG_CLK_CTRL_MAIN (1 << 0)
|
||||
|
||||
#define USBOTG_RST_CTRL 0x10
|
||||
#define USBOTG_RST_RSTI2C (1 << 15)
|
||||
#define USBOTG_RST_RSTCTRL (1 << 5)
|
||||
#define USBOTG_RST_RSTFC (1 << 4)
|
||||
#define USBOTG_RST_RSTFSKE (1 << 3)
|
||||
#define USBOTG_RST_RSTRH (1 << 2)
|
||||
#define USBOTG_RST_RSTHSIE (1 << 1)
|
||||
#define USBOTG_RST_RSTHC (1 << 0)
|
||||
|
||||
#define USBOTG_FRM_INTVL 0x14
|
||||
#define USBOTG_FRM_REMAIN 0x18
|
||||
#define USBOTG_HNP_CSR 0x1c
|
||||
#define USBOTG_HNP_ISR 0x2c
|
||||
#define USBOTG_HNP_IEN 0x30
|
||||
|
||||
#define USBOTG_I2C_TXCVR_REG(x) (0x100 + (x))
|
||||
#define USBOTG_I2C_XCVR_DEVAD 0x118
|
||||
#define USBOTG_I2C_SEQ_OP_REG 0x119
|
||||
#define USBOTG_I2C_SEQ_RD_STARTAD 0x11a
|
||||
#define USBOTG_I2C_OP_CTRL_REG 0x11b
|
||||
#define USBOTG_I2C_SCLK_TO_SCK_HPER 0x11e
|
||||
#define USBOTG_I2C_MASTER_INT_REG 0x11f
|
||||
|
||||
#define USBH_HOST_CTRL 0x80
|
||||
#define USBH_HOST_CTRL_HCRESET (1 << 31)
|
||||
#define USBH_HOST_CTRL_SCHDOVR(x) ((x) << 16)
|
||||
#define USBH_HOST_CTRL_RMTWUEN (1 << 4)
|
||||
#define USBH_HOST_CTRL_HCUSBSTE_RESET (0 << 2)
|
||||
#define USBH_HOST_CTRL_HCUSBSTE_RESUME (1 << 2)
|
||||
#define USBH_HOST_CTRL_HCUSBSTE_OPERATIONAL (2 << 2)
|
||||
#define USBH_HOST_CTRL_HCUSBSTE_SUSPEND (3 << 2)
|
||||
#define USBH_HOST_CTRL_CTLBLKSR_1 (0 << 0)
|
||||
#define USBH_HOST_CTRL_CTLBLKSR_2 (1 << 0)
|
||||
#define USBH_HOST_CTRL_CTLBLKSR_3 (2 << 0)
|
||||
#define USBH_HOST_CTRL_CTLBLKSR_4 (3 << 0)
|
||||
|
||||
#define USBH_SYSISR 0x88
|
||||
#define USBH_SYSISR_PSCINT (1 << 6)
|
||||
#define USBH_SYSISR_FMOFINT (1 << 5)
|
||||
#define USBH_SYSISR_HERRINT (1 << 4)
|
||||
#define USBH_SYSISR_RESDETINT (1 << 3)
|
||||
#define USBH_SYSISR_SOFINT (1 << 2)
|
||||
#define USBH_SYSISR_DONEINT (1 << 1)
|
||||
#define USBH_SYSISR_SORINT (1 << 0)
|
||||
|
||||
#define USBH_SYSIEN 0x8c
|
||||
#define USBH_SYSIEN_PSCINT (1 << 6)
|
||||
#define USBH_SYSIEN_FMOFINT (1 << 5)
|
||||
#define USBH_SYSIEN_HERRINT (1 << 4)
|
||||
#define USBH_SYSIEN_RESDETINT (1 << 3)
|
||||
#define USBH_SYSIEN_SOFINT (1 << 2)
|
||||
#define USBH_SYSIEN_DONEINT (1 << 1)
|
||||
#define USBH_SYSIEN_SORINT (1 << 0)
|
||||
|
||||
#define USBH_XBUFSTAT 0x98
|
||||
#define USBH_YBUFSTAT 0x9c
|
||||
#define USBH_XYINTEN 0xa0
|
||||
#define USBH_XFILLSTAT 0xa8
|
||||
#define USBH_YFILLSTAT 0xac
|
||||
#define USBH_ETDENSET 0xc0
|
||||
#define USBH_ETDENCLR 0xc4
|
||||
#define USBH_IMMEDINT 0xcc
|
||||
#define USBH_ETDDONESTAT 0xd0
|
||||
#define USBH_ETDDONEEN 0xd4
|
||||
#define USBH_FRMNUB 0xe0
|
||||
#define USBH_LSTHRESH 0xe4
|
||||
|
||||
#define USBH_ROOTHUBA 0xe8
|
||||
#define USBH_ROOTHUBA_PWRTOGOOD_MASK (0xff)
|
||||
#define USBH_ROOTHUBA_PWRTOGOOD_SHIFT (24)
|
||||
#define USBH_ROOTHUBA_NOOVRCURP (1 << 12)
|
||||
#define USBH_ROOTHUBA_OVRCURPM (1 << 11)
|
||||
#define USBH_ROOTHUBA_DEVTYPE (1 << 10)
|
||||
#define USBH_ROOTHUBA_PWRSWTMD (1 << 9)
|
||||
#define USBH_ROOTHUBA_NOPWRSWT (1 << 8)
|
||||
#define USBH_ROOTHUBA_NDNSTMPRT_MASK (0xff)
|
||||
|
||||
#define USBH_ROOTHUBB 0xec
|
||||
#define USBH_ROOTHUBB_PRTPWRCM(x) (1 << ((x) + 16))
|
||||
#define USBH_ROOTHUBB_DEVREMOVE(x) (1 << (x))
|
||||
|
||||
#define USBH_ROOTSTAT 0xf0
|
||||
#define USBH_ROOTSTAT_CLRRMTWUE (1 << 31)
|
||||
#define USBH_ROOTSTAT_OVRCURCHG (1 << 17)
|
||||
#define USBH_ROOTSTAT_DEVCONWUE (1 << 15)
|
||||
#define USBH_ROOTSTAT_OVRCURI (1 << 1)
|
||||
#define USBH_ROOTSTAT_LOCPWRS (1 << 0)
|
||||
|
||||
#define USBH_PORTSTAT(x) (0xf4 + ((x) * 4))
|
||||
#define USBH_PORTSTAT_PRTRSTSC (1 << 20)
|
||||
#define USBH_PORTSTAT_OVRCURIC (1 << 19)
|
||||
#define USBH_PORTSTAT_PRTSTATSC (1 << 18)
|
||||
#define USBH_PORTSTAT_PRTENBLSC (1 << 17)
|
||||
#define USBH_PORTSTAT_CONNECTSC (1 << 16)
|
||||
#define USBH_PORTSTAT_LSDEVCON (1 << 9)
|
||||
#define USBH_PORTSTAT_PRTPWRST (1 << 8)
|
||||
#define USBH_PORTSTAT_PRTRSTST (1 << 4)
|
||||
#define USBH_PORTSTAT_PRTOVRCURI (1 << 3)
|
||||
#define USBH_PORTSTAT_PRTSUSPST (1 << 2)
|
||||
#define USBH_PORTSTAT_PRTENABST (1 << 1)
|
||||
#define USBH_PORTSTAT_CURCONST (1 << 0)
|
||||
|
||||
#define USB_DMAREV 0x800
|
||||
#define USB_DMAINTSTAT 0x804
|
||||
#define USB_DMAINTSTAT_EPERR (1 << 1)
|
||||
#define USB_DMAINTSTAT_ETDERR (1 << 0)
|
||||
|
||||
#define USB_DMAINTEN 0x808
|
||||
#define USB_DMAINTEN_EPERRINTEN (1 << 1)
|
||||
#define USB_DMAINTEN_ETDERRINTEN (1 << 0)
|
||||
|
||||
#define USB_ETDDMAERSTAT 0x80c
|
||||
#define USB_EPDMAERSTAT 0x810
|
||||
#define USB_ETDDMAEN 0x820
|
||||
#define USB_EPDMAEN 0x824
|
||||
#define USB_ETDDMAXTEN 0x828
|
||||
#define USB_EPDMAXTEN 0x82c
|
||||
#define USB_ETDDMAENXYT 0x830
|
||||
#define USB_EPDMAENXYT 0x834
|
||||
#define USB_ETDDMABST4EN 0x838
|
||||
#define USB_EPDMABST4EN 0x83c
|
||||
|
||||
#define USB_MISCCONTROL 0x840
|
||||
#define USB_MISCCONTROL_ISOPREVFRM (1 << 3)
|
||||
#define USB_MISCCONTROL_SKPRTRY (1 << 2)
|
||||
#define USB_MISCCONTROL_ARBMODE (1 << 1)
|
||||
#define USB_MISCCONTROL_FILTCC (1 << 0)
|
||||
|
||||
#define USB_ETDDMACHANLCLR 0x848
|
||||
#define USB_EPDMACHANLCLR 0x84c
|
||||
#define USB_ETDSMSA(x) (0x900 + ((x) * 4))
|
||||
#define USB_EPSMSA(x) (0x980 + ((x) * 4))
|
||||
#define USB_ETDDMABUFPTR(x) (0xa00 + ((x) * 4))
|
||||
#define USB_EPDMABUFPTR(x) (0xa80 + ((x) * 4))
|
||||
|
||||
#define USB_ETD_DWORD(x, w) (0x200 + ((x) * 16) + ((w) * 4))
|
||||
#define DW0_ADDRESS 0
|
||||
#define DW0_ENDPNT 7
|
||||
#define DW0_DIRECT 11
|
||||
#define DW0_SPEED 13
|
||||
#define DW0_FORMAT 14
|
||||
#define DW0_MAXPKTSIZ 16
|
||||
#define DW0_HALTED 27
|
||||
#define DW0_TOGCRY 28
|
||||
#define DW0_SNDNAK 30
|
||||
|
||||
#define DW1_XBUFSRTAD 0
|
||||
#define DW1_YBUFSRTAD 16
|
||||
|
||||
#define DW2_RTRYDELAY 0
|
||||
#define DW2_POLINTERV 0
|
||||
#define DW2_STARTFRM 0
|
||||
#define DW2_RELPOLPOS 8
|
||||
#define DW2_DIRPID 16
|
||||
#define DW2_BUFROUND 18
|
||||
#define DW2_DELAYINT 19
|
||||
#define DW2_DATATOG 22
|
||||
#define DW2_ERRORCNT 24
|
||||
#define DW2_COMPCODE 28
|
||||
|
||||
#define DW3_TOTBYECNT 0
|
||||
#define DW3_PKTLEN0 0
|
||||
#define DW3_COMPCODE0 12
|
||||
#define DW3_PKTLEN1 16
|
||||
#define DW3_BUFSIZE 21
|
||||
#define DW3_COMPCODE1 28
|
||||
|
||||
#define USBCTRL 0x600
|
||||
#define USBCTRL_I2C_WU_INT_STAT (1 << 27)
|
||||
#define USBCTRL_OTG_WU_INT_STAT (1 << 26)
|
||||
#define USBCTRL_HOST_WU_INT_STAT (1 << 25)
|
||||
#define USBCTRL_FNT_WU_INT_STAT (1 << 24)
|
||||
#define USBCTRL_I2C_WU_INT_EN (1 << 19)
|
||||
#define USBCTRL_OTG_WU_INT_EN (1 << 18)
|
||||
#define USBCTRL_HOST_WU_INT_EN (1 << 17)
|
||||
#define USBCTRL_FNT_WU_INT_EN (1 << 16)
|
||||
#define USBCTRL_OTC_RCV_RXDP (1 << 13)
|
||||
#define USBCTRL_HOST1_BYP_TLL (1 << 12)
|
||||
#define USBCTRL_OTG_BYP_VAL(x) ((x) << 10)
|
||||
#define USBCTRL_HOST1_BYP_VAL(x) ((x) << 8)
|
||||
#define USBCTRL_OTG_PWR_MASK (1 << 6)
|
||||
#define USBCTRL_HOST1_PWR_MASK (1 << 5)
|
||||
#define USBCTRL_HOST2_PWR_MASK (1 << 4)
|
||||
#define USBCTRL_USB_BYP (1 << 2)
|
||||
#define USBCTRL_HOST1_TXEN_OE (1 << 1)
|
||||
|
||||
|
||||
/* Values in TD blocks */
|
||||
#define TD_DIR_SETUP 0
|
||||
#define TD_DIR_OUT 1
|
||||
#define TD_DIR_IN 2
|
||||
#define TD_FORMAT_CONTROL 0
|
||||
#define TD_FORMAT_ISO 1
|
||||
#define TD_FORMAT_BULK 2
|
||||
#define TD_FORMAT_INT 3
|
||||
#define TD_TOGGLE_CARRY 0
|
||||
#define TD_TOGGLE_DATA0 2
|
||||
#define TD_TOGGLE_DATA1 3
|
||||
|
||||
/* control transfer states */
|
||||
#define US_CTRL_SETUP 2
|
||||
#define US_CTRL_DATA 1
|
||||
#define US_CTRL_ACK 0
|
||||
|
||||
/* bulk transfer main state and 0-length packet */
|
||||
#define US_BULK 1
|
||||
#define US_BULK0 0
|
||||
|
||||
/*ETD format description*/
|
||||
#define IMX_FMT_CTRL 0x0
|
||||
#define IMX_FMT_ISO 0x1
|
||||
#define IMX_FMT_BULK 0x2
|
||||
#define IMX_FMT_INT 0x3
|
||||
|
||||
static char fmt_urb_to_etd[4] = {
|
||||
/*PIPE_ISOCHRONOUS*/ IMX_FMT_ISO,
|
||||
/*PIPE_INTERRUPT*/ IMX_FMT_INT,
|
||||
/*PIPE_CONTROL*/ IMX_FMT_CTRL,
|
||||
/*PIPE_BULK*/ IMX_FMT_BULK
|
||||
};
|
||||
|
||||
/* condition (error) CC codes and mapping (OHCI like) */
|
||||
|
||||
#define TD_CC_NOERROR 0x00
|
||||
#define TD_CC_CRC 0x01
|
||||
#define TD_CC_BITSTUFFING 0x02
|
||||
#define TD_CC_DATATOGGLEM 0x03
|
||||
#define TD_CC_STALL 0x04
|
||||
#define TD_DEVNOTRESP 0x05
|
||||
#define TD_PIDCHECKFAIL 0x06
|
||||
/*#define TD_UNEXPECTEDPID 0x07 - reserved, not active on MX2*/
|
||||
#define TD_DATAOVERRUN 0x08
|
||||
#define TD_DATAUNDERRUN 0x09
|
||||
#define TD_BUFFEROVERRUN 0x0C
|
||||
#define TD_BUFFERUNDERRUN 0x0D
|
||||
#define TD_SCHEDULEOVERRUN 0x0E
|
||||
#define TD_NOTACCESSED 0x0F
|
||||
|
||||
static const int cc_to_error[16] = {
|
||||
/* No Error */ 0,
|
||||
/* CRC Error */ -EILSEQ,
|
||||
/* Bit Stuff */ -EPROTO,
|
||||
/* Data Togg */ -EILSEQ,
|
||||
/* Stall */ -EPIPE,
|
||||
/* DevNotResp */ -ETIMEDOUT,
|
||||
/* PIDCheck */ -EPROTO,
|
||||
/* UnExpPID */ -EPROTO,
|
||||
/* DataOver */ -EOVERFLOW,
|
||||
/* DataUnder */ -EREMOTEIO,
|
||||
/* (for hw) */ -EIO,
|
||||
/* (for hw) */ -EIO,
|
||||
/* BufferOver */ -ECOMM,
|
||||
/* BuffUnder */ -ENOSR,
|
||||
/* (for HCD) */ -ENOSPC,
|
||||
/* (for HCD) */ -EALREADY
|
||||
};
|
||||
|
||||
/* HCD data associated with a usb core URB */
|
||||
struct urb_priv {
|
||||
struct urb *urb;
|
||||
struct usb_host_endpoint *ep;
|
||||
int active;
|
||||
int state;
|
||||
struct td *isoc_td;
|
||||
int isoc_remaining;
|
||||
int isoc_status;
|
||||
};
|
||||
|
||||
/* HCD data associated with a usb core endpoint */
|
||||
struct ep_priv {
|
||||
struct usb_host_endpoint *ep;
|
||||
struct list_head td_list;
|
||||
struct list_head queue;
|
||||
int etd[NUM_ISO_ETDS];
|
||||
int waiting_etd;
|
||||
};
|
||||
|
||||
/* isoc packet */
|
||||
struct td {
|
||||
struct list_head list;
|
||||
struct urb *urb;
|
||||
struct usb_host_endpoint *ep;
|
||||
dma_addr_t data;
|
||||
unsigned long buf_addr;
|
||||
int len;
|
||||
int frame;
|
||||
int isoc_index;
|
||||
};
|
||||
|
||||
/* HCD data associated with a hardware ETD */
|
||||
struct etd_priv {
|
||||
struct usb_host_endpoint *ep;
|
||||
struct urb *urb;
|
||||
struct td *td;
|
||||
struct list_head queue;
|
||||
dma_addr_t dma_handle;
|
||||
int alloc;
|
||||
int len;
|
||||
int dmem_size;
|
||||
int dmem_offset;
|
||||
int active_count;
|
||||
#ifdef DEBUG
|
||||
int activated_frame;
|
||||
int disactivated_frame;
|
||||
int last_int_frame;
|
||||
int last_req_frame;
|
||||
u32 submitted_dwords[4];
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Hardware data memory info */
|
||||
struct imx21_dmem_area {
|
||||
struct usb_host_endpoint *ep;
|
||||
unsigned int offset;
|
||||
unsigned int size;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
struct debug_usage_stats {
|
||||
unsigned int value;
|
||||
unsigned int maximum;
|
||||
};
|
||||
|
||||
struct debug_stats {
|
||||
unsigned long submitted;
|
||||
unsigned long completed_ok;
|
||||
unsigned long completed_failed;
|
||||
unsigned long unlinked;
|
||||
unsigned long queue_etd;
|
||||
unsigned long queue_dmem;
|
||||
};
|
||||
|
||||
struct debug_isoc_trace {
|
||||
int schedule_frame;
|
||||
int submit_frame;
|
||||
int request_len;
|
||||
int done_frame;
|
||||
int done_len;
|
||||
int cc;
|
||||
struct td *td;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* HCD data structure */
|
||||
struct imx21 {
|
||||
spinlock_t lock;
|
||||
struct device *dev;
|
||||
struct mx21_usbh_platform_data *pdata;
|
||||
struct list_head dmem_list;
|
||||
struct list_head queue_for_etd; /* eps queued due to etd shortage */
|
||||
struct list_head queue_for_dmem; /* etds queued due to dmem shortage */
|
||||
struct etd_priv etd[USB_NUM_ETD];
|
||||
struct clk *clk;
|
||||
void __iomem *regs;
|
||||
#ifdef DEBUG
|
||||
struct dentry *debug_root;
|
||||
struct debug_stats nonisoc_stats;
|
||||
struct debug_stats isoc_stats;
|
||||
struct debug_usage_stats etd_usage;
|
||||
struct debug_usage_stats dmem_usage;
|
||||
struct debug_isoc_trace isoc_trace[20];
|
||||
struct debug_isoc_trace isoc_trace_failed[20];
|
||||
unsigned long debug_unblocks;
|
||||
int isoc_trace_index;
|
||||
int isoc_trace_index_failed;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user