summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Yan <leo.yan@linaro.org>2022-07-04 15:45:13 +0800
committerLeo Yan <leo.yan@linaro.org>2022-07-04 17:04:02 +0800
commit5f527aac3c3b1e409c6d4d84997110481e4d25e5 (patch)
treeb765f12ecd630673630b079d7dc52e027e023973
parentbc9cc2cedcbf975430a303a329138658bec67d38 (diff)
i2c: qup: Add interconnect bandwidth request
Signed-off-by: Leo Yan <leo.yan@linaro.org>
-rw-r--r--arch/arm64/boot/dts/qcom/msm8939.dtsi12
-rw-r--r--drivers/i2c/busses/i2c-qup.c25
2 files changed, 37 insertions, 0 deletions
diff --git a/arch/arm64/boot/dts/qcom/msm8939.dtsi b/arch/arm64/boot/dts/qcom/msm8939.dtsi
index 823eeb74b35c6..4ea9ecdf771e7 100644
--- a/arch/arm64/boot/dts/qcom/msm8939.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8939.dtsi
@@ -1620,6 +1620,8 @@
pinctrl-names = "default", "sleep";
pinctrl-0 = <&i2c1_default>;
pinctrl-1 = <&i2c1_sleep>;
+ interconnect-names = "i2c-mem";
+ interconnects = <&pcnoc MASTER_BLSP_1 &bimc SLAVE_EBI_CH0>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1637,6 +1639,8 @@
pinctrl-names = "default", "sleep";
pinctrl-0 = <&i2c2_default>;
pinctrl-1 = <&i2c2_sleep>;
+ interconnect-names = "i2c-mem";
+ interconnects = <&pcnoc MASTER_BLSP_1 &bimc SLAVE_EBI_CH0>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1654,6 +1658,8 @@
pinctrl-names = "default", "sleep";
pinctrl-0 = <&i2c3_default>;
pinctrl-1 = <&i2c3_sleep>;
+ interconnect-names = "i2c-mem";
+ interconnects = <&pcnoc MASTER_BLSP_1 &bimc SLAVE_EBI_CH0>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1671,6 +1677,8 @@
pinctrl-names = "default", "sleep";
pinctrl-0 = <&i2c4_default>;
pinctrl-1 = <&i2c4_sleep>;
+ interconnect-names = "i2c-mem";
+ interconnects = <&pcnoc MASTER_BLSP_1 &bimc SLAVE_EBI_CH0>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1688,6 +1696,8 @@
pinctrl-names = "default", "sleep";
pinctrl-0 = <&i2c5_default>;
pinctrl-1 = <&i2c5_sleep>;
+ interconnect-names = "i2c-mem";
+ interconnects = <&pcnoc MASTER_BLSP_1 &bimc SLAVE_EBI_CH0>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1705,6 +1715,8 @@
pinctrl-names = "default", "sleep";
pinctrl-0 = <&i2c6_default>;
pinctrl-1 = <&i2c6_sleep>;
+ interconnect-names = "i2c-mem";
+ interconnects = <&pcnoc MASTER_BLSP_1 &bimc SLAVE_EBI_CH0>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 69e9f3ecf87d7..5ee5c3e83131c 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -14,6 +14,7 @@
#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/i2c.h>
+#include <linux/interconnect.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
@@ -275,6 +276,11 @@ struct qup_i2c_dev {
void (*read_rx_fifo)(struct qup_i2c_dev *qup);
/* function to write tags in tx fifo for i2c read transfer */
void (*write_rx_tags)(struct qup_i2c_dev *qup);
+
+ /* frequency mode standard */
+ u32 clk_freq;
+ /* interconnect path to scale according to bandwidth needs */
+ struct icc_path *path;
};
static irqreturn_t qup_i2c_interrupt(int irq, void *dev)
@@ -1648,6 +1654,16 @@ static void qup_i2c_disable_clocks(struct qup_i2c_dev *qup)
clk_disable_unprepare(qup->pclk);
}
+static void qup_i2c_enable_icc(struct qup_i2c_dev *qup)
+{
+ icc_set_bw(qup->path, 0, kbps_to_icc(qup->clk_freq));
+}
+
+static void qup_i2c_disable_icc(struct qup_i2c_dev *qup)
+{
+ icc_set_bw(qup->path, 0, 0);
+}
+
static const struct acpi_device_id qup_i2c_acpi_match[] = {
{ "QCOM8010"},
{ },
@@ -1772,6 +1788,10 @@ nodma:
}
ACPI_COMPANION_SET(&qup->adap.dev, ACPI_COMPANION(qup->dev));
} else {
+ qup->path = of_icc_get(qup->dev, "i2c-mem");
+ if (IS_ERR(qup->path))
+ return PTR_ERR(qup->path);
+
qup->clk = devm_clk_get(qup->dev, "core");
if (IS_ERR(qup->clk)) {
dev_err(qup->dev, "Could not get core clock\n");
@@ -1783,6 +1803,8 @@ nodma:
dev_err(qup->dev, "Could not get iface clock\n");
return PTR_ERR(qup->pclk);
}
+ qup->clk_freq = clk_freq;
+ qup_i2c_enable_icc(qup);
qup_i2c_enable_clocks(qup);
src_clk_freq = clk_get_rate(qup->clk);
}
@@ -1915,6 +1937,7 @@ static int qup_i2c_remove(struct platform_device *pdev)
disable_irq(qup->irq);
qup_i2c_disable_clocks(qup);
+ icc_put(qup->path);
i2c_del_adapter(&qup->adap);
pm_runtime_disable(qup->dev);
pm_runtime_set_suspended(qup->dev);
@@ -1927,6 +1950,7 @@ static int qup_i2c_pm_suspend_runtime(struct device *device)
struct qup_i2c_dev *qup = dev_get_drvdata(device);
dev_dbg(device, "pm_runtime: suspending...\n");
+ qup_i2c_disable_icc(qup);
qup_i2c_disable_clocks(qup);
return 0;
}
@@ -1936,6 +1960,7 @@ static int qup_i2c_pm_resume_runtime(struct device *device)
struct qup_i2c_dev *qup = dev_get_drvdata(device);
dev_dbg(device, "pm_runtime: resuming...\n");
+ qup_i2c_enable_icc(qup);
qup_i2c_enable_clocks(qup);
return 0;
}