From: Chandana Kishori Chiluveru <cchiluve@codeaurora.org>
To: balbi@kernel.org, agross@kernel.org, david.brown@linaro.org
Cc: linux-usb@vger.kernel.org, linux-arm-msm@vger.kernel.org,
Chandana Kishori Chiluveru <cchiluve@codeaurora.org>
Subject: [PATCH 2/3] usb: dwc3: qcom: Add interconnect support in dwc3 driver
Date: Wed, 11 Sep 2019 10:24:34 +0530 [thread overview]
Message-ID: <1568177675-18764-3-git-send-email-cchiluve@codeaurora.org> (raw)
In-Reply-To: <1568177675-18764-1-git-send-email-cchiluve@codeaurora.org>
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: Chandana Kishori Chiluveru <cchiluve@codeaurora.org>
---
drivers/usb/dwc3/dwc3-qcom.c | 147 ++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 145 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c
index 184df4d..4b8c2ae 100644
--- a/drivers/usb/dwc3/dwc3-qcom.c
+++ b/drivers/usb/dwc3/dwc3-qcom.c
@@ -14,6 +14,7 @@
#include <linux/extcon.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
+#include <linux/interconnect.h>
#include <linux/phy/phy.h>
#include <linux/usb/of.h>
#include <linux/reset.h>
@@ -38,6 +39,9 @@
#define PWR_EVNT_LPM_IN_L2_MASK BIT(4)
#define PWR_EVNT_LPM_OUT_L2_MASK BIT(5)
+#define USB_DDR "usb-ddr"
+#define APPS_USB "apps-usb"
+
struct dwc3_qcom {
struct device *dev;
void __iomem *qscratch_base;
@@ -59,8 +63,13 @@ struct dwc3_qcom {
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;
};
+static int usb_interconnect_enable(struct dwc3_qcom *qcom);
+static int usb_interconnect_disable(struct dwc3_qcom *qcom);
+
static inline void dwc3_qcom_setbits(void __iomem *base, u32 offset, u32 val)
{
u32 reg;
@@ -222,7 +231,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;
@@ -234,6 +243,11 @@ static int dwc3_qcom_suspend(struct dwc3_qcom *qcom)
for (i = qcom->num_clocks - 1; i >= 0; i--)
clk_disable_unprepare(qcom->clks[i]);
+ /* Remove bus voting */
+ ret = usb_interconnect_disable(qcom);
+ if (ret)
+ dev_err(qcom->dev, "bus bw voting failed %d\n", ret);
+
qcom->is_suspended = true;
dwc3_qcom_enable_interrupts(qcom);
@@ -259,6 +273,11 @@ static int dwc3_qcom_resume(struct dwc3_qcom *qcom)
}
}
+ /* Add bus voting */
+ ret = usb_interconnect_enable(qcom);
+ if (ret)
+ dev_err(qcom->dev, "bus bw voting failed %d\n", ret);
+
/* Clear existing events from PHY related to L2 in/out */
dwc3_qcom_setbits(qcom->qscratch_base, PWR_EVNT_IRQ_STAT_REG,
PWR_EVNT_LPM_IN_L2_MASK | PWR_EVNT_LPM_OUT_L2_MASK);
@@ -409,6 +428,116 @@ static int dwc3_qcom_clk_init(struct dwc3_qcom *qcom, int count)
return 0;
}
+/* Interconnect path bandwidths in KBps */
+#define USB_MEMORY_AVG_HS_BW 240000
+#define USB_MEMORY_PEAK_HS_BW 700000
+#define USB_MEMORY_AVG_SS_BW 1000000
+#define USB_MEMORY_PEAK_SS_BW 2500000
+#define APPS_USB_AVG_BW 0
+#define APPS_USB_PEAK_BW 40000
+
+/**
+ * usb_interconnect_init() - Request to get interconnect path handle
+ * @qcom: Pointer to the concerned usb core.
+ *
+ */
+static int usb_interconnect_init(struct dwc3_qcom *qcom)
+{
+ struct device *dev = qcom->dev;
+
+ 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 %s path\n",
+ PTR_ERR(qcom->usb_ddr_icc_path), USB_DDR);
+ 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 %s path\n",
+ PTR_ERR(qcom->apps_usb_icc_path), APPS_USB);
+ return PTR_ERR(qcom->usb_ddr_icc_path);
+ }
+
+ return 0;
+}
+
+/**
+ * geni_interconnect_exit() - Request to release interconnect path handle
+ * @qcom: Pointer to the concerned usb core.
+ *
+ * This function is used to release interconnect path handle.
+ */
+static void usb_interconnect_exit(struct dwc3_qcom *qcom)
+{
+ icc_put(qcom->usb_ddr_icc_path);
+ icc_put(qcom->apps_usb_icc_path);
+}
+
+/* Currently we only use bandwidth level, so just "enable" interconnects */
+static int usb_interconnect_enable(struct dwc3_qcom *qcom)
+{
+ struct dwc3 *dwc;
+ int ret;
+
+ dwc = platform_get_drvdata(qcom->dwc3);
+ if (!dwc) {
+ dev_err(qcom->dev, "Failed to get dwc3 device\n");
+ return -EPROBE_DEFER;
+ }
+
+ if (dwc->maximum_speed == USB_SPEED_SUPER) {
+ ret = icc_set_bw(qcom->usb_ddr_icc_path,
+ USB_MEMORY_AVG_SS_BW, USB_MEMORY_PEAK_SS_BW);
+ if (ret)
+ return ret;
+ } 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)
+ goto err_disable_mem_path;
+
+ return 0;
+
+err_disable_mem_path:
+ icc_set_bw(qcom->usb_ddr_icc_path, 0, 0);
+
+ return ret;
+}
+
+/* To disable an interconnect, we just its bandwidth to 0 */
+static int usb_interconnect_disable(struct dwc3_qcom *qcom)
+{
+ struct dwc3 *dwc = platform_get_drvdata(qcom->dwc3);
+ 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; /* Success */
+
+ /* Re-enable things in the event of an error */
+err_reenable_memory_path:
+ if (dwc->maximum_speed == USB_SPEED_SUPER)
+ icc_set_bw(qcom->usb_ddr_icc_path,
+ USB_MEMORY_AVG_SS_BW, USB_MEMORY_PEAK_SS_BW);
+ else
+ icc_set_bw(qcom->usb_ddr_icc_path,
+ USB_MEMORY_AVG_HS_BW, USB_MEMORY_PEAK_HS_BW);
+
+ return ret;
+}
static int dwc3_qcom_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node, *dwc3_np;
@@ -494,6 +623,17 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
goto depopulate;
}
+ ret = usb_interconnect_init(qcom);
+ if (ret) {
+ dev_err(dev, "failed to get interconnect handle ret:%d\n", ret);
+ goto depopulate;
+ }
+ ret = usb_interconnect_enable(qcom);
+ if (ret) {
+ dev_err(qcom->dev, "bus bw voting failed %d\n", ret);
+ goto interconnect_exit;
+ }
+
qcom->mode = usb_get_dr_mode(&qcom->dwc3->dev);
/* enable vbus override for device mode */
@@ -503,7 +643,7 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
/* register extcon to override sw_vbus on Vbus change later */
ret = dwc3_qcom_register_extcon(qcom);
if (ret)
- goto depopulate;
+ goto interconnect_exit;
device_init_wakeup(&pdev->dev, 1);
qcom->is_suspended = false;
@@ -513,6 +653,8 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
return 0;
+interconnect_exit:
+ usb_interconnect_exit(qcom);
depopulate:
of_platform_depopulate(&pdev->dev);
clk_disable:
@@ -540,6 +682,7 @@ static int dwc3_qcom_remove(struct platform_device *pdev)
}
qcom->num_clocks = 0;
+ usb_interconnect_exit(qcom);
reset_control_assert(qcom->resets);
pm_runtime_allow(dev);
--
Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc.,
is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
next prev parent reply other threads:[~2019-09-11 4:55 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-09-11 4:54 [PATCH 0/3] ADD interconnect support for USB Chandana Kishori Chiluveru
2019-09-11 4:54 ` [PATCH 1/3] dt-bindings: Introduce interconnect bindings for usb Chandana Kishori Chiluveru
2019-09-16 21:19 ` Matthias Kaehlcke
2019-09-11 4:54 ` Chandana Kishori Chiluveru [this message]
2019-09-12 12:54 ` [PATCH 2/3] usb: dwc3: qcom: Add interconnect support in dwc3 driver Georgi Djakov
2019-09-11 4:54 ` [PATCH 3/3] arm64: dts: sdm845: Add interconnect properties for USB Chandana Kishori Chiluveru
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=1568177675-18764-3-git-send-email-cchiluve@codeaurora.org \
--to=cchiluve@codeaurora.org \
--cc=agross@kernel.org \
--cc=balbi@kernel.org \
--cc=david.brown@linaro.org \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-usb@vger.kernel.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.