summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/DMA-attributes.txt19
-rw-r--r--arch/arm/boot/dts/qcom/dsi-panel-nt36850-truly-dualmipi-wqhd-cmd.dtsi416
-rw-r--r--arch/arm/boot/dts/qcom/msm-pm660.dtsi6
-rw-r--r--arch/arm/boot/dts/qcom/msm-pm660l-rpm-regulator.dtsi6
-rw-r--r--arch/arm/boot/dts/qcom/msm-pmi8998.dtsi6
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-camera-sensor-cdp.dtsi1
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-camera-sensor-mtp.dtsi1
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-interposer-pm660.dtsi12
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-v2.dtsi37
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-mtp.dtsi4
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-qrd.dts6
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-qrd.dtsi47
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-vidc.dtsi1
-rw-r--r--arch/arm/boot/dts/qcom/sdm660.dtsi16
-rw-r--r--arch/arm/configs/msmcortex_defconfig2
-rw-r--r--arch/arm/configs/sdm660-perf_defconfig2
-rw-r--r--arch/arm/configs/sdm660_defconfig2
-rw-r--r--arch/arm64/configs/msm-perf_defconfig2
-rw-r--r--arch/arm64/configs/msm_defconfig2
-rw-r--r--arch/arm64/configs/msmcortex-perf_defconfig2
-rw-r--r--arch/arm64/configs/msmcortex_defconfig2
-rw-r--r--arch/arm64/configs/sdm660-perf_defconfig8
-rw-r--r--arch/arm64/configs/sdm660_defconfig8
-rw-r--r--arch/arm64/mm/fault.c20
-rw-r--r--drivers/clk/msm/clock-gcc-8998.c5
-rw-r--r--drivers/clk/msm/clock-osm.c111
-rw-r--r--drivers/clk/qcom/clk-cpu-osm.c113
-rw-r--r--drivers/cpuidle/lpm-levels.c5
-rw-r--r--drivers/gpu/drm/msm/Kconfig2
-rw-r--r--drivers/gpu/msm/kgsl_iommu.c20
-rw-r--r--drivers/hwtracing/coresight/coresight-etm4x.c2
-rw-r--r--drivers/input/Kconfig8
-rw-r--r--drivers/input/Makefile1
-rw-r--r--drivers/input/misc/Kconfig9
-rw-r--r--drivers/input/misc/Makefile1
-rw-r--r--drivers/input/misc/qpnp-power-on.c (renamed from drivers/input/qpnp-power-on.c)6
-rw-r--r--drivers/iommu/arm-smmu.c20
-rw-r--r--drivers/iommu/io-pgtable-arm.c78
-rw-r--r--drivers/iommu/io-pgtable.h3
-rw-r--r--drivers/iommu/iommu.c7
-rw-r--r--drivers/media/dvb-core/dvb_ringbuffer.c8
-rw-r--r--drivers/media/platform/msm/camera_v2/common/cam_soc_api.c44
-rw-r--r--drivers/media/platform/msm/camera_v2/common/cam_soc_api.h17
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp.c4
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp.h30
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp32.c11
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp40.c14
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp44.c15
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp46.c14
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp47.c17
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp47.h2
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp48.c59
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp48.h4
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c20
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c2
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c144
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h5
-rw-r--r--drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c45
-rw-r--r--drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h2
-rw-r--r--drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp_soc.c12
-rw-r--r--drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.c19
-rw-r--r--drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.h3
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_base.c38
-rw-r--r--drivers/media/platform/msm/vidc/venus_hfi.c1
-rw-r--r--drivers/mfd/wcd9xxx-irq.c19
-rw-r--r--drivers/misc/qseecom.c4
-rw-r--r--drivers/mmc/core/mmc.c8
-rw-r--r--drivers/power/qcom-charger/pmic-voter.c137
-rw-r--r--drivers/power/qcom-charger/qpnp-fg-gen3.c18
-rw-r--r--drivers/power/qcom-charger/qpnp-qnovo.c25
-rw-r--r--drivers/power/qcom-charger/qpnp-smb2.c21
-rw-r--r--drivers/power/qcom-charger/smb-lib.c65
-rw-r--r--drivers/power/qcom-charger/smb-lib.h5
-rw-r--r--drivers/power/qcom-charger/smb-reg.h6
-rw-r--r--drivers/power/reset/msm-poweroff.c4
-rw-r--r--drivers/scsi/ufs/ufshcd.c9
-rw-r--r--drivers/scsi/ufs/ufshcd.h1
-rw-r--r--drivers/soc/qcom/spcom.c64
-rw-r--r--drivers/thermal/msm-tsens.c12
-rw-r--r--drivers/usb/gadget/function/f_gsi.c3
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi.c7
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi.h1
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi_host.c14
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi_panel.c5
-rw-r--r--drivers/video/fbdev/msm/msm_mdss_io_8974.c16
-rw-r--r--include/linux/dma-attrs.h2
-rw-r--r--include/linux/input/qpnp-power-on.h (renamed from include/linux/qpnp/power-on.h)4
-rw-r--r--include/linux/iommu.h9
-rw-r--r--include/trace/events/msm_cam.h136
-rw-r--r--include/trace/events/sched.h9
-rw-r--r--kernel/sched/hmp.c1
-rw-r--r--kernel/time/hrtimer.c20
-rw-r--r--kernel/time/timer.c41
-rw-r--r--sound/soc/codecs/wcd934x/wcd934x.c8
-rw-r--r--sound/soc/msm/Kconfig2
-rw-r--r--sound/soc/msm/msm-cpe-lsm.c7
-rw-r--r--sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c11
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c1
-rw-r--r--sound/soc/msm/qdsp6v2/q6core.c5
99 files changed, 1845 insertions, 404 deletions
diff --git a/Documentation/DMA-attributes.txt b/Documentation/DMA-attributes.txt
index 64a4f9bb62c4..6eadd564a247 100644
--- a/Documentation/DMA-attributes.txt
+++ b/Documentation/DMA-attributes.txt
@@ -126,3 +126,22 @@ DMA_ATTR_EXEC_MAPPING
By default, the DMA mappings are non-executable. Some use cases might require
an executable mapping. This attribute can be used to indicate to the DMA
subsystem to create an executable mappings for the buffer.
+
+DMA_ATTR_FORCE_COHERENT
+-----------------------
+
+When passed to a DMA map call the DMA_ATTR_FORCE_COHERENT DMA
+attribute can be used to force a buffer to be mapped as IO coherent.
+This DMA attribute is only currently supported for arm64 stage 1 IOMMU
+mappings.
+
+DMA_ATTR_FORCE_NON_COHERENT
+---------------------------
+When passed to a DMA map call the DMA_ATTR_FORCE_NON_COHERENT DMA
+attribute can be used to force a buffer to not be mapped as IO
+coherent.
+The DMA_ATTR_FORCE_NON_COHERENT DMA attribute overrides the buffer IO
+coherency configuration set by making the device IO coherent.
+
+This DMA attribute is only currently supported for arm64 stage 1 IOMMU
+mappings.
diff --git a/arch/arm/boot/dts/qcom/dsi-panel-nt36850-truly-dualmipi-wqhd-cmd.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-nt36850-truly-dualmipi-wqhd-cmd.dtsi
new file mode 100644
index 000000000000..7774a28ff495
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/dsi-panel-nt36850-truly-dualmipi-wqhd-cmd.dtsi
@@ -0,0 +1,416 @@
+/* Copyright (c) 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+&mdss_mdp {
+ dsi_dual_nt36850_truly_cmd: qcom,mdss_dsi_nt36850_truly_wqhd_cmd{
+ qcom,mdss-dsi-panel-name =
+ "Dual nt36850 cmd mode dsi truly panel without DSC";
+ qcom,mdss-dsi-panel-type = "dsi_cmd_mode";
+ qcom,mdss-dsi-panel-framerate = <60>;
+ qcom,mdss-dsi-virtual-channel-id = <0>;
+ qcom,mdss-dsi-stream = <0>;
+ qcom,mdss-dsi-panel-width = <720>;
+ qcom,mdss-dsi-panel-height = <2560>;
+ qcom,mdss-dsi-h-front-porch = <120>;
+ qcom,mdss-dsi-h-back-porch = <140>;
+ qcom,mdss-dsi-h-pulse-width = <20>;
+ qcom,mdss-dsi-h-sync-skew = <0>;
+ qcom,mdss-dsi-v-back-porch = <20>;
+ qcom,mdss-dsi-v-front-porch = <8>;
+ qcom,mdss-dsi-v-pulse-width = <4>;
+ qcom,mdss-dsi-h-left-border = <0>;
+ qcom,mdss-dsi-h-right-border = <0>;
+ qcom,mdss-dsi-v-top-border = <0>;
+ qcom,mdss-dsi-v-bottom-border = <0>;
+ qcom,mdss-dsi-bpp = <24>;
+ qcom,mdss-dsi-color-order = "rgb_swap_rgb";
+ qcom,mdss-dsi-underflow-color = <0xff>;
+ qcom,mdss-dsi-border-color = <0>;
+ qcom,mdss-dsi-on-command = [
+ 15 01 00 00 00 00 02 ff 24
+ 15 01 00 00 00 00 02 fb 01
+ 15 01 00 00 00 00 02 00 19
+ 15 01 00 00 00 00 02 01 03
+ 15 01 00 00 00 00 02 02 04
+ 15 01 00 00 00 00 02 03 1b
+ 15 01 00 00 00 00 02 04 1d
+ 15 01 00 00 00 00 02 05 01
+ 15 01 00 00 00 00 02 06 0c
+ 15 01 00 00 00 00 02 07 0f
+ 15 01 00 00 00 00 02 08 1f
+ 15 01 00 00 00 00 02 09 00
+ 15 01 00 00 00 00 02 0a 00
+ 15 01 00 00 00 00 02 0b 13
+ 15 01 00 00 00 00 02 0c 16
+ 15 01 00 00 00 00 02 0d 14
+ 15 01 00 00 00 00 02 0e 15
+ 15 01 00 00 00 00 02 0f 00
+ 15 01 00 00 00 00 02 10 19
+ 15 01 00 00 00 00 02 11 03
+ 15 01 00 00 00 00 02 12 04
+ 15 01 00 00 00 00 02 13 1b
+ 15 01 00 00 00 00 02 14 1d
+ 15 01 00 00 00 00 02 15 01
+ 15 01 00 00 00 00 02 16 0c
+ 15 01 00 00 00 00 02 17 0f
+ 15 01 00 00 00 00 02 18 1f
+ 15 01 00 00 00 00 02 19 00
+ 15 01 00 00 00 00 02 1a 00
+ 15 01 00 00 00 00 02 1b 13
+ 15 01 00 00 00 00 02 1c 16
+ 15 01 00 00 00 00 02 1d 14
+ 15 01 00 00 00 00 02 1e 15
+ 15 01 00 00 00 00 02 1f 00
+ 15 01 00 00 00 00 02 21 01
+ 15 01 00 00 00 00 02 22 10
+ 15 01 00 00 00 00 02 23 28
+ 15 01 00 00 00 00 02 24 28
+ 15 01 00 00 00 00 02 25 5d
+ 15 01 00 00 00 00 02 26 28
+ 15 01 00 00 00 00 02 27 28
+ 15 01 00 00 00 00 02 29 d8
+ 15 01 00 00 00 00 02 2a 15
+ 15 01 00 00 00 00 02 2b 00
+ 15 01 00 00 00 00 02 2d 00
+ 15 01 00 00 00 00 02 2f 02
+ 15 01 00 00 00 00 02 30 02
+ 15 01 00 00 00 00 02 31 00
+ 15 01 00 00 00 00 02 32 23
+ 15 01 00 00 00 00 02 33 01
+ 15 01 00 00 00 00 02 34 03
+ 15 01 00 00 00 00 02 35 49
+ 15 01 00 00 00 00 02 36 00
+ 15 01 00 00 00 00 02 37 1d
+ 15 01 00 00 00 00 02 38 08
+ 15 01 00 00 00 00 02 39 03
+ 15 01 00 00 00 00 02 3a 49
+ 15 01 00 00 00 00 02 42 01
+ 15 01 00 00 00 00 02 43 8c
+ 15 01 00 00 00 00 02 44 a3
+ 15 01 00 00 00 00 02 48 8c
+ 15 01 00 00 00 00 02 49 a3
+ 15 01 00 00 00 00 02 5b 00
+ 15 01 00 00 00 00 02 5f 4d
+ 15 01 00 00 00 00 02 63 00
+ 15 01 00 00 00 00 02 67 04
+ 15 01 00 00 00 00 02 6e 10
+ 15 01 00 00 00 00 02 72 02
+ 15 01 00 00 00 00 02 73 00
+ 15 01 00 00 00 00 02 74 04
+ 15 01 00 00 00 00 02 75 1b
+ 15 01 00 00 00 00 02 76 05
+ 15 01 00 00 00 00 02 77 01
+ 15 01 00 00 00 00 02 78 00
+ 15 01 00 00 00 00 02 79 00
+ 15 01 00 00 00 00 02 7a 00
+ 15 01 00 00 00 00 02 7b 91
+ 15 01 00 00 00 00 02 7c da
+ 15 01 00 00 00 00 02 7d 10
+ 15 01 00 00 00 00 02 7e 04
+ 15 01 00 00 00 00 02 7f 1b
+ 15 01 00 00 00 00 02 80 00
+ 15 01 00 00 00 00 02 81 05
+ 15 01 00 00 00 00 02 82 01
+ 15 01 00 00 00 00 02 83 00
+ 15 01 00 00 00 00 02 84 05
+ 15 01 00 00 00 00 02 85 05
+ 15 01 00 00 00 00 02 86 1b
+ 15 01 00 00 00 00 02 87 1b
+ 15 01 00 00 00 00 02 88 1b
+ 15 01 00 00 00 00 02 89 1b
+ 15 01 00 00 00 00 02 8a 00
+ 15 01 00 00 00 00 02 8b f0
+ 15 01 00 00 00 00 02 8c 00
+ 15 01 00 00 00 00 02 8f 63
+ 15 01 00 00 00 00 02 90 51
+ 15 01 00 00 00 00 02 91 40
+ 15 01 00 00 00 00 02 92 51
+ 15 01 00 00 00 00 02 93 08
+ 15 01 00 00 00 00 02 94 08
+ 15 01 00 00 00 00 02 95 51
+ 15 01 00 00 00 00 02 96 51
+ 15 01 00 00 00 00 02 97 00
+ 15 01 00 00 00 00 02 98 00
+ 15 01 00 00 00 00 02 99 33
+ 15 01 00 00 00 00 02 9b ff
+ 15 01 00 00 00 00 02 9c 01
+ 15 01 00 00 00 00 02 9d 30
+ 15 01 00 00 00 00 02 a5 10
+ 15 01 00 00 00 00 02 a6 01
+ 15 01 00 00 00 00 02 a9 21
+ 15 01 00 00 00 00 02 b3 2a
+ 15 01 00 00 00 00 02 b4 da
+ 15 01 00 00 00 00 02 ba 83
+ 15 01 00 00 00 00 02 c4 24
+ 15 01 00 00 00 00 02 c5 aa
+ 15 01 00 00 00 00 02 c6 09
+ 15 01 00 00 00 00 02 c7 00
+ 15 01 00 00 00 00 02 c9 c0
+ 15 01 00 00 00 00 02 ca 04
+ 15 01 00 00 00 00 02 d5 3f
+ 15 01 00 00 00 00 02 d6 10
+ 15 01 00 00 00 00 02 d7 3f
+ 15 01 00 00 00 00 02 d8 10
+ 15 01 00 00 00 00 02 d9 ee
+ 15 01 00 00 00 00 02 da 49
+ 15 01 00 00 00 00 02 db 94
+ 15 01 00 00 00 00 02 e9 33
+ 15 01 00 00 00 00 02 eb 28
+ 15 01 00 00 00 00 02 ec 00
+ 15 01 00 00 00 00 02 ee 00
+ 15 01 00 00 00 00 02 ef 06
+ 15 01 00 00 00 00 02 f0 01
+ 15 01 00 00 00 00 02 f1 01
+ 15 01 00 00 00 00 02 f2 0d
+ 15 01 00 00 00 00 02 f3 48
+ 15 01 00 00 00 00 02 f6 00
+ 15 01 00 00 00 00 02 f7 00
+ 15 01 00 00 00 00 02 f8 00
+ 15 01 00 00 00 00 02 f9 00
+ 15 01 00 00 00 00 02 ff 26
+ 15 01 00 00 00 00 02 fb 01
+ 15 01 00 00 00 00 02 00 ab
+ 15 01 00 00 00 00 02 01 00
+ 15 01 00 00 00 00 02 02 80
+ 15 01 00 00 00 00 02 03 08
+ 15 01 00 00 00 00 02 04 01
+ 15 01 00 00 00 00 02 05 32
+ 15 01 00 00 00 00 02 06 4c
+ 15 01 00 00 00 00 02 07 26
+ 15 01 00 00 00 00 02 08 09
+ 15 01 00 00 00 00 02 09 02
+ 15 01 00 00 00 00 02 0a 32
+ 15 01 00 00 00 00 02 0b 55
+ 15 01 00 00 00 00 02 0c 14
+ 15 01 00 00 00 00 02 0d 28
+ 15 01 00 00 00 00 02 0e 00
+ 15 01 00 00 00 00 02 0f 00
+ 15 01 00 00 00 00 02 10 00
+ 15 01 00 00 00 00 02 11 22
+ 15 01 00 00 00 00 02 12 0a
+ 15 01 00 00 00 00 02 13 20
+ 15 01 00 00 00 00 02 14 06
+ 15 01 00 00 00 00 02 15 00
+ 15 01 00 00 00 00 02 16 40
+ 15 01 00 00 00 00 02 19 43
+ 15 01 00 00 00 00 02 1a 03
+ 15 01 00 00 00 00 02 1b 25
+ 15 01 00 00 00 00 02 1c 11
+ 15 01 00 00 00 00 02 1d 00
+ 15 01 00 00 00 00 02 1e 80
+ 15 01 00 00 00 00 02 1f 00
+ 15 01 00 00 00 00 02 20 00
+ 15 01 00 00 00 00 02 21 03
+ 15 01 00 00 00 00 02 22 22
+ 15 01 00 00 00 00 02 23 25
+ 15 01 00 00 00 00 02 24 00
+ 15 01 00 00 00 00 02 25 a7
+ 15 01 00 00 00 00 02 26 00
+ 15 01 00 00 00 00 02 27 a5
+ 15 01 00 00 00 00 02 28 06
+ 15 01 00 00 00 00 02 29 85
+ 15 01 00 00 00 00 02 2a 3f
+ 15 01 00 00 00 00 02 2b 97
+ 15 01 00 00 00 00 02 2f 25
+ 15 01 00 00 00 00 02 30 26
+ 15 01 00 00 00 00 02 31 41
+ 15 01 00 00 00 00 02 32 04
+ 15 01 00 00 00 00 02 33 04
+ 15 01 00 00 00 00 02 34 2b
+ 15 01 00 00 00 00 02 35 00
+ 15 01 00 00 00 00 02 36 00
+ 15 01 00 00 00 00 02 37 c8
+ 15 01 00 00 00 00 02 38 26
+ 15 01 00 00 00 00 02 39 25
+ 15 01 00 00 00 00 02 3a 26
+ 15 01 00 00 00 00 02 3f eb
+ 15 01 00 00 00 00 02 41 21
+ 15 01 00 00 00 00 02 42 03
+ 15 01 00 00 00 00 02 43 00
+ 15 01 00 00 00 00 02 44 11
+ 15 01 00 00 00 00 02 45 00
+ 15 01 00 00 00 00 02 46 00
+ 15 01 00 00 00 00 02 47 00
+ 15 01 00 00 00 00 02 48 00
+ 15 01 00 00 00 00 02 49 03
+ 15 01 00 00 00 00 02 4a 00
+ 15 01 00 00 00 00 02 4b 00
+ 15 01 00 00 00 00 02 4c 01
+ 15 01 00 00 00 00 02 4d 4e
+ 15 01 00 00 00 00 02 4e 01
+ 15 01 00 00 00 00 02 4f 4c
+ 15 01 00 00 00 00 02 50 0d
+ 15 01 00 00 00 00 02 51 0e
+ 15 01 00 00 00 00 02 52 23
+ 15 01 00 00 00 00 02 53 97
+ 15 01 00 00 00 00 02 54 4b
+ 15 01 00 00 00 00 02 55 4c
+ 15 01 00 00 00 00 02 56 20
+ 15 01 00 00 00 00 02 58 04
+ 15 01 00 00 00 00 02 59 04
+ 15 01 00 00 00 00 02 5a 09
+ 15 01 00 00 00 00 02 5b 00
+ 15 01 00 00 00 00 02 5c 00
+ 15 01 00 00 00 00 02 5d c8
+ 15 01 00 00 00 00 02 5e 4c
+ 15 01 00 00 00 00 02 5f 4b
+ 15 01 00 00 00 00 02 60 00
+ 15 01 00 00 00 00 02 80 2b
+ 15 01 00 00 00 00 02 81 43
+ 15 01 00 00 00 00 02 82 03
+ 15 01 00 00 00 00 02 83 25
+ 15 01 00 00 00 00 02 84 11
+ 15 01 00 00 00 00 02 85 00
+ 15 01 00 00 00 00 02 86 80
+ 15 01 00 00 00 00 02 87 00
+ 15 01 00 00 00 00 02 88 00
+ 15 01 00 00 00 00 02 89 03
+ 15 01 00 00 00 00 02 8a 22
+ 15 01 00 00 00 00 02 8b 25
+ 15 01 00 00 00 00 02 8c 00
+ 15 01 00 00 00 00 02 8d a4
+ 15 01 00 00 00 00 02 8e 00
+ 15 01 00 00 00 00 02 8f a2
+ 15 01 00 00 00 00 02 90 06
+ 15 01 00 00 00 00 02 91 63
+ 15 01 00 00 00 00 02 92 30
+ 15 01 00 00 00 00 02 93 97
+ 15 01 00 00 00 00 02 94 25
+ 15 01 00 00 00 00 02 95 26
+ 15 01 00 00 00 00 02 96 41
+ 15 01 00 00 00 00 02 97 04
+ 15 01 00 00 00 00 02 98 04
+ 15 01 00 00 00 00 02 99 f0
+ 15 01 00 00 00 00 02 9a 00
+ 15 01 00 00 00 00 02 9b 00
+ 15 01 00 00 00 00 02 9c c8
+ 15 01 00 00 00 00 02 9d 50
+ 15 01 00 00 00 00 02 9e 26
+ 15 01 00 00 00 00 02 9f 25
+ 15 01 00 00 00 00 02 a0 26
+ 15 01 00 00 00 00 02 a2 00
+ 15 01 00 00 00 00 02 a3 33
+ 15 01 00 00 00 00 02 a5 40
+ 15 01 00 00 00 00 02 a6 40
+ 15 01 00 00 00 00 02 ac 91
+ 15 01 00 00 00 00 02 ad 66
+ 15 01 00 00 00 00 02 ae 66
+ 15 01 00 00 00 00 02 b1 40
+ 15 01 00 00 00 00 02 b2 40
+ 15 01 00 00 00 00 02 b4 40
+ 15 01 00 00 00 00 02 b5 40
+ 15 01 00 00 00 00 02 b7 40
+ 15 01 00 00 00 00 02 b8 40
+ 15 01 00 00 00 00 02 ba 22
+ 15 01 00 00 00 00 02 bb 00
+ 15 01 00 00 00 00 02 c2 01
+ 15 01 00 00 00 00 02 c3 01
+ 15 01 00 00 00 00 02 c4 01
+ 15 01 00 00 00 00 02 c5 01
+ 15 01 00 00 00 00 02 c6 01
+ 15 01 00 00 00 00 02 c8 00
+ 15 01 00 00 00 00 02 c9 00
+ 15 01 00 00 00 00 02 ca 00
+ 15 01 00 00 00 00 02 cd 00
+ 15 01 00 00 00 00 02 ce 00
+ 15 01 00 00 00 00 02 d6 04
+ 15 01 00 00 00 00 02 d7 00
+ 15 01 00 00 00 00 02 d8 0d
+ 15 01 00 00 00 00 02 d9 00
+ 15 01 00 00 00 00 02 da 00
+ 15 01 00 00 00 00 02 db 00
+ 15 01 00 00 00 00 02 dc 00
+ 15 01 00 00 00 00 02 dd 00
+ 15 01 00 00 00 00 02 de 00
+ 15 01 00 00 00 00 02 df 01
+ 15 01 00 00 00 00 02 e0 00
+ 15 01 00 00 00 00 02 e1 00
+ 15 01 00 00 00 00 02 e2 19
+ 15 01 00 00 00 00 02 e3 04
+ 15 01 00 00 00 00 02 e4 00
+ 15 01 00 00 00 00 02 e5 04
+ 15 01 00 00 00 00 02 e6 00
+ 15 01 00 00 00 00 02 e7 12
+ 15 01 00 00 00 00 02 e8 00
+ 15 01 00 00 00 00 02 e9 50
+ 15 01 00 00 00 00 02 ea 10
+ 15 01 00 00 00 00 02 eb 02
+ 15 01 00 00 00 00 02 ff 27
+ 15 01 00 00 00 00 02 fb 01
+ 15 01 00 00 00 00 02 ff 28
+ 15 01 00 00 00 00 02 fb 01
+ 15 01 00 00 00 00 02 60 0a
+ 15 01 00 00 00 00 02 63 32
+ 15 01 00 00 00 00 02 64 01
+ 15 01 00 00 00 00 02 68 da
+ 15 01 00 00 00 00 02 69 00
+ 15 01 00 00 00 00 02 ff 29
+ 15 01 00 00 00 00 02 fb 01
+ 15 01 00 00 00 00 02 60 0a
+ 15 01 00 00 00 00 02 63 32
+ 15 01 00 00 00 00 02 64 01
+ 15 01 00 00 00 00 02 68 da
+ 15 01 00 00 00 00 02 69 00
+ 15 01 00 00 00 00 02 ff e0
+ 15 01 00 00 00 00 02 fb 01
+ 15 01 00 00 00 00 02 35 40
+ 15 01 00 00 00 00 02 36 40
+ 15 01 00 00 00 00 02 37 00
+ 15 01 00 00 00 00 02 89 c6
+ 15 01 00 00 00 00 02 ff f0
+ 15 01 00 00 00 00 02 fb 01
+ 15 01 00 00 00 00 02 ea 40
+ 15 01 00 00 00 00 02 ff 10
+ 15 01 00 00 00 00 02 36 00
+ 15 01 00 00 00 00 02 35 00
+ 39 01 00 00 00 00 03 44 03 e8
+ 15 01 00 00 00 00 02 51 ff
+ 15 01 00 00 00 00 02 53 2c
+ 15 01 00 00 00 00 02 55 01
+ 05 01 00 00 0a 00 02 20 00
+ 15 01 00 00 00 00 02 bb 10
+ 05 01 00 00 78 00 02 11 00
+ 05 01 00 00 14 00 02 29 00];
+ qcom,mdss-dsi-off-command = [05 01 00 00 14 00 02 28 00
+ 05 01 00 00 78 00 02 10 00];
+ qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+ qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
+ qcom,mdss-dsi-h-sync-pulse = <0>;
+ qcom,mdss-dsi-traffic-mode = "non_burst_sync_event";
+ qcom,mdss-dsi-lane-map = "lane_map_0123";
+ qcom,mdss-dsi-bllp-eof-power-mode;
+ qcom,mdss-dsi-bllp-power-mode;
+ qcom,mdss-dsi-tx-eot-append;
+ qcom,cmd-sync-wait-broadcast;
+ qcom,mdss-dsi-lane-0-state;
+ qcom,mdss-dsi-lane-1-state;
+ qcom,mdss-dsi-lane-2-state;
+ qcom,mdss-dsi-lane-3-state;
+ qcom,mdss-dsi-wr-mem-start = <0x2c>;
+ qcom,mdss-dsi-wr-mem-continue = <0x3c>;
+ qcom,mdss-dsi-te-pin-select = <1>;
+ qcom,mdss-dsi-te-dcs-command = <1>;
+ qcom,mdss-dsi-te-check-enable;
+ qcom,mdss-dsi-te-using-te-pin;
+ qcom,mdss-dsi-panel-timings =
+ [da 34 24 00 64 68 28 38 2a 03 04 00];
+ qcom,mdss-dsi-t-clk-pre = <0x29>;
+ qcom,mdss-dsi-t-clk-post = <0x03>;
+ qcom,mdss-dsi-dma-trigger = "trigger_sw";
+ qcom,mdss-dsi-mdp-trigger = "none";
+ qcom,mdss-dsi-lp11-init;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-reset-sequence = <1 10>, <0 10>, <1 10>;
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/msm-pm660.dtsi b/arch/arm/boot/dts/qcom/msm-pm660.dtsi
index 3674e2e5570b..e8e773a33622 100644
--- a/arch/arm/boot/dts/qcom/msm-pm660.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-pm660.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, 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
@@ -585,8 +585,8 @@
pm660_haptics: qcom,haptic@c000 {
compatible = "qcom,qpnp-haptic";
reg = <0xc000 0x100>;
- interrupts = <0x1 0xc0 0x0>,
- <0x1 0xc0 0x1>;
+ interrupts = <0x1 0xc0 0x0 IRQ_TYPE_NONE>,
+ <0x1 0xc0 0x1 IRQ_TYPE_NONE>;
interrupt-names = "sc-irq", "play-irq";
qcom,actuator-type = "lra";
qcom,play-mode = "direct";
diff --git a/arch/arm/boot/dts/qcom/msm-pm660l-rpm-regulator.dtsi b/arch/arm/boot/dts/qcom/msm-pm660l-rpm-regulator.dtsi
index b10f8e559090..83235317fa02 100644
--- a/arch/arm/boot/dts/qcom/msm-pm660l-rpm-regulator.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-pm660l-rpm-regulator.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, 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
@@ -193,7 +193,7 @@
rpm-regulator-ldob9 {
compatible = "qcom,rpm-smd-regulator-resource";
- qcom,resource-name = "rwsc";
+ qcom,resource-name = "rwlc";
qcom,resource-id = <0>;
qcom,regulator-type = <0>;
status = "disabled";
@@ -208,7 +208,7 @@
rpm-regulator-ldob10 {
compatible = "qcom,rpm-smd-regulator-resource";
- qcom,resource-name = "rwsm";
+ qcom,resource-name = "rwlm";
qcom,resource-id = <0>;
qcom,regulator-type = <0>;
status = "disabled";
diff --git a/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi b/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi
index 99f3f58cc20e..b1880c076e1c 100644
--- a/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, 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
@@ -618,8 +618,8 @@
status = "disabled";
compatible = "qcom,qpnp-haptic";
reg = <0xc000 0x100>;
- interrupts = <0x3 0xc0 0x0>,
- <0x3 0xc0 0x1>;
+ interrupts = <0x3 0xc0 0x0 IRQ_TYPE_NONE>,
+ <0x3 0xc0 0x1 IRQ_TYPE_NONE>;
interrupt-names = "sc-irq", "play-irq";
qcom,actuator-type = "lra";
qcom,play-mode = "direct";
diff --git a/arch/arm/boot/dts/qcom/msm8998-camera-sensor-cdp.dtsi b/arch/arm/boot/dts/qcom/msm8998-camera-sensor-cdp.dtsi
index 61fc31a17e52..2cb08e1709a5 100644
--- a/arch/arm/boot/dts/qcom/msm8998-camera-sensor-cdp.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8998-camera-sensor-cdp.dtsi
@@ -254,6 +254,7 @@
qcom,csid-sd-index = <1>;
qcom,mount-angle = <90>;
qcom,eeprom-src = <&eeprom1>;
+ qcom,actuator-src = <&actuator1>;
cam_vdig-supply = <&pm8998_lvs1>;
cam_vio-supply = <&pm8998_lvs1>;
cam_vana-supply = <&pmi8998_bob>;
diff --git a/arch/arm/boot/dts/qcom/msm8998-camera-sensor-mtp.dtsi b/arch/arm/boot/dts/qcom/msm8998-camera-sensor-mtp.dtsi
index 0bd9ab40e8f1..0a41383ba874 100644
--- a/arch/arm/boot/dts/qcom/msm8998-camera-sensor-mtp.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8998-camera-sensor-mtp.dtsi
@@ -254,6 +254,7 @@
qcom,csid-sd-index = <1>;
qcom,mount-angle = <90>;
qcom,eeprom-src = <&eeprom1>;
+ qcom,actuator-src = <&actuator1>;
cam_vdig-supply = <&pm8998_lvs1>;
cam_vio-supply = <&pm8998_lvs1>;
cam_vana-supply = <&pmi8998_bob>;
diff --git a/arch/arm/boot/dts/qcom/msm8998-interposer-pm660.dtsi b/arch/arm/boot/dts/qcom/msm8998-interposer-pm660.dtsi
index a13475085e58..c9522154ae7d 100644
--- a/arch/arm/boot/dts/qcom/msm8998-interposer-pm660.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8998-interposer-pm660.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, 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
@@ -245,3 +245,13 @@
/delete-node/cpr4-ctrl@05061000;
/delete-node/regulator@01fcf004;
};
+
+&rpm_bus {
+ rpm-regulator-ldob9 {
+ qcom,resource-name = "rwsc";
+ };
+
+ rpm-regulator-ldob10 {
+ qcom,resource-name = "rwsm";
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/msm8998-v2.dtsi b/arch/arm/boot/dts/qcom/msm8998-v2.dtsi
index 99975877658d..2408ad515b61 100644
--- a/arch/arm/boot/dts/qcom/msm8998-v2.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8998-v2.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016 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
@@ -298,6 +298,7 @@
&devfreq_memlat_0 {
qcom,core-dev-table =
+ < 300000 1525 >,
< 595200 3143 >,
< 1324800 4173 >,
< 1555200 5859 >,
@@ -1194,7 +1195,7 @@
&msm_gpu {
/* Updated chip ID */
qcom,chipid = <0x05040001>;
- qcom,initial-pwrlevel = <5>;
+ qcom,initial-pwrlevel = <6>;
qcom,gpu-pwrlevels {
#address-cells = <1>;
@@ -1204,23 +1205,23 @@
qcom,gpu-pwrlevel@0 {
reg = <0>;
- qcom,gpu-freq = <670000000>;
+ qcom,gpu-freq = <710000000>;
qcom,bus-freq = <12>;
- qcom,bus-min = <11>;
+ qcom,bus-min = <12>;
qcom,bus-max = <12>;
};
qcom,gpu-pwrlevel@1 {
reg = <1>;
- qcom,gpu-freq = <596000000>;
- qcom,bus-freq = <11>;
- qcom,bus-min = <9>;
+ qcom,gpu-freq = <670000000>;
+ qcom,bus-freq = <12>;
+ qcom,bus-min = <11>;
qcom,bus-max = <12>;
};
qcom,gpu-pwrlevel@2 {
reg = <2>;
- qcom,gpu-freq = <515000000>;
+ qcom,gpu-freq = <596000000>;
qcom,bus-freq = <11>;
qcom,bus-min = <9>;
qcom,bus-max = <12>;
@@ -1228,30 +1229,38 @@
qcom,gpu-pwrlevel@3 {
reg = <3>;
+ qcom,gpu-freq = <515000000>;
+ qcom,bus-freq = <11>;
+ qcom,bus-min = <9>;
+ qcom,bus-max = <12>;
+ };
+
+ qcom,gpu-pwrlevel@4 {
+ reg = <4>;
qcom,gpu-freq = <414000000>;
qcom,bus-freq = <9>;
qcom,bus-min = <8>;
qcom,bus-max = <11>;
};
- qcom,gpu-pwrlevel@4 {
- reg = <4>;
+ qcom,gpu-pwrlevel@5 {
+ reg = <5>;
qcom,gpu-freq = <342000000>;
qcom,bus-freq = <8>;
qcom,bus-min = <5>;
qcom,bus-max = <9>;
};
- qcom,gpu-pwrlevel@5 {
- reg = <5>;
+ qcom,gpu-pwrlevel@6 {
+ reg = <6>;
qcom,gpu-freq = <257000000>;
qcom,bus-freq = <5>;
qcom,bus-min = <3>;
qcom,bus-max = <8>;
};
- qcom,gpu-pwrlevel@6 {
- reg = <6>;
+ qcom,gpu-pwrlevel@7 {
+ reg = <7>;
qcom,gpu-freq = <27000000>;
qcom,bus-freq = <0>;
qcom,bus-min = <0>;
diff --git a/arch/arm/boot/dts/qcom/sdm630-mtp.dtsi b/arch/arm/boot/dts/qcom/sdm630-mtp.dtsi
index 6779d80d76cf..16d6c1bf9500 100644
--- a/arch/arm/boot/dts/qcom/sdm630-mtp.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630-mtp.dtsi
@@ -20,5 +20,9 @@
pinctrl-0 = <&uart_console_active>;
};
+&mem_client_3_size {
+ qcom,peripheral-size = <0x500000>;
+};
+
&soc {
};
diff --git a/arch/arm/boot/dts/qcom/sdm660-qrd.dts b/arch/arm/boot/dts/qcom/sdm660-qrd.dts
index 29fc0d776fd0..a8fde35ba49c 100644
--- a/arch/arm/boot/dts/qcom/sdm660-qrd.dts
+++ b/arch/arm/boot/dts/qcom/sdm660-qrd.dts
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, 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
@@ -23,3 +23,7 @@
qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
<0x0001001b 0x0201011a 0x0 0x0>;
};
+
+&pm660l_wled {
+ qcom,led-strings-list = [00 01];
+};
diff --git a/arch/arm/boot/dts/qcom/sdm660-qrd.dtsi b/arch/arm/boot/dts/qcom/sdm660-qrd.dtsi
index 2b53a88f4bf5..f3908ce512af 100644
--- a/arch/arm/boot/dts/qcom/sdm660-qrd.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-qrd.dtsi
@@ -15,6 +15,10 @@
/ {
};
+&blsp2_uart1_hs {
+ status = "ok";
+};
+
&uartblsp1dm1 {
status = "ok";
pinctrl-names = "default";
@@ -103,3 +107,46 @@
&soc {
};
+
+&pm660l_gpios {
+ /* GPIO 7 for VOL_UP */
+ gpio@c600 {
+ status = "ok";
+ qcom,mode = <0>;
+ qcom,pull = <0>;
+ qcom,vin-sel = <0>;
+ qcom,src-sel = <0>;
+ qcom,out-strength = <1>;
+ };
+};
+
+&soc {
+ gpio_keys {
+ compatible = "gpio-keys";
+ input-name = "gpio-keys";
+ status = "ok";
+
+ vol_up {
+ label = "volume_up";
+ gpios = <&pm660l_gpios 7 0x1>;
+ linux,input-type = <1>;
+ linux,code = <115>;
+ gpio-key,wakeup;
+ debounce-interval = <15>;
+ };
+ };
+};
+
+/ {
+ qrd_batterydata: qcom,battery-data {
+ qcom,batt-id-range-pct = <15>;
+
+ #include "fg-gen3-batterydata-qrd-skuk-4v4-3000mah.dtsi"
+ };
+};
+
+&pm660_fg {
+ qcom,battery-data = <&qrd_batterydata>;
+ qcom,fg-jeita-thresholds = <0 5 55 55>;
+ qcom,fg-cutoff-voltage = <3700>;
+};
diff --git a/arch/arm/boot/dts/qcom/sdm660-vidc.dtsi b/arch/arm/boot/dts/qcom/sdm660-vidc.dtsi
index 10cf4de2a8e0..ae3f1949115a 100644
--- a/arch/arm/boot/dts/qcom/sdm660-vidc.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-vidc.dtsi
@@ -26,6 +26,7 @@
qcom,hfi = "venus";
qcom,hfi-version = "3xx";
qcom,firmware-name = "venus";
+ qcom,never-unload-fw;
qcom,sw-power-collapse;
qcom,reg-presets =
<0x80010 0x001f001f>,
diff --git a/arch/arm/boot/dts/qcom/sdm660.dtsi b/arch/arm/boot/dts/qcom/sdm660.dtsi
index 563bd00120d6..54aa729352a3 100644
--- a/arch/arm/boot/dts/qcom/sdm660.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660.dtsi
@@ -1094,7 +1094,8 @@
reg-names = "osm", "pwrcl_pll", "perfcl_pll",
"apcs_common", "perfcl_efuse";
- /* ToDo: Add power and perf supply rails */
+ vdd-pwrcl-supply = <&apc0_pwrcl_vreg>;
+ vdd-perfcl-supply = <&apc1_perfcl_vreg>;
interrupts = <GIC_SPI 35 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 36 IRQ_TYPE_EDGE_RISING>;
@@ -1160,19 +1161,6 @@
qcom,wfx-fsm-en;
qcom,pc-fsm-en;
- qcom,pwrcl-apcs-mem-acc-cfg =
- <0x179d1360 0x179d1364 0x179d1364>;
- qcom,perfcl-apcs-mem-acc-cfg =
- <0x179d1368 0x179d136C 0x179d1370>;
- qcom,pwrcl-apcs-mem-acc-val =
- <0x00000000 0x80000000 0x80000000>,
- <0x00000000 0x00000000 0x00000000>,
- <0x00000000 0x00000001 0x00000001>;
- qcom,perfcl-apcs-mem-acc-val =
- <0x00000000 0x00000000 0x80000000>,
- <0x00000000 0x00000000 0x00000000>,
- <0x00000000 0x00000000 0x00000001>;
-
clock-names = "aux_clk", "xo_a";
clocks = <&clock_gcc HMSS_GPLL0_CLK_SRC>,
<&clock_rpmcc RPM_XO_A_CLK_SRC>;
diff --git a/arch/arm/configs/msmcortex_defconfig b/arch/arm/configs/msmcortex_defconfig
index c5c7d924aab6..9cf5a15e80eb 100644
--- a/arch/arm/configs/msmcortex_defconfig
+++ b/arch/arm/configs/msmcortex_defconfig
@@ -254,7 +254,6 @@ CONFIG_PPPOPNS=y
CONFIG_WCNSS_MEM_PRE_ALLOC=y
CONFIG_ATH_CARDS=y
CONFIG_CLD_LL_CORE=y
-CONFIG_QPNP_POWER_ON=y
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_KEYRESET=y
CONFIG_KEYBOARD_GPIO=y
@@ -266,6 +265,7 @@ CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v21=y
CONFIG_SECURE_TOUCH=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_HBTP_INPUT=y
+CONFIG_INPUT_QPNP_POWER_ON=y
CONFIG_INPUT_KEYCHORD=y
CONFIG_INPUT_UINPUT=y
CONFIG_INPUT_GPIO=y
diff --git a/arch/arm/configs/sdm660-perf_defconfig b/arch/arm/configs/sdm660-perf_defconfig
index 879b6ff88423..d555a1b179d8 100644
--- a/arch/arm/configs/sdm660-perf_defconfig
+++ b/arch/arm/configs/sdm660-perf_defconfig
@@ -280,7 +280,6 @@ CONFIG_USB_USBNET=y
CONFIG_WCNSS_MEM_PRE_ALLOC=y
CONFIG_ATH_CARDS=y
CONFIG_CLD_LL_CORE=y
-CONFIG_QPNP_POWER_ON=y
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_KEYRESET=y
CONFIG_KEYBOARD_GPIO=y
@@ -292,6 +291,7 @@ CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v21=y
CONFIG_SECURE_TOUCH=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_HBTP_INPUT=y
+CONFIG_INPUT_QPNP_POWER_ON=y
CONFIG_INPUT_KEYCHORD=y
CONFIG_INPUT_UINPUT=y
CONFIG_INPUT_GPIO=y
diff --git a/arch/arm/configs/sdm660_defconfig b/arch/arm/configs/sdm660_defconfig
index 10b8666a2d40..2c94274b0637 100644
--- a/arch/arm/configs/sdm660_defconfig
+++ b/arch/arm/configs/sdm660_defconfig
@@ -279,7 +279,6 @@ CONFIG_USB_USBNET=y
CONFIG_WCNSS_MEM_PRE_ALLOC=y
CONFIG_ATH_CARDS=y
CONFIG_CLD_LL_CORE=y
-CONFIG_QPNP_POWER_ON=y
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_KEYRESET=y
CONFIG_KEYBOARD_GPIO=y
@@ -291,6 +290,7 @@ CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v21=y
CONFIG_SECURE_TOUCH=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_HBTP_INPUT=y
+CONFIG_INPUT_QPNP_POWER_ON=y
CONFIG_INPUT_KEYCHORD=y
CONFIG_INPUT_UINPUT=y
CONFIG_INPUT_GPIO=y
diff --git a/arch/arm64/configs/msm-perf_defconfig b/arch/arm64/configs/msm-perf_defconfig
index 08dccf8e5022..07e413e31234 100644
--- a/arch/arm64/configs/msm-perf_defconfig
+++ b/arch/arm64/configs/msm-perf_defconfig
@@ -279,7 +279,6 @@ CONFIG_WIL6210=m
CONFIG_CNSS=y
CONFIG_CLD_LL_CORE=y
CONFIG_BUS_AUTO_SUSPEND=y
-CONFIG_QPNP_POWER_ON=y
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_KEYRESET=y
CONFIG_KEYBOARD_GPIO=y
@@ -293,6 +292,7 @@ CONFIG_SECURE_TOUCH=y
CONFIG_TOUCHSCREEN_GEN_VKEYS=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_HBTP_INPUT=y
+CONFIG_INPUT_QPNP_POWER_ON=y
CONFIG_INPUT_KEYCHORD=y
CONFIG_INPUT_UINPUT=y
CONFIG_INPUT_GPIO=y
diff --git a/arch/arm64/configs/msm_defconfig b/arch/arm64/configs/msm_defconfig
index 4620e74de5bc..76d949319dfa 100644
--- a/arch/arm64/configs/msm_defconfig
+++ b/arch/arm64/configs/msm_defconfig
@@ -265,7 +265,6 @@ CONFIG_WIL6210=m
CONFIG_CNSS=y
CONFIG_CLD_LL_CORE=y
CONFIG_BUS_AUTO_SUSPEND=y
-CONFIG_QPNP_POWER_ON=y
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_KEYRESET=y
CONFIG_KEYBOARD_GPIO=y
@@ -280,6 +279,7 @@ CONFIG_SECURE_TOUCH=y
CONFIG_TOUCHSCREEN_GEN_VKEYS=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_HBTP_INPUT=y
+CONFIG_INPUT_QPNP_POWER_ON=y
CONFIG_INPUT_UINPUT=y
CONFIG_INPUT_GPIO=y
# CONFIG_SERIO_SERPORT is not set
diff --git a/arch/arm64/configs/msmcortex-perf_defconfig b/arch/arm64/configs/msmcortex-perf_defconfig
index 71d067b27ddd..07d24ea6b707 100644
--- a/arch/arm64/configs/msmcortex-perf_defconfig
+++ b/arch/arm64/configs/msmcortex-perf_defconfig
@@ -275,7 +275,6 @@ CONFIG_WCNSS_MEM_PRE_ALLOC=y
CONFIG_ATH_CARDS=y
CONFIG_WIL6210=m
CONFIG_CLD_LL_CORE=y
-CONFIG_QPNP_POWER_ON=y
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_KEYRESET=y
CONFIG_KEYBOARD_GPIO=y
@@ -286,6 +285,7 @@ CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v21=y
CONFIG_SECURE_TOUCH=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_HBTP_INPUT=y
+CONFIG_INPUT_QPNP_POWER_ON=y
CONFIG_INPUT_UINPUT=y
# CONFIG_SERIO_SERPORT is not set
# CONFIG_VT is not set
diff --git a/arch/arm64/configs/msmcortex_defconfig b/arch/arm64/configs/msmcortex_defconfig
index 02b9e08955f6..25b5c206e1ae 100644
--- a/arch/arm64/configs/msmcortex_defconfig
+++ b/arch/arm64/configs/msmcortex_defconfig
@@ -275,7 +275,6 @@ CONFIG_WCNSS_MEM_PRE_ALLOC=y
CONFIG_ATH_CARDS=y
CONFIG_WIL6210=m
CONFIG_CLD_LL_CORE=y
-CONFIG_QPNP_POWER_ON=y
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_KEYRESET=y
CONFIG_KEYBOARD_GPIO=y
@@ -287,6 +286,7 @@ CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v21=y
CONFIG_SECURE_TOUCH=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_HBTP_INPUT=y
+CONFIG_INPUT_QPNP_POWER_ON=y
CONFIG_INPUT_KEYCHORD=y
CONFIG_INPUT_UINPUT=y
CONFIG_INPUT_GPIO=y
diff --git a/arch/arm64/configs/sdm660-perf_defconfig b/arch/arm64/configs/sdm660-perf_defconfig
index f15fd895e65c..7d203e49d595 100644
--- a/arch/arm64/configs/sdm660-perf_defconfig
+++ b/arch/arm64/configs/sdm660-perf_defconfig
@@ -278,7 +278,6 @@ CONFIG_WCNSS_MEM_PRE_ALLOC=y
CONFIG_ATH_CARDS=y
CONFIG_WIL6210=m
CONFIG_CLD_LL_CORE=y
-CONFIG_QPNP_POWER_ON=y
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_KEYRESET=y
CONFIG_KEYBOARD_GPIO=y
@@ -289,6 +288,7 @@ CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v21=y
CONFIG_SECURE_TOUCH=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_HBTP_INPUT=y
+CONFIG_INPUT_QPNP_POWER_ON=y
CONFIG_INPUT_UINPUT=y
# CONFIG_SERIO_SERPORT is not set
# CONFIG_VT is not set
@@ -397,9 +397,9 @@ CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE=y
CONFIG_MSMB_JPEG=y
CONFIG_MSM_FD=y
CONFIG_MSM_JPEGDMA=y
-CONFIG_MSM_VIDC_V4L2=m
-CONFIG_MSM_VIDC_VMEM=m
-CONFIG_MSM_VIDC_GOVERNORS=m
+CONFIG_MSM_VIDC_V4L2=y
+CONFIG_MSM_VIDC_VMEM=y
+CONFIG_MSM_VIDC_GOVERNORS=y
CONFIG_MSM_SDE_ROTATOR=y
CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
CONFIG_QCOM_KGSL=y
diff --git a/arch/arm64/configs/sdm660_defconfig b/arch/arm64/configs/sdm660_defconfig
index b52a672a5b5e..c295ba7e0d70 100644
--- a/arch/arm64/configs/sdm660_defconfig
+++ b/arch/arm64/configs/sdm660_defconfig
@@ -278,7 +278,6 @@ CONFIG_WCNSS_MEM_PRE_ALLOC=y
CONFIG_ATH_CARDS=y
CONFIG_WIL6210=m
CONFIG_CLD_LL_CORE=y
-CONFIG_QPNP_POWER_ON=y
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_KEYRESET=y
CONFIG_KEYBOARD_GPIO=y
@@ -290,6 +289,7 @@ CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v21=y
CONFIG_SECURE_TOUCH=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_HBTP_INPUT=y
+CONFIG_INPUT_QPNP_POWER_ON=y
CONFIG_INPUT_KEYCHORD=y
CONFIG_INPUT_UINPUT=y
CONFIG_INPUT_GPIO=y
@@ -399,9 +399,9 @@ CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE=y
CONFIG_MSMB_JPEG=y
CONFIG_MSM_FD=y
CONFIG_MSM_JPEGDMA=y
-CONFIG_MSM_VIDC_V4L2=m
-CONFIG_MSM_VIDC_VMEM=m
-CONFIG_MSM_VIDC_GOVERNORS=m
+CONFIG_MSM_VIDC_V4L2=y
+CONFIG_MSM_VIDC_VMEM=y
+CONFIG_MSM_VIDC_GOVERNORS=y
CONFIG_MSM_SDE_ROTATOR=y
CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
CONFIG_QCOM_KGSL=y
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 7326be306618..68cd3bb8eb89 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -39,6 +39,7 @@
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
#include <asm/edac.h>
+#include <soc/qcom/scm.h>
#include <trace/events/exception.h>
@@ -408,6 +409,23 @@ no_context:
return 0;
}
+static int do_tlb_conf_fault(unsigned long addr,
+ unsigned int esr,
+ struct pt_regs *regs)
+{
+#define SCM_TLB_CONFLICT_CMD 0x1B
+ struct scm_desc desc = {
+ .args[0] = addr,
+ .arginfo = SCM_ARGS(1),
+ };
+
+ if (scm_call2_atomic(SCM_SIP_FNID(SCM_SVC_MP, SCM_TLB_CONFLICT_CMD),
+ &desc))
+ return 1;
+
+ return 0;
+}
+
/*
* First Level Translation Fault Handler
*
@@ -499,7 +517,7 @@ static struct fault_info {
{ do_bad, SIGBUS, 0, "unknown 45" },
{ do_bad, SIGBUS, 0, "unknown 46" },
{ do_bad, SIGBUS, 0, "unknown 47" },
- { do_bad, SIGBUS, 0, "TLB conflict abort" },
+ { do_tlb_conf_fault, SIGBUS, 0, "TLB conflict abort" },
{ do_bad, SIGBUS, 0, "unknown 49" },
{ do_bad, SIGBUS, 0, "unknown 50" },
{ do_bad, SIGBUS, 0, "unknown 51" },
diff --git a/drivers/clk/msm/clock-gcc-8998.c b/drivers/clk/msm/clock-gcc-8998.c
index b1d767a4cb6f..87cf6cc5631e 100644
--- a/drivers/clk/msm/clock-gcc-8998.c
+++ b/drivers/clk/msm/clock-gcc-8998.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-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
@@ -2799,6 +2799,9 @@ static int msm_gcc_8998_probe(struct platform_device *pdev)
/* This clock is used for all MMSSCC register access */
clk_prepare_enable(&gcc_mmss_noc_cfg_ahb_clk.c);
+ /* Keep bimc gfx clock port on all the time */
+ clk_prepare_enable(&gcc_bimc_gfx_clk.c);
+
/* This clock is used for all GPUCC register access */
clk_prepare_enable(&gcc_gpu_cfg_ahb_clk.c);
diff --git a/drivers/clk/msm/clock-osm.c b/drivers/clk/msm/clock-osm.c
index 9e1036c19760..79e8a7d8eb00 100644
--- a/drivers/clk/msm/clock-osm.c
+++ b/drivers/clk/msm/clock-osm.c
@@ -231,6 +231,8 @@ enum clk_osm_trace_packet_id {
#define MSM8998V2_PWRCL_BOOT_RATE 1555200000
#define MSM8998V2_PERFCL_BOOT_RATE 1728000000
+#define DEBUG_REG_NUM 3
+
/* ACD registers */
#define ACD_HW_VERSION 0x0
#define ACDCR 0x4
@@ -340,6 +342,12 @@ struct osm_entry {
long frequency;
};
+const char *clk_panic_reg_names[] = {"WDOG_DOMAIN_PSTATE_STATUS",
+ "WDOG_PROGRAM_COUNTER",
+ "APM_STATUS"};
+const int clk_panic_reg_offsets[] = {WDOG_DOMAIN_PSTATE_STATUS,
+ WDOG_PROGRAM_COUNTER};
+
static struct dentry *osm_debugfs_base;
struct clk_osm {
@@ -350,6 +358,7 @@ struct clk_osm {
struct platform_device *vdd_dev;
void *vbases[NUM_BASES];
unsigned long pbases[NUM_BASES];
+ void __iomem *debug_regs[DEBUG_REG_NUM];
spinlock_t lock;
u32 cpu_reg_mask;
@@ -1371,6 +1380,64 @@ static int clk_osm_resources_init(struct platform_device *pdev)
perfcl_clk.acd_init = false;
}
+ pwrcl_clk.debug_regs[0] = devm_ioremap(&pdev->dev,
+ pwrcl_clk.pbases[OSM_BASE] +
+ clk_panic_reg_offsets[0],
+ 0x4);
+ if (!pwrcl_clk.debug_regs[0]) {
+ dev_err(&pdev->dev, "Failed to map %s debug register\n",
+ clk_panic_reg_names[0]);
+ return -ENOMEM;
+ }
+
+ pwrcl_clk.debug_regs[1] = devm_ioremap(&pdev->dev,
+ pwrcl_clk.pbases[OSM_BASE] +
+ clk_panic_reg_offsets[1],
+ 0x4);
+ if (!pwrcl_clk.debug_regs[1]) {
+ dev_err(&pdev->dev, "Failed to map %s debug register\n",
+ clk_panic_reg_names[1]);
+ return -ENOMEM;
+ }
+
+ pwrcl_clk.debug_regs[2] = devm_ioremap(&pdev->dev,
+ pwrcl_clk.apm_ctrl_status,
+ 0x4);
+ if (!pwrcl_clk.debug_regs[2]) {
+ dev_err(&pdev->dev, "Failed to map %s debug register\n",
+ clk_panic_reg_names[2]);
+ return -ENOMEM;
+ }
+
+ perfcl_clk.debug_regs[0] = devm_ioremap(&pdev->dev,
+ perfcl_clk.pbases[OSM_BASE] +
+ clk_panic_reg_offsets[0],
+ 0x4);
+ if (!perfcl_clk.debug_regs[0]) {
+ dev_err(&pdev->dev, "Failed to map %s debug register\n",
+ clk_panic_reg_names[0]);
+ return -ENOMEM;
+ }
+
+ perfcl_clk.debug_regs[1] = devm_ioremap(&pdev->dev,
+ perfcl_clk.pbases[OSM_BASE] +
+ clk_panic_reg_offsets[1],
+ 0x4);
+ if (!perfcl_clk.debug_regs[1]) {
+ dev_err(&pdev->dev, "Failed to map %s debug register\n",
+ clk_panic_reg_names[1]);
+ return -ENOMEM;
+ }
+
+ perfcl_clk.debug_regs[2] = devm_ioremap(&pdev->dev,
+ perfcl_clk.apm_ctrl_status,
+ 0x4);
+ if (!perfcl_clk.debug_regs[2]) {
+ dev_err(&pdev->dev, "Failed to map %s debug register\n",
+ clk_panic_reg_names[2]);
+ return -ENOMEM;
+ }
+
vdd_pwrcl = devm_regulator_get(&pdev->dev, "vdd-pwrcl");
if (IS_ERR(vdd_pwrcl)) {
rc = PTR_ERR(vdd_pwrcl);
@@ -2976,36 +3043,16 @@ static int clk_osm_panic_callback(struct notifier_block *nfb,
unsigned long event,
void *data)
{
- void __iomem *virt_addr;
- u32 value, reg;
+ int i;
+ u32 value;
struct clk_osm *c = container_of(nfb,
struct clk_osm,
panic_notifier);
- reg = c->pbases[OSM_BASE] + WDOG_DOMAIN_PSTATE_STATUS;
- virt_addr = ioremap(reg, 0x4);
- if (virt_addr != NULL) {
- value = readl_relaxed(virt_addr);
- pr_err("DOM%d_PSTATE_STATUS[0x%08x]=0x%08x\n", c->cluster_num,
- reg, value);
- iounmap(virt_addr);
- }
-
- reg = c->pbases[OSM_BASE] + WDOG_PROGRAM_COUNTER;
- virt_addr = ioremap(reg, 0x4);
- if (virt_addr != NULL) {
- value = readl_relaxed(virt_addr);
- pr_err("DOM%d_PROGRAM_COUNTER[0x%08x]=0x%08x\n", c->cluster_num,
- reg, value);
- iounmap(virt_addr);
- }
-
- virt_addr = ioremap(c->apm_ctrl_status, 0x4);
- if (virt_addr != NULL) {
- value = readl_relaxed(virt_addr);
- pr_err("APM_CTLER_STATUS_%d[0x%08x]=0x%08x\n", c->cluster_num,
- c->apm_ctrl_status, value);
- iounmap(virt_addr);
+ for (i = 0; i < DEBUG_REG_NUM; i++) {
+ value = readl_relaxed(c->debug_regs[i]);
+ pr_err("%s_%d=0x%08x\n", clk_panic_reg_names[i],
+ c->cluster_num, value);
}
return NOTIFY_OK;
@@ -3108,17 +3155,17 @@ static int cpu_clock_osm_driver_probe(struct platform_device *pdev)
msm8998_v2 = true;
}
- rc = clk_osm_resources_init(pdev);
+ rc = clk_osm_parse_dt_configs(pdev);
if (rc) {
- if (rc != -EPROBE_DEFER)
- dev_err(&pdev->dev, "resources init failed, rc=%d\n",
- rc);
+ dev_err(&pdev->dev, "Unable to parse device tree configurations\n");
return rc;
}
- rc = clk_osm_parse_dt_configs(pdev);
+ rc = clk_osm_resources_init(pdev);
if (rc) {
- dev_err(&pdev->dev, "Unable to parse device tree configurations\n");
+ if (rc != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "resources init failed, rc=%d\n",
+ rc);
return rc;
}
diff --git a/drivers/clk/qcom/clk-cpu-osm.c b/drivers/clk/qcom/clk-cpu-osm.c
index ab6a1384ffbd..5ed0dba189f7 100644
--- a/drivers/clk/qcom/clk-cpu-osm.c
+++ b/drivers/clk/qcom/clk-cpu-osm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 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
@@ -88,6 +88,7 @@ enum clk_osm_trace_packet_id {
#define CORE_COUNT_VAL(val) ((val & GENMASK(18, 16)) >> 16)
#define SINGLE_CORE 1
#define MAX_CORE_COUNT 4
+#define DEBUG_REG_NUM 3
#define ENABLE_REG 0x1004
#define INDEX_REG 0x1150
@@ -321,6 +322,13 @@ static struct dentry *osm_debugfs_base;
static struct regulator *vdd_pwrcl;
static struct regulator *vdd_perfcl;
+const char *clk_panic_reg_names[] = {"WDOG_DOMAIN_PSTATE_STATUS",
+ "WDOG_PROGRAM_COUNTER",
+ "APM_STATUS"};
+
+const int clk_panic_reg_offsets[] = {WDOG_DOMAIN_PSTATE_STATUS,
+ WDOG_PROGRAM_COUNTER};
+
static const struct regmap_config osm_qcom_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
@@ -336,6 +344,7 @@ struct clk_osm {
struct platform_device *vdd_dev;
void *vbases[NUM_BASES];
unsigned long pbases[NUM_BASES];
+ void __iomem *debug_regs[DEBUG_REG_NUM];
spinlock_t lock;
u32 cpu_reg_mask;
@@ -1366,6 +1375,64 @@ static int clk_osm_resources_init(struct platform_device *pdev)
perfcl_clk.acd_init = false;
}
+ pwrcl_clk.debug_regs[0] = devm_ioremap(&pdev->dev,
+ pwrcl_clk.pbases[OSM_BASE] +
+ clk_panic_reg_offsets[0],
+ 0x4);
+ if (!pwrcl_clk.debug_regs[0]) {
+ dev_err(&pdev->dev, "Failed to map %s debug register\n",
+ clk_panic_reg_names[0]);
+ return -ENOMEM;
+ }
+
+ pwrcl_clk.debug_regs[1] = devm_ioremap(&pdev->dev,
+ pwrcl_clk.pbases[OSM_BASE] +
+ clk_panic_reg_offsets[1],
+ 0x4);
+ if (!pwrcl_clk.debug_regs[1]) {
+ dev_err(&pdev->dev, "Failed to map %s debug register\n",
+ clk_panic_reg_names[1]);
+ return -ENOMEM;
+ }
+
+ pwrcl_clk.debug_regs[2] = devm_ioremap(&pdev->dev,
+ pwrcl_clk.apm_ctrl_status,
+ 0x4);
+ if (!pwrcl_clk.debug_regs[2]) {
+ dev_err(&pdev->dev, "Failed to map %s debug register\n",
+ clk_panic_reg_names[2]);
+ return -ENOMEM;
+ };
+
+ perfcl_clk.debug_regs[0] = devm_ioremap(&pdev->dev,
+ perfcl_clk.pbases[OSM_BASE] +
+ clk_panic_reg_offsets[0],
+ 0x4);
+ if (!perfcl_clk.debug_regs[0]) {
+ dev_err(&pdev->dev, "Failed to map %s debug register\n",
+ clk_panic_reg_names[0]);
+ return -ENOMEM;
+ }
+
+ perfcl_clk.debug_regs[1] = devm_ioremap(&pdev->dev,
+ perfcl_clk.pbases[OSM_BASE] +
+ clk_panic_reg_offsets[1],
+ 0x4);
+ if (!perfcl_clk.debug_regs[1]) {
+ dev_err(&pdev->dev, "Failed to map %s debug register\n",
+ clk_panic_reg_names[1]);
+ return -ENOMEM;
+ }
+
+ perfcl_clk.debug_regs[2] = devm_ioremap(&pdev->dev,
+ perfcl_clk.apm_ctrl_status,
+ 0x4);
+ if (!perfcl_clk.debug_regs[2]) {
+ dev_err(&pdev->dev, "Failed to map %s debug register\n",
+ clk_panic_reg_names[2]);
+ return -ENOMEM;
+ };
+
vdd_pwrcl = devm_regulator_get(&pdev->dev, "vdd-pwrcl");
if (IS_ERR(vdd_pwrcl)) {
rc = PTR_ERR(vdd_pwrcl);
@@ -2859,36 +2926,16 @@ static int clk_osm_panic_callback(struct notifier_block *nfb,
unsigned long event,
void *data)
{
- void __iomem *virt_addr;
- u32 value, reg;
+ int i;
+ u32 value;
struct clk_osm *c = container_of(nfb,
struct clk_osm,
panic_notifier);
- reg = c->pbases[OSM_BASE] + WDOG_DOMAIN_PSTATE_STATUS;
- virt_addr = ioremap(reg, 0x4);
- if (virt_addr != NULL) {
- value = readl_relaxed(virt_addr);
- pr_err("DOM%d_PSTATE_STATUS[0x%08x]=0x%08x\n", c->cluster_num,
- reg, value);
- iounmap(virt_addr);
- }
-
- reg = c->pbases[OSM_BASE] + WDOG_PROGRAM_COUNTER;
- virt_addr = ioremap(reg, 0x4);
- if (virt_addr != NULL) {
- value = readl_relaxed(virt_addr);
- pr_err("DOM%d_PROGRAM_COUNTER[0x%08x]=0x%08x\n", c->cluster_num,
- reg, value);
- iounmap(virt_addr);
- }
-
- virt_addr = ioremap(c->apm_ctrl_status, 0x4);
- if (virt_addr != NULL) {
- value = readl_relaxed(virt_addr);
- pr_err("APM_CTLER_STATUS_%d[0x%08x]=0x%08x\n", c->cluster_num,
- c->apm_ctrl_status, value);
- iounmap(virt_addr);
+ for (i = 0; i < DEBUG_REG_NUM; i++) {
+ value = readl_relaxed(c->debug_regs[i]);
+ pr_err("%s_%d=0x%08x\n", clk_panic_reg_names[i],
+ c->cluster_num, value);
}
return NOTIFY_OK;
@@ -3020,17 +3067,17 @@ static int clk_cpu_osm_driver_probe(struct platform_device *pdev)
clk_data->clk_num = num_clks;
- rc = clk_osm_resources_init(pdev);
+ rc = clk_osm_parse_dt_configs(pdev);
if (rc) {
- if (rc != -EPROBE_DEFER)
- dev_err(&pdev->dev, "resources init failed, rc=%d\n",
- rc);
+ dev_err(&pdev->dev, "Unable to parse device tree configurations\n");
return rc;
}
- rc = clk_osm_parse_dt_configs(pdev);
+ rc = clk_osm_resources_init(pdev);
if (rc) {
- dev_err(&pdev->dev, "Unable to parse device tree configurations\n");
+ if (rc != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "resources init failed, rc=%d\n",
+ rc);
return rc;
}
diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c
index 81801605d6e7..823b7d988284 100644
--- a/drivers/cpuidle/lpm-levels.c
+++ b/drivers/cpuidle/lpm-levels.c
@@ -1061,8 +1061,9 @@ static int cluster_select(struct lpm_cluster *cluster, bool from_idle,
best_level = i;
- if (predicted ? (pred_us <= pwr_params->max_residency)
- : (sleep_us <= pwr_params->max_residency))
+ if (from_idle &&
+ (predicted ? (pred_us <= pwr_params->max_residency)
+ : (sleep_us <= pwr_params->max_residency)))
break;
}
diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig
index 84d3ec98e6b9..7f29f3644fb6 100644
--- a/drivers/gpu/drm/msm/Kconfig
+++ b/drivers/gpu/drm/msm/Kconfig
@@ -3,7 +3,7 @@ config DRM_MSM
tristate "MSM DRM"
depends on DRM
depends on ARCH_QCOM || (ARM && COMPILE_TEST)
- depends on OF && COMMON_CLK
+ depends on OF
select REGULATOR
select DRM_KMS_HELPER
select DRM_PANEL
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index bc681057250d..d997cdd2cc7e 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-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
@@ -134,7 +134,7 @@ static void kgsl_iommu_unmap_globals(struct kgsl_pagetable *pagetable)
}
}
-static void kgsl_iommu_map_globals(struct kgsl_pagetable *pagetable)
+static int kgsl_iommu_map_globals(struct kgsl_pagetable *pagetable)
{
unsigned int i;
@@ -143,9 +143,11 @@ static void kgsl_iommu_map_globals(struct kgsl_pagetable *pagetable)
int ret = kgsl_mmu_map(pagetable,
global_pt_entries[i].memdesc);
- BUG_ON(ret);
+ if (ret)
+ return ret;
}
}
+ return 0;
}
static void kgsl_iommu_unmap_global_secure_pt_entry(struct kgsl_pagetable
@@ -158,16 +160,16 @@ static void kgsl_iommu_unmap_global_secure_pt_entry(struct kgsl_pagetable
}
-static void kgsl_map_global_secure_pt_entry(struct kgsl_pagetable *pagetable)
+static int kgsl_map_global_secure_pt_entry(struct kgsl_pagetable *pagetable)
{
- int ret;
+ int ret = 0;
struct kgsl_memdesc *entry = kgsl_global_secure_pt_entry;
if (entry != NULL) {
entry->pagetable = pagetable;
ret = kgsl_mmu_map(pagetable, entry);
- BUG_ON(ret);
}
+ return ret;
}
static void kgsl_iommu_remove_global(struct kgsl_mmu *mmu,
@@ -1171,7 +1173,7 @@ static int _init_global_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt)
goto done;
}
- kgsl_iommu_map_globals(pt);
+ ret = kgsl_iommu_map_globals(pt);
done:
if (ret)
@@ -1227,7 +1229,7 @@ static int _init_secure_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt)
ctx->regbase = iommu->regbase + KGSL_IOMMU_CB0_OFFSET
+ (cb_num << KGSL_IOMMU_CB_SHIFT);
- kgsl_map_global_secure_pt_entry(pt);
+ ret = kgsl_map_global_secure_pt_entry(pt);
done:
if (ret)
@@ -1288,7 +1290,7 @@ static int _init_per_process_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt)
goto done;
}
- kgsl_iommu_map_globals(pt);
+ ret = kgsl_iommu_map_globals(pt);
done:
if (ret)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c
index a37b5ce9a6b2..287d839f98d0 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x.c
@@ -2824,6 +2824,8 @@ err_late_init:
unregister_hotcpu_notifier(&etm4_cpu_notifier);
unregister_hotcpu_notifier(&etm4_cpu_dying_notifier);
}
+ etmdrvdata[drvdata->cpu] = NULL;
+ dev_set_drvdata(dev, NULL);
return ret;
}
diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig
index 9b8bcdffdfba..2557dcda7621 100644
--- a/drivers/input/Kconfig
+++ b/drivers/input/Kconfig
@@ -25,14 +25,6 @@ config INPUT
if INPUT
-config QPNP_POWER_ON
- tristate "QPNP PMIC POWER-ON Driver"
- depends on SPMI && ARCH_QCOM
- help
- This driver supports the power-on functionality on Qualcomm
- PNP PMIC. It currently supports reporting the change in status of
- the KPDPWR_N line (connected to the power-key).
-
config INPUT_LEDS
tristate "Export input device LEDs in sysfs"
depends on LEDS_CLASS
diff --git a/drivers/input/Makefile b/drivers/input/Makefile
index fd35ebf6acd9..2a6d05ab9170 100644
--- a/drivers/input/Makefile
+++ b/drivers/input/Makefile
@@ -7,7 +7,6 @@
obj-$(CONFIG_INPUT) += input-core.o
input-core-y := input.o input-compat.o input-mt.o ff-core.o
-obj-$(CONFIG_QPNP_POWER_ON) += qpnp-power-on.o
obj-$(CONFIG_INPUT_FF_MEMLESS) += ff-memless.o
obj-$(CONFIG_INPUT_POLLDEV) += input-polldev.o
obj-$(CONFIG_INPUT_SPARSEKMAP) += sparse-keymap.o
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 9c1380b65b77..5cfa1848e37c 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -161,6 +161,15 @@ config INPUT_PMIC8XXX_PWRKEY
To compile this driver as a module, choose M here: the
module will be called pmic8xxx-pwrkey.
+config INPUT_QPNP_POWER_ON
+ tristate "QPNP PMIC Power-on support"
+ depends on SPMI
+ help
+ This option enables device driver support for the power-on
+ functionality of Qualcomm Technologies, Inc. PNP PMICs. It supports
+ reporting the change in status of the KPDPWR_N line (connected to the
+ power-key) as well as reset features.
+
config INPUT_SPARCSPKR
tristate "SPARC Speaker support"
depends on PCI && SPARC64
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 4e806ac056ce..a5ab4b762d31 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -57,6 +57,7 @@ obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o
obj-$(CONFIG_INPUT_PM8941_PWRKEY) += pm8941-pwrkey.o
obj-$(CONFIG_INPUT_PM8XXX_VIBRATOR) += pm8xxx-vibrator.o
obj-$(CONFIG_INPUT_PMIC8XXX_PWRKEY) += pmic8xxx-pwrkey.o
+obj-$(CONFIG_INPUT_QPNP_POWER_ON) += qpnp-power-on.o
obj-$(CONFIG_INPUT_POWERMATE) += powermate.o
obj-$(CONFIG_INPUT_PWM_BEEPER) += pwm-beeper.o
obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o
diff --git a/drivers/input/qpnp-power-on.c b/drivers/input/misc/qpnp-power-on.c
index 967b23cae05c..e1c16aa5da43 100644
--- a/drivers/input/qpnp-power-on.c
+++ b/drivers/input/misc/qpnp-power-on.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-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
@@ -30,7 +30,7 @@
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/of_regulator.h>
-#include <linux/qpnp/power-on.h>
+#include <linux/input/qpnp-power-on.h>
#include <linux/power_supply.h>
#define PMIC_VER_8941 0x01
@@ -223,7 +223,7 @@ struct qpnp_pon {
static int pon_ship_mode_en;
module_param_named(
- ship_mode_en, pon_ship_mode_en, int, S_IRUSR | S_IWUSR
+ ship_mode_en, pon_ship_mode_en, int, 0600
);
static struct qpnp_pon *sys_reset_dev;
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 791f2fe70236..582261d5aa17 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -530,6 +530,8 @@ static bool arm_smmu_is_master_side_secure(struct arm_smmu_domain *smmu_domain);
static bool arm_smmu_is_static_cb(struct arm_smmu_device *smmu);
static bool arm_smmu_is_slave_side_secure(struct arm_smmu_domain *smmu_domain);
static bool arm_smmu_has_secure_vmid(struct arm_smmu_domain *smmu_domain);
+static bool arm_smmu_is_iova_coherent(struct iommu_domain *domain,
+ dma_addr_t iova);
static int arm_smmu_enable_s1_translations(struct arm_smmu_domain *smmu_domain);
@@ -2664,6 +2666,23 @@ static phys_addr_t arm_smmu_iova_to_phys(struct iommu_domain *domain,
return ret;
}
+static bool arm_smmu_is_iova_coherent(struct iommu_domain *domain,
+ dma_addr_t iova)
+{
+ bool ret;
+ unsigned long flags;
+ struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
+ struct io_pgtable_ops *ops = smmu_domain->pgtbl_ops;
+
+ if (!ops)
+ return false;
+
+ flags = arm_smmu_pgtbl_lock(smmu_domain);
+ ret = ops->is_iova_coherent(ops, iova);
+ arm_smmu_pgtbl_unlock(smmu_domain, flags);
+ return ret;
+}
+
static int arm_smmu_wait_for_halt(struct arm_smmu_device *smmu)
{
void __iomem *impl_def1_base = ARM_SMMU_IMPL_DEF1(smmu);
@@ -3311,6 +3330,7 @@ static struct iommu_ops arm_smmu_ops = {
.tlbi_domain = arm_smmu_tlbi_domain,
.enable_config_clocks = arm_smmu_enable_config_clocks,
.disable_config_clocks = arm_smmu_disable_config_clocks,
+ .is_iova_coherent = arm_smmu_is_iova_coherent,
};
static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
index 1cd1a18dd037..3f9825a9addb 100644
--- a/drivers/iommu/io-pgtable-arm.c
+++ b/drivers/iommu/io-pgtable-arm.c
@@ -109,6 +109,7 @@
#define ARM_LPAE_PTE_AP_RW (((arm_lpae_iopte)1) << 6)
#define ARM_LPAE_PTE_AP_PRIV_RO (((arm_lpae_iopte)2) << 6)
#define ARM_LPAE_PTE_AP_RO (((arm_lpae_iopte)3) << 6)
+#define ARM_LPAE_PTE_ATTRINDX_MASK 0x7
#define ARM_LPAE_PTE_ATTRINDX_SHIFT 2
#define ARM_LPAE_PTE_nG (((arm_lpae_iopte)1) << 11)
@@ -813,39 +814,91 @@ static size_t arm_lpae_unmap(struct io_pgtable_ops *ops, unsigned long iova,
return unmapped;
}
-static phys_addr_t arm_lpae_iova_to_phys(struct io_pgtable_ops *ops,
- unsigned long iova)
+static int arm_lpae_iova_to_pte(struct arm_lpae_io_pgtable *data,
+ unsigned long iova, int *plvl_ret,
+ arm_lpae_iopte *ptep_ret)
{
- struct arm_lpae_io_pgtable *data = io_pgtable_ops_to_data(ops);
arm_lpae_iopte pte, *ptep = data->pgd;
- int lvl = ARM_LPAE_START_LVL(data);
+ *plvl_ret = ARM_LPAE_START_LVL(data);
+ *ptep_ret = 0;
do {
/* Valid IOPTE pointer? */
if (!ptep)
- return 0;
+ return -EINVAL;
/* Grab the IOPTE we're interested in */
- pte = *(ptep + ARM_LPAE_LVL_IDX(iova, lvl, data));
+ pte = *(ptep + ARM_LPAE_LVL_IDX(iova, *plvl_ret, data));
/* Valid entry? */
if (!pte)
- return 0;
+ return -EINVAL;
/* Leaf entry? */
- if (iopte_leaf(pte,lvl))
+ if (iopte_leaf(pte, *plvl_ret))
goto found_translation;
/* Take it to the next level */
ptep = iopte_deref(pte, data);
- } while (++lvl < ARM_LPAE_MAX_LEVELS);
+ } while (++(*plvl_ret) < ARM_LPAE_MAX_LEVELS);
/* Ran out of page tables to walk */
- return 0;
+ return -EINVAL;
found_translation:
- iova &= ((1 << ARM_LPAE_LVL_SHIFT(lvl, data)) - 1);
- return ((phys_addr_t)iopte_to_pfn(pte,data) << data->pg_shift) | iova;
+ *ptep_ret = pte;
+ return 0;
+}
+
+static phys_addr_t arm_lpae_iova_to_phys(struct io_pgtable_ops *ops,
+ unsigned long iova)
+{
+ struct arm_lpae_io_pgtable *data = io_pgtable_ops_to_data(ops);
+ arm_lpae_iopte pte;
+ int lvl;
+ phys_addr_t phys = 0;
+
+ if (!arm_lpae_iova_to_pte(data, iova, &lvl, &pte)) {
+ iova &= ((1 << ARM_LPAE_LVL_SHIFT(lvl, data)) - 1);
+ phys = ((phys_addr_t)iopte_to_pfn(pte, data)
+ << data->pg_shift) | iova;
+ }
+
+ return phys;
+}
+
+static bool __arm_lpae_is_iova_coherent(struct arm_lpae_io_pgtable *data,
+ arm_lpae_iopte *ptep)
+{
+ if (data->iop.fmt == ARM_64_LPAE_S1 ||
+ data->iop.fmt == ARM_32_LPAE_S1) {
+ int attr_idx = (*ptep & (ARM_LPAE_PTE_ATTRINDX_MASK <<
+ ARM_LPAE_PTE_ATTRINDX_SHIFT)) >>
+ ARM_LPAE_PTE_ATTRINDX_SHIFT;
+ if ((attr_idx == ARM_LPAE_MAIR_ATTR_IDX_CACHE) &&
+ ((*ptep & ARM_LPAE_PTE_SH_IS) ||
+ (*ptep & ARM_LPAE_PTE_SH_OS)))
+ return true;
+ } else {
+ if (*ptep & ARM_LPAE_PTE_MEMATTR_OIWB)
+ return true;
+ }
+
+ return false;
+}
+
+static bool arm_lpae_is_iova_coherent(struct io_pgtable_ops *ops,
+ unsigned long iova)
+{
+ struct arm_lpae_io_pgtable *data = io_pgtable_ops_to_data(ops);
+ arm_lpae_iopte pte;
+ int lvl;
+ bool ret = false;
+
+ if (!arm_lpae_iova_to_pte(data, iova, &lvl, &pte))
+ ret = __arm_lpae_is_iova_coherent(data, &pte);
+
+ return ret;
}
static void arm_lpae_restrict_pgsizes(struct io_pgtable_cfg *cfg)
@@ -925,6 +978,7 @@ arm_lpae_alloc_pgtable(struct io_pgtable_cfg *cfg)
.map_sg = arm_lpae_map_sg,
.unmap = arm_lpae_unmap,
.iova_to_phys = arm_lpae_iova_to_phys,
+ .is_iova_coherent = arm_lpae_is_iova_coherent,
};
return data;
diff --git a/drivers/iommu/io-pgtable.h b/drivers/iommu/io-pgtable.h
index 1d92edbd5ed1..32ae3c59fe7c 100644
--- a/drivers/iommu/io-pgtable.h
+++ b/drivers/iommu/io-pgtable.h
@@ -114,6 +114,9 @@ struct io_pgtable_ops {
size_t size);
phys_addr_t (*iova_to_phys)(struct io_pgtable_ops *ops,
unsigned long iova);
+ bool (*is_iova_coherent)(struct io_pgtable_ops *ops,
+ unsigned long iova);
+
};
/**
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 8ab502d80270..a77a45088b9d 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1336,6 +1336,13 @@ phys_addr_t iommu_iova_to_phys_hard(struct iommu_domain *domain,
return domain->ops->iova_to_phys_hard(domain, iova);
}
+bool iommu_is_iova_coherent(struct iommu_domain *domain, dma_addr_t iova)
+{
+ if (unlikely(domain->ops->is_iova_coherent == NULL))
+ return 0;
+
+ return domain->ops->is_iova_coherent(domain, iova);
+}
static unsigned long iommu_get_pgsize_bitmap(struct iommu_domain *domain)
{
if (domain->ops->get_pgsize_bitmap)
diff --git a/drivers/media/dvb-core/dvb_ringbuffer.c b/drivers/media/dvb-core/dvb_ringbuffer.c
index 0d44deed65bd..8ab60a4fec00 100644
--- a/drivers/media/dvb-core/dvb_ringbuffer.c
+++ b/drivers/media/dvb-core/dvb_ringbuffer.c
@@ -233,9 +233,11 @@ ssize_t dvb_ringbuffer_write_user(struct dvb_ringbuffer *rbuf,
*/
smp_store_release(&rbuf->pwrite, 0);
}
- status = copy_from_user(rbuf->data+rbuf->pwrite, buf, todo);
- if (status)
- return len - todo;
+
+ if (copy_from_user(rbuf->data + rbuf->pwrite, buf, todo)) {
+ smp_store_release(&rbuf->pwrite, oldpwrite);
+ return -EFAULT;
+ }
/* smp_store_release() for write pointer update, see above */
smp_store_release(&rbuf->pwrite, (rbuf->pwrite + todo) % rbuf->size);
diff --git a/drivers/media/platform/msm/camera_v2/common/cam_soc_api.c b/drivers/media/platform/msm/camera_v2/common/cam_soc_api.c
index 6c09f3820dfd..34fffa8dd7ce 100644
--- a/drivers/media/platform/msm/camera_v2/common/cam_soc_api.c
+++ b/drivers/media/platform/msm/camera_v2/common/cam_soc_api.c
@@ -686,6 +686,50 @@ error:
}
EXPORT_SYMBOL(msm_camera_regulator_enable);
+/* set regulator mode */
+int msm_camera_regulator_set_mode(struct msm_cam_regulator *vdd_info,
+ int cnt, bool mode)
+{
+ int i;
+ int rc;
+ struct msm_cam_regulator *tmp = vdd_info;
+
+ if (!tmp) {
+ pr_err("Invalid params");
+ return -EINVAL;
+ }
+ CDBG("cnt : %d\n", cnt);
+
+ for (i = 0; i < cnt; i++) {
+ if (tmp && !IS_ERR_OR_NULL(tmp->vdd)) {
+ CDBG("name : %s, enable : %d\n", tmp->name, mode);
+ if (mode) {
+ rc = regulator_set_mode(tmp->vdd,
+ REGULATOR_MODE_FAST);
+ if (rc < 0) {
+ pr_err("regulator enable failed %d\n",
+ i);
+ goto error;
+ }
+ } else {
+ rc = regulator_set_mode(tmp->vdd,
+ REGULATOR_MODE_NORMAL);
+ if (rc < 0)
+ pr_err("regulator disable failed %d\n",
+ i);
+ goto error;
+ }
+ }
+ tmp++;
+ }
+
+ return 0;
+error:
+ return rc;
+}
+EXPORT_SYMBOL(msm_camera_regulator_set_mode);
+
+
/* Put regulators regulators */
void msm_camera_put_regulators(struct platform_device *pdev,
struct msm_cam_regulator **vdd_info, int cnt)
diff --git a/drivers/media/platform/msm/camera_v2/common/cam_soc_api.h b/drivers/media/platform/msm/camera_v2/common/cam_soc_api.h
index 0e9d26bebe30..55074490bd72 100644
--- a/drivers/media/platform/msm/camera_v2/common/cam_soc_api.h
+++ b/drivers/media/platform/msm/camera_v2/common/cam_soc_api.h
@@ -248,6 +248,23 @@ int msm_camera_regulator_enable(struct msm_cam_regulator *vdd_info,
int cnt, int enable);
/**
+ * @brief : set the regultors mode
+ *
+ * This function sets the regulators for a specific
+ * mode. say:REGULATOR_MODE_FAST/REGULATOR_MODE_NORMAL
+ *
+ * @param vdd_info: Pointer to list of regulators
+ * @param cnt: Number of regulators to enable/disable
+ * @param mode: Flags specifies either enable/disable
+ *
+ * @return Status of operation. Negative in case of error. Zero otherwise.
+ */
+
+int msm_camera_regulator_set_mode(struct msm_cam_regulator *vdd_info,
+ int cnt, bool mode);
+
+
+/**
* @brief : Release the regulators
*
* This function releases the regulator resources.
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp.c
index 35daf30bac63..840d84388a17 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.c
@@ -500,6 +500,10 @@ static int vfe_probe(struct platform_device *pdev)
memset(&vfe_common_data, 0, sizeof(vfe_common_data));
mutex_init(&vfe_common_data.vfe_common_mutex);
spin_lock_init(&vfe_common_data.common_dev_data_lock);
+ spin_lock_init(&vfe_common_data.vfe_irq_dump.
+ common_dev_irq_dump_lock);
+ spin_lock_init(&vfe_common_data.vfe_irq_dump.
+ common_dev_tasklet_dump_lock);
for (i = 0; i < (VFE_AXI_SRC_MAX * MAX_VFE); i++)
spin_lock_init(&(vfe_common_data.streams[i].lock));
for (i = 0; i < (MSM_ISP_STATS_MAX * MAX_VFE); i++)
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
index 9c7eba21fde1..4b881f4fd7b6 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
@@ -66,6 +66,8 @@
#define MAX_BUFFERS_IN_HW 2
#define MAX_VFE 2
+#define MAX_VFE_IRQ_DEBUG_DUMP_SIZE 10
+#define MAX_RECOVERY_THRESHOLD 5
struct vfe_device;
struct msm_vfe_axi_stream;
@@ -133,6 +135,8 @@ struct msm_isp_timestamp {
};
struct msm_vfe_irq_ops {
+ void (*read_and_clear_irq_status)(struct vfe_device *vfe_dev,
+ uint32_t *irq_status0, uint32_t *irq_status1);
void (*read_irq_status)(struct vfe_device *vfe_dev,
uint32_t *irq_status0, uint32_t *irq_status1);
void (*process_reg_update)(struct vfe_device *vfe_dev,
@@ -525,6 +529,7 @@ struct msm_vfe_axi_shared_data {
uint16_t stream_handle_cnt;
uint32_t event_mask;
uint8_t enable_frameid_recovery;
+ uint8_t recovery_count;
};
struct msm_vfe_stats_hardware_info {
@@ -691,6 +696,26 @@ struct master_slave_resource_info {
enum msm_vfe_dual_cam_sync_mode dual_sync_mode;
};
+struct msm_vfe_irq_debug_info {
+ uint32_t vfe_id;
+ struct msm_isp_timestamp ts;
+ uint32_t core_id;
+ uint32_t irq_status0[MAX_VFE];
+ uint32_t irq_status1[MAX_VFE];
+ uint32_t ping_pong_status[MAX_VFE];
+};
+
+struct msm_vfe_irq_dump {
+ spinlock_t common_dev_irq_dump_lock;
+ spinlock_t common_dev_tasklet_dump_lock;
+ uint8_t current_irq_index;
+ uint8_t current_tasklet_index;
+ struct msm_vfe_irq_debug_info
+ irq_debug[MAX_VFE_IRQ_DEBUG_DUMP_SIZE];
+ struct msm_vfe_irq_debug_info
+ tasklet_debug[MAX_VFE_IRQ_DEBUG_DUMP_SIZE];
+};
+
struct msm_vfe_common_dev_data {
spinlock_t common_dev_data_lock;
struct dual_vfe_resource *dual_vfe_res;
@@ -698,6 +723,8 @@ struct msm_vfe_common_dev_data {
struct msm_vfe_axi_stream streams[VFE_AXI_SRC_MAX * MAX_VFE];
struct msm_vfe_stats_stream stats_streams[MSM_ISP_STATS_MAX * MAX_VFE];
struct mutex vfe_common_mutex;
+ /* Irq debug Info */
+ struct msm_vfe_irq_dump vfe_irq_dump;
};
struct msm_vfe_common_subdev {
@@ -790,8 +817,9 @@ struct vfe_device {
/* irq info */
uint32_t irq0_mask;
uint32_t irq1_mask;
-
uint32_t bus_err_ign_mask;
+ uint32_t recovery_irq0_mask;
+ uint32_t recovery_irq1_mask;
};
struct vfe_parent_device {
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
index 43f562b18209..bf18fc59585c 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
@@ -576,7 +576,7 @@ static void msm_vfe32_process_error_status(struct vfe_device *vfe_dev)
pr_err("%s: axi error\n", __func__);
}
-static void msm_vfe32_read_irq_status(struct vfe_device *vfe_dev,
+static void msm_vfe32_read_and_clear_irq_status(struct vfe_device *vfe_dev,
uint32_t *irq_status0, uint32_t *irq_status1)
{
*irq_status0 = msm_camera_io_r(vfe_dev->vfe_base + 0x2C);
@@ -594,6 +594,13 @@ static void msm_vfe32_read_irq_status(struct vfe_device *vfe_dev,
msm_camera_io_r(vfe_dev->vfe_base + 0x7B4);
}
+static void msm_vfe32_read_irq_status(struct vfe_device *vfe_dev,
+ uint32_t *irq_status0, uint32_t irq_status1)
+{
+ *irq_status0 = msm_camera_io_r(vfe_dev->vfe_base + 0x2C);
+ *irq_status1 = msm_camera_io_r(vfe_dev->vfe_base + 0x30);
+}
+
static void msm_vfe32_process_reg_update(struct vfe_device *vfe_dev,
uint32_t irq_status0, uint32_t irq_status1,
struct msm_isp_timestamp *ts)
@@ -1423,6 +1430,8 @@ struct msm_vfe_hardware_info vfe32_hw_info = {
.vfe_clk_idx = VFE32_CLK_IDX,
.vfe_ops = {
.irq_ops = {
+ .read_and_clear_irq_status =
+ msm_vfe32_read_and_clear_irq_status,
.read_irq_status = msm_vfe32_read_irq_status,
.process_camif_irq = msm_vfe32_process_camif_irq,
.process_reset_irq = msm_vfe32_process_reset_irq,
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
index ab01d37790d6..8e549c338bdd 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
@@ -566,7 +566,7 @@ static void msm_vfe40_process_error_status(struct vfe_device *vfe_dev)
msm_isp_update_last_overflow_ab_ib(vfe_dev);
}
-static void msm_vfe40_read_irq_status(struct vfe_device *vfe_dev,
+static void msm_vfe40_read_and_clear_irq_status(struct vfe_device *vfe_dev,
uint32_t *irq_status0, uint32_t *irq_status1)
{
*irq_status0 = msm_camera_io_r(vfe_dev->vfe_base + 0x38);
@@ -599,6 +599,13 @@ static void msm_vfe40_read_irq_status(struct vfe_device *vfe_dev,
}
+static void msm_vfe40_read_irq_status(struct vfe_device *vfe_dev,
+ uint32_t *irq_status0, uint32_t *irq_status1)
+{
+ *irq_status0 = msm_camera_io_r(vfe_dev->vfe_base + 0x38);
+ *irq_status1 = msm_camera_io_r(vfe_dev->vfe_base + 0x3C);
+}
+
static void msm_vfe40_process_reg_update(struct vfe_device *vfe_dev,
uint32_t irq_status0, uint32_t irq_status1,
struct msm_isp_timestamp *ts)
@@ -1770,7 +1777,8 @@ static int msm_vfe40_axi_halt(struct vfe_device *vfe_dev,
static void msm_vfe40_axi_restart(struct vfe_device *vfe_dev,
uint32_t blocking, uint32_t enable_camif)
{
- msm_vfe40_config_irq(vfe_dev, 0x800000E0, 0xFEFFFF7E,
+ msm_vfe40_config_irq(vfe_dev, vfe_dev->recovery_irq0_mask,
+ vfe_dev->recovery_irq1_mask,
MSM_ISP_IRQ_ENABLE);
msm_camera_io_w_mb(0x140000, vfe_dev->vfe_base + 0x318);
@@ -2198,6 +2206,8 @@ struct msm_vfe_hardware_info vfe40_hw_info = {
.min_ib = 12000000,
.vfe_ops = {
.irq_ops = {
+ .read_and_clear_irq_status =
+ msm_vfe40_read_and_clear_irq_status,
.read_irq_status = msm_vfe40_read_irq_status,
.process_camif_irq = msm_vfe40_process_input_irq,
.process_reset_irq = msm_vfe40_process_reset_irq,
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c
index 0a72a041de28..957cbc292be3 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c
@@ -401,7 +401,7 @@ static void msm_vfe44_process_error_status(struct vfe_device *vfe_dev)
}
}
-static void msm_vfe44_read_irq_status(struct vfe_device *vfe_dev,
+static void msm_vfe44_read_and_clear_irq_status(struct vfe_device *vfe_dev,
uint32_t *irq_status0, uint32_t *irq_status1)
{
*irq_status0 = msm_camera_io_r(vfe_dev->vfe_base + 0x38);
@@ -429,6 +429,13 @@ static void msm_vfe44_read_irq_status(struct vfe_device *vfe_dev,
}
+static void msm_vfe44_read_irq_status(struct vfe_device *vfe_dev,
+ uint32_t *irq_status0, uint32_t *irq_status1)
+{
+ *irq_status0 = msm_camera_io_r(vfe_dev->vfe_base + 0x38);
+ *irq_status1 = msm_camera_io_r(vfe_dev->vfe_base + 0x3C);
+}
+
static void msm_vfe44_process_reg_update(struct vfe_device *vfe_dev,
uint32_t irq_status0, uint32_t irq_status1,
struct msm_isp_timestamp *ts)
@@ -1341,8 +1348,8 @@ static int msm_vfe44_axi_halt(struct vfe_device *vfe_dev,
static void msm_vfe44_axi_restart(struct vfe_device *vfe_dev,
uint32_t blocking, uint32_t enable_camif)
{
- msm_vfe44_config_irq(vfe_dev, 0x800000E0, 0xFFFFFF7E,
- MSM_ISP_IRQ_ENABLE);
+ msm_vfe44_config_irq(vfe_dev, vfe_dev->recovery_irq0_mask,
+ vfe_dev->recovery_irq1_mask, MSM_ISP_IRQ_ENABLE);
msm_camera_io_w_mb(0x140000, vfe_dev->vfe_base + 0x318);
/* Start AXI */
@@ -1806,6 +1813,8 @@ struct msm_vfe_hardware_info vfe44_hw_info = {
.min_ib = 100000000,
.vfe_ops = {
.irq_ops = {
+ .read_and_clear_irq_status =
+ msm_vfe44_read_and_clear_irq_status,
.read_irq_status = msm_vfe44_read_irq_status,
.process_camif_irq = msm_vfe44_process_input_irq,
.process_reset_irq = msm_vfe44_process_reset_irq,
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c
index f2d53c956fdc..cc768db875db 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c
@@ -345,7 +345,7 @@ static void msm_vfe46_process_error_status(struct vfe_device *vfe_dev)
pr_err("%s: status bf scale bus overflow\n", __func__);
}
-static void msm_vfe46_read_irq_status(struct vfe_device *vfe_dev,
+static void msm_vfe46_read_and_clear_irq_status(struct vfe_device *vfe_dev,
uint32_t *irq_status0, uint32_t *irq_status1)
{
*irq_status0 = msm_camera_io_r(vfe_dev->vfe_base + 0x6C);
@@ -369,6 +369,13 @@ static void msm_vfe46_read_irq_status(struct vfe_device *vfe_dev,
}
+static void msm_vfe46_read_irq_status(struct vfe_device *vfe_dev,
+ uint32_t *irq_status0, uint32_t *irq_status1)
+{
+ *irq_status0 = msm_camera_io_r(vfe_dev->vfe_base + 0x6C);
+ *irq_status1 = msm_camera_io_r(vfe_dev->vfe_base + 0x70);
+}
+
static void msm_vfe46_process_reg_update(struct vfe_device *vfe_dev,
uint32_t irq_status0, uint32_t irq_status1,
struct msm_isp_timestamp *ts)
@@ -1406,7 +1413,8 @@ static int msm_vfe46_axi_halt(struct vfe_device *vfe_dev,
static void msm_vfe46_axi_restart(struct vfe_device *vfe_dev,
uint32_t blocking, uint32_t enable_camif)
{
- msm_vfe46_config_irq(vfe_dev, 0x810000E0, 0xFFFFFF7E,
+ msm_vfe46_config_irq(vfe_dev, vfe_dev->recovery_irq0_mask,
+ vfe_dev->recovery_irq1_mask,
MSM_ISP_IRQ_ENABLE);
msm_camera_io_w_mb(0x20000, vfe_dev->vfe_base + 0x3CC);
@@ -1882,6 +1890,8 @@ struct msm_vfe_hardware_info vfe46_hw_info = {
.min_ib = 100000000,
.vfe_ops = {
.irq_ops = {
+ .read_and_clear_irq_status =
+ msm_vfe46_read_and_clear_irq_status,
.read_irq_status = msm_vfe46_read_irq_status,
.process_camif_irq = msm_vfe46_process_input_irq,
.process_reset_irq = msm_vfe46_process_reset_irq,
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
index 71ee9211a434..9747cfd6dca3 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
@@ -556,7 +556,7 @@ void msm_vfe47_process_error_status(struct vfe_device *vfe_dev)
pr_err("%s: status dsp error\n", __func__);
}
-void msm_vfe47_read_irq_status(struct vfe_device *vfe_dev,
+void msm_vfe47_read_and_clear_irq_status(struct vfe_device *vfe_dev,
uint32_t *irq_status0, uint32_t *irq_status1)
{
*irq_status0 = msm_camera_io_r(vfe_dev->vfe_base + 0x6C);
@@ -582,6 +582,13 @@ void msm_vfe47_read_irq_status(struct vfe_device *vfe_dev,
}
+void msm_vfe47_read_irq_status(struct vfe_device *vfe_dev,
+ uint32_t *irq_status0, uint32_t *irq_status1)
+{
+ *irq_status0 = msm_camera_io_r(vfe_dev->vfe_base + 0x6C);
+ *irq_status1 = msm_camera_io_r(vfe_dev->vfe_base + 0x70);
+}
+
void msm_vfe47_process_reg_update(struct vfe_device *vfe_dev,
uint32_t irq_status0, uint32_t irq_status1,
struct msm_isp_timestamp *ts)
@@ -1931,7 +1938,9 @@ void msm_vfe47_axi_restart(struct vfe_device *vfe_dev,
uint32_t blocking, uint32_t enable_camif)
{
vfe_dev->hw_info->vfe_ops.irq_ops.config_irq(vfe_dev,
- 0x810000E0, 0xFFFFFF7E, MSM_ISP_IRQ_ENABLE);
+ vfe_dev->recovery_irq0_mask,
+ vfe_dev->recovery_irq1_mask,
+ MSM_ISP_IRQ_ENABLE);
/* Start AXI */
msm_camera_io_w(0x0, vfe_dev->vfe_base + 0x400);
@@ -2783,7 +2792,8 @@ struct msm_vfe_hardware_info vfe47_hw_info = {
.min_ab = 100000000,
.vfe_ops = {
.irq_ops = {
- .read_irq_status = msm_vfe47_read_irq_status,
+ .read_and_clear_irq_status =
+ msm_vfe47_read_and_clear_irq_status,
.process_camif_irq = msm_vfe47_process_input_irq,
.process_reset_irq = msm_vfe47_process_reset_irq,
.process_halt_irq = msm_vfe47_process_halt_irq,
@@ -2793,6 +2803,7 @@ struct msm_vfe_hardware_info vfe47_hw_info = {
.process_stats_irq = msm_isp_process_stats_irq,
.process_epoch_irq = msm_vfe47_process_epoch_irq,
.config_irq = msm_vfe47_config_irq,
+ .read_irq_status = msm_vfe47_read_irq_status,
},
.axi_ops = {
.reload_wm = msm_vfe47_axi_reload_wm,
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.h
index 55cf6a17b18c..22a1a21bce9a 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.h
@@ -30,6 +30,8 @@ enum msm_vfe47_stats_comp_idx {
extern struct msm_vfe_hardware_info vfe47_hw_info;
+void msm_vfe47_read_and_clear_irq_status(struct vfe_device *vfe_dev,
+ uint32_t *irq_status0, uint32_t *irq_status1);
void msm_vfe47_read_irq_status(struct vfe_device *vfe_dev,
uint32_t *irq_status0, uint32_t *irq_status1);
void msm_vfe47_enable_camif_error(struct vfe_device *vfe_dev,
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp48.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp48.c
index f346ceb6c9e5..1f2db9683cd0 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp48.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp48.c
@@ -26,6 +26,25 @@
#include "cam_soc_api.h"
#define MSM_VFE48_BUS_CLIENT_INIT 0xABAB
+#define VFE48_STATS_BURST_LEN 3
+#define VFE48_UB_SIZE_VFE 2048 /* 2048 * 256 bits = 64KB */
+#define VFE48_UB_STATS_SIZE 144
+#define MSM_ISP48_TOTAL_IMAGE_UB_VFE (VFE48_UB_SIZE_VFE - VFE48_UB_STATS_SIZE)
+
+
+static uint32_t stats_base_addr[] = {
+ 0x1D4, /* HDR_BE */
+ 0x254, /* BG(AWB_BG) */
+ 0x214, /* BF */
+ 0x1F4, /* HDR_BHIST */
+ 0x294, /* RS */
+ 0x2B4, /* CS */
+ 0x2D4, /* IHIST */
+ 0x274, /* BHIST (SKIN_BHIST) */
+ 0x234, /* AEC_BG */
+};
+
+#define VFE48_STATS_BASE(idx) (stats_base_addr[idx])
static struct msm_vfe_axi_hardware_info msm_vfe48_axi_hw_info = {
.num_wm = 7,
@@ -260,6 +279,40 @@ static void msm_vfe48_set_bus_err_ign_mask(struct vfe_device *vfe_dev,
vfe_dev->bus_err_ign_mask &= ~(1 << wm);
}
+void msm_vfe48_stats_cfg_ub(struct vfe_device *vfe_dev)
+{
+ int i;
+ uint32_t ub_offset = 0, stats_burst_len;
+ uint32_t ub_size[VFE47_NUM_STATS_TYPE] = {
+ 16, /* MSM_ISP_STATS_HDR_BE */
+ 16, /* MSM_ISP_STATS_BG */
+ 16, /* MSM_ISP_STATS_BF */
+ 16, /* MSM_ISP_STATS_HDR_BHIST */
+ 16, /* MSM_ISP_STATS_RS */
+ 16, /* MSM_ISP_STATS_CS */
+ 16, /* MSM_ISP_STATS_IHIST */
+ 16, /* MSM_ISP_STATS_BHIST */
+ 16, /* MSM_ISP_STATS_AEC_BG */
+ };
+
+ stats_burst_len = VFE48_STATS_BURST_LEN;
+ ub_offset = VFE48_UB_SIZE_VFE;
+
+ for (i = 0; i < VFE47_NUM_STATS_TYPE; i++) {
+ ub_offset -= ub_size[i];
+ msm_camera_io_w(stats_burst_len << 30 |
+ ub_offset << 16 | (ub_size[i] - 1),
+ vfe_dev->vfe_base + VFE48_STATS_BASE(i) + 0x14);
+ }
+}
+
+uint32_t msm_vfe48_get_ub_size(struct vfe_device *vfe_dev)
+{
+ return MSM_ISP48_TOTAL_IMAGE_UB_VFE;
+}
+
+
+
struct msm_vfe_hardware_info vfe48_hw_info = {
.num_iommu_ctx = 1,
.num_iommu_secure_ctx = 0,
@@ -269,6 +322,8 @@ struct msm_vfe_hardware_info vfe48_hw_info = {
.min_ab = 100000000,
.vfe_ops = {
.irq_ops = {
+ .read_and_clear_irq_status =
+ msm_vfe47_read_and_clear_irq_status,
.read_irq_status = msm_vfe47_read_irq_status,
.process_camif_irq = msm_vfe47_process_input_irq,
.process_reset_irq = msm_vfe47_process_reset_irq,
@@ -307,7 +362,7 @@ struct msm_vfe_hardware_info vfe48_hw_info = {
.update_cgc_override =
msm_vfe47_axi_update_cgc_override,
.ub_reg_offset = msm_vfe47_ub_reg_offset,
- .get_ub_size = msm_vfe47_get_ub_size,
+ .get_ub_size = msm_vfe48_get_ub_size,
},
.core_ops = {
.reg_update = msm_vfe47_reg_update,
@@ -345,7 +400,7 @@ struct msm_vfe_hardware_info vfe48_hw_info = {
.clear_wm_irq_mask = msm_vfe47_stats_clear_wm_irq_mask,
.cfg_wm_reg = msm_vfe47_stats_cfg_wm_reg,
.clear_wm_reg = msm_vfe47_stats_clear_wm_reg,
- .cfg_ub = msm_vfe47_stats_cfg_ub,
+ .cfg_ub = msm_vfe48_stats_cfg_ub,
.enable_module = msm_vfe47_stats_enable_module,
.update_ping_pong_addr =
msm_vfe47_stats_update_ping_pong_addr,
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp48.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp48.h
index ccca2010105f..3cf819fb1174 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp48.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp48.h
@@ -32,4 +32,8 @@ static inline int msm_vfe_is_vfe48(struct vfe_device *vfe_dev)
MSM_VFE48_HW_VERSION_MASK) == MSM_VFE48_HW_VERSION);
}
+void msm_vfe48_stats_cfg_ub(struct vfe_device *vfe_dev);
+uint32_t msm_vfe48_get_ub_size(struct vfe_device *vfe_dev);
+
+
#endif /* __MSM_ISP48_H__ */
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
index 941119fad78e..60801ff6be0a 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
@@ -558,6 +558,7 @@ static int msm_isp_composite_irq(struct vfe_device *vfe_dev,
{
/* interrupt recv on same vfe w/o recv on other vfe */
if (stream_info->composite_irq[irq] & (1 << vfe_dev->pdev->id)) {
+ msm_isp_dump_ping_pong_mismatch(vfe_dev);
pr_err("%s: irq %d out of sync for dual vfe on vfe %d\n",
__func__, irq, vfe_dev->pdev->id);
return -EINVAL;
@@ -1604,7 +1605,23 @@ void msm_isp_halt_send_error(struct vfe_device *vfe_dev, uint32_t event)
struct msm_isp_event_data error_event;
struct msm_vfe_axi_halt_cmd halt_cmd;
struct vfe_device *temp_dev = NULL;
+ uint32_t irq_status0 = 0, irq_status1 = 0;
+ if (atomic_read(&vfe_dev->error_info.overflow_state) !=
+ NO_OVERFLOW)
+ /* Recovery is already in Progress */
+ return;
+
+ if (event == ISP_EVENT_PING_PONG_MISMATCH &&
+ vfe_dev->axi_data.recovery_count < MAX_RECOVERY_THRESHOLD) {
+ pr_err("%s: ping pong mismatch on vfe%d recovery count %d\n",
+ __func__, vfe_dev->pdev->id,
+ vfe_dev->axi_data.recovery_count);
+ msm_isp_process_overflow_irq(vfe_dev,
+ &irq_status0, &irq_status1, 1);
+ vfe_dev->axi_data.recovery_count++;
+ return;
+ }
memset(&halt_cmd, 0, sizeof(struct msm_vfe_axi_halt_cmd));
memset(&error_event, 0, sizeof(struct msm_isp_event_data));
halt_cmd.stop_camif = 1;
@@ -3777,6 +3794,7 @@ void msm_isp_process_axi_irq_stream(struct vfe_device *vfe_dev,
(~(pingpong_status >>
stream_info->wm[vfe_idx][i]) & 0x1)) {
spin_unlock_irqrestore(&stream_info->lock, flags);
+ msm_isp_dump_ping_pong_mismatch(vfe_dev);
pr_err("%s: Write master ping pong mismatch. Status: 0x%x %x\n",
__func__, pingpong_status,
stream_info->stream_src);
@@ -3798,7 +3816,7 @@ void msm_isp_process_axi_irq_stream(struct vfe_device *vfe_dev,
spin_unlock_irqrestore(&stream_info->lock, flags);
if (rc < 0)
msm_isp_halt_send_error(vfe_dev,
- ISP_EVENT_BUF_FATAL_ERROR);
+ ISP_EVENT_PING_PONG_MISMATCH);
return;
}
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
index 38ce78d941c9..72703c9590ed 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
@@ -195,7 +195,7 @@ static int32_t msm_isp_stats_buf_divert(struct vfe_device *vfe_dev,
spin_unlock_irqrestore(&stream_info->lock, flags);
if (rc < 0)
msm_isp_halt_send_error(vfe_dev,
- ISP_EVENT_BUF_FATAL_ERROR);
+ ISP_EVENT_PING_PONG_MISMATCH);
return rc;
}
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
index 4abb6d1d91a8..e238f54a9100 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
@@ -21,6 +21,9 @@
#include "msm_camera_io_util.h"
#include "cam_smmu_api.h"
#include "msm_isp48.h"
+#define CREATE_TRACE_POINTS
+#include "trace/events/msm_cam.h"
+
#define MAX_ISP_V4l2_EVENTS 100
static DEFINE_MUTEX(bandwidth_mgr_mutex);
@@ -1784,9 +1787,10 @@ static inline void msm_isp_update_error_info(struct vfe_device *vfe_dev,
vfe_dev->error_info.error_count++;
}
-static int msm_isp_process_overflow_irq(
+int msm_isp_process_overflow_irq(
struct vfe_device *vfe_dev,
- uint32_t *irq_status0, uint32_t *irq_status1)
+ uint32_t *irq_status0, uint32_t *irq_status1,
+ uint8_t force_overflow)
{
uint32_t overflow_mask;
uint32_t bus_err = 0;
@@ -1816,7 +1820,7 @@ static int msm_isp_process_overflow_irq(
get_overflow_mask(&overflow_mask);
overflow_mask &= *irq_status1;
- if (overflow_mask) {
+ if (overflow_mask || force_overflow) {
struct msm_isp_event_data error_event;
int i;
struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
@@ -1840,7 +1844,8 @@ static int msm_isp_process_overflow_irq(
pr_err("%s: wm %d assigned to stream handle %x\n",
__func__, i, axi_data->free_wm[i]);
}
-
+ vfe_dev->recovery_irq0_mask = vfe_dev->irq0_mask;
+ vfe_dev->recovery_irq1_mask = vfe_dev->irq1_mask;
vfe_dev->hw_info->vfe_ops.core_ops.
set_halt_restart_mask(vfe_dev);
/* mask off other vfe if dual vfe is used */
@@ -1855,6 +1860,8 @@ static int msm_isp_process_overflow_irq(
atomic_set(&temp_vfe->error_info.overflow_state,
OVERFLOW_DETECTED);
+ temp_vfe->recovery_irq0_mask = temp_vfe->irq0_mask;
+ temp_vfe->recovery_irq1_mask = temp_vfe->irq1_mask;
temp_vfe->hw_info->vfe_ops.core_ops.
set_halt_restart_mask(temp_vfe);
}
@@ -1889,6 +1896,77 @@ void msm_isp_reset_burst_count_and_frame_drop(
msm_isp_reset_framedrop(vfe_dev, stream_info);
}
+void msm_isp_prepare_irq_debug_info(struct vfe_device *vfe_dev,
+ uint32_t irq_status0, uint32_t irq_status1)
+{
+
+ unsigned long flags;
+ struct msm_vfe_irq_debug_info *irq_debug;
+ uint8_t current_index;
+
+ spin_lock_irqsave(&vfe_dev->common_data->vfe_irq_dump.
+ common_dev_irq_dump_lock, flags);
+ /* Fill current VFE debug info */
+ current_index = vfe_dev->common_data->vfe_irq_dump.
+ current_irq_index % MAX_VFE_IRQ_DEBUG_DUMP_SIZE;
+ irq_debug = &vfe_dev->common_data->vfe_irq_dump.
+ irq_debug[current_index];
+ irq_debug->vfe_id = vfe_dev->pdev->id;
+ irq_debug->core_id = smp_processor_id();
+ msm_isp_get_timestamp(&irq_debug->ts, vfe_dev);
+ irq_debug->irq_status0[vfe_dev->pdev->id] = irq_status0;
+ irq_debug->irq_status1[vfe_dev->pdev->id] = irq_status1;
+ irq_debug->ping_pong_status[vfe_dev->pdev->id] =
+ vfe_dev->hw_info->vfe_ops.axi_ops.
+ get_pingpong_status(vfe_dev);
+ if (vfe_dev->is_split &&
+ (vfe_dev->common_data->
+ dual_vfe_res->vfe_dev[!vfe_dev->pdev->id])
+ && (vfe_dev->common_data->dual_vfe_res->
+ vfe_dev[!vfe_dev->pdev->id]->vfe_open_cnt)) {
+ /* Fill other VFE debug Info */
+ vfe_dev->hw_info->vfe_ops.irq_ops.read_irq_status(
+ vfe_dev->common_data->dual_vfe_res->
+ vfe_dev[!vfe_dev->pdev->id],
+ &irq_debug->irq_status0[!vfe_dev->pdev->id],
+ &irq_debug->irq_status1[!vfe_dev->pdev->id]);
+ irq_debug->ping_pong_status[!vfe_dev->pdev->id] =
+ vfe_dev->hw_info->vfe_ops.axi_ops.
+ get_pingpong_status(vfe_dev->common_data->
+ dual_vfe_res->vfe_dev[!vfe_dev->pdev->id]);
+ }
+ vfe_dev->common_data->vfe_irq_dump.current_irq_index++;
+ spin_unlock_irqrestore(&vfe_dev->common_data->vfe_irq_dump.
+ common_dev_irq_dump_lock, flags);
+}
+
+void msm_isp_prepare_tasklet_debug_info(struct vfe_device *vfe_dev,
+ uint32_t irq_status0, uint32_t irq_status1,
+ struct msm_isp_timestamp ts)
+{
+ struct msm_vfe_irq_debug_info *irq_debug;
+ uint8_t current_index;
+ unsigned long flags;
+
+ spin_lock_irqsave(&vfe_dev->common_data->vfe_irq_dump.
+ common_dev_tasklet_dump_lock, flags);
+ current_index = vfe_dev->common_data->vfe_irq_dump.
+ current_tasklet_index % MAX_VFE_IRQ_DEBUG_DUMP_SIZE;
+ irq_debug = &vfe_dev->common_data->vfe_irq_dump.
+ tasklet_debug[current_index];
+ irq_debug->vfe_id = vfe_dev->pdev->id;
+ irq_debug->core_id = smp_processor_id();
+ irq_debug->ts = ts;
+ irq_debug->irq_status0[vfe_dev->pdev->id] = irq_status0;
+ irq_debug->irq_status1[vfe_dev->pdev->id] = irq_status1;
+ irq_debug->ping_pong_status[vfe_dev->pdev->id] =
+ vfe_dev->hw_info->vfe_ops.axi_ops.
+ get_pingpong_status(vfe_dev);
+ vfe_dev->common_data->vfe_irq_dump.current_tasklet_index++;
+ spin_unlock_irqrestore(&vfe_dev->common_data->vfe_irq_dump.
+ common_dev_tasklet_dump_lock, flags);
+}
+
static void msm_isp_enqueue_tasklet_cmd(struct vfe_device *vfe_dev,
uint32_t irq_status0, uint32_t irq_status1)
{
@@ -1923,7 +2001,7 @@ irqreturn_t msm_isp_process_irq(int irq_num, void *data)
uint32_t error_mask0, error_mask1;
vfe_dev->hw_info->vfe_ops.irq_ops.
- read_irq_status(vfe_dev, &irq_status0, &irq_status1);
+ read_and_clear_irq_status(vfe_dev, &irq_status0, &irq_status1);
if ((irq_status0 == 0) && (irq_status1 == 0)) {
ISP_DBG("%s:VFE%d irq_status0 & 1 are both 0\n",
@@ -1932,7 +2010,7 @@ irqreturn_t msm_isp_process_irq(int irq_num, void *data)
}
if (msm_isp_process_overflow_irq(vfe_dev,
- &irq_status0, &irq_status1)) {
+ &irq_status0, &irq_status1, 0)) {
/* if overflow initiated no need to handle the interrupts */
pr_err("overflow processed\n");
return IRQ_HANDLED;
@@ -1953,7 +2031,7 @@ irqreturn_t msm_isp_process_irq(int irq_num, void *data)
ISP_DBG("%s: error_mask0/1 & error_count are set!\n", __func__);
return IRQ_HANDLED;
}
-
+ msm_isp_prepare_irq_debug_info(vfe_dev, irq_status0, irq_status1);
msm_isp_enqueue_tasklet_cmd(vfe_dev, irq_status0, irq_status1);
return IRQ_HANDLED;
@@ -1991,6 +2069,8 @@ void msm_isp_do_tasklet(unsigned long data)
irq_status1 = queue_cmd->vfeInterruptStatus1;
ts = queue_cmd->ts;
spin_unlock_irqrestore(&vfe_dev->tasklet_lock, flags);
+ msm_isp_prepare_tasklet_debug_info(vfe_dev,
+ irq_status0, irq_status1, ts);
ISP_DBG("%s: vfe_id %d status0: 0x%x status1: 0x%x\n",
__func__, vfe_dev->pdev->id, irq_status0, irq_status1);
irq_ops->process_reset_irq(vfe_dev,
@@ -2242,3 +2322,53 @@ void msm_isp_flush_tasklet(struct vfe_device *vfe_dev)
return;
}
+void msm_isp_irq_debug_dump(struct vfe_device *vfe_dev)
+{
+
+ uint8_t i, dump_index;
+ unsigned long flags;
+
+ spin_lock_irqsave(&vfe_dev->common_data->vfe_irq_dump.
+ common_dev_irq_dump_lock, flags);
+ dump_index = vfe_dev->common_data->vfe_irq_dump.
+ current_irq_index;
+ for (i = 0; i < MAX_VFE_IRQ_DEBUG_DUMP_SIZE; i++) {
+ trace_msm_cam_ping_pong_debug_dump(
+ vfe_dev->common_data->vfe_irq_dump.
+ irq_debug[dump_index % MAX_VFE_IRQ_DEBUG_DUMP_SIZE]);
+ dump_index++;
+ }
+ spin_unlock_irqrestore(&vfe_dev->common_data->vfe_irq_dump.
+ common_dev_irq_dump_lock, flags);
+}
+
+
+void msm_isp_tasklet_debug_dump(struct vfe_device *vfe_dev)
+{
+
+ uint8_t i, dump_index;
+ unsigned long flags;
+
+ spin_lock_irqsave(&vfe_dev->common_data->vfe_irq_dump.
+ common_dev_tasklet_dump_lock, flags);
+ dump_index = vfe_dev->common_data->vfe_irq_dump.
+ current_tasklet_index;
+ for (i = 0; i < MAX_VFE_IRQ_DEBUG_DUMP_SIZE; i++) {
+ trace_msm_cam_tasklet_debug_dump(
+ vfe_dev->common_data->vfe_irq_dump.
+ tasklet_debug[
+ dump_index % MAX_VFE_IRQ_DEBUG_DUMP_SIZE]);
+ dump_index++;
+ }
+ spin_unlock_irqrestore(&vfe_dev->common_data->vfe_irq_dump.
+ common_dev_tasklet_dump_lock, flags);
+}
+
+void msm_isp_dump_ping_pong_mismatch(struct vfe_device *vfe_dev)
+{
+
+ trace_msm_cam_string(" ***** msm_isp_dump_irq_debug ****");
+ msm_isp_irq_debug_dump(vfe_dev);
+ trace_msm_cam_string(" ***** msm_isp_dump_taskelet_debug ****");
+ msm_isp_tasklet_debug_dump(vfe_dev);
+}
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h
index f4280581a730..d075bd1721ac 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h
@@ -72,4 +72,9 @@ void msm_isp_print_fourcc_error(const char *origin, uint32_t fourcc_format);
void msm_isp_flush_tasklet(struct vfe_device *vfe_dev);
void msm_isp_get_timestamp(struct msm_isp_timestamp *time_stamp,
struct vfe_device *vfe_dev);
+void msm_isp_dump_ping_pong_mismatch(struct vfe_device *vfe_dev);
+int msm_isp_process_overflow_irq(
+ struct vfe_device *vfe_dev,
+ uint32_t *irq_status0, uint32_t *irq_status1,
+ uint8_t force_overflow);
#endif /* __MSM_ISP_UTIL_H__ */
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
index 4527d6699b88..1cf2c54aa8b8 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
@@ -1372,6 +1372,7 @@ static int cpp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
mutex_unlock(&cpp_dev->mutex);
return rc;
}
+
cpp_dev->state = CPP_STATE_IDLE;
CPP_DBG("Invoking msm_ion_client_create()\n");
@@ -2479,7 +2480,7 @@ static int msm_cpp_cfg_frame(struct cpp_device *cpp_dev,
struct msm_buf_mngr_info buff_mgr_info, dup_buff_mgr_info;
int32_t in_fd;
int32_t num_output_bufs = 1;
- int32_t stripe_base = 0;
+ uint32_t stripe_base = 0;
uint32_t stripe_size;
uint8_t tnr_enabled;
enum msm_camera_buf_mngr_buf_type buf_type =
@@ -2514,6 +2515,13 @@ static int msm_cpp_cfg_frame(struct cpp_device *cpp_dev,
return -EINVAL;
}
+ if (stripe_base == UINT_MAX || new_frame->num_strips >
+ (UINT_MAX - 1 - stripe_base) / stripe_size) {
+ pr_err("Invalid frame message,num_strips %d is large\n",
+ new_frame->num_strips);
+ return -EINVAL;
+ }
+
if ((stripe_base + new_frame->num_strips * stripe_size + 1) !=
new_frame->msg_len) {
pr_err("Invalid frame message,len=%d,expected=%d\n",
@@ -4177,27 +4185,22 @@ static int msm_cpp_update_gdscr_status(struct cpp_device *cpp_dev,
bool status)
{
int rc = 0;
- int value = 0;
-
+ uint32_t msm_cpp_reg_idx;
if (!cpp_dev) {
pr_err("%s: cpp device invalid\n", __func__);
rc = -EINVAL;
goto end;
}
-
- if (cpp_dev->camss_cpp_base) {
- value = msm_camera_io_r(cpp_dev->camss_cpp_base);
- pr_debug("value from camss cpp %x, status %d\n", value, status);
- if (status) {
- value &= CPP_GDSCR_SW_COLLAPSE_ENABLE;
- value |= CPP_GDSCR_HW_CONTROL_ENABLE;
- } else {
- value |= CPP_GDSCR_HW_CONTROL_DISABLE;
- value &= CPP_GDSCR_SW_COLLAPSE_DISABLE;
- }
- pr_debug("value %x after camss cpp mask\n", value);
- msm_camera_io_w(value, cpp_dev->camss_cpp_base);
+ msm_cpp_reg_idx = msm_cpp_get_regulator_index(cpp_dev, "vdd");
+ if (msm_cpp_reg_idx < 0) {
+ pr_err(" Fail to regulator index\n");
+ return -EINVAL;
}
+ rc = msm_camera_regulator_set_mode(cpp_dev->cpp_vdd +
+ msm_cpp_reg_idx, 1, status);
+ if (rc < 0)
+ pr_err("update cpp gdscr status failed\n");
+
end:
return rc;
}
@@ -4306,14 +4309,6 @@ static int cpp_probe(struct platform_device *pdev)
memset(&cpp_vbif, 0, sizeof(struct msm_cpp_vbif_data));
cpp_dev->vbif_data = &cpp_vbif;
- cpp_dev->camss_cpp_base =
- msm_camera_get_reg_base(pdev, "camss_cpp", true);
- if (!cpp_dev->camss_cpp_base) {
- rc = -ENOMEM;
- pr_err("failed to get camss_cpp_base\n");
- goto camss_cpp_base_failed;
- }
-
cpp_dev->base =
msm_camera_get_reg_base(pdev, "cpp", true);
if (!cpp_dev->base) {
@@ -4485,7 +4480,7 @@ vbif_base_failed:
cpp_base_failed:
msm_camera_put_reg_base(pdev, cpp_dev->camss_cpp_base,
"camss_cpp", true);
-camss_cpp_base_failed:
+
kfree(cpp_dev);
return rc;
}
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h
index 470c0cf1131b..e69b9d633a1f 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h
@@ -289,6 +289,8 @@ struct cpp_device {
int msm_cpp_set_micro_clk(struct cpp_device *cpp_dev);
int msm_update_freq_tbl(struct cpp_device *cpp_dev);
int msm_cpp_get_clock_index(struct cpp_device *cpp_dev, const char *clk_name);
+int msm_cpp_get_regulator_index(struct cpp_device *cpp_dev,
+ const char *regulator_name);
long msm_cpp_set_core_clk(struct cpp_device *cpp_dev, long rate, int idx);
void msm_cpp_fetch_dt_params(struct cpp_device *cpp_dev);
int msm_cpp_read_payload_params_from_dt(struct cpp_device *cpp_dev);
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp_soc.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp_soc.c
index ddd32fc5c339..f016c348f144 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp_soc.c
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp_soc.c
@@ -71,6 +71,18 @@ int msm_cpp_get_clock_index(struct cpp_device *cpp_dev, const char *clk_name)
return -EINVAL;
}
+int msm_cpp_get_regulator_index(struct cpp_device *cpp_dev,
+ const char *regulator_name)
+{
+ uint32_t i = 0;
+
+ for (i = 0; i < cpp_dev->num_reg; i++) {
+ if (!strcmp(regulator_name, cpp_dev->cpp_vdd[i].name))
+ return i;
+ }
+ return -EINVAL;
+}
+
static int cpp_get_clk_freq_tbl_dt(struct cpp_device *cpp_dev)
{
uint32_t i, count, min_clk_rate;
diff --git a/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.c b/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.c
index f2f1dca81f18..d7fb2449582c 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.c
+++ b/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2015 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2016 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
@@ -1054,10 +1054,16 @@ static int vpe_reset(struct vpe_device *vpe_dev)
return rc;
}
-static void vpe_update_scale_coef(struct vpe_device *vpe_dev, uint32_t *p)
+static int vpe_update_scale_coef(struct vpe_device *vpe_dev, uint32_t *p)
{
uint32_t i, offset;
offset = *p;
+
+ if (offset > VPE_SCALE_COEFF_MAX_N-VPE_SCALE_COEFF_NUM) {
+ pr_err("%s: invalid offset %d passed in", __func__, offset);
+ return -EINVAL;
+ }
+
for (i = offset; i < (VPE_SCALE_COEFF_NUM + offset); i++) {
VPE_DBG("Setting scale table %d\n", i);
msm_camera_io_w(*(++p),
@@ -1065,6 +1071,8 @@ static void vpe_update_scale_coef(struct vpe_device *vpe_dev, uint32_t *p)
msm_camera_io_w(*(++p),
vpe_dev->base + VPE_SCALE_COEFF_MSBn(i));
}
+
+ return 0;
}
static void vpe_input_plane_config(struct vpe_device *vpe_dev, uint32_t *p)
@@ -1102,13 +1110,16 @@ static void vpe_operation_config(struct vpe_device *vpe_dev, uint32_t *p)
*/
static void msm_vpe_transaction_setup(struct vpe_device *vpe_dev, void *data)
{
- int i;
+ int i, rc = 0;
void *iter = data;
vpe_mem_dump("vpe_transaction", data, VPE_TRANSACTION_SETUP_CONFIG_LEN);
for (i = 0; i < VPE_NUM_SCALER_TABLES; ++i) {
- vpe_update_scale_coef(vpe_dev, (uint32_t *)iter);
+ rc = vpe_update_scale_coef(vpe_dev, (uint32_t *)iter);
+ if (rc != 0)
+ return;
+
iter += VPE_SCALER_CONFIG_LEN;
}
vpe_input_plane_config(vpe_dev, (uint32_t *)iter);
diff --git a/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.h b/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.h
index f1869a2b9776..0c55ff70309e 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.h
+++ b/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 2016 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
@@ -70,6 +70,7 @@
#define VPE_SCALE_COEFF_LSBn(n) (0x50400 + 8 * (n))
#define VPE_SCALE_COEFF_MSBn(n) (0x50404 + 8 * (n))
#define VPE_SCALE_COEFF_NUM 32
+#define VPE_SCALE_COEFF_MAX_N 127
/*********** end of register offset ********************/
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c
index 5e763f74170e..9048d54bed38 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012, 2015-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
@@ -76,7 +76,10 @@ u32 sde_apply_comp_ratio_factor(u32 quota,
#define RES_1080p (1088*1920)
#define RES_UHD (3840*2160)
+#define RES_WQXGA (2560*1600)
#define XIN_HALT_TIMEOUT_US 0x4000
+#define MDSS_MDP_HW_REV_320 0x30020000 /* sdm660 */
+#define MDSS_MDP_HW_REV_330 0x30030000 /* sdm630 */
static int sde_mdp_wait_for_xin_halt(u32 xin_id)
{
@@ -174,15 +177,32 @@ u32 sde_mdp_get_ot_limit(u32 width, u32 height, u32 pixfmt, u32 fps, u32 is_rd)
SDEROT_DBG("w:%d h:%d fps:%d pixfmt:%8.8x yuv:%d res:%d rd:%d\n",
width, height, fps, pixfmt, is_yuv, res, is_rd);
- if (!is_yuv)
- goto exit;
+ switch (mdata->mdss_version) {
+ case MDSS_MDP_HW_REV_320:
+ case MDSS_MDP_HW_REV_330:
+ if ((res <= RES_1080p) && (fps <= 30) && is_yuv)
+ ot_lim = 2;
+ else if ((res <= RES_1080p) && (fps <= 60) && is_yuv)
+ ot_lim = 4;
+ else if ((res <= RES_UHD) && (fps <= 30) && is_yuv)
+ ot_lim = 8;
+ else if ((res <= RES_WQXGA) && (fps <= 60) && is_yuv)
+ ot_lim = 4;
+ else if ((res <= RES_WQXGA) && (fps <= 60))
+ ot_lim = 16;
+ break;
+ default:
+ if (is_yuv) {
+ if ((res <= RES_1080p) && (fps <= 30))
+ ot_lim = 2;
+ else if ((res <= RES_1080p) && (fps <= 60))
+ ot_lim = 4;
+ else if ((res <= RES_UHD) && (fps <= 30))
+ ot_lim = 8;
+ }
+ break;
+ }
- if ((res <= RES_1080p) && (fps <= 30))
- ot_lim = 2;
- else if ((res <= RES_1080p) && (fps <= 60))
- ot_lim = 4;
- else if ((res <= RES_UHD) && (fps <= 30))
- ot_lim = 8;
exit:
SDEROT_DBG("ot_lim=%d\n", ot_lim);
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 9970c4152ef9..30d1bae48e7d 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -4418,6 +4418,7 @@ static void __unload_fw(struct venus_hfi_device *device)
if (device->state != VENUS_STATE_DEINIT)
flush_workqueue(device->venus_pm_workq);
+ __vote_buses(device, NULL, 0);
subsystem_put(device->resources.fw.cookie);
__interface_queues_release(device);
__venus_power_off(device, false);
diff --git a/drivers/mfd/wcd9xxx-irq.c b/drivers/mfd/wcd9xxx-irq.c
index b6a476cd882d..2bc8bdff54f1 100644
--- a/drivers/mfd/wcd9xxx-irq.c
+++ b/drivers/mfd/wcd9xxx-irq.c
@@ -698,20 +698,27 @@ static int wcd9xxx_map_irq(struct wcd9xxx_core_resource *wcd9xxx_res, int irq)
static int wcd9xxx_irq_probe(struct platform_device *pdev)
{
- int irq;
+ int irq, dir_apps_irq = -EINVAL;
struct wcd9xxx_irq_drv_data *data;
struct device_node *node = pdev->dev.of_node;
int ret = -EINVAL;
irq = of_get_named_gpio(node, "qcom,gpio-connect", 0);
- if (!gpio_is_valid(irq)) {
+ if (!gpio_is_valid(irq))
+ dir_apps_irq = platform_get_irq_byname(pdev, "wcd_irq");
+
+ if (!gpio_is_valid(irq) && dir_apps_irq < 0) {
dev_err(&pdev->dev, "TLMM connect gpio not found\n");
return -EPROBE_DEFER;
} else {
- irq = gpio_to_irq(irq);
- if (irq < 0) {
- dev_err(&pdev->dev, "Unable to configure irq\n");
- return irq;
+ if (dir_apps_irq > 0) {
+ irq = dir_apps_irq;
+ } else {
+ irq = gpio_to_irq(irq);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "Unable to configure irq\n");
+ return irq;
+ }
}
dev_dbg(&pdev->dev, "%s: virq = %d\n", __func__, irq);
data = wcd9xxx_irq_add_domain(node, node->parent);
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 6b3d84a2c145..20949487f859 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -7660,11 +7660,11 @@ static void __qseecom_deinit_clk(enum qseecom_ce_hw_instance ce)
}
if (qclk->ce_core_clk != NULL) {
clk_put(qclk->ce_core_clk);
- qclk->ce_clk = NULL;
+ qclk->ce_core_clk = NULL;
}
if (qclk->ce_bus_clk != NULL) {
clk_put(qclk->ce_bus_clk);
- qclk->ce_clk = NULL;
+ qclk->ce_bus_clk = NULL;
}
if (qclk->ce_core_src_clk != NULL) {
clk_put(qclk->ce_core_src_clk);
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index a3f650f5ee9f..7aa01372412d 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1192,10 +1192,6 @@ static int mmc_select_hs400(struct mmc_card *card)
if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
send_status = false;
- /* Reduce frequency to HS frequency */
- max_dtr = card->ext_csd.hs_max_dtr;
- mmc_set_clock(host, max_dtr);
-
/* Switch card to HS mode */
val = EXT_CSD_TIMING_HS;
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
@@ -1211,6 +1207,10 @@ static int mmc_select_hs400(struct mmc_card *card)
/* Set host controller to HS timing */
mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
+ /* Reduce frequency to HS frequency */
+ max_dtr = card->ext_csd.hs_max_dtr;
+ mmc_set_clock(host, max_dtr);
+
if (!send_status) {
err = mmc_switch_status(card);
if (err)
diff --git a/drivers/power/qcom-charger/pmic-voter.c b/drivers/power/qcom-charger/pmic-voter.c
index 8072b63f53fe..e1a92fb23912 100644
--- a/drivers/power/qcom-charger/pmic-voter.c
+++ b/drivers/power/qcom-charger/pmic-voter.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-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
@@ -21,6 +21,7 @@
#include "pmic-voter.h"
#define NUM_MAX_CLIENTS 8
+#define DEBUG_FORCE_CLIENT "DEBUG_FORCE_CLIENT"
static DEFINE_SPINLOCK(votable_list_slock);
static LIST_HEAD(votable_list);
@@ -48,7 +49,12 @@ struct votable {
const char *effective_client);
char *client_strs[NUM_MAX_CLIENTS];
bool voted_on;
- struct dentry *ent;
+ struct dentry *root;
+ struct dentry *status_ent;
+ u32 force_val;
+ struct dentry *force_val_ent;
+ bool force_active;
+ struct dentry *force_active_ent;
};
/**
@@ -236,6 +242,9 @@ int get_client_vote(struct votable *votable, const char *client_str)
*/
int get_effective_result_locked(struct votable *votable)
{
+ if (votable->force_active)
+ return votable->force_val;
+
return votable->effective_result;
}
@@ -249,8 +258,29 @@ int get_effective_result(struct votable *votable)
return value;
}
+/**
+ * get_effective_client() -
+ * get_effective_client_locked() -
+ * The unlocked and locked variants of getting the effective client
+ * amongst all the enabled voters.
+ *
+ * @votable: the votable object
+ *
+ * Returns:
+ * The effective client.
+ * For MIN and MAX votable, returns NULL when the votable
+ * object has been created but no clients have casted their votes or
+ * the last enabled client disables its vote.
+ * For SET_ANY votable it returns NULL too when no clients have casted
+ * their votes. But for SET_ANY since there is no concept of abstaining
+ * from election, the only client that casts a vote or the client that
+ * caused the result to change is returned.
+ */
const char *get_effective_client_locked(struct votable *votable)
{
+ if (votable->force_active)
+ return DEBUG_FORCE_CLIENT;
+
return get_client_str(votable, votable->effective_client_id);
}
@@ -313,7 +343,7 @@ int vote(struct votable *votable, const char *client_str, bool enabled, int val)
if ((votable->votes[client_id].enabled == enabled) &&
(votable->votes[client_id].value == val)) {
- pr_debug("%s: %s,%d same vote %s of %d\n",
+ pr_debug("%s: %s,%d same vote %s of val=%d\n",
votable->name,
client_str, client_id,
enabled ? "on" : "off",
@@ -325,13 +355,13 @@ int vote(struct votable *votable, const char *client_str, bool enabled, int val)
votable->votes[client_id].value = val;
if (similar_vote && votable->voted_on) {
- pr_debug("%s: %s,%d Similar vote %s of %d\n",
+ pr_debug("%s: %s,%d Ignoring similar vote %s of val=%d\n",
votable->name,
client_str, client_id, enabled ? "on" : "off", val);
goto out;
}
- pr_debug("%s: %s,%d voting %s of %d\n",
+ pr_debug("%s: %s,%d voting %s of val=%d\n",
votable->name,
client_str, client_id, enabled ? "on" : "off", val);
switch (votable->type) {
@@ -361,7 +391,7 @@ int vote(struct votable *votable, const char *client_str, bool enabled, int val)
votable->name, effective_result,
get_client_str(votable, effective_id),
effective_id);
- if (votable->callback)
+ if (votable->callback && !votable->force_active)
rc = votable->callback(votable, votable->data,
effective_result,
get_client_str(votable, effective_id));
@@ -412,6 +442,42 @@ out:
return NULL;
}
+static int force_active_get(void *data, u64 *val)
+{
+ struct votable *votable = data;
+
+ *val = votable->force_active;
+
+ return 0;
+}
+
+static int force_active_set(void *data, u64 val)
+{
+ struct votable *votable = data;
+ int rc = 0;
+
+ lock_votable(votable);
+ votable->force_active = !!val;
+
+ if (!votable->callback)
+ goto out;
+
+ if (votable->force_active) {
+ rc = votable->callback(votable, votable->data,
+ votable->force_val,
+ DEBUG_FORCE_CLIENT);
+ } else {
+ rc = votable->callback(votable, votable->data,
+ votable->effective_result,
+ get_client_str(votable, votable->effective_client_id));
+ }
+out:
+ unlock_votable(votable);
+ return rc;
+}
+DEFINE_SIMPLE_ATTRIBUTE(votable_force_ops, force_active_get, force_active_set,
+ "%lld\n");
+
static int show_votable_clients(struct seq_file *m, void *data)
{
struct votable *votable = m->private;
@@ -421,8 +487,8 @@ static int show_votable_clients(struct seq_file *m, void *data)
lock_votable(votable);
- seq_printf(m, "%s:\n", votable->name);
- seq_puts(m, "Clients:\n");
+ seq_printf(m, "Votable %s:\n", votable->name);
+ seq_puts(m, "clients:\n");
for (i = 0; i < votable->num_clients; i++) {
if (votable->client_strs[i]) {
seq_printf(m, "%-15s:\t\ten=%d\t\tv=%d\n",
@@ -444,7 +510,7 @@ static int show_votable_clients(struct seq_file *m, void *data)
break;
}
- seq_printf(m, "Type: %s\n", type_str);
+ seq_printf(m, "type: %s\n", type_str);
seq_puts(m, "Effective:\n");
effective_client_str = get_effective_client_locked(votable);
seq_printf(m, "%-15s:\t\tv=%d\n",
@@ -455,16 +521,16 @@ static int show_votable_clients(struct seq_file *m, void *data)
return 0;
}
-static int votable_debugfs_open(struct inode *inode, struct file *file)
+static int votable_status_open(struct inode *inode, struct file *file)
{
struct votable *votable = inode->i_private;
return single_open(file, show_votable_clients, votable);
}
-static const struct file_operations votable_debugfs_ops = {
+static const struct file_operations votable_status_ops = {
.owner = THIS_MODULE,
- .open = votable_debugfs_open,
+ .open = votable_status_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
@@ -527,11 +593,45 @@ struct votable *create_votable(const char *name,
list_add(&votable->list, &votable_list);
spin_unlock_irqrestore(&votable_list_slock, flags);
- votable->ent = debugfs_create_file(name, S_IFREG | S_IRUGO,
- debug_root, votable,
- &votable_debugfs_ops);
- if (!votable->ent) {
- pr_err("Couldn't create %s debug file\n", name);
+ votable->root = debugfs_create_dir(name, debug_root);
+ if (!votable->root) {
+ pr_err("Couldn't create debug dir %s\n", name);
+ kfree(votable->name);
+ kfree(votable);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ votable->status_ent = debugfs_create_file("status", S_IFREG | S_IRUGO,
+ votable->root, votable,
+ &votable_status_ops);
+ if (!votable->status_ent) {
+ pr_err("Couldn't create status dbg file for %s\n", name);
+ debugfs_remove_recursive(votable->root);
+ kfree(votable->name);
+ kfree(votable);
+ return ERR_PTR(-EEXIST);
+ }
+
+ votable->force_val_ent = debugfs_create_u32("force_val",
+ S_IFREG | S_IWUSR | S_IRUGO,
+ votable->root,
+ &(votable->force_val));
+
+ if (!votable->force_val_ent) {
+ pr_err("Couldn't create force_val dbg file for %s\n", name);
+ debugfs_remove_recursive(votable->root);
+ kfree(votable->name);
+ kfree(votable);
+ return ERR_PTR(-EEXIST);
+ }
+
+ votable->force_active_ent = debugfs_create_file("force_active",
+ S_IFREG | S_IRUGO,
+ votable->root, votable,
+ &votable_force_ops);
+ if (!votable->force_active_ent) {
+ pr_err("Couldn't create force_active dbg file for %s\n", name);
+ debugfs_remove_recursive(votable->root);
kfree(votable->name);
kfree(votable);
return ERR_PTR(-EEXIST);
@@ -552,7 +652,8 @@ void destroy_votable(struct votable *votable)
list_del(&votable->list);
spin_unlock_irqrestore(&votable_list_slock, flags);
- debugfs_remove(votable->ent);
+ debugfs_remove_recursive(votable->root);
+
for (i = 0; i < votable->num_clients && votable->client_strs[i]; i++)
kfree(votable->client_strs[i]);
diff --git a/drivers/power/qcom-charger/qpnp-fg-gen3.c b/drivers/power/qcom-charger/qpnp-fg-gen3.c
index 02f5ea06e22d..8523efa1a4ab 100644
--- a/drivers/power/qcom-charger/qpnp-fg-gen3.c
+++ b/drivers/power/qcom-charger/qpnp-fg-gen3.c
@@ -2301,7 +2301,14 @@ static int fg_get_time_to_full(struct fg_chip *chip, int *val)
return -ENODATA;
}
- if (chip->charge_status == POWER_SUPPLY_STATUS_FULL) {
+ rc = fg_get_prop_capacity(chip, &msoc);
+ if (rc < 0) {
+ pr_err("failed to get msoc rc=%d\n", rc);
+ return rc;
+ }
+ fg_dbg(chip, FG_TTF, "msoc=%d\n", msoc);
+
+ if (msoc >= 100) {
*val = 0;
return 0;
}
@@ -2364,13 +2371,6 @@ static int fg_get_time_to_full(struct fg_chip *chip, int *val)
act_cap_uah *= MILLI_UNIT;
fg_dbg(chip, FG_TTF, "actual_capacity_uah=%d\n", act_cap_uah);
- rc = fg_get_prop_capacity(chip, &msoc);
- if (rc < 0) {
- pr_err("failed to get msoc rc=%d\n", rc);
- return rc;
- }
- fg_dbg(chip, FG_TTF, "msoc=%d\n", msoc);
-
rc = fg_get_sram_prop(chip, FG_SRAM_FULL_SOC, &full_soc);
if (rc < 0) {
pr_err("failed to get full soc rc=%d\n", rc);
@@ -2410,7 +2410,7 @@ skip_cc_estimate:
fg_dbg(chip, FG_TTF, "t_predicted_cc=%lld\n", t_predicted_cc);
/* CV estimate starts here */
- if (chip->charge_type == POWER_SUPPLY_CHARGE_TYPE_TAPER)
+ if (chip->charge_type >= POWER_SUPPLY_CHARGE_TYPE_TAPER)
ln_val = ibatt_avg / abs(chip->dt.sys_term_curr_ma);
else
ln_val = i_cc2cv / abs(chip->dt.sys_term_curr_ma);
diff --git a/drivers/power/qcom-charger/qpnp-qnovo.c b/drivers/power/qcom-charger/qpnp-qnovo.c
index ac1c900f4771..7bc90fbf2929 100644
--- a/drivers/power/qcom-charger/qpnp-qnovo.c
+++ b/drivers/power/qcom-charger/qpnp-qnovo.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016 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
@@ -99,8 +99,6 @@
#define VADC_LSB_NA 1220700
#define GAIN_LSB_FACTOR 976560
-#define MIN_EN_UA 1000000
-
#define USER_VOTER "user_voter"
#define OK_TO_QNOVO_VOTER "ok_to_qnovo_voter"
@@ -119,9 +117,7 @@ enum {
struct chg_props {
bool charging;
bool usb_online;
- int usb_input_uA;
bool dc_online;
- int dc_input_uA;
};
struct chg_status {
@@ -1092,7 +1088,6 @@ static void get_chg_props(struct qnovo *chip, struct chg_props *cp)
}
cp->usb_online = false;
- cp->usb_input_uA = 0;
if (!chip->usb_psy)
chip->usb_psy = power_supply_get_by_name("usb");
if (chip->usb_psy) {
@@ -1102,17 +1097,9 @@ static void get_chg_props(struct qnovo *chip, struct chg_props *cp)
pr_err("Couldn't read usb online rc = %d\n", rc);
else
cp->usb_online = (bool)pval.intval;
-
- rc = power_supply_get_property(chip->usb_psy,
- POWER_SUPPLY_PROP_CURRENT_MAX, &pval);
- if (rc < 0)
- pr_err("Couldn't read usb current max rc = %d\n", rc);
- else
- cp->usb_input_uA = pval.intval;
}
cp->dc_online = false;
- cp->dc_input_uA = 0;
if (!chip->dc_psy)
chip->dc_psy = power_supply_get_by_name("dc");
if (chip->dc_psy) {
@@ -1122,13 +1109,6 @@ static void get_chg_props(struct qnovo *chip, struct chg_props *cp)
pr_err("Couldn't read dc online rc = %d\n", rc);
else
cp->dc_online = (bool)pval.intval;
-
- rc = power_supply_get_property(chip->dc_psy,
- POWER_SUPPLY_PROP_CURRENT_MAX, &pval);
- if (rc < 0)
- pr_err("Couldn't read dc current max rc = %d\n", rc);
- else
- cp->dc_input_uA = pval.intval;
}
}
@@ -1138,8 +1118,7 @@ static void get_chg_status(struct qnovo *chip, const struct chg_props *cp,
cs->ok_to_qnovo = false;
if (cp->charging &&
- ((cp->usb_online && cp->usb_input_uA >= MIN_EN_UA)
- || (cp->dc_online && cp->dc_input_uA >= MIN_EN_UA)))
+ (cp->usb_online || cp->dc_online))
cs->ok_to_qnovo = true;
}
diff --git a/drivers/power/qcom-charger/qpnp-smb2.c b/drivers/power/qcom-charger/qpnp-smb2.c
index 463cbb7cb8ba..a07325102631 100644
--- a/drivers/power/qcom-charger/qpnp-smb2.c
+++ b/drivers/power/qcom-charger/qpnp-smb2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016 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
@@ -1144,13 +1144,6 @@ static int smb2_configure_typec(struct smb_charger *chg)
return rc;
}
- rc = smblib_validate_initial_typec_legacy_status(chg);
- if (rc < 0) {
- dev_err(chg->dev, "Couldn't validate typec legacy status rc=%d\n",
- rc);
- return rc;
- }
-
return rc;
}
@@ -1891,6 +1884,12 @@ static int smb2_probe(struct platform_device *pdev)
goto cleanup;
}
+ rc = smb2_init_hw(chip);
+ if (rc < 0) {
+ pr_err("Couldn't initialize hardware rc=%d\n", rc);
+ goto cleanup;
+ }
+
rc = smb2_init_dc_psy(chip);
if (rc < 0) {
pr_err("Couldn't initialize dc psy rc=%d\n", rc);
@@ -1923,12 +1922,6 @@ static int smb2_probe(struct platform_device *pdev)
goto cleanup;
}
- rc = smb2_init_hw(chip);
- if (rc < 0) {
- pr_err("Couldn't initialize hardware rc=%d\n", rc);
- goto cleanup;
- }
-
rc = smb2_determine_initial_status(chip);
if (rc < 0) {
pr_err("Couldn't determine initial status rc=%d\n",
diff --git a/drivers/power/qcom-charger/smb-lib.c b/drivers/power/qcom-charger/smb-lib.c
index 86140386f0e3..6d010a11d034 100644
--- a/drivers/power/qcom-charger/smb-lib.c
+++ b/drivers/power/qcom-charger/smb-lib.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016 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
@@ -16,7 +16,7 @@
#include <linux/iio/consumer.h>
#include <linux/power_supply.h>
#include <linux/regulator/driver.h>
-#include <linux/qpnp/power-on.h>
+#include <linux/input/qpnp-power-on.h>
#include <linux/irq.h>
#include "smb-lib.h"
#include "smb-reg.h"
@@ -627,6 +627,21 @@ static void smblib_uusb_removal(struct smb_charger *chg)
smblib_err(chg, "Couldn't un-vote for USB ICL rc=%d\n", rc);
}
+static bool smblib_sysok_reason_usbin(struct smb_charger *chg)
+{
+ int rc;
+ u8 stat;
+
+ rc = smblib_read(chg, SYSOK_REASON_STATUS_REG, &stat);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't get SYSOK_REASON_STATUS rc=%d\n", rc);
+ /* assuming 'not usbin' in case of read failure */
+ return false;
+ }
+
+ return stat & SYSOK_REASON_USBIN_BIT;
+}
+
/*********************
* VOTABLE CALLBACKS *
*********************/
@@ -2852,6 +2867,8 @@ static void smblib_handle_typec_removal(struct smb_charger *chg)
typec_source_removal(chg);
typec_sink_removal(chg);
+ chg->usb_ever_removed = true;
+
smblib_update_usb_type(chg);
}
@@ -2860,6 +2877,7 @@ static void smblib_handle_typec_insertion(struct smb_charger *chg,
{
int rp;
bool vbus_cc_short = false;
+ bool valid_legacy_cable;
vote(chg->pd_disallowed_votable_indirect, CC_DETACHED_VOTER, false, 0);
@@ -2871,10 +2889,12 @@ static void smblib_handle_typec_insertion(struct smb_charger *chg,
typec_sink_removal(chg);
}
+ valid_legacy_cable = legacy_cable &&
+ (chg->usb_ever_removed || !smblib_sysok_reason_usbin(chg));
vote(chg->pd_disallowed_votable_indirect, LEGACY_CABLE_VOTER,
- legacy_cable, 0);
+ valid_legacy_cable, 0);
- if (legacy_cable) {
+ if (valid_legacy_cable) {
rp = smblib_get_prop_ufp_mode(chg);
if (rp == POWER_SUPPLY_TYPEC_SOURCE_HIGH
|| rp == POWER_SUPPLY_TYPEC_NON_COMPLIANT) {
@@ -3476,40 +3496,3 @@ int smblib_deinit(struct smb_charger *chg)
return 0;
}
-
-int smblib_validate_initial_typec_legacy_status(struct smb_charger *chg)
-{
- int rc;
- u8 stat;
-
-
- if (qpnp_pon_is_warm_reset())
- return 0;
-
- rc = smblib_read(chg, TYPE_C_STATUS_5_REG, &stat);
- if (rc < 0) {
- smblib_err(chg, "Couldn't read TYPE_C_STATUS_5 rc=%d\n", rc);
- return rc;
- }
-
- if ((stat & TYPEC_LEGACY_CABLE_STATUS_BIT) == 0)
- return 0;
-
- rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
- TYPEC_DISABLE_CMD_BIT, TYPEC_DISABLE_CMD_BIT);
- if (rc < 0) {
- smblib_err(chg, "Couldn't disable typec rc=%d\n", rc);
- return rc;
- }
-
- usleep_range(150000, 151000);
-
- rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
- TYPEC_DISABLE_CMD_BIT, 0);
- if (rc < 0) {
- smblib_err(chg, "Couldn't enable typec rc=%d\n", rc);
- return rc;
- }
-
- return 0;
-}
diff --git a/drivers/power/qcom-charger/smb-lib.h b/drivers/power/qcom-charger/smb-lib.h
index f6335aae2637..b65c0211405a 100644
--- a/drivers/power/qcom-charger/smb-lib.h
+++ b/drivers/power/qcom-charger/smb-lib.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016 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
@@ -233,6 +233,7 @@ struct smb_charger {
/* extcon for VBUS / ID notification to USB for uUSB */
struct extcon_dev *extcon;
+ bool usb_ever_removed;
};
int smblib_read(struct smb_charger *chg, u16 addr, u8 *val);
@@ -377,8 +378,6 @@ int smblib_get_prop_slave_current_now(struct smb_charger *chg,
int smblib_set_prop_ship_mode(struct smb_charger *chg,
const union power_supply_propval *val);
-int smblib_validate_initial_typec_legacy_status(struct smb_charger *chg);
-
int smblib_init(struct smb_charger *chg);
int smblib_deinit(struct smb_charger *chg);
#endif /* __SMB2_CHARGER_H */
diff --git a/drivers/power/qcom-charger/smb-reg.h b/drivers/power/qcom-charger/smb-reg.h
index a30efbe3651e..a9606ab1944b 100644
--- a/drivers/power/qcom-charger/smb-reg.h
+++ b/drivers/power/qcom-charger/smb-reg.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016 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
@@ -860,6 +860,10 @@ enum {
#define WDOG_STATUS_1_BIT BIT(1)
#define BARK_BITE_STATUS_BIT BIT(0)
+#define SYSOK_REASON_STATUS_REG (MISC_BASE + 0x0D)
+#define SYSOK_REASON_DCIN_BIT BIT(1)
+#define SYSOK_REASON_USBIN_BIT BIT(0)
+
/* MISC Interrupt Bits */
#define SWITCHER_POWER_OK_RT_STS_BIT BIT(7)
#define TEMPERATURE_CHANGE_RT_STS_BIT BIT(6)
diff --git a/drivers/power/reset/msm-poweroff.c b/drivers/power/reset/msm-poweroff.c
index 267df592ba8a..cd02ed5bd46a 100644
--- a/drivers/power/reset/msm-poweroff.c
+++ b/drivers/power/reset/msm-poweroff.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-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
@@ -23,7 +23,7 @@
#include <linux/reboot.h>
#include <linux/pm.h>
#include <linux/delay.h>
-#include <linux/qpnp/power-on.h>
+#include <linux/input/qpnp-power-on.h>
#include <linux/of_address.h>
#include <asm/cacheflush.h>
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 6e88e4b11273..2138e81bb9e9 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1344,7 +1344,8 @@ start:
hba->clk_gating.state = REQ_CLKS_ON;
trace_ufshcd_clk_gating(dev_name(hba->dev),
hba->clk_gating.state);
- schedule_work(&hba->clk_gating.ungate_work);
+ queue_work(hba->clk_gating.ungating_workq,
+ &hba->clk_gating.ungate_work);
/*
* fall through to check if we should wait for this
* work to be done or not.
@@ -1617,6 +1618,7 @@ static enum hrtimer_restart ufshcd_clkgate_hrtimer_handler(
static void ufshcd_init_clk_gating(struct ufs_hba *hba)
{
struct ufs_clk_gating *gating = &hba->clk_gating;
+ char wq_name[sizeof("ufs_clk_ungating_00")];
hba->clk_gating.state = CLKS_ON;
@@ -1645,6 +1647,10 @@ static void ufshcd_init_clk_gating(struct ufs_hba *hba)
hrtimer_init(&gating->gate_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
gating->gate_hrtimer.function = ufshcd_clkgate_hrtimer_handler;
+ snprintf(wq_name, ARRAY_SIZE(wq_name), "ufs_clk_ungating_%d",
+ hba->host->host_no);
+ hba->clk_gating.ungating_workq = create_singlethread_workqueue(wq_name);
+
gating->is_enabled = true;
gating->delay_ms_pwr_save = UFSHCD_CLK_GATING_DELAY_MS_PWR_SAVE;
@@ -1707,6 +1713,7 @@ static void ufshcd_exit_clk_gating(struct ufs_hba *hba)
device_remove_file(hba->dev, &hba->clk_gating.enable_attr);
ufshcd_cancel_gate_work(hba);
cancel_work_sync(&hba->clk_gating.ungate_work);
+ destroy_workqueue(hba->clk_gating.ungating_workq);
}
static void ufshcd_set_auto_hibern8_timer(struct ufs_hba *hba, u32 delay)
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index b20afd85beab..c34a998aac17 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -431,6 +431,7 @@ struct ufs_clk_gating {
struct device_attribute enable_attr;
bool is_enabled;
int active_reqs;
+ struct workqueue_struct *ungating_workq;
};
/* Hibern8 state */
diff --git a/drivers/soc/qcom/spcom.c b/drivers/soc/qcom/spcom.c
index e8ea99827403..9b71083e4f27 100644
--- a/drivers/soc/qcom/spcom.c
+++ b/drivers/soc/qcom/spcom.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-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
@@ -274,6 +274,8 @@ static int spcom_open(struct spcom_channel *ch, unsigned int timeout_msec);
static int spcom_close(struct spcom_channel *ch);
static void spcom_notify_rx_abort(void *handle, const void *priv,
const void *pkt_priv);
+static struct spcom_channel *spcom_find_channel_by_name(const char *name);
+static int spcom_unlock_ion_buf(struct spcom_channel *ch, int fd);
/**
* spcom_is_ready() - driver is initialized and ready.
@@ -347,6 +349,9 @@ static int spcom_create_predefined_channels_chardev(void)
static void spcom_link_state_notif_cb(struct glink_link_state_cb_info *cb_info,
void *priv)
{
+ struct spcom_channel *ch = NULL;
+ const char *ch_name = "sp_kernel";
+
spcom_dev->link_state = cb_info->link_state;
pr_debug("spcom_link_state_notif_cb called. transport = %s edge = %s\n",
@@ -359,6 +364,17 @@ static void spcom_link_state_notif_cb(struct glink_link_state_cb_info *cb_info,
break;
case GLINK_LINK_STATE_DOWN:
pr_err("GLINK_LINK_STATE_DOWN.\n");
+
+ /*
+ * Free all the SKP ION buffers that were locked
+ * for SPSS app swapping, when remote subsystem reset.
+ */
+ pr_debug("Free all SKP ION buffers on SSR.\n");
+ ch = spcom_find_channel_by_name(ch_name);
+ if (!ch)
+ pr_err("failed to find channel [%s].\n", ch_name);
+ else
+ spcom_unlock_ion_buf(ch, SPCOM_ION_FD_UNLOCK_ALL);
break;
default:
pr_err("unknown link_state [%d].\n", cb_info->link_state);
@@ -1643,24 +1659,18 @@ static int spcom_handle_lock_ion_buf_command(struct spcom_channel *ch,
}
/**
- * spcom_handle_unlock_ion_buf_command() - Unlock an ION buffer.
+ * spcom_unlock_ion_buf() - Unlock an ION buffer.
*
* Unlock an ION buffer, let it be free, when it is no longer being used by
* the remote subsystem.
*/
-static int spcom_handle_unlock_ion_buf_command(struct spcom_channel *ch,
- void *cmd_buf, int size)
+static int spcom_unlock_ion_buf(struct spcom_channel *ch, int fd)
{
- struct spcom_user_command *cmd = cmd_buf;
- int fd = cmd->arg;
struct ion_client *ion_client = spcom_dev->ion_client;
int i;
+ bool found = false;
- if (size != sizeof(*cmd)) {
- pr_err("cmd size [%d] , expected [%d].\n",
- (int) size, (int) sizeof(*cmd));
- return -EINVAL;
- }
+ pr_debug("Unlock ion buf ch [%s] fd [%d].\n", ch->name, fd);
/* Check ION client */
if (ion_client == NULL) {
@@ -1669,6 +1679,8 @@ static int spcom_handle_unlock_ion_buf_command(struct spcom_channel *ch,
}
if (fd == (int) SPCOM_ION_FD_UNLOCK_ALL) {
+ pr_debug("unlocked ALL ion buf ch [%s].\n", ch->name);
+ found = true;
/* unlock all ION buf */
for (i = 0 ; i < ARRAY_SIZE(ch->ion_handle_table) ; i++) {
if (ch->ion_handle_table[i] != NULL) {
@@ -1686,15 +1698,45 @@ static int spcom_handle_unlock_ion_buf_command(struct spcom_channel *ch,
ch->ion_handle_table[i] = NULL;
ch->ion_fd_table[i] = -1;
pr_debug("unlocked ion buf#[%d].\n", i);
+ found = true;
break;
}
}
}
+ if (!found) {
+ pr_err("ch [%s] fd [%d] was not found.\n", ch->name, fd);
+ return -ENODEV;
+ }
+
return 0;
}
/**
+ * spcom_handle_unlock_ion_buf_command() - Unlock an ION buffer.
+ *
+ * Unlock an ION buffer, let it be free, when it is no longer being used by
+ * the remote subsystem.
+ */
+static int spcom_handle_unlock_ion_buf_command(struct spcom_channel *ch,
+ void *cmd_buf, int size)
+{
+ int ret;
+ struct spcom_user_command *cmd = cmd_buf;
+ int fd = cmd->arg;
+
+ if (size != sizeof(*cmd)) {
+ pr_err("cmd size [%d] , expected [%d].\n",
+ (int) size, (int) sizeof(*cmd));
+ return -EINVAL;
+ }
+
+ ret = spcom_unlock_ion_buf(ch, fd);
+
+ return ret;
+}
+
+/**
* spcom_handle_fake_ssr_command() - Handle fake ssr command from user space.
*/
static int spcom_handle_fake_ssr_command(struct spcom_channel *ch, int arg)
diff --git a/drivers/thermal/msm-tsens.c b/drivers/thermal/msm-tsens.c
index 4585313772ff..b7733e90fc8b 100644
--- a/drivers/thermal/msm-tsens.c
+++ b/drivers/thermal/msm-tsens.c
@@ -170,10 +170,8 @@
#define TSENS_DEBUG_OFFSET_WORD3 0xc
#define TSENS_DEBUG_OFFSET_ROW 0x10
#define TSENS_DEBUG_DECIDEGC -950
-#define TSENS_DEBUG_MIN_CYCLE 63000
-#define TSENS_DEBUG_MAX_CYCLE 64000
-#define TSENS_DEBUG_POLL_MIN 200000
-#define TSENS_DEBUG_POLL_MAX 210000
+#define TSENS_DEBUG_CYCLE_MS 64
+#define TSENS_DEBUG_POLL_MS 200
#define TSENS_DEBUG_BUS_ID2_MIN_CYCLE 50
#define TSENS_DEBUG_BUS_ID2_MAX_CYCLE 51
#define TSENS_DEBUG_ID_MASK_1_4 0xffffffe1
@@ -1412,8 +1410,7 @@ static void tsens_poll(struct work_struct *work)
spin_unlock_irqrestore(&tmdev->tsens_crit_lock, flags);
if (tmdev->tsens_critical_poll) {
- usleep_range(TSENS_DEBUG_POLL_MIN,
- TSENS_DEBUG_POLL_MAX);
+ msleep(TSENS_DEBUG_POLL_MS);
sensor_status_addr = TSENS_TM_SN_STATUS(tmdev->tsens_addr);
spin_lock_irqsave(&tmdev->tsens_crit_lock, flags);
@@ -1567,8 +1564,7 @@ debug_start:
offset += TSENS_DEBUG_OFFSET_ROW;
}
loop++;
- usleep_range(TSENS_DEBUG_MIN_CYCLE,
- TSENS_DEBUG_MAX_CYCLE);
+ msleep(TSENS_DEBUG_CYCLE_MS);
}
BUG();
}
diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c
index 47e077d180ec..b3d223a76f07 100644
--- a/drivers/usb/gadget/function/f_gsi.c
+++ b/drivers/usb/gadget/function/f_gsi.c
@@ -3007,6 +3007,9 @@ static void gsi_free_inst(struct usb_function_instance *f)
{
struct gsi_opts *opts = container_of(f, struct gsi_opts, func_inst);
+ if (!opts->gsi)
+ return;
+
if (opts->gsi->c_port.ctrl_device.fops)
misc_deregister(&opts->gsi->c_port.ctrl_device);
diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c
index 423a15d82679..f2c2287d7d8c 100644
--- a/drivers/video/fbdev/msm/mdss_dsi.c
+++ b/drivers/video/fbdev/msm/mdss_dsi.c
@@ -2090,6 +2090,13 @@ static int __mdss_dsi_dfps_update_clks(struct mdss_panel_data *pdata,
MIPI_OUTP((sctrl_pdata->ctrl_base) + DSI_DYNAMIC_REFRESH_CTRL,
0x00);
+ rc = mdss_dsi_phy_pll_reset_status(ctrl_pdata);
+ if (rc) {
+ pr_err("%s: pll cannot be locked reset core ready failed %d\n",
+ __func__, rc);
+ goto dfps_timeout;
+ }
+
__mdss_dsi_mask_dfps_errors(ctrl_pdata, false);
if (sctrl_pdata)
__mdss_dsi_mask_dfps_errors(sctrl_pdata, false);
diff --git a/drivers/video/fbdev/msm/mdss_dsi.h b/drivers/video/fbdev/msm/mdss_dsi.h
index 6c840c8459ae..1743a5f23b5d 100644
--- a/drivers/video/fbdev/msm/mdss_dsi.h
+++ b/drivers/video/fbdev/msm/mdss_dsi.h
@@ -694,6 +694,7 @@ void mdss_dsi_dfps_config_8996(struct mdss_dsi_ctrl_pdata *ctrl);
void mdss_dsi_set_burst_mode(struct mdss_dsi_ctrl_pdata *ctrl);
void mdss_dsi_set_reg(struct mdss_dsi_ctrl_pdata *ctrl, int off,
u32 mask, u32 val);
+int mdss_dsi_phy_pll_reset_status(struct mdss_dsi_ctrl_pdata *ctrl);
static inline const char *__mdss_dsi_pm_name(enum dsi_pm_type module)
{
diff --git a/drivers/video/fbdev/msm/mdss_dsi_host.c b/drivers/video/fbdev/msm/mdss_dsi_host.c
index 635ef68b4e94..22a424cc15b8 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_host.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_host.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-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
@@ -1216,6 +1216,15 @@ void mdss_dsi_dsc_config(struct mdss_dsi_ctrl_pdata *ctrl, struct dsc_desc *dsc)
{
u32 data, offset;
+ if (!dsc) {
+ if (ctrl->panel_mode == DSI_VIDEO_MODE)
+ offset = MDSS_DSI_VIDEO_COMPRESSION_MODE_CTRL;
+ else
+ offset = MDSS_DSI_COMMAND_COMPRESSION_MODE_CTRL;
+ MIPI_OUTP((ctrl->ctrl_base) + offset, 0);
+ return;
+ }
+
if (dsc->pkt_per_line <= 0) {
pr_err("%s: Error: pkt_per_line cannot be negative or 0\n",
__func__);
@@ -1404,8 +1413,7 @@ static void mdss_dsi_mode_setup(struct mdss_panel_data *pdata)
MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x5C, stream_total);
}
- if (dsc) /* compressed */
- mdss_dsi_dsc_config(ctrl_pdata, dsc);
+ mdss_dsi_dsc_config(ctrl_pdata, dsc);
}
void mdss_dsi_ctrl_setup(struct mdss_dsi_ctrl_pdata *ctrl)
diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c
index 29288f0bca74..c3ae4c1f8c17 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_panel.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c
@@ -1494,8 +1494,9 @@ static int mdss_dsi_parse_topology_config(struct device_node *np,
goto end;
}
}
- rc = of_property_read_string(cfg_np, "qcom,split-mode", &data);
- if (!rc && !strcmp(data, "pingpong-split"))
+
+ if (!of_property_read_string(cfg_np, "qcom,split-mode",
+ &data) && !strcmp(data, "pingpong-split"))
pinfo->use_pingpong_split = true;
if (((timing->lm_widths[0]) || (timing->lm_widths[1])) &&
diff --git a/drivers/video/fbdev/msm/msm_mdss_io_8974.c b/drivers/video/fbdev/msm/msm_mdss_io_8974.c
index fdd888edc2fb..3dc2e952b5dd 100644
--- a/drivers/video/fbdev/msm/msm_mdss_io_8974.c
+++ b/drivers/video/fbdev/msm/msm_mdss_io_8974.c
@@ -16,6 +16,8 @@
#include <linux/err.h>
#include <linux/io.h>
#include <linux/clk/msm-clk.h>
+#include <linux/iopoll.h>
+#include <linux/kthread.h>
#include "mdss_dsi.h"
#include "mdss_dp.h"
@@ -427,6 +429,20 @@ static void mdss_dsi_ctrl_phy_reset(struct mdss_dsi_ctrl_pdata *ctrl)
wmb(); /* maek sure reset cleared */
}
+int mdss_dsi_phy_pll_reset_status(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+ int rc;
+ u32 val;
+ u32 const sleep_us = 10, timeout_us = 100;
+
+ pr_debug("%s: polling for RESETSM_READY_STATUS.CORE_READY\n",
+ __func__);
+ rc = readl_poll_timeout(ctrl->phy_io.base + 0x4cc, val,
+ (val & 0x1), sleep_us, timeout_us);
+
+ return rc;
+}
+
static void mdss_dsi_phy_sw_reset_sub(struct mdss_dsi_ctrl_pdata *ctrl)
{
struct mdss_dsi_ctrl_pdata *sctrl = NULL;
diff --git a/include/linux/dma-attrs.h b/include/linux/dma-attrs.h
index 9799594ce09d..4c86e4483e0d 100644
--- a/include/linux/dma-attrs.h
+++ b/include/linux/dma-attrs.h
@@ -22,6 +22,8 @@ enum dma_attr {
DMA_ATTR_SKIP_ZEROING,
DMA_ATTR_NO_DELAYED_UNMAP,
DMA_ATTR_EXEC_MAPPING,
+ DMA_ATTR_FORCE_COHERENT,
+ DMA_ATTR_FORCE_NON_COHERENT,
DMA_ATTR_MAX,
};
diff --git a/include/linux/qpnp/power-on.h b/include/linux/input/qpnp-power-on.h
index da8f5a8622dd..a2624ab57826 100644
--- a/include/linux/qpnp/power-on.h
+++ b/include/linux/input/qpnp-power-on.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2015, 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
@@ -60,7 +60,7 @@ enum pon_restart_reason {
PON_RESTART_REASON_KEYS_CLEAR = 0x06,
};
-#ifdef CONFIG_QPNP_POWER_ON
+#ifdef CONFIG_INPUT_QPNP_POWER_ON
int qpnp_pon_system_pwr_off(enum pon_power_off_type type);
int qpnp_pon_is_warm_reset(void);
int qpnp_pon_trigger_config(enum pon_trigger_source pon_src, bool enable);
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index d33e10784b23..d7db6b2eeb52 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -237,6 +237,7 @@ struct iommu_ops {
#endif
unsigned long (*get_pgsize_bitmap)(struct iommu_domain *domain);
+ bool (*is_iova_coherent)(struct iommu_domain *domain, dma_addr_t iova);
unsigned long pgsize_bitmap;
void *priv;
};
@@ -273,6 +274,8 @@ extern size_t default_iommu_map_sg(struct iommu_domain *domain, unsigned long io
extern phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova);
extern phys_addr_t iommu_iova_to_phys_hard(struct iommu_domain *domain,
dma_addr_t iova);
+extern bool iommu_is_iova_coherent(struct iommu_domain *domain,
+ dma_addr_t iova);
extern void iommu_set_fault_handler(struct iommu_domain *domain,
iommu_fault_handler_t handler, void *token);
extern void iommu_trigger_fault(struct iommu_domain *domain,
@@ -505,6 +508,12 @@ static inline phys_addr_t iommu_iova_to_phys_hard(struct iommu_domain *domain,
return 0;
}
+static inline bool iommu_is_iova_coherent(struct iommu_domain *domain,
+ dma_addr_t iova)
+{
+ return 0;
+}
+
static inline void iommu_set_fault_handler(struct iommu_domain *domain,
iommu_fault_handler_t handler, void *token)
{
diff --git a/include/trace/events/msm_cam.h b/include/trace/events/msm_cam.h
new file mode 100644
index 000000000000..b52845407ef0
--- /dev/null
+++ b/include/trace/events/msm_cam.h
@@ -0,0 +1,136 @@
+/* Copyright (c) 2016, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ */
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM msm_cam
+
+#if !defined(_TRACE_MSM_VFE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_MSM_VFE_H
+
+#include "msm_isp.h"
+#include <linux/types.h>
+#include <linux/tracepoint.h>
+
+#define STRING_LEN 80
+
+
+TRACE_EVENT(msm_cam_string,
+ TP_PROTO(const char *str),
+ TP_ARGS(str),
+ TP_STRUCT__entry(
+ __array(char, str, STRING_LEN)
+ ),
+ TP_fast_assign(
+ strlcpy(__entry->str, str, STRING_LEN);
+ ),
+ TP_printk("msm_cam: %s", __entry->str)
+);
+
+TRACE_EVENT(msm_cam_tasklet_debug_dump,
+ TP_PROTO(struct msm_vfe_irq_debug_info tasklet_state),
+ TP_ARGS(tasklet_state),
+ TP_STRUCT__entry(
+ __field(unsigned int, vfe_id)
+ __field(unsigned int, core_id)
+ __field(unsigned int, irq_status0)
+ __field(unsigned int, irq_status1)
+ __field(unsigned int, ping_pong_status)
+ __field(long, tv_sec)
+ __field(long, tv_usec)
+ ),
+ TP_fast_assign(
+ __entry->vfe_id = tasklet_state.vfe_id;
+ __entry->irq_status0 =
+ tasklet_state.irq_status0[tasklet_state.vfe_id];
+ __entry->irq_status1 =
+ tasklet_state.irq_status1[tasklet_state.vfe_id];
+ __entry->core_id = tasklet_state.core_id;
+ __entry->ping_pong_status =
+ tasklet_state.ping_pong_status[tasklet_state.vfe_id];
+ __entry->tv_sec =
+ tasklet_state.ts.buf_time.tv_sec;
+ __entry->tv_usec =
+ tasklet_state.ts.buf_time.tv_usec;
+ ),
+ TP_printk("vfe_id %d, core %d, irq_st0 0x%x, irq_st1 0x%x\n"
+ "pi_po_st 0x%x, time %ld:%ld",
+ __entry->vfe_id,
+ __entry->core_id,
+ __entry->irq_status0,
+ __entry->irq_status1,
+ __entry->ping_pong_status,
+ __entry->tv_sec,
+ __entry->tv_usec
+ )
+);
+
+TRACE_EVENT(msm_cam_ping_pong_debug_dump,
+ TP_PROTO(struct msm_vfe_irq_debug_info ping_pong_state),
+ TP_ARGS(ping_pong_state),
+ TP_STRUCT__entry(
+ __field(unsigned int, curr_vfe_id)
+ __field(unsigned int, curr_irq_status0)
+ __field(unsigned int, curr_irq_status1)
+ __field(unsigned int, curr_ping_pong_status)
+ __field(unsigned int, othr_vfe_id)
+ __field(unsigned int, othr_irq_status0)
+ __field(unsigned int, othr_irq_status1)
+ __field(unsigned int, othr_ping_pong_status)
+ __field(long, othr_tv_sec)
+ __field(long, othr_tv_usec)
+ __field(unsigned int, core_id)
+ ),
+ TP_fast_assign(
+ __entry->curr_vfe_id =
+ ping_pong_state.vfe_id;
+ __entry->curr_irq_status0 =
+ ping_pong_state.irq_status0[ping_pong_state.vfe_id];
+ __entry->curr_irq_status1 =
+ ping_pong_state.irq_status1[ping_pong_state.vfe_id];
+ __entry->curr_ping_pong_status =
+ ping_pong_state.
+ ping_pong_status[ping_pong_state.vfe_id];
+ __entry->othr_vfe_id =
+ !ping_pong_state.vfe_id;
+ __entry->othr_irq_status0 =
+ ping_pong_state.irq_status0[!ping_pong_state.vfe_id];
+ __entry->othr_irq_status1 =
+ ping_pong_state.irq_status1[!ping_pong_state.vfe_id];
+ __entry->othr_ping_pong_status =
+ ping_pong_state.
+ ping_pong_status[!ping_pong_state.vfe_id];
+ __entry->othr_tv_sec =
+ ping_pong_state.ts.buf_time.tv_sec;
+ __entry->othr_tv_usec =
+ ping_pong_state.ts.buf_time.tv_usec;
+ __entry->core_id = ping_pong_state.core_id;
+ ),
+ TP_printk("vfe_id %d, irq_st0 0x%x, irq_st1 0x%x, pi_po_st 0x%x\n"
+ "other vfe_id %d, irq_st0 0x%x, irq_st1 0x%x\n"
+ "pi_po_st 0x%x, time %ld:%ld core %d",
+ __entry->curr_vfe_id,
+ __entry->curr_irq_status0,
+ __entry->curr_irq_status1,
+ __entry->curr_ping_pong_status,
+ __entry->othr_vfe_id,
+ __entry->othr_irq_status0,
+ __entry->othr_irq_status1,
+ __entry->othr_ping_pong_status,
+ __entry->othr_tv_sec,
+ __entry->othr_tv_usec,
+ __entry->core_id
+ )
+);
+
+#endif /* _MSM_CAM_TRACE_H */
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h
index 0a59832e0515..9d58d703527c 100644
--- a/include/trace/events/sched.h
+++ b/include/trace/events/sched.h
@@ -398,6 +398,7 @@ TRACE_EVENT(sched_get_task_cpu_cycles,
__field(u64, exec_time )
__field(u32, freq )
__field(u32, legacy_freq )
+ __field(u32, max_freq)
),
TP_fast_assign(
@@ -407,11 +408,13 @@ TRACE_EVENT(sched_get_task_cpu_cycles,
__entry->exec_time = exec_time;
__entry->freq = cpu_cycles_to_freq(cycles, exec_time);
__entry->legacy_freq = cpu_cur_freq(cpu);
+ __entry->max_freq = cpu_max_freq(cpu);
),
- TP_printk("cpu=%d event=%d cycles=%llu exec_time=%llu freq=%u legacy_freq=%u",
- __entry->cpu, __entry->event, __entry->cycles,
- __entry->exec_time, __entry->freq, __entry->legacy_freq)
+ TP_printk("cpu=%d event=%d cycles=%llu exec_time=%llu freq=%u legacy_freq=%u max_freq=%u",
+ __entry->cpu, __entry->event, __entry->cycles,
+ __entry->exec_time, __entry->freq, __entry->legacy_freq,
+ __entry->max_freq)
);
TRACE_EVENT(sched_update_history,
diff --git a/kernel/sched/hmp.c b/kernel/sched/hmp.c
index d3547391b937..180e2fcf785b 100644
--- a/kernel/sched/hmp.c
+++ b/kernel/sched/hmp.c
@@ -3340,6 +3340,7 @@ skip_early:
busy[i].prev_load = div64_u64(sched_ravg_window,
NSEC_PER_USEC);
busy[i].new_task_load = 0;
+ busy[i].predicted_load = 0;
goto exit_early;
}
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index 271d83e30d19..bf7fc4989e5c 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -1850,15 +1850,19 @@ schedule_hrtimeout_range_clock(ktime_t *expires, u64 delta,
* You can set the task state as follows -
*
* %TASK_UNINTERRUPTIBLE - at least @timeout time is guaranteed to
- * pass before the routine returns.
+ * pass before the routine returns unless the current task is explicitly
+ * woken up, (e.g. by wake_up_process()).
*
* %TASK_INTERRUPTIBLE - the routine may return early if a signal is
- * delivered to the current task.
+ * delivered to the current task or the current task is explicitly woken
+ * up.
*
* The current task state is guaranteed to be TASK_RUNNING when this
* routine returns.
*
- * Returns 0 when the timer has expired otherwise -EINTR
+ * Returns 0 when the timer has expired. If the task was woken before the
+ * timer expired by a signal (only possible in state TASK_INTERRUPTIBLE) or
+ * by an explicit wakeup, it returns -EINTR.
*/
int __sched schedule_hrtimeout_range(ktime_t *expires, u64 delta,
const enum hrtimer_mode mode)
@@ -1880,15 +1884,19 @@ EXPORT_SYMBOL_GPL(schedule_hrtimeout_range);
* You can set the task state as follows -
*
* %TASK_UNINTERRUPTIBLE - at least @timeout time is guaranteed to
- * pass before the routine returns.
+ * pass before the routine returns unless the current task is explicitly
+ * woken up, (e.g. by wake_up_process()).
*
* %TASK_INTERRUPTIBLE - the routine may return early if a signal is
- * delivered to the current task.
+ * delivered to the current task or the current task is explicitly woken
+ * up.
*
* The current task state is guaranteed to be TASK_RUNNING when this
* routine returns.
*
- * Returns 0 when the timer has expired otherwise -EINTR
+ * Returns 0 when the timer has expired. If the task was woken before the
+ * timer expired by a signal (only possible in state TASK_INTERRUPTIBLE) or
+ * by an explicit wakeup, it returns -EINTR.
*/
int __sched schedule_hrtimeout(ktime_t *expires,
const enum hrtimer_mode mode)
diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index 5ebefc7cfa4f..2bde2c2b1cb3 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -811,8 +811,15 @@ static struct tvec_base *lock_timer_base(struct timer_list *timer,
__acquires(timer->base->lock)
{
for (;;) {
- u32 tf = timer->flags;
struct tvec_base *base;
+ u32 tf;
+
+ /*
+ * We need to use READ_ONCE() here, otherwise the compiler
+ * might re-read @tf between the check for TIMER_MIGRATING
+ * and spin_lock().
+ */
+ tf = READ_ONCE(timer->flags);
if (!(tf & TIMER_MIGRATING)) {
base = get_timer_base(tf);
@@ -1529,11 +1536,12 @@ static void process_timeout(unsigned long __data)
* You can set the task state as follows -
*
* %TASK_UNINTERRUPTIBLE - at least @timeout jiffies are guaranteed to
- * pass before the routine returns. The routine will return 0
+ * pass before the routine returns unless the current task is explicitly
+ * woken up, (e.g. by wake_up_process())".
*
* %TASK_INTERRUPTIBLE - the routine may return early if a signal is
- * delivered to the current task. In this case the remaining time
- * in jiffies will be returned, or 0 if the timer expired in time
+ * delivered to the current task or the current task is explicitly woken
+ * up.
*
* The current task state is guaranteed to be TASK_RUNNING when this
* routine returns.
@@ -1542,7 +1550,9 @@ static void process_timeout(unsigned long __data)
* the CPU away without a bound on the timeout. In this case the return
* value will be %MAX_SCHEDULE_TIMEOUT.
*
- * In all cases the return value is guaranteed to be non-negative.
+ * Returns 0 when the timer has expired otherwise the remaining time in
+ * jiffies will be returned. In all cases the return value is guaranteed
+ * to be non-negative.
*/
signed long __sched schedule_timeout(signed long timeout)
{
@@ -1777,16 +1787,6 @@ unsigned long msleep_interruptible(unsigned int msecs)
EXPORT_SYMBOL(msleep_interruptible);
-static void __sched do_usleep_range(unsigned long min, unsigned long max)
-{
- ktime_t kmin;
- u64 delta;
-
- kmin = ktime_set(0, min * NSEC_PER_USEC);
- delta = (u64)(max - min) * NSEC_PER_USEC;
- schedule_hrtimeout_range(&kmin, delta, HRTIMER_MODE_REL);
-}
-
/**
* usleep_range - Drop in replacement for udelay where wakeup is flexible
* @min: Minimum time in usecs to sleep
@@ -1794,7 +1794,14 @@ static void __sched do_usleep_range(unsigned long min, unsigned long max)
*/
void __sched usleep_range(unsigned long min, unsigned long max)
{
- __set_current_state(TASK_UNINTERRUPTIBLE);
- do_usleep_range(min, max);
+ ktime_t exp = ktime_add_us(ktime_get(), min);
+ u64 delta = (u64)(max - min) * NSEC_PER_USEC;
+
+ for (;;) {
+ __set_current_state(TASK_UNINTERRUPTIBLE);
+ /* Do not return before the requested sleep time has elapsed */
+ if (!schedule_hrtimeout_range(&exp, delta, HRTIMER_MODE_ABS))
+ break;
+ }
}
EXPORT_SYMBOL(usleep_range);
diff --git a/sound/soc/codecs/wcd934x/wcd934x.c b/sound/soc/codecs/wcd934x/wcd934x.c
index 9b45db43ffb2..f2850d5e5ed3 100644
--- a/sound/soc/codecs/wcd934x/wcd934x.c
+++ b/sound/soc/codecs/wcd934x/wcd934x.c
@@ -5204,6 +5204,14 @@ static int tavil_mad_input_put(struct snd_kcontrol *kcontrol,
tavil_mad_input = ucontrol->value.integer.value[0];
+ if (tavil_mad_input >= sizeof(tavil_conn_mad_text)/
+ sizeof(tavil_conn_mad_text[0])) {
+ dev_err(codec->dev,
+ "%s: tavil_mad_input = %d out of bounds\n",
+ __func__, tavil_mad_input);
+ return -EINVAL;
+ }
+
if (strnstr(tavil_conn_mad_text[tavil_mad_input], "NOTUSED",
sizeof("NOTUSED"))) {
dev_dbg(codec->dev,
diff --git a/sound/soc/msm/Kconfig b/sound/soc/msm/Kconfig
index 835022b76b78..6ecd300a18ac 100644
--- a/sound/soc/msm/Kconfig
+++ b/sound/soc/msm/Kconfig
@@ -124,7 +124,6 @@ config SND_SOC_INT_CODEC
select SND_SOC_SDM660_CDC
select QTI_PP
select DTS_SRS_TM
- select DOLBY_DAP
select DOLBY_DS2
select SND_HWDEP
select MSM_ULTRASOUND
@@ -157,7 +156,6 @@ config SND_SOC_EXT_CODEC
select MFD_CORE
select QTI_PP
select DTS_SRS_TM
- select DOLBY_DAP
select DOLBY_DS2
select SND_SOC_CPE
select SND_SOC_WCD_CPE
diff --git a/sound/soc/msm/msm-cpe-lsm.c b/sound/soc/msm/msm-cpe-lsm.c
index ef4c9b01d91e..5b90cc11548e 100644
--- a/sound/soc/msm/msm-cpe-lsm.c
+++ b/sound/soc/msm/msm-cpe-lsm.c
@@ -1878,6 +1878,13 @@ static int msm_cpe_lsm_reg_model(struct snd_pcm_substream *substream,
lsm_ops->lsm_get_snd_model_offset(cpe->core_handle,
session, &offset);
+ /* Check if 'p_info->param_size + offset' crosses U32_MAX. */
+ if (p_info->param_size > U32_MAX - offset) {
+ dev_err(rtd->dev,
+ "%s: Invalid param_size %d\n",
+ __func__, p_info->param_size);
+ return -EINVAL;
+ }
session->snd_model_size = p_info->param_size + offset;
session->snd_model_data = vzalloc(session->snd_model_size);
diff --git a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c
index bb0f890d300f..5866e46cc6a2 100644
--- a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c
+++ b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 2016, 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
* only version 2 as published by the Free Software Foundation.
@@ -18,6 +18,10 @@
#include "msm-dolby-dap-config.h"
+#ifndef DOLBY_PARAM_VCNB_MAX_LENGTH
+#define DOLBY_PARAM_VCNB_MAX_LENGTH 40
+#endif
+
/* dolby endp based parameters */
struct dolby_dap_endp_params_s {
int device;
@@ -896,6 +900,11 @@ int msm_dolby_dap_param_visualizer_control_get(struct snd_kcontrol *kcontrol,
uint32_t param_payload_len =
DOLBY_PARAM_PAYLOAD_SIZE * sizeof(uint32_t);
int port_id, copp_idx, idx;
+ if (length > DOLBY_PARAM_VCNB_MAX_LENGTH || length <= 0) {
+ pr_err("%s Incorrect VCNB length", __func__);
+ ucontrol->value.integer.value[0] = 0;
+ return -EINVAL;
+ }
for (idx = 0; idx < AFE_MAX_PORTS; idx++) {
port_id = dolby_dap_params_states.port_id[idx];
copp_idx = dolby_dap_params_states.copp_idx[idx];
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 2639bfd5b8fd..dc57ae804dfa 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -10982,6 +10982,7 @@ static const struct snd_soc_dapm_route intercon[] = {
{"TERT_MI2S_UL_HL", NULL, "TERT_MI2S_TX"},
{"SEC_I2S_RX", NULL, "SEC_I2S_DL_HL"},
{"PRI_MI2S_UL_HL", NULL, "PRI_MI2S_TX"},
+ {"SEC_MI2S_UL_HL", NULL, "SEC_MI2S_TX"},
{"SEC_MI2S_RX", NULL, "SEC_MI2S_DL_HL"},
{"PRI_MI2S_RX", NULL, "PRI_MI2S_DL_HL"},
{"TERT_MI2S_RX", NULL, "TERT_MI2S_DL_HL"},
diff --git a/sound/soc/msm/qdsp6v2/q6core.c b/sound/soc/msm/qdsp6v2/q6core.c
index 9782fa26a2e9..5399a101ba62 100644
--- a/sound/soc/msm/qdsp6v2/q6core.c
+++ b/sound/soc/msm/qdsp6v2/q6core.c
@@ -221,7 +221,6 @@ struct cal_block_data *cal_utils_get_cal_block_by_key(
int32_t core_set_license(uint32_t key, uint32_t module_id)
{
struct avcs_cmd_set_license *cmd_setl = NULL;
- struct audio_cal_info_metainfo *metainfo = NULL;
struct cal_block_data *cal_block = NULL;
int rc = 0, packet_size = 0;
@@ -278,9 +277,9 @@ int32_t core_set_license(uint32_t key, uint32_t module_id)
memcpy((uint8_t *)cmd_setl + sizeof(struct avcs_cmd_set_license),
cal_block->cal_data.kvaddr,
cal_block->cal_data.size);
- pr_info("%s: Set license opcode=0x%x ,key=0x%x, id =0x%x, size = %d\n",
+ pr_info("%s: Set license opcode=0x%x, id =0x%x, size = %d\n",
__func__, cmd_setl->hdr.opcode,
- metainfo->nKey, cmd_setl->id, cmd_setl->size);
+ cmd_setl->id, cmd_setl->size);
rc = apr_send_pkt(q6core_lcl.core_handle_q, (uint32_t *)cmd_setl);
if (rc < 0)
pr_err("%s: SET_LICENSE failed op[0x%x]rc[%d]\n",