summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/display/msm/sde.txt26
-rw-r--r--Documentation/devicetree/bindings/fb/adv7533.txt3
-rw-r--r--arch/arm/boot/dts/qcom/msm8996.dtsi1
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-mdss-panels.dtsi26
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-sde.dtsi7
-rw-r--r--arch/arm/boot/dts/qcom/sda660-pm660a-qrd-hdk.dts11
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi16
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-regulator.dtsi8
-rw-r--r--arch/arm64/configs/msmcortex-perf_defconfig1
-rw-r--r--arch/arm64/configs/msmcortex_defconfig1
-rw-r--r--drivers/char/adsprpc.c5
-rw-r--r--drivers/char/diag/diagfwd_glink.h2
-rw-r--r--drivers/clk/qcom/Makefile1
-rw-r--r--drivers/clk/qcom/clk-regmap-mux-div.c255
-rw-r--r--drivers/clk/qcom/clk-regmap-mux-div.h65
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c2
-rw-r--r--drivers/gpu/drm/msm/msm_mmu.h4
-rw-r--r--drivers/gpu/drm/msm/msm_smmu.c14
-rw-r--r--drivers/gpu/msm/kgsl_pwrctrl.c110
-rw-r--r--drivers/misc/qseecom.c24
-rw-r--r--drivers/soc/qcom/icnss_utils.c14
-rw-r--r--drivers/usb/gadget/configfs.c46
-rw-r--r--drivers/usb/pd/policy_engine.c6
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi.c3
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi_host.c7
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_overlay.c5
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_pp.h4
-rw-r--r--drivers/video/fbdev/msm/msm_dba/adv7533.c16
-rw-r--r--include/soc/qcom/icnss.h2
-rw-r--r--include/soc/qcom/minidump.h5
-rw-r--r--sound/soc/codecs/sdm660_cdc/msm-analog-cdc.c93
-rw-r--r--sound/soc/codecs/sdm660_cdc/msm-analog-cdc.h3
32 files changed, 702 insertions, 84 deletions
diff --git a/Documentation/devicetree/bindings/display/msm/sde.txt b/Documentation/devicetree/bindings/display/msm/sde.txt
index c9e7d7423d7f..e14acdc6303e 100644
--- a/Documentation/devicetree/bindings/display/msm/sde.txt
+++ b/Documentation/devicetree/bindings/display/msm/sde.txt
@@ -264,6 +264,22 @@ Bus Scaling Data:
* Current values of src & dst are defined at
include/linux/msm-bus-board.h
+SMMU Subnodes:
+- smmu_sde_****: Child nodes representing sde smmu virtual
+ devices
+
+Subnode properties:
+- compatible: Compatible names used for smmu devices.
+ names should be:
+ "qcom,smmu_sde_unsec": smmu context bank device
+ for unsecure sde real time domain.
+ "qcom,smmu_sde_sec": smmu context bank device
+ for secure sde real time domain.
+ "qcom,smmu_sde_nrt_unsec": smmu context bank device
+ for unsecure sde non-real time domain.
+ "qcom,smmu_sde_nrt_sec": smmu context bank device
+ for secure sde non-real time domain.
+
Please refer to ../../interrupt-controller/interrupts.txt for a general
description of interrupt bindings.
@@ -469,4 +485,14 @@ Example:
<1 590 0 160000>,
<1 590 0 320000>;
};
+
+ smmu_kms_unsec: qcom,smmu_kms_unsec_cb {
+ compatible = "qcom,smmu_sde_unsec";
+ iommus = <&mmss_smmu 0>;
+ };
+
+ smmu_kms_sec: qcom,smmu_kms_sec_cb {
+ compatible = "qcom,smmu_sde_sec";
+ iommus = <&mmss_smmu 1>;
+ };
};
diff --git a/Documentation/devicetree/bindings/fb/adv7533.txt b/Documentation/devicetree/bindings/fb/adv7533.txt
index 8b85fcd730cb..b198f37f8fc6 100644
--- a/Documentation/devicetree/bindings/fb/adv7533.txt
+++ b/Documentation/devicetree/bindings/fb/adv7533.txt
@@ -23,6 +23,8 @@ Optional properties:
- qcom,max-voltage-level Maximum voltage level to be supplied to bridge chip
- qcom,enable-load Load current to bridge chip when enabled
- qcom,disable-load Load current to bridge chip when disabled
+- qcom,post-on-sleep Sleep time (ms) to indicate the sleep
+ time after the vreg is enabled
Example:
&soc {
@@ -46,6 +48,7 @@ Example:
qcom,max-voltage-level = <0>;
qcom,enable-load = <0>;
qcom,disable-load = <0>;
+ qcom,post-on-sleep = <10>;
};
};
};
diff --git a/arch/arm/boot/dts/qcom/msm8996.dtsi b/arch/arm/boot/dts/qcom/msm8996.dtsi
index ee069f5d8bdf..7c3f035a841b 100644
--- a/arch/arm/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996.dtsi
@@ -1737,6 +1737,7 @@
mhi: qcom,mhi {
compatible = "qcom,mhi";
+ status = "disabled";
};
qcom,ipc-spinlock@740000 {
diff --git a/arch/arm/boot/dts/qcom/msm8998-mdss-panels.dtsi b/arch/arm/boot/dts/qcom/msm8998-mdss-panels.dtsi
index b53ff87d5092..93b6a7664ed8 100644
--- a/arch/arm/boot/dts/qcom/msm8998-mdss-panels.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8998-mdss-panels.dtsi
@@ -83,25 +83,39 @@
};
&dsi_dual_nt35597_video {
- qcom,mdss-dsi-panel-timings = [00 1c 08 07 23 22 07 07 05 03 04 00];
- qcom,mdss-dsi-t-clk-post = <0x0d>;
- qcom,mdss-dsi-t-clk-pre = <0x2d>;
+ qcom,mdss-dsi-panel-timings = [00 1a 04 06 0a 0a 05 06 05 03 04 00];
+ qcom,mdss-dsi-t-clk-post = <0x07>;
+ qcom,mdss-dsi-t-clk-pre = <0x25>;
+ qcom,mdss-dsi-tx-eot-append;
qcom,cmd-sync-wait-broadcast;
qcom,esd-check-enabled;
- qcom,mdss-dsi-panel-status-check-mode = "bta_check";
qcom,mdss-dsi-min-refresh-rate = <55>;
qcom,mdss-dsi-max-refresh-rate = <60>;
qcom,mdss-dsi-pan-enable-dynamic-fps;
qcom,mdss-dsi-pan-fps-update = "dfps_immediate_porch_mode_vfp";
+ qcom,mdss-dsi-panel-status-check-mode = "reg_read";
+ qcom,mdss-dsi-panel-status-command = [06 01 00 01 00 00 01 0a];
+ qcom,mdss-dsi-panel-status-command-state = "dsi_hs_mode";
+ qcom,mdss-dsi-panel-status-value = <0x9c>;
+ qcom,mdss-dsi-panel-on-check-value = <0x9c>;
+ qcom,mdss-dsi-panel-status-read-length = <1>;
+ qcom,mdss-dsi-panel-max-error-count = <3>;
};
&dsi_dual_nt35597_cmd {
qcom,mdss-dsi-panel-timings = [00 1c 08 07 23 22 07 07 05 03 04 00];
qcom,mdss-dsi-t-clk-post = <0x0d>;
qcom,mdss-dsi-t-clk-pre = <0x2d>;
+ qcom,mdss-dsi-tx-eot-append;
qcom,cmd-sync-wait-broadcast;
qcom,esd-check-enabled;
- qcom,mdss-dsi-panel-status-check-mode = "bta_check";
+ qcom,mdss-dsi-panel-status-check-mode = "reg_read";
+ qcom,mdss-dsi-panel-status-command = [06 01 00 01 00 00 01 0a];
+ qcom,mdss-dsi-panel-status-command-state = "dsi_hs_mode";
+ qcom,mdss-dsi-panel-status-value = <0x9c>;
+ qcom,mdss-dsi-panel-on-check-value = <0x9c>;
+ qcom,mdss-dsi-panel-status-read-length = <1>;
+ qcom,mdss-dsi-panel-max-error-count = <3>;
};
&dsi_dual_nt35597_truly_video {
@@ -120,6 +134,7 @@
qcom,mdss-dsi-panel-timings = [00 11 04 04 07 0c 04 04 03 03 04 00];
qcom,mdss-dsi-t-clk-post = <0x05>;
qcom,mdss-dsi-t-clk-pre = <0x1b>;
+ qcom,mdss-dsi-tx-eot-append;
qcom,esd-check-enabled;
qcom,mdss-dsi-panel-status-check-mode = "reg_read";
qcom,mdss-dsi-panel-status-command = [06 01 00 01 00 00 01 0a];
@@ -138,6 +153,7 @@
qcom,mdss-dsi-panel-timings = [00 11 04 04 07 0c 04 04 03 03 04 00];
qcom,mdss-dsi-t-clk-post = <0x05>;
qcom,mdss-dsi-t-clk-pre = <0x1b>;
+ qcom,mdss-dsi-tx-eot-append;
qcom,esd-check-enabled;
qcom,mdss-dsi-panel-status-check-mode = "reg_read";
qcom,mdss-dsi-panel-status-command = [06 01 00 01 00 00 01 0a];
diff --git a/arch/arm/boot/dts/qcom/msm8998-sde.dtsi b/arch/arm/boot/dts/qcom/msm8998-sde.dtsi
index 795635d8d13d..354ac830e0fa 100644
--- a/arch/arm/boot/dts/qcom/msm8998-sde.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8998-sde.dtsi
@@ -139,10 +139,15 @@
};
smmu_kms_unsec: qcom,smmu_kms_unsec_cb {
- compatible = "qcom,smmu_mdp_unsec";
+ compatible = "qcom,smmu_sde_unsec";
iommus = <&mmss_smmu 0>;
};
+ smmu_kms_sec: qcom,smmu_kms_sec_cb {
+ compatible = "qcom,smmu_sde_sec";
+ iommus = <&mmss_smmu 1>;
+ };
+
/* data and reg bus scale settings */
qcom,sde-data-bus {
qcom,msm-bus,name = "mdss_sde";
diff --git a/arch/arm/boot/dts/qcom/sda660-pm660a-qrd-hdk.dts b/arch/arm/boot/dts/qcom/sda660-pm660a-qrd-hdk.dts
index 7be428693f83..7fb0c9d03825 100644
--- a/arch/arm/boot/dts/qcom/sda660-pm660a-qrd-hdk.dts
+++ b/arch/arm/boot/dts/qcom/sda660-pm660a-qrd-hdk.dts
@@ -208,3 +208,14 @@
"SpkrLeft IN", "SPK1 OUT";
qcom,msm-mbhc-hphl-swh = <0>;
};
+
+&usb2s {
+ status = "okay";
+};
+
+&qusb_phy0 {
+ reg = <0x0c012000 0x180>,
+ <0x00188018 0x4>;
+ reg-names = "qusb_phy_base",
+ "ref_clk_addr";
+};
diff --git a/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi b/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi
index 19862f02aa84..3ffd43bcda60 100644
--- a/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi
@@ -133,7 +133,13 @@
23 1e 07 08 05 03 04 a0
23 18 07 08 04 03 04 a0];
qcom,esd-check-enabled;
- qcom,mdss-dsi-panel-status-check-mode = "bta_check";
+ qcom,mdss-dsi-panel-status-check-mode = "reg_read";
+ qcom,mdss-dsi-panel-status-command = [06 01 00 01 00 00 01 0a];
+ qcom,mdss-dsi-panel-status-command-state = "dsi_hs_mode";
+ qcom,mdss-dsi-panel-status-value = <0x9c>;
+ qcom,mdss-dsi-panel-on-check-value = <0x9c>;
+ qcom,mdss-dsi-panel-status-read-length = <1>;
+ qcom,mdss-dsi-panel-max-error-count = <3>;
qcom,mdss-dsi-min-refresh-rate = <53>;
qcom,mdss-dsi-max-refresh-rate = <60>;
qcom,mdss-dsi-pan-enable-dynamic-fps;
@@ -190,7 +196,13 @@
qcom,mdss-dsi-pan-enable-dynamic-fps;
qcom,mdss-dsi-pan-fps-update = "dfps_immediate_porch_mode_vfp";
qcom,esd-check-enabled;
- qcom,mdss-dsi-panel-status-check-mode = "bta_check";
+ qcom,mdss-dsi-panel-status-check-mode = "reg_read";
+ qcom,mdss-dsi-panel-status-command = [06 01 00 01 00 00 01 0a];
+ qcom,mdss-dsi-panel-status-command-state = "dsi_hs_mode";
+ qcom,mdss-dsi-panel-status-value = <0x9c>;
+ qcom,mdss-dsi-panel-on-check-value = <0x9c>;
+ qcom,mdss-dsi-panel-status-read-length = <1>;
+ qcom,mdss-dsi-panel-max-error-count = <3>;
};
&dsi_nt35597_truly_dsc_cmd {
diff --git a/arch/arm/boot/dts/qcom/sdm660-regulator.dtsi b/arch/arm/boot/dts/qcom/sdm660-regulator.dtsi
index b701ecd562cd..66bea3050586 100644
--- a/arch/arm/boot/dts/qcom/sdm660-regulator.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-regulator.dtsi
@@ -453,6 +453,8 @@
pm660l_bob: regulator-bob {
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3600000>;
+ qcom,pwm-threshold-current = <2000000>;
+ qcom,init-bob-mode = <2>;
status = "okay";
};
@@ -462,6 +464,8 @@
qcom,set = <3>;
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3600000>;
+ qcom,pwm-threshold-current = <2000000>;
+ qcom,init-bob-mode = <2>;
qcom,use-pin-ctrl-voltage1;
};
@@ -471,6 +475,8 @@
qcom,set = <3>;
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3600000>;
+ qcom,pwm-threshold-current = <2000000>;
+ qcom,init-bob-mode = <2>;
qcom,use-pin-ctrl-voltage2;
};
@@ -480,6 +486,8 @@
qcom,set = <3>;
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3600000>;
+ qcom,pwm-threshold-current = <2000000>;
+ qcom,init-bob-mode = <2>;
qcom,use-pin-ctrl-voltage3;
};
};
diff --git a/arch/arm64/configs/msmcortex-perf_defconfig b/arch/arm64/configs/msmcortex-perf_defconfig
index 6f5be663140f..5adb7697cc3e 100644
--- a/arch/arm64/configs/msmcortex-perf_defconfig
+++ b/arch/arm64/configs/msmcortex-perf_defconfig
@@ -32,7 +32,6 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_RD_XZ is not set
# CONFIG_RD_LZO is not set
# CONFIG_RD_LZ4 is not set
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_AIO is not set
# CONFIG_MEMBARRIER is not set
diff --git a/arch/arm64/configs/msmcortex_defconfig b/arch/arm64/configs/msmcortex_defconfig
index f09a134a2fd5..124a342fc1a6 100644
--- a/arch/arm64/configs/msmcortex_defconfig
+++ b/arch/arm64/configs/msmcortex_defconfig
@@ -32,7 +32,6 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_RD_XZ is not set
# CONFIG_RD_LZO is not set
# CONFIG_RD_LZ4 is not set
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_AIO is not set
# CONFIG_MEMBARRIER is not set
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index 14c833691194..a7c21407a814 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -1686,6 +1686,9 @@ static int fastrpc_init_process(struct fastrpc_file *fl,
int namelen;
int pageslen;
} inbuf;
+
+ if (!init->filelen)
+ goto bail;
VERIFY(err, proc_name = kzalloc(init->filelen, GFP_KERNEL));
if (err)
goto bail;
@@ -1694,7 +1697,7 @@ static int fastrpc_init_process(struct fastrpc_file *fl,
if (err)
goto bail;
inbuf.pgid = current->tgid;
- inbuf.namelen = strlen(proc_name)+1;
+ inbuf.namelen = init->filelen;
inbuf.pageslen = 0;
if (!me->staticpd_flags) {
inbuf.pageslen = 1;
diff --git a/drivers/char/diag/diagfwd_glink.h b/drivers/char/diag/diagfwd_glink.h
index a84fa4edfca0..6cad44522ab6 100644
--- a/drivers/char/diag/diagfwd_glink.h
+++ b/drivers/char/diag/diagfwd_glink.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 4c18181c047c..d3e88f40bdfd 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -9,6 +9,7 @@ clk-qcom-y += clk-rcg2.o
clk-qcom-y += clk-branch.o
clk-qcom-y += clk-regmap-divider.o
clk-qcom-y += clk-regmap-mux.o
+clk-qcom-y += clk-regmap-mux-div.o
clk-qcom-$(CONFIG_KRAIT_CLOCKS) += clk-krait.o
clk-qcom-y += clk-hfpll.o
clk-qcom-y += reset.o clk-voter.o
diff --git a/drivers/clk/qcom/clk-regmap-mux-div.c b/drivers/clk/qcom/clk-regmap-mux-div.c
new file mode 100644
index 000000000000..9593aefb0bf6
--- /dev/null
+++ b/drivers/clk/qcom/clk-regmap-mux-div.c
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2015, Linaro Limited
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/regmap.h>
+
+#include "clk-regmap-mux-div.h"
+
+#define CMD_RCGR 0x0
+#define CMD_RCGR_UPDATE BIT(0)
+#define CMD_RCGR_DIRTY_CFG BIT(4)
+#define CMD_RCGR_ROOT_OFF BIT(31)
+#define CFG_RCGR 0x4
+
+#define to_clk_regmap_mux_div(_hw) \
+ container_of(to_clk_regmap(_hw), struct clk_regmap_mux_div, clkr)
+
+int __mux_div_set_src_div(struct clk_regmap_mux_div *md, u32 src, u32 div)
+{
+ int ret, count;
+ u32 val, mask;
+ const char *name = clk_hw_get_name(&md->clkr.hw);
+
+ val = (div << md->hid_shift) | (src << md->src_shift);
+ mask = ((BIT(md->hid_width) - 1) << md->hid_shift) |
+ ((BIT(md->src_width) - 1) << md->src_shift);
+
+ ret = regmap_update_bits(md->clkr.regmap, CFG_RCGR + md->reg_offset,
+ mask, val);
+ if (ret)
+ return ret;
+
+ ret = regmap_update_bits(md->clkr.regmap, CMD_RCGR + md->reg_offset,
+ CMD_RCGR_UPDATE, CMD_RCGR_UPDATE);
+ if (ret)
+ return ret;
+
+ /* Wait for update to take effect */
+ for (count = 500; count > 0; count--) {
+ ret = regmap_read(md->clkr.regmap, CMD_RCGR + md->reg_offset,
+ &val);
+ if (ret)
+ return ret;
+ if (!(val & CMD_RCGR_UPDATE))
+ return 0;
+ udelay(1);
+ }
+
+ pr_err("%s: RCG did not update its configuration", name);
+ return -EBUSY;
+}
+
+static void __mux_div_get_src_div(struct clk_regmap_mux_div *md, u32 *src,
+ u32 *div)
+{
+ u32 val, __div, __src;
+ const char *name = clk_hw_get_name(&md->clkr.hw);
+
+ regmap_read(md->clkr.regmap, CMD_RCGR + md->reg_offset, &val);
+
+ if (val & CMD_RCGR_DIRTY_CFG) {
+ pr_err("%s: RCG configuration is pending\n", name);
+ return;
+ }
+
+ regmap_read(md->clkr.regmap, CFG_RCGR + md->reg_offset, &val);
+ __src = (val >> md->src_shift);
+ __src &= BIT(md->src_width) - 1;
+ *src = __src;
+
+ __div = (val >> md->hid_shift);
+ __div &= BIT(md->hid_width) - 1;
+ *div = __div;
+}
+
+static int mux_div_enable(struct clk_hw *hw)
+{
+ struct clk_regmap_mux_div *md = to_clk_regmap_mux_div(hw);
+
+ return __mux_div_set_src_div(md, md->src, md->div);
+}
+
+static inline bool is_better_rate(unsigned long req, unsigned long best,
+ unsigned long new)
+{
+ return (req <= new && new < best) || (best < req && best < new);
+}
+
+static int mux_div_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ struct clk_regmap_mux_div *md = to_clk_regmap_mux_div(hw);
+ unsigned int i, div, max_div;
+ unsigned long actual_rate, best_rate = 0;
+ unsigned long req_rate = req->rate;
+
+ for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
+ struct clk_hw *parent = clk_hw_get_parent_by_index(hw, i);
+ unsigned long parent_rate = clk_hw_get_rate(parent);
+
+ max_div = BIT(md->hid_width) - 1;
+ for (div = 1; div < max_div; div++) {
+ parent_rate = mult_frac(req_rate, div, 2);
+ parent_rate = clk_hw_round_rate(parent, parent_rate);
+ actual_rate = mult_frac(parent_rate, 2, div);
+
+ if (is_better_rate(req_rate, best_rate, actual_rate)) {
+ best_rate = actual_rate;
+ req->rate = best_rate;
+ req->best_parent_rate = parent_rate;
+ req->best_parent_hw = parent;
+ }
+
+ if (actual_rate < req_rate || best_rate <= req_rate)
+ break;
+ }
+ }
+
+ if (!best_rate)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int __mux_div_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
+ unsigned long prate, u32 src)
+{
+ struct clk_regmap_mux_div *md = to_clk_regmap_mux_div(hw);
+ int ret;
+ u32 div, max_div, best_src = 0, best_div = 0;
+ unsigned int i;
+ unsigned long actual_rate, best_rate = 0;
+
+ for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
+ struct clk_hw *parent = clk_hw_get_parent_by_index(hw, i);
+ unsigned long parent_rate = clk_hw_get_rate(parent);
+
+ max_div = BIT(md->hid_width) - 1;
+ for (div = 1; div < max_div; div++) {
+ parent_rate = mult_frac(rate, div, 2);
+ parent_rate = clk_hw_round_rate(parent, parent_rate);
+ actual_rate = mult_frac(parent_rate, 2, div);
+
+ if (is_better_rate(rate, best_rate, actual_rate)) {
+ best_rate = actual_rate;
+ best_src = md->parent_map[i].cfg;
+ best_div = div - 1;
+ }
+
+ if (actual_rate < rate || best_rate <= rate)
+ break;
+ }
+ }
+
+ ret = __mux_div_set_src_div(md, best_src, best_div);
+ if (!ret) {
+ md->div = best_div;
+ md->src = best_src;
+ }
+
+ return ret;
+}
+
+static u8 mux_div_get_parent(struct clk_hw *hw)
+{
+ struct clk_regmap_mux_div *md = to_clk_regmap_mux_div(hw);
+ const char *name = clk_hw_get_name(hw);
+ u32 i, div, src = 0;
+
+ __mux_div_get_src_div(md, &src, &div);
+
+ for (i = 0; i < clk_hw_get_num_parents(hw); i++)
+ if (src == md->parent_map[i].cfg)
+ return i;
+
+ pr_err("%s: Can't find parent with src %d\n", name, src);
+ return 0;
+}
+
+static int mux_div_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct clk_regmap_mux_div *md = to_clk_regmap_mux_div(hw);
+
+ return __mux_div_set_src_div(md, md->parent_map[index].cfg, md->div);
+}
+
+static int mux_div_set_rate(struct clk_hw *hw,
+ unsigned long rate, unsigned long prate)
+{
+ struct clk_regmap_mux_div *md = to_clk_regmap_mux_div(hw);
+
+ return __mux_div_set_rate_and_parent(hw, rate, prate, md->src);
+}
+
+static int mux_div_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
+ unsigned long prate, u8 index)
+{
+ struct clk_regmap_mux_div *md = to_clk_regmap_mux_div(hw);
+
+ return __mux_div_set_rate_and_parent(hw, rate, prate,
+ md->parent_map[index].cfg);
+}
+
+static unsigned long mux_div_recalc_rate(struct clk_hw *hw, unsigned long prate)
+{
+ struct clk_regmap_mux_div *md = to_clk_regmap_mux_div(hw);
+ u32 div, src;
+ int i, num_parents = clk_hw_get_num_parents(hw);
+ const char *name = clk_hw_get_name(hw);
+
+ __mux_div_get_src_div(md, &src, &div);
+ for (i = 0; i < num_parents; i++)
+ if (src == md->parent_map[i].cfg) {
+ struct clk_hw *p = clk_hw_get_parent_by_index(hw, i);
+ unsigned long parent_rate = clk_hw_get_rate(p);
+
+ return mult_frac(parent_rate, 2, div + 1);
+ }
+
+ pr_err("%s: Can't find parent %d\n", name, src);
+ return 0;
+}
+
+static void mux_div_disable(struct clk_hw *hw)
+{
+ struct clk_regmap_mux_div *md = to_clk_regmap_mux_div(hw);
+
+ __mux_div_set_src_div(md, md->safe_src, md->safe_div);
+}
+
+const struct clk_ops clk_regmap_mux_div_ops = {
+ .enable = mux_div_enable,
+ .disable = mux_div_disable,
+ .get_parent = mux_div_get_parent,
+ .set_parent = mux_div_set_parent,
+ .set_rate = mux_div_set_rate,
+ .set_rate_and_parent = mux_div_set_rate_and_parent,
+ .determine_rate = mux_div_determine_rate,
+ .recalc_rate = mux_div_recalc_rate,
+};
+EXPORT_SYMBOL_GPL(clk_regmap_mux_div_ops);
diff --git a/drivers/clk/qcom/clk-regmap-mux-div.h b/drivers/clk/qcom/clk-regmap-mux-div.h
new file mode 100644
index 000000000000..6fac5c54a824
--- /dev/null
+++ b/drivers/clk/qcom/clk-regmap-mux-div.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2015, Linaro Limited
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __QCOM_CLK_REGMAP_MUX_DIV_H__
+#define __QCOM_CLK_REGMAP_MUX_DIV_H__
+
+#include <linux/clk-provider.h>
+#include "clk-rcg.h"
+#include "clk-regmap.h"
+
+/**
+ * struct mux_div_clk - combined mux/divider clock
+ * @reg_offset: offset of the mux/divider register
+ * @hid_width: number of bits in half integer divider
+ * @hid_shift: lowest bit of hid value field
+ * @src_width: number of bits in source select
+ * @src_shift: lowest bit of source select field
+ * @div: the divider raw configuration value
+ * @src: the mux index which will be used if the clock is enabled
+ * @safe_src: the safe source mux value we switch to, while the main PLL is
+ * reconfigured
+ * @safe_div: the safe divider value that we set, while the main PLL is
+ * reconfigured
+ * @safe_freq: When switching rates from A to B, the mux div clock will
+ * instead switch from A -> safe_freq -> B. This allows the
+ * mux_div clock to change rates while enabled, even if this
+ * behavior is not supported by the parent clocks.
+ * If changing the rate of parent A also causes the rate of
+ * parent B to change, then safe_freq must be defined.
+ * safe_freq is expected to have a source clock which is always
+ * on and runs at only one rate.
+ * @parent_map: pointer to parent_map struct
+ * @clkr: handle between common and hardware-specific interfaces
+ */
+
+struct clk_regmap_mux_div {
+ u32 reg_offset;
+ u32 hid_width;
+ u32 hid_shift;
+ u32 src_width;
+ u32 src_shift;
+ u32 div;
+ u32 src;
+ u32 safe_src;
+ u32 safe_div;
+ unsigned long safe_freq;
+ const struct parent_map *parent_map;
+ struct clk_regmap clkr;
+};
+
+extern const struct clk_ops clk_regmap_mux_div_ops;
+int __mux_div_set_src_div(struct clk_regmap_mux_div *md, u32 src, u32 div);
+
+#endif
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 74f298d7328d..a3bdc30b9620 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -1996,6 +1996,7 @@ void __exit adreno_unregister(void)
static int __init msm_drm_register(void)
{
DBG("init");
+ msm_smmu_driver_init();
msm_dsi_register();
msm_edp_register();
hdmi_register();
@@ -2011,6 +2012,7 @@ static void __exit msm_drm_unregister(void)
adreno_unregister();
msm_edp_unregister();
msm_dsi_unregister();
+ msm_smmu_driver_cleanup();
}
module_init(msm_drm_register);
diff --git a/drivers/gpu/drm/msm/msm_mmu.h b/drivers/gpu/drm/msm/msm_mmu.h
index 033370ccbe24..8148d3e9e850 100644
--- a/drivers/gpu/drm/msm/msm_mmu.h
+++ b/drivers/gpu/drm/msm/msm_mmu.h
@@ -83,4 +83,8 @@ static inline void msm_mmu_disable(struct msm_mmu *mmu)
mmu->funcs->disable(mmu);
}
+/* SDE smmu driver initialize and cleanup functions */
+int __init msm_smmu_driver_init(void);
+void __exit msm_smmu_driver_cleanup(void);
+
#endif /* __MSM_MMU_H__ */
diff --git a/drivers/gpu/drm/msm/msm_smmu.c b/drivers/gpu/drm/msm/msm_smmu.c
index c2dd5f96521e..7d0dda032c59 100644
--- a/drivers/gpu/drm/msm/msm_smmu.c
+++ b/drivers/gpu/drm/msm/msm_smmu.c
@@ -192,13 +192,13 @@ static struct msm_smmu_domain msm_smmu_domains[MSM_SMMU_DOMAIN_MAX] = {
};
static const struct of_device_id msm_smmu_dt_match[] = {
- { .compatible = "qcom,smmu_mdp_unsec",
+ { .compatible = "qcom,smmu_sde_unsec",
.data = &msm_smmu_domains[MSM_SMMU_DOMAIN_UNSECURE] },
- { .compatible = "qcom,smmu_mdp_sec",
+ { .compatible = "qcom,smmu_sde_sec",
.data = &msm_smmu_domains[MSM_SMMU_DOMAIN_SECURE] },
- { .compatible = "qcom,smmu_rot_unsec",
+ { .compatible = "qcom,smmu_sde_nrt_unsec",
.data = &msm_smmu_domains[MSM_SMMU_DOMAIN_NRT_UNSECURE] },
- { .compatible = "qcom,smmu_rot_sec",
+ { .compatible = "qcom,smmu_sde_nrt_sec",
.data = &msm_smmu_domains[MSM_SMMU_DOMAIN_NRT_SECURE] },
{}
};
@@ -394,7 +394,7 @@ static struct platform_driver msm_smmu_driver = {
},
};
-static int __init msm_smmu_driver_init(void)
+int __init msm_smmu_driver_init(void)
{
int ret;
@@ -404,13 +404,11 @@ static int __init msm_smmu_driver_init(void)
return ret;
}
-module_init(msm_smmu_driver_init);
-static void __exit msm_smmu_driver_cleanup(void)
+void __exit msm_smmu_driver_cleanup(void)
{
platform_driver_unregister(&msm_smmu_driver);
}
-module_exit(msm_smmu_driver_cleanup);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("MSM SMMU driver");
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 0150d50c925b..50da3a128436 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -81,6 +81,12 @@ static void kgsl_pwrctrl_set_state(struct kgsl_device *device,
static void kgsl_pwrctrl_request_state(struct kgsl_device *device,
unsigned int state);
static int _isense_clk_set_rate(struct kgsl_pwrctrl *pwr, int level);
+static int kgsl_pwrctrl_clk_set_rate(struct clk *grp_clk, unsigned int freq,
+ const char *name);
+static void _gpu_clk_prepare_enable(struct kgsl_device *device,
+ struct clk *clk, const char *name);
+static void _bimc_clk_prepare_enable(struct kgsl_device *device,
+ struct clk *clk, const char *name);
/**
* _record_pwrevent() - Record the history of the new event
@@ -405,7 +411,8 @@ void kgsl_pwrctrl_pwrlevel_change(struct kgsl_device *device,
pwrlevel = &pwr->pwrlevels[pwr->active_pwrlevel];
/* Change register settings if any BEFORE pwrlevel change*/
kgsl_pwrctrl_pwrlevel_change_settings(device, 0);
- clk_set_rate(pwr->grp_clks[0], pwrlevel->gpu_freq);
+ kgsl_pwrctrl_clk_set_rate(pwr->grp_clks[0],
+ pwrlevel->gpu_freq, clocks[0]);
_isense_clk_set_rate(pwr, pwr->active_pwrlevel);
trace_kgsl_pwrlevel(device,
@@ -423,9 +430,12 @@ void kgsl_pwrctrl_pwrlevel_change(struct kgsl_device *device,
if (pwr->gpu_bimc_int_clk) {
if (pwr->active_pwrlevel == 0 &&
!pwr->gpu_bimc_interface_enabled) {
- clk_set_rate(pwr->gpu_bimc_int_clk,
- pwr->gpu_bimc_int_clk_freq);
- clk_prepare_enable(pwr->gpu_bimc_int_clk);
+ kgsl_pwrctrl_clk_set_rate(pwr->gpu_bimc_int_clk,
+ pwr->gpu_bimc_int_clk_freq,
+ "bimc_gpu_clk");
+ _bimc_clk_prepare_enable(device,
+ pwr->gpu_bimc_int_clk,
+ "bimc_gpu_clk");
pwr->gpu_bimc_interface_enabled = 1;
} else if (pwr->previous_pwrlevel == 0
&& pwr->gpu_bimc_interface_enabled) {
@@ -1650,9 +1660,9 @@ static void kgsl_pwrctrl_clk(struct kgsl_device *device, int state,
(requested_state != KGSL_STATE_NAP)) {
for (i = KGSL_MAX_CLKS - 1; i > 0; i--)
clk_unprepare(pwr->grp_clks[i]);
- clk_set_rate(pwr->grp_clks[0],
+ kgsl_pwrctrl_clk_set_rate(pwr->grp_clks[0],
pwr->pwrlevels[pwr->num_pwrlevels - 1].
- gpu_freq);
+ gpu_freq, clocks[0]);
_isense_clk_set_rate(pwr,
pwr->num_pwrlevels - 1);
}
@@ -1664,9 +1674,9 @@ static void kgsl_pwrctrl_clk(struct kgsl_device *device, int state,
for (i = KGSL_MAX_CLKS - 1; i > 0; i--)
clk_unprepare(pwr->grp_clks[i]);
if ((pwr->pwrlevels[0].gpu_freq > 0)) {
- clk_set_rate(pwr->grp_clks[0],
+ kgsl_pwrctrl_clk_set_rate(pwr->grp_clks[0],
pwr->pwrlevels[pwr->num_pwrlevels - 1].
- gpu_freq);
+ gpu_freq, clocks[0]);
_isense_clk_set_rate(pwr,
pwr->num_pwrlevels - 1);
}
@@ -1679,29 +1689,31 @@ static void kgsl_pwrctrl_clk(struct kgsl_device *device, int state,
/* High latency clock maintenance. */
if (device->state != KGSL_STATE_NAP) {
if (pwr->pwrlevels[0].gpu_freq > 0) {
- clk_set_rate(pwr->grp_clks[0],
+ kgsl_pwrctrl_clk_set_rate(
+ pwr->grp_clks[0],
pwr->pwrlevels
[pwr->active_pwrlevel].
- gpu_freq);
+ gpu_freq, clocks[0]);
_isense_clk_set_rate(pwr,
pwr->active_pwrlevel);
}
-
- for (i = KGSL_MAX_CLKS - 1; i > 0; i--)
- clk_prepare(pwr->grp_clks[i]);
}
- /* as last step, enable grp_clk
- this is to let GPU interrupt to come */
+
for (i = KGSL_MAX_CLKS - 1; i > 0; i--)
- clk_enable(pwr->grp_clks[i]);
+ _gpu_clk_prepare_enable(device,
+ pwr->grp_clks[i], clocks[i]);
+
/* Enable the gpu-bimc-interface clocks */
if (pwr->gpu_bimc_int_clk) {
if (pwr->active_pwrlevel == 0 &&
!pwr->gpu_bimc_interface_enabled) {
- clk_set_rate(pwr->gpu_bimc_int_clk,
- pwr->gpu_bimc_int_clk_freq);
- clk_prepare_enable(
- pwr->gpu_bimc_int_clk);
+ kgsl_pwrctrl_clk_set_rate(
+ pwr->gpu_bimc_int_clk,
+ pwr->gpu_bimc_int_clk_freq,
+ "bimc_gpu_clk");
+ _bimc_clk_prepare_enable(device,
+ pwr->gpu_bimc_int_clk,
+ "bimc_gpu_clk");
pwr->gpu_bimc_interface_enabled = 1;
}
}
@@ -2022,7 +2034,54 @@ static int _isense_clk_set_rate(struct kgsl_pwrctrl *pwr, int level)
rate = clk_round_rate(pwr->grp_clks[pwr->isense_clk_indx],
level > pwr->isense_clk_on_level ?
KGSL_XO_CLK_FREQ : KGSL_ISENSE_CLK_FREQ);
- return clk_set_rate(pwr->grp_clks[pwr->isense_clk_indx], rate);
+ return kgsl_pwrctrl_clk_set_rate(pwr->grp_clks[pwr->isense_clk_indx],
+ rate, clocks[pwr->isense_clk_indx]);
+}
+
+/*
+ * _gpu_clk_prepare_enable - Enable the specified GPU clock
+ * Try once to enable it and then BUG() for debug
+ */
+static void _gpu_clk_prepare_enable(struct kgsl_device *device,
+ struct clk *clk, const char *name)
+{
+ int ret;
+
+ if (device->state == KGSL_STATE_NAP) {
+ ret = clk_enable(clk);
+ if (ret)
+ goto err;
+ return;
+ }
+
+ ret = clk_prepare_enable(clk);
+ if (!ret)
+ return;
+err:
+ /* Failure is fatal so BUG() to facilitate debug */
+ KGSL_DRV_FATAL(device, "KGSL:%s enable error:%d\n", name, ret);
+}
+
+/*
+ * _bimc_clk_prepare_enable - Enable the specified GPU clock
+ * Try once to enable it and then BUG() for debug
+ */
+static void _bimc_clk_prepare_enable(struct kgsl_device *device,
+ struct clk *clk, const char *name)
+{
+ int ret = clk_prepare_enable(clk);
+ /* Failure is fatal so BUG() to facilitate debug */
+ if (ret)
+ KGSL_DRV_FATAL(device, "KGSL:%s enable error:%d\n", name, ret);
+}
+
+static int kgsl_pwrctrl_clk_set_rate(struct clk *grp_clk, unsigned int freq,
+ const char *name)
+{
+ int ret = clk_set_rate(grp_clk, freq);
+
+ WARN(ret, "KGSL:%s set freq %d failed:%d\n", name, freq, ret);
+ return ret;
}
static inline void _close_pcl(struct kgsl_pwrctrl *pwr)
@@ -2117,11 +2176,12 @@ int kgsl_pwrctrl_init(struct kgsl_device *device)
pwr->pwrlevels[i].gpu_freq = freq;
}
- clk_set_rate(pwr->grp_clks[0],
- pwr->pwrlevels[pwr->num_pwrlevels - 1].gpu_freq);
+ kgsl_pwrctrl_clk_set_rate(pwr->grp_clks[0],
+ pwr->pwrlevels[pwr->num_pwrlevels - 1].gpu_freq, clocks[0]);
- clk_set_rate(pwr->grp_clks[6],
- clk_round_rate(pwr->grp_clks[6], KGSL_RBBMTIMER_CLK_FREQ));
+ kgsl_pwrctrl_clk_set_rate(pwr->grp_clks[6],
+ clk_round_rate(pwr->grp_clks[6], KGSL_RBBMTIMER_CLK_FREQ),
+ clocks[6]);
_isense_clk_set_rate(pwr, pwr->num_pwrlevels - 1);
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 7d09f22d3bc6..500185546599 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -2908,7 +2908,11 @@ static int qseecom_send_service_cmd(struct qseecom_dev_handle *data,
}
if (req.cmd_id == QSEOS_RPMB_CHECK_PROV_STATUS_COMMAND) {
pr_warn("RPMB key status is 0x%x\n", resp.result);
- *(uint32_t *)req.resp_buf = resp.result;
+ if (put_user(resp.result,
+ (uint32_t __user *)req.resp_buf)) {
+ ret = -EINVAL;
+ goto exit;
+ }
ret = 0;
}
break;
@@ -6498,11 +6502,16 @@ static int __qseecom_qteec_issue_cmd(struct qseecom_dev_handle *data,
void *cmd_buf = NULL;
size_t cmd_len;
struct sglist_info *table = data->sglistinfo_ptr;
+ void *req_ptr = NULL;
+ void *resp_ptr = NULL;
ret = __qseecom_qteec_validate_msg(data, req);
if (ret)
return ret;
+ req_ptr = req->req_ptr;
+ resp_ptr = req->resp_ptr;
+
/* find app_id & img_name from list */
spin_lock_irqsave(&qseecom.registered_app_list_lock, flags);
list_for_each_entry(ptr_app, &qseecom.registered_app_list_head,
@@ -6520,6 +6529,11 @@ static int __qseecom_qteec_issue_cmd(struct qseecom_dev_handle *data,
return -ENOENT;
}
+ req->req_ptr = (void *)__qseecom_uvirt_to_kvirt(data,
+ (uintptr_t)req->req_ptr);
+ req->resp_ptr = (void *)__qseecom_uvirt_to_kvirt(data,
+ (uintptr_t)req->resp_ptr);
+
if ((cmd_id == QSEOS_TEE_OPEN_SESSION) ||
(cmd_id == QSEOS_TEE_REQUEST_CANCELLATION)) {
ret = __qseecom_update_qteec_req_buf(
@@ -6531,10 +6545,10 @@ static int __qseecom_qteec_issue_cmd(struct qseecom_dev_handle *data,
if (qseecom.qsee_version < QSEE_VERSION_40) {
ireq.app_id = data->client.app_id;
ireq.req_ptr = (uint32_t)__qseecom_uvirt_to_kphys(data,
- (uintptr_t)req->req_ptr);
+ (uintptr_t)req_ptr);
ireq.req_len = req->req_len;
ireq.resp_ptr = (uint32_t)__qseecom_uvirt_to_kphys(data,
- (uintptr_t)req->resp_ptr);
+ (uintptr_t)resp_ptr);
ireq.resp_len = req->resp_len;
ireq.sglistinfo_ptr = (uint32_t)virt_to_phys(table);
ireq.sglistinfo_len = SGLISTINFO_TABLE_SIZE;
@@ -6545,10 +6559,10 @@ static int __qseecom_qteec_issue_cmd(struct qseecom_dev_handle *data,
} else {
ireq_64bit.app_id = data->client.app_id;
ireq_64bit.req_ptr = (uint64_t)__qseecom_uvirt_to_kphys(data,
- (uintptr_t)req->req_ptr);
+ (uintptr_t)req_ptr);
ireq_64bit.req_len = req->req_len;
ireq_64bit.resp_ptr = (uint64_t)__qseecom_uvirt_to_kphys(data,
- (uintptr_t)req->resp_ptr);
+ (uintptr_t)resp_ptr);
ireq_64bit.resp_len = req->resp_len;
if ((data->client.app_arch == ELFCLASS32) &&
((ireq_64bit.req_ptr >=
diff --git a/drivers/soc/qcom/icnss_utils.c b/drivers/soc/qcom/icnss_utils.c
index a7a0ffa2c18e..6974146c6112 100644
--- a/drivers/soc/qcom/icnss_utils.c
+++ b/drivers/soc/qcom/icnss_utils.c
@@ -12,11 +12,13 @@
#include <linux/module.h>
#include <linux/slab.h>
+#include <soc/qcom/icnss.h>
#define ICNSS_MAX_CH_NUM 45
static DEFINE_MUTEX(unsafe_channel_list_lock);
static DEFINE_SPINLOCK(dfs_nol_info_lock);
+static int driver_load_cnt;
static struct icnss_unsafe_channel_list {
u16 unsafe_ch_count;
@@ -124,3 +126,15 @@ int icnss_wlan_get_dfs_nol(void *info, u16 info_len)
return len;
}
EXPORT_SYMBOL(icnss_wlan_get_dfs_nol);
+
+void icnss_increment_driver_load_cnt(void)
+{
+ ++driver_load_cnt;
+}
+EXPORT_SYMBOL(icnss_increment_driver_load_cnt);
+
+int icnss_get_driver_load_cnt(void)
+{
+ return driver_load_cnt;
+}
+EXPORT_SYMBOL(icnss_get_driver_load_cnt);
diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index e5d3a0bdf32a..a2c14bb5efa4 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -23,6 +23,7 @@ void acc_disconnect(void);
static struct class *android_class;
static struct device *android_device;
static int index;
+static int gadget_index;
struct device *create_function_device(char *name)
{
@@ -1439,21 +1440,21 @@ static void android_work(struct work_struct *data)
spin_unlock_irqrestore(&cdev->lock, flags);
if (status[0]) {
- kobject_uevent_env(&android_device->kobj,
+ kobject_uevent_env(&gi->dev->kobj,
KOBJ_CHANGE, connected);
pr_info("%s: sent uevent %s\n", __func__, connected[0]);
uevent_sent = true;
}
if (status[1]) {
- kobject_uevent_env(&android_device->kobj,
+ kobject_uevent_env(&gi->dev->kobj,
KOBJ_CHANGE, configured);
pr_info("%s: sent uevent %s\n", __func__, configured[0]);
uevent_sent = true;
}
if (status[2]) {
- kobject_uevent_env(&android_device->kobj,
+ kobject_uevent_env(&gi->dev->kobj,
KOBJ_CHANGE, disconnected);
pr_info("%s: sent uevent %s\n", __func__, disconnected[0]);
uevent_sent = true;
@@ -1613,23 +1614,28 @@ static int android_device_create(struct gadget_info *gi)
{
struct device_attribute **attrs;
struct device_attribute *attr;
+ char str[10];
INIT_WORK(&gi->work, android_work);
- android_device = device_create(android_class, NULL,
- MKDEV(0, 0), NULL, "android0");
- if (IS_ERR(android_device))
- return PTR_ERR(android_device);
+ snprintf(str, sizeof(str), "android%d", gadget_index - 1);
+ pr_debug("Creating android device %s\n", str);
+ gi->dev = device_create(android_class, NULL,
+ MKDEV(0, 0), NULL, str);
+ if (IS_ERR(gi->dev))
+ return PTR_ERR(gi->dev);
- dev_set_drvdata(android_device, gi);
+ dev_set_drvdata(gi->dev, gi);
+ if (gadget_index == 1)
+ android_device = gi->dev;
attrs = android_usb_attributes;
while ((attr = *attrs++)) {
int err;
- err = device_create_file(android_device, attr);
+ err = device_create_file(gi->dev, attr);
if (err) {
- device_destroy(android_device->class,
- android_device->devt);
+ device_destroy(gi->dev->class,
+ gi->dev->devt);
return err;
}
}
@@ -1637,15 +1643,15 @@ static int android_device_create(struct gadget_info *gi)
return 0;
}
-static void android_device_destroy(void)
+static void android_device_destroy(struct device *dev)
{
struct device_attribute **attrs;
struct device_attribute *attr;
attrs = android_usb_attributes;
while ((attr = *attrs++))
- device_remove_file(android_device, attr);
- device_destroy(android_device->class, android_device->devt);
+ device_remove_file(dev, attr);
+ device_destroy(dev->class, dev->devt);
}
#else
static inline int android_device_create(struct gadget_info *gi)
@@ -1653,7 +1659,7 @@ static inline int android_device_create(struct gadget_info *gi)
return 0;
}
-static inline void android_device_destroy(void)
+static inline void android_device_destroy(struct device *dev)
{
}
#endif
@@ -1705,6 +1711,8 @@ static struct config_group *gadgets_make(
if (!gi->composite.gadget_driver.function)
goto err;
+ gadget_index++;
+ pr_debug("Creating gadget index %d\n", gadget_index);
if (android_device_create(gi) < 0)
goto err;
@@ -1719,8 +1727,14 @@ err:
static void gadgets_drop(struct config_group *group, struct config_item *item)
{
+ struct gadget_info *gi;
+
+ gi = container_of(to_config_group(item), struct gadget_info, group);
config_item_put(item);
- android_device_destroy();
+ if (gi->dev) {
+ android_device_destroy(gi->dev);
+ gi->dev = NULL;
+ }
}
static struct configfs_group_operations gadgets_ops = {
diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c
index 0272800269eb..03aeec2e878c 100644
--- a/drivers/usb/pd/policy_engine.c
+++ b/drivers/usb/pd/policy_engine.c
@@ -34,6 +34,10 @@ static bool usb_compliance_mode;
module_param(usb_compliance_mode, bool, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(usb_compliance_mode, "Start USB stack for USB3.1 compliance testing");
+static bool disable_usb_pd;
+module_param(disable_usb_pd, bool, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(disable_usb_pd, "Disable USB PD for USB3.1 compliance testing");
+
enum usbpd_state {
PE_UNKNOWN,
PE_ERROR_RECOVERY,
@@ -920,7 +924,7 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
break;
}
- if (!val.intval)
+ if (!val.intval || disable_usb_pd)
break;
pd_reset_protocol(pd);
diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c
index 4f1333426113..48b151b8080a 100644
--- a/drivers/video/fbdev/msm/mdss_dsi.c
+++ b/drivers/video/fbdev/msm/mdss_dsi.c
@@ -3429,9 +3429,10 @@ static int mdss_dsi_ctrl_probe(struct platform_device *pdev)
hw_vsync_handler, IRQF_TRIGGER_FALLING,
"VSYNC_GPIO", ctrl_pdata);
if (rc) {
- pr_err("TE request_irq failed.\n");
+ pr_err("%s: TE request_irq failed for ESD\n", __func__);
goto error_shadow_clk_deinit;
}
+ te_irq_registered = 1;
disable_irq(gpio_to_irq(ctrl_pdata->disp_te_gpio));
}
diff --git a/drivers/video/fbdev/msm/mdss_dsi_host.c b/drivers/video/fbdev/msm/mdss_dsi_host.c
index b448153df1df..c766ff983045 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_host.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_host.c
@@ -2275,6 +2275,7 @@ static int mdss_dsi_cmd_dma_rx(struct mdss_dsi_ctrl_pdata *ctrl,
bool ack_error = false;
char reg[16] = {0x0};
int repeated_bytes = 0;
+ struct mdss_dsi_ctrl_pdata *mctrl = mdss_dsi_get_other_ctrl(ctrl);
lp = (u32 *)rp->data;
temp = (u32 *)reg;
@@ -2335,7 +2336,11 @@ static int mdss_dsi_cmd_dma_rx(struct mdss_dsi_ctrl_pdata *ctrl,
off += ((cnt - 1) * 4);
for (i = 0; i < cnt; i++) {
- data = (u32)MIPI_INP((ctrl->ctrl_base) + off);
+ if (mdss_dsi_sync_wait_trigger(ctrl))
+ data = (u32)MIPI_INP((mctrl->ctrl_base) + off);
+ else
+ data = (u32)MIPI_INP((ctrl->ctrl_base) + off);
+
/* to network byte order */
if (!repeated_bytes)
*lp++ = ntohl(data);
diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
index 3c679877705d..fbd5b01a81e7 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
@@ -4987,9 +4987,10 @@ static int mdss_fb_get_metadata(struct msm_fb_data_type *mfd,
ret = mdss_fb_get_hw_caps(mfd, &metadata->data.caps);
break;
case metadata_op_get_ion_fd:
- if (mfd->fb_ion_handle) {
+ if (mfd->fb_ion_handle && mfd->fb_ion_client) {
metadata->data.fbmem_ionfd =
- dma_buf_fd(mfd->fbmem_buf, 0);
+ ion_share_dma_buf_fd(mfd->fb_ion_client,
+ mfd->fb_ion_handle);
if (metadata->data.fbmem_ionfd < 0)
pr_err("fd allocation failed. fd = %d\n",
metadata->data.fbmem_ionfd);
diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp.h b/drivers/video/fbdev/msm/mdss_mdp_pp.h
index 809c389e99e8..136e2d79787c 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_pp.h
+++ b/drivers/video/fbdev/msm/mdss_mdp_pp.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -181,7 +181,7 @@ struct mdss_pp_res_type {
struct mdp_hist_lut_data enhist_disp_cfg[MDSS_BLOCK_DISP_NUM];
struct mdp_dither_cfg_data dither_disp_cfg[MDSS_BLOCK_DISP_NUM];
struct mdp_gamut_cfg_data gamut_disp_cfg[MDSS_BLOCK_DISP_NUM];
- uint16_t gamut_tbl[MDSS_BLOCK_DISP_NUM][GAMUT_TOTAL_TABLE_SIZE];
+ uint16_t gamut_tbl[MDSS_BLOCK_DISP_NUM][GAMUT_TOTAL_TABLE_SIZE * 3];
u32 hist_data[MDSS_BLOCK_DISP_NUM][HIST_V_SIZE];
struct pp_sts_type pp_disp_sts[MDSS_BLOCK_DISP_NUM];
struct mdp_dither_cfg_data pa_dither_cfg[MDSS_BLOCK_DISP_NUM];
diff --git a/drivers/video/fbdev/msm/msm_dba/adv7533.c b/drivers/video/fbdev/msm/msm_dba/adv7533.c
index 63e178d76403..09632b49d33b 100644
--- a/drivers/video/fbdev/msm/msm_dba/adv7533.c
+++ b/drivers/video/fbdev/msm/msm_dba/adv7533.c
@@ -517,13 +517,25 @@ static void adv7533_parse_vreg_dt(struct device *dev,
}
mp->vreg_config[i].disable_load = val_array[i];
- pr_debug("%s: %s min=%d, max=%d, enable=%d disable=%d\n",
+ /* post-on-sleep */
+ memset(val_array, 0, sizeof(u32) * dt_vreg_total);
+ rc = of_property_read_u32_array(of_node,
+ "qcom,post-on-sleep", val_array,
+ dt_vreg_total);
+ if (rc)
+ pr_warn("%s: error read post on sleep. rc=%d\n",
+ __func__, rc);
+ else
+ mp->vreg_config[i].post_on_sleep = val_array[i];
+
+ pr_debug("%s: %s min=%d, max=%d, enable=%d disable=%d post-on-sleep=%d\n",
__func__,
mp->vreg_config[i].vreg_name,
mp->vreg_config[i].min_voltage,
mp->vreg_config[i].max_voltage,
mp->vreg_config[i].enable_load,
- mp->vreg_config[i].disable_load);
+ mp->vreg_config[i].disable_load,
+ mp->vreg_config[i].post_on_sleep);
}
devm_kfree(dev, val_array);
diff --git a/include/soc/qcom/icnss.h b/include/soc/qcom/icnss.h
index b434da092b8e..0764b9e26962 100644
--- a/include/soc/qcom/icnss.h
+++ b/include/soc/qcom/icnss.h
@@ -152,4 +152,6 @@ extern u8 *icnss_get_wlan_mac_address(struct device *dev, uint32_t *num);
extern int icnss_trigger_recovery(struct device *dev);
extern void cnss_set_cc_source(enum cnss_cc_src cc_source);
extern enum cnss_cc_src cnss_get_cc_source(void);
+extern int icnss_get_driver_load_cnt(void);
+extern void icnss_increment_driver_load_cnt(void);
#endif /* _ICNSS_WLAN_H_ */
diff --git a/include/soc/qcom/minidump.h b/include/soc/qcom/minidump.h
index 2db61a40e2cc..5eb18cb1a365 100644
--- a/include/soc/qcom/minidump.h
+++ b/include/soc/qcom/minidump.h
@@ -37,12 +37,13 @@ struct md_region {
*/
#ifdef CONFIG_QCOM_MINIDUMP
extern int msm_minidump_add_region(const struct md_region *entry);
+/* Sets to true, if minidump table is initialized */
extern bool minidump_enabled;
#else
static inline int msm_minidump_add_region(const struct md_region *entry)
{
- return -ENODEV;
+ /* Return quietly, if minidump is not supported */
+ return 0;
}
-static inline bool msm_minidump_enabled(void) { return false; }
#endif
#endif
diff --git a/sound/soc/codecs/sdm660_cdc/msm-analog-cdc.c b/sound/soc/codecs/sdm660_cdc/msm-analog-cdc.c
index 00f2aa766363..ee057e99bc41 100644
--- a/sound/soc/codecs/sdm660_cdc/msm-analog-cdc.c
+++ b/sound/soc/codecs/sdm660_cdc/msm-analog-cdc.c
@@ -1400,8 +1400,26 @@ static int msm_anlg_cdc_codec_enable_on_demand_supply(
}
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
- if (atomic_inc_return(&supply->ref) == 1)
+ if (atomic_inc_return(&supply->ref) == 1) {
+ ret = regulator_set_voltage(supply->supply,
+ supply->min_uv,
+ supply->max_uv);
+ if (ret) {
+ dev_err(codec->dev,
+ "Setting regulator voltage(en) for micbias with err = %d\n",
+ ret);
+ goto out;
+ }
+ ret = regulator_set_load(supply->supply,
+ supply->optimum_ua);
+ if (ret < 0) {
+ dev_err(codec->dev,
+ "Setting regulator optimum mode(en) failed for micbias with err = %d\n",
+ ret);
+ goto out;
+ }
ret = regulator_enable(supply->supply);
+ }
if (ret)
dev_err(codec->dev, "%s: Failed to enable %s\n",
__func__,
@@ -1413,12 +1431,27 @@ static int msm_anlg_cdc_codec_enable_on_demand_supply(
__func__, on_demand_supply_name[w->shift]);
goto out;
}
- if (atomic_dec_return(&supply->ref) == 0)
+ if (atomic_dec_return(&supply->ref) == 0) {
ret = regulator_disable(supply->supply);
if (ret)
dev_err(codec->dev, "%s: Failed to disable %s\n",
__func__,
on_demand_supply_name[w->shift]);
+ ret = regulator_set_voltage(supply->supply,
+ 0,
+ supply->max_uv);
+ if (ret) {
+ dev_err(codec->dev,
+ "Setting regulator voltage(dis) failed for micbias with err = %d\n",
+ ret);
+ goto out;
+ }
+ ret = regulator_set_load(supply->supply, 0);
+ if (ret < 0)
+ dev_err(codec->dev,
+ "Setting regulator optimum mode(dis) failed for micbias with err = %d\n",
+ ret);
+ }
break;
default:
break;
@@ -3685,6 +3718,30 @@ static struct regulator *msm_anlg_cdc_find_regulator(
return NULL;
}
+static void msm_anlg_cdc_update_micbias_regulator(
+ const struct sdm660_cdc_priv *sdm660_cdc,
+ const char *name,
+ struct on_demand_supply *micbias_supply)
+{
+ int i;
+ struct sdm660_cdc_pdata *pdata = sdm660_cdc->dev->platform_data;
+
+ for (i = 0; i < sdm660_cdc->num_of_supplies; i++) {
+ if (sdm660_cdc->supplies[i].supply &&
+ !strcmp(sdm660_cdc->supplies[i].supply, name)) {
+ micbias_supply->supply =
+ sdm660_cdc->supplies[i].consumer;
+ micbias_supply->min_uv = pdata->regulator[i].min_uv;
+ micbias_supply->max_uv = pdata->regulator[i].max_uv;
+ micbias_supply->optimum_ua =
+ pdata->regulator[i].optimum_ua;
+ return;
+ }
+ }
+
+ dev_err(sdm660_cdc->dev, "Error: regulator not found:%s\n", name);
+}
+
static int msm_anlg_cdc_device_down(struct snd_soc_codec *codec)
{
struct msm_asoc_mach_data *pdata = NULL;
@@ -4114,10 +4171,10 @@ static int msm_anlg_cdc_soc_probe(struct snd_soc_codec *codec)
wcd9xxx_spmi_set_codec(codec);
- sdm660_cdc->on_demand_list[ON_DEMAND_MICBIAS].supply =
- msm_anlg_cdc_find_regulator(
+ msm_anlg_cdc_update_micbias_regulator(
sdm660_cdc,
- on_demand_supply_name[ON_DEMAND_MICBIAS]);
+ on_demand_supply_name[ON_DEMAND_MICBIAS],
+ &sdm660_cdc->on_demand_list[ON_DEMAND_MICBIAS]);
atomic_set(&sdm660_cdc->on_demand_list[ON_DEMAND_MICBIAS].ref,
0);
@@ -4183,7 +4240,7 @@ static int msm_anlg_cdc_enable_static_supplies_to_optimum(
if (pdata->regulator[i].ondemand)
continue;
if (regulator_count_voltages(
- sdm660_cdc->supplies[i].consumer) <= 0)
+ sdm660_cdc->supplies[i].consumer) <= 0)
continue;
ret = regulator_set_voltage(
@@ -4216,7 +4273,7 @@ static int msm_anlg_cdc_disable_static_supplies_to_optimum(
if (pdata->regulator[i].ondemand)
continue;
if (regulator_count_voltages(
- sdm660_cdc->supplies[i].consumer) <= 0)
+ sdm660_cdc->supplies[i].consumer) <= 0)
continue;
regulator_set_voltage(sdm660_cdc->supplies[i].consumer, 0,
pdata->regulator[i].max_uv);
@@ -4317,6 +4374,28 @@ static int msm_anlg_cdc_init_supplies(struct sdm660_cdc_priv *sdm660_cdc,
if (regulator_count_voltages(
sdm660_cdc->supplies[i].consumer) <= 0)
continue;
+ if (pdata->regulator[i].ondemand) {
+ ret = regulator_set_voltage(
+ sdm660_cdc->supplies[i].consumer,
+ 0, pdata->regulator[i].max_uv);
+ if (ret) {
+ dev_err(sdm660_cdc->dev,
+ "Setting regulator voltage failed for regulator %s err = %d\n",
+ sdm660_cdc->supplies[i].supply, ret);
+ goto err_supplies;
+ }
+ ret = regulator_set_load(
+ sdm660_cdc->supplies[i].consumer, 0);
+ if (ret < 0) {
+ dev_err(sdm660_cdc->dev,
+ "Setting regulator optimum mode failed for regulator %s err = %d\n",
+ sdm660_cdc->supplies[i].supply, ret);
+ goto err_supplies;
+ } else {
+ ret = 0;
+ continue;
+ }
+ }
ret = regulator_set_voltage(sdm660_cdc->supplies[i].consumer,
pdata->regulator[i].min_uv,
pdata->regulator[i].max_uv);
diff --git a/sound/soc/codecs/sdm660_cdc/msm-analog-cdc.h b/sound/soc/codecs/sdm660_cdc/msm-analog-cdc.h
index 0c9e9a6aeb6a..9563565f36d2 100644
--- a/sound/soc/codecs/sdm660_cdc/msm-analog-cdc.h
+++ b/sound/soc/codecs/sdm660_cdc/msm-analog-cdc.h
@@ -144,6 +144,9 @@ struct sdm660_cdc_regulator {
struct on_demand_supply {
struct regulator *supply;
atomic_t ref;
+ int min_uv;
+ int max_uv;
+ int optimum_ua;
};
struct wcd_imped_i_ref {