aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinaro CI <ci_notify@linaro.org>2018-12-10 00:22:06 +0000
committerLinaro CI <ci_notify@linaro.org>2018-12-10 00:22:06 +0000
commit326fab9ca08c222f3f7e7ab3e8bb614e40616f95 (patch)
treeda36e02a735ab6432e388a723485cb2f292cd709
parent3e8b95aa84367a867377f34e6f9cb787eeedbe41 (diff)
parent026de00a26ccdde3debde4737269fc2dde0f4d83 (diff)
Merge remote-tracking branch 'bus-scaling-consumers/bus-scaling-consumers' into integration-linux-qcomlt
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916.dtsi21
-rw-r--r--arch/arm64/boot/dts/qcom/msm8996.dtsi21
-rw-r--r--drivers/crypto/Kconfig1
-rw-r--r--drivers/crypto/qcom-rng.c10
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c14
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c27
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.h2
-rw-r--r--drivers/i2c/busses/Kconfig1
-rw-r--r--drivers/i2c/busses/i2c-qup.c25
-rw-r--r--drivers/media/platform/qcom/venus/core.c57
-rw-r--r--drivers/media/platform/qcom/venus/core.h13
-rw-r--r--drivers/media/platform/qcom/venus/helpers.c64
-rw-r--r--drivers/mmc/host/Kconfig1
-rw-r--r--drivers/mmc/host/sdhci-msm.c44
-rw-r--r--drivers/pci/controller/dwc/Kconfig1
-rw-r--r--drivers/pci/controller/dwc/pcie-qcom.c9
-rw-r--r--drivers/phy/qualcomm/Kconfig1
-rw-r--r--drivers/phy/qualcomm/phy-qcom-usb-hs.c10
-rw-r--r--drivers/scsi/ufs/Kconfig1
-rw-r--r--drivers/scsi/ufs/ufs-qcom.c13
20 files changed, 328 insertions, 8 deletions
diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
index cd32053d67c3..87a0ccf65cf1 100644
--- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
@@ -521,6 +521,8 @@
pinctrl-names = "default", "sleep";
pinctrl-0 = <&i2c2_default>;
pinctrl-1 = <&i2c2_sleep>;
+ interconnect-names = "i2c-mem";
+ interconnects = <&pnoc MASTER_BLSP_1 &bimc SLAVE_EBI_CH0>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -536,6 +538,8 @@
pinctrl-names = "default", "sleep";
pinctrl-0 = <&i2c4_default>;
pinctrl-1 = <&i2c4_sleep>;
+ interconnect-names = "i2c-mem";
+ interconnects = <&pnoc MASTER_BLSP_1 &bimc SLAVE_EBI_CH0>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -551,6 +555,8 @@
pinctrl-names = "default", "sleep";
pinctrl-0 = <&i2c6_default>;
pinctrl-1 = <&i2c6_sleep>;
+ interconnect-names = "i2c-mem";
+ interconnects = <&pnoc MASTER_BLSP_1 &bimc SLAVE_EBI_CH0>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -602,6 +608,8 @@
<&gcc GCC_SDCC1_AHB_CLK>,
<&xo_board>;
clock-names = "core", "iface", "xo";
+ interconnect-names = "sdhc-mem";
+ interconnects = <&pnoc MASTER_SDCC_1 &bimc SLAVE_EBI_CH0>;
mmc-ddr-1_8v;
bus-width = <8>;
non-removable;
@@ -619,6 +627,8 @@
<&gcc GCC_SDCC2_AHB_CLK>,
<&xo_board>;
clock-names = "core", "iface", "xo";
+ interconnect-names = "sdhc-mem";
+ interconnects = <&pnoc MASTER_SDCC_2 &bimc SLAVE_EBI_CH0>;
bus-width = <4>;
status = "disabled";
};
@@ -655,6 +665,8 @@
reset-names = "phy", "por";
qcom,init-seq = /bits/ 8 <0x0 0x44
0x1 0x6b 0x2 0x24 0x3 0x13>;
+ interconnects = <&pnoc MASTER_USB_HS &bimc SLAVE_EBI_CH0>;
+ interconnect-names = "usb-mem";
};
};
};
@@ -748,6 +760,8 @@
reg = <0x00022000 0x200>;
clocks = <&gcc GCC_PRNG_AHB_CLK>;
clock-names = "core";
+ interconnects = <&bimc MASTER_AMPSS_M0 &pnoc SLAVE_PRNG>;
+ interconnect-names = "cpu";
};
qfprom: qfprom@5c000 {
@@ -847,6 +861,8 @@
power-domains = <&gcc OXILI_GDSC>;
operating-points-v2 = <&gpu_opp_table>;
iommus = <&gpu_iommu 1>, <&gpu_iommu 2>;
+ interconnects = <&bimc MASTER_GRAPHICS_3D &bimc SLAVE_EBI_CH0>;
+ interconnect-names = "gfx";
};
mdss: mdss@1a00000 {
@@ -892,6 +908,9 @@
iommus = <&apps_iommu 4>;
+ interconnects = <&snoc MASTER_MDP_PORT0 &bimc SLAVE_EBI_CH0>;
+ interconnect-names = "port0";
+
ports {
#address-cells = <1>;
#size-cells = <0>;
@@ -1384,6 +1403,8 @@
clock-names = "core", "iface", "bus";
iommus = <&apps_iommu 5>;
memory-region = <&venus_mem>;
+ interconnects = <&snoc MASTER_VIDEO_P0 &bimc SLAVE_EBI_CH0>;
+ interconnect-names = "video";
status = "okay";
video-decoder {
diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi
index 465e805443f5..04948602df35 100644
--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -972,6 +972,8 @@
pinctrl-names = "default", "sleep";
pinctrl-0 = <&blsp2_i2c0_default>;
pinctrl-1 = <&blsp2_i2c0_sleep>;
+ interconnects = <&pnoc MASTER_BLSP_2 &bimc SLAVE_EBI_CH0>;
+ interconnect-names = "ddr";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -984,6 +986,8 @@
clocks = <&gcc GCC_BLSP2_UART2_APPS_CLK>,
<&gcc GCC_BLSP2_AHB_CLK>;
clock-names = "core", "iface";
+ interconnects = <&pnoc MASTER_BLSP_2 &bimc SLAVE_EBI_CH0>;
+ interconnect-names = "ddr";
status = "disabled";
};
@@ -997,6 +1001,8 @@
pinctrl-names = "default", "sleep";
pinctrl-0 = <&blsp2_i2c1_default>;
pinctrl-1 = <&blsp2_i2c1_sleep>;
+ interconnects = <&pnoc MASTER_BLSP_2 &bimc SLAVE_EBI_CH0>;
+ interconnect-names = "ddr";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1022,6 +1028,8 @@
pinctrl-names = "default", "sleep";
pinctrl-0 = <&blsp1_i2c2_default>;
pinctrl-1 = <&blsp1_i2c2_sleep>;
+ interconnects = <&pnoc MASTER_BLSP_1 &bimc SLAVE_EBI_CH0>;
+ interconnect-names = "ddr";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1056,6 +1064,8 @@
clocks = <&gcc GCC_SDCC2_AHB_CLK>,
<&gcc GCC_SDCC2_APPS_CLK>,
<&xo_board>;
+ interconnects = <&pnoc MASTER_SDCC_2 &bimc SLAVE_EBI_CH0>;
+ interconnect-names = "sdhc-mem";
bus-width = <4>;
};
@@ -1417,6 +1427,9 @@
assigned-clock-rates = <19200000>, <60000000>;
power-domains = <&gcc USB30_GDSC>;
+
+ interconnects = <&pnoc MASTER_USB_HS &bimc SLAVE_EBI_CH0>;
+ interconnect-names = "usb-mem";
status = "disabled";
dwc3@7600000 {
@@ -1515,6 +1528,8 @@
"bus_master",
"bus_slave";
+ interconnects = <&a0noc MASTER_PCIE &bimc SLAVE_EBI_CH0>;
+ interconnect-names = "pcie-mem";
};
pcie1: pcie@608000 {
@@ -1568,6 +1583,9 @@
"cfg",
"bus_master",
"bus_slave";
+
+ interconnects = <&a0noc MASTER_PCIE_1 &bimc SLAVE_EBI_CH0>;
+ interconnect-names = "pcie-mem";
};
pcie2: pcie@610000 {
@@ -1620,6 +1638,9 @@
"cfg",
"bus_master",
"bus_slave";
+
+ interconnects = <&a0noc MASTER_PCIE_2 &bimc SLAVE_EBI_CH0>;
+ interconnect-names = "pcie-mem";
};
};
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index caa98a7fe392..c7cc2bad42e4 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -599,6 +599,7 @@ config CRYPTO_DEV_QCE
config CRYPTO_DEV_QCOM_RNG
tristate "Qualcomm Random Number Generator Driver"
depends on ARCH_QCOM || COMPILE_TEST
+ depends on INTERCONNECT || !INTERCONNECT
select CRYPTO_RNG
help
This driver provides support for the Random Number
diff --git a/drivers/crypto/qcom-rng.c b/drivers/crypto/qcom-rng.c
index e54249ccc009..e696a76caa5b 100644
--- a/drivers/crypto/qcom-rng.c
+++ b/drivers/crypto/qcom-rng.c
@@ -7,6 +7,7 @@
#include <linux/acpi.h>
#include <linux/clk.h>
#include <linux/crypto.h>
+#include <linux/interconnect.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
@@ -30,6 +31,7 @@ struct qcom_rng {
void __iomem *base;
struct clk *clk;
unsigned int skip_init;
+ struct icc_path *path;
};
struct qcom_rng_ctx {
@@ -75,6 +77,8 @@ static int qcom_rng_generate(struct crypto_rng *tfm,
struct qcom_rng *rng = ctx->rng;
int ret;
+ icc_set(rng->path, 0, kBps_to_icc(800));
+
ret = clk_prepare_enable(rng->clk);
if (ret)
return ret;
@@ -86,6 +90,8 @@ static int qcom_rng_generate(struct crypto_rng *tfm,
mutex_unlock(&rng->lock);
clk_disable_unprepare(rng->clk);
+ icc_set(rng->path, 0, 0);
+
return 0;
}
@@ -164,6 +170,10 @@ static int qcom_rng_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, rng);
mutex_init(&rng->lock);
+ rng->path = of_icc_get(&pdev->dev, "cpu");
+ if (IS_ERR(rng->path))
+ return PTR_ERR(rng->path);
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
rng->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(rng->base))
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
index bddd625ab91b..4fee0fc4b2e5 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
@@ -16,6 +16,7 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <linux/interconnect.h>
#include <linux/of_irq.h>
#include "msm_drv.h"
@@ -1050,6 +1051,19 @@ static const struct component_ops mdp5_ops = {
static int mdp5_dev_probe(struct platform_device *pdev)
{
+ struct icc_path *path0 = of_icc_get(&pdev->dev, "port0");
+ struct icc_path *path1 = of_icc_get(&pdev->dev, "port1");
+ struct icc_path *path_rot = of_icc_get(&pdev->dev, "rotator");
+
+ if (IS_ERR(path0))
+ return PTR_ERR(path0);
+ icc_set(path0, 0, 6400000);
+
+ if (!IS_ERR(path1))
+ icc_set(path1, 0, 6400000);
+ if (!IS_ERR(path_rot))
+ icc_set(path_rot, 0, 6400000);
+
DBG("");
return component_add(&pdev->dev, &mdp5_ops);
}
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 2b7c8946adba..711c52b7b537 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -90,6 +90,25 @@ static struct devfreq_dev_profile msm_devfreq_profile = {
.get_cur_freq = msm_devfreq_get_cur_freq,
};
+static int bs_init(struct msm_gpu *gpu)
+{
+ gpu->path = of_icc_get(&gpu->pdev->dev, "gfx");
+ if (IS_ERR(gpu->path))
+ return PTR_ERR(gpu->path);
+
+ return 0;
+}
+
+static void bs_set(struct msm_gpu *gpu, int idx)
+{
+ u32 peak_bw = 0;
+
+ if (idx > 0)
+ peak_bw = 14432000;
+
+ icc_set(gpu->path, 0, peak_bw);
+}
+
static void msm_devfreq_init(struct msm_gpu *gpu)
{
/* We need target support to do devfreq */
@@ -181,6 +200,7 @@ static int enable_axi(struct msm_gpu *gpu)
{
if (gpu->ebi1_clk)
clk_prepare_enable(gpu->ebi1_clk);
+ bs_set(gpu, 1);
return 0;
}
@@ -188,6 +208,7 @@ static int disable_axi(struct msm_gpu *gpu)
{
if (gpu->ebi1_clk)
clk_disable_unprepare(gpu->ebi1_clk);
+ bs_set(gpu, 0);
return 0;
}
@@ -850,6 +871,7 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
gpu->num_perfcntrs = ARRAY_SIZE(gpu->last_cntrs);
gpu->dev = drm;
+ gpu->pdev = pdev;
gpu->funcs = funcs;
gpu->name = name;
@@ -889,6 +911,10 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
if (ret)
goto fail;
+ ret = bs_init(gpu);
+ if (ret)
+ goto fail;
+
gpu->ebi1_clk = msm_clk_get(pdev, "bus");
DBG("ebi1_clk: %p", gpu->ebi1_clk);
if (IS_ERR(gpu->ebi1_clk))
@@ -905,7 +931,6 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
if (IS_ERR(gpu->gpu_cx))
gpu->gpu_cx = NULL;
- gpu->pdev = pdev;
platform_set_drvdata(pdev, gpu);
msm_devfreq_init(gpu);
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index f82bac086666..7b48bd6f1874 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -20,6 +20,7 @@
#include <linux/clk.h>
#include <linux/regulator/consumer.h>
+#include <linux/interconnect.h>
#include "msm_drv.h"
#include "msm_fence.h"
@@ -118,6 +119,7 @@ struct msm_gpu {
int nr_clocks;
struct clk *ebi1_clk, *core_clk, *rbbmtimer_clk;
uint32_t fast_rate;
+ struct icc_path *path;
/* Hang and Inactivity Detection:
*/
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index f2c681971201..ec78a46fd128 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -858,6 +858,7 @@ config I2C_QCOM_GENI
config I2C_QUP
tristate "Qualcomm QUP based I2C controller"
depends on ARCH_QCOM
+ depends on INTERCONNECT || !INTERCONNECT
help
If you say yes to this option, support will be included for the
built-in I2C interface on the Qualcomm SoCs.
diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index e09cd0775ae9..8f6f73ee8138 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>
@@ -280,6 +281,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)
@@ -1654,6 +1660,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(qup->path, 0, kbps_to_icc(qup->clk_freq));
+}
+
+static void qup_i2c_disable_icc(struct qup_i2c_dev *qup)
+{
+ icc_set(qup->path, 0, 0);
+}
+
static const struct acpi_device_id qup_i2c_acpi_match[] = {
{ "QCOM8010"},
{ },
@@ -1782,6 +1798,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");
@@ -1793,6 +1813,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);
}
@@ -1925,6 +1947,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);
@@ -1937,6 +1960,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;
}
@@ -1946,6 +1970,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;
}
diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c
index bb6add9d340e..3f6aad6c5711 100644
--- a/drivers/media/platform/qcom/venus/core.c
+++ b/drivers/media/platform/qcom/venus/core.c
@@ -14,6 +14,7 @@
*/
#include <linux/clk.h>
#include <linux/init.h>
+#include <linux/interconnect.h>
#include <linux/ioctl.h>
#include <linux/list.h>
#include <linux/module.h>
@@ -248,6 +249,10 @@ static int venus_probe(struct platform_device *pdev)
if (IS_ERR(core->base))
return PTR_ERR(core->base);
+ core->video_path = of_icc_get(dev, "video");
+ if (IS_ERR(core->video_path))
+ return PTR_ERR(core->video_path);
+
core->irq = platform_get_irq(pdev, 0);
if (core->irq < 0)
return core->irq;
@@ -350,6 +355,8 @@ static int venus_remove(struct platform_device *pdev)
pm_runtime_put_sync(dev);
pm_runtime_disable(dev);
+ icc_put(core->video_path);
+
v4l2_device_unregister(&core->v4l2_dev);
return ret;
@@ -399,6 +406,22 @@ static const struct freq_tbl msm8916_freq_table[] = {
{ 108000, 100000000 }, /* 1280x720 @ 30 */
};
+static const struct bw_tbl msm8916_bw_table_enc[] = {
+ { 244800, 908600, 1537600, 0, 0 },
+ { 216000, 908600, 1537600, 0, 0 },
+ { 108000, 400900, 1079000, 0, 0 },
+ { 72000, 400900, 1079000, 0, 0 },
+ { 36000, 133600, 674400, 0, 0 },
+};
+
+static const struct bw_tbl msm8916_bw_table_dec[] = {
+ { 244800, 677600, 1331000, 0, 0 },
+ { 216000, 677600, 1331000, 0, 0 },
+ { 108000, 298900, 831900, 0, 0 },
+ { 72000, 298900, 831900, 0, 0 },
+ { 36000, 99600, 831900, 0, 0 },
+};
+
static const struct reg_val msm8916_reg_preset[] = {
{ 0xe0020, 0x05555556 },
{ 0xe0024, 0x05555556 },
@@ -408,6 +431,10 @@ static const struct reg_val msm8916_reg_preset[] = {
static const struct venus_resources msm8916_res = {
.freq_tbl = msm8916_freq_table,
.freq_tbl_size = ARRAY_SIZE(msm8916_freq_table),
+ .bw_tbl_enc = msm8916_bw_table_enc,
+ .bw_tbl_enc_size = ARRAY_SIZE(msm8916_bw_table_enc),
+ .bw_tbl_dec = msm8916_bw_table_dec,
+ .bw_tbl_dec_size = ARRAY_SIZE(msm8916_bw_table_dec),
.reg_tbl = msm8916_reg_preset,
.reg_tbl_size = ARRAY_SIZE(msm8916_reg_preset),
.clks = { "core", "iface", "bus", },
@@ -451,18 +478,38 @@ static const struct venus_resources msm8996_res = {
};
static const struct freq_tbl sdm845_freq_table[] = {
- { 1944000, 380000000 }, /* 4k UHD @ 60 */
- { 972000, 320000000 }, /* 4k UHD @ 30 */
- { 489600, 200000000 }, /* 1080p @ 60 */
- { 244800, 100000000 }, /* 1080p @ 30 */
+ { 3110400, 533000000 }, /* 4096x2160@90 */
+ { 2073600, 444000000 }, /* 4096x2160@60 */
+ { 1944000, 404000000 }, /* 3840x2160@60 */
+ { 972000, 330000000 }, /* 3840x2160@30 */
+ { 489600, 200000000 }, /* 1920x1080@60 */
+ { 244800, 100000000 }, /* 1920x1080@30 */
+};
+
+static const struct bw_tbl sdm845_bw_table_enc[] = {
+ { 1944000, 1612000, 0, 2416000, 0 }, /* 3840x2160@60 h264*/
+ { 972000, 951000, 0, 1434000, 0 }, /* 3840x2160@30 h264*/
+ { 489600, 723000, 0, 973000, 0 }, /* 1920x1080@60 h264 */
+ { 244800, 370000, 0, 495000, 0 }, /* 1920x1080@30 h264 */
+};
+
+static const struct bw_tbl sdm845_bw_table_dec[] = {
+ { 2073600, 3929000, 0, 5551000, 0 }, /* 4096x2160@60 h264 */
+ { 1036800, 1987000, 0, 2797000, 0 }, /* 4096x2160@30 h264 */
+ { 489600, 1040000, 0, 1298000, 0 }, /* 1920x1080@60 h264 */
+ { 244800, 530000, 0, 659000, 0 }, /* 1920x1080@30 h264 */
};
static const struct venus_resources sdm845_res = {
.freq_tbl = sdm845_freq_table,
.freq_tbl_size = ARRAY_SIZE(sdm845_freq_table),
+ .bw_tbl_enc = sdm845_bw_table_enc,
+ .bw_tbl_enc_size = ARRAY_SIZE(sdm845_bw_table_enc),
+ .bw_tbl_dec = sdm845_bw_table_dec,
+ .bw_tbl_dec_size = ARRAY_SIZE(sdm845_bw_table_dec),
.clks = {"core", "iface", "bus" },
.clks_num = 3,
- .max_load = 2563200,
+ .max_load = 3110400, /* 4096x2160@90 */
.hfi_version = HFI_VERSION_4XX,
.vmem_id = VIDC_RESOURCE_NONE,
.vmem_size = 0,
diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h
index 2f02365f4818..2ce3d7a60c86 100644
--- a/drivers/media/platform/qcom/venus/core.h
+++ b/drivers/media/platform/qcom/venus/core.h
@@ -30,6 +30,14 @@ struct freq_tbl {
unsigned long freq;
};
+struct bw_tbl {
+ u32 mbs_per_sec;
+ u32 avg;
+ u32 peak;
+ u32 avg_10bit;
+ u32 peak_10bit;
+};
+
struct reg_val {
u32 reg;
u32 value;
@@ -39,6 +47,10 @@ struct venus_resources {
u64 dma_mask;
const struct freq_tbl *freq_tbl;
unsigned int freq_tbl_size;
+ const struct bw_tbl *bw_tbl_enc;
+ unsigned int bw_tbl_enc_size;
+ const struct bw_tbl *bw_tbl_dec;
+ unsigned int bw_tbl_dec_size;
const struct reg_val *reg_tbl;
unsigned int reg_tbl_size;
const char * const clks[VIDC_CLKS_NUM_MAX];
@@ -122,6 +134,7 @@ struct venus_core {
struct clk *core1_clk;
struct clk *core0_bus_clk;
struct clk *core1_bus_clk;
+ struct icc_path *video_path;
struct video_device *vdev_dec;
struct video_device *vdev_enc;
struct v4l2_device v4l2_dev;
diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c
index e436385bc5ab..ab66686b340a 100644
--- a/drivers/media/platform/qcom/venus/helpers.c
+++ b/drivers/media/platform/qcom/venus/helpers.c
@@ -14,6 +14,7 @@
*/
#include <linux/clk.h>
#include <linux/iopoll.h>
+#include <linux/interconnect.h>
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/pm_runtime.h>
@@ -348,6 +349,67 @@ static u32 load_per_type(struct venus_core *core, u32 session_type)
return mbs_per_sec;
}
+static void mbs_to_bw(struct venus_inst *inst, u32 mbs, u32 *avg, u32 *peak)
+{
+ const struct venus_resources *res = inst->core->res;
+ const struct bw_tbl *bw_tbl;
+ unsigned int num_rows, i;
+
+ *avg = 0;
+ *peak = 0;
+
+ if (mbs == 0)
+ return;
+
+ if (inst->session_type == VIDC_SESSION_TYPE_ENC) {
+ num_rows = res->bw_tbl_enc_size;
+ bw_tbl = res->bw_tbl_enc;
+ } else if (inst->session_type == VIDC_SESSION_TYPE_DEC) {
+ num_rows = res->bw_tbl_dec_size;
+ bw_tbl = res->bw_tbl_dec;
+ } else {
+ return;
+ }
+
+ if (!bw_tbl || num_rows == 0)
+ return;
+
+ for (i = 0; i < num_rows; i++) {
+ if (mbs > bw_tbl[i].mbs_per_sec)
+ break;
+
+ if (inst->dpb_fmt & HFI_COLOR_FORMAT_10_BIT_BASE) {
+ *avg = bw_tbl[i].avg_10bit;
+ *peak = bw_tbl[i].peak_10bit;
+ } else {
+ *avg = bw_tbl[i].avg;
+ *peak = bw_tbl[i].peak;
+ }
+ }
+}
+
+static int load_scale_bw(struct venus_core *core)
+{
+ struct venus_inst *inst = NULL;
+ u32 mbs_per_sec, avg, peak, total_avg = 0, total_peak = 0;
+
+ mutex_lock(&core->lock);
+ list_for_each_entry(inst, &core->instances, list) {
+ mbs_per_sec = load_per_instance(inst);
+ dev_dbg(core->dev, "mbs_per_sec:%u, fps:%llu\n", mbs_per_sec,
+ inst->fps);
+ mbs_to_bw(inst, mbs_per_sec, &avg, &peak);
+ total_avg += avg;
+ total_peak += peak;
+ }
+ mutex_unlock(&core->lock);
+
+ dev_dbg(core->dev, "total: avg_bw: %u, peak_bw: %u\n",
+ total_avg, total_peak);
+
+ return icc_set(core->video_path, total_avg, total_peak);
+}
+
static int load_scale_clocks(struct venus_core *core)
{
const struct freq_tbl *table = core->res->freq_tbl;
@@ -391,6 +453,8 @@ set_freq:
if (ret)
goto err;
+ load_scale_bw(core);
+
return 0;
err:
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 1b58739d9744..b0ad37ba4f30 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -464,6 +464,7 @@ config MMC_SDHCI_MSM
tristate "Qualcomm SDHCI Controller Support"
depends on ARCH_QCOM || (ARM && COMPILE_TEST)
depends on MMC_SDHCI_PLTFM
+ depends on INTERCONNECT || !INTERCONNECT
select MMC_SDHCI_IO_ACCESSORS
help
This selects the Secure Digital Host Controller Interface (SDHCI)
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 3cc8bfee6c18..c31e88b33fdb 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -20,6 +20,7 @@
#include <linux/mmc/mmc.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
+#include <linux/interconnect.h>
#include <linux/iopoll.h>
#include <linux/regulator/consumer.h>
@@ -258,6 +259,7 @@ struct sdhci_msm_host {
bool mci_removed;
const struct sdhci_msm_variant_ops *var_ops;
const struct sdhci_msm_offset *offset;
+ struct icc_path *path;
};
static const struct sdhci_msm_offset *sdhci_priv_msm_offset(struct sdhci_host *host)
@@ -1627,6 +1629,33 @@ static const struct sdhci_msm_variant_info sdhci_msm_v5_var = {
.offset = &sdhci_msm_v5_offset,
};
+static int sdhci_msm_icc_enable(struct sdhci_msm_host *msm_host, bool enable)
+{
+ struct sdhci_host *host = dev_get_drvdata(&msm_host->pdev->dev);
+ struct mmc_host *mmc = host->mmc;
+ struct mmc_ios *ios = &mmc->ios;
+ unsigned char bus_width = 1 << ios->bus_width;
+ u32 bw;
+
+ if (!enable)
+ return icc_set(msm_host->path, 0, 0);
+
+ /* calculate the needed bandwidth */
+ bw = host->clock;
+
+ if (host->timing == MMC_TIMING_UHS_DDR50 ||
+ host->timing == MMC_TIMING_MMC_DDR52) {
+ bw *= 2;
+ }
+
+ if (bus_width == 4)
+ bw /= 2;
+ else if (bus_width == 1)
+ bw /= 8;
+
+ return icc_set(msm_host->path, 0, Bps_to_icc(bw));
+}
+
static const struct of_device_id sdhci_msm_dt_match[] = {
{.compatible = "qcom,sdhci-msm-v4", .data = &sdhci_msm_mci_var},
{.compatible = "qcom,sdhci-msm-v5", .data = &sdhci_msm_v5_var},
@@ -1698,16 +1727,22 @@ static int sdhci_msm_probe(struct platform_device *pdev)
msm_host->saved_tuning_phase = INVALID_TUNING_PHASE;
+ msm_host->path = of_icc_get(&pdev->dev, "sdhc-mem");
+ if (IS_ERR(msm_host->path)) {
+ ret = PTR_ERR(msm_host->path);
+ goto pltfm_free;
+ }
+
/* Setup SDCC bus voter clock. */
msm_host->bus_clk = devm_clk_get(&pdev->dev, "bus");
if (!IS_ERR(msm_host->bus_clk)) {
/* Vote for max. clk rate for max. performance */
ret = clk_set_rate(msm_host->bus_clk, INT_MAX);
if (ret)
- goto pltfm_free;
+ goto icc_disable;
ret = clk_prepare_enable(msm_host->bus_clk);
if (ret)
- goto pltfm_free;
+ goto icc_disable;
}
/* Setup main peripheral bus clock */
@@ -1883,6 +1918,8 @@ clk_disable:
bus_clk_disable:
if (!IS_ERR(msm_host->bus_clk))
clk_disable_unprepare(msm_host->bus_clk);
+icc_disable:
+ icc_put(msm_host->path);
pltfm_free:
sdhci_pltfm_free(pdev);
return ret;
@@ -1902,6 +1939,7 @@ static int sdhci_msm_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
+ icc_put(msm_host->path);
clk_bulk_disable_unprepare(ARRAY_SIZE(msm_host->bulk_clks),
msm_host->bulk_clks);
if (!IS_ERR(msm_host->bus_clk))
@@ -1917,6 +1955,7 @@ static int sdhci_msm_runtime_suspend(struct device *dev)
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+ sdhci_msm_icc_enable(msm_host, false);
clk_bulk_disable_unprepare(ARRAY_SIZE(msm_host->bulk_clks),
msm_host->bulk_clks);
@@ -1929,6 +1968,7 @@ static int sdhci_msm_runtime_resume(struct device *dev)
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+ sdhci_msm_icc_enable(msm_host, true);
return clk_bulk_prepare_enable(ARRAY_SIZE(msm_host->bulk_clks),
msm_host->bulk_clks);
}
diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig
index 91b0194240a5..dd333d26f30d 100644
--- a/drivers/pci/controller/dwc/Kconfig
+++ b/drivers/pci/controller/dwc/Kconfig
@@ -136,6 +136,7 @@ config PCIE_QCOM
bool "Qualcomm PCIe controller"
depends on OF && (ARCH_QCOM || COMPILE_TEST)
depends on PCI_MSI_IRQ_DOMAIN
+ depends on INTERCONNECT != m
select PCIE_DW_HOST
help
Say Y here to enable PCIe controller support on Qualcomm SoCs. The
diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c
index d185ea5fe996..e21ea1a2f6d3 100644
--- a/drivers/pci/controller/dwc/pcie-qcom.c
+++ b/drivers/pci/controller/dwc/pcie-qcom.c
@@ -11,6 +11,7 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
+#include <linux/interconnect.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/iopoll.h>
@@ -110,6 +111,7 @@ struct qcom_pcie_resources_2_3_2 {
struct clk *cfg_clk;
struct clk *pipe_clk;
struct regulator_bulk_data supplies[QCOM_PCIE_2_3_2_MAX_SUPPLY];
+ struct icc_path *path;
};
struct qcom_pcie_resources_2_4_0 {
@@ -504,6 +506,10 @@ static int qcom_pcie_get_resources_2_3_2(struct qcom_pcie *pcie)
if (ret)
return ret;
+ res->path = of_icc_get(dev, "pcie-mem");
+ if (IS_ERR(res->path))
+ return PTR_ERR(res->path);
+
res->aux_clk = devm_clk_get(dev, "aux");
if (IS_ERR(res->aux_clk))
return PTR_ERR(res->aux_clk);
@@ -534,6 +540,7 @@ static void qcom_pcie_deinit_2_3_2(struct qcom_pcie *pcie)
clk_disable_unprepare(res->aux_clk);
regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies);
+ icc_put(res->path);
}
static void qcom_pcie_post_deinit_2_3_2(struct qcom_pcie *pcie)
@@ -581,6 +588,8 @@ static int qcom_pcie_init_2_3_2(struct qcom_pcie *pcie)
goto err_slave_clk;
}
+ icc_set(res->path, 500, 800);
+
/* enable PCIe clocks and resets */
val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL);
val &= ~BIT(0);
diff --git a/drivers/phy/qualcomm/Kconfig b/drivers/phy/qualcomm/Kconfig
index 32f7d34eb784..fcbdbc851cc9 100644
--- a/drivers/phy/qualcomm/Kconfig
+++ b/drivers/phy/qualcomm/Kconfig
@@ -71,6 +71,7 @@ config PHY_QCOM_USB_HS
tristate "Qualcomm USB HS PHY module"
depends on USB_ULPI_BUS
depends on EXTCON || !EXTCON # if EXTCON=m, this cannot be built-in
+ depends on INTERCONNECT || !INTERCONNECT
select GENERIC_PHY
help
Support for the USB high-speed ULPI compliant phy on Qualcomm
diff --git a/drivers/phy/qualcomm/phy-qcom-usb-hs.c b/drivers/phy/qualcomm/phy-qcom-usb-hs.c
index abbbe75070da..39d85f3a1bcf 100644
--- a/drivers/phy/qualcomm/phy-qcom-usb-hs.c
+++ b/drivers/phy/qualcomm/phy-qcom-usb-hs.c
@@ -15,6 +15,7 @@
#include <linux/reset.h>
#include <linux/extcon.h>
#include <linux/notifier.h>
+#include <linux/interconnect.h>
#define ULPI_PWR_CLK_MNG_REG 0x88
# define ULPI_PWR_OTG_COMP_DISABLE BIT(0)
@@ -39,6 +40,7 @@ struct qcom_usb_hs_phy {
struct reset_control *reset;
struct ulpi_seq *init_seq;
struct extcon_dev *vbus_edev;
+ struct icc_path *path;
struct notifier_block vbus_notify;
};
@@ -155,6 +157,8 @@ static int qcom_usb_hs_phy_power_on(struct phy *phy)
goto err_ulpi;
}
+ icc_set(uphy->path, MBps_to_icc(80), MBps_to_icc(6));
+
if (uphy->vbus_edev) {
state = extcon_get_state(uphy->vbus_edev, EXTCON_USB);
/* setup initial state */
@@ -182,6 +186,8 @@ static int qcom_usb_hs_phy_power_off(struct phy *phy)
{
struct qcom_usb_hs_phy *uphy = phy_get_drvdata(phy);
+ icc_set(uphy->path, 0, 0);
+
regulator_disable(uphy->v3p3);
regulator_disable(uphy->v1p8);
clk_disable_unprepare(uphy->sleep_clk);
@@ -250,6 +256,10 @@ static int qcom_usb_hs_phy_probe(struct ulpi *ulpi)
uphy->reset = NULL;
}
+ uphy->path = of_icc_get(&ulpi->dev, "usb-mem");
+ if (IS_ERR(uphy->path))
+ return PTR_ERR(uphy->path);
+
uphy->phy = devm_phy_create(&ulpi->dev, ulpi->dev.of_node,
&qcom_usb_hs_phy_ops);
if (IS_ERR(uphy->phy))
diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
index 2ddd426323e9..7dea8a6347b0 100644
--- a/drivers/scsi/ufs/Kconfig
+++ b/drivers/scsi/ufs/Kconfig
@@ -91,6 +91,7 @@ config SCSI_UFS_DWC_TC_PLATFORM
config SCSI_UFS_QCOM
tristate "QCOM specific hooks to UFS controller platform driver"
depends on SCSI_UFSHCD_PLATFORM && ARCH_QCOM
+ depends on INTERCONNECT || !INTERCONNECT
select PHY_QCOM_UFS
help
This selects the QCOM specific additions to UFSHCD platform driver.
diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 14237d234280..4e3d1c2b67dc 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -12,6 +12,7 @@
*
*/
+#include <linux/interconnect.h>
#include <linux/time.h>
#include <linux/of.h>
#include <linux/platform_device.h>
@@ -877,6 +878,7 @@ static int ufs_qcom_bus_register(struct ufs_qcom_host *host)
}
#endif /* CONFIG_MSM_BUS_SCALING */
+
static void ufs_qcom_dev_ref_clk_ctrl(struct ufs_qcom_host *host, bool enable)
{
if (host->dev_ref_clk_ctrl_mmio &&
@@ -1652,6 +1654,17 @@ static int ufs_qcom_probe(struct platform_device *pdev)
{
int err;
struct device *dev = &pdev->dev;
+ struct icc_path *path = of_icc_get(dev, "ddr");
+ struct icc_path *path_cfg = of_icc_get(dev, "cfg");
+
+ if (IS_ERR(path))
+ return PTR_ERR(path);
+
+ if (IS_ERR(path_cfg))
+ return PTR_ERR(path_cfg);
+
+ icc_set(path, 4096000, 0);
+ icc_set(path_cfg, 1000, 0);
/* Perform generic probe */
err = ufshcd_pltfrm_init(pdev, &ufs_hba_qcom_vops);