[PATCH] Make ci_udc available in SPL

This is needed for SDP downloads of eg. fitimages in SPL stage.
Signed-off-by: Manuel Traut manut@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
participants (1)
-
Manuel Traut