[PATCH 2/2] ehci: msm: bring up iface + core clocks
Caleb Connolly
caleb.connolly at linaro.org
Thu May 2 15:39:15 CEST 2024
On 02/05/2024 15:16, Sam Day wrote:
> This seems to be necessary on my samsung-a5. Without this patch, the
> first access of EHCI registers causes a bus stall and subsequent reset.
>
> I am unsure why this wasn't already necessary for db410c, perhaps those
> clocks are already enabled on boot.
>
> Signed-off-by: Sam Day <me at samcday.com>
> ---
> drivers/usb/host/ehci-msm.c | 37 +++++++++++++++++++++++++++++++++++--
> 1 file changed, 35 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
> index 98fe7bc3bc..b2e294dd64 100644
> --- a/drivers/usb/host/ehci-msm.c
> +++ b/drivers/usb/host/ehci-msm.c
> @@ -7,8 +7,10 @@
> * Based on Linux driver
> */
>
> +#include <clk.h>
> #include <common.h>
> #include <dm.h>
> +#include <dm/device_compat.h>
> #include <dm/lists.h>
> #include <errno.h>
> #include <usb.h>
> @@ -25,6 +27,8 @@ struct msm_ehci_priv {
> struct usb_ehci *ehci; /* Start of IP core*/
> struct ulpi_viewport ulpi_vp; /* ULPI Viewport */
> struct phy phy;
> + struct clk iface_clk;
> + struct clk core_clk;
You could simplify this with the bulk clock API, but I'm easy either way.
Reviewed-by: Caleb Connolly <caleb.connolly at linaro.org>
> };
>
> static int msm_init_after_reset(struct ehci_ctrl *dev)
> @@ -53,20 +57,46 @@ static int ehci_usb_probe(struct udevice *dev)
> struct ehci_hcor *hcor;
> int ret;
>
> + ret = clk_get_by_name(dev, "core", &p->core_clk);
> + if (ret) {
> + dev_err(dev, "Failed to get core clock: %d\n", ret);
> + return ret;
> + }
> +
> + ret = clk_get_by_name(dev, "iface", &p->iface_clk);
> + if (ret) {
> + dev_err(dev, "Failed to get iface clock: %d\n", ret);
> + return ret;
> + }
> +
> + ret = clk_prepare_enable(&p->core_clk);
> + if (ret)
> + return ret;
> +
> + ret = clk_prepare_enable(&p->iface_clk);
> + if (ret)
> + goto cleanup_core;
> +
> hccr = (struct ehci_hccr *)((phys_addr_t)&ehci->caplength);
> hcor = (struct ehci_hcor *)((phys_addr_t)hccr +
> HC_LENGTH(ehci_readl(&(hccr)->cr_capbase)));
>
> ret = generic_setup_phy(dev, &p->phy, 0);
> if (ret)
> - return ret;
> + goto cleanup_iface;
>
> ret = board_usb_init(0, plat->init_type);
> if (ret < 0)
> - return ret;
> + goto cleanup_iface;
>
> return ehci_register(dev, hccr, hcor, &msm_ehci_ops, 0,
> plat->init_type);
> +
> +cleanup_iface:
> + clk_disable_unprepare(&p->iface_clk);
> +cleanup_core:
> + clk_disable_unprepare(&p->core_clk);
> + return ret;
> }
>
> static int ehci_usb_remove(struct udevice *dev)
> @@ -82,6 +112,9 @@ static int ehci_usb_remove(struct udevice *dev)
> /* Stop controller. */
> clrbits_le32(&ehci->usbcmd, CMD_RUN);
>
> + clk_disable_unprepare(&p->iface_clk);
> + clk_disable_unprepare(&p->core_clk);
> +
> ret = generic_shutdown_phy(&p->phy);
> if (ret)
> return ret;
>
--
// Caleb (they/them)
More information about the U-Boot
mailing list