[PATCH] Make ci_udc available in SPL

Manuel Traut manut at mecka.net
Thu Apr 7 14:34:21 CEST 2022


This is needed for SDP downloads of eg. fitimages
in SPL stage.

Signed-off-by: Manuel Traut <manut at mecka.net>
---
  common/spl/Kconfig          |  10 +++
  common/usb_hub.c            |   4 +
  drivers/usb/gadget/Makefile |  18 ++--
  drivers/usb/gadget/ci_udc.c | 159 +++++++++++++++++-------------------
  drivers/usb/gadget/ci_udc.h |   2 +-
  drivers/usb/host/Makefile   |   2 +-
  6 files changed, 98 insertions(+), 97 deletions(-)

diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index dc319adeac..f5545d2cb2 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -1181,6 +1181,16 @@ config SPL_USB_GADGET

  if SPL_USB_GADGET

+config SPL_CI_UDC
+	bool "Support USB CI UDC controller in SPL"
+	help
+	  Enables CI UDC driver to be available in SPL
+
+config SPL_USB_EHCI_HCD
+	bool "Support USB EHCI Host in SPL"
+	help
+	  Enables EHCI host driver in SPL.
+
  config SPL_USB_ETHER
  	bool "Support USB Ethernet drivers"
  	depends on SPL_NET
diff --git a/common/usb_hub.c b/common/usb_hub.c
index ba11a188ca..d572d7dd17 100644
--- a/common/usb_hub.c
+++ b/common/usb_hub.c
@@ -166,7 +166,9 @@ static void usb_hub_power_on(struct usb_hub_device 
*hub)
  	int i;
  	struct usb_device *dev;
  	unsigned pgood_delay = hub->desc.bPwrOn2PwrGood * 2;
+#ifndef CONFIG_SPL_BUILD
  	const char *env;
+#endif

  	dev = hub->pusb_dev;

@@ -185,6 +187,7 @@ static void usb_hub_power_on(struct usb_hub_device 
*hub)
  		return;
  #endif

+#ifndef CONFIG_SPL_BUILD
  	/*
  	 * Wait for power to become stable,
  	 * plus spec-defined max time for device to connect
@@ -196,6 +199,7 @@ static void usb_hub_power_on(struct usb_hub_device 
*hub)
  		pgood_delay = max(pgood_delay,
  			          (unsigned)simple_strtol(env, NULL, 0));
  	debug("pgood_delay=%dms\n", pgood_delay);
+#endif

  	/*
  	 * Do a minimum delay of the larger value of 100ms or pgood_delay
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index d5d891b205..df88ae2f30 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -21,16 +21,16 @@ obj-$(CONFIG_USB_GADGET_DWC2_OTG) += dwc2_udc_otg.o
  obj-$(CONFIG_USB_GADGET_DWC2_OTG_PHY) += dwc2_udc_otg_phy.o
  obj-$(CONFIG_USB_GADGET_FOTG210) += fotg210.o
  obj-$(CONFIG_USB_GADGET_MAX3420) += max3420_udc.o
-obj-$(CONFIG_CI_UDC)	+= ci_udc.o
+obj-$(CONFIG_$(SPL_)CI_UDC)	+= ci_udc.o
  ifndef CONFIG_SPL_BUILD
-obj-$(CONFIG_USB_GADGET_DOWNLOAD) += g_dnl.o
-obj-$(CONFIG_USB_FUNCTION_THOR) += f_thor.o
-obj-$(CONFIG_DFU_OVER_USB) += f_dfu.o
-obj-$(CONFIG_USB_FUNCTION_MASS_STORAGE) += f_mass_storage.o
-obj-$(CONFIG_USB_FUNCTION_FASTBOOT) += f_fastboot.o
-obj-$(CONFIG_USB_FUNCTION_SDP) += f_sdp.o
-obj-$(CONFIG_USB_FUNCTION_ROCKUSB) += f_rockusb.o
-obj-$(CONFIG_USB_FUNCTION_ACM)	+= f_acm.o
+obj-$(CONFIG_$(SPL_)USB_GADGET_DOWNLOAD) += g_dnl.o
+obj-$(CONFIG_$(SPL_)USB_FUNCTION_THOR) += f_thor.o
+obj-$(CONFIG_$(SPL_)DFU_OVER_USB) += f_dfu.o
+obj-$(CONFIG_$(SPL_)USB_FUNCTION_MASS_STORAGE) += f_mass_storage.o
+obj-$(CONFIG_$(SPL_)USB_FUNCTION_FASTBOOT) += f_fastboot.o
+obj-$(CONFIG_$(SPL_)USB_FUNCTION_SDP) += f_sdp.o
+obj-$(CONFIG_$(SPL_)USB_FUNCTION_ROCKUSB) += f_rockusb.o
+obj-$(CONFIG_$(SPL_)USB_FUNCTION_ACM)	+= f_acm.o
  endif
  endif
  ifdef CONFIG_USB_ETHER
diff --git a/drivers/usb/gadget/ci_udc.c b/drivers/usb/gadget/ci_udc.c
index 542684c1c3..2e274331fe 100644
--- a/drivers/usb/gadget/ci_udc.c
+++ b/drivers/usb/gadget/ci_udc.c
@@ -25,6 +25,7 @@
  #include <usb/ci_udc.h>
  #include "../host/ehci.h"
  #include "ci_udc.h"
+#include <dm.h>

  /*
   * Check if the system has too long cachelines. If the cachelines are
@@ -94,10 +95,42 @@ static struct usb_request *
  ci_ep_alloc_request(struct usb_ep *ep, unsigned int gfp_flags);
  static void ci_ep_free_request(struct usb_ep *ep, struct usb_request 
*_req);

+static int ci_gadget_start(struct usb_gadget *g, struct 
usb_gadget_driver *d);
+static int ci_gadget_stop(struct usb_gadget *g);
+
  static struct usb_gadget_ops ci_udc_ops = {
-	.pullup = ci_pullup,
+	.pullup    = ci_pullup,
+	.udc_start = ci_gadget_start,
+	.udc_stop  = ci_gadget_stop,
+};
+
+static struct ci_drv controller = {
+	.gadget	= {
+		.name	= "ci_udc",
+		.ops	= &ci_udc_ops,
+		.is_dualspeed = 1,
+		.is_otg = 0,
+		.is_a_peripheral = 0,
+		.b_hnp_enable = 0,
+		.a_hnp_support = 0,
+		.a_alt_hnp_support = 0,
+	},
  };

+static int ci_gadget_start(struct usb_gadget *g, struct 
usb_gadget_driver *d)
+{
+	controller.driver = d;
+	printf("Registered gadget driver %s\n", controller.gadget.name);
+	return 0;
+}
+
+static int ci_gadget_stop(struct usb_gadget *g)
+{
+	printf("Unregistered gadget driver %s\n", controller.gadget.name);
+	controller.driver = 0;
+	return 0;
+}
+
  static struct usb_ep_ops ci_ep_ops = {
  	.enable         = ci_ep_enable,
  	.disable        = ci_ep_disable,
@@ -107,10 +140,6 @@ static struct usb_ep_ops ci_ep_ops = {
  	.free_request   = ci_ep_free_request,
  };

-__weak void ci_init_after_reset(struct ehci_ctrl *ctrl)
-{
-}
-
  /* Init values for USB endpoints. */
  static const struct usb_ep ci_ep_init[5] = {
  	[0] = {	/* EP 0 */
@@ -140,15 +169,6 @@ static const struct usb_ep ci_ep_init[5] = {
  	},
  };

-static struct ci_drv controller = {
-	.gadget	= {
-		.name	= "ci_udc",
-		.ops	= &ci_udc_ops,
-		.is_dualspeed = 1,
-		.max_speed = USB_SPEED_HIGH,
-	},
-};
-
  /**
   * ci_get_qh() - return queue head for endpoint
   * @ep_num:	Endpoint number
@@ -310,7 +330,7 @@ static void ci_ep_free_request(struct usb_ep *ep, 
struct usb_request *req)

  static void ep_enable(int num, int in, int maxpacket)
  {
-	struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
+	struct ci_udc *udc = controller.udc;
  	unsigned n;

  	n = readl(&udc->epctrl[num]);
@@ -432,7 +452,7 @@ static void ci_debounce(struct ci_req *ci_req, int 
in)

  static void ci_ep_submit_next_request(struct ci_ep *ci_ep)
  {
-	struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
+	struct ci_udc *udc = controller.udc;
  	struct ept_queue_item *item;
  	struct ept_queue_head *head;
  	int bit, num, len, in;
@@ -673,7 +693,7 @@ static void handle_setup(void)
  	struct ci_ep *ci_ep = &controller.ep[0];
  	struct ci_req *ci_req;
  	struct usb_request *req;
-	struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
+	struct ci_udc *udc = controller.udc;
  	struct ept_queue_head *head;
  	struct usb_ctrlrequest r;
  	int status = 0;
@@ -776,7 +796,7 @@ static void stop_activity(void)
  {
  	int i, num, in;
  	struct ept_queue_head *head;
-	struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
+	struct ci_udc *udc = controller.udc;
  	writel(readl(&udc->epcomp), &udc->epcomp);
  #ifdef CONFIG_CI_UDC_HAS_HOSTPC
  	writel(readl(&udc->epsetupstat), &udc->epsetupstat);
@@ -800,16 +820,18 @@ static void stop_activity(void)
  	}
  }

-void udc_irq(void)
+static int udc_irq(void)
  {
-	struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
-	unsigned n = readl(&udc->usbsts);
-	writel(n, &udc->usbsts);
+	struct ci_udc *udc = controller.udc;
+	unsigned n;
  	int bit, i, num, in;

+	n = readl(&udc->usbsts);
+	writel(n, &udc->usbsts);
+
  	n &= (STS_SLI | STS_URI | STS_PCI | STS_UI | STS_UEI);
  	if (n == 0)
-		return;
+		return IRQ_NONE;

  	if (n & STS_URI) {
  		DBG("-- reset --\n");
@@ -867,23 +889,17 @@ void udc_irq(void)
  			}
  		}
  	}
+	return IRQ_HANDLED;
  }

-int usb_gadget_handle_interrupts(int index)
+int dm_usb_gadget_handle_interrupts(struct udevice *dev)
  {
-	u32 value;
-	struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
-
-	value = readl(&udc->usbsts);
-	if (value)
-		udc_irq();
-
-	return value;
+	return udc_irq();
  }

  void udc_disconnect(void)
  {
-	struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
+	struct ci_udc *udc = controller.udc;
  	/* disable pullup */
  	stop_activity();
  	writel(USBCMD_FS2, &udc->usbcmd);
@@ -894,14 +910,12 @@ void udc_disconnect(void)

  static int ci_pullup(struct usb_gadget *gadget, int is_on)
  {
-	struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
+	struct ci_udc *udc = controller.udc;
  	if (is_on) {
  		/* RESET */
  		writel(USBCMD_ITC(MICRO_8FRAME) | USBCMD_RST, &udc->usbcmd);
  		udelay(200);

-		ci_init_after_reset(controller.ctrl);
-
  		writel((unsigned long)controller.epts, &udc->epinitaddr);

  		/* select DEVICE mode */
@@ -924,7 +938,7 @@ static int ci_pullup(struct usb_gadget *gadget, int 
is_on)
  	return 0;
  }

-static int ci_udc_probe(void)
+static int ci_udc_probe(struct udevice *dev)
  {
  	struct ept_queue_head *head;
  	int i;
@@ -936,6 +950,9 @@ static int ci_udc_probe(void)
  	const int eplist_raw_sz = num * sizeof(struct ept_queue_head);
  	const int eplist_sz = roundup(eplist_raw_sz, ARCH_DMA_MINALIGN);

+	controller.driver = 0;
+	controller.udc = (struct ci_udc *) 0x32e40140; // TODO read from DTB
+
  	/* The QH list must be aligned to 4096 bytes. */
  	controller.epts = memalign(eplist_align, eplist_sz);
  	if (!controller.epts)
@@ -1010,66 +1027,36 @@ static int ci_udc_probe(void)
  		return -ENOMEM;
  	}

-	return 0;
+	return usb_add_gadget_udc((struct device *)dev, &controller.gadget);
  }

-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+static int ci_udc_remove(struct udevice *dev)
  {
-	int ret;
-
-	if (!driver)
-		return -EINVAL;
-	if (!driver->bind || !driver->setup || !driver->disconnect)
-		return -EINVAL;
-
-#if CONFIG_IS_ENABLED(DM_USB)
-	ret = usb_setup_ehci_gadget(&controller.ctrl);
-#else
-	ret = usb_lowlevel_init(0, USB_INIT_DEVICE, (void 
**)&controller.ctrl);
-#endif
-	if (ret)
-		return ret;
-
-	ret = ci_udc_probe();
-	if (ret) {
-		DBG("udc probe failed, returned %d\n", ret);
-		return ret;
-	}
-
-	ret = driver->bind(&controller.gadget);
-	if (ret) {
-		DBG("driver->bind() returned %d\n", ret);
-		return ret;
-	}
-	controller.driver = driver;
-
-	return 0;
-}
-
-int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
-{
-	udc_disconnect();
-
-	driver->unbind(&controller.gadget);
-	controller.driver = NULL;
-
+	usb_del_gadget_udc(&controller.gadget);
  	ci_ep_free_request(&controller.ep[0].ep, &controller.ep0_req->req);
  	free(controller.items_mem);
  	free(controller.epts);

-#if CONFIG_IS_ENABLED(DM_USB)
-	usb_remove_ehci_gadget(&controller.ctrl);
-#else
-	usb_lowlevel_stop(0);
-	controller.ctrl = NULL;
-#endif
-
-	return 0;
+	return dm_scan_fdt_dev(dev);
  }

+static const struct udevice_id ci_udc_ids[] = {
+	{ .compatible = "fsl,imx27-usb-gadget" },
+	{},
+};
+
+U_BOOT_DRIVER(ci_udc_usb) = {
+	.name       = "ci-udc",
+	.id         = UCLASS_USB_GADGET_GENERIC,
+	.of_match   = ci_udc_ids,
+	.probe      = ci_udc_probe,
+	.remove     = ci_udc_remove,
+	.priv_auto  = sizeof(struct ci_udc),
+};
+
  bool dfu_usb_get_reset(void)
  {
-	struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
+	struct ci_udc *udc = controller.udc;

  	return !!(readl(&udc->usbsts) & STS_URI);
  }
diff --git a/drivers/usb/gadget/ci_udc.h b/drivers/usb/gadget/ci_udc.h
index 95cc07992b..c087ac533d 100644
--- a/drivers/usb/gadget/ci_udc.h
+++ b/drivers/usb/gadget/ci_udc.h
@@ -101,7 +101,7 @@ struct ci_drv {
  	struct ci_req			*ep0_req;
  	bool				ep0_data_phase;
  	struct usb_gadget_driver	*driver;
-	struct ehci_ctrl		*ctrl;
+	struct ci_udc		*udc;
  	struct ept_queue_head		*epts;
  	uint8_t				*items_mem;
  	struct ci_ep			ep[NUM_ENDPOINTS];
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index eb6fe9f6b3..08474daaf2 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -20,7 +20,7 @@ obj-$(CONFIG_USB_OHCI_PCI) += ohci-pci.o
  obj-$(CONFIG_USB_OHCI_GENERIC) += ohci-generic.o

  # echi
-obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o
+obj-$(CONFIG_$(SPL_)USB_EHCI_HCD) += ehci-hcd.o
  obj-$(CONFIG_USB_EHCI_ARMADA100) += ehci-armada100.o utmi-armada100.o
  obj-$(CONFIG_USB_EHCI_ATMEL) += ehci-atmel.o
  obj-$(CONFIG_USB_EHCI_FSL) += ehci-fsl.o
-- 
2.30.2



More information about the U-Boot mailing list