* [PATCH 0/3] Support MSM8916 USB PHY + UDC in qcom_defconfig
@ 2025-04-12 19:39 Sam Day
2025-04-12 19:39 ` [PATCH 1/3] usb: udc: ci: support USB gadget driver model Sam Day
` (2 more replies)
0 siblings, 3 replies; 9+ messages in thread
From: Sam Day @ 2025-04-12 19:39 UTC (permalink / raw)
To: Lukasz Majewski, Mattijs Korpershoek, Marek Vasut, Tom Rini,
Caleb Connolly, Neil Armstrong, Sumit Garg, Stephan Gerhold
Cc: u-boot, u-boot-qcom, Sam Day
The MSM8916 SoC includes a ChipIdea UDC. The U-Boot driver for this UDC
is quite old, and did not support USB gadget driver model. As a result,
it could not be built alongside the DWC3 driver. This meant that
qcom_defconfig could not include support for USB on MSM8916.
This series adds support to build ChipIdea UDC with DM_USB_GADGET and
ensures that the newly introduced driver is registered from the MSM EHCI
glue driver.
The ChipIdea UDC driver continues to work without DM_USB_GADGET. I
tested these changes by building dragonboard410c_defconfig (which does
not enable DM_USB_GADGET), booting it, and then chain-booting (via
fastboot) another u-boot build built with qcom_defconfig. USB gadget
mode worked in both builds.
Signed-off-by: Sam Day <me@samcday.com>
---
Sam Day (3):
usb: udc: ci: support USB gadget driver model
usb: host: ehci-msm: Register ChipIdea UDC from glue wrapper
qcom_defconfig: Enable MSM8916 USB PHY + ChipIdea UDC
configs/qcom_defconfig | 6 ++++
drivers/usb/gadget/ci_udc.c | 84 ++++++++++++++++++++++++++++++++++++++++++++-
drivers/usb/host/ehci-msm.c | 7 ++++
3 files changed, 96 insertions(+), 1 deletion(-)
---
base-commit: a40fc5afaec079ee4e621965fed18dcc94240d8c
change-id: 20250412-msm8916-usb-a1dc93c01bd5
prerequisite-message-id: <20250407-ehci-msm-fixes-v1-0-f8b30eb05d07@linaro.org>
prerequisite-patch-id: 006e55423a2d28cc23ff11035da672b418ebec51
prerequisite-patch-id: 8c51357ca78f0465407e0a74fda666a3e540f6d8
prerequisite-patch-id: 68d707d65315e9ea7c61ba97c58257ea9a3e3152
prerequisite-patch-id: 514522633917dd1efd2380a53949c5e7ff5ff0dd
prerequisite-patch-id: 9ee7e8f41aa3070f802d087bd763ab384e681adb
prerequisite-patch-id: fbfd19c0f729fe157c31bc40d48d19d0083d23a4
Best regards,
--
Sam Day <me@samcday.com>
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH 1/3] usb: udc: ci: support USB gadget driver model 2025-04-12 19:39 [PATCH 0/3] Support MSM8916 USB PHY + UDC in qcom_defconfig Sam Day @ 2025-04-12 19:39 ` Sam Day 2025-04-16 18:51 ` Stephan Gerhold 2025-04-12 19:40 ` [PATCH 2/3] usb: host: ehci-msm: Register ChipIdea UDC from glue wrapper Sam Day 2025-04-12 19:40 ` [PATCH 3/3] qcom_defconfig: Enable MSM8916 USB PHY + ChipIdea UDC Sam Day 2 siblings, 1 reply; 9+ messages in thread From: Sam Day @ 2025-04-12 19:39 UTC (permalink / raw) To: Lukasz Majewski, Mattijs Korpershoek, Marek Vasut, Tom Rini, Caleb Connolly, Neil Armstrong, Sumit Garg, Stephan Gerhold Cc: u-boot, u-boot-qcom, Sam Day When CONFIG_DM_USB_GADGET is enabled, a UCLASS_USB_GADGET_GENERIC driver will be defined that wraps the ChipIdea UDC operations. The (dm_)?usb_gadget_.* symbols will no longer be defined (as these are now handled by the UDC uclass). If CONFIG_DM_USB_GADGET is not enabled, this driver behaves as it previously did. This new driver does not declare any compatibles of its own. It requires a glue driver to bind it. The ehci_msm driver will be updated in the following commit to do exactly that. Signed-off-by: Sam Day <me@samcday.com> --- drivers/usb/gadget/ci_udc.c | 84 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/ci_udc.c b/drivers/usb/gadget/ci_udc.c index 4bff75da759ded6716641713fbe47f6ba79386dc..179f8540da30c693d11d772aacc00cc37f7669c5 100644 --- a/drivers/usb/gadget/ci_udc.c +++ b/drivers/usb/gadget/ci_udc.c @@ -10,6 +10,7 @@ #include <command.h> #include <config.h> #include <cpu_func.h> +#include <dm.h> #include <net.h> #include <malloc.h> #include <wait_bit.h> @@ -94,8 +95,18 @@ 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); +#if CONFIG_IS_ENABLED(DM_USB_GADGET) +static int ci_udc_gadget_start(struct usb_gadget *g, + struct usb_gadget_driver *driver); +static int ci_udc_gadget_stop(struct usb_gadget *g); +#endif + static const struct usb_gadget_ops ci_udc_ops = { .pullup = ci_pullup, +#if CONFIG_IS_ENABLED(DM_USB_GADGET) + .udc_start = ci_udc_gadget_start, + .udc_stop = ci_udc_gadget_stop, +#endif }; static const struct usb_ep_ops ci_ep_ops = { @@ -927,7 +938,7 @@ void udc_irq(void) } } -int dm_usb_gadget_handle_interrupts(struct udevice *dev) +static int ci_udc_handle_interrupts(struct udevice *dev) { struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; u32 value; @@ -1072,6 +1083,71 @@ static int ci_udc_probe(void) return 0; } +#if CONFIG_IS_ENABLED(DM_USB_GADGET) +static int ci_udc_generic_probe(struct udevice *dev) +{ + int ret; +#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) + return ret; + + return usb_add_gadget_udc((struct device *)dev, &controller.gadget); +} + +static int ci_udc_generic_remove(struct udevice *dev) +{ + usb_del_gadget_udc(&controller.gadget); + + if (IS_ENABLED(CONFIG_DM_USB)) { + usb_remove_ehci_gadget(&controller.ctrl); + } else { + usb_lowlevel_stop(0); + controller.ctrl = NULL; + } + + return 0; +} + +static const struct usb_gadget_generic_ops ci_udc_generic_ops = { + .handle_interrupts = ci_udc_handle_interrupts, +}; + +U_BOOT_DRIVER(ci_udc_generic) = { + .name = "ci-udc", + .id = UCLASS_USB_GADGET_GENERIC, + .ops = &ci_udc_generic_ops, + .probe = ci_udc_generic_probe, + .remove = ci_udc_generic_remove, +}; + +static int ci_udc_gadget_start(struct usb_gadget *g, + struct usb_gadget_driver *driver) +{ + controller.driver = driver; + return 0; +} + +static int ci_udc_gadget_stop(struct usb_gadget *g) +{ + controller.driver = NULL; + udc_disconnect(); + + ci_ep_free_request(&controller.ep[0].ep, &controller.ep0_req->req); + free(controller.items_mem); + free(controller.epts); + + return 0; +} + +#else int usb_gadget_register_driver(struct usb_gadget_driver *driver) { int ret; @@ -1126,6 +1202,12 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) return 0; } +int dm_usb_gadget_handle_interrupts(struct udevice *dev) +{ + return ci_udc_handle_interrupts(dev); +} +#endif + bool dfu_usb_get_reset(void) { struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; -- 2.49.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 1/3] usb: udc: ci: support USB gadget driver model 2025-04-12 19:39 ` [PATCH 1/3] usb: udc: ci: support USB gadget driver model Sam Day @ 2025-04-16 18:51 ` Stephan Gerhold 2025-04-19 9:32 ` Sam Day 0 siblings, 1 reply; 9+ messages in thread From: Stephan Gerhold @ 2025-04-16 18:51 UTC (permalink / raw) To: Sam Day Cc: Lukasz Majewski, Mattijs Korpershoek, Marek Vasut, Tom Rini, Caleb Connolly, Neil Armstrong, Sumit Garg, u-boot, u-boot-qcom On Sat, Apr 12, 2025 at 07:39:57PM +0000, Sam Day wrote: > When CONFIG_DM_USB_GADGET is enabled, a UCLASS_USB_GADGET_GENERIC driver > will be defined that wraps the ChipIdea UDC operations. The > (dm_)?usb_gadget_.* symbols will no longer be defined (as these are now > handled by the UDC uclass). > > If CONFIG_DM_USB_GADGET is not enabled, this driver behaves as it > previously did. > > This new driver does not declare any compatibles of its own. It requires > a glue driver to bind it. The ehci_msm driver will be updated in the > following commit to do exactly that. > > Signed-off-by: Sam Day <me@samcday.com> Thanks a lot for working on this. Seems to work without problems on my dragonboard410c. Just some minor nits below to reduce code duplication. > --- > drivers/usb/gadget/ci_udc.c | 84 ++++++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 83 insertions(+), 1 deletion(-) > > diff --git a/drivers/usb/gadget/ci_udc.c b/drivers/usb/gadget/ci_udc.c > index 4bff75da759ded6716641713fbe47f6ba79386dc..179f8540da30c693d11d772aacc00cc37f7669c5 100644 > --- a/drivers/usb/gadget/ci_udc.c > +++ b/drivers/usb/gadget/ci_udc.c > @@ -10,6 +10,7 @@ > #include <command.h> > #include <config.h> > #include <cpu_func.h> > +#include <dm.h> > #include <net.h> > #include <malloc.h> > #include <wait_bit.h> > @@ -94,8 +95,18 @@ 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); > > +#if CONFIG_IS_ENABLED(DM_USB_GADGET) > +static int ci_udc_gadget_start(struct usb_gadget *g, > + struct usb_gadget_driver *driver); > +static int ci_udc_gadget_stop(struct usb_gadget *g); > +#endif > + > static const struct usb_gadget_ops ci_udc_ops = { > .pullup = ci_pullup, > +#if CONFIG_IS_ENABLED(DM_USB_GADGET) > + .udc_start = ci_udc_gadget_start, > + .udc_stop = ci_udc_gadget_stop, > +#endif > }; > > static const struct usb_ep_ops ci_ep_ops = { > @@ -927,7 +938,7 @@ void udc_irq(void) > } > } > > -int dm_usb_gadget_handle_interrupts(struct udevice *dev) > +static int ci_udc_handle_interrupts(struct udevice *dev) > { > struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; > u32 value; > @@ -1072,6 +1083,71 @@ static int ci_udc_probe(void) > return 0; > } > > +#if CONFIG_IS_ENABLED(DM_USB_GADGET) > +static int ci_udc_generic_probe(struct udevice *dev) > +{ > + int ret; > +#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 ... > [...] > +static int ci_udc_generic_remove(struct udevice *dev) > +{ > + usb_del_gadget_udc(&controller.gadget); > + > + if (IS_ENABLED(CONFIG_DM_USB)) { > + usb_remove_ehci_gadget(&controller.ctrl); > + } else { > + usb_lowlevel_stop(0); > + controller.ctrl = NULL; > + } This style is nice for compile testing. But in the probe() function above you're still using the #if/#else pre-processor style. Can it use if (IS_ENABLED(...)) too? if (IS_ENABLED(CONFIG_DM_USB)) ret = usb_setup_ehci_gadget(&controller.ctrl); else ret = usb_lowlevel_init(0, USB_INIT_DEVICE, (void **)&controller.ctrl); if (ret) return ret; This seems to compile at least. If yes, can you make the same cleanup for the old !DM_USB_GADGET case, so the two code paths are consistent? > + > + return 0; > +} > + > +static const struct usb_gadget_generic_ops ci_udc_generic_ops = { > + .handle_interrupts = ci_udc_handle_interrupts, > +}; > + > +U_BOOT_DRIVER(ci_udc_generic) = { > + .name = "ci-udc", > + .id = UCLASS_USB_GADGET_GENERIC, > + .ops = &ci_udc_generic_ops, > + .probe = ci_udc_generic_probe, > + .remove = ci_udc_generic_remove, > +}; > + > +static int ci_udc_gadget_start(struct usb_gadget *g, > + struct usb_gadget_driver *driver) > +{ > + controller.driver = driver; > + return 0; > +} > + > +static int ci_udc_gadget_stop(struct usb_gadget *g) > +{ > + controller.driver = NULL; > + udc_disconnect(); > + > + ci_ep_free_request(&controller.ep[0].ep, &controller.ep0_req->req); > + free(controller.items_mem); > + free(controller.epts); > + > + return 0; > +} I wonder if you could just define the start and stop function outside the #if blocks and call them from usb_gadget_unregister_driver() and usb_gadget_register_driver(). This would avoid duplicating the code, reducing the risk that someone forgets to update one of those when making changes. The same could be also said for probe()/remove(), i.e. moving the if (IS_ENABLED(CONFIG_DM_USB)) { usb_remove_ehci_gadget(&controller.ctrl); } else { usb_lowlevel_stop(0); controller.ctrl = NULL; } block to a separate function and calling that from both variants. Not sure if that would also be worth it? Thanks, Stephan ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/3] usb: udc: ci: support USB gadget driver model 2025-04-16 18:51 ` Stephan Gerhold @ 2025-04-19 9:32 ` Sam Day 2025-06-04 7:07 ` Wojciech Dubowik 0 siblings, 1 reply; 9+ messages in thread From: Sam Day @ 2025-04-19 9:32 UTC (permalink / raw) To: Stephan Gerhold Cc: Lukasz Majewski, Mattijs Korpershoek, Marek Vasut, Tom Rini, Caleb Connolly, Neil Armstrong, Sumit Garg, u-boot, u-boot-qcom Heya Stephan, On Wed Apr 16, 2025 at 8:51 PM CEST, Stephan Gerhold wrote: > On Sat, Apr 12, 2025 at 07:39:57PM +0000, Sam Day wrote: >> When CONFIG_DM_USB_GADGET is enabled, a UCLASS_USB_GADGET_GENERIC driver >> will be defined that wraps the ChipIdea UDC operations. The >> (dm_)?usb_gadget_.* symbols will no longer be defined (as these are now >> handled by the UDC uclass). >> >> If CONFIG_DM_USB_GADGET is not enabled, this driver behaves as it >> previously did. >> >> This new driver does not declare any compatibles of its own. It requires >> a glue driver to bind it. The ehci_msm driver will be updated in the >> following commit to do exactly that. >> >> Signed-off-by: Sam Day <me@samcday.com> > > Thanks a lot for working on this. Seems to work without problems on my > dragonboard410c. Just some minor nits below to reduce code duplication. \0/ Thanks for the review and testing! > >> --- >> drivers/usb/gadget/ci_udc.c | 84 ++++++++++++++++++++++++++++++++++++++++++++- >> 1 file changed, 83 insertions(+), 1 deletion(-) >> >> diff --git a/drivers/usb/gadget/ci_udc.c b/drivers/usb/gadget/ci_udc.c >> index 4bff75da759ded6716641713fbe47f6ba79386dc..179f8540da30c693d11d772aacc00cc37f7669c5 100644 >> --- a/drivers/usb/gadget/ci_udc.c >> +++ b/drivers/usb/gadget/ci_udc.c >> @@ -10,6 +10,7 @@ >> #include <command.h> >> #include <config.h> >> #include <cpu_func.h> >> +#include <dm.h> >> #include <net.h> >> #include <malloc.h> >> #include <wait_bit.h> >> @@ -94,8 +95,18 @@ 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); >> >> +#if CONFIG_IS_ENABLED(DM_USB_GADGET) >> +static int ci_udc_gadget_start(struct usb_gadget *g, >> + struct usb_gadget_driver *driver); >> +static int ci_udc_gadget_stop(struct usb_gadget *g); >> +#endif >> + >> static const struct usb_gadget_ops ci_udc_ops = { >> .pullup = ci_pullup, >> +#if CONFIG_IS_ENABLED(DM_USB_GADGET) >> + .udc_start = ci_udc_gadget_start, >> + .udc_stop = ci_udc_gadget_stop, >> +#endif >> }; >> >> static const struct usb_ep_ops ci_ep_ops = { >> @@ -927,7 +938,7 @@ void udc_irq(void) >> } >> } >> >> -int dm_usb_gadget_handle_interrupts(struct udevice *dev) >> +static int ci_udc_handle_interrupts(struct udevice *dev) >> { >> struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; >> u32 value; >> @@ -1072,6 +1083,71 @@ static int ci_udc_probe(void) >> return 0; >> } >> >> +#if CONFIG_IS_ENABLED(DM_USB_GADGET) >> +static int ci_udc_generic_probe(struct udevice *dev) >> +{ >> + int ret; >> +#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 > > ... > >> [...] >> +static int ci_udc_generic_remove(struct udevice *dev) >> +{ >> + usb_del_gadget_udc(&controller.gadget); >> + >> + if (IS_ENABLED(CONFIG_DM_USB)) { >> + usb_remove_ehci_gadget(&controller.ctrl); >> + } else { >> + usb_lowlevel_stop(0); >> + controller.ctrl = NULL; >> + } > > This style is nice for compile testing. But in the probe() function > above you're still using the #if/#else pre-processor style. Can it use > if (IS_ENABLED(...)) too? Ah, I had converted a few of these when checkpatch reprimanded me. Guess I missed this one - oops! > > if (IS_ENABLED(CONFIG_DM_USB)) > ret = usb_setup_ehci_gadget(&controller.ctrl); > else > ret = usb_lowlevel_init(0, USB_INIT_DEVICE, (void **)&controller.ctrl); > if (ret) > return ret; > > This seems to compile at least. > > If yes, can you make the same cleanup for the old !DM_USB_GADGET case, > so the two code paths are consistent? Thanks, I've done this in v2. > >> + >> + return 0; >> +} >> + >> +static const struct usb_gadget_generic_ops ci_udc_generic_ops = { >> + .handle_interrupts = ci_udc_handle_interrupts, >> +}; >> + >> +U_BOOT_DRIVER(ci_udc_generic) = { >> + .name = "ci-udc", >> + .id = UCLASS_USB_GADGET_GENERIC, >> + .ops = &ci_udc_generic_ops, >> + .probe = ci_udc_generic_probe, >> + .remove = ci_udc_generic_remove, >> +}; >> + >> +static int ci_udc_gadget_start(struct usb_gadget *g, >> + struct usb_gadget_driver *driver) >> +{ >> + controller.driver = driver; >> + return 0; >> +} >> + >> +static int ci_udc_gadget_stop(struct usb_gadget *g) >> +{ >> + controller.driver = NULL; >> + udc_disconnect(); >> + >> + ci_ep_free_request(&controller.ep[0].ep, &controller.ep0_req->req); >> + free(controller.items_mem); >> + free(controller.epts); >> + >> + return 0; >> +} > > I wonder if you could just define the start and stop function outside > the #if blocks and call them from usb_gadget_unregister_driver() > and usb_gadget_register_driver(). This would avoid duplicating the code, > reducing the risk that someone forgets to update one of those when > making changes. So, not quite unfortunately. In the case of ci_udc_gadget_stop(), the controller.driver = NULL happening before calling into udc_disconnect() is important: the generic UDC uclass code has already called driver->disconnect() and calling it again is a Very Bad Thing to do. So we can't just delegate usb_gadget_unregister_driver to ci_udc_gadget_stop outright. In v2 I've tried to unify the codepaths as much as possible though, both to avoid duplication and the risks of future patches making incomplete changes. > > The same could be also said for probe()/remove(), i.e. moving the > > if (IS_ENABLED(CONFIG_DM_USB)) { > usb_remove_ehci_gadget(&controller.ctrl); > } else { > usb_lowlevel_stop(0); > controller.ctrl = NULL; > } > > block to a separate function and calling that from both variants. Not > sure if that would also be worth it? Good call, these ones are less problematic, and I've done that in v2. Rock on \m/, -Sam > > Thanks, > Stephan ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/3] usb: udc: ci: support USB gadget driver model 2025-04-19 9:32 ` Sam Day @ 2025-06-04 7:07 ` Wojciech Dubowik 0 siblings, 0 replies; 9+ messages in thread From: Wojciech Dubowik @ 2025-06-04 7:07 UTC (permalink / raw) To: Sam Day; +Cc: u-boot On Sat, Apr 19, 2025 at 09:32:04AM +0000, Sam Day wrote: > Heya Stephan, > > On Wed Apr 16, 2025 at 8:51 PM CEST, Stephan Gerhold wrote: > > On Sat, Apr 12, 2025 at 07:39:57PM +0000, Sam Day wrote: > >> When CONFIG_DM_USB_GADGET is enabled, a UCLASS_USB_GADGET_GENERIC driver > >> will be defined that wraps the ChipIdea UDC operations. The > >> (dm_)?usb_gadget_.* symbols will no longer be defined (as these are now > >> handled by the UDC uclass). > >> > >> If CONFIG_DM_USB_GADGET is not enabled, this driver behaves as it > >> previously did. > >> > >> This new driver does not declare any compatibles of its own. It requires > >> a glue driver to bind it. The ehci_msm driver will be updated in the > >> following commit to do exactly that. > >> > >> Signed-off-by: Sam Day <me at samcday.com> > > > > Thanks a lot for working on this. Seems to work without problems on my > > dragonboard410c. Just some minor nits below to reduce code duplication. > > \0/ Thanks for the review and testing! > > > > >> --- > >> drivers/usb/gadget/ci_udc.c | 84 ++++++++++++++++++++++++++++++++++++++++++++- > >> 1 file changed, 83 insertions(+), 1 deletion(-) > >> > >> diff --git a/drivers/usb/gadget/ci_udc.c b/drivers/usb/gadget/ci_udc.c > >> index 4bff75da759ded6716641713fbe47f6ba79386dc..179f8540da30c693d11d772aacc00cc37f7669c5 100644 > >> --- a/drivers/usb/gadget/ci_udc.c > >> +++ b/drivers/usb/gadget/ci_udc.c > >> @@ -10,6 +10,7 @@ > >> #include <command.h> > >> #include <config.h> > >> #include <cpu_func.h> > >> +#include <dm.h> > >> #include <net.h> > >> #include <malloc.h> > >> #include <wait_bit.h> > >> @@ -94,8 +95,18 @@ 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); > >> > >> +#if CONFIG_IS_ENABLED(DM_USB_GADGET) > >> +static int ci_udc_gadget_start(struct usb_gadget *g, > >> + struct usb_gadget_driver *driver); > >> +static int ci_udc_gadget_stop(struct usb_gadget *g); > >> +#endif > >> + > >> static const struct usb_gadget_ops ci_udc_ops = { > >> .pullup = ci_pullup, > >> +#if CONFIG_IS_ENABLED(DM_USB_GADGET) > >> + .udc_start = ci_udc_gadget_start, > >> + .udc_stop = ci_udc_gadget_stop, > >> +#endif > >> }; > >> > >> static const struct usb_ep_ops ci_ep_ops = { > >> @@ -927,7 +938,7 @@ void udc_irq(void) > >> } > >> } > >> > >> -int dm_usb_gadget_handle_interrupts(struct udevice *dev) > >> +static int ci_udc_handle_interrupts(struct udevice *dev) > >> { > >> struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; > >> u32 value; > >> @@ -1072,6 +1083,71 @@ static int ci_udc_probe(void) > >> return 0; > >> } > >> > >> +#if CONFIG_IS_ENABLED(DM_USB_GADGET) > >> +static int ci_udc_generic_probe(struct udevice *dev) > >> +{ > >> + int ret; > >> +#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 > > > > ... > > > >> [...] > >> +static int ci_udc_generic_remove(struct udevice *dev) > >> +{ > >> + usb_del_gadget_udc(&controller.gadget); > >> + > >> + if (IS_ENABLED(CONFIG_DM_USB)) { > >> + usb_remove_ehci_gadget(&controller.ctrl); > >> + } else { > >> + usb_lowlevel_stop(0); > >> + controller.ctrl = NULL; > >> + } > > > > This style is nice for compile testing. But in the probe() function > > above you're still using the #if/#else pre-processor style. Can it use > > if (IS_ENABLED(...)) too? > > Ah, I had converted a few of these when checkpatch reprimanded me. Guess > I missed this one - oops! > > > > > if (IS_ENABLED(CONFIG_DM_USB)) > > ret = usb_setup_ehci_gadget(&controller.ctrl); > > else > > ret = usb_lowlevel_init(0, USB_INIT_DEVICE, (void **)&controller.ctrl); > > if (ret) > > return ret; > > > > This seems to compile at least. > > > > If yes, can you make the same cleanup for the old !DM_USB_GADGET case, > > so the two code paths are consistent? > > Thanks, I've done this in v2. > > > > >> + > >> + return 0; > >> +} > >> + > >> +static const struct usb_gadget_generic_ops ci_udc_generic_ops = { > >> + .handle_interrupts = ci_udc_handle_interrupts, > >> +}; > >> + > >> +U_BOOT_DRIVER(ci_udc_generic) = { > >> + .name = "ci-udc", > >> + .id = UCLASS_USB_GADGET_GENERIC, > >> + .ops = &ci_udc_generic_ops, > >> + .probe = ci_udc_generic_probe, > >> + .remove = ci_udc_generic_remove, > >> +}; > >> + > >> +static int ci_udc_gadget_start(struct usb_gadget *g, > >> + struct usb_gadget_driver *driver) > >> +{ > >> + controller.driver = driver; > >> + return 0; > >> +} > >> + > >> +static int ci_udc_gadget_stop(struct usb_gadget *g) > >> +{ > >> + controller.driver = NULL; > >> + udc_disconnect(); > >> + > >> + ci_ep_free_request(&controller.ep[0].ep, &controller.ep0_req->req); > >> + free(controller.items_mem); > >> + free(controller.epts); > >> + > >> + return 0; > >> +} > > > > I wonder if you could just define the start and stop function outside > > the #if blocks and call them from usb_gadget_unregister_driver() > > and usb_gadget_register_driver(). This would avoid duplicating the code, > > reducing the risk that someone forgets to update one of those when > > making changes. > > So, not quite unfortunately. In the case of ci_udc_gadget_stop(), the > controller.driver = NULL happening before calling into udc_disconnect() > is important: the generic UDC uclass code has already called > driver->disconnect() and calling it again is a Very Bad Thing to do. So > we can't just delegate usb_gadget_unregister_driver to > ci_udc_gadget_stop outright. > > In v2 I've tried to unify the codepaths as much as possible though, > both to avoid duplication and the risks of future patches making > incomplete changes. > > > > > The same could be also said for probe()/remove(), i.e. moving the > > > > if (IS_ENABLED(CONFIG_DM_USB)) { > > usb_remove_ehci_gadget(&controller.ctrl); > > } else { > > usb_lowlevel_stop(0); > > controller.ctrl = NULL; > > } > > > > block to a separate function and calling that from both variants. Not > > sure if that would also be worth it? > > Good call, these ones are less problematic, and I've done that in v2. Hello Sam, Are you going to send v2 soon? I am just asking as I had something similar in the pipeline. Regrads, Wojtek > > Rock on \m/, > -Sam > > > > > Thanks, > > Stephan > > ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 2/3] usb: host: ehci-msm: Register ChipIdea UDC from glue wrapper 2025-04-12 19:39 [PATCH 0/3] Support MSM8916 USB PHY + UDC in qcom_defconfig Sam Day 2025-04-12 19:39 ` [PATCH 1/3] usb: udc: ci: support USB gadget driver model Sam Day @ 2025-04-12 19:40 ` Sam Day 2025-04-16 18:57 ` Stephan Gerhold 2025-04-12 19:40 ` [PATCH 3/3] qcom_defconfig: Enable MSM8916 USB PHY + ChipIdea UDC Sam Day 2 siblings, 1 reply; 9+ messages in thread From: Sam Day @ 2025-04-12 19:40 UTC (permalink / raw) To: Lukasz Majewski, Mattijs Korpershoek, Marek Vasut, Tom Rini, Caleb Connolly, Neil Armstrong, Sumit Garg, Stephan Gerhold Cc: u-boot, u-boot-qcom, Sam Day When CONFIG_DM_USB_GADGET is enabled, the CI UDC driver needs to be explicitly bound. So we do this from the newly introduced glue driver. Signed-off-by: Sam Day <me@samcday.com> --- drivers/usb/host/ehci-msm.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c index 8aeb6a915563453ad2a02721d4828fd1b300a4e4..ae40e96e6349b1a352608e6350ce950a3cff95af 100644 --- a/drivers/usb/host/ehci-msm.c +++ b/drivers/usb/host/ehci-msm.c @@ -161,6 +161,13 @@ static int qcom_ci_hdrc_bind(struct udevice *dev) if (ret) return ret; + if (IS_ENABLED(CONFIG_DM_USB_GADGET) && IS_ENABLED(CONFIG_CI_UDC)) { + ret = device_bind_driver_to_node(dev, "ci-udc", "ci-udc", + dev_ofnode(dev), NULL); + if (ret) + return ret; + } + if (!ofnode_valid(ulpi_node)) return 0; -- 2.49.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 2/3] usb: host: ehci-msm: Register ChipIdea UDC from glue wrapper 2025-04-12 19:40 ` [PATCH 2/3] usb: host: ehci-msm: Register ChipIdea UDC from glue wrapper Sam Day @ 2025-04-16 18:57 ` Stephan Gerhold 0 siblings, 0 replies; 9+ messages in thread From: Stephan Gerhold @ 2025-04-16 18:57 UTC (permalink / raw) To: Sam Day Cc: Lukasz Majewski, Mattijs Korpershoek, Marek Vasut, Tom Rini, Caleb Connolly, Neil Armstrong, Sumit Garg, u-boot, u-boot-qcom On Sat, Apr 12, 2025 at 07:40:03PM +0000, Sam Day wrote: > When CONFIG_DM_USB_GADGET is enabled, the CI UDC driver needs to be > explicitly bound. So we do this from the newly introduced glue driver. > > Signed-off-by: Sam Day <me@samcday.com> > --- > drivers/usb/host/ehci-msm.c | 7 +++++++ > 1 file changed, 7 insertions(+) > > diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c > index 8aeb6a915563453ad2a02721d4828fd1b300a4e4..ae40e96e6349b1a352608e6350ce950a3cff95af 100644 > --- a/drivers/usb/host/ehci-msm.c > +++ b/drivers/usb/host/ehci-msm.c > @@ -161,6 +161,13 @@ static int qcom_ci_hdrc_bind(struct udevice *dev) > if (ret) > return ret; > > + if (IS_ENABLED(CONFIG_DM_USB_GADGET) && IS_ENABLED(CONFIG_CI_UDC)) { > + ret = device_bind_driver_to_node(dev, "ci-udc", "ci-udc", > + dev_ofnode(dev), NULL); Nitpick: Indentation looks off here (we usually align with the open parenthesis ( Thanks, Stephan ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 3/3] qcom_defconfig: Enable MSM8916 USB PHY + ChipIdea UDC 2025-04-12 19:39 [PATCH 0/3] Support MSM8916 USB PHY + UDC in qcom_defconfig Sam Day 2025-04-12 19:39 ` [PATCH 1/3] usb: udc: ci: support USB gadget driver model Sam Day 2025-04-12 19:40 ` [PATCH 2/3] usb: host: ehci-msm: Register ChipIdea UDC from glue wrapper Sam Day @ 2025-04-12 19:40 ` Sam Day 2025-04-16 19:03 ` Stephan Gerhold 2 siblings, 1 reply; 9+ messages in thread From: Sam Day @ 2025-04-12 19:40 UTC (permalink / raw) To: Lukasz Majewski, Mattijs Korpershoek, Marek Vasut, Tom Rini, Caleb Connolly, Neil Armstrong, Sumit Garg, Stephan Gerhold Cc: u-boot, u-boot-qcom, Sam Day Now that the ChipIdea UDC driver supports USB Gadget driver model, we can enable it alongside the dwc3 generic driver. Signed-off-by: Sam Day <me@samcday.com> --- configs/qcom_defconfig | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/configs/qcom_defconfig b/configs/qcom_defconfig index 537806450dc4a61d3c617cdd2b0cfb8eab1c343c..e8582d4e6bd2fae4ff2f7e34dc32651ea2de76bc 100644 --- a/configs/qcom_defconfig +++ b/configs/qcom_defconfig @@ -45,6 +45,7 @@ CONFIG_OF_UPSTREAM_BUILD_VENDOR=y CONFIG_USE_DEFAULT_ENV_FILE=y CONFIG_DEFAULT_ENV_FILE="board/qualcomm/default.env" CONFIG_BUTTON_QCOM_PMIC=y +CONFIG_CI_UDC=y CONFIG_CLK=y CONFIG_CLK_STUB=y CONFIG_CLK_QCOM_APQ8016=y @@ -121,6 +122,7 @@ CONFIG_RNG_MSM=y CONFIG_SCSI=y CONFIG_MSM_SERIAL=y CONFIG_MSM_GENI_SERIAL=y +CONFIG_MSM8916_USB_PHY=y CONFIG_SOC_QCOM=y CONFIG_QCOM_COMMAND_DB=y CONFIG_QCOM_RPMH=y @@ -133,6 +135,10 @@ CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y CONFIG_USB_DWC3=y CONFIG_USB_DWC3_GENERIC=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_MSM=y +CONFIG_USB_ULPI=y +CONFIG_USB_ULPI_VIEWPORT=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_DOWNLOAD=y CONFIG_USB_FUNCTION_MASS_STORAGE=y -- 2.49.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 3/3] qcom_defconfig: Enable MSM8916 USB PHY + ChipIdea UDC 2025-04-12 19:40 ` [PATCH 3/3] qcom_defconfig: Enable MSM8916 USB PHY + ChipIdea UDC Sam Day @ 2025-04-16 19:03 ` Stephan Gerhold 0 siblings, 0 replies; 9+ messages in thread From: Stephan Gerhold @ 2025-04-16 19:03 UTC (permalink / raw) To: Sam Day Cc: Lukasz Majewski, Mattijs Korpershoek, Marek Vasut, Tom Rini, Caleb Connolly, Neil Armstrong, Sumit Garg, u-boot, u-boot-qcom On Sat, Apr 12, 2025 at 07:40:11PM +0000, Sam Day wrote: > Now that the ChipIdea UDC driver supports USB Gadget driver model, we > can enable it alongside the dwc3 generic driver. > > Signed-off-by: Sam Day <me@samcday.com> > --- > configs/qcom_defconfig | 6 ++++++ > 1 file changed, 6 insertions(+) > > diff --git a/configs/qcom_defconfig b/configs/qcom_defconfig > index 537806450dc4a61d3c617cdd2b0cfb8eab1c343c..e8582d4e6bd2fae4ff2f7e34dc32651ea2de76bc 100644 > --- a/configs/qcom_defconfig > +++ b/configs/qcom_defconfig > @@ -45,6 +45,7 @@ CONFIG_OF_UPSTREAM_BUILD_VENDOR=y > CONFIG_USE_DEFAULT_ENV_FILE=y > CONFIG_DEFAULT_ENV_FILE="board/qualcomm/default.env" > CONFIG_BUTTON_QCOM_PMIC=y > +CONFIG_CI_UDC=y > CONFIG_CLK=y > CONFIG_CLK_STUB=y > CONFIG_CLK_QCOM_APQ8016=y > @@ -121,6 +122,7 @@ CONFIG_RNG_MSM=y > CONFIG_SCSI=y > CONFIG_MSM_SERIAL=y > CONFIG_MSM_GENI_SERIAL=y > +CONFIG_MSM8916_USB_PHY=y > CONFIG_SOC_QCOM=y > CONFIG_QCOM_COMMAND_DB=y > CONFIG_QCOM_RPMH=y > @@ -133,6 +135,10 @@ CONFIG_USB_XHCI_HCD=y > CONFIG_USB_XHCI_DWC3=y > CONFIG_USB_DWC3=y > CONFIG_USB_DWC3_GENERIC=y > +CONFIG_USB_EHCI_HCD=y > +CONFIG_USB_EHCI_MSM=y > +CONFIG_USB_ULPI=y > +CONFIG_USB_ULPI_VIEWPORT=y > CONFIG_USB_GADGET=y > CONFIG_USB_GADGET_DOWNLOAD=y > CONFIG_USB_FUNCTION_MASS_STORAGE=y Please run "make savedefconfig" "cp defconfig configs/qcom_defconfig". Defconfigs are not alphabetically ordered, they are ordered based on the definitions in the Kconfig files. And some of the options (e.g. CONFIG_MSM8916_USB_PHY) will disappear because they're already selected by other options. :-) Thanks, Stephan ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2025-06-04 12:48 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-04-12 19:39 [PATCH 0/3] Support MSM8916 USB PHY + UDC in qcom_defconfig Sam Day 2025-04-12 19:39 ` [PATCH 1/3] usb: udc: ci: support USB gadget driver model Sam Day 2025-04-16 18:51 ` Stephan Gerhold 2025-04-19 9:32 ` Sam Day 2025-06-04 7:07 ` Wojciech Dubowik 2025-04-12 19:40 ` [PATCH 2/3] usb: host: ehci-msm: Register ChipIdea UDC from glue wrapper Sam Day 2025-04-16 18:57 ` Stephan Gerhold 2025-04-12 19:40 ` [PATCH 3/3] qcom_defconfig: Enable MSM8916 USB PHY + ChipIdea UDC Sam Day 2025-04-16 19:03 ` Stephan Gerhold
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox