diff options
author | Linaro CI <ci_notify@linaro.org> | 2018-12-10 00:22:06 +0000 |
---|---|---|
committer | Linaro CI <ci_notify@linaro.org> | 2018-12-10 00:22:06 +0000 |
commit | 326fab9ca08c222f3f7e7ab3e8bb614e40616f95 (patch) | |
tree | da36e02a735ab6432e388a723485cb2f292cd709 | |
parent | 3e8b95aa84367a867377f34e6f9cb787eeedbe41 (diff) | |
parent | 026de00a26ccdde3debde4737269fc2dde0f4d83 (diff) |
Merge remote-tracking branch 'bus-scaling-consumers/bus-scaling-consumers' into integration-linux-qcomlt
-rw-r--r-- | arch/arm64/boot/dts/qcom/msm8916.dtsi | 21 | ||||
-rw-r--r-- | arch/arm64/boot/dts/qcom/msm8996.dtsi | 21 | ||||
-rw-r--r-- | drivers/crypto/Kconfig | 1 | ||||
-rw-r--r-- | drivers/crypto/qcom-rng.c | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 14 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_gpu.c | 27 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_gpu.h | 2 | ||||
-rw-r--r-- | drivers/i2c/busses/Kconfig | 1 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-qup.c | 25 | ||||
-rw-r--r-- | drivers/media/platform/qcom/venus/core.c | 57 | ||||
-rw-r--r-- | drivers/media/platform/qcom/venus/core.h | 13 | ||||
-rw-r--r-- | drivers/media/platform/qcom/venus/helpers.c | 64 | ||||
-rw-r--r-- | drivers/mmc/host/Kconfig | 1 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-msm.c | 44 | ||||
-rw-r--r-- | drivers/pci/controller/dwc/Kconfig | 1 | ||||
-rw-r--r-- | drivers/pci/controller/dwc/pcie-qcom.c | 9 | ||||
-rw-r--r-- | drivers/phy/qualcomm/Kconfig | 1 | ||||
-rw-r--r-- | drivers/phy/qualcomm/phy-qcom-usb-hs.c | 10 | ||||
-rw-r--r-- | drivers/scsi/ufs/Kconfig | 1 | ||||
-rw-r--r-- | drivers/scsi/ufs/ufs-qcom.c | 13 |
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); |