diff mbox

[09/15] Introduce Cadence USBSSP DRD Driver - added debugfs files.

Message ID 1530647879-10007-10-git-send-email-pawell@cadence.com (mailing list archive)
State New, archived
Headers show

Commit Message

Pawel Laszczak July 3, 2018, 7:57 p.m. UTC
Signed-off-by: Laszczak Pawel <pawell@cadence.com>
---
 drivers/usb/usbssp/gadget-debugfs.c | 514 ++++++++++++++++++++++++++++
 drivers/usb/usbssp/gadget-debugfs.h | 137 ++++++++
 2 files changed, 651 insertions(+)
 create mode 100644 drivers/usb/usbssp/gadget-debugfs.c
 create mode 100644 drivers/usb/usbssp/gadget-debugfs.h

Comments

Greg KH July 4, 2018, 9:15 a.m. UTC | #1
On Tue, Jul 03, 2018 at 08:57:53PM +0100, Pawel Laszczak wrote:
> Signed-off-by: Laszczak Pawel <pawell@cadence.com>
> ---

Again for all of these, you need a changelog text.

>  drivers/usb/usbssp/gadget-debugfs.c | 514 ++++++++++++++++++++++++++++
>  drivers/usb/usbssp/gadget-debugfs.h | 137 ++++++++
>  2 files changed, 651 insertions(+)
>  create mode 100644 drivers/usb/usbssp/gadget-debugfs.c
>  create mode 100644 drivers/usb/usbssp/gadget-debugfs.h
> 
> diff --git a/drivers/usb/usbssp/gadget-debugfs.c b/drivers/usb/usbssp/gadget-debugfs.c
> new file mode 100644
> index 000000000000..c0d1e96728e6
> --- /dev/null
> +++ b/drivers/usb/usbssp/gadget-debugfs.c
> @@ -0,0 +1,514 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * USBSSP device controller driver
> + *
> + * Copyright (C) 2018 Cadence.
> + *
> + * Author: Pawel Laszczak
> + * Some code borrowed from the Linux XHCI driver.

What code was borrowed?  Please acknowledge that copyright.

Also, why isn't Pawel's signed-off-by on this?

thanks,

greg k-h
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Pawel Laszczak July 5, 2018, 9:44 a.m. UTC | #2
> > Signed-off-by: Laszczak Pawel <pawell@cadence.com>
> > ---
> 
> Again for all of these, you need a changelog text.
> 
> >  drivers/usb/usbssp/gadget-debugfs.c | 514
> ++++++++++++++++++++++++++++
> >  drivers/usb/usbssp/gadget-debugfs.h | 137 ++++++++
> >  2 files changed, 651 insertions(+)
> >  create mode 100644 drivers/usb/usbssp/gadget-debugfs.c
> >  create mode 100644 drivers/usb/usbssp/gadget-debugfs.h
> >
> > diff --git a/drivers/usb/usbssp/gadget-debugfs.c
> b/drivers/usb/usbssp/gadget-debugfs.c
> > new file mode 100644
> > index 000000000000..c0d1e96728e6
> > --- /dev/null
> > +++ b/drivers/usb/usbssp/gadget-debugfs.c
> > @@ -0,0 +1,514 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * USBSSP device controller driver
> > + *
> > + * Copyright (C) 2018 Cadence.
> > + *
> > + * Author: Pawel Laszczak
> > + * Some code borrowed from the Linux XHCI driver.
> 
> What code was borrowed?  Please acknowledge that copyright.

USBSSP controller is very similar to XHCI controller and 
is mostly  compliance with XHCI specification.  
In result, driver for device mode based on 
drivers/usb/host/xhci* driver. 

Especially xhci.c, xhci-ring.c, xhci-mem.c , xhci-debugfs.c
and xhci-trace.h was re-used. By borrowed I means that these 
files have been taken from xhci driver and have been adopted
in such way that it can be use for the device side. 
Probably this sentence should looks like: 
" A  lot of code based on Linux XHCI driver" ?

You know, the most of algorithm for handling transfer and
memory management are the same as for XHCI driver.

Because the USB gadget API in kernel completely different 
from Host USB API, so files had to been changed very much. 

What do you think by "Please acknowledge that copyright" ?

"
The standard header for xhci driver looks like: 
// SPDX-License-Identifier: GPL-2.0
/*
 * xHCI host controller driver PCI Bus Glue.
 *
 * Copyright (C) 2008 Intel Corp.
 *
 * Author: Sarah Sharp
 * Some code borrowed from the Linux EHCI driver.
 */
"
Should I add In my header:
Copyright (C) 2018 Cadence. 
Copyright (C) 2008 Intel Corp.

or something like this:
.... 
A  lot of code based on Linux XHCI driver
Origin: Copyright (C) 2008 Intel Corp

Thanks very much for all advice and comments. 
Pawel Laszczak
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Greg KH July 5, 2018, 3:13 p.m. UTC | #3
On Thu, Jul 05, 2018 at 09:44:27AM +0000, Pawel Laszczak wrote:
> > > Signed-off-by: Laszczak Pawel <pawell@cadence.com>
> > > ---
> > 
> > Again for all of these, you need a changelog text.
> > 
> > >  drivers/usb/usbssp/gadget-debugfs.c | 514
> > ++++++++++++++++++++++++++++
> > >  drivers/usb/usbssp/gadget-debugfs.h | 137 ++++++++
> > >  2 files changed, 651 insertions(+)
> > >  create mode 100644 drivers/usb/usbssp/gadget-debugfs.c
> > >  create mode 100644 drivers/usb/usbssp/gadget-debugfs.h
> > >
> > > diff --git a/drivers/usb/usbssp/gadget-debugfs.c
> > b/drivers/usb/usbssp/gadget-debugfs.c
> > > new file mode 100644
> > > index 000000000000..c0d1e96728e6
> > > --- /dev/null
> > > +++ b/drivers/usb/usbssp/gadget-debugfs.c
> > > @@ -0,0 +1,514 @@
> > > +// SPDX-License-Identifier: GPL-2.0
> > > +/*
> > > + * USBSSP device controller driver
> > > + *
> > > + * Copyright (C) 2018 Cadence.
> > > + *
> > > + * Author: Pawel Laszczak
> > > + * Some code borrowed from the Linux XHCI driver.
> > 
> > What code was borrowed?  Please acknowledge that copyright.
> 
> USBSSP controller is very similar to XHCI controller and 
> is mostly  compliance with XHCI specification.  
> In result, driver for device mode based on 
> drivers/usb/host/xhci* driver. 
> 
> Especially xhci.c, xhci-ring.c, xhci-mem.c , xhci-debugfs.c
> and xhci-trace.h was re-used. By borrowed I means that these 
> files have been taken from xhci driver and have been adopted
> in such way that it can be use for the device side. 
> Probably this sentence should looks like: 
> " A  lot of code based on Linux XHCI driver" ?

Be specific, just like you said so here.  And include the copyright
ownership of that code please, because it is relevant here.

> You know, the most of algorithm for handling transfer and
> memory management are the same as for XHCI driver.
> 
> Because the USB gadget API in kernel completely different 
> from Host USB API, so files had to been changed very much. 
> 
> What do you think by "Please acknowledge that copyright" ?
> 
> "
> The standard header for xhci driver looks like: 
> // SPDX-License-Identifier: GPL-2.0
> /*
>  * xHCI host controller driver PCI Bus Glue.
>  *
>  * Copyright (C) 2008 Intel Corp.
>  *
>  * Author: Sarah Sharp
>  * Some code borrowed from the Linux EHCI driver.
>  */
> "
> Should I add In my header:
> Copyright (C) 2018 Cadence. 
> Copyright (C) 2008 Intel Corp.
> 
> or something like this:
> .... 
> A  lot of code based on Linux XHCI driver
> Origin: Copyright (C) 2008 Intel Corp

Yes, that would be good.

thanks,

greg k-h
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/usb/usbssp/gadget-debugfs.c b/drivers/usb/usbssp/gadget-debugfs.c
new file mode 100644
index 000000000000..c0d1e96728e6
--- /dev/null
+++ b/drivers/usb/usbssp/gadget-debugfs.c
@@ -0,0 +1,514 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * USBSSP device controller driver
+ *
+ * Copyright (C) 2018 Cadence.
+ *
+ * Author: Pawel Laszczak
+ * Some code borrowed from the Linux XHCI driver.
+ */
+
+#include <linux/slab.h>
+
+#include "gadget.h"
+#include "gadget-debugfs.h"
+
+static const struct debugfs_reg32 usbssp_cap_regs[] = {
+	dump_register(CAPLENGTH),
+	dump_register(HCSPARAMS1),
+	dump_register(HCSPARAMS2),
+	dump_register(HCSPARAMS3),
+	dump_register(HCCPARAMS1),
+	dump_register(DOORBELLOFF),
+	dump_register(RUNTIMEOFF),
+	dump_register(HCCPARAMS2),
+};
+
+static const struct debugfs_reg32 usbssp_op_regs[] = {
+	dump_register(USBCMD),
+	dump_register(USBSTS),
+	dump_register(PAGESIZE),
+	dump_register(DNCTRL),
+	dump_register(CRCR),
+	dump_register(DCBAAP_LOW),
+	dump_register(DCBAAP_HIGH),
+	dump_register(CONFIG),
+};
+
+static const struct debugfs_reg32 usbssp_runtime_regs[] = {
+	dump_register(MFINDEX),
+	dump_register(IR0_IMAN),
+	dump_register(IR0_IMOD),
+	dump_register(IR0_ERSTSZ),
+	dump_register(IR0_ERSTBA_LOW),
+	dump_register(IR0_ERSTBA_HIGH),
+	dump_register(IR0_ERDP_LOW),
+	dump_register(IR0_ERDP_HIGH),
+};
+
+static const struct debugfs_reg32 usbssp_extcap_legsup[] = {
+	dump_register(EXTCAP_USBLEGSUP),
+	dump_register(EXTCAP_USBLEGCTLSTS),
+};
+
+static const struct debugfs_reg32 usbssp_extcap_protocol[] = {
+	dump_register(EXTCAP_REVISION),
+	dump_register(EXTCAP_NAME),
+	dump_register(EXTCAP_PORTINFO),
+	dump_register(EXTCAP_PORTTYPE),
+	dump_register(EXTCAP_MANTISSA1),
+	dump_register(EXTCAP_MANTISSA2),
+	dump_register(EXTCAP_MANTISSA3),
+	dump_register(EXTCAP_MANTISSA4),
+	dump_register(EXTCAP_MANTISSA5),
+	dump_register(EXTCAP_MANTISSA6),
+};
+
+static const struct debugfs_reg32 usbssp_extcap_dbc[] = {
+	dump_register(EXTCAP_DBC_CAPABILITY),
+	dump_register(EXTCAP_DBC_DOORBELL),
+	dump_register(EXTCAP_DBC_ERSTSIZE),
+	dump_register(EXTCAP_DBC_ERST_LOW),
+	dump_register(EXTCAP_DBC_ERST_HIGH),
+	dump_register(EXTCAP_DBC_ERDP_LOW),
+	dump_register(EXTCAP_DBC_ERDP_HIGH),
+	dump_register(EXTCAP_DBC_CONTROL),
+	dump_register(EXTCAP_DBC_STATUS),
+	dump_register(EXTCAP_DBC_PORTSC),
+	dump_register(EXTCAP_DBC_CONT_LOW),
+	dump_register(EXTCAP_DBC_CONT_HIGH),
+	dump_register(EXTCAP_DBC_DEVINFO1),
+	dump_register(EXTCAP_DBC_DEVINFO2),
+};
+
+static struct dentry *usbssp_debugfs_root;
+
+static struct usbssp_regset *usbssp_debugfs_alloc_regset(
+				struct usbssp_udc *usbssp_data)
+{
+	struct usbssp_regset *regset;
+
+	regset = kzalloc(sizeof(*regset), GFP_KERNEL);
+	if (!regset)
+		return NULL;
+
+	/*
+	 * The allocation and free of regset are executed in order.
+	 * We needn't a lock here.
+	 */
+	INIT_LIST_HEAD(&regset->list);
+	list_add_tail(&regset->list, &usbssp_data->regset_list);
+
+	return regset;
+}
+
+static void usbssp_debugfs_free_regset(struct usbssp_regset *regset)
+{
+	if (!regset)
+		return;
+
+	list_del(&regset->list);
+	kfree(regset);
+}
+
+static void usbssp_debugfs_regset(struct usbssp_udc *usbssp_data, u32 base,
+				  const struct debugfs_reg32 *regs,
+				  size_t nregs, struct dentry *parent,
+				  const char *fmt, ...)
+{
+	struct usbssp_regset *rgs;
+	va_list args;
+	struct debugfs_regset32	*regset;
+
+	rgs = usbssp_debugfs_alloc_regset(usbssp_data);
+	if (!rgs)
+		return;
+
+	va_start(args, fmt);
+	vsnprintf(rgs->name, sizeof(rgs->name), fmt, args);
+	va_end(args);
+
+	regset = &rgs->regset;
+	regset->regs = regs;
+	regset->nregs = nregs;
+	regset->base = usbssp_data->regs + base;
+
+	debugfs_create_regset32((const char *)rgs->name, 0444, parent, regset);
+}
+
+static void usbssp_debugfs_extcap_regset(struct usbssp_udc *usbssp_data,
+					 int cap_id,
+					 const struct debugfs_reg32 *regs,
+					 size_t n, const char *cap_name)
+{
+	u32 offset;
+	int index = 0;
+	size_t psic, nregs = n;
+	void __iomem *base = &usbssp_data->cap_regs->hc_capbase;
+
+	offset = usbssp_find_next_ext_cap(base, 0, cap_id);
+	while (offset) {
+		if (cap_id == USBSSP_EXT_CAPS_PROTOCOL) {
+			psic = USBSSP_EXT_PORT_PSIC(readl(base + offset + 8));
+			nregs = min(4 + psic, n);
+		}
+
+		usbssp_debugfs_regset(usbssp_data, offset, regs, nregs,
+				usbssp_data->debugfs_root, "%s:%02d",
+				cap_name, index);
+		offset = usbssp_find_next_ext_cap(base, offset, cap_id);
+		index++;
+	}
+}
+
+static int usbssp_ring_enqueue_show(struct seq_file *s, void *unused)
+{
+	dma_addr_t dma;
+	struct usbssp_ring *ring = *(struct usbssp_ring **)s->private;
+
+	dma = usbssp_trb_virt_to_dma(ring->enq_seg, ring->enqueue);
+	seq_printf(s, "%pad\n", &dma);
+
+	return 0;
+}
+
+static int usbssp_ring_dequeue_show(struct seq_file *s, void *unused)
+{
+	dma_addr_t dma;
+	struct usbssp_ring *ring = *(struct usbssp_ring **)s->private;
+
+	dma = usbssp_trb_virt_to_dma(ring->deq_seg, ring->dequeue);
+	seq_printf(s, "%pad\n", &dma);
+
+	return 0;
+}
+
+static int usbssp_ring_cycle_show(struct seq_file *s, void *unused)
+{
+	struct usbssp_ring *ring = *(struct usbssp_ring **)s->private;
+
+	seq_printf(s, "%d\n", ring->cycle_state);
+
+	return 0;
+}
+
+static void usbssp_ring_dump_segment(struct seq_file *s,
+				     struct usbssp_segment *seg)
+{
+	int i;
+	dma_addr_t dma;
+	union usbssp_trb *trb;
+
+	for (i = 0; i < TRBS_PER_SEGMENT; i++) {
+		trb = &seg->trbs[i];
+		dma = seg->dma + i * sizeof(*trb);
+		seq_printf(s, "%pad: %s\n", &dma,
+				usbssp_decode_trb(trb->generic.field[0],
+					trb->generic.field[1],
+					trb->generic.field[2],
+					trb->generic.field[3]));
+	}
+}
+
+static int usbssp_ring_trb_show(struct seq_file *s, void *unused)
+{
+	int i;
+	struct usbssp_ring *ring = *(struct usbssp_ring **)s->private;
+	struct usbssp_segment *seg = ring->first_seg;
+
+	for (i = 0; i < ring->num_segs; i++) {
+		usbssp_ring_dump_segment(s, seg);
+		seg = seg->next;
+	}
+
+	return 0;
+}
+
+static struct usbssp_file_map ring_files[] = {
+	{"enqueue",	usbssp_ring_enqueue_show, },
+	{"dequeue",	usbssp_ring_dequeue_show, },
+	{"cycle",	usbssp_ring_cycle_show, },
+	{"trbs",	usbssp_ring_trb_show, },
+};
+
+static int usbssp_ring_open(struct inode *inode, struct file *file)
+{
+	int i;
+	struct usbssp_file_map *f_map;
+	const char *file_name = file_dentry(file)->d_iname;
+
+	for (i = 0; i < ARRAY_SIZE(ring_files); i++) {
+		f_map = &ring_files[i];
+
+		if (strcmp(f_map->name, file_name) == 0)
+			break;
+	}
+
+	return single_open(file, f_map->show, inode->i_private);
+	return 0;
+}
+
+static const struct file_operations usbssp_ring_fops = {
+	.open = usbssp_ring_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static int usbssp_slot_context_show(struct seq_file *s, void *unused)
+{
+	struct usbssp_udc *usbssp_data;
+	struct usbssp_slot_ctx *slot_ctx;
+	struct usbssp_slot_priv *priv = s->private;
+	struct usbssp_device *dev = priv->dev;
+
+	usbssp_data = gadget_to_usbssp(dev->gadget);
+	slot_ctx = usbssp_get_slot_ctx(usbssp_data, dev->out_ctx);
+	seq_printf(s, "%pad: %s\n", &dev->out_ctx->dma,
+		   usbssp_decode_slot_context(slot_ctx->dev_info,
+				slot_ctx->dev_info2, slot_ctx->int_target,
+				slot_ctx->dev_state));
+
+	return 0;
+}
+
+static int usbssp_endpoint_context_show(struct seq_file *s, void *unused)
+{
+	int dci;
+	dma_addr_t dma;
+	struct usbssp_udc *usbssp_data;
+	struct usbssp_ep_ctx *ep_ctx;
+	struct usbssp_slot_priv	*priv = s->private;
+	struct usbssp_device *dev = priv->dev;
+
+	usbssp_data = gadget_to_usbssp(dev->gadget);
+
+	for (dci = 1; dci < 32; dci++) {
+		ep_ctx = usbssp_get_ep_ctx(usbssp_data, dev->out_ctx, dci);
+		dma = dev->out_ctx->dma +
+		      dci * CTX_SIZE(usbssp_data->hcc_params);
+		seq_printf(s, "%pad: %s\n", &dma,
+			   usbssp_decode_ep_context(ep_ctx->ep_info,
+					ep_ctx->ep_info2, ep_ctx->deq,
+					ep_ctx->tx_info));
+	}
+
+	return 0;
+}
+
+static int usbssp_device_name_show(struct seq_file *s, void *unused)
+{
+	struct usbssp_slot_priv *priv = s->private;
+	struct usbssp_device *dev = priv->dev;
+
+	seq_printf(s, "%s\n", dev_name(&dev->gadget->dev));
+
+	return 0;
+}
+
+static struct usbssp_file_map context_files[] = {
+	{"name",	 usbssp_device_name_show, },
+	{"slot-context", usbssp_slot_context_show, },
+	{"ep-context",	 usbssp_endpoint_context_show, },
+};
+
+static int usbssp_context_open(struct inode *inode, struct file *file)
+{
+	int i;
+	struct usbssp_file_map *f_map;
+	const char *file_name = file_dentry(file)->d_iname;
+
+	for (i = 0; i < ARRAY_SIZE(context_files); i++) {
+		f_map = &context_files[i];
+
+		if (strcmp(f_map->name, file_name) == 0)
+			break;
+	}
+
+	return single_open(file, f_map->show, inode->i_private);
+}
+
+static const struct file_operations usbssp_context_fops = {
+	.open		= usbssp_context_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static void usbssp_debugfs_create_files(struct usbssp_udc *usbssp_data,
+					struct usbssp_file_map *files,
+					size_t nentries, void *data,
+					struct dentry *parent,
+					const struct file_operations *fops)
+{
+	int i;
+
+	for (i = 0; i < nentries; i++)
+		debugfs_create_file(files[i].name, 0444, parent, data, fops);
+}
+
+static struct dentry *usbssp_debugfs_create_ring_dir(struct usbssp_udc
+						     *usbssp_data,
+						     struct usbssp_ring **ring,
+						     const char *name,
+						     struct dentry *parent)
+{
+	struct dentry *dir;
+
+	dir = debugfs_create_dir(name, parent);
+	usbssp_debugfs_create_files(usbssp_data, ring_files,
+			ARRAY_SIZE(ring_files), ring, dir, &usbssp_ring_fops);
+
+	return dir;
+}
+
+static void usbssp_debugfs_create_context_files(struct usbssp_udc *usbssp_data,
+						struct dentry *parent,
+						int slot_id)
+{
+	struct usbssp_device	*dev = &usbssp_data->devs;
+
+	usbssp_debugfs_create_files(usbssp_data, context_files,
+			ARRAY_SIZE(context_files), dev->debugfs_private,
+			parent, &usbssp_context_fops);
+}
+
+void usbssp_debugfs_create_endpoint(struct usbssp_udc *usbssp_data,
+				    struct usbssp_device *dev,
+				    int ep_index)
+{
+	struct usbssp_ep_priv *epriv;
+	struct usbssp_slot_priv *spriv = dev->debugfs_private;
+
+	if (spriv->eps[ep_index])
+		return;
+
+	epriv = kzalloc(sizeof(*epriv), GFP_KERNEL);
+	if (!epriv)
+		return;
+
+	snprintf(epriv->name, sizeof(epriv->name), "ep%02d", ep_index);
+	epriv->root = usbssp_debugfs_create_ring_dir(usbssp_data,
+				&dev->eps[ep_index].ring, epriv->name,
+				spriv->root);
+	spriv->eps[ep_index] = epriv;
+}
+
+void usbssp_debugfs_remove_endpoint(struct usbssp_udc *usbssp_data,
+				    struct usbssp_device *dev,
+				    int ep_index)
+{
+	struct usbssp_ep_priv *epriv;
+	struct usbssp_slot_priv *spriv = dev->debugfs_private;
+
+	if (!spriv || !spriv->eps[ep_index])
+		return;
+
+	epriv = spriv->eps[ep_index];
+	debugfs_remove_recursive(epriv->root);
+	spriv->eps[ep_index] = NULL;
+	kfree(epriv);
+}
+
+void usbssp_debugfs_create_slot(struct usbssp_udc *usbssp_data, int slot_id)
+{
+	struct usbssp_slot_priv *priv;
+	struct usbssp_device *dev = &usbssp_data->devs;
+
+	priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
+	if (!priv)
+		return;
+
+	snprintf(priv->name, sizeof(priv->name), "%02d", slot_id);
+	priv->root = debugfs_create_dir(priv->name, usbssp_data->debugfs_slots);
+	priv->dev = dev;
+	dev->debugfs_private = priv;
+
+	usbssp_debugfs_create_ring_dir(usbssp_data, &dev->eps[0].ring,
+			"ep00", priv->root);
+
+	usbssp_debugfs_create_context_files(usbssp_data, priv->root, slot_id);
+}
+
+void usbssp_debugfs_remove_slot(struct usbssp_udc *usbssp_data, int slot_id)
+{
+	int i;
+	struct usbssp_slot_priv *priv;
+	struct usbssp_device *dev = &usbssp_data->devs;
+
+	if (!dev || !dev->debugfs_private)
+		return;
+
+	priv = dev->debugfs_private;
+
+	debugfs_remove_recursive(priv->root);
+
+	for (i = 0; i < 31; i++)
+		kfree(priv->eps[i]);
+
+	kfree(priv);
+	dev->debugfs_private = NULL;
+}
+
+void usbssp_debugfs_init(struct usbssp_udc *usbssp_data)
+{
+	struct device *dev =  usbssp_data->dev;
+
+	usbssp_data->debugfs_root = debugfs_create_dir(dev_name(dev),
+					usbssp_debugfs_root);
+
+	INIT_LIST_HEAD(&usbssp_data->regset_list);
+
+	usbssp_debugfs_regset(usbssp_data,
+			0, usbssp_cap_regs, ARRAY_SIZE(usbssp_cap_regs),
+			usbssp_data->debugfs_root, "reg-cap");
+
+	usbssp_debugfs_regset(usbssp_data,
+			HC_LENGTH(readl(&usbssp_data->cap_regs->hc_capbase)),
+			usbssp_op_regs, ARRAY_SIZE(usbssp_op_regs),
+			usbssp_data->debugfs_root, "reg-op");
+
+	usbssp_debugfs_regset(usbssp_data,
+			readl(&usbssp_data->cap_regs->run_regs_off) & RTSOFF_MASK,
+			usbssp_runtime_regs, ARRAY_SIZE(usbssp_runtime_regs),
+			usbssp_data->debugfs_root, "reg-runtime");
+
+	usbssp_debugfs_extcap_regset(usbssp_data, USBSSP_EXT_CAPS_PROTOCOL,
+			usbssp_extcap_protocol,
+			ARRAY_SIZE(usbssp_extcap_protocol),
+			"reg-ext-protocol");
+
+	usbssp_debugfs_create_ring_dir(usbssp_data, &usbssp_data->cmd_ring,
+			"command-ring",
+			usbssp_data->debugfs_root);
+
+	usbssp_debugfs_create_ring_dir(usbssp_data, &usbssp_data->event_ring,
+			"event-ring",
+			usbssp_data->debugfs_root);
+
+	usbssp_data->debugfs_slots = debugfs_create_dir("devices",
+			usbssp_data->debugfs_root);
+}
+
+void usbssp_debugfs_exit(struct usbssp_udc *usbssp_data)
+{
+	struct usbssp_regset *rgs, *tmp;
+
+	debugfs_remove_recursive(usbssp_data->debugfs_root);
+	usbssp_data->debugfs_root = NULL;
+	usbssp_data->debugfs_slots = NULL;
+
+	list_for_each_entry_safe(rgs, tmp, &usbssp_data->regset_list, list)
+		usbssp_debugfs_free_regset(rgs);
+}
+
+void __init usbssp_debugfs_create_root(void)
+{
+	usbssp_debugfs_root = debugfs_create_dir("usbssp", usb_debug_root);
+}
+
+void __exit usbssp_debugfs_remove_root(void)
+{
+	debugfs_remove_recursive(usbssp_debugfs_root);
+	usbssp_debugfs_root = NULL;
+}
diff --git a/drivers/usb/usbssp/gadget-debugfs.h b/drivers/usb/usbssp/gadget-debugfs.h
new file mode 100644
index 000000000000..53adb028e7f2
--- /dev/null
+++ b/drivers/usb/usbssp/gadget-debugfs.h
@@ -0,0 +1,137 @@ 
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * USBSSP device controller driver
+ *
+ * Copyright (C) 2018 Cadence.
+ *
+ * Author: Pawel Laszczak
+ * Some code borrowed from the Linux XHCI driver.
+ */
+
+#ifndef __LINUX_USBSSP_DEBUGFS_H
+#define __LINUX_USBSSP_DEBUGFS_H
+
+#include <linux/debugfs.h>
+
+#define DEBUGFS_NAMELEN 32
+
+#define REG_CAPLENGTH		0x00
+#define REG_HCSPARAMS1		0x04
+#define REG_HCSPARAMS2		0x08
+#define REG_HCSPARAMS3		0x0c
+#define REG_HCCPARAMS1		0x10
+#define REG_DOORBELLOFF		0x14
+#define REG_RUNTIMEOFF		0x18
+#define REG_HCCPARAMS2		0x1c
+
+#define	REG_USBCMD		0x00
+#define REG_USBSTS		0x04
+#define REG_PAGESIZE		0x08
+#define REG_DNCTRL		0x14
+#define REG_CRCR		0x18
+#define REG_DCBAAP_LOW		0x30
+#define REG_DCBAAP_HIGH		0x34
+#define REG_CONFIG		0x38
+
+#define REG_MFINDEX		0x00
+#define REG_IR0_IMAN		0x20
+#define REG_IR0_IMOD		0x24
+#define REG_IR0_ERSTSZ		0x28
+#define REG_IR0_ERSTBA_LOW	0x30
+#define REG_IR0_ERSTBA_HIGH	0x34
+#define REG_IR0_ERDP_LOW	0x38
+#define REG_IR0_ERDP_HIGH	0x3c
+
+#define REG_EXTCAP_USBLEGSUP	0x00
+#define REG_EXTCAP_USBLEGCTLSTS	0x04
+
+#define REG_EXTCAP_REVISION	0x00
+#define REG_EXTCAP_NAME		0x04
+#define REG_EXTCAP_PORTINFO	0x08
+#define REG_EXTCAP_PORTTYPE	0x0c
+#define REG_EXTCAP_MANTISSA1	0x10
+#define REG_EXTCAP_MANTISSA2	0x14
+#define REG_EXTCAP_MANTISSA3	0x18
+#define REG_EXTCAP_MANTISSA4	0x1c
+#define REG_EXTCAP_MANTISSA5	0x20
+#define REG_EXTCAP_MANTISSA6	0x24
+
+#define REG_EXTCAP_DBC_CAPABILITY	0x00
+#define REG_EXTCAP_DBC_DOORBELL		0x04
+#define REG_EXTCAP_DBC_ERSTSIZE		0x08
+#define REG_EXTCAP_DBC_ERST_LOW		0x10
+#define REG_EXTCAP_DBC_ERST_HIGH	0x14
+#define REG_EXTCAP_DBC_ERDP_LOW		0x18
+#define REG_EXTCAP_DBC_ERDP_HIGH	0x1c
+#define REG_EXTCAP_DBC_CONTROL		0x20
+#define REG_EXTCAP_DBC_STATUS		0x24
+#define REG_EXTCAP_DBC_PORTSC		0x28
+#define REG_EXTCAP_DBC_CONT_LOW		0x30
+#define REG_EXTCAP_DBC_CONT_HIGH	0x34
+#define REG_EXTCAP_DBC_DEVINFO1		0x38
+#define REG_EXTCAP_DBC_DEVINFO2		0x3c
+
+#define dump_register(nm)		\
+{					\
+	.name	= __stringify(nm),	\
+	.offset	= REG_ ##nm,		\
+}
+
+struct usbssp_regset {
+	char			name[DEBUGFS_NAMELEN];
+	struct debugfs_regset32	regset;
+	size_t			nregs;
+	struct dentry		*parent;
+	struct list_head	list;
+};
+
+struct usbssp_file_map {
+	const char		*name;
+	int			(*show)(struct seq_file *s, void *unused);
+};
+
+struct usbssp_ep_priv {
+	char			name[DEBUGFS_NAMELEN];
+	struct dentry		*root;
+};
+
+struct usbssp_slot_priv {
+	char			name[DEBUGFS_NAMELEN];
+	struct dentry		*root;
+	struct usbssp_ep_priv	*eps[31];
+	struct usbssp_device	*dev;
+};
+
+#ifdef CONFIG_DEBUG_FS
+void usbssp_debugfs_init(struct usbssp_udc *usbssp_data);
+void usbssp_debugfs_exit(struct usbssp_udc *usbssp_data);
+void __init usbssp_debugfs_create_root(void);
+void __exit usbssp_debugfs_remove_root(void);
+void usbssp_debugfs_create_slot(struct usbssp_udc *usbssp_data, int slot_id);
+void usbssp_debugfs_remove_slot(struct usbssp_udc *usbssp_data, int slot_id);
+void usbssp_debugfs_create_endpoint(struct usbssp_udc *usbssp_data,
+				    struct usbssp_device *dev_priv,
+				    int ep_index);
+void usbssp_debugfs_remove_endpoint(struct usbssp_udc *usbssp_data,
+				    struct usbssp_device *dev_priv,
+				    int ep_index);
+#else
+static inline void usbssp_debugfs_init(struct usbssp_udc *usbssp_data) { }
+static inline void usbssp_debugfs_exit(struct usbssp_udc *usbssp_data) { }
+static inline void __init usbssp_debugfs_create_root(void) { }
+static inline void __exit usbssp_debugfs_remove_root(void) { }
+static inline void usbssp_debugfs_create_slot(struct usbssp_udc *usbssp_data,
+					      int s) { }
+static inline void usbssp_debugfs_remove_slot(struct usbssp_udc *xusbssp_data,
+					      int s) { }
+static inline void
+usbssp_debugfs_create_endpoint(struct usbssp_udc *usbssp_data,
+			       struct usbssp_device *dev_priv,
+			       int ep_index) { }
+static inline void
+usbssp_debugfs_remove_endpoint(struct usbssp_udc *usbssp_data,
+			       struct usbssp_device *dev_priv,
+			       int ep_index) { }
+#endif /* CONFIG_DEBUG_FS */
+#endif /*__LINUX_USBSSP_DEBUGFS_H*/