From patchwork Tue Mar 10 10:09:08 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Delaunay X-Patchwork-Id: 243472 List-Id: U-Boot discussion From: patrick.delaunay at st.com (Patrick Delaunay) Date: Tue, 10 Mar 2020 11:09:08 +0100 Subject: [PATCH v6 1/5] dm: clk: add stub when CONFIG_CLK is deactivated In-Reply-To: <20200310100912.28129-1-patrick.delaunay@st.com> References: <20200310100912.28129-1-patrick.delaunay@st.com> Message-ID: <20200310100912.28129-2-patrick.delaunay@st.com> Add stub for functions clk_...() when CONFIG_CLK is deactivated. This patch avoids compilation issues for driver using these API without protection (#if CONFIG_IS_ENABLED(CLK)) For example, before this patch we have undefined reference to `clk_disable_bulk') for code: clk_disable_bulk(&priv->clks); clk_release_bulk(&priv->clks); Signed-off-by: Patrick Delaunay Reviewed-by: Simon Goldschmidt --- Changes in v6: - return success in stub for clk_free/clk_enable/clk_disable/ clk_enable_bulk/clk_disable_bulk Changes in v5: - use ERR_PTR in clk_get_parent() - force bulk->count = 0 in clk_get_bulk to avoid issue for next call of clk_enable_bulk / clk_enable_bulk - update commit message Changes in v4: - Add stub for all functions using 'struct clk' or 'struct clk_bulk' after remarks on v3 Changes in v3: - Add stub for clk_disable_bulk Changes in v2: None include/clk.h | 102 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 89 insertions(+), 13 deletions(-) diff --git a/include/clk.h b/include/clk.h index 3336301815..60c4b7d075 100644 --- a/include/clk.h +++ b/include/clk.h @@ -9,6 +9,7 @@ #define _CLK_H_ #include +#include #include #include @@ -312,6 +313,7 @@ static inline int clk_release_bulk(struct clk_bulk *bulk) return clk_release_all(bulk->clks, bulk->count); } +#if CONFIG_IS_ENABLED(CLK) /** * clk_request - Request a clock by provider-specific ID. * @@ -433,19 +435,6 @@ int clk_disable_bulk(struct clk_bulk *bulk); */ bool clk_is_match(const struct clk *p, const struct clk *q); -int soc_clk_dump(void); - -/** - * clk_valid() - check if clk is valid - * - * @clk: the clock to check - * @return true if valid, or false - */ -static inline bool clk_valid(struct clk *clk) -{ - return clk && !!clk->dev; -} - /** * clk_get_by_id() - Get the clock by its ID * @@ -465,6 +454,93 @@ int clk_get_by_id(ulong id, struct clk **clkp); * @return true on binded, or false on no */ bool clk_dev_binded(struct clk *clk); + +#else /* CONFIG_IS_ENABLED(CLK) */ + +static inline int clk_request(struct udevice *dev, struct clk *clk) +{ + return -ENOSYS; +} + +static inline int clk_free(struct clk *clk) +{ + return 0; +} + +static inline ulong clk_get_rate(struct clk *clk) +{ + return -ENOSYS; +} + +static inline struct clk *clk_get_parent(struct clk *clk) +{ + return ERR_PTR(-ENOSYS); +} + +static inline long long clk_get_parent_rate(struct clk *clk) +{ + return -ENOSYS; +} + +static inline ulong clk_set_rate(struct clk *clk, ulong rate) +{ + return -ENOSYS; +} + +static inline int clk_set_parent(struct clk *clk, struct clk *parent) +{ + return -ENOSYS; +} + +static inline int clk_enable(struct clk *clk) +{ + return 0; +} + +static inline int clk_enable_bulk(struct clk_bulk *bulk) +{ + return 0; +} + +static inline int clk_disable(struct clk *clk) +{ + return 0; +} + +static inline int clk_disable_bulk(struct clk_bulk *bulk) +{ + return 0; +} + +static inline bool clk_is_match(const struct clk *p, const struct clk *q) +{ + return false; +} + +static inline int clk_get_by_id(ulong id, struct clk **clkp) +{ + return -ENOSYS; +} + +static inline bool clk_dev_binded(struct clk *clk) +{ + return false; +} +#endif /* CONFIG_IS_ENABLED(CLK) */ + +/** + * clk_valid() - check if clk is valid + * + * @clk: the clock to check + * @return true if valid, or false + */ +static inline bool clk_valid(struct clk *clk) +{ + return clk && !!clk->dev; +} + +int soc_clk_dump(void); + #endif #define clk_prepare_enable(clk) clk_enable(clk) From patchwork Tue Mar 10 10:09:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Delaunay X-Patchwork-Id: 243473 List-Id: U-Boot discussion From: patrick.delaunay at st.com (Patrick Delaunay) Date: Tue, 10 Mar 2020 11:09:09 +0100 Subject: [PATCH v6 2/5] usb: host: dwc2: add phy support In-Reply-To: <20200310100912.28129-1-patrick.delaunay@st.com> References: <20200310100912.28129-1-patrick.delaunay@st.com> Message-ID: <20200310100912.28129-3-patrick.delaunay@st.com> Use generic phy to initialize the PHY associated to the DWC2 device and available in the device tree. This patch don't added dependency because when CONFIG_PHY is not activated, the generic PHY function are stubbed. Reviewed-by: Simon Goldschmidt Signed-off-by: Patrick Delaunay --- Changes in v6: None Changes in v5: - inverse logic for -ENOENT test on generic_phy_get_by_index result - Add some comments Changes in v4: None Changes in v3: None Changes in v2: - update dev_err - update commit message - change dev_err to dev_dbg for PHY function call - treat dwc2_shutdown_phy error drivers/usb/host/dwc2.c | 66 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c index e4efaf1e59..a8e64825b5 100644 --- a/drivers/usb/host/dwc2.c +++ b/drivers/usb/host/dwc2.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -37,6 +38,7 @@ struct dwc2_priv { #ifdef CONFIG_DM_REGULATOR struct udevice *vbus_supply; #endif + struct phy phy; #else uint8_t *aligned_buffer; uint8_t *status_buffer; @@ -1322,13 +1324,71 @@ static int dwc2_usb_ofdata_to_platdata(struct udevice *dev) return 0; } +static int dwc2_setup_phy(struct udevice *dev) +{ + struct dwc2_priv *priv = dev_get_priv(dev); + int ret; + + ret = generic_phy_get_by_index(dev, 0, &priv->phy); + if (ret) { + if (ret == -ENOENT) + return 0; /* no PHY, nothing to do */ + dev_err(dev, "Failed to get USB PHY: %d.\n", ret); + return ret; + } + + ret = generic_phy_init(&priv->phy); + if (ret) { + dev_dbg(dev, "Failed to init USB PHY: %d.\n", ret); + return ret; + } + + ret = generic_phy_power_on(&priv->phy); + if (ret) { + dev_dbg(dev, "Failed to power on USB PHY: %d.\n", ret); + generic_phy_exit(&priv->phy); + return ret; + } + + return 0; +} + +static int dwc2_shutdown_phy(struct udevice *dev) +{ + struct dwc2_priv *priv = dev_get_priv(dev); + int ret; + + /* PHY is not valid when generic_phy_get_by_index() = -ENOENT */ + if (!generic_phy_valid(&priv->phy)) + return 0; /* no PHY, nothing to do */ + + ret = generic_phy_power_off(&priv->phy); + if (ret) { + dev_dbg(dev, "Failed to power off USB PHY: %d.\n", ret); + return ret; + } + + ret = generic_phy_exit(&priv->phy); + if (ret) { + dev_dbg(dev, "Failed to power off USB PHY: %d.\n", ret); + return ret; + } + + return 0; +} + static int dwc2_usb_probe(struct udevice *dev) { struct dwc2_priv *priv = dev_get_priv(dev); struct usb_bus_priv *bus_priv = dev_get_uclass_priv(dev); + int ret; bus_priv->desc_before_addr = true; + ret = dwc2_setup_phy(dev); + if (ret) + return ret; + return dwc2_init_common(dev, priv); } @@ -1341,6 +1401,12 @@ static int dwc2_usb_remove(struct udevice *dev) if (ret) return ret; + ret = dwc2_shutdown_phy(dev); + if (ret) { + dev_dbg(dev, "Failed to shutdown USB PHY: %d.\n", ret); + return ret; + } + dwc2_uninit_common(priv->regs); reset_release_bulk(&priv->resets); From patchwork Tue Mar 10 10:09:10 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Delaunay X-Patchwork-Id: 243474 List-Id: U-Boot discussion From: patrick.delaunay at st.com (Patrick Delaunay) Date: Tue, 10 Mar 2020 11:09:10 +0100 Subject: [PATCH v6 3/5] usb: host: dwc2: add clk support In-Reply-To: <20200310100912.28129-1-patrick.delaunay@st.com> References: <20200310100912.28129-1-patrick.delaunay@st.com> Message-ID: <20200310100912.28129-4-patrick.delaunay@st.com> Add support for clock with driver model. This patch don't added dependency because when CONFIG_CLK is not activated the clk function are stubbed. Reviewed-by: Simon Goldschmidt Signed-off-by: Patrick Delaunay --- Changes in v6: None Changes in v5: None Changes in v4: None Changes in v3: None Changes in v2: None drivers/usb/host/dwc2.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c index a8e64825b5..b1b79d0a18 100644 --- a/drivers/usb/host/dwc2.c +++ b/drivers/usb/host/dwc2.c @@ -5,14 +5,15 @@ */ #include +#include #include #include #include #include -#include #include #include #include +#include #include #include #include @@ -39,6 +40,7 @@ struct dwc2_priv { struct udevice *vbus_supply; #endif struct phy phy; + struct clk_bulk clks; #else uint8_t *aligned_buffer; uint8_t *status_buffer; @@ -1377,6 +1379,26 @@ static int dwc2_shutdown_phy(struct udevice *dev) return 0; } +static int dwc2_clk_init(struct udevice *dev) +{ + struct dwc2_priv *priv = dev_get_priv(dev); + int ret; + + ret = clk_get_bulk(dev, &priv->clks); + if (ret == -ENOSYS || ret == -ENOENT) + return 0; + if (ret) + return ret; + + ret = clk_enable_bulk(&priv->clks); + if (ret) { + clk_release_bulk(&priv->clks); + return ret; + } + + return 0; +} + static int dwc2_usb_probe(struct udevice *dev) { struct dwc2_priv *priv = dev_get_priv(dev); @@ -1385,6 +1407,10 @@ static int dwc2_usb_probe(struct udevice *dev) bus_priv->desc_before_addr = true; + ret = dwc2_clk_init(dev); + if (ret) + return ret; + ret = dwc2_setup_phy(dev); if (ret) return ret; @@ -1410,6 +1436,8 @@ static int dwc2_usb_remove(struct udevice *dev) dwc2_uninit_common(priv->regs); reset_release_bulk(&priv->resets); + clk_disable_bulk(&priv->clks); + clk_release_bulk(&priv->clks); return 0; } From patchwork Tue Mar 10 10:09:11 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Delaunay X-Patchwork-Id: 243475 List-Id: U-Boot discussion From: patrick.delaunay at st.com (Patrick Delaunay) Date: Tue, 10 Mar 2020 11:09:11 +0100 Subject: [PATCH v6 4/5] usb: host: dwc2: force reset assert In-Reply-To: <20200310100912.28129-1-patrick.delaunay@st.com> References: <20200310100912.28129-1-patrick.delaunay@st.com> Message-ID: <20200310100912.28129-5-patrick.delaunay@st.com> Assert reset before deassert in dwc2_reset; this patch solve issues when the DWC2 registers are already initialized with value incompatible with host mode. Force a hardware reset of the IP reset all the DWC2 registers at default value, the host driver start with a clean state (Core Soft reset doen in dwc_otg_core_reset is not enought to reset all register). The error can occurs in U-Boot when DWC2 device gadget driver force device mode (called by ums or dfu command, before to execute the usb start command). Signed-off-by: Patrick Delaunay Reviewed-by: Simon Goldschmidt --- Changes in v6: None Changes in v5: None Changes in v4: None Changes in v3: None Changes in v2: - add clk_disable_bulk in dwc2_usb_remove drivers/usb/host/dwc2.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c index b1b79d0a18..640ae3e730 100644 --- a/drivers/usb/host/dwc2.c +++ b/drivers/usb/host/dwc2.c @@ -1151,6 +1151,8 @@ static int dwc2_reset(struct udevice *dev) return ret; } + /* force reset to clear all IP register */ + reset_assert_bulk(&priv->resets); ret = reset_deassert_bulk(&priv->resets); if (ret) { reset_release_bulk(&priv->resets); From patchwork Tue Mar 10 10:09:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Delaunay X-Patchwork-Id: 243476 List-Id: U-Boot discussion From: patrick.delaunay at st.com (Patrick Delaunay) Date: Tue, 10 Mar 2020 11:09:12 +0100 Subject: [PATCH v6 5/5] usb: host: dwc2: add trace to have clean usb start In-Reply-To: <20200310100912.28129-1-patrick.delaunay@st.com> References: <20200310100912.28129-1-patrick.delaunay@st.com> Message-ID: <20200310110755.v6.5.I43934c501010bbca1ee5f7c7780e3999eefc425f@changeid> Solve issue for the display of "usb start" command on stm32mp1 because one carriage return is missing in DWC2 probe. Before the patch: STM32MP> usb start starting USB... Bus usb-otg at 49000000: Bus usbh-ehci at 5800d000: USB EHCI 1.00 after the patch: STM32MP> usb start starting USB... Bus usb-otg at 49000000: USB DWC2 Bus usbh-ehci at 5800d000: USB EHCI 1.00 Signed-off-by: Patrick Delaunay --- Changes in v6: None Changes in v5: None Changes in v4: None Changes in v3: None Changes in v2: None drivers/usb/host/dwc2.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c index 640ae3e730..f25ed2dab0 100644 --- a/drivers/usb/host/dwc2.c +++ b/drivers/usb/host/dwc2.c @@ -1219,6 +1219,8 @@ static int dwc2_init_common(struct udevice *dev, struct dwc2_priv *priv) if (readl(®s->gintsts) & DWC2_GINTSTS_CURMODE_HOST) mdelay(1000); + printf("USB DWC2\n"); + return 0; }