diff options
author | Leo Yan <leo.yan@linaro.org> | 2022-07-04 15:45:13 +0800 |
---|---|---|
committer | Leo Yan <leo.yan@linaro.org> | 2022-07-04 17:04:02 +0800 |
commit | 5f527aac3c3b1e409c6d4d84997110481e4d25e5 (patch) | |
tree | b765f12ecd630673630b079d7dc52e027e023973 | |
parent | bc9cc2cedcbf975430a303a329138658bec67d38 (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.dtsi | 12 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-qup.c | 25 |
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; } |