All of lore.kernel.org
 help / color / mirror / Atom feed
From: Rui Miguel Silva <rui.silva@linaro.org>
To: u-boot@lists.denx.de, Marek Vasut <marex@denx.de>
Cc: Tom Rini <trini@konsulko.com>, Rui Miguel Silva <rui.silva@linaro.org>
Subject: [PATCH v5 1/3] usb: common: move urb code to common
Date: Wed, 29 Jun 2022 11:06:14 +0100	[thread overview]
Message-ID: <20220629100616.417550-2-rui.silva@linaro.org> (raw)
In-Reply-To: <20220629100616.417550-1-rui.silva@linaro.org>

Move urb code from musb only use to a more common scope, so other
drivers in the future can use the handling of urb in usb.

Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org>
---
 drivers/usb/common/Makefile                   |   3 +
 drivers/usb/common/usb_urb.c                  | 160 ++++++++++++++++++
 drivers/usb/host/r8a66597-hcd.c               |  30 +---
 drivers/usb/musb-new/musb_core.c              |   2 +-
 drivers/usb/musb-new/musb_host.c              |   2 +-
 drivers/usb/musb-new/musb_host.h              |   2 +-
 drivers/usb/musb-new/musb_uboot.c             |  38 +----
 drivers/usb/musb-new/musb_uboot.h             |   2 +-
 .../linux/usb/usb_urb_compat.h                |  47 ++++-
 include/usb_defs.h                            |  32 ++++
 10 files changed, 242 insertions(+), 76 deletions(-)
 create mode 100644 drivers/usb/common/usb_urb.c
 rename drivers/usb/musb-new/usb-compat.h => include/linux/usb/usb_urb_compat.h (59%)

diff --git a/drivers/usb/common/Makefile b/drivers/usb/common/Makefile
index 3bedbf213f47..7eacc909f2d9 100644
--- a/drivers/usb/common/Makefile
+++ b/drivers/usb/common/Makefile
@@ -4,5 +4,8 @@
 #
 
 obj-$(CONFIG_$(SPL_)DM_USB) += common.o
+obj-$(CONFIG_USB_MUSB_HOST) += usb_urb.o
+obj-$(CONFIG_USB_MUSB_GADGET) += usb_urb.o
+obj-$(CONFIG_USB_R8A66597_HCD) += usb_urb.o
 obj-$(CONFIG_USB_EHCI_FSL) += fsl-dt-fixup.o fsl-errata.o
 obj-$(CONFIG_USB_XHCI_FSL) += fsl-dt-fixup.o fsl-errata.o
diff --git a/drivers/usb/common/usb_urb.c b/drivers/usb/common/usb_urb.c
new file mode 100644
index 000000000000..be3b6b9f32e8
--- /dev/null
+++ b/drivers/usb/common/usb_urb.c
@@ -0,0 +1,160 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Common code for usb urb handling, based on the musb-new code
+ *
+ * Copyright 2021 Linaro, Rui Miguel Silva <rui.silva@linaro.org>
+ *
+ */
+
+#include <dm/device.h>
+#include <dm/device_compat.h>
+#include <linux/usb/usb_urb_compat.h>
+
+#include <time.h>
+#include <usb.h>
+
+#if CONFIG_IS_ENABLED(DM_USB)
+struct usb_device *usb_dev_get_parent(struct usb_device *udev)
+{
+	struct udevice *parent = udev->dev->parent;
+
+	/*
+	 * When called from usb-uclass.c: usb_scan_device() udev->dev points
+	 * to the parent udevice, not the actual udevice belonging to the
+	 * udev as the device is not instantiated yet.
+	 *
+	 * If dev is an usb-bus, then we are called from usb_scan_device() for
+	 * an usb-device plugged directly into the root port, return NULL.
+	 */
+	if (device_get_uclass_id(udev->dev) == UCLASS_USB)
+		return NULL;
+
+	/*
+	 * If these 2 are not the same we are being called from
+	 * usb_scan_device() and udev itself is the parent.
+	 */
+	if (dev_get_parent_priv(udev->dev) != udev)
+		return udev;
+
+	/* We are being called normally, use the parent pointer */
+	if (device_get_uclass_id(parent) == UCLASS_USB_HUB)
+		return dev_get_parent_priv(parent);
+
+	return NULL;
+}
+#else
+struct usb_device *usb_dev_get_parent(struct usb_device *udev)
+{
+	return udev->parent;
+}
+#endif
+
+static void usb_urb_complete(struct urb *urb)
+{
+	urb->dev->status &= ~USB_ST_NOT_PROC;
+	urb->dev->act_len = urb->actual_length;
+
+	if (urb->status == -EINPROGRESS)
+		urb->status = 0;
+}
+
+void usb_urb_fill(struct urb *urb, struct usb_host_endpoint *hep,
+		  struct usb_device *dev, int endpoint_type,
+		  unsigned long pipe, void *buffer, int len,
+		  struct devrequest *setup, int interval)
+{
+	int epnum = usb_pipeendpoint(pipe);
+	int is_in = usb_pipein(pipe);
+	u16 maxpacketsize = is_in ? dev->epmaxpacketin[epnum] :
+					dev->epmaxpacketout[epnum];
+
+	memset(urb, 0, sizeof(struct urb));
+	memset(hep, 0, sizeof(struct usb_host_endpoint));
+	INIT_LIST_HEAD(&hep->urb_list);
+	INIT_LIST_HEAD(&urb->urb_list);
+	urb->ep = hep;
+	urb->complete = usb_urb_complete;
+	urb->status = -EINPROGRESS;
+	urb->dev = dev;
+	urb->pipe = pipe;
+	urb->transfer_buffer = buffer;
+	urb->transfer_dma = (unsigned long)buffer;
+	urb->transfer_buffer_length = len;
+	urb->setup_packet = (unsigned char *)setup;
+
+	urb->ep->desc.wMaxPacketSize = __cpu_to_le16(maxpacketsize);
+	urb->ep->desc.bmAttributes = endpoint_type;
+	urb->ep->desc.bEndpointAddress = ((is_in ? USB_DIR_IN : USB_DIR_OUT) |
+					  epnum);
+	urb->ep->desc.bInterval = interval;
+}
+
+int usb_urb_submit(struct usb_hcd *hcd, struct urb *urb)
+{
+	const struct usb_urb_ops *ops = hcd->urb_ops;
+	unsigned long timeout;
+	int ret;
+
+	if (!ops)
+		return -EINVAL;
+
+	ret = ops->urb_enqueue(hcd, urb, 0);
+	if (ret < 0) {
+		printf("Failed to enqueue URB to controller\n");
+		return ret;
+	}
+
+	timeout = get_timer(0) + USB_TIMEOUT_MS(urb->pipe);
+	do {
+		if (ctrlc())
+			return -EIO;
+		ops->isr(0, hcd);
+	} while (urb->status == -EINPROGRESS && get_timer(0) < timeout);
+
+	if (urb->status == -EINPROGRESS)
+		ops->urb_dequeue(hcd, urb, -ETIME);
+
+	return urb->status;
+}
+
+int usb_urb_submit_control(struct usb_hcd *hcd, struct urb *urb,
+			   struct usb_host_endpoint *hep,
+			   struct usb_device *dev, unsigned long pipe,
+			   void *buffer, int len, struct devrequest *setup,
+			   int interval, enum usb_device_speed speed)
+{
+	const struct usb_urb_ops *ops = hcd->urb_ops;
+
+	usb_urb_fill(urb, hep, dev, USB_ENDPOINT_XFER_CONTROL, pipe, buffer,
+		     len, setup, 0);
+
+	/* Fix speed for non hub-attached devices */
+	if (!usb_dev_get_parent(dev)) {
+		dev->speed = speed;
+		if (ops->hub_control)
+			return ops->hub_control(hcd, dev, pipe, buffer, len,
+						setup);
+	}
+
+	return usb_urb_submit(hcd, urb);
+}
+
+int usb_urb_submit_bulk(struct usb_hcd *hcd, struct urb *urb,
+			struct usb_host_endpoint *hep, struct usb_device *dev,
+			unsigned long pipe, void *buffer, int len)
+{
+	usb_urb_fill(urb, hep, dev, USB_ENDPOINT_XFER_BULK, pipe, buffer, len,
+		     NULL, 0);
+
+	return usb_urb_submit(hcd, urb);
+}
+
+int usb_urb_submit_irq(struct usb_hcd *hcd, struct urb *urb,
+		       struct usb_host_endpoint *hep, struct usb_device *dev,
+		       unsigned long pipe, void *buffer, int len, int interval)
+{
+	usb_urb_fill(urb, hep, dev, USB_ENDPOINT_XFER_INT, pipe, buffer, len,
+		     NULL, interval);
+
+	return usb_urb_submit(hcd, urb);
+}
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
index f1fc93f3d403..3ccbc16da379 100644
--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -14,6 +14,7 @@
 #include <dm/device_compat.h>
 #include <linux/delay.h>
 #include <linux/iopoll.h>
+#include <linux/usb/usb_urb_compat.h>
 #include <power/regulator.h>
 
 #include "r8a66597.h"
@@ -24,35 +25,6 @@
 #define R8A66597_DPRINT(...)
 #endif
 
-static inline struct usb_device *usb_dev_get_parent(struct usb_device *udev)
-{
-	struct udevice *parent = udev->dev->parent;
-
-	/*
-	 * When called from usb-uclass.c: usb_scan_device() udev->dev points
-	 * to the parent udevice, not the actual udevice belonging to the
-	 * udev as the device is not instantiated yet.
-	 *
-	 * If dev is an usb-bus, then we are called from usb_scan_device() for
-	 * an usb-device plugged directly into the root port, return NULL.
-	 */
-	if (device_get_uclass_id(udev->dev) == UCLASS_USB)
-		return NULL;
-
-	/*
-	 * If these 2 are not the same we are being called from
-	 * usb_scan_device() and udev itself is the parent.
-	 */
-	if (dev_get_parent_priv(udev->dev) != udev)
-		return udev;
-
-	/* We are being called normally, use the parent pointer */
-	if (device_get_uclass_id(parent) == UCLASS_USB_HUB)
-		return dev_get_parent_priv(parent);
-
-	return NULL;
-}
-
 static void get_hub_data(struct usb_device *dev, u16 *hub_devnum, u16 *hubport)
 {
 	struct usb_device *parent = usb_dev_get_parent(dev);
diff --git a/drivers/usb/musb-new/musb_core.c b/drivers/usb/musb-new/musb_core.c
index 18d9bc805f8a..fc7af7484e4c 100644
--- a/drivers/usb/musb-new/musb_core.c
+++ b/drivers/usb/musb-new/musb_core.c
@@ -89,9 +89,9 @@
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 #include <linux/usb/musb.h>
+#include <linux/usb/usb_urb_compat.h>
 #include <asm/io.h>
 #include "linux-compat.h"
-#include "usb-compat.h"
 #endif
 
 #include "musb_core.h"
diff --git a/drivers/usb/musb-new/musb_host.c b/drivers/usb/musb-new/musb_host.c
index acb2d40f3b5a..e5905d90d66f 100644
--- a/drivers/usb/musb-new/musb_host.c
+++ b/drivers/usb/musb-new/musb_host.c
@@ -26,8 +26,8 @@
 #include <dm/device_compat.h>
 #include <usb.h>
 #include <linux/bug.h>
+#include <linux/usb/usb_urb_compat.h>
 #include "linux-compat.h"
-#include "usb-compat.h"
 #endif
 
 #include "musb_core.h"
diff --git a/drivers/usb/musb-new/musb_host.h b/drivers/usb/musb-new/musb_host.h
index afc8fa35a738..5a604bdb0cf2 100644
--- a/drivers/usb/musb-new/musb_host.h
+++ b/drivers/usb/musb-new/musb_host.h
@@ -10,7 +10,7 @@
 #ifndef _MUSB_HOST_H
 #define _MUSB_HOST_H
 #ifdef __UBOOT__
-#include "usb-compat.h"
+#include <linux/usb/usb_urb_compat.h>
 #endif
 
 static inline struct usb_hcd *musb_to_hcd(struct musb *musb)
diff --git a/drivers/usb/musb-new/musb_uboot.c b/drivers/usb/musb-new/musb_uboot.c
index 61ff68def2fa..d186facc7e02 100644
--- a/drivers/usb/musb-new/musb_uboot.c
+++ b/drivers/usb/musb-new/musb_uboot.c
@@ -8,10 +8,10 @@
 #include <linux/errno.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
+#include <linux/usb/usb_urb_compat.h>
 
 #include <usb.h>
 #include "linux-compat.h"
-#include "usb-compat.h"
 #include "musb_core.h"
 #include "musb_host.h"
 #include "musb_gadget.h"
@@ -453,39 +453,3 @@ struct musb *musb_register(struct musb_hdrc_platform_data *plat, void *bdata,
 
 	return *musbp;
 }
-
-#if CONFIG_IS_ENABLED(DM_USB)
-struct usb_device *usb_dev_get_parent(struct usb_device *udev)
-{
-	struct udevice *parent = udev->dev->parent;
-
-	/*
-	 * When called from usb-uclass.c: usb_scan_device() udev->dev points
-	 * to the parent udevice, not the actual udevice belonging to the
-	 * udev as the device is not instantiated yet.
-	 *
-	 * If dev is an usb-bus, then we are called from usb_scan_device() for
-	 * an usb-device plugged directly into the root port, return NULL.
-	 */
-	if (device_get_uclass_id(udev->dev) == UCLASS_USB)
-		return NULL;
-
-	/*
-	 * If these 2 are not the same we are being called from
-	 * usb_scan_device() and udev itself is the parent.
-	 */
-	if (dev_get_parent_priv(udev->dev) != udev)
-		return udev;
-
-	/* We are being called normally, use the parent pointer */
-	if (device_get_uclass_id(parent) == UCLASS_USB_HUB)
-		return dev_get_parent_priv(parent);
-
-	return NULL;
-}
-#else
-struct usb_device *usb_dev_get_parent(struct usb_device *udev)
-{
-	return udev->parent;
-}
-#endif
diff --git a/drivers/usb/musb-new/musb_uboot.h b/drivers/usb/musb-new/musb_uboot.h
index 18282efccc9d..6b162f03b19e 100644
--- a/drivers/usb/musb-new/musb_uboot.h
+++ b/drivers/usb/musb-new/musb_uboot.h
@@ -8,8 +8,8 @@
 #define __MUSB_UBOOT_H__
 
 #include <usb.h>
+#include <linux/usb/usb_urb_compat.h>
 #include "linux-compat.h"
-#include "usb-compat.h"
 #include "musb_core.h"
 
 struct musb_host_data {
diff --git a/drivers/usb/musb-new/usb-compat.h b/include/linux/usb/usb_urb_compat.h
similarity index 59%
rename from drivers/usb/musb-new/usb-compat.h
rename to include/linux/usb/usb_urb_compat.h
index df68c9220a7a..2e8c9d8db79a 100644
--- a/drivers/usb/musb-new/usb-compat.h
+++ b/include/linux/usb/usb_urb_compat.h
@@ -1,16 +1,32 @@
-#ifndef __USB_COMPAT_H__
-#define __USB_COMPAT_H__
+/* SPDX-License-Identifier: GPL-2.0+ */
 
-#include "usb.h"
+#ifndef __USB_URB_COMPAT_H__
+#define __USB_URB_COMPAT_H__
+
+#include <linux/compat.h>
+#include <usb.h>
 
 struct udevice;
+struct urb;
+struct usb_hcd;
+
+struct usb_urb_ops {
+	int (*urb_enqueue)(struct usb_hcd *hcd, struct urb *urb,
+			   gfp_t mem_flags);
+	int (*urb_dequeue)(struct usb_hcd *hcd, struct urb *urb, int status);
+	int (*hub_control)(struct usb_hcd *hcd, struct usb_device *dev,
+			   unsigned long pipe, void *buffer, int len,
+			   struct devrequest *setup);
+	irqreturn_t (*isr)(int irq, void *priv);
+};
 
 struct usb_hcd {
 	void *hcd_priv;
+	const struct usb_urb_ops *urb_ops;
 };
 
 struct usb_host_endpoint {
-	struct usb_endpoint_descriptor		desc;
+	struct usb_endpoint_descriptor desc;
 	struct list_head urb_list;
 	void *hcpriv;
 };
@@ -23,8 +39,6 @@ struct usb_host_endpoint {
 #define URB_SHORT_NOT_OK	0x0001	/* report short reads as errors */
 #define URB_ZERO_PACKET		0x0040	/* Finish bulk OUT with short packet */
 
-struct urb;
-
 typedef void (*usb_complete_t)(struct urb *);
 
 struct urb {
@@ -76,4 +90,25 @@ static inline int usb_hcd_unmap_urb_for_dma(struct usb_hcd *hcd,
  */
 struct usb_device *usb_dev_get_parent(struct usb_device *udev);
 
+int usb_urb_submit_control(struct usb_hcd *hcd, struct urb *urb,
+			   struct usb_host_endpoint *hep,
+			   struct usb_device *dev, unsigned long pipe,
+			   void *buffer, int len, struct devrequest *setup,
+			   int interval, enum usb_device_speed speed);
+
+int usb_urb_submit_bulk(struct usb_hcd *hcd, struct urb *urb,
+			struct usb_host_endpoint *hep, struct usb_device *dev,
+			unsigned long pipe, void *buffer, int len);
+
+int usb_urb_submit_irq(struct usb_hcd *hcd, struct urb *urb,
+		       struct usb_host_endpoint *hep, struct usb_device *dev,
+		       unsigned long pipe, void *buffer, int len, int interval);
+
+void usb_urb_fill(struct urb *urb, struct usb_host_endpoint *hep,
+		  struct usb_device *dev, int endpoint_type,
+		  unsigned long pipe, void *buffer, int len,
+		  struct devrequest *setup, int interval);
+
+int usb_urb_submit(struct usb_hcd *hcd, struct urb *urb);
+
 #endif /* __USB_COMPAT_H__ */
diff --git a/include/usb_defs.h b/include/usb_defs.h
index 6dd2c997f9b3..ec00161710a5 100644
--- a/include/usb_defs.h
+++ b/include/usb_defs.h
@@ -81,6 +81,32 @@
 #define EndpointOutRequest \
 	((USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8)
 
+/* class requests from the USB 2.0 hub spec, table 11-15 */
+#define HUB_CLASS_REQ(dir, type, request) ((((dir) | (type)) << 8) | (request))
+/* GetBusState and SetHubDescriptor are optional, omitted */
+#define ClearHubFeature		HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_HUB, \
+					      USB_REQ_CLEAR_FEATURE)
+#define ClearPortFeature	HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_PORT, \
+					      USB_REQ_CLEAR_FEATURE)
+#define GetHubDescriptor	HUB_CLASS_REQ(USB_DIR_IN, USB_RT_HUB, \
+					      USB_REQ_GET_DESCRIPTOR)
+#define GetHubStatus		HUB_CLASS_REQ(USB_DIR_IN, USB_RT_HUB, \
+					      USB_REQ_GET_STATUS)
+#define GetPortStatus		HUB_CLASS_REQ(USB_DIR_IN, USB_RT_PORT, \
+					      USB_REQ_GET_STATUS)
+#define SetHubFeature		HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_HUB, \
+					      USB_REQ_SET_FEATURE)
+#define SetPortFeature		HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_PORT, \
+					      USB_REQ_SET_FEATURE)
+#define ClearTTBuffer		HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_PORT, \
+					      HUB_CLEAR_TT_BUFFER)
+#define ResetTT			HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_PORT, \
+					      HUB_RESET_TT)
+#define GetTTState		HUB_CLASS_REQ(USB_DIR_IN, USB_RT_PORT, \
+					      HUB_GET_TT_STATE)
+#define StopTT			HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_PORT, \
+					      HUB_STOP_TT)
+
 /* Descriptor types */
 #define USB_DT_DEVICE        0x01
 #define USB_DT_CONFIG        0x02
@@ -289,10 +315,16 @@
 #define USB_SS_PORT_STAT_C_CONFIG_ERROR	0x0080
 
 /* wHubCharacteristics (masks) */
+#define HUB_CHAR_COMMON_OCPM        0x0000 /* All ports Over-Current reporting */
+#define HUB_CHAR_INDV_PORT_LPSM     0x0001 /* per-port power control */
+#define HUB_CHAR_NO_LPSM            0x0002 /* no power switching */
 #define HUB_CHAR_LPSM               0x0003
 #define HUB_CHAR_COMPOUND           0x0004
+#define HUB_CHAR_INDV_PORT_OCPM     0x0008 /* per-port Over-current reporting */
+#define HUB_CHAR_NO_OCPM            0x0010 /* No Over-current Protection support */
 #define HUB_CHAR_OCPM               0x0018
 #define HUB_CHAR_TTTT               0x0060 /* TT Think Time mask */
+#define HUB_CHAR_PORTIND            0x0080 /* per-port indicators (LEDs) */
 
 /*
  * Hub Status & Hub Change bit masks
-- 
2.37.0


  reply	other threads:[~2022-06-29 10:06 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-06-29 10:06 [PATCH v5 0/3] usb: add isp1760 hcd support Rui Miguel Silva
2022-06-29 10:06 ` Rui Miguel Silva [this message]
2022-06-29 10:06 ` [PATCH v5 2/3] usb: add isp1760 family driver Rui Miguel Silva
2022-06-29 10:06 ` [PATCH v5 3/3] corstone1000: enable isp1763 usb controller and mmc Rui Miguel Silva

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220629100616.417550-2-rui.silva@linaro.org \
    --to=rui.silva@linaro.org \
    --cc=marex@denx.de \
    --cc=trini@konsulko.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.