[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