From: Matthias Kaehlcke <mka@chromium.org>
To: Sandeep Maheswaram <sanm@codeaurora.org>
Cc: Andy Gross <agross@kernel.org>,
Bjorn Andersson <bjorn.andersson@linaro.org>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Rob Herring <robh+dt@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
Felipe Balbi <balbi@kernel.org>,
Stephen Boyd <swboyd@chromium.org>,
Doug Anderson <dianders@chromium.org>,
linux-arm-msm@vger.kernel.org, linux-usb@vger.kernel.org,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
Manu Gautam <mgautam@codeaurora.org>,
Chandana Kishori Chiluveru <cchiluve@codeaurora.org>
Subject: Re: [PATCH v8 1/2] usb: dwc3: qcom: Add interconnect support in dwc3 driver
Date: Thu, 9 Jul 2020 10:19:04 -0700 [thread overview]
Message-ID: <20200709171904.GK3191083@google.com> (raw)
In-Reply-To: <1594310413-14577-2-git-send-email-sanm@codeaurora.org>
Hi Sandeep,
On Thu, Jul 09, 2020 at 09:30:11PM +0530, Sandeep Maheswaram wrote:
> Add interconnect support in dwc3-qcom driver to vote for bus
> bandwidth.
>
> This requires for two different paths - from USB master to
> DDR slave. The other is from APPS master to USB slave.
>
> Signed-off-by: Sandeep Maheswaram <sanm@codeaurora.org>
> Signed-off-by: Chandana Kishori Chiluveru <cchiluve@codeaurora.org>
> Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
> ---
> drivers/usb/dwc3/dwc3-qcom.c | 127 ++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 125 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c
> index 1dfd024..5532988 100644
> --- a/drivers/usb/dwc3/dwc3-qcom.c
> +++ b/drivers/usb/dwc3/dwc3-qcom.c
> @@ -13,6 +13,7 @@
> #include <linux/module.h>
> #include <linux/kernel.h>
> #include <linux/extcon.h>
> +#include <linux/interconnect.h>
> #include <linux/of_platform.h>
> #include <linux/platform_device.h>
> #include <linux/phy/phy.h>
> @@ -43,6 +44,14 @@
> #define SDM845_QSCRATCH_SIZE 0x400
> #define SDM845_DWC3_CORE_SIZE 0xcd00
>
> +/* Interconnect path bandwidths in MBps */
> +#define USB_MEMORY_AVG_HS_BW MBps_to_icc(240)
> +#define USB_MEMORY_PEAK_HS_BW MBps_to_icc(700)
> +#define USB_MEMORY_AVG_SS_BW MBps_to_icc(1000)
> +#define USB_MEMORY_PEAK_SS_BW MBps_to_icc(2500)
> +#define APPS_USB_AVG_BW 0
> +#define APPS_USB_PEAK_BW MBps_to_icc(40)
> +
> struct dwc3_acpi_pdata {
> u32 qscratch_base_offset;
> u32 qscratch_base_size;
> @@ -73,9 +82,12 @@ struct dwc3_qcom {
>
> const struct dwc3_acpi_pdata *acpi_pdata;
>
> + enum usb_device_speed max_speed;
> enum usb_dr_mode mode;
> bool is_suspended;
> bool pm_suspended;
> + struct icc_path *usb_ddr_icc_path;
> + struct icc_path *apps_usb_icc_path;
nit: the names are a bit clunky, the 'usb' part is redundant. You could name
'icc_path_ddr' and 'icc_path_apps' or add an anonymous struct:
struct {
struct icc_path ddr;
struct icc_path apps;
};
not super-important, but since it looks like you have to respin anyway it's
something to consider.
> };
>
> static inline void dwc3_qcom_setbits(void __iomem *base, u32 offset, u32 val)
> @@ -190,6 +202,99 @@ static int dwc3_qcom_register_extcon(struct dwc3_qcom *qcom)
> return 0;
> }
>
> +/* Currently we only use bandwidth level, so just "enable" interconnects */
> +static int dwc3_qcom_interconnect_enable(struct dwc3_qcom *qcom)
> +{
> + int ret;
> +
> + if (qcom->max_speed >= USB_SPEED_SUPER)
> + ret = icc_set_bw(qcom->usb_ddr_icc_path,
> + USB_MEMORY_AVG_SS_BW, USB_MEMORY_PEAK_SS_BW);
> + else
> + ret = icc_set_bw(qcom->usb_ddr_icc_path,
> + USB_MEMORY_AVG_HS_BW, USB_MEMORY_PEAK_HS_BW);
> +
> + if (ret)
> + return ret;
> +
> + ret = icc_set_bw(qcom->apps_usb_icc_path,
> + APPS_USB_AVG_BW, APPS_USB_PEAK_BW);
> + if (ret)
> + icc_set_bw(qcom->usb_ddr_icc_path, 0, 0);
> +
The helpers icc_enable/disable() were recently added. With that you only
have to set the bandwidth once (unless it changes) and then use icc_disable()
to set it to 0 and icc_enable() to restore it.
With icc_enable/disable() the above code would move to
dwc3_qcom_interconnect_init(). It would also make it unnecessary to
have a 'max_speed' field in struct dwc3_qcom.
With that it might not be worth to keep dwc3_qcom_interconnect_enable/disable(),
since they will be relatively short and only have a single caller.
> + return ret;
> +}
> +
> +/* To disable an interconnect, we just set its bandwidth to 0 */
> +static int dwc3_qcom_interconnect_disable(struct dwc3_qcom *qcom)
> +{
> + int ret;
> +
> + ret = icc_set_bw(qcom->usb_ddr_icc_path, 0, 0);
> + if (ret)
> + return ret;
> +
> + ret = icc_set_bw(qcom->apps_usb_icc_path, 0, 0);
> + if (ret)
> + goto err_reenable_memory_path;
> +
> + return 0;
> +
> + /* Re-enable things in the event of an error */
> +err_reenable_memory_path:
> + dwc3_qcom_interconnect_enable(qcom);
> +
> + return ret;
> +}
> +
> +/**
> + * dwc3_qcom_interconnect_init() - Get interconnect path handles
> + * @qcom: Pointer to the concerned usb core.
> + *
> + */
> +static int dwc3_qcom_interconnect_init(struct dwc3_qcom *qcom)
> +{
> + struct device *dev = qcom->dev;
> + int ret;
> +
> + if (!device_is_bound(&qcom->dwc3->dev))
> + return -EPROBE_DEFER;
This is the main reason you need to respin. The outcome of earlier
discussions with Greg KH and Rob Herring was that using device_is_bound()
isn't the correct solution, which is why you call usb_get_maximum_speed()
in _probe().
> +
> + qcom->usb_ddr_icc_path = of_icc_get(dev, "usb-ddr");
> + if (IS_ERR(qcom->usb_ddr_icc_path)) {
> + dev_err(dev, "Error: (%ld) failed getting usb-ddr path\n",
nit: the "Error ... failed" is a bit redundant, the message is also
inconsistent with the format used when dwc3_qcom_interconnect_enable()
fails (a few lines further below). I would suggest to use "failed to
<whatever failed>: %d\n".
> + PTR_ERR(qcom->usb_ddr_icc_path));
> + return PTR_ERR(qcom->usb_ddr_icc_path);
> + }
> +
> + qcom->apps_usb_icc_path = of_icc_get(dev, "apps-usb");
> + if (IS_ERR(qcom->apps_usb_icc_path)) {
> + dev_err(dev, "Error: (%ld) failed getting apps-usb path\n",
> + PTR_ERR(qcom->apps_usb_icc_path));
ditto
> + return PTR_ERR(qcom->apps_usb_icc_path);
> + }
> +
> + ret = dwc3_qcom_interconnect_enable(qcom);
> + if (ret) {
> + dev_err(dev, "failed to enable interconnect %d\n", ret);
nit: add ':' after 'interconnect'
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +/**
> + * dwc3_qcom_interconnect_exit() - Release interconnect path handles
> + * @qcom: Pointer to the concerned usb core.
> + *
> + * This function is used to release interconnect path handle.
> + */
> +static void dwc3_qcom_interconnect_exit(struct dwc3_qcom *qcom)
> +{
> + icc_put(qcom->usb_ddr_icc_path);
> + icc_put(qcom->apps_usb_icc_path);
> +}
> +
> static void dwc3_qcom_disable_interrupts(struct dwc3_qcom *qcom)
> {
> if (qcom->hs_phy_irq) {
> @@ -239,7 +344,7 @@ static void dwc3_qcom_enable_interrupts(struct dwc3_qcom *qcom)
> static int dwc3_qcom_suspend(struct dwc3_qcom *qcom)
> {
> u32 val;
> - int i;
> + int i, ret;
>
> if (qcom->is_suspended)
> return 0;
> @@ -251,6 +356,10 @@ static int dwc3_qcom_suspend(struct dwc3_qcom *qcom)
> for (i = qcom->num_clocks - 1; i >= 0; i--)
> clk_disable_unprepare(qcom->clks[i]);
>
> + ret = dwc3_qcom_interconnect_disable(qcom);
> + if (ret)
> + dev_warn(qcom->dev, "failed to disable interconnect %d\n", ret);
nit: add ':' after 'interconnect'.
> +
> qcom->is_suspended = true;
> dwc3_qcom_enable_interrupts(qcom);
>
> @@ -276,6 +385,10 @@ static int dwc3_qcom_resume(struct dwc3_qcom *qcom)
> }
> }
>
> + ret = dwc3_qcom_interconnect_enable(qcom);
> + if (ret)
> + dev_warn(qcom->dev, "failed to enable interconnect %d\n", ret);
ditto
next prev parent reply other threads:[~2020-07-09 17:19 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-07-09 16:00 [PATCH v8 0/2] ADD interconnect support for Qualcomm DWC3 driver Sandeep Maheswaram
2020-07-09 16:00 ` [PATCH v8 1/2] usb: dwc3: qcom: Add interconnect support in dwc3 driver Sandeep Maheswaram
2020-07-09 17:19 ` Matthias Kaehlcke [this message]
2020-07-09 17:26 ` Matthias Kaehlcke
2020-07-09 16:00 ` [PATCH v8 2/2] arm64: dts: qcom: sc7180: Add maximum speed property for DWC3 USB node Sandeep Maheswaram
2020-07-09 17:41 ` Matthias Kaehlcke
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200709171904.GK3191083@google.com \
--to=mka@chromium.org \
--cc=agross@kernel.org \
--cc=balbi@kernel.org \
--cc=bjorn.andersson@linaro.org \
--cc=cchiluve@codeaurora.org \
--cc=devicetree@vger.kernel.org \
--cc=dianders@chromium.org \
--cc=gregkh@linuxfoundation.org \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=mgautam@codeaurora.org \
--cc=robh+dt@kernel.org \
--cc=sanm@codeaurora.org \
--cc=swboyd@chromium.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.