Merge "msm: smd: add support for secondary channel table"
diff --git a/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt b/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt
index d07eba6..3947f75 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt
@@ -28,11 +28,21 @@
core can be used for freq control.
- qcom,core-limit-temp: Threshold temperature to start shutting down cores
in degC
-- qcom,core-temp-hysterisis: Degrees C below which the cores will be brought
+- qcom,core-temp-hysteresis: Degrees C below which the cores will be brought
online in sequence.
- qcom,core-control-mask: The cpu mask that will be used to determine if a
core can be controlled or not. A mask of 0 indicates
the feature is disabled.
+- qcom,hotplug-temp: Threshold temperature to start shutting down cores
+ in degC. This will be used when polling based
+ core control is disabled. The difference between hotplug-temp
+ and core-limit-temp is that core-limit-temp is used during
+ early boot prior to thermal_sys being available for hotplug.
+- qcom,hotplug-temp-hysteresis: Degrees C below which thermal will not force the
+ cores to be offlined. Cores can be brought online if needed.
+- qcpm,cpu-sensors: List of type names in thermal zone device struct which maps
+ to cpu0, cpu1, cpu2, cpu3 in sequence depending on how many
+ cpus there are.
- qcom,vdd-restriction-temp: When temperature is below this threshold, will
enable vdd restriction which will set higher voltage on
key voltage rails, in degC.
@@ -81,8 +91,12 @@
qcom,freq-step = <2>;
qcom,freq-control-mask = <0xf>
qcom,core-limit-temp = <90>;
- qcom,core-temp-hysterisis = <10>;
+ qcom,core-temp-hysteresis = <10>;
qcom,core-control-mask = <7>;
+ qcom,hotplug-temp = <110>;
+ qcom,hotplug-temp-hysteresis = <20>;
+ qcom,cpu-sensors = "tsens_tz_sensor5", "tsens_tz_sensor6",
+ "tsens_tz_sensor7", "tsens_tz_sensor8";
qcom,pmic-sw-mode-temp = <90>;
qcom,pmic-sw-mode-temp-hysteresis = <80>;
qcom,pmic-sw-mode-regs = "vdd-dig";
diff --git a/Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt
index d77e96c..ce60d8d 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt
@@ -23,6 +23,10 @@
- focaltech,display-coords : display coordinates in pixels. It is a four
tuple consisting of min x, min y, max x and
max y values
+ - focaltech,name : name of the controller
+ - focaltech,group-id : group id of this device
+ - focaltech,hard-reset-delay-ms : hard reset delay in ms
+ - focaltech,soft-reset-delay-ms : soft reset delay in ms
Optional properties:
@@ -33,21 +37,43 @@
- focaltech,no-force-update : to specify force update is allowed
- focaltech,button-map : button map of key codes. The number
of key codes depend on panel
-
+ - focaltech,fw-name : specify the firmware file name
+ - focaltech,fw-delay-aa-ms : specify the "aa" delay in ms for firmware upgrade
+ - focaltech,fw-delay-55-ms : specify the "55" delay in ms for firmware upgrade
+ - focaltech,fw-upgrade-id1 : specify the upgrade id1 for firmware upgrade
+ - focaltech,fw-upgrade-id2 : specify the upgrade id2 for firmware upgrade
+ - focaltech,fw-delay-readid-ms : specify the read id delay in ms for firmware upgrade
+ - focaltech,fw-delay-era-flsh-ms : specify the erase flash delay in ms for firmware upgrade
+ - focaltech,fw-auto-cal : specify whether calibration is needed after firmware upgrade
Example:
- i2c@f9924000 {
- ft5x06_ts@38 {
+ i2c@f9923000{
+ focaltech@38{
compatible = "focaltech,5x06";
reg = <0x38>;
interrupt-parent = <&msmgpio>;
- interrupts = <61 0x2>;
- vdd-supply = <&pm8941_l22>;
- vcc_i2c-supply = <&pm8941_s3>;
- focaltech,reset-gpio = <&msmgpio 60 0x00>;
- focaltech,irq-gpio = <&msmgpio 61 0x00>;
- focaltech,panel-coords = <0 0 480 800>;
+ interrupts = <1 0x2>;
+ vdd-supply = <&pm8110_l19>;
+ vcc_i2c-supply = <&pm8110_l14>;
+ focaltech,name = "ft6x06";
+ focaltech,family-id = <0x06>;
+ focaltech,reset-gpio = <&msmgpio 0 0x00>;
+ focaltech,irq-gpio = <&msmgpio 1 0x00>;
focaltech,display-coords = <0 0 480 800>;
- focaltech,button-map= <158 102 139 217>;
- focaltech,family-id = <0x0a>;
+ focaltech,panel-coords = <0 0 480 800>;
+ focaltech,button-map= <139 102 158>;
+ focaltech,no-force-update;
+ focaltech,i2c-pull-up;
+ focaltech,group-id = <1>;
+ focaltech,hard-reset-delay = <20>;
+ focaltech,soft-reset-delay = <150>;
+ focaltech,num-max-touches = <2>;
+ focaltech,fw-name = "ft_8610_qrd_fw.bin";
+ focaltech,fw-delay-aa-ms = <100>;
+ focaltech,fw-delay-55-ms = <30>;
+ focaltech,fw-upgrade-id1 = <0x79>;
+ focaltech,fw-upgrade-id2 = <0x08>;
+ focaltech,fw-delay-readid-ms = <10>;
+ focaltech,fw-delay-era-flsh-ms = <2000>;
+ focaltech,fw-auto-cal;
};
};
diff --git a/Documentation/devicetree/bindings/input/touchscreen/synaptics_i2c_rmi4.txt b/Documentation/devicetree/bindings/input/touchscreen/synaptics_i2c_rmi4.txt
index 0f35e73..8fd813c 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/synaptics_i2c_rmi4.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/synaptics_i2c_rmi4.txt
@@ -14,12 +14,14 @@
- vdd-supply : Analog power supply needed to power device
- vcc_i2c-supply : Power source required to pull up i2c bus
- synaptics,i2c-pull-up : specify to indicate pull up is needed
+ - synaptics,disable-gpios : specify to disable gpios in suspend (power saving)
- synaptics,button-map : virtual key code mappings to be used
- synaptics,x-flip : modify orientation of the x axis
- synaptics,y-flip : modify orientation of the y axis
- synaptics,panel-x : panel x dimension
- synaptics,panel-y : panel y dimension
- synaptics,fw-image-name : name of firmware .img file in /etc/firmware
+ - synaptics,power-down : fully power down regulators in suspend
Example:
i2c@f9927000 { /* BLSP1 QUP5 */
diff --git a/Documentation/devicetree/bindings/sound/taiko_codec.txt b/Documentation/devicetree/bindings/sound/taiko_codec.txt
index 9abf54e..489eb38 100644
--- a/Documentation/devicetree/bindings/sound/taiko_codec.txt
+++ b/Documentation/devicetree/bindings/sound/taiko_codec.txt
@@ -35,6 +35,12 @@
- qcom,cdc-vddcx-2-voltage: cx-2 supply's voltage level min and max in mV.
- qcom,cdc-vddcx-2-current: cx-2 supply's max current in mA.
+ - cdc-vdd-buckhelper-supply: phandle of helper regulator supply's
+ device tree node. This supply is a helper regulator for
+ cdc-vdd-buck-supply regulator.
+ - cdc-vdd-buckhelper-voltage: helper supply's voltage level min and max in mV.
+ - qcom,cdc-vdd-buckhelper-current: helper supply's max current in mA.
+
- qcom,cdc-static-supplies: List of supplies to be enabled prior to codec
hardware probe. Supplies in this list will be
stay enabled.
@@ -76,6 +82,10 @@
dynamically.
Supplies in this list are off by default.
+- qcom,cdc-cp-supplies: List of supplies required for codec chargepump enable
+ Supplies in this list can be enabled/disabled dynamically and
+ are off by default.
+
- qcom,cdc-micbias2-headset-only: Boolean. Allow micbias 2 only to headset mic.
Example:
diff --git a/arch/arm/boot/dts/batterydata-qrd-4v2-1800mah.dtsi b/arch/arm/boot/dts/batterydata-qrd-4v2-1800mah.dtsi
new file mode 100644
index 0000000..e44e943
--- /dev/null
+++ b/arch/arm/boot/dts/batterydata-qrd-4v2-1800mah.dtsi
@@ -0,0 +1,105 @@
+/* Copyright (c) 2013, 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.
+ */
+
+qcom,qrd-4v2-1800mah-data {
+ qcom,fcc-mah = <1800>;
+ qcom,default-rbatt-mohm = <146>;
+ qcom,rbatt-capacitive-mohm = <0>;
+ qcom,flat-ocv-threshold-uv = <3800000>;
+ qcom,max-voltage-uv = <4200000>;
+ qcom,v-cutoff-uv = <3400000>;
+ qcom,chg-term-ua = <100000>;
+ qcom,batt-id-kohm = <47>;
+
+ qcom,rbatt-sf-lut {
+ qcom,lut-col-legend = <(-20) 0 25 40 60>;
+ qcom,lut-row-legend = <100 95 90 85 80>,
+ <75 70 65 60 55>,
+ <50 45 40 35 30>,
+ <25 20 15 10 9>,
+ <8 7 6 5 4>,
+ <3 2 1 0>;
+ qcom,lut-data = <904 234 100 85 80>,
+ <905 234 100 85 80>,
+ <934 244 102 86 81>,
+ <928 254 105 87 82>,
+ <933 268 109 89 84>,
+ <924 280 114 91 85>,
+ <913 283 123 96 88>,
+ <916 267 135 103 91>,
+ <930 252 137 110 95>,
+ <954 247 117 106 95>,
+ <990 247 103 88 85>,
+ <1036 253 104 86 84>,
+ <1101 264 108 89 85>,
+ <1211 286 112 93 88>,
+ <1366 340 120 95 87>,
+ <1601 394 128 95 87>,
+ <2178 402 128 97 89>,
+ <5419 423 126 97 89>,
+ <10789 528 128 97 91>,
+ <13463 589 132 100 91>,
+ <17695 678 137 102 92>,
+ <23046 814 145 104 93>,
+ <30725 1019 153 106 93>,
+ <41382 1359 156 106 93>,
+ <56311 1959 165 108 95>,
+ <77209 3523 189 117 99>,
+ <104609 6039 235 127 105>,
+ <138858 9711 352 141 112>,
+ <165825 15373 1069 246 226>;
+ };
+
+ qcom,fcc-temp-lut {
+ qcom,lut-col-legend = <(-20) 0 25 40 60>;
+ qcom,lut-data = <1859 1868 1873 1861 1859>;
+ };
+
+ qcom,pc-temp-ocv-lut {
+ qcom,lut-col-legend = <(-20) 0 25 40 60>;
+ qcom,lut-row-legend = <100 95 90 85 80>,
+ <75 70 65 60 55>,
+ <50 45 40 35 30>,
+ <25 20 15 10 9>,
+ <8 7 6 5 4>,
+ <3 2 1 0>;
+ qcom,lut-data = <4178 4176 4174 4169 4163>,
+ <4090 4100 4105 4101 4099>,
+ <4029 4049 4053 4050 4048>,
+ <3973 3998 4006 4004 4002>,
+ <3932 3959 3965 3962 3960>,
+ <3891 3920 3928 3925 3922>,
+ <3855 3882 3894 3891 3889>,
+ <3825 3844 3862 3862 3859>,
+ <3803 3813 3829 3834 3831>,
+ <3788 3792 3797 3802 3800>,
+ <3777 3780 3778 3776 3773>,
+ <3764 3775 3771 3767 3763>,
+ <3749 3769 3766 3763 3757>,
+ <3725 3756 3758 3755 3750>,
+ <3687 3727 3736 3735 3729>,
+ <3631 3675 3698 3698 3691>,
+ <3571 3607 3637 3642 3637>,
+ <3514 3548 3568 3572 3570>,
+ <3458 3506 3519 3522 3522>,
+ <3444 3498 3511 3516 3515>,
+ <3430 3489 3503 3509 3508>,
+ <3413 3477 3493 3500 3500>,
+ <3395 3461 3478 3488 3486>,
+ <3373 3433 3446 3463 3456>,
+ <3346 3394 3397 3418 3410>,
+ <3307 3341 3334 3361 3352>,
+ <3251 3270 3254 3287 3277>,
+ <3160 3167 3152 3183 3172>,
+ <3000 3000 3000 3000 3000>;
+ };
+};
diff --git a/arch/arm/boot/dts/msm-pm8841.dtsi b/arch/arm/boot/dts/msm-pm8841.dtsi
index a2d80ec..43bd0c9 100644
--- a/arch/arm/boot/dts/msm-pm8841.dtsi
+++ b/arch/arm/boot/dts/msm-pm8841.dtsi
@@ -238,5 +238,28 @@
reg = <0x2b00 0x100>;
};
};
+
+ krait_regulator_pmic: qcom,krait-regulator-pmic@2000 {
+ spmi-dev-container;
+ compatible = "qcom,krait-regulator-pmic";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ status = "disabled";
+
+ qcom,ctl@2000 {
+ status = "disabled";
+ reg = <0x2000 0x100>;
+ };
+
+ qcom,ps@2100 {
+ status = "disabled";
+ reg = <0x2100 0x100>;
+ };
+
+ qcom,freq@2200 {
+ status = "disabled";
+ reg = <0x2200 0x100>;
+ };
+ };
};
};
diff --git a/arch/arm/boot/dts/msm-pma8084.dtsi b/arch/arm/boot/dts/msm-pma8084.dtsi
index 3ff1b60..c070443 100644
--- a/arch/arm/boot/dts/msm-pma8084.dtsi
+++ b/arch/arm/boot/dts/msm-pma8084.dtsi
@@ -814,5 +814,28 @@
compatible = "qcom,qpnp-regulator";
status = "disabled";
};
+
+ krait_regulator_pmic: qcom,krait-regulator-pmic@2900 {
+ spmi-dev-container;
+ compatible = "qcom,krait-regulator-pmic";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ status = "disabled";
+
+ qcom,ctl@2900 {
+ reg = <0x2900 0x100>;
+ status = "disabled";
+ };
+
+ qcom,ps@2a00 {
+ reg = <0x2a00 0x100>;
+ status = "disabled";
+ };
+
+ qcom,freq@2b00 {
+ reg = <0x2b00 0x100>;
+ status = "disabled";
+ };
+ };
};
};
diff --git a/arch/arm/boot/dts/msm8226-cdp.dtsi b/arch/arm/boot/dts/msm8226-cdp.dtsi
index 104cb4c..e44ce07 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8226-cdp.dtsi
@@ -36,6 +36,7 @@
synaptics,button-map = <139 102 158>;
synaptics,i2c-pull-up;
synaptics,power-down;
+ synaptics,disable-gpios;
};
};
diff --git a/arch/arm/boot/dts/msm8226-mdss.dtsi b/arch/arm/boot/dts/msm8226-mdss.dtsi
index 5f991fb..8852a8d 100644
--- a/arch/arm/boot/dts/msm8226-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8226-mdss.dtsi
@@ -41,7 +41,7 @@
qcom,vbif-settings = <0x004 0x00000001>,
<0x0D8 0x00000707>,
<0x124 0x00000003>;
- qcom,mdp-settings = <0x02E0 0x000000A9>,
+ qcom,mdp-settings = <0x02E0 0x000000A5>,
<0x02E4 0x00000055>;
mdss_fb0: qcom,mdss_fb_primary {
diff --git a/arch/arm/boot/dts/msm8226-mtp.dtsi b/arch/arm/boot/dts/msm8226-mtp.dtsi
index 977c772..3138b06 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8226-mtp.dtsi
@@ -36,6 +36,7 @@
synaptics,button-map = <139 102 158>;
synaptics,i2c-pull-up;
synaptics,power-down;
+ synaptics,disable-gpios;
};
};
diff --git a/arch/arm/boot/dts/msm8226-qrd.dtsi b/arch/arm/boot/dts/msm8226-qrd.dtsi
index 7d7d949..8ab517a 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8226-qrd.dtsi
@@ -31,6 +31,7 @@
synaptics,button-map = <139 102 158>;
synaptics,i2c-pull-up;
synaptics,power-down;
+ synaptics,disable-gpios;
};
focaltech@38 {
compatible = "focaltech,5x06";
diff --git a/arch/arm/boot/dts/msm8226-pm.dtsi b/arch/arm/boot/dts/msm8226-v1-pm.dtsi
similarity index 96%
rename from arch/arm/boot/dts/msm8226-pm.dtsi
rename to arch/arm/boot/dts/msm8226-v1-pm.dtsi
index ef0a55e..827cdff 100644
--- a/arch/arm/boot/dts/msm8226-pm.dtsi
+++ b/arch/arm/boot/dts/msm8226-v1-pm.dtsi
@@ -24,7 +24,7 @@
qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
- qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 07 60 3b 76 76
+ qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
};
@@ -41,7 +41,7 @@
qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
- qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 07 60 3b 76 76
+ qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
};
@@ -58,7 +58,7 @@
qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
- qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 07 60 3b 76 76
+ qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
};
@@ -75,7 +75,7 @@
qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
- qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 07 60 3b 76 76
+ qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
};
diff --git a/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts b/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts
index d73fb93..1cbf00d 100644
--- a/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts
+++ b/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts
@@ -80,15 +80,15 @@
goodix,button-map= <158 102 139>;
goodix,family-id = <0x0>;
goodix,cfg-data = [
- 41 D0 02 00 05 0A 05 01 01 08
- 12 58 50 41 03 05 00 00 00 00
- 00 00 00 00 00 00 00 8C 2E 0E
- 28 24 73 13 00 00 00 83 03 1D
- 40 02 00 00 00 03 64 32 00 00
- 00 1A 38 94 C0 02 00 00 00 04
- 9E 1C 00 8D 20 00 7A 26 00 6D
- 2C 00 60 34 00 60 10 38 68 00
- F0 50 35 FF FF 27 00 00 00 00
+ 41 D0 02 00 05 0A 35 01 01 0F
+ 2D 08 55 32 03 04 00 00 00 00
+ 00 00 05 0A 0C 0F 0A 8C 0E 0E
+ 30 2E B8 08 00 00 00 83 03 1D
+ 00 00 00 00 00 00 00 00 00 00
+ 00 2D 62 94 C5 02 05 00 00 04
+ 96 30 00 80 39 00 71 42 00 63
+ 4D 00 56 5A 00 56 10 38 68 00
+ 56 50 35 AA AA 27 00 00 00 00
00 01 1B 14 0C 14 00 00 01 00
00 00 00 00 00 00 00 00 00 00
00 00 02 04 06 08 0A 0C 0E 10
@@ -97,8 +97,8 @@
FF FF 00 02 04 06 08 0A 0C 0F
10 12 13 14 16 18 1C 1D 1E 1F
20 21 22 24 26 28 29 2A FF FF
- FF FF FF FF FF FF FF 22 22 22
- 22 22 22 FF 07 01];
+ FF FF FF FF FF FF FF FF FF FF
+ FF FF FF FF 06 01];
};
};
};
diff --git a/arch/arm/boot/dts/msm8226-v1.dtsi b/arch/arm/boot/dts/msm8226-v1.dtsi
index 2833673..8d127e8 100644
--- a/arch/arm/boot/dts/msm8226-v1.dtsi
+++ b/arch/arm/boot/dts/msm8226-v1.dtsi
@@ -17,6 +17,7 @@
*/
/include/ "msm8226.dtsi"
+/include/ "msm8226-v1-pm.dtsi"
&tsens {
qcom,sensors = <4>;
diff --git a/arch/arm/boot/dts/msm8226-pm.dtsi b/arch/arm/boot/dts/msm8226-v2-pm.dtsi
similarity index 94%
copy from arch/arm/boot/dts/msm8226-pm.dtsi
copy to arch/arm/boot/dts/msm8226-v2-pm.dtsi
index ef0a55e..03064f2 100644
--- a/arch/arm/boot/dts/msm8226-pm.dtsi
+++ b/arch/arm/boot/dts/msm8226-v2-pm.dtsi
@@ -24,7 +24,7 @@
qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
- qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 07 60 3b 76 76
+ qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
};
@@ -41,7 +41,7 @@
qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
- qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 07 60 3b 76 76
+ qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
};
@@ -58,7 +58,7 @@
qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
- qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 07 60 3b 76 76
+ qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
};
@@ -75,7 +75,7 @@
qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
- qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 07 60 3b 76 76
+ qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
};
@@ -96,6 +96,8 @@
qcom,phase-port = <0x1>;
qcom,pfm-port = <0x2>;
qcom,saw2-spm-cmd-ret = [00 03 00 0f];
+ qcom,saw2-spm-cmd-gdhs = [00 20 32 6b c0 e0 d0 42 07 50
+ 4e 02 02 d0 e0 c0 22 6b 02 32 50 0f];
qcom,saw2-spm-cmd-pc = [00 32 b0 10 e0 d0 6b c0 42 f0
11 07 01 b0 50 4e 02 02 c0 d0 12 e0 6b 02 32
50 f0 0f]; /*APCS_PMIC_OFF_L2RAM_OFF*/
@@ -130,7 +132,7 @@
qcom,lpm-level@2 {
reg = <0x2>;
qcom,mode = "pc";
- qcom,l2 = "l2_cache_retention";
+ qcom,l2 = "l2_cache_gdhs";
qcom,latency-us = <20000>;
qcom,ss-power = <138>;
qcom,energy-overhead = <1208400>;
diff --git a/arch/arm/boot/dts/msm8226-v2-qrd-dvt.dts b/arch/arm/boot/dts/msm8226-v2-qrd-dvt.dts
index 0a3148b..9e98681 100644
--- a/arch/arm/boot/dts/msm8226-v2-qrd-dvt.dts
+++ b/arch/arm/boot/dts/msm8226-v2-qrd-dvt.dts
@@ -31,3 +31,7 @@
qcom,cont-splash-enabled;
};
};
+
+&pm8226_bms {
+ qcom,use-external-rsense;
+};
diff --git a/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts b/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts
index 95af304..fba41e5 100644
--- a/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts
+++ b/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts
@@ -81,15 +81,15 @@
goodix,button-map= <158 102 139>;
goodix,family-id = <0x0>;
goodix,cfg-data = [
- 41 D0 02 00 05 0A 05 01 01 08
- 12 58 50 41 03 05 00 00 00 00
- 00 00 00 00 00 00 00 8C 2E 0E
- 28 24 73 13 00 00 00 83 03 1D
- 40 02 00 00 00 03 64 32 00 00
- 00 1A 38 94 C0 02 00 00 00 04
- 9E 1C 00 8D 20 00 7A 26 00 6D
- 2C 00 60 34 00 60 10 38 68 00
- F0 50 35 FF FF 27 00 00 00 00
+ 41 D0 02 00 05 0A 35 01 01 0F
+ 2D 08 55 32 03 04 00 00 00 00
+ 00 00 05 0A 0C 0F 0A 8C 0E 0E
+ 30 2E B8 08 00 00 00 83 03 1D
+ 00 00 00 00 00 00 00 00 00 00
+ 00 2D 62 94 C5 02 05 00 00 04
+ 96 30 00 80 39 00 71 42 00 63
+ 4D 00 56 5A 00 56 10 38 68 00
+ 56 50 35 AA AA 27 00 00 00 00
00 01 1B 14 0C 14 00 00 01 00
00 00 00 00 00 00 00 00 00 00
00 00 02 04 06 08 0A 0C 0E 10
@@ -98,8 +98,8 @@
FF FF 00 02 04 06 08 0A 0C 0F
10 12 13 14 16 18 1C 1D 1E 1F
20 21 22 24 26 28 29 2A FF FF
- FF FF FF FF FF FF FF 22 22 22
- 22 22 22 FF 07 01];
+ FF FF FF FF FF FF FF FF FF FF
+ FF FF FF FF 06 01];
};
};
};
@@ -160,3 +160,11 @@
qcom,fast-avg-setup = <0>;
};
};
+
+&pm8226_bms {
+ qcom,use-external-rsense;
+};
+
+&pm8226_iadc {
+ qcom,rsense = <10000000>;
+};
diff --git a/arch/arm/boot/dts/msm8226-v2.dtsi b/arch/arm/boot/dts/msm8226-v2.dtsi
index 2b3b7c2..9681d2a 100644
--- a/arch/arm/boot/dts/msm8226-v2.dtsi
+++ b/arch/arm/boot/dts/msm8226-v2.dtsi
@@ -17,6 +17,7 @@
*/
/include/ "msm8226.dtsi"
+/include/ "msm8226-v2-pm.dtsi"
&pm8226_l3 {
regulator-min-microvolt = <750000>;
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 8f153cd..da52984 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -51,7 +51,6 @@
/include/ "msm8226-camera.dtsi"
/include/ "msm-gdsc.dtsi"
/include/ "msm8226-iommu.dtsi"
-/include/ "msm8226-pm.dtsi"
/include/ "msm8226-smp2p.dtsi"
/include/ "msm8226-gpu.dtsi"
/include/ "msm8226-bus.dtsi"
@@ -340,12 +339,18 @@
qcom,cdc-vdd-cx-voltage = <1200000 1200000>;
qcom,cdc-vdd-cx-current = <10000>;
- qcom,cdc-static-supplies = "cdc-vdd-buck",
- "cdc-vdd-h",
+ cdc-vdd-buckhelper-supply = <&pm8226_l25>;
+ qcom,cdc-vdd-buckhelper-voltage = <1775000 2125000>;
+ qcom,cdc-vdd-buckhelper-current = <10000>;
+
+ qcom,cdc-static-supplies = "cdc-vdd-h",
"cdc-vdd-px",
"cdc-vdd-a-1p2v",
"cdc-vdd-cx";
+ qcom,cdc-cp-supplies = "cdc-vdd-buck",
+ "cdc-vdd-buckhelper";
+
qcom,cdc-micbias-ldoh-v = <0x3>;
qcom,cdc-micbias-cfilt1-mv = <1800>;
qcom,cdc-micbias-cfilt2-mv = <2700>;
@@ -912,6 +917,8 @@
interrupts = <0 99 0>;
qcom,i2c-bus-freq = <384000>;
qcom,i2c-src-freq = <19200000>;
+ qcom,sda-gpio = <&msmgpio 18 0>;
+ qcom,scl-gpio = <&msmgpio 19 0>;
};
qcom,acpuclk@f9011050 {
diff --git a/arch/arm/boot/dts/msm8610-bus.dtsi b/arch/arm/boot/dts/msm8610-bus.dtsi
index cef04ef..6b72e66 100644
--- a/arch/arm/boot/dts/msm8610-bus.dtsi
+++ b/arch/arm/boot/dts/msm8610-bus.dtsi
@@ -952,6 +952,7 @@
cell-id = <2048>;
label = "fab_mmss_noc";
qcom,masterp = <1>;
+ qcom,gateway;
qcom,qport = <1>;
qcom,buswidth = <8>;
qcom,ws = <10000>;
diff --git a/arch/arm/boot/dts/msm8610-cdp.dts b/arch/arm/boot/dts/msm8610-cdp.dtsi
similarity index 95%
rename from arch/arm/boot/dts/msm8610-cdp.dts
rename to arch/arm/boot/dts/msm8610-cdp.dtsi
index f3470c2..bfccb78 100644
--- a/arch/arm/boot/dts/msm8610-cdp.dts
+++ b/arch/arm/boot/dts/msm8610-cdp.dtsi
@@ -10,19 +10,6 @@
* GNU General Public License for more details.
*/
-/dts-v1/;
-
-/include/ "msm8610.dtsi"
-/include/ "dsi-v2-panel-truly-wvga-video.dtsi"
-/include/ "msm8610-camera-sensor-cdp-mtp.dtsi"
-
-/ {
- model = "Qualcomm MSM 8610 CDP";
- compatible = "qcom,msm8610-cdp", "qcom,msm8610", "qcom,cdp";
- qcom,msm-id = <147 1 0>, <165 1 0>, <161 1 0>, <162 1 0>,
- <163 1 0>, <164 1 0>, <166 1 0>;
-};
-
&soc {
serial@f991e000 {
status = "ok";
@@ -52,7 +39,7 @@
/* Object 6, Instance = 0 */
00 00 00 00 00 00
/* Object 38, Instance = 0 */
- 1D 02 00 0A 06 0D 00 00
+ 1D 03 00 1E 07 0D 00 00
/* Object 7, Instance = 0 */
20 08 32
/* Object 8, Instance = 0 */
@@ -60,7 +47,7 @@
/* Object 9, Instance = 0 */
83 00 00 13 0B 00 20 32 01 03
00 32 05 30 0A 05 0A 00 70 03
- FC 01 00 36 2F D8 00 00 40 00
+ FC 01 04 2F F8 DC 00 00 40 00
00 0A 00 00 02
/* Object 18, Instance = 0 */
00 00
@@ -143,6 +130,10 @@
"AMIC1", "MIC BIAS External",
"AMIC2", "MIC BIAS Internal2";
};
+
+ qcom,dsi_v2_truly_wvga_video {
+ qcom,cont-splash-enabled;
+ };
};
&i2c_cdc {
diff --git a/arch/arm/boot/dts/msm8610-mtp.dts b/arch/arm/boot/dts/msm8610-mtp.dtsi
similarity index 95%
rename from arch/arm/boot/dts/msm8610-mtp.dts
rename to arch/arm/boot/dts/msm8610-mtp.dtsi
index 0d4c174..349c8f7 100644
--- a/arch/arm/boot/dts/msm8610-mtp.dts
+++ b/arch/arm/boot/dts/msm8610-mtp.dtsi
@@ -10,19 +10,6 @@
* GNU General Public License for more details.
*/
-/dts-v1/;
-
-/include/ "msm8610.dtsi"
-/include/ "dsi-v2-panel-truly-wvga-video.dtsi"
-/include/ "msm8610-camera-sensor-cdp-mtp.dtsi"
-
-/ {
- model = "Qualcomm MSM 8610 MTP";
- compatible = "qcom,msm8610-mtp", "qcom,msm8610", "qcom,mtp";
- qcom,msm-id = <147 8 0>, <165 8 0>, <161 8 0>, <162 8 0>,
- <163 8 0>, <164 8 0>, <166 8 0>;
-};
-
&soc {
serial@f991e000 {
status = "ok";
@@ -52,7 +39,7 @@
/* Object 6, Instance = 0 */
00 00 00 00 00 00
/* Object 38, Instance = 0 */
- 1D 02 00 0A 06 0D 00 00
+ 1D 03 00 1E 07 0D 00 00
/* Object 7, Instance = 0 */
20 08 32
/* Object 8, Instance = 0 */
@@ -60,7 +47,7 @@
/* Object 9, Instance = 0 */
83 00 00 13 0B 00 20 32 01 03
00 32 05 30 0A 05 0A 00 70 03
- FC 01 00 36 2F D8 00 00 40 00
+ FC 01 04 2F F8 DC 00 00 40 00
00 0A 00 00 02
/* Object 18, Instance = 0 */
00 00
@@ -181,6 +168,10 @@
"AMIC1", "MIC BIAS External",
"AMIC2", "MIC BIAS Internal2";
};
+
+ qcom,dsi_v2_truly_wvga_video {
+ qcom,cont-splash-enabled;
+ };
};
&i2c_cdc {
diff --git a/arch/arm/boot/dts/msm8610-pm.dtsi b/arch/arm/boot/dts/msm8610-pm.dtsi
index d31a65c..beeeed3 100644
--- a/arch/arm/boot/dts/msm8610-pm.dtsi
+++ b/arch/arm/boot/dts/msm8610-pm.dtsi
@@ -24,7 +24,7 @@
qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
- qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 07 60 3b 76 76
+ qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
};
@@ -41,7 +41,7 @@
qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
- qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 07 60 3b 76 76
+ qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
};
@@ -58,7 +58,7 @@
qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 06 26 30 0f];
- qcom,saw2-spm-cmd-pc = [00 20 10 80 30 90 5b 60 07 60 3b 76 76
+ qcom,saw2-spm-cmd-pc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 06 26 30 0f];
};
@@ -75,7 +75,7 @@
qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
- qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 07 60 3b 76 76
+ qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
};
@@ -208,45 +208,43 @@
qcom,gpio-parent = <&msmgpio>;
qcom,gpio-map = <3 1>,
- <4 4 >,
- <5 5 >,
- <6 9 >,
- <7 13>,
- <8 17>,
- <9 21>,
- <10 27>,
- <11 29>,
- <12 31>,
- <13 33>,
- <14 35>,
- <15 37>,
- <16 38>,
- <17 39>,
- <18 41>,
- <19 46>,
- <20 48>,
- <21 49>,
- <22 50>,
- <23 51>,
- <24 52>,
- <25 54>,
- <26 62>,
- <27 63>,
- <28 64>,
- <29 65>,
- <30 66>,
- <31 67>,
- <32 68>,
- <33 69>,
- <34 71>,
- <35 72>,
- <36 106>,
- <37 107>,
- <38 108>,
- <39 109>,
- <40 110>,
- <54 111>,
- <55 113>;
+ <4 5 >,
+ <5 9 >,
+ <6 14>,
+ <7 15>,
+ <8 32>,
+ <9 33>,
+ <10 34>,
+ <11 35>,
+ <12 41>,
+ <13 42>,
+ <14 72>,
+ <15 73>,
+ <16 74>,
+ <17 75>,
+ <18 76>,
+ <19 77>,
+ <20 78>,
+ <21 79>,
+ <22 80>,
+ <23 81>,
+ <24 82>,
+ <25 83>,
+ <26 84>,
+ <27 85>,
+ <28 87>,
+ <29 90>,
+ <30 91>,
+ <31 92>,
+ <32 93>,
+ <33 94>,
+ <34 95>,
+ <35 96>,
+ <36 97>,
+ <37 98>,
+ <38 99>,
+ <39 100>,
+ <40 101>;
};
qcom,pm-8x60@fe805664 {
diff --git a/arch/arm/boot/dts/msm8610-qrd.dtsi b/arch/arm/boot/dts/msm8610-qrd.dtsi
index bd1705f..49068b5 100644
--- a/arch/arm/boot/dts/msm8610-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8610-qrd.dtsi
@@ -26,8 +26,6 @@
* };
*/
-/include/ "msm8610.dtsi"
-
&soc {
i2c@f9923000{
focaltech@38{
@@ -37,6 +35,7 @@
interrupts = <1 0x2>;
vdd-supply = <&pm8110_l19>;
vcc_i2c-supply = <&pm8110_l14>;
+ focaltech,name = "ft6x06";
focaltech,family-id = <0x06>;
focaltech,reset-gpio = <&msmgpio 0 0x00>;
focaltech,irq-gpio = <&msmgpio 1 0x00>;
@@ -45,6 +44,17 @@
focaltech,button-map= <139 102 158>;
focaltech,no-force-update;
focaltech,i2c-pull-up;
+ focaltech,group-id = <1>;
+ focaltech,hard-reset-delay-ms = <20>;
+ focaltech,soft-reset-delay-ms = <150>;
+ focaltech,num-max-touches = <2>;
+ focaltech,fw-name = "ft_8610_qrd_fw.bin";
+ focaltech,fw-delay-aa-ms = <100>;
+ focaltech,fw-delay-55-ms = <30>;
+ focaltech,fw-upgrade-id1 = <0x79>;
+ focaltech,fw-upgrade-id2 = <0x08>;
+ focaltech,fw-delay-readid-ms = <10>;
+ focaltech,fw-delay-era-flsh-ms = <2000>;
};
};
@@ -344,3 +354,10 @@
mpp@a300 { /* MPP 4 */
};
};
+
+&pm8110_vadc {
+ chan@30 {
+ label = "batt_therm";
+ qcom,scale-function = <6>;
+ };
+};
diff --git a/arch/arm/boot/dts/msm8610-v1-cdp.dts b/arch/arm/boot/dts/msm8610-v1-cdp.dts
new file mode 100644
index 0000000..ba0851f
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-v1-cdp.dts
@@ -0,0 +1,27 @@
+/* Copyright (c) 2013, 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.
+ */
+
+/dts-v1/;
+
+/include/ "msm8610-v1.dtsi"
+/include/ "msm8610-cdp.dtsi"
+/include/ "dsi-v2-panel-truly-wvga-video.dtsi"
+/include/ "msm8610-camera-sensor-cdp-mtp.dtsi"
+
+/ {
+ model = "Qualcomm MSM 8610 CDP";
+ compatible = "qcom,msm8610-cdp", "qcom,msm8610", "qcom,cdp";
+ qcom,msm-id = <147 1 0>, <165 1 0>, <161 1 0>, <162 1 0>,
+ <163 1 0>, <164 1 0>, <166 1 0>;
+};
+
+
diff --git a/arch/arm/boot/dts/msm8610-v1-mtp.dts b/arch/arm/boot/dts/msm8610-v1-mtp.dts
new file mode 100644
index 0000000..010903f
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-v1-mtp.dts
@@ -0,0 +1,27 @@
+/* Copyright (c) 2013, 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.
+ */
+
+/dts-v1/;
+
+/include/ "msm8610-v1.dtsi"
+/include/ "msm8610-mtp.dtsi"
+/include/ "dsi-v2-panel-truly-wvga-video.dtsi"
+/include/ "msm8610-camera-sensor-cdp-mtp.dtsi"
+
+/ {
+ model = "Qualcomm MSM 8610 MTP";
+ compatible = "qcom,msm8610-mtp", "qcom,msm8610", "qcom,mtp";
+ qcom,msm-id = <147 8 0>, <165 8 0>, <161 8 0>, <162 8 0>,
+ <163 8 0>, <164 8 0>, <166 8 0>;
+};
+
+
diff --git a/arch/arm/boot/dts/msm8610-qrd-skuaa.dts b/arch/arm/boot/dts/msm8610-v1-qrd-skuaa.dts
similarity index 92%
rename from arch/arm/boot/dts/msm8610-qrd-skuaa.dts
rename to arch/arm/boot/dts/msm8610-v1-qrd-skuaa.dts
index aeaf8ca..5abe5c0 100644
--- a/arch/arm/boot/dts/msm8610-qrd-skuaa.dts
+++ b/arch/arm/boot/dts/msm8610-v1-qrd-skuaa.dts
@@ -12,6 +12,7 @@
/dts-v1/;
+/include/ "msm8610-v1.dtsi"
/include/ "msm8610-qrd.dtsi"
/include/ "dsi-v2-panel-hx8379a-wvga-video.dtsi"
/include/ "msm8610-qrd-camera-sensor.dtsi"
@@ -45,3 +46,10 @@
status = "ok";
qcom,batt-type = <5>;
};
+
+&pm8110_vadc {
+ chan@30 {
+ label = "batt_therm";
+ qcom,scale-function = <7>;
+ };
+};
diff --git a/arch/arm/boot/dts/msm8610-qrd-skuab.dts b/arch/arm/boot/dts/msm8610-v1-qrd-skuab.dts
similarity index 83%
rename from arch/arm/boot/dts/msm8610-qrd-skuab.dts
rename to arch/arm/boot/dts/msm8610-v1-qrd-skuab.dts
index 947a312..b4559ff 100644
--- a/arch/arm/boot/dts/msm8610-qrd-skuab.dts
+++ b/arch/arm/boot/dts/msm8610-v1-qrd-skuab.dts
@@ -12,6 +12,7 @@
/dts-v1/;
+/include/ "msm8610-v1.dtsi"
/include/ "msm8610-qrd.dtsi"
/include/ "dsi-v2-panel-otm8018b-fwvga-video.dtsi"
/include/ "msm8612-qrd-camera-sensor.dtsi"
@@ -80,7 +81,30 @@
};
};
+ usb@f9a55000 {
+ qcom,hsusb-otg-phy-init-seq =
+ <0x44 0x80 0x6a 0x81 0x34 0x82 0x23 0x83 0xffffffff>;
+ };
+
qcom,dsi_v2_otm8018b_fwvga_video {
status = "ok";
};
};
+
+/ {
+ qrd_batterydata: qcom,battery-data {
+ qcom,rpull-up-kohm = <100>;
+ qcom,vref-batt-therm = <1800000>;
+
+ /include/ "batterydata-qrd-4v2-1800mah.dtsi"
+ };
+};
+
+&pm8110_bms {
+ status = "ok";
+ qcom,battery-data = <&qrd_batterydata>;
+};
+
+&pm8110_chg {
+ qcom,battery-data = <&qrd_batterydata>;
+};
diff --git a/arch/arm/boot/dts/msm8610-v1.dtsi b/arch/arm/boot/dts/msm8610-v1.dtsi
new file mode 100644
index 0000000..5052b96
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-v1.dtsi
@@ -0,0 +1,19 @@
+/* Copyright (c) 2013, 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.
+ */
+
+/*
+ * As a general rule, only version-specific property overrides should be placed
+ * inside this file. However, device definitions should be placed inside the
+ * msm8610.dtsi file.
+ */
+
+/include/ "msm8610.dtsi"
diff --git a/arch/arm/boot/dts/msm8610-v2-cdp.dts b/arch/arm/boot/dts/msm8610-v2-cdp.dts
new file mode 100644
index 0000000..51ef7a2
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-v2-cdp.dts
@@ -0,0 +1,27 @@
+/* Copyright (c) 2013, 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.
+ */
+
+/dts-v1/;
+
+/include/ "msm8610-v2.dtsi"
+/include/ "msm8610-cdp.dtsi"
+/include/ "dsi-v2-panel-truly-wvga-video.dtsi"
+/include/ "msm8610-camera-sensor-cdp-mtp.dtsi"
+
+/ {
+ model = "Qualcomm MSM 8610v2 CDP";
+ compatible = "qcom,msm8610-cdp", "qcom,msm8610", "qcom,cdp";
+ qcom,msm-id = <147 1 0x10001>, <165 1 0x10001>, <161 1 0x10001>, <162 1 0x10001>,
+ <163 1 0x10001>, <164 1 0x10001>, <166 1 0x10001>;
+};
+
+
diff --git a/arch/arm/boot/dts/msm8610-v2-mtp.dts b/arch/arm/boot/dts/msm8610-v2-mtp.dts
new file mode 100644
index 0000000..e1c9bb8
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-v2-mtp.dts
@@ -0,0 +1,27 @@
+/* Copyright (c) 2013, 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.
+ */
+
+/dts-v1/;
+
+/include/ "msm8610-v2.dtsi"
+/include/ "msm8610-mtp.dtsi"
+/include/ "dsi-v2-panel-truly-wvga-video.dtsi"
+/include/ "msm8610-camera-sensor-cdp-mtp.dtsi"
+
+/ {
+ model = "Qualcomm MSM 8610v2 MTP";
+ compatible = "qcom,msm8610-mtp", "qcom,msm8610", "qcom,mtp";
+ qcom,msm-id = <147 8 0x10001>, <165 8 0x10001>, <161 8 0x10001>, <162 8 0x10001>,
+ <163 8 0x10001>, <164 8 0x10001>, <166 8 0x10001>;
+};
+
+
diff --git a/arch/arm/boot/dts/msm8610-v2-qrd-skuaa.dts b/arch/arm/boot/dts/msm8610-v2-qrd-skuaa.dts
new file mode 100644
index 0000000..6ad8cb5
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-v2-qrd-skuaa.dts
@@ -0,0 +1,27 @@
+/* Copyright (c) 2013, 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.
+ */
+
+/dts-v1/;
+
+/include/ "msm8610-v2.dtsi"
+/include/ "msm8610-qrd.dtsi"
+/include/ "dsi-v2-panel-hx8379a-wvga-video.dtsi"
+/include/ "msm8610-qrd-camera-sensor.dtsi"
+
+/ {
+ model = "Qualcomm MSM 8610v2 QRD";
+ compatible = "qcom,msm8610-qrd", "qcom,msm8610", "qcom,qrd";
+ qcom,board-id = <11 1>, <11 0>;
+ qcom,msm-id = <147 0x10001>, <165 0x10001>, <161 0x10001>, <162 0x10001>,
+ <163 0x10001>, <164 0x10001>, <166 0x10001>;
+};
+
diff --git a/arch/arm/boot/dts/msm8610-v2-qrd-skuab.dts b/arch/arm/boot/dts/msm8610-v2-qrd-skuab.dts
new file mode 100644
index 0000000..225be06
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-v2-qrd-skuab.dts
@@ -0,0 +1,24 @@
+/* Copyright (c) 2013, 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.
+ */
+
+/dts-v1/;
+
+/include/ "msm8610-v2.dtsi"
+/include/ "msm8610-qrd.dtsi"
+
+/ {
+ model = "Qualcomm MSM 8610v2 QRD";
+ compatible = "qcom,msm8610-qrd", "qcom,msm8610", "qcom,qrd";
+ qcom,board-id = <11 3>;
+ qcom,msm-id = <147 0x10001>, <165 0x10001>, <161 0x10001>, <162 0x10001>,
+ <163 0x10001>, <164 0x10001>, <166 0x10001>;
+};
diff --git a/arch/arm/boot/dts/msm8610-v2.dtsi b/arch/arm/boot/dts/msm8610-v2.dtsi
new file mode 100644
index 0000000..5052b96
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-v2.dtsi
@@ -0,0 +1,19 @@
+/* Copyright (c) 2013, 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.
+ */
+
+/*
+ * As a general rule, only version-specific property overrides should be placed
+ * inside this file. However, device definitions should be placed inside the
+ * msm8610.dtsi file.
+ */
+
+/include/ "msm8610.dtsi"
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index c6104bf..efa68b9 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -472,6 +472,7 @@
qcom,i2c-src-freq = <19200000>;
qcom,sda-gpio = <&msmgpio 2 0>;
qcom,scl-gpio = <&msmgpio 3 0>;
+ qcom,master-id = <86>;
};
i2c_cdc: i2c@f9927000 { /* BLSP1 QUP5 */
@@ -484,6 +485,8 @@
interrupt-names = "qup_err_intr";
interrupts = <0 99 0>;
qcom,i2c-bus-freq = <100000>;
+ qcom,i2c-src-freq = <19200000>;
+ qcom,master-id = <86>;
};
i2c: i2c@f9928000 { /* BLSP1 QUP6 */
@@ -499,6 +502,7 @@
qcom,i2c-src-freq = <19200000>;
qcom,sda-gpio = <&msmgpio 16 0>;
qcom,scl-gpio = <&msmgpio 17 0>;
+ qcom,master-id = <86>;
};
i2c@f9925000 { /* BLSP-1 QUP-3 */
@@ -511,6 +515,10 @@
interrupt-names = "qup_err_intr";
interrupts = <0 97 0>;
qcom,i2c-bus-freq = <100000>;
+ qcom,i2c-src-freq = <19200000>;
+ qcom,sda-gpio = <&msmgpio 10 0>;
+ qcom,scl-gpio = <&msmgpio 11 0>;
+ qcom,master-id = <86>;
};
spi_4: spi@f9926000 { /* BLSP1 QUP4 */
@@ -929,10 +937,16 @@
};
&gdsc_vfe {
+ qcom,clock-names = "core_clk", "iface_clk", "bus_clk";
+ qcom,skip-logic-collapse;
+ qcom,retain-periph;
+ qcom,retain-mem;
status = "ok";
};
&gdsc_oxili_cx {
+ qcom,clock-names = "core_clk", "iface_clk", "mem_clk";
+ qcom,skip-logic-collapse;
status = "ok";
};
diff --git a/arch/arm/boot/dts/msm8926.dtsi b/arch/arm/boot/dts/msm8926.dtsi
index 5afcb4e..9159ba2 100644
--- a/arch/arm/boot/dts/msm8926.dtsi
+++ b/arch/arm/boot/dts/msm8926.dtsi
@@ -78,6 +78,10 @@
qcom,slope = <2901 2846 3038 2955 2901 2846>;
};
+&msmgpio {
+ ngpio = <120>;
+};
+
&memory_hole {
qcom,memblock-remove = <0x08000000 0x7500000
0x0fa00000 0x500000>; /* Address and size of the hole */
diff --git a/arch/arm/boot/dts/msm8974-ion.dtsi b/arch/arm/boot/dts/msm8974-ion.dtsi
index 63f6d59..455ed2d 100644
--- a/arch/arm/boot/dts/msm8974-ion.dtsi
+++ b/arch/arm/boot/dts/msm8974-ion.dtsi
@@ -55,5 +55,12 @@
qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
qcom,memory-reservation-size = <0x614000>;
};
+
+ qcom,ion-heap@23 { /* OTHER PIL HEAP */
+ compatible = "qcom,msm-ion-reserve";
+ reg = <23>;
+ qcom,heap-align = <0x1000>;
+ qcom,memory-fixed = <0x05d00000 0x1e00000>;
+ };
};
};
diff --git a/arch/arm/boot/dts/msm8974-v1.dtsi b/arch/arm/boot/dts/msm8974-v1.dtsi
index 86a61cd..249c963 100644
--- a/arch/arm/boot/dts/msm8974-v1.dtsi
+++ b/arch/arm/boot/dts/msm8974-v1.dtsi
@@ -165,3 +165,19 @@
qcom,retain-mem;
qcom,retain-periph;
};
+
+&krait_regulator_pmic {
+ status = "ok";
+
+ qcom,ctl@2000 {
+ status = "ok";
+ };
+
+ qcom,ps@2100 {
+ status = "ok";
+ };
+
+ qcom,freq@2200 {
+ status = "ok";
+ };
+};
diff --git a/arch/arm/boot/dts/msm8974-v2.dtsi b/arch/arm/boot/dts/msm8974-v2.dtsi
index 9d5e50b..af4030f 100644
--- a/arch/arm/boot/dts/msm8974-v2.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2.dtsi
@@ -168,3 +168,19 @@
&tspp {
vdd_cx-supply = <&pm8841_s2_corner>;
};
+
+&krait_regulator_pmic {
+ status = "ok";
+
+ qcom,ctl@2000 {
+ status = "ok";
+ };
+
+ qcom,ps@2100 {
+ status = "ok";
+ };
+
+ qcom,freq@2200 {
+ status = "ok";
+ };
+};
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index e45b279..1845e17 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -1517,6 +1517,10 @@
qcom,core-limit-temp = <80>;
qcom,core-temp-hysteresis = <10>;
qcom,core-control-mask = <0xe>;
+ qcom,hotplug-temp = <110>;
+ qcom,hotplug-temp-hysteresis = <20>;
+ qcom,cpu-sensors = "tsens_tz_sensor5", "tsens_tz_sensor6",
+ "tsens_tz_sensor7", "tsens_tz_sensor8";
qcom,vdd-restriction-temp = <5>;
qcom,vdd-restriction-temp-hysteresis = <10>;
qcom,pmic-sw-mode-temp = <85>;
@@ -1553,7 +1557,7 @@
memory_hole: qcom,msm-mem-hole {
compatible = "qcom,msm-mem-hole";
- qcom,memblock-remove = <0x7b00000 0x8400000>; /* Address and Size of Hole */
+ qcom,memblock-remove = <0x5d00000 0xa200000>; /* Address and Size of Hole */
};
uart7: uart@f995d000 { /*BLSP #2, UART #7 */
diff --git a/arch/arm/boot/dts/msm8974pro-ab.dtsi b/arch/arm/boot/dts/msm8974pro-ab.dtsi
index 88687bd..5809069 100644
--- a/arch/arm/boot/dts/msm8974pro-ab.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-ab.dtsi
@@ -39,3 +39,19 @@
&tspp {
vdd_cx-supply = <&pm8841_s2_corner>;
};
+
+&krait_regulator_pmic {
+ status = "ok";
+
+ qcom,ctl@2000 {
+ status = "ok";
+ };
+
+ qcom,ps@2100 {
+ status = "ok";
+ };
+
+ qcom,freq@2200 {
+ status = "ok";
+ };
+};
diff --git a/arch/arm/boot/dts/msm8974pro-ac-mtp.dtsi b/arch/arm/boot/dts/msm8974pro-ac-mtp.dtsi
index 250afd2..debf7fb 100644
--- a/arch/arm/boot/dts/msm8974pro-ac-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-ac-mtp.dtsi
@@ -62,10 +62,6 @@
vbus_dwc3-supply = <&pm8941_mvs1>;
};
- qcom,mdss_dsi_toshiba_720p_video {
- qcom,rst-gpio = <&pma8084_gpios 20 0>;
- };
-
gpio_keys {
camera_snapshot {
gpios = <&pma8084_gpios 3 0x1>;
diff --git a/arch/arm/boot/dts/msm8974pro-ac.dtsi b/arch/arm/boot/dts/msm8974pro-ac.dtsi
index 032c256..4c55169 100644
--- a/arch/arm/boot/dts/msm8974pro-ac.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-ac.dtsi
@@ -52,6 +52,7 @@
vdd-supply = <&pma8084_l22>;
vddio-supply = <&pma8084_l12>;
vdda-supply = <&pma8084_l2>;
+ qcom,platform-reset-gpio = <&pma8084_gpios 20 0>;
};
qcom,mdss_dsi@fd922e00 {
@@ -188,3 +189,19 @@
&tspp {
vdd_cx-supply = <&pma8084_s2_corner>;
};
+
+&krait_regulator_pmic {
+ status = "ok";
+
+ qcom,ctl@2900 {
+ status = "ok";
+ };
+
+ qcom,ps@2a00 {
+ status = "ok";
+ };
+
+ qcom,freq@2b00 {
+ status = "ok";
+ };
+};
diff --git a/arch/arm/boot/dts/msm8974pro-pm.dtsi b/arch/arm/boot/dts/msm8974pro-pm.dtsi
new file mode 100644
index 0000000..31bff88
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974pro-pm.dtsi
@@ -0,0 +1,340 @@
+/* Copyright (c) 2013, 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.
+ */
+
+&soc {
+ qcom,spm@f9089000 {
+ compatible = "qcom,spm-v2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xf9089000 0x1000>;
+ qcom,core-id = <0>;
+ qcom,saw2-ver-reg = <0xfd0>;
+ qcom,saw2-cfg = <0x01>;
+ qcom,saw2-avs-ctl = <0>;
+ qcom,saw2-avs-hysteresis = <0>;
+ qcom,saw2-avs-limit = <0>;
+ qcom,saw2-avs-dly= <0>;
+ qcom,saw2-spm-dly= <0x3C102800>;
+ qcom,saw2-spm-ctl = <0x1>;
+ qcom,saw2-spm-cmd-wfi = [03 0b 0f];
+ qcom,saw2-spm-cmd-ret = [42 1b 00 d8 5B 03 d8 5b 0b 00 42 1b 0f];
+ qcom,saw2-spm-cmd-spc = [00 20 80 10 E8 5B 03 3B E8 5B 82 10 0B
+ 30 06 26 30 0F];
+ qcom,saw2-spm-cmd-pc = [00 20 80 10 E8 5B 03 3B E8 5B 82 10 0B
+ 30 06 26 30 0F];
+ };
+
+ qcom,spm@f9099000 {
+ compatible = "qcom,spm-v2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xf9099000 0x1000>;
+ qcom,core-id = <1>;
+ qcom,saw2-ver-reg = <0xfd0>;
+ qcom,saw2-cfg = <0x01>;
+ qcom,saw2-avs-ctl = <0>;
+ qcom,saw2-avs-hysteresis = <0>;
+ qcom,saw2-avs-limit = <0>;
+ qcom,saw2-avs-dly= <0>;
+ qcom,saw2-spm-dly= <0x3C102800>;
+ qcom,saw2-spm-ctl = <0x1>;
+ qcom,saw2-spm-cmd-wfi = [03 0b 0f];
+ qcom,saw2-spm-cmd-ret = [42 1b 00 d8 5B 03 d8 5b 0b 00 42 1b 0f];
+ qcom,saw2-spm-cmd-spc = [00 20 80 10 E8 5B 03 3B E8 5B 82 10 0B
+ 30 06 26 30 0F];
+ qcom,saw2-spm-cmd-pc = [00 20 80 10 E8 5B 03 3B E8 5B 82 10 0B
+ 30 06 26 30 0F];
+ };
+
+ qcom,spm@f90a9000 {
+ compatible = "qcom,spm-v2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xf90a9000 0x1000>;
+ qcom,core-id = <2>;
+ qcom,saw2-ver-reg = <0xfd0>;
+ qcom,saw2-cfg = <0x01>;
+ qcom,saw2-avs-ctl = <0>;
+ qcom,saw2-avs-hysteresis = <0>;
+ qcom,saw2-avs-limit = <0>;
+ qcom,saw2-avs-dly= <0>;
+ qcom,saw2-spm-dly= <0x3C102800>;
+ qcom,saw2-spm-ctl = <0x1>;
+ qcom,saw2-spm-cmd-wfi = [03 0b 0f];
+ qcom,saw2-spm-cmd-ret = [42 1b 00 d8 5B 03 d8 5b 0b 00 42 1b 0f];
+ qcom,saw2-spm-cmd-spc = [00 20 80 10 E8 5B 03 3B E8 5B 82 10 0B
+ 30 06 26 30 0F];
+ qcom,saw2-spm-cmd-pc = [00 20 80 10 E8 5B 03 3B E8 5B 82 10 0B
+ 30 06 26 30 0F];
+ };
+
+ qcom,spm@f90b9000 {
+ compatible = "qcom,spm-v2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xf90b9000 0x1000>;
+ qcom,core-id = <3>;
+ qcom,saw2-ver-reg = <0xfd0>;
+ qcom,saw2-cfg = <0x01>;
+ qcom,saw2-avs-ctl = <0>;
+ qcom,saw2-avs-hysteresis = <0>;
+ qcom,saw2-avs-limit = <0>;
+ qcom,saw2-avs-dly= <0>;
+ qcom,saw2-spm-dly= <0x3C102800>;
+ qcom,saw2-spm-ctl = <0x1>;
+ qcom,saw2-spm-cmd-wfi = [03 0b 0f];
+ qcom,saw2-spm-cmd-ret = [42 1b 00 d8 5B 03 d8 5b 0b 00 42 1b 0f];
+ qcom,saw2-spm-cmd-spc = [00 20 80 10 E8 5B 03 3B E8 5B 82 10 0B
+ 30 06 26 30 0F];
+ qcom,saw2-spm-cmd-pc = [00 20 80 10 E8 5B 03 3B E8 5B 82 10 0B
+ 30 06 26 30 0F];
+ };
+
+ qcom,spm@f9012000 {
+ compatible = "qcom,spm-v2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xf9012000 0x1000>;
+ qcom,core-id = <0xffff>; /* L2/APCS SAW */
+ qcom,saw2-ver-reg = <0xfd0>;
+ qcom,saw2-cfg = <0x14>;
+ qcom,saw2-avs-ctl = <0>;
+ qcom,saw2-avs-hysteresis = <0>;
+ qcom,saw2-avs-limit = <0>;
+ qcom,saw2-avs-dly= <0>;
+ qcom,saw2-spm-dly= <0x3C102800>;
+ qcom,saw2-spm-ctl = <0x1>;
+ qcom,saw2-pmic-data0 = <0x02030080>;
+ qcom,saw2-pmic-data1 = <0x00030000>;
+ qcom,vctl-timeout-us = <50>;
+ qcom,vctl-port = <0x0>;
+ qcom,phase-port = <0x1>;
+ qcom,pfm-port = <0x2>;
+ qcom,saw2-spm-cmd-ret = [1f 00 03 00 0f];
+ qcom,saw2-spm-cmd-gdhs = [00 32 42 07 44 50 02 32 50 0f];
+ qcom,saw2-spm-cmd-pc = [00 10 32 b0 11 42 07 01 b0 12 44
+ 50 02 32 50 0f];
+ };
+
+ qcom,lpm-levels {
+ compatible = "qcom,lpm-levels";
+ qcom,default-l2-state = "l2_cache_retention";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ qcom,lpm-level@0 {
+ reg = <0x0>;
+ qcom,mode = "wfi";
+ qcom,l2 = "l2_cache_retention";
+ qcom,latency-us = <1>;
+ qcom,ss-power = <715>;
+ qcom,energy-overhead = <17700>;
+ qcom,time-overhead = <2>;
+ };
+
+ qcom,lpm-level@1 {
+ reg = <0x1>;
+ qcom,mode = "retention";
+ qcom,l2 = "l2_cache_retention";
+ qcom,latency-us = <35>;
+ qcom,ss-power = <542>;
+ qcom,energy-overhead = <34920>;
+ qcom,time-overhead = <40>;
+ };
+
+
+ qcom,lpm-level@2 {
+ reg = <0x2>;
+ qcom,mode = "standalone_pc";
+ qcom,l2 = "l2_cache_retention";
+ qcom,latency-us = <300>;
+ qcom,ss-power = <476>;
+ qcom,energy-overhead = <225300>;
+ qcom,time-overhead = <350>;
+ };
+
+ qcom,lpm-level@3 {
+ reg = <0x3>;
+ qcom,mode = "pc";
+ qcom,l2 = "l2_cache_gdhs";
+ qcom,gpio-detectable;
+ qcom,latency-us = <20000>;
+ qcom,ss-power = <163>;
+ qcom,energy-overhead = <1577736>;
+ qcom,time-overhead = <5067>;
+ };
+
+ qcom,lpm-level@4 {
+ reg = <0x4>;
+ qcom,mode = "pc";
+ qcom,l2 = "l2_cache_pc";
+ qcom,latency-us = <30000>;
+ qcom,ss-power = <83>;
+ qcom,energy-overhead = <2274420>;
+ qcom,time-overhead = <6605>;
+ };
+ };
+
+ qcom,pm-boot {
+ compatible = "qcom,pm-boot";
+ qcom,mode = "tz";
+ };
+
+ qcom,mpm@fc4281d0 {
+ compatible = "qcom,mpm-v2";
+ reg = <0xfc4281d0 0x1000>, /* MSM_RPM_MPM_BASE 4K */
+ <0xf9011008 0x4>; /* MSM_APCS_GCC_BASE 4K */
+ reg-names = "vmpm", "ipc";
+ interrupts = <0 171 1>;
+
+ qcom,ipc-bit-offset = <1>;
+
+ qcom,gic-parent = <&intc>;
+ qcom,gic-map = <2 216>, /* tsens_upper_lower_int */
+ <47 165>, /* usb30_hs_phy_irq */
+ <50 172>, /* usb1_hs_async_wakeup_irq */
+ <53 104>, /* mdss_irq */
+ <62 222>, /* ee0_krait_hlos_spmi_periph_irq */
+ <0xff 56>, /* modem_watchdog */
+ <0xff 57>, /* mss_to_apps_irq(0) */
+ <0xff 58>, /* mss_to_apps_irq(1) */
+ <0xff 59>, /* mss_to_apps_irq(2) */
+ <0xff 60>, /* mss_to_apps_irq(3) */
+ <0xff 61>, /* mss_a2_bam_irq */
+ <0xff 70>, /* iommu_pmon_nonsecure_irq */
+ <0xff 97>, /* iommu_nonsecure_irq */
+ <0xff 105>, /* iommu_pmon_nonsecure_irq */
+ <0xff 173>, /* o_wcss_apss_smd_hi */
+ <0xff 174>, /* o_wcss_apss_smd_med */
+ <0xff 175>, /* o_wcss_apss_smd_low */
+ <0xff 176>, /* o_wcss_apss_smsm_irq */
+ <0xff 177>, /* o_wcss_apss_wlan_data_xfer_done */
+ <0xff 178>, /* o_wcss_apss_wlan_rx_data_avail */
+ <0xff 179>, /* o_wcss_apss_asic_intr */
+
+ <0xff 181>, /* wcnss watchdog */
+ <0xff 188>, /* lpass_irq_out_apcs(0) */
+ <0xff 189>, /* lpass_irq_out_apcs(1) */
+ <0xff 190>, /* lpass_irq_out_apcs(2) */
+ <0xff 191>, /* lpass_irq_out_apcs(3) */
+ <0xff 192>, /* lpass_irq_out_apcs(4) */
+ <0xff 193>, /* lpass_irq_out_apcs(5) */
+ <0xff 194>, /* lpass_irq_out_apcs(6) */
+ <0xff 195>, /* lpass_irq_out_apcs(7) */
+ <0xff 196>, /* lpass_irq_out_apcs(8) */
+ <0xff 197>, /* lpass_irq_out_apcs(9) */
+ <0xff 200>, /* rpm_ipc(4) */
+ <0xff 201>, /* rpm_ipc(5) */
+ <0xff 202>, /* rpm_ipc(6) */
+ <0xff 203>, /* rpm_ipc(7) */
+ <0xff 204>, /* rpm_ipc(24) */
+ <0xff 205>, /* rpm_ipc(25) */
+ <0xff 206>, /* rpm_ipc(26) */
+ <0xff 207>, /* rpm_ipc(27) */
+ <0xff 211>, /* usb_dwc3_otg */
+ <0xff 240>; /* summary_irq_kpss */
+
+ qcom,gpio-parent = <&msmgpio>;
+ qcom,gpio-map = <3 102>,
+ <4 1 >,
+ <5 5 >,
+ <6 9 >,
+ <7 18>,
+ <8 20>,
+ <9 24>,
+ <10 27>,
+ <11 28>,
+ <12 34>,
+ <13 35>,
+ <14 37>,
+ <15 42>,
+ <16 44>,
+ <17 46>,
+ <18 50>,
+ <19 54>,
+ <20 59>,
+ <21 61>,
+ <22 62>,
+ <23 64>,
+ <24 65>,
+ <25 66>,
+ <26 67>,
+ <27 68>,
+ <28 71>,
+ <29 72>,
+ <30 73>,
+ <31 74>,
+ <32 75>,
+ <33 77>,
+ <34 79>,
+ <35 80>,
+ <36 82>,
+ <37 86>,
+ <38 92>,
+ <39 93>,
+ <40 95>,
+ <41 144>;
+ };
+
+ qcom,pm-8x60@fe805664 {
+ compatible = "qcom,pm-8x60";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ reg = <0xfe805664 0x40>;
+ qcom,pc-mode = "tz_l2_int";
+ qcom,use-sync-timer;
+ qcom,cpus-as-clocks;
+
+ qcom,pm-snoc-client {
+ compatible = "qcom,pm-snoc-client";
+ qcom,msm-bus,name = "ocimem_snoc";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,active-only;
+ qcom,msm-bus,vectors-KBps =
+ <54 585 0 0>,
+ <54 585 0 800000>;
+ };
+ };
+
+ qcom,cpu-sleep-status@f9088008{
+ compatible = "qcom,cpu-sleep-status";
+ reg = <0xf9088008 0x100>;
+ qcom,cpu-alias-addr = <0x10000>;
+ qcom,sleep-status-mask= <0x80000>;
+ };
+
+ qcom,rpm-log@fc19dc00 {
+ compatible = "qcom,rpm-log";
+ reg = <0xfc19dc00 0x4000>;
+ qcom,rpm-addr-phys = <0xfc000000>;
+ qcom,offset-version = <4>;
+ qcom,offset-page-buffer-addr = <36>;
+ qcom,offset-log-len = <40>;
+ qcom,offset-log-len-mask = <44>;
+ qcom,offset-page-indices = <56>;
+ };
+
+ qcom,rpm-stats@fc19dba0 {
+ compatible = "qcom,rpm-stats";
+ reg = <0xfc19dba0 0x1000>;
+ reg-names = "phys_addr_base";
+ qcom,sleep-stats-version = <2>;
+ };
+
+ qcom,rpm-rbcpr-stats@fc000000 {
+ compatible = "qcom,rpmrbcpr-stats";
+ reg = <0xfc000000 0x1a0000>;
+ qcom,start-offset = <0x190010>;
+ };
+};
diff --git a/arch/arm/boot/dts/msm8974pro.dtsi b/arch/arm/boot/dts/msm8974pro.dtsi
index e7c6a48..7914a6a 100644
--- a/arch/arm/boot/dts/msm8974pro.dtsi
+++ b/arch/arm/boot/dts/msm8974pro.dtsi
@@ -19,7 +19,7 @@
/include/ "msm8974.dtsi"
/include/ "msm8974-v2-iommu.dtsi"
/include/ "msm8974-v2-iommu-domains.dtsi"
-/include/ "msm8974-v2-pm.dtsi"
+/include/ "msm8974pro-pm.dtsi"
/include/ "msm8974pro-ion.dtsi"
&soc {
diff --git a/arch/arm/configs/msm8226-perf_defconfig b/arch/arm/configs/msm8226-perf_defconfig
index 67ed35c..47b425c 100644
--- a/arch/arm/configs/msm8226-perf_defconfig
+++ b/arch/arm/configs/msm8226-perf_defconfig
@@ -1,6 +1,5 @@
# CONFIG_ARM_PATCH_PHYS_VIRT is not set
CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_SYSVIPC=y
CONFIG_RCU_FAST_NO_HZ=y
CONFIG_IKCONFIG=y
@@ -72,6 +71,7 @@
CONFIG_MSM_RTB_SEPARATE_CPUS=y
CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
CONFIG_MSM_BOOT_STATS=y
+CONFIG_STRICT_MEMORY_RWX=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_SMP=y
diff --git a/arch/arm/configs/msm8226_defconfig b/arch/arm/configs/msm8226_defconfig
index d42d54d..97c3664 100644
--- a/arch/arm/configs/msm8226_defconfig
+++ b/arch/arm/configs/msm8226_defconfig
@@ -1,6 +1,5 @@
# CONFIG_ARM_PATCH_PHYS_VIRT is not set
CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_SYSVIPC=y
CONFIG_RCU_FAST_NO_HZ=y
CONFIG_IKCONFIG=y
@@ -73,6 +72,7 @@
CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
CONFIG_MSM_BOOT_STATS=y
CONFIG_MSM_XPU_ERR_FATAL=y
+CONFIG_STRICT_MEMORY_RWX=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_SMP=y
diff --git a/arch/arm/configs/msm8610-perf_defconfig b/arch/arm/configs/msm8610-perf_defconfig
index 795a50d..8591812 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -71,6 +71,7 @@
CONFIG_SENSORS_ADSP=y
CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
CONFIG_MSM_BOOT_STATS=y
+CONFIG_STRICT_MEMORY_RWX=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_SMP=y
@@ -232,6 +233,7 @@
CONFIG_INPUT_MISC=y
CONFIG_INPUT_UINPUT=y
CONFIG_INPUT_GPIO=m
+# CONFIG_INPUT_MOUSEDEV is not set
CONFIG_SERIAL_MSM_HSL=y
CONFIG_SERIAL_MSM_HSL_CONSOLE=y
CONFIG_DIAG_CHAR=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index a5f0704..20938d5 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -1,6 +1,5 @@
# CONFIG_ARM_PATCH_PHYS_VIRT is not set
CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_SYSVIPC=y
CONFIG_RCU_FAST_NO_HZ=y
CONFIG_IKCONFIG=y
@@ -71,6 +70,7 @@
CONFIG_MSM_RTB_SEPARATE_CPUS=y
CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
CONFIG_MSM_BOOT_STATS=y
+CONFIG_STRICT_MEMORY_RWX=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_SMP=y
@@ -232,6 +232,7 @@
CONFIG_INPUT_MISC=y
CONFIG_INPUT_UINPUT=y
CONFIG_INPUT_GPIO=m
+# CONFIG_INPUT_MOUSEDEV is not set
CONFIG_SERIAL_MSM_HSL=y
CONFIG_SERIAL_MSM_HSL_CONSOLE=y
CONFIG_DIAG_CHAR=y
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index f498919..12ffa66 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -296,7 +296,7 @@
obj-$(CONFIG_ARCH_MSM8610) += gdsc.o
obj-$(CONFIG_ARCH_MPQ8092) += gdsc.o
obj-$(CONFIG_ARCH_APQ8084) += gdsc.o
-obj-$(CONFIG_KRAIT_REGULATOR) += krait-regulator.o
+obj-$(CONFIG_KRAIT_REGULATOR) += krait-regulator.o krait-regulator-pmic.o
obj-$(CONFIG_ARCH_MSMKRYPTON) += board-krypton.o board-krypton-gpiomux.o
obj-$(CONFIG_ARCH_MSMSAMARIUM) += board-samarium.o board-samarium-gpiomux.o
obj-$(CONFIG_ARCH_MSM9625) += board-9625.o board-9625-gpiomux.o
diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
index 01c7a2a..910264e 100644
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -134,12 +134,16 @@
# MSM8610
zreladdr-$(CONFIG_ARCH_MSM8610) := 0x00008000
- dtb-$(CONFIG_ARCH_MSM8610) += msm8610-cdp.dtb
- dtb-$(CONFIG_ARCH_MSM8610) += msm8610-mtp.dtb
+ dtb-$(CONFIG_ARCH_MSM8610) += msm8610-v1-cdp.dtb
+ dtb-$(CONFIG_ARCH_MSM8610) += msm8610-v2-cdp.dtb
+ dtb-$(CONFIG_ARCH_MSM8610) += msm8610-v1-mtp.dtb
+ dtb-$(CONFIG_ARCH_MSM8610) += msm8610-v2-mtp.dtb
dtb-$(CONFIG_ARCH_MSM8610) += msm8610-rumi.dtb
dtb-$(CONFIG_ARCH_MSM8610) += msm8610-sim.dtb
- dtb-$(CONFIG_ARCH_MSM8610) += msm8610-qrd-skuaa.dtb
- dtb-$(CONFIG_ARCH_MSM8610) += msm8610-qrd-skuab.dtb
+ dtb-$(CONFIG_ARCH_MSM8610) += msm8610-v1-qrd-skuaa.dtb
+ dtb-$(CONFIG_ARCH_MSM8610) += msm8610-v1-qrd-skuab.dtb
+ dtb-$(CONFIG_ARCH_MSM8610) += msm8610-v2-qrd-skuaa.dtb
+ dtb-$(CONFIG_ARCH_MSM8610) += msm8610-v2-qrd-skuab.dtb
# MSMSAMARIUM
zreladdr-$(CONFIG_ARCH_MSMSAMARIUM) := 0x00008000
diff --git a/arch/arm/mach-msm/board-8226-gpiomux.c b/arch/arm/mach-msm/board-8226-gpiomux.c
index 4ea5654..ebb90af 100644
--- a/arch/arm/mach-msm/board-8226-gpiomux.c
+++ b/arch/arm/mach-msm/board-8226-gpiomux.c
@@ -57,7 +57,7 @@
static struct gpiomux_setting synaptics_reset_sus_cfg = {
.func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_6MA,
+ .drv = GPIOMUX_DRV_2MA,
.pull = GPIOMUX_PULL_DOWN,
};
diff --git a/arch/arm/mach-msm/clock-8610.c b/arch/arm/mach-msm/clock-8610.c
index 39916ef..f8c206b 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -240,6 +240,7 @@
#define GFX3D_CMD_RCGR 0x4000
#define OXILI_GFX3D_CBCR 0x4028
#define OXILI_GFX3D_BCR 0x4030
+#define GMEM_GFX3D_BCR 0x4040
#define OXILI_AHB_BCR 0x4044
#define OXILI_AHB_CBCR 0x403C
#define AHB_CMD_RCGR 0x5000
@@ -2147,6 +2148,7 @@
static struct branch_clk csi_vfe_clk = {
.cbcr_reg = CSI_VFE_CBCR,
+ .bcr_reg = CSI_VFE_BCR,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -2217,6 +2219,7 @@
static struct branch_clk gmem_gfx3d_clk = {
.cbcr_reg = GMEM_GFX3D_CBCR,
+ .bcr_reg = GMEM_GFX3D_BCR,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -2358,6 +2361,7 @@
static struct branch_clk oxili_ahb_clk = {
.cbcr_reg = OXILI_AHB_CBCR,
+ .bcr_reg = OXILI_AHB_BCR,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -2369,6 +2373,7 @@
static struct branch_clk oxili_gfx3d_clk = {
.cbcr_reg = OXILI_GFX3D_CBCR,
+ .bcr_reg = OXILI_GFX3D_BCR,
.has_sibling = 0,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -2381,6 +2386,7 @@
static struct branch_clk vfe_clk = {
.cbcr_reg = VFE_CBCR,
+ .bcr_reg = VFE_BCR,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -2393,6 +2399,7 @@
static struct branch_clk vfe_ahb_clk = {
.cbcr_reg = VFE_AHB_CBCR,
+ .bcr_reg = VFE_AHB_BCR,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -2404,6 +2411,7 @@
static struct branch_clk vfe_axi_clk = {
.cbcr_reg = VFE_AXI_CBCR,
+ .bcr_reg = VFE_AXI_BCR,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
/* FIXME: Remove this once simulation is fixed. */
@@ -3133,6 +3141,14 @@
CLK_LOOKUP("iface_clk", gcc_ce1_ahb_clk.c, "fd404000.qcom,qcrypto"),
CLK_LOOKUP("bus_clk", gcc_ce1_axi_clk.c, "fd404000.qcom,qcrypto"),
CLK_LOOKUP("core_clk_src", ce1_clk_src.c, "fd404000.qcom,qcrypto"),
+
+ /* GDSC clocks */
+ CLK_LOOKUP("core_clk", vfe_clk.c, "fd8c36a4.qcom,gdsc"),
+ CLK_LOOKUP("iface_clk", vfe_ahb_clk.c, "fd8c36a4.qcom,gdsc"),
+ CLK_LOOKUP("bus_clk", vfe_axi_clk.c, "fd8c36a4.qcom,gdsc"),
+ CLK_LOOKUP("core_clk", oxili_gfx3d_clk.c, "fd8c4034.qcom,gdsc"),
+ CLK_LOOKUP("iface_clk", oxili_ahb_clk.c, "fd8c4034.qcom,gdsc"),
+ CLK_LOOKUP("mem_clk", gmem_gfx3d_clk.c, "fd8c4034.qcom,gdsc"),
};
static struct clk_lookup msm_clocks_8610_rumi[] = {
diff --git a/arch/arm/mach-msm/clock-local2.c b/arch/arm/mach-msm/clock-local2.c
index b7852fe..4488869 100644
--- a/arch/arm/mach-msm/clock-local2.c
+++ b/arch/arm/mach-msm/clock-local2.c
@@ -549,19 +549,21 @@
u32 cbcr_val;
unsigned long irq_flags;
struct branch_clk *branch = to_branch_clk(c);
- int ret = 0;
+ int delay_us = 0, ret = 0;
spin_lock_irqsave(&local_clock_reg_lock, irq_flags);
cbcr_val = readl_relaxed(CBCR_REG(branch));
switch (flags) {
case CLKFLAG_RETAIN_PERIPH:
cbcr_val |= BIT(13);
+ delay_us = 1;
break;
case CLKFLAG_NORETAIN_PERIPH:
cbcr_val &= ~BIT(13);
break;
case CLKFLAG_RETAIN_MEM:
cbcr_val |= BIT(14);
+ delay_us = 1;
break;
case CLKFLAG_NORETAIN_MEM:
cbcr_val &= ~BIT(14);
@@ -570,17 +572,11 @@
ret = -EINVAL;
}
writel_relaxed(cbcr_val, CBCR_REG(branch));
- /*
- * 8974v2.2 has a requirement that writes to set bits 13 and 14 are
- * separated by at least 2 bus cycles. Cover one of these cycles by
- * performing an extra write here. The other cycle is covered by the
- * read-modify-write design of this function.
- */
- writel_relaxed(cbcr_val, CBCR_REG(branch));
- spin_unlock_irqrestore(&local_clock_reg_lock, irq_flags);
-
- /* Make sure write is issued before returning. */
+ /* Make sure power is enabled before returning. */
mb();
+ udelay(delay_us);
+
+ spin_unlock_irqrestore(&local_clock_reg_lock, irq_flags);
return ret;
}
diff --git a/arch/arm/mach-msm/gdsc.c b/arch/arm/mach-msm/gdsc.c
index 774548c..ea4865d 100644
--- a/arch/arm/mach-msm/gdsc.c
+++ b/arch/arm/mach-msm/gdsc.c
@@ -111,6 +111,13 @@
uint32_t regval;
int i, ret = 0;
+ for (i = sc->clock_count-1; i >= 0; i--) {
+ if (sc->toggle_mem)
+ clk_set_flags(sc->clocks[i], CLKFLAG_NORETAIN_MEM);
+ if (sc->toggle_periph)
+ clk_set_flags(sc->clocks[i], CLKFLAG_NORETAIN_PERIPH);
+ }
+
if (sc->toggle_logic) {
regval = readl_relaxed(sc->gdscr);
regval |= SW_COLLAPSE_MASK;
@@ -123,18 +130,11 @@
dev_err(&rdev->dev, "%s disable timed out\n",
sc->rdesc.name);
} else {
- for (i = 0; i < sc->clock_count; i++)
+ for (i = sc->clock_count-1; i >= 0; i--)
clk_reset(sc->clocks[i], CLK_RESET_ASSERT);
sc->resets_asserted = true;
}
- for (i = 0; i < sc->clock_count; i++) {
- if (sc->toggle_mem)
- clk_set_flags(sc->clocks[i], CLKFLAG_NORETAIN_MEM);
- if (sc->toggle_periph)
- clk_set_flags(sc->clocks[i], CLKFLAG_NORETAIN_PERIPH);
- }
-
return ret;
}
@@ -225,20 +225,9 @@
retain_mem = of_property_read_bool(pdev->dev.of_node,
"qcom,retain-mem");
+ sc->toggle_mem = !retain_mem;
retain_periph = of_property_read_bool(pdev->dev.of_node,
"qcom,retain-periph");
- for (i = 0; i < sc->clock_count; i++) {
- if (retain_mem || (regval & PWR_ON_MASK))
- clk_set_flags(sc->clocks[i], CLKFLAG_RETAIN_MEM);
- else
- clk_set_flags(sc->clocks[i], CLKFLAG_NORETAIN_MEM);
-
- if (retain_periph || (regval & PWR_ON_MASK))
- clk_set_flags(sc->clocks[i], CLKFLAG_RETAIN_PERIPH);
- else
- clk_set_flags(sc->clocks[i], CLKFLAG_NORETAIN_PERIPH);
- }
- sc->toggle_mem = !retain_mem;
sc->toggle_periph = !retain_periph;
sc->toggle_logic = !of_property_read_bool(pdev->dev.of_node,
"qcom,skip-logic-collapse");
@@ -255,6 +244,18 @@
}
}
+ for (i = 0; i < sc->clock_count; i++) {
+ if (retain_mem || (regval & PWR_ON_MASK))
+ clk_set_flags(sc->clocks[i], CLKFLAG_RETAIN_MEM);
+ else
+ clk_set_flags(sc->clocks[i], CLKFLAG_NORETAIN_MEM);
+
+ if (retain_periph || (regval & PWR_ON_MASK))
+ clk_set_flags(sc->clocks[i], CLKFLAG_RETAIN_PERIPH);
+ else
+ clk_set_flags(sc->clocks[i], CLKFLAG_NORETAIN_PERIPH);
+ }
+
sc->rdev = regulator_register(&sc->rdesc, &pdev->dev, init_data, sc,
pdev->dev.of_node);
if (IS_ERR(sc->rdev)) {
diff --git a/arch/arm/mach-msm/ipc_router.c b/arch/arm/mach-msm/ipc_router.c
index 863a2d7..6fe945c 100644
--- a/arch/arm/mach-msm/ipc_router.c
+++ b/arch/arm/mach-msm/ipc_router.c
@@ -1350,7 +1350,7 @@
struct msm_ipc_router_xprt_info *xprt_info)
{
int i;
- struct msm_ipc_routing_table_entry *rt_entry;
+ struct msm_ipc_routing_table_entry *rt_entry, *tmp_rt_entry;
if (!xprt_info) {
pr_err("%s: Invalid xprt_info\n", __func__);
@@ -1360,7 +1360,8 @@
down_write(&server_list_lock_lha2);
down_write(&routing_table_lock_lha3);
for (i = 0; i < RT_HASH_SIZE; i++) {
- list_for_each_entry(rt_entry, &routing_table[i], list) {
+ list_for_each_entry_safe(rt_entry, tmp_rt_entry,
+ &routing_table[i], list) {
down_write(&rt_entry->lock_lha4);
if (rt_entry->xprt_info != xprt_info) {
up_write(&rt_entry->lock_lha4);
@@ -1369,6 +1370,8 @@
cleanup_rmt_ports(xprt_info, rt_entry);
rt_entry->xprt_info = NULL;
up_write(&rt_entry->lock_lha4);
+ list_del(&rt_entry->list);
+ kfree(rt_entry);
}
}
up_write(&routing_table_lock_lha3);
diff --git a/arch/arm/mach-msm/krait-regulator-pmic.c b/arch/arm/mach-msm/krait-regulator-pmic.c
new file mode 100644
index 0000000..5081e7b
--- /dev/null
+++ b/arch/arm/mach-msm/krait-regulator-pmic.c
@@ -0,0 +1,403 @@
+/* Copyright (c) 2013, 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.
+ */
+
+#define pr_fmt(fmt) "PMIC PDN %s: " fmt, __func__
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/spmi.h>
+#include <linux/delay.h>
+
+#define KRAIT_REG_PMIC_DEV_NAME "qcom,krait-regulator-pmic"
+
+#define REG_DIG_MAJOR 0x01
+#define REG_DIG_MINOR 0x00
+
+#define REG_PERPH_TYPE 0x04
+#define CTRL_TYPE_VAL 0x1C
+#define PS_TYPE_VAL 0x1C
+#define FREQ_TYPE_VAL 0x1D
+
+#define REG_PERPH_SUBTYPE 0x05
+#define CTRL_SUBTYPE_VAL 0x08
+#define PS_SUBTYPE_VAL 0x01
+#define FREQ_SUBTYPE_VAL 0x19
+
+#define REG_V_CTL1 0x40
+#define V_CTL1_VAL 0x00
+
+#define REG_MODE_CTL 0x45
+#define NPM_MODE_BIT BIT(7)
+#define AUTO_MODE_BIT BIT(6)
+
+#define REG_EN_CTL 0x46
+#define EN_BIT BIT(7)
+
+#define REG_PD_CTL 0x48
+#define PD_CTL_VAL 0x08
+
+#define REG_MULTIPHASE_CTL 0x51
+#define MULTIPHASE_EN_BIT BIT(7)
+
+#define REG_PHASE_CTL 0x52
+#define BALANCE_EN_BIT BIT(7)
+
+#define REG_VS_CTL 0x61
+#define VS_CTL_VAL 0x85
+
+#define REG_GANG_CTL2 0xC1
+#define GANG_EN_BIT BIT(7)
+
+#define REG_PWM_CL 0x60
+
+struct krait_vreg_pmic_chip {
+ struct spmi_device *spmi;
+ u16 ctrl_base;
+ u16 ps_base;
+ u16 freq_base;
+ u8 ctrl_dig_major;
+ u8 ctrl_dig_minor;
+};
+
+static struct krait_vreg_pmic_chip *the_chip;
+
+static struct of_device_id krait_vreg_pmic_match_table[] = {
+ { .compatible = KRAIT_REG_PMIC_DEV_NAME },
+ {}
+};
+
+static int read_byte(struct spmi_device *spmi, u16 addr, u8 *val)
+{
+ int rc;
+
+ rc = spmi_ext_register_readl(spmi->ctrl, spmi->sid, addr, val, 1);
+ if (rc) {
+ pr_err("SPMI read failed [%d,0x%04x] rc=%d\n",
+ spmi->sid, addr, rc);
+ return rc;
+ }
+ return 0;
+}
+
+static int write_byte(struct spmi_device *spmi, u16 addr, u8 *val)
+{
+ int rc;
+
+ rc = spmi_ext_register_writel(spmi->ctrl, spmi->sid, addr, val, 1);
+ if (rc) {
+ pr_err("SPMI write failed [%d,0x%04x] val = 0x%02x rc=%d\n",
+ spmi->sid, addr, *val, rc);
+ return rc;
+ }
+ return 0;
+}
+
+#define ISTEP_MA 500
+#define IOFFSET_MA 1000
+#define OVERSHOOT_DIG_MAJOR 1
+#define OVERSHOOT_DIG_MINOR 1
+static bool v_overshoot_fixed(void)
+{
+ if (the_chip->ctrl_dig_major > OVERSHOOT_DIG_MAJOR
+ || (the_chip->ctrl_dig_major == OVERSHOOT_DIG_MAJOR
+ && the_chip->ctrl_dig_minor > OVERSHOOT_DIG_MINOR)) {
+ pr_debug("fixed in h/w\n");
+ return true;
+ }
+ return false;
+}
+
+/**
+ * krait_pmic_is_ready - function to check if the driver is initialized
+ *
+ * CONTEXT: Can be called in atomic context
+ *
+ * RETURNS: true if this driver has initialized, false otherwise
+ */
+bool krait_pmic_is_ready(void)
+{
+ if (the_chip == NULL) {
+ pr_debug("kait_regulator_pmic not ready yet\n");
+ return false;
+ }
+ return true;
+}
+EXPORT_SYMBOL(krait_pmic_is_ready);
+
+#define I_PFM_MA 2000
+
+/**
+ * krait_pmic_post_pfm_entry - workarounds after entering pfm mode
+ *
+ * CONTEXT: Can be called in atomic context
+ *
+ * RETURNS: 0 on success, error code on failure
+ */
+int krait_pmic_post_pfm_entry(void)
+{
+ u8 setpoint;
+ int rc;
+
+ if (the_chip == NULL) {
+ pr_debug("kait_regulator_pmic not ready yet\n");
+ return -ENXIO;
+ }
+
+ if (v_overshoot_fixed())
+ return 0;
+
+ setpoint = (I_PFM_MA - IOFFSET_MA) / ISTEP_MA;
+ rc = write_byte(the_chip->spmi,
+ the_chip->ps_base + REG_PWM_CL, &setpoint);
+ pr_debug("wrote 0x%02x->[%d 0x%04x] rc = %d\n", setpoint,
+ the_chip->spmi->sid,
+ the_chip->ps_base + REG_PWM_CL, rc);
+ return rc;
+}
+EXPORT_SYMBOL(krait_pmic_post_pfm_entry);
+
+#define I_PWM_MA 3500
+/**
+ * krait_pmic_post_pwm_entry - workarounds after entering pwm mode
+ *
+ * CONTEXT: Can be called in atomic context
+ *
+ * RETURNS: 0 on success, error code on failure
+ */
+int krait_pmic_post_pwm_entry(void)
+{
+ u8 setpoint;
+ int rc;
+
+ if (the_chip == NULL) {
+ pr_debug("kait_regulator_pmic not ready yet\n");
+ return -ENXIO;
+ }
+
+ if (v_overshoot_fixed())
+ return 0;
+
+ udelay(50);
+ setpoint = (I_PWM_MA - IOFFSET_MA) / ISTEP_MA;
+
+ rc = write_byte(the_chip->spmi,
+ the_chip->ps_base + REG_PWM_CL, &setpoint);
+ pr_debug("wrote 0x%02x->[%d 0x%04x] rc = %d\n", setpoint,
+ the_chip->spmi->sid,
+ the_chip->ps_base + REG_PWM_CL, rc);
+ return rc;
+}
+EXPORT_SYMBOL(krait_pmic_post_pwm_entry);
+
+#define READ_BYTE(chip, addr, val, rc) \
+do { \
+ rc = read_byte(chip->spmi, (addr), &val); \
+ if (rc) \
+ pr_err("register read failed rc=%d\n", rc); \
+} while (0)
+
+#define GANGED_VREG_COUNT 4
+static int gang_configuration_check(struct krait_vreg_pmic_chip *chip)
+{
+ u8 val;
+ int rc;
+ int i;
+
+ return 0;
+
+ READ_BYTE(chip, chip->ctrl_base + REG_V_CTL1, val, rc);
+ if (rc)
+ return rc;
+ BUG_ON(val != V_CTL1_VAL);
+
+ READ_BYTE(chip, chip->ctrl_base + REG_MODE_CTL, val, rc);
+ if (rc)
+ return rc;
+ /* The Auto mode should be off */
+ BUG_ON(val & AUTO_MODE_BIT);
+ /* The NPM mode should be on */
+ BUG_ON(!(val & NPM_MODE_BIT));
+
+ READ_BYTE(chip, chip->ctrl_base + REG_EN_CTL, val, rc);
+ if (rc)
+ return rc;
+ /* The en bit should be set */
+ BUG_ON(val & EN_BIT);
+
+ READ_BYTE(chip, chip->ctrl_base + REG_PD_CTL, val, rc);
+ if (rc)
+ return rc;
+ BUG_ON(val != PD_CTL_VAL);
+
+ READ_BYTE(chip, chip->ctrl_base + REG_MULTIPHASE_CTL, val, rc);
+ if (rc)
+ return rc;
+ BUG_ON(!(val & MULTIPHASE_EN_BIT));
+
+ READ_BYTE(chip, chip->ctrl_base + REG_PHASE_CTL, val, rc);
+ if (rc)
+ return rc;
+ BUG_ON(!(val & BALANCE_EN_BIT));
+
+ READ_BYTE(chip, chip->ctrl_base + REG_VS_CTL, val, rc);
+ if (rc)
+ return rc;
+ BUG_ON(val != VS_CTL_VAL);
+
+ for (i = 0; i < GANGED_VREG_COUNT; i++) {
+ READ_BYTE(chip,
+ chip->ctrl_base + i * 0x300 + REG_GANG_CTL2, val, rc);
+ if (rc)
+ return rc;
+
+ if (!(val & GANG_EN_BIT)) {
+ pr_err("buck = %d, ctrl gang not enabled\n", i);
+ BUG();
+ }
+ }
+
+ for (i = 0; i < GANGED_VREG_COUNT; i++) {
+ READ_BYTE(chip,
+ chip->ps_base + i * 0x300 + REG_GANG_CTL2, val, rc);
+ if (rc)
+ return rc;
+
+ if (!(val & GANG_EN_BIT)) {
+ pr_err("buck = %d, ps gang not enabled\n", i);
+ BUG();
+ }
+ }
+
+ for (i = 0; i < GANGED_VREG_COUNT; i++) {
+ READ_BYTE(chip,
+ chip->freq_base + i * 0x300 + REG_GANG_CTL2, val, rc);
+ if (rc)
+ return rc;
+
+ if (!(val & GANG_EN_BIT)) {
+ pr_err("buck = %d, freq gang not enabled\n", i);
+ BUG();
+ }
+ }
+ return 0;
+}
+
+static int __devinit krait_vreg_pmic_probe(struct spmi_device *spmi)
+{
+ u8 type, subtype;
+ int rc;
+ struct krait_vreg_pmic_chip *chip;
+ struct spmi_resource *spmi_resource;
+ struct resource *resource;
+
+ chip = devm_kzalloc(&spmi->dev, sizeof *chip, GFP_KERNEL);
+ if (chip == NULL) {
+ pr_err("kzalloc() failed.\n");
+ return -ENOMEM;
+ }
+
+ chip->spmi = spmi;
+
+ spmi_for_each_container_dev(spmi_resource, spmi) {
+ if (!spmi_resource) {
+ pr_err("spmi resource absent\n");
+ return -ENXIO;
+ }
+
+ resource = spmi_get_resource(spmi, spmi_resource,
+ IORESOURCE_MEM, 0);
+ if (!(resource && resource->start)) {
+ pr_err("node %s IO resource absent!\n",
+ spmi->dev.of_node->full_name);
+ return -ENXIO;
+ }
+
+ rc = read_byte(chip->spmi,
+ resource->start + REG_PERPH_TYPE,
+ &type);
+ if (rc) {
+ pr_err("Peripheral type read failed rc=%d\n", rc);
+ return -ENXIO;
+ }
+
+ rc = read_byte(chip->spmi,
+ resource->start + REG_PERPH_SUBTYPE,
+ &subtype);
+ if (rc) {
+ pr_err("Peripheral subtype read failed rc=%d\n", rc);
+ return -ENXIO;
+ }
+
+ if (type == CTRL_TYPE_VAL && subtype == CTRL_SUBTYPE_VAL)
+ chip->ctrl_base = resource->start;
+ else if (type == PS_TYPE_VAL && subtype == PS_SUBTYPE_VAL)
+ chip->ps_base = resource->start;
+ else if (type == FREQ_TYPE_VAL && subtype == FREQ_SUBTYPE_VAL)
+ chip->freq_base = resource->start;
+ }
+
+ if (chip->ctrl_base == 0) {
+ pr_err("ctrl base address missing\n");
+ return -ENXIO;
+ }
+
+ if (chip->ps_base == 0) {
+ pr_err("ps base address missing\n");
+ return -ENXIO;
+ }
+
+ if (chip->freq_base == 0) {
+ pr_err("freq base address missing\n");
+ return -ENXIO;
+ }
+
+ READ_BYTE(chip, chip->ctrl_base + REG_DIG_MAJOR,
+ chip->ctrl_dig_major, rc);
+ if (rc)
+ return rc;
+
+ READ_BYTE(chip, chip->ctrl_base + REG_DIG_MINOR,
+ chip->ctrl_dig_minor, rc);
+ if (rc)
+ return rc;
+
+ gang_configuration_check(chip);
+
+ the_chip = chip;
+ return 0;
+}
+
+static struct spmi_driver qpnp_revid_driver = {
+ .probe = krait_vreg_pmic_probe,
+ .driver = {
+ .name = KRAIT_REG_PMIC_DEV_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = krait_vreg_pmic_match_table,
+ },
+};
+
+static int __init qpnp_revid_init(void)
+{
+ return spmi_driver_register(&qpnp_revid_driver);
+}
+
+static void __exit qpnp_revid_exit(void)
+{
+ return spmi_driver_unregister(&qpnp_revid_driver);
+}
+
+module_init(qpnp_revid_init);
+module_exit(qpnp_revid_exit);
+
+MODULE_DESCRIPTION("KRAIT REGULATOR PMIC DRIVER");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/krait-regulator-pmic.h b/arch/arm/mach-msm/krait-regulator-pmic.h
new file mode 100644
index 0000000..06ca3ea
--- /dev/null
+++ b/arch/arm/mach-msm/krait-regulator-pmic.h
@@ -0,0 +1,18 @@
+/* Copyright (c) 2013, 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.
+ */
+
+#ifndef __ARCH_ARM_MACH_MSM_KRAIT_REGULATOR_PMIC_H
+#define __ARCH_ARM_MACH_MSM_KRAIT_REGULATOR_PMIC_H
+bool krait_pmic_is_ready(void);
+int krait_pmic_post_pfm_entry(void);
+int krait_pmic_post_pwm_entry(void);
+#endif
diff --git a/arch/arm/mach-msm/krait-regulator.c b/arch/arm/mach-msm/krait-regulator.c
index 9c5f197..4b2259e 100644
--- a/arch/arm/mach-msm/krait-regulator.c
+++ b/arch/arm/mach-msm/krait-regulator.c
@@ -29,7 +29,9 @@
#include <linux/regulator/krait-regulator.h>
#include <linux/debugfs.h>
#include <linux/syscore_ops.h>
+#include <linux/cpu.h>
#include <mach/msm_iomap.h>
+#include "krait-regulator-pmic.h"
#include "spm.h"
#include "pm.h"
@@ -222,8 +224,9 @@
int cpu_num;
int coeff1;
int coeff2;
- bool online;
+ bool reg_en;
int online_at_probe;
+ bool force_bhs;
};
DEFINE_PER_CPU(struct krait_power_vreg *, krait_vregs);
@@ -372,7 +375,7 @@
phase_scaling_factor = pvreg->efuse_phase_scaling_factor;
list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
- if (!kvreg->online)
+ if (!kvreg->reg_en)
continue;
if (kvreg->mode == LDO_MODE) {
@@ -414,7 +417,7 @@
struct krait_power_vreg *kvreg;
list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
- if (kvreg->online)
+ if (kvreg->reg_en)
online_total++;
}
return online_total;
@@ -427,7 +430,7 @@
struct pmic_gang_vreg *pvreg = from->pvreg;
list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
- if (!kvreg->online)
+ if (!kvreg->reg_en)
continue;
load_total += kvreg->load;
}
@@ -474,16 +477,18 @@
}
/* First check if the coeff is low for PFM mode */
- if (load_total <= pvreg->pfm_threshold && n_online == 1) {
+ if (load_total <= pvreg->pfm_threshold
+ && n_online == 1
+ && krait_pmic_is_ready()) {
if (!pvreg->pfm_mode) {
rc = msm_spm_enable_fts_lpm(PMIC_FTS_MODE_PFM);
if (rc) {
pr_err("%s PFM en failed load_t %d rc = %d\n",
from->name, load_total, rc);
return rc;
- } else {
- pvreg->pfm_mode = true;
}
+ krait_pmic_post_pfm_entry();
+ pvreg->pfm_mode = true;
}
return rc;
}
@@ -495,10 +500,10 @@
pr_err("%s PFM exit failed load %d rc = %d\n",
from->name, coeff_total, rc);
return rc;
- } else {
- pvreg->pfm_mode = false;
- udelay(PWM_SETTLING_TIME_US);
}
+ pvreg->pfm_mode = false;
+ krait_pmic_post_pwm_entry();
+ udelay(PWM_SETTLING_TIME_US);
}
/* calculate phases */
@@ -565,7 +570,7 @@
mutex_lock(&pvreg->krait_power_vregs_lock);
kvreg->load = load_uA;
- if (!kvreg->online) {
+ if (!kvreg->reg_en) {
mutex_unlock(&pvreg->krait_power_vregs_lock);
return kvreg->mode;
}
@@ -588,10 +593,10 @@
return kvreg->mode;
}
-static int switch_to_using_hs(struct krait_power_vreg *kvreg)
+static void __switch_to_using_bhs(void *info)
{
- if (kvreg->mode == HS_MODE)
- return 0;
+ struct krait_power_vreg *kvreg = info;
+
/* enable bhs */
if (version > KPSS_VERSION_2P0) {
krait_masked_write(kvreg, APC_PWR_GATE_MODE,
@@ -645,21 +650,18 @@
kvreg->mode = HS_MODE;
pr_debug("%s using BHS\n", kvreg->name);
- return 0;
}
-static int switch_to_using_ldo(struct krait_power_vreg *kvreg)
+static void __switch_to_using_ldo(void *info)
{
- if (kvreg->mode == LDO_MODE
- && get_krait_ldo_uv(kvreg) == kvreg->uV - kvreg->ldo_delta_uV)
- return 0;
+ struct krait_power_vreg *kvreg = info;
/*
* if the krait is in ldo mode and a voltage change is requested on the
* ldo switch to using hs before changing ldo voltage
*/
if (kvreg->mode == LDO_MODE)
- switch_to_using_hs(kvreg);
+ __switch_to_using_bhs(kvreg);
set_krait_ldo_uv(kvreg, kvreg->uV - kvreg->ldo_delta_uV);
if (version > KPSS_VERSION_2P0) {
@@ -698,7 +700,25 @@
kvreg->mode = LDO_MODE;
pr_debug("%s using LDO\n", kvreg->name);
- return 0;
+}
+
+static int switch_to_using_ldo(struct krait_power_vreg *kvreg)
+{
+ if (kvreg->mode == LDO_MODE
+ && get_krait_ldo_uv(kvreg) == kvreg->uV - kvreg->ldo_delta_uV)
+ return 0;
+
+ return smp_call_function_single(kvreg->cpu_num,
+ __switch_to_using_ldo, kvreg, 1);
+}
+
+static int switch_to_using_bhs(struct krait_power_vreg *kvreg)
+{
+ if (kvreg->mode == HS_MODE)
+ return 0;
+
+ return smp_call_function_single(kvreg->cpu_num,
+ __switch_to_using_bhs, kvreg, 1);
}
static int set_pmic_gang_voltage(struct pmic_gang_vreg *pvreg, int uV)
@@ -750,6 +770,41 @@
return rc;
}
+static int configure_ldo_or_hs_one(struct krait_power_vreg *kvreg, int vmax)
+{
+ int rc;
+
+ if (!kvreg->reg_en)
+ return 0;
+
+ if (kvreg->force_bhs)
+ /*
+ * The cpu is in transitory phase where it is being
+ * prepared to be offlined or onlined and is being
+ * forced to run on BHS during that time
+ */
+ return 0;
+
+ if (kvreg->uV <= kvreg->ldo_threshold_uV
+ && kvreg->uV - kvreg->ldo_delta_uV + kvreg->headroom_uV
+ <= vmax) {
+ rc = switch_to_using_ldo(kvreg);
+ if (rc < 0) {
+ pr_err("could not switch %s to ldo rc = %d\n",
+ kvreg->name, rc);
+ return rc;
+ }
+ } else {
+ rc = switch_to_using_bhs(kvreg);
+ if (rc < 0) {
+ pr_err("could not switch %s to hs rc = %d\n",
+ kvreg->name, rc);
+ return rc;
+ }
+ }
+ return 0;
+}
+
static int configure_ldo_or_hs_all(struct krait_power_vreg *from, int vmax)
{
struct pmic_gang_vreg *pvreg = from->pvreg;
@@ -757,27 +812,12 @@
int rc = 0;
list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
- if (!kvreg->online)
- continue;
- if (kvreg->uV <= kvreg->ldo_threshold_uV
- && kvreg->uV - kvreg->ldo_delta_uV + kvreg->headroom_uV
- <= vmax) {
- rc = switch_to_using_ldo(kvreg);
- if (rc < 0) {
- pr_err("could not switch %s to ldo rc = %d\n",
- kvreg->name, rc);
- return rc;
- }
- } else {
- rc = switch_to_using_hs(kvreg);
- if (rc < 0) {
- pr_err("could not switch %s to hs rc = %d\n",
- kvreg->name, rc);
- return rc;
- }
+ rc = configure_ldo_or_hs_one(kvreg, vmax);
+ if (rc) {
+ pr_err("could not switch %s\n", kvreg->name);
+ break;
}
}
-
return rc;
}
@@ -856,7 +896,7 @@
struct krait_power_vreg *kvreg;
list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
- if (!kvreg->online)
+ if (!kvreg->reg_en)
continue;
v = kvreg->uV;
@@ -896,7 +936,7 @@
rc = krait_voltage_decrease(kvreg, vmax);
if (rc < 0) {
- dev_err(&rdev->dev, "%s failed to set %duV from %duV rc = %d\n",
+ pr_err("%s failed to set %duV from %duV rc = %d\n",
kvreg->name, requested_uV, orig_krait_uV, rc);
}
@@ -927,7 +967,7 @@
}
mutex_lock(&pvreg->krait_power_vregs_lock);
- if (!kvreg->online) {
+ if (!kvreg->reg_en) {
kvreg->uV = min_uV;
mutex_unlock(&pvreg->krait_power_vregs_lock);
return 0;
@@ -943,7 +983,7 @@
{
struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
- return kvreg->online;
+ return kvreg->reg_en;
}
static int krait_power_enable(struct regulator_dev *rdev)
@@ -953,8 +993,9 @@
int rc;
mutex_lock(&pvreg->krait_power_vregs_lock);
+ pr_debug("enable %s\n", kvreg->name);
__krait_power_mdd_enable(kvreg, true);
- kvreg->online = true;
+ kvreg->reg_en = true;
rc = _get_optimum_mode(rdev, kvreg->uV, kvreg->uV, kvreg->load);
if (rc < 0)
goto en_err;
@@ -975,7 +1016,8 @@
int rc;
mutex_lock(&pvreg->krait_power_vregs_lock);
- kvreg->online = false;
+ pr_debug("disable %s\n", kvreg->name);
+ kvreg->reg_en = false;
rc = _get_optimum_mode(rdev, kvreg->uV, kvreg->uV, kvreg->load);
if (rc < 0)
@@ -999,6 +1041,69 @@
.is_enabled = krait_power_is_enabled,
};
+static int krait_regulator_cpu_callback(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+{
+ int cpu = (int)hcpu;
+ struct krait_power_vreg *kvreg = per_cpu(krait_vregs, cpu);
+ struct pmic_gang_vreg *pvreg = kvreg->pvreg;
+
+ pr_debug("start state=0x%02x, cpu=%d is_online=%d\n",
+ (int)action, cpu, cpu_online(cpu));
+ switch (action & ~CPU_TASKS_FROZEN) {
+ case CPU_UP_PREPARE:
+ mutex_lock(&pvreg->krait_power_vregs_lock);
+ kvreg->force_bhs = true;
+ /*
+ * cpu is offline at this point, force bhs on which ever cpu
+ * this callback is running on
+ */
+ pr_debug("%s force BHS locally\n", kvreg->name);
+ __switch_to_using_bhs(kvreg);
+ mutex_unlock(&pvreg->krait_power_vregs_lock);
+ break;
+ case CPU_UP_CANCELED:
+ case CPU_ONLINE:
+ mutex_lock(&pvreg->krait_power_vregs_lock);
+ kvreg->force_bhs = false;
+ /*
+ * switch the cpu to proper bhs/ldo, the cpu is online at this
+ * point. The gang voltage and mode votes for the cpu were
+ * submitted in CPU_UP_PREPARE phase
+ */
+ configure_ldo_or_hs_one(kvreg, pvreg->pmic_vmax_uV);
+ mutex_unlock(&pvreg->krait_power_vregs_lock);
+ break;
+ case CPU_DOWN_PREPARE:
+ mutex_lock(&pvreg->krait_power_vregs_lock);
+ kvreg->force_bhs = true;
+ /*
+ * switch the cpu to run on bhs using smp function calls. Note
+ * that the cpu is online at this point.
+ */
+ pr_debug("%s force BHS remotely\n", kvreg->name);
+ switch_to_using_bhs(kvreg);
+ mutex_unlock(&pvreg->krait_power_vregs_lock);
+ break;
+ case CPU_DOWN_FAILED:
+ mutex_lock(&pvreg->krait_power_vregs_lock);
+ kvreg->force_bhs = false;
+ configure_ldo_or_hs_one(kvreg, pvreg->pmic_vmax_uV);
+ mutex_unlock(&pvreg->krait_power_vregs_lock);
+ break;
+ default:
+ break;
+ }
+
+ pr_debug("done state=0x%02x, cpu=%d is_online=%d\n",
+ (int)action, cpu, cpu_online(cpu));
+ return NOTIFY_OK;
+}
+
+static struct notifier_block krait_cpu_notifier = {
+ .notifier_call = krait_regulator_cpu_callback,
+};
+
static struct dentry *dent;
static int get_retention_dbg_uV(void *data, u64 *val)
{
@@ -1481,11 +1586,14 @@
KRAIT_REGULATOR_DRIVER_NAME, rc);
return rc;
}
+
+ register_hotcpu_notifier(&krait_cpu_notifier);
return platform_driver_register(&krait_pdn_driver);
}
static void __exit krait_power_exit(void)
{
+ unregister_hotcpu_notifier(&krait_cpu_notifier);
platform_driver_unregister(&krait_power_driver);
platform_driver_unregister(&krait_pdn_driver);
}
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_id.c b/arch/arm/mach-msm/msm_bus/msm_bus_id.c
index 7e9883f..25a749a 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_id.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_id.c
@@ -35,16 +35,22 @@
if (!fabreg->info[i].gateway) {
fabreg->info[i].priv_id = fabid + fabreg->info[i].id;
if (fabreg->info[i].id < SLAVE_ID_KEY) {
- WARN(fabreg->info[i].id >= MSM_BUS_MASTER_LAST,
- "id %d exceeds array size!\n",
- fabreg->info[i].id);
+ if (fabreg->info[i].id >= MSM_BUS_MASTER_LAST) {
+ WARN(1, "id %d exceeds array size!\n",
+ fabreg->info[i].id);
+ continue;
+ }
+
master_iids[fabreg->info[i].id] =
fabreg->info[i].priv_id;
} else {
- WARN((fabreg->info[i].id - SLAVE_ID_KEY) >=
- (MSM_BUS_SLAVE_LAST - SLAVE_ID_KEY),
- "id %d exceeds array size!\n",
- fabreg->info[i].id);
+ if ((fabreg->info[i].id - SLAVE_ID_KEY) >=
+ (MSM_BUS_SLAVE_LAST - SLAVE_ID_KEY)) {
+ WARN(1, "id %d exceeds array size!\n",
+ fabreg->info[i].id);
+ continue;
+ }
+
slave_iids[fabreg->info[i].id - (SLAVE_ID_KEY)]
= fabreg->info[i].priv_id;
}
diff --git a/arch/arm/mach-msm/msm_cache_dump.c b/arch/arm/mach-msm/msm_cache_dump.c
index 86e8963..a5593bf 100644
--- a/arch/arm/mach-msm/msm_cache_dump.c
+++ b/arch/arm/mach-msm/msm_cache_dump.c
@@ -23,15 +23,16 @@
#include <linux/notifier.h>
#include <linux/of.h>
#include <linux/of_device.h>
+#include <linux/dma-mapping.h>
#include <mach/scm.h>
#include <mach/msm_cache_dump.h>
-#include <mach/memory.h>
#include <mach/msm_iomap.h>
#include <mach/msm_memory_dump.h>
#define L2_DUMP_OFFSET 0x14
-static unsigned long msm_cache_dump_addr;
+static dma_addr_t msm_cache_dump_addr;
+static void *msm_cache_dump_vaddr;
/*
* These should not actually be dereferenced. There's no
@@ -76,7 +77,6 @@
unsigned long buf;
unsigned long size;
} l1_cache_data;
- void *temp;
u32 l1_size, l2_size;
unsigned long total_size;
@@ -102,19 +102,20 @@
};
total_size = l1_size + l2_size;
- msm_cache_dump_addr = allocate_contiguous_ebi_nomap(total_size, SZ_4K);
+ msm_cache_dump_vaddr = (void *) dma_alloc_coherent(&pdev->dev,
+ total_size, &msm_cache_dump_addr,
+ GFP_KERNEL);
- if (!msm_cache_dump_addr) {
+ if (!msm_cache_dump_vaddr) {
pr_err("%s: Could not get memory for cache dumping\n",
__func__);
return -ENOMEM;
}
- temp = ioremap(msm_cache_dump_addr, total_size);
- memset(temp, 0xFF, total_size);
+ memset(msm_cache_dump_vaddr, 0xFF, total_size);
/* Clean caches before sending buffer to TZ */
- clean_caches((unsigned long) temp, total_size, msm_cache_dump_addr);
- iounmap(temp);
+ clean_caches((unsigned long) msm_cache_dump_vaddr, total_size,
+ msm_cache_dump_addr);
l1_cache_data.buf = msm_cache_dump_addr;
l1_cache_data.size = l1_size;
@@ -126,8 +127,9 @@
pr_err("%s: could not register L1 buffer ret = %d.\n",
__func__, ret);
- l1_dump = (struct l1_cache_dump *)msm_cache_dump_addr;
- l2_dump = (struct l2_cache_dump *)(msm_cache_dump_addr + l1_size);
+ l1_dump = (struct l1_cache_dump *)(uint32_t)msm_cache_dump_addr;
+ l2_dump = (struct l2_cache_dump *)(uint32_t)(msm_cache_dump_addr
+ + l1_size);
#if defined(CONFIG_MSM_CACHE_DUMP_ON_PANIC)
l1_cache_data.buf = msm_cache_dump_addr + l1_size;
diff --git a/drivers/char/diag/diag_debugfs.c b/drivers/char/diag/diag_debugfs.c
index a24fc54..aa88b37 100644
--- a/drivers/char/diag/diag_debugfs.c
+++ b/drivers/char/diag/diag_debugfs.c
@@ -350,19 +350,21 @@
bytes_written = scnprintf(buf+bytes_in_buffer, bytes_remaining,
"i: %3d, cmd_code: %4x, subsys_id: %4x, "
"client: %2d, cmd_code_lo: %4x, "
- "cmd_code_hi: %4x, process_id: %5d\n",
+ "cmd_code_hi: %4x, process_id: %5d %s\n",
i,
driver->table[i].cmd_code,
driver->table[i].subsys_id,
driver->table[i].client_id,
driver->table[i].cmd_code_lo,
driver->table[i].cmd_code_hi,
- driver->table[i].process_id);
+ driver->table[i].process_id,
+ (diag_find_polling_reg(i) ? "<- Polling cmd reg" : ""));
bytes_in_buffer += bytes_written;
/* Check if there is room to add another table entry */
bytes_remaining = buf_size - bytes_in_buffer;
+
if (bytes_remaining < bytes_written)
break;
}
diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c
index c91095e..755f0a1 100644
--- a/drivers/char/diag/diag_masks.c
+++ b/drivers/char/diag/diag_masks.c
@@ -19,9 +19,13 @@
#include "diagfwd_cntl.h"
#include "diag_masks.h"
-int diag_event_config;
int diag_event_num_bytes;
+#define DIAG_CTRL_MASK_INVALID 0
+#define DIAG_CTRL_MASK_ALL_DISABLED 1
+#define DIAG_CTRL_MASK_ALL_ENABLED 2
+#define DIAG_CTRL_MASK_VALID 3
+
#define ALL_EQUIP_ID 100
#define ALL_SSID -1
#define MAX_SSID_PER_RANGE 100
@@ -106,6 +110,8 @@
uint8_t *parse_ptr, *ptr = driver->msg_masks;
mutex_lock(&driver->diagchar_mutex);
+ driver->msg_status = rt_mask ? DIAG_CTRL_MASK_ALL_ENABLED :
+ DIAG_CTRL_MASK_ALL_DISABLED;
while (*(uint32_t *)(ptr + 4)) {
first_ssid = *(uint32_t *)ptr;
ptr += 8; /* increment by 8 to skip 'last' */
@@ -131,7 +137,6 @@
uint8_t *ptr_buffer_end = &(*(driver->msg_masks)) + MSG_MASK_SIZE;
mutex_lock(&driver->diagchar_mutex);
-
/* First SSID can be zero : So check that last is non-zero */
while (*(uint32_t *)(ptr + 4)) {
first = *(uint32_t *)ptr;
@@ -177,6 +182,7 @@
} else
pr_alert("diag: Not enough buffer space for MSG_MASK\n");
}
+ driver->msg_status = DIAG_CTRL_MASK_VALID;
mutex_unlock(&driver->diagchar_mutex);
diag_print_mask_table();
}
@@ -186,28 +192,29 @@
uint8_t *ptr = driver->event_masks;
mutex_lock(&driver->diagchar_mutex);
- if (toggle)
+ if (toggle) {
+ driver->event_status = DIAG_CTRL_MASK_ALL_ENABLED;
memset(ptr, 0xFF, EVENT_MASK_SIZE);
- else
+ } else {
+ driver->event_status = DIAG_CTRL_MASK_ALL_DISABLED;
memset(ptr, 0, EVENT_MASK_SIZE);
+ }
mutex_unlock(&driver->diagchar_mutex);
}
-static void diag_update_event_mask(uint8_t *buf, int toggle, int num_bytes)
+static void diag_update_event_mask(uint8_t *buf, int num_bytes)
{
uint8_t *ptr = driver->event_masks;
uint8_t *temp = buf + 2;
mutex_lock(&driver->diagchar_mutex);
- if (!toggle)
- memset(ptr, 0 , EVENT_MASK_SIZE);
- else
- if (CHK_OVERFLOW(ptr, ptr,
- ptr+EVENT_MASK_SIZE, num_bytes))
- memcpy(ptr, temp , num_bytes);
- else
- printk(KERN_CRIT "Not enough buffer space for EVENT_MASK\n");
+ if (CHK_OVERFLOW(ptr, ptr, ptr+EVENT_MASK_SIZE, num_bytes)) {
+ memcpy(ptr, temp, num_bytes);
+ driver->event_status = DIAG_CTRL_MASK_VALID;
+ } else {
+ pr_err("diag: In %s, not enough buffer space\n", __func__);
+ }
mutex_unlock(&driver->diagchar_mutex);
}
@@ -226,6 +233,7 @@
(parse_ptr->num_items + 7)/8);
parse_ptr++;
}
+ driver->log_status = DIAG_CTRL_MASK_ALL_DISABLED;
mutex_unlock(&driver->diagchar_mutex);
}
@@ -282,10 +290,13 @@
}
ptr_data = driver->log_masks + offset;
if (CHK_OVERFLOW(driver->log_masks, ptr_data, driver->log_masks
- + LOG_MASK_SIZE, (num_items+7)/8))
- memcpy(ptr_data, temp , (num_items+7)/8);
- else
+ + LOG_MASK_SIZE, (num_items+7)/8)) {
+ memcpy(ptr_data, temp, (num_items+7)/8);
+ driver->log_status = DIAG_CTRL_MASK_VALID;
+ } else {
pr_err("diag: Not enough buffer space for LOG_MASK\n");
+ driver->log_status = DIAG_CTRL_MASK_INVALID;
+ }
mutex_unlock(&driver->diagchar_mutex);
}
@@ -330,15 +341,36 @@
driver->log_mask->num_items = ptr->num_items;
driver->log_mask->data_len = 11 + size;
driver->log_mask->stream_id = 1; /* 2, if dual stream */
- driver->log_mask->status = 3; /* status for valid mask */
driver->log_mask->equip_id = ptr->equip_id;
- driver->log_mask->log_mask_size = size;
+ driver->log_mask->status = driver->log_status;
+ switch (driver->log_status) {
+ case DIAG_CTRL_MASK_ALL_DISABLED:
+ driver->log_mask->log_mask_size = 0;
+ break;
+ case DIAG_CTRL_MASK_ALL_ENABLED:
+ driver->log_mask->log_mask_size = 0;
+ break;
+ case DIAG_CTRL_MASK_VALID:
+ driver->log_mask->log_mask_size = size;
+ break;
+ default:
+ /* Log status is not set or the buffer is corrupted */
+ pr_err("diag: In %s, invalid status %d", __func__,
+ driver->log_status);
+ driver->log_mask->status = DIAG_CTRL_MASK_INVALID;
+ }
+
+ if (driver->msg_mask->status == DIAG_CTRL_MASK_INVALID) {
+ mutex_unlock(&driver->diag_cntl_mutex);
+ return;
+ }
/* send only desired update, NOT ALL */
if (equip_id == ALL_EQUIP_ID || equip_id ==
driver->log_mask->equip_id) {
memcpy(buf, driver->log_mask, header_size);
- memcpy(buf+header_size, driver->log_masks+ptr->index,
- size);
+ if (driver->log_status == DIAG_CTRL_MASK_VALID)
+ memcpy(buf + header_size,
+ driver->log_masks+ptr->index, size);
if (ch) {
while (retry_count < 3) {
wr_size = smd_write(ch, buf,
@@ -380,11 +412,34 @@
driver->event_mask->cmd_type = DIAG_CTRL_MSG_EVENT_MASK;
driver->event_mask->data_len = 7 + num_bytes;
driver->event_mask->stream_id = 1; /* 2, if dual stream */
- driver->event_mask->status = 3; /* status for valid mask */
- driver->event_mask->event_config = diag_event_config; /* event config */
- driver->event_mask->event_mask_size = num_bytes;
+ driver->event_mask->status = driver->event_status;
+
+ switch (driver->event_status) {
+ case DIAG_CTRL_MASK_ALL_DISABLED:
+ driver->event_mask->event_config = 0;
+ driver->event_mask->event_mask_size = 0;
+ break;
+ case DIAG_CTRL_MASK_ALL_ENABLED:
+ driver->event_mask->event_config = 1;
+ driver->event_mask->event_mask_size = 0;
+ break;
+ case DIAG_CTRL_MASK_VALID:
+ driver->event_mask->event_config = 1;
+ driver->event_mask->event_mask_size = num_bytes;
+ memcpy(buf + header_size, driver->event_masks, num_bytes);
+ break;
+ default:
+ /* Event status is not set yet or the buffer is corrupted */
+ pr_err("diag: In %s, invalid status %d", __func__,
+ driver->event_status);
+ driver->event_mask->status = DIAG_CTRL_MASK_INVALID;
+ }
+
+ if (driver->event_mask->status == DIAG_CTRL_MASK_INVALID) {
+ mutex_unlock(&driver->diag_cntl_mutex);
+ return;
+ }
memcpy(buf, driver->event_mask, header_size);
- memcpy(buf+header_size, driver->event_masks, num_bytes);
if (ch) {
while (retry_count < 3) {
wr_size = smd_write(ch, buf, header_size + num_bytes);
@@ -418,44 +473,68 @@
ptr += 4;
actual_last = *(uint32_t *)ptr;
ptr += 4;
- if ((updated_ssid_first >= first && updated_ssid_last <=
- actual_last) || (updated_ssid_first == ALL_SSID)) {
- /* send f3 mask update */
- driver->msg_mask->cmd_type = DIAG_CTRL_MSG_F3_MASK;
- driver->msg_mask->msg_mask_size = actual_last -
- first + 1;
- driver->msg_mask->data_len = 11 +
- 4 * (driver->msg_mask->msg_mask_size);
- driver->msg_mask->stream_id = 1; /* 2, if dual stream */
- driver->msg_mask->status = 3; /* status valid mask */
- driver->msg_mask->msg_mode = 0; /* Legcay mode */
- driver->msg_mask->ssid_first = first;
- driver->msg_mask->ssid_last = actual_last;
- memcpy(buf, driver->msg_mask, header_size);
+ if (!((updated_ssid_first >= first && updated_ssid_last <=
+ actual_last) || (updated_ssid_first == ALL_SSID))) {
+ ptr += MAX_SSID_PER_RANGE*4;
+ continue;
+ }
+ /* send f3 mask update */
+ driver->msg_mask->cmd_type = DIAG_CTRL_MSG_F3_MASK;
+ driver->msg_mask->status = driver->msg_status;
+ switch (driver->msg_status) {
+ case DIAG_CTRL_MASK_ALL_DISABLED:
+ driver->msg_mask->msg_mask_size = 0;
+ break;
+ case DIAG_CTRL_MASK_ALL_ENABLED:
+ driver->msg_mask->msg_mask_size = 1;
memcpy(buf+header_size, ptr,
4 * (driver->msg_mask->msg_mask_size));
- if (ch) {
- while (retry_count < 3) {
- size = smd_write(ch, buf, header_size +
- 4*(driver->msg_mask->msg_mask_size));
- if (size == -ENOMEM) {
- retry_count++;
- usleep_range(10000, 10100);
- } else
- break;
- }
- if (size != header_size +
- 4*(driver->msg_mask->msg_mask_size))
- pr_err("diag: proc %d, msg mask update fail %d, tried %d\n",
- proc, size, (header_size +
- 4*(driver->msg_mask->msg_mask_size)));
- else
- pr_debug("diag: sending mask update for ssid first %d, last %d on PROC %d\n",
- first, actual_last, proc);
- } else
- pr_err("diag: proc %d, ch invalid msg mask update\n",
- proc);
+ break;
+ case DIAG_CTRL_MASK_VALID:
+ driver->msg_mask->msg_mask_size = actual_last -
+ first + 1;
+ memcpy(buf+header_size, ptr,
+ 4 * (driver->msg_mask->msg_mask_size));
+ break;
+ default:
+ /* Msg status is not set or the buffer is corrupted */
+ pr_err("diag: In %s, invalid status %d", __func__,
+ driver->msg_status);
+ driver->msg_mask->status = DIAG_CTRL_MASK_INVALID;
}
+
+ if (driver->msg_mask->status == DIAG_CTRL_MASK_INVALID) {
+ mutex_unlock(&driver->diag_cntl_mutex);
+ return;
+ }
+ driver->msg_mask->data_len = 11 +
+ 4 * (driver->msg_mask->msg_mask_size);
+ driver->msg_mask->stream_id = 1; /* 2, if dual stream */
+ driver->msg_mask->msg_mode = 0; /* Legcay mode */
+ driver->msg_mask->ssid_first = first;
+ driver->msg_mask->ssid_last = actual_last;
+ memcpy(buf, driver->msg_mask, header_size);
+ if (ch) {
+ while (retry_count < 3) {
+ size = smd_write(ch, buf, header_size +
+ 4*(driver->msg_mask->msg_mask_size));
+ if (size == -ENOMEM) {
+ retry_count++;
+ usleep_range(10000, 10100);
+ } else
+ break;
+ }
+ if (size != header_size +
+ 4*(driver->msg_mask->msg_mask_size))
+ pr_err("diag: proc %d, msg mask update fail %d, tried %d\n",
+ proc, size, (header_size +
+ 4*(driver->msg_mask->msg_mask_size)));
+ else
+ pr_debug("diag: sending mask update for ssid first %d, last %d on PROC %d\n",
+ first, actual_last, proc);
+ } else
+ pr_err("diag: proc %d, ch invalid msg mask update\n",
+ proc);
ptr += MAX_SSID_PER_RANGE*4;
}
mutex_unlock(&driver->diag_cntl_mutex);
@@ -706,8 +785,8 @@
#endif
} else if (*buf == 0x82) { /* event mask change */
buf += 4;
- diag_event_num_bytes = (*(uint16_t *)buf)/8+1;
- diag_update_event_mask(buf, 1, (*(uint16_t *)buf)/8+1);
+ diag_event_num_bytes = (*(uint16_t *)buf)/8+1;
+ diag_update_event_mask(buf, diag_event_num_bytes);
diag_update_userspace_clients(EVENT_MASKS_TYPE);
#if defined(CONFIG_DIAG_OVER_USB)
if (chk_apps_only()) {
@@ -729,7 +808,6 @@
}
#endif
} else if (*buf == 0x60) {
- diag_event_config = *(buf+1);
diag_toggle_event_mask(*(buf+1));
diag_update_userspace_clients(EVENT_MASKS_TYPE);
#if defined(CONFIG_DIAG_OVER_USB)
@@ -764,6 +842,10 @@
void diag_masks_init(void)
{
+ driver->event_status = DIAG_CTRL_MASK_INVALID;
+ driver->msg_status = DIAG_CTRL_MASK_INVALID;
+ driver->log_status = DIAG_CTRL_MASK_INVALID;
+
if (driver->event_mask == NULL) {
driver->event_mask = kzalloc(sizeof(
struct diag_ctrl_event_mask), GFP_KERNEL);
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 7ef1d80..45314d9 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -362,9 +362,12 @@
struct work_struct diag_drain_work;
struct workqueue_struct *diag_cntl_wq;
uint8_t *msg_masks;
+ uint8_t msg_status;
uint8_t *log_masks;
+ uint8_t log_status;
int log_masks_length;
uint8_t *event_masks;
+ uint8_t event_status;
uint8_t log_on_demand_support;
struct diag_master_table *table;
uint8_t *pkt_buf;
@@ -412,5 +415,6 @@
extern uint16_t wrap_count;
void diag_get_timestamp(char *time_str);
+int diag_find_polling_reg(int i);
#endif
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 24d7fac..6cc18da 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -327,17 +327,19 @@
subsys_id = driver->table[i].subsys_id;
cmd_code_lo = driver->table[i].cmd_code_lo;
cmd_code_hi = driver->table[i].cmd_code_hi;
- if (driver->table[i].cmd_code == 0x0C)
- return 1;
- else if (driver->table[i].cmd_code == 0xFF) {
- if (subsys_id == 0x04 && cmd_code_hi == 0x0E &&
- cmd_code_lo == 0x0E)
+
+ if (driver->table[i].cmd_code == 0xFF) {
+ if (subsys_id == 0xFF && cmd_code_hi >= 0x0C &&
+ cmd_code_lo <= 0x0C)
return 1;
- else if (subsys_id == 0x08 && cmd_code_hi == 0x02 &&
- cmd_code_lo == 0x02)
+ if (subsys_id == 0x04 && cmd_code_hi >= 0x0E &&
+ cmd_code_lo <= 0x0E)
return 1;
- else if (subsys_id == 0x32 && cmd_code_hi == 0x03 &&
- cmd_code_lo == 0x03)
+ else if (subsys_id == 0x08 && cmd_code_hi >= 0x02 &&
+ cmd_code_lo <= 0x02)
+ return 1;
+ else if (subsys_id == 0x32 && cmd_code_hi >= 0x03 &&
+ cmd_code_lo <= 0x03)
return 1;
}
return 0;
@@ -356,7 +358,8 @@
}
/* re-scan the registration table */
for (i = 0; i < diag_max_reg; i++) {
- if (diag_find_polling_reg(i) == 1) {
+ if (driver->table[i].process_id != 0 &&
+ diag_find_polling_reg(i) == 1) {
driver->polling_reg_flag = 1;
break;
}
diff --git a/drivers/coresight/coresight-tmc.c b/drivers/coresight/coresight-tmc.c
index c501700..d500c0a 100644
--- a/drivers/coresight/coresight-tmc.c
+++ b/drivers/coresight/coresight-tmc.c
@@ -1451,14 +1451,17 @@
if (!drvdata->byte_cntr_present) {
dev_info(&pdev->dev, "Byte Counter feature absent\n");
- return 0;
+ goto out;
}
drvdata->byte_cntr_irq = platform_get_irq_byname(pdev,
"byte-cntr-irq");
if (drvdata->byte_cntr_irq < 0) {
+ /* Even though this is an error condition, we do not fail
+ * the probe as the byte counter feature is optional
+ */
dev_err(&pdev->dev, "Byte-cntr-irq not specified\n");
- return 0;
+ goto err;
}
ret = devm_request_irq(&pdev->dev, drvdata->byte_cntr_irq,
tmc_etr_byte_cntr_irq,
@@ -1466,7 +1469,7 @@
node_name, drvdata);
if (ret) {
dev_err(&pdev->dev, "Request irq failed\n");
- return ret;
+ goto err;
}
init_waitqueue_head(&drvdata->wq);
node_size += strlen(node_name);
@@ -1477,10 +1480,14 @@
ret = tmc_etr_byte_cntr_dev_register(drvdata);
if (ret) {
dev_err(&pdev->dev, "Byte cntr node not registered\n");
- return ret;
+ goto err;
}
dev_info(&pdev->dev, "Byte Counter feature enabled\n");
return 0;
+err:
+ drvdata->byte_cntr_present = false;
+out:
+ return ret;
}
static void tmc_etr_byte_cntr_exit(struct tmc_drvdata *drvdata)
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 418c488..1f60c65 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -346,6 +346,7 @@
dbs_tuners_ins.sampling_rate = new_rate
= max(new_rate, min_sampling_rate);
+ get_online_cpus();
for_each_online_cpu(cpu) {
struct cpufreq_policy *policy;
struct cpu_dbs_info_s *dbs_info;
@@ -380,6 +381,7 @@
}
mutex_unlock(&dbs_info->timer_mutex);
}
+ put_online_cpus();
}
static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b,
diff --git a/drivers/hwmon/qpnp-adc-common.c b/drivers/hwmon/qpnp-adc-common.c
index 8b0fcf4..9e0be59 100644
--- a/drivers/hwmon/qpnp-adc-common.c
+++ b/drivers/hwmon/qpnp-adc-common.c
@@ -131,57 +131,111 @@
};
static const struct qpnp_vadc_map_pt adcmap_qrd_btm_threshold[] = {
- {-200, 1672},
- {-180, 1656},
- {-160, 1639},
- {-140, 1620},
- {-120, 1599},
- {-100, 1577},
- {-80, 1553},
- {-60, 1527},
- {-40, 1550},
- {-20, 1471},
- {0, 1440},
- {20, 1408},
- {40, 1374},
- {60, 1339},
- {80, 1303},
- {100, 1266},
- {120, 1228},
- {140, 1190},
- {160, 1150},
- {180, 1111},
- {200, 1071},
- {220, 1032},
- {240, 992},
- {260, 953},
- {280, 915},
- {300, 877},
- {320, 841},
- {340, 805},
- {360, 770},
- {380, 736},
- {400, 704},
- {420, 673},
- {440, 643},
- {460, 614},
- {480, 587},
- {500, 561},
- {520, 536},
- {540, 513},
- {560, 491},
- {580, 470},
- {600, 450},
- {620, 431},
- {640, 414},
- {660, 397},
- {680, 382},
- {700, 367},
- {720, 353},
- {740, 340},
- {760, 328},
- {780, 317},
- {800, 306},
+ {-200, 1540},
+ {-180, 1517},
+ {-160, 1492},
+ {-140, 1467},
+ {-120, 1440},
+ {-100, 1412},
+ {-80, 1383},
+ {-60, 1353},
+ {-40, 1323},
+ {-20, 1292},
+ {0, 1260},
+ {20, 1228},
+ {40, 1196},
+ {60, 1163},
+ {80, 1131},
+ {100, 1098},
+ {120, 1066},
+ {140, 1034},
+ {160, 1002},
+ {180, 971},
+ {200, 941},
+ {220, 911},
+ {240, 882},
+ {260, 854},
+ {280, 826},
+ {300, 800},
+ {320, 774},
+ {340, 749},
+ {360, 726},
+ {380, 703},
+ {400, 681},
+ {420, 660},
+ {440, 640},
+ {460, 621},
+ {480, 602},
+ {500, 585},
+ {520, 568},
+ {540, 552},
+ {560, 537},
+ {580, 523},
+ {600, 510},
+ {620, 497},
+ {640, 485},
+ {660, 473},
+ {680, 462},
+ {700, 452},
+ {720, 442},
+ {740, 433},
+ {760, 424},
+ {780, 416},
+ {800, 408},
+};
+
+static const struct qpnp_vadc_map_pt adcmap_qrd_skuaa_btm_threshold[] = {
+ {-200, 1476},
+ {-180, 1450},
+ {-160, 1422},
+ {-140, 1394},
+ {-120, 1365},
+ {-100, 1336},
+ {-80, 1306},
+ {-60, 1276},
+ {-40, 1246},
+ {-20, 1216},
+ {0, 1185},
+ {20, 1155},
+ {40, 1126},
+ {60, 1096},
+ {80, 1068},
+ {100, 1040},
+ {120, 1012},
+ {140, 986},
+ {160, 960},
+ {180, 935},
+ {200, 911},
+ {220, 888},
+ {240, 866},
+ {260, 844},
+ {280, 824},
+ {300, 805},
+ {320, 786},
+ {340, 769},
+ {360, 752},
+ {380, 737},
+ {400, 722},
+ {420, 707},
+ {440, 694},
+ {460, 681},
+ {480, 669},
+ {500, 658},
+ {520, 648},
+ {540, 637},
+ {560, 628},
+ {580, 619},
+ {600, 611},
+ {620, 603},
+ {640, 595},
+ {660, 588},
+ {680, 582},
+ {700, 575},
+ {720, 569},
+ {740, 564},
+ {760, 559},
+ {780, 554},
+ {800, 549},
};
/* Voltage to temperature */
@@ -539,6 +593,25 @@
}
EXPORT_SYMBOL(qpnp_adc_scale_qrd_batt_therm);
+int32_t qpnp_adc_scale_qrd_skuaa_batt_therm(struct qpnp_vadc_chip *chip,
+ int32_t adc_code,
+ const struct qpnp_adc_properties *adc_properties,
+ const struct qpnp_vadc_chan_properties *chan_properties,
+ struct qpnp_vadc_result *adc_chan_result)
+{
+ int64_t bat_voltage = 0;
+
+ bat_voltage = qpnp_adc_scale_ratiometric_calib(adc_code,
+ adc_properties, chan_properties);
+
+ return qpnp_adc_map_temp_voltage(
+ adcmap_qrd_skuaa_btm_threshold,
+ ARRAY_SIZE(adcmap_qrd_skuaa_btm_threshold),
+ bat_voltage,
+ &adc_chan_result->physical);
+}
+EXPORT_SYMBOL(qpnp_adc_scale_qrd_skuaa_batt_therm);
+
int32_t qpnp_adc_scale_therm_pu1(struct qpnp_vadc_chip *chip,
int32_t adc_code,
const struct qpnp_adc_properties *adc_properties,
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index c4a2567..548764f 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -126,6 +126,7 @@
[SCALE_THERM_100K_PULLUP] = {qpnp_adc_scale_therm_pu2},
[SCALE_THERM_150K_PULLUP] = {qpnp_adc_scale_therm_pu1},
[SCALE_QRD_BATT_THERM] = {qpnp_adc_scale_qrd_batt_therm},
+ [SCALE_QRD_SKUAA_BATT_THERM] = {qpnp_adc_scale_qrd_skuaa_batt_therm},
};
static int32_t qpnp_vadc_read_reg(struct qpnp_vadc_chip *vadc, int16_t reg,
diff --git a/drivers/input/misc/mpu3050.c b/drivers/input/misc/mpu3050.c
index ded2b6e..e0d8a47 100644
--- a/drivers/input/misc/mpu3050.c
+++ b/drivers/input/misc/mpu3050.c
@@ -320,15 +320,19 @@
if (sensor->use_poll)
schedule_delayed_work(&sensor->input_work,
msecs_to_jiffies(sensor->poll_interval));
- else
+ else {
i2c_smbus_write_byte_data(sensor->client,
MPU3050_INT_CFG,
MPU3050_ACTIVE_LOW |
MPU3050_OPEN_DRAIN |
MPU3050_RAW_RDY_EN);
+ enable_irq(sensor->client->irq);
+ }
} else {
if (sensor->use_poll)
cancel_delayed_work_sync(&sensor->input_work);
+ else
+ disable_irq(sensor->client->irq);
gpio_set_value(sensor->enable_gpio, 0);
pm_runtime_put(sensor->dev);
}
@@ -448,6 +452,7 @@
mpu3050_config_regulator(client, 1);
udelay(10);
gpio_set_value(sensor->enable_gpio, 1);
+ msleep(60);
}
value = i2c_smbus_read_byte_data(client, MPU3050_PWR_MGM);
@@ -709,7 +714,6 @@
}
mpu3050_set_power_mode(client, 1);
- msleep(10);
ret = i2c_smbus_read_byte_data(client, MPU3050_CHIP_ID_REG);
if (ret < 0) {
@@ -864,6 +868,10 @@
static int mpu3050_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
+ struct mpu3050_sensor *sensor = i2c_get_clientdata(client);
+
+ if (!sensor->use_poll)
+ disable_irq(client->irq);
mpu3050_set_power_mode(client, 0);
@@ -879,9 +887,12 @@
static int mpu3050_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
+ struct mpu3050_sensor *sensor = i2c_get_clientdata(client);
mpu3050_set_power_mode(client, 1);
- msleep(100); /* wait for gyro chip resume */
+
+ if (!sensor->use_poll)
+ enable_irq(client->irq);
return 0;
}
diff --git a/drivers/input/touchscreen/ft5x06_ts.c b/drivers/input/touchscreen/ft5x06_ts.c
index 83b2aa1..6044512 100644
--- a/drivers/input/touchscreen/ft5x06_ts.c
+++ b/drivers/input/touchscreen/ft5x06_ts.c
@@ -41,22 +41,23 @@
#define FT_SUSPEND_LEVEL 1
#endif
-#define CFG_MAX_TOUCH_POINTS 5
+#define FT_DRIVER_VERSION 0x01
-#define FT_STARTUP_DLY 150
-#define FT_RESET_DLY 20
+#define FT_META_REGS 3
+#define FT_ONE_TCH_LEN 6
+#define FT_TCH_LEN(x) (FT_META_REGS + FT_ONE_TCH_LEN * x)
#define FT_PRESS 0x7F
#define FT_MAX_ID 0x0F
-#define FT_TOUCH_STEP 6
#define FT_TOUCH_X_H_POS 3
#define FT_TOUCH_X_L_POS 4
#define FT_TOUCH_Y_H_POS 5
#define FT_TOUCH_Y_L_POS 6
+#define FT_TD_STATUS 2
#define FT_TOUCH_EVENT_POS 3
#define FT_TOUCH_ID_POS 5
-
-#define POINT_READ_BUF (3 + FT_TOUCH_STEP * CFG_MAX_TOUCH_POINTS)
+#define FT_TOUCH_DOWN 0
+#define FT_TOUCH_CONTACT 2
/*register address*/
#define FT_REG_DEV_MODE 0x00
@@ -104,55 +105,6 @@
#define FT_UPGRADE_AA 0xAA
#define FT_UPGRADE_55 0x55
-/*upgrade config of FT5606*/
-#define FT5606_UPGRADE_AA_DELAY 50
-#define FT5606_UPGRADE_55_DELAY 10
-#define FT5606_UPGRADE_ID_1 0x79
-#define FT5606_UPGRADE_ID_2 0x06
-#define FT5606_UPGRADE_READID_DELAY 100
-#define FT5606_UPGRADE_EARSE_DELAY 2000
-
-/*upgrade config of FT5316*/
-#define FT5316_UPGRADE_AA_DELAY 50
-#define FT5316_UPGRADE_55_DELAY 30
-#define FT5316_UPGRADE_ID_1 0x79
-#define FT5316_UPGRADE_ID_2 0x07
-#define FT5316_UPGRADE_READID_DELAY 1
-#define FT5316_UPGRADE_EARSE_DELAY 1500
-
-/*upgrade config of FT5x06(x=2,3,4)*/
-#define FT5X06_UPGRADE_AA_DELAY 50
-#define FT5X06_UPGRADE_55_DELAY 30
-#define FT5X06_UPGRADE_ID_1 0x79
-#define FT5X06_UPGRADE_ID_2 0x03
-#define FT5X06_UPGRADE_READID_DELAY 1
-#define FT5X06_UPGRADE_EARSE_DELAY 2000
-
-/*upgrade config of FT6208*/
-#define FT6208_UPGRADE_AA_DELAY 60
-#define FT6208_UPGRADE_55_DELAY 10
-#define FT6208_UPGRADE_ID_1 0x79
-#define FT6208_UPGRADE_ID_2 0x05
-#define FT6208_UPGRADE_READID_DELAY 10
-#define FT6208_UPGRADE_EARSE_DELAY 2000
-
-/*upgrade config of FT6x06*/
-#define FT6X06_UPGRADE_AA_DELAY 100
-#define FT6X06_UPGRADE_55_DELAY 30
-#define FT6X06_UPGRADE_ID_1 0x79
-#define FT6X06_UPGRADE_ID_2 0x08
-#define FT6X06_UPGRADE_READID_DELAY 10
-#define FT6X06_UPGRADE_EARSE_DELAY 2000
-
-#define FT_UPGRADE_INFO(x, y) do { \
- x->delay_55 = y##_UPGRADE_55_DELAY; \
- x->delay_aa = y##_UPGRADE_AA_DELAY; \
- x->upgrade_id_1 = y##_UPGRADE_ID_1; \
- x->upgrade_id_2 = y##_UPGRADE_ID_2; \
- x->delay_readid = y##_UPGRADE_READID_DELAY; \
- x->delay_earse_flash = y##_UPGRADE_EARSE_DELAY; \
- } while (0)
-
#define FT_FW_MIN_SIZE 8
#define FT_FW_MAX_SIZE 32768
#define FT_FW_FILE_VER(x) ((x)->data[(x)->size - 2])
@@ -180,39 +132,26 @@
#define FT_REG_CAL 0x00
#define FT_CAL_MASK 0x70
-#define FT_INFO_MAX_LEN 200
+#define FT_INFO_MAX_LEN 512
-#define FT_STORE_TS_INFO(buf, id, fw_ver) \
+#define FT_STORE_TS_INFO(buf, id, name, max_tch, group_id, fw_name, fw_ver) \
snprintf(buf, FT_INFO_MAX_LEN, \
"controller\t= focaltech\n" \
"model\t\t= 0x%x\n" \
- "fw_ver\t\t= 0x%x\n", id, fw_ver)
+ "name\t\t= %s\n" \
+ "max_touches\t= %d\n" \
+ "drv_ver\t\t= 0x%x\n" \
+ "group_id\t= 0x%x\n" \
+ "fw_name\t\t= %s\n" \
+ "fw_ver\t\t= 0x%x\n", id, name, \
+ max_tch, FT_DRIVER_VERSION, group_id, \
+ fw_name, fw_ver)
#define FT_DEBUG_DIR_NAME "ts_debug"
-struct ts_event {
- u16 x[CFG_MAX_TOUCH_POINTS]; /*x coordinate */
- u16 y[CFG_MAX_TOUCH_POINTS]; /*y coordinate */
- /* touch event: 0 -- down; 1-- contact; 2 -- contact */
- u8 touch_event[CFG_MAX_TOUCH_POINTS];
- u8 finger_id[CFG_MAX_TOUCH_POINTS]; /*touch ID */
- u16 pressure;
- u8 touch_point;
-};
-
-struct upgrade_info {
- u16 delay_aa; /*delay of write FT_UPGRADE_AA */
- u16 delay_55; /*delay of write FT_UPGRADE_55 */
- u8 upgrade_id_1; /*upgrade id 1 */
- u8 upgrade_id_2; /*upgrade id 2 */
- u16 delay_readid; /*delay of read id */
- u16 delay_earse_flash; /*delay of earse flash*/
-};
-
struct ft5x06_ts_data {
struct i2c_client *client;
struct input_dev *input_dev;
- struct ts_event event;
const struct ft5x06_ts_platform_data *pdata;
struct regulator *vdd;
struct regulator *vcc_i2c;
@@ -223,6 +162,8 @@
u16 addr;
bool suspended;
char *ts_info;
+ u8 *tch_data;
+ u32 tch_data_len;
#if defined(CONFIG_FB)
struct notifier_block fb_notif;
#elif defined(CONFIG_HAS_EARLYSUSPEND)
@@ -305,88 +246,65 @@
return ft5x06_i2c_read(client, &addr, 1, val, 1);
}
-static void ft5x06_report_value(struct ft5x06_ts_data *data)
-{
- struct ts_event *event = &data->event;
- int i;
- int fingerdown = 0;
-
- for (i = 0; i < event->touch_point; i++) {
- if (event->touch_event[i] == 0 || event->touch_event[i] == 2) {
- event->pressure = FT_PRESS;
- fingerdown++;
- } else {
- event->pressure = 0;
- }
-
- input_mt_slot(data->input_dev, event->finger_id[i]);
- input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER,
- !!event->pressure);
-
- if (event->pressure == FT_PRESS) {
- input_report_abs(data->input_dev, ABS_MT_POSITION_X,
- event->x[i]);
- input_report_abs(data->input_dev, ABS_MT_POSITION_Y,
- event->y[i]);
- input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR,
- event->pressure);
- }
- }
-
- input_report_key(data->input_dev, BTN_TOUCH, !!fingerdown);
- input_sync(data->input_dev);
-}
-
-static int ft5x06_handle_touchdata(struct ft5x06_ts_data *data)
-{
- struct ts_event *event = &data->event;
- int num_points;
- int ret, i;
- u8 buf[POINT_READ_BUF] = { 0 };
- u8 pointid = FT_MAX_ID;
-
- ret = ft5x06_i2c_read(data->client, buf, 1, buf, POINT_READ_BUF);
- if (ret < 0) {
- dev_err(&data->client->dev, "%s read touchdata failed.\n",
- __func__);
- return ret;
- }
- memset(event, 0, sizeof(struct ts_event));
-
- event->touch_point = 0;
- num_points = buf[2] & FT_STATUS_NUM_TP_MASK;
-
- for (i = 0; i < num_points; i++) {
- pointid = (buf[FT_TOUCH_ID_POS + FT_TOUCH_STEP * i]) >> 4;
- if (pointid >= FT_MAX_ID)
- break;
- else
- event->touch_point++;
- event->x[i] =
- (s16) (buf[FT_TOUCH_X_H_POS + FT_TOUCH_STEP * i] & 0x0F) <<
- 8 | (s16) buf[FT_TOUCH_X_L_POS + FT_TOUCH_STEP * i];
- event->y[i] =
- (s16) (buf[FT_TOUCH_Y_H_POS + FT_TOUCH_STEP * i] & 0x0F) <<
- 8 | (s16) buf[FT_TOUCH_Y_L_POS + FT_TOUCH_STEP * i];
- event->touch_event[i] =
- buf[FT_TOUCH_EVENT_POS + FT_TOUCH_STEP * i] >> 6;
- event->finger_id[i] =
- (buf[FT_TOUCH_ID_POS + FT_TOUCH_STEP * i]) >> 4;
- }
-
- ft5x06_report_value(data);
-
- return 0;
-}
-
static irqreturn_t ft5x06_ts_interrupt(int irq, void *dev_id)
{
struct ft5x06_ts_data *data = dev_id;
- int rc;
+ struct input_dev *ip_dev;
+ int rc, i;
+ u32 id, x, y, pressure, status, num_touches;
+ u8 reg = 0x00, *buf;
+ bool update_input = false;
- rc = ft5x06_handle_touchdata(data);
- if (rc)
- pr_err("%s: handling touchdata failed\n", __func__);
+ if (!data) {
+ pr_err("%s: Invalid data\n", __func__);
+ return IRQ_HANDLED;
+ }
+
+ ip_dev = data->input_dev;
+ buf = data->tch_data;
+
+ rc = ft5x06_i2c_read(data->client, ®, 1,
+ buf, data->tch_data_len);
+ if (rc < 0) {
+ dev_err(&data->client->dev, "%s: read data fail\n", __func__);
+ return IRQ_HANDLED;
+ }
+
+ for (i = 0; i < data->pdata->num_max_touches; i++) {
+ id = (buf[FT_TOUCH_ID_POS + FT_ONE_TCH_LEN * i]) >> 4;
+ if (id >= FT_MAX_ID)
+ break;
+
+ update_input = true;
+
+ x = (buf[FT_TOUCH_X_H_POS + FT_ONE_TCH_LEN * i] & 0x0F) << 8 |
+ (buf[FT_TOUCH_X_L_POS + FT_ONE_TCH_LEN * i]);
+ y = (buf[FT_TOUCH_Y_H_POS + FT_ONE_TCH_LEN * i] & 0x0F) << 8 |
+ (buf[FT_TOUCH_Y_L_POS + FT_ONE_TCH_LEN * i]);
+
+ status = buf[FT_TOUCH_EVENT_POS + FT_ONE_TCH_LEN * i] >> 6;
+
+ num_touches = buf[FT_TD_STATUS] & FT_STATUS_NUM_TP_MASK;
+
+ /* invalid combination */
+ if (!num_touches && !status && !id)
+ break;
+
+ input_mt_slot(ip_dev, id);
+ if (status == FT_TOUCH_DOWN || status == FT_TOUCH_CONTACT) {
+ pressure = FT_PRESS;
+ input_mt_report_slot_state(ip_dev, MT_TOOL_FINGER, 1);
+ input_report_abs(ip_dev, ABS_MT_POSITION_X, x);
+ input_report_abs(ip_dev, ABS_MT_POSITION_Y, y);
+ input_report_abs(ip_dev, ABS_MT_PRESSURE, pressure);
+ } else
+ input_mt_report_slot_state(ip_dev, MT_TOOL_FINGER, 0);
+ }
+
+ if (update_input) {
+ input_mt_report_pointer_emulation(ip_dev, false);
+ input_sync(ip_dev);
+ }
return IRQ_HANDLED;
}
@@ -519,7 +437,7 @@
disable_irq(data->client->irq);
/* release all touches */
- for (i = 0; i < CFG_MAX_TOUCH_POINTS; i++) {
+ for (i = 0; i < data->pdata->num_max_touches; i++) {
input_mt_slot(data->input_dev, i);
input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER, 0);
}
@@ -553,7 +471,7 @@
pwr_off_fail:
if (gpio_is_valid(data->pdata->reset_gpio)) {
gpio_set_value_cansleep(data->pdata->reset_gpio, 0);
- msleep(FT_RESET_DLY);
+ msleep(data->pdata->hard_rst_dly);
gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
}
enable_irq(data->client->irq);
@@ -566,7 +484,7 @@
int err;
if (!data->suspended) {
- dev_info(dev, "Already in awake state\n");
+ dev_dbg(dev, "Already in awake state\n");
return 0;
}
@@ -586,11 +504,11 @@
if (gpio_is_valid(data->pdata->reset_gpio)) {
gpio_set_value_cansleep(data->pdata->reset_gpio, 0);
- msleep(FT_RESET_DLY);
+ msleep(data->pdata->hard_rst_dly);
gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
}
- msleep(FT_STARTUP_DLY);
+ msleep(data->pdata->soft_rst_dly);
enable_irq(data->client->irq);
@@ -649,16 +567,17 @@
static int ft5x06_auto_cal(struct i2c_client *client)
{
+ struct ft5x06_ts_data *data = i2c_get_clientdata(client);
u8 temp = 0, i;
/* set to factory mode */
- msleep(2 * FT_STARTUP_DLY);
+ msleep(2 * data->pdata->soft_rst_dly);
ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_FACTORYMODE_VALUE);
- msleep(FT_STARTUP_DLY);
+ msleep(data->pdata->soft_rst_dly);
/* start calibration */
ft5x0x_write_reg(client, FT_DEV_MODE_REG_CAL, FT_CAL_START);
- msleep(2 * FT_STARTUP_DLY);
+ msleep(2 * data->pdata->soft_rst_dly);
for (i = 0; i < FT_CAL_RETRY; i++) {
ft5x0x_read_reg(client, FT_REG_CAL, &temp);
/*return to normal mode, calibration finish */
@@ -667,36 +586,17 @@
}
/*calibration OK */
- msleep(2 * FT_STARTUP_DLY);
+ msleep(2 * data->pdata->soft_rst_dly);
ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_FACTORYMODE_VALUE);
- msleep(FT_STARTUP_DLY);
+ msleep(data->pdata->soft_rst_dly);
/* store calibration data */
ft5x0x_write_reg(client, FT_DEV_MODE_REG_CAL, FT_CAL_STORE);
- msleep(2 * FT_STARTUP_DLY);
+ msleep(2 * data->pdata->soft_rst_dly);
/* set to normal mode */
ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_WORKMODE_VALUE);
- msleep(2 * FT_STARTUP_DLY);
-
- return 0;
-}
-
-static int ft5x06_get_upgrade_info(u8 family_id, struct upgrade_info *info)
-{
- switch (family_id) {
- case FT5306I_ID:
- FT_UPGRADE_INFO(info, FT5X06);
- break;
- case FT5316_ID:
- FT_UPGRADE_INFO(info, FT5316);
- break;
- case FT6X06_ID:
- FT_UPGRADE_INFO(info, FT6X06);
- break;
- default:
- return -EINVAL;
- }
+ msleep(2 * data->pdata->soft_rst_dly);
return 0;
}
@@ -705,7 +605,7 @@
const u8 *data, u32 data_len)
{
struct ft5x06_ts_data *ts_data = i2c_get_clientdata(client);
- struct upgrade_info info;
+ struct fw_upgrade_info info = ts_data->pdata->info;
u8 reset_reg;
u8 w_buf[FT_MAX_WR_BUF] = {0}, r_buf[FT_MAX_RD_BUF] = {0};
u8 pkt_buf[FT_FW_PKT_LEN + FT_FW_PKT_META_LEN];
@@ -713,12 +613,6 @@
u32 pkt_num, pkt_len;
u8 fw_ecc;
- rc = ft5x06_get_upgrade_info(ts_data->family_id, &info);
- if (rc < 0) {
- dev_err(&client->dev, "Cannot get upgrade information!\n");
- return -EINVAL;
- }
-
for (i = 0, j = 0; i < FT_UPGRADE_LOOP; i++) {
/* reset - write 0xaa and 0x55 to reset register */
if (ts_data->family_id == FT6X06_ID)
@@ -765,7 +659,7 @@
/* erase app and panel paramenter area */
w_buf[0] = FT_ERASE_APP_REG;
ft5x06_i2c_write(client, w_buf, 1);
- msleep(info.delay_earse_flash);
+ msleep(info.delay_erase_flash);
w_buf[0] = FT_ERASE_PANEL_REG;
ft5x06_i2c_write(client, w_buf, 1);
@@ -840,7 +734,7 @@
/* reset */
w_buf[0] = FT_REG_RESET_FW;
ft5x06_i2c_write(client, w_buf, 1);
- msleep(FT_STARTUP_DLY);
+ msleep(ts_data->pdata->soft_rst_dly);
dev_info(&client->dev, "Firmware upgrade successful\n");
@@ -888,14 +782,16 @@
rc = ft5x06_fw_upgrade_start(data->client, fw->data, fw->size);
if (rc < 0)
dev_err(dev, "update failed (%d)\n", rc);
- else
+ else if (data->pdata->info.auto_cal)
ft5x06_auto_cal(data->client);
} else {
dev_err(dev, "FW format error\n");
rc = -EIO;
}
- FT_STORE_TS_INFO(data->ts_info, data->family_id, FT_FW_FILE_VER(fw));
+ FT_STORE_TS_INFO(data->ts_info, data->family_id, data->pdata->name,
+ data->pdata->num_max_touches, data->pdata->group_id,
+ data->pdata->fw_name, FT_FW_FILE_VER(fw));
rel_fw:
release_firmware(fw);
return rc;
@@ -1177,6 +1073,13 @@
u32 temp_val, num_buttons;
u32 button_map[MAX_BUTTONS];
+ pdata->name = "focaltech";
+ rc = of_property_read_string(np, "focaltech,name", &pdata->name);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read name\n");
+ return rc;
+ }
+
rc = ft5x06_get_dt_coords(dev, "focaltech,panel-coords", pdata);
if (rc && (rc != -EINVAL))
return rc;
@@ -1201,6 +1104,86 @@
if (pdata->irq_gpio < 0)
return pdata->irq_gpio;
+ pdata->fw_name = "ft_fw.bin";
+ rc = of_property_read_string(np, "focaltech,fw-name", &pdata->fw_name);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read fw name\n");
+ return rc;
+ }
+
+ rc = of_property_read_u32(np, "focaltech,group-id", &temp_val);
+ if (!rc)
+ pdata->group_id = temp_val;
+ else
+ return rc;
+
+ rc = of_property_read_u32(np, "focaltech,hard-reset-delay-ms",
+ &temp_val);
+ if (!rc)
+ pdata->hard_rst_dly = temp_val;
+ else
+ return rc;
+
+ rc = of_property_read_u32(np, "focaltech,soft-reset-delay-ms",
+ &temp_val);
+ if (!rc)
+ pdata->soft_rst_dly = temp_val;
+ else
+ return rc;
+
+ rc = of_property_read_u32(np, "focaltech,num-max-touches", &temp_val);
+ if (!rc)
+ pdata->num_max_touches = temp_val;
+ else
+ return rc;
+
+ rc = of_property_read_u32(np, "focaltech,fw-delay-aa-ms", &temp_val);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read fw delay aa\n");
+ return rc;
+ } else if (rc != -EINVAL)
+ pdata->info.delay_aa = temp_val;
+
+ rc = of_property_read_u32(np, "focaltech,fw-delay-55-ms", &temp_val);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read fw delay 55\n");
+ return rc;
+ } else if (rc != -EINVAL)
+ pdata->info.delay_55 = temp_val;
+
+ rc = of_property_read_u32(np, "focaltech,fw-upgrade-id1", &temp_val);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read fw upgrade id1\n");
+ return rc;
+ } else if (rc != -EINVAL)
+ pdata->info.upgrade_id_1 = temp_val;
+
+ rc = of_property_read_u32(np, "focaltech,fw-upgrade-id2", &temp_val);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read fw upgrade id2\n");
+ return rc;
+ } else if (rc != -EINVAL)
+ pdata->info.upgrade_id_2 = temp_val;
+
+ rc = of_property_read_u32(np, "focaltech,fw-delay-readid-ms",
+ &temp_val);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read fw delay read id\n");
+ return rc;
+ } else if (rc != -EINVAL)
+ pdata->info.delay_readid = temp_val;
+
+ rc = of_property_read_u32(np, "focaltech,fw-delay-era-flsh-ms",
+ &temp_val);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read fw delay erase flash\n");
+ return rc;
+ } else if (rc != -EINVAL)
+ pdata->info.delay_erase_flash = temp_val;
+
+ pdata->info.auto_cal = of_property_read_bool(np,
+ "focaltech,fw-auto-cal");
+
rc = of_property_read_u32(np, "focaltech,family-id", &temp_val);
if (!rc)
pdata->family_id = temp_val;
@@ -1241,7 +1224,7 @@
struct dentry *temp;
u8 reg_value;
u8 reg_addr;
- int err;
+ int err, len;
if (client->dev.of_node) {
pdata = devm_kzalloc(&client->dev,
@@ -1252,8 +1235,10 @@
}
err = ft5x06_parse_dt(&client->dev, pdata);
- if (err)
+ if (err) {
+ dev_err(&client->dev, "DT parsing failed\n");
return err;
+ }
} else
pdata = client->dev.platform_data;
@@ -1267,7 +1252,26 @@
return -ENODEV;
}
- data = kzalloc(sizeof(struct ft5x06_ts_data), GFP_KERNEL);
+ data = devm_kzalloc(&client->dev,
+ sizeof(struct ft5x06_ts_data), GFP_KERNEL);
+ if (!data) {
+ dev_err(&client->dev, "Not enough memory\n");
+ return -ENOMEM;
+ }
+
+ if (pdata->fw_name) {
+ len = strlen(pdata->fw_name);
+ if (len > FT_FW_NAME_MAX_LEN - 1) {
+ dev_err(&client->dev, "Invalid firmware name\n");
+ return -EINVAL;
+ }
+
+ strlcpy(data->fw_name, pdata->fw_name, len + 1);
+ }
+
+ data->tch_data_len = FT_TCH_LEN(pdata->num_max_touches);
+ data->tch_data = devm_kzalloc(&client->dev,
+ data->tch_data_len, GFP_KERNEL);
if (!data) {
dev_err(&client->dev, "Not enough memory\n");
return -ENOMEM;
@@ -1275,9 +1279,8 @@
input_dev = input_allocate_device();
if (!input_dev) {
- err = -ENOMEM;
dev_err(&client->dev, "failed to allocate input device\n");
- goto free_mem;
+ return -ENOMEM;
}
data->input_dev = input_dev;
@@ -1296,12 +1299,12 @@
__set_bit(BTN_TOUCH, input_dev->keybit);
__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
- input_mt_init_slots(input_dev, CFG_MAX_TOUCH_POINTS);
+ input_mt_init_slots(input_dev, pdata->num_max_touches);
input_set_abs_params(input_dev, ABS_MT_POSITION_X, pdata->x_min,
pdata->x_max, 0, 0);
input_set_abs_params(input_dev, ABS_MT_POSITION_Y, pdata->y_min,
pdata->y_max, 0, 0);
- input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, FT_PRESS, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, FT_PRESS, 0, 0);
err = input_register_device(input_dev);
if (err) {
@@ -1364,12 +1367,12 @@
"set_direction for reset gpio failed\n");
goto free_reset_gpio;
}
- msleep(FT_RESET_DLY);
+ msleep(data->pdata->hard_rst_dly);
gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
}
/* make sure CTP already finish startup process */
- msleep(FT_STARTUP_DLY);
+ msleep(data->pdata->soft_rst_dly);
/* check the controller id */
reg_addr = FT_REG_ID;
@@ -1453,7 +1456,8 @@
goto free_debug_dir;
}
- data->ts_info = kzalloc(FT_INFO_MAX_LEN, GFP_KERNEL);
+ data->ts_info = devm_kzalloc(&client->dev,
+ FT_INFO_MAX_LEN, GFP_KERNEL);
if (!data->ts_info) {
dev_err(&client->dev, "Not enough memory\n");
goto free_debug_dir;
@@ -1481,7 +1485,9 @@
dev_info(&client->dev, "Firmware version = 0x%x\n", reg_value);
- FT_STORE_TS_INFO(data->ts_info, data->family_id, reg_value);
+ FT_STORE_TS_INFO(data->ts_info, data->family_id, data->pdata->name,
+ data->pdata->num_max_touches, data->pdata->group_id,
+ data->pdata->fw_name, reg_value);
#if defined(CONFIG_FB)
data->fb_notif.notifier_call = fb_notifier_callback;
@@ -1532,8 +1538,6 @@
input_dev = NULL;
free_inputdev:
input_free_device(input_dev);
-free_mem:
- kfree(data);
return err;
}
@@ -1571,8 +1575,6 @@
ft5x06_power_init(data, false);
input_unregister_device(data->input_dev);
- kfree(data->ts_info);
- kfree(data);
return 0;
}
diff --git a/drivers/input/touchscreen/synaptics_i2c_rmi4.c b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
index ba0be2b..0b234ce 100644
--- a/drivers/input/touchscreen/synaptics_i2c_rmi4.c
+++ b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
@@ -1056,6 +1056,10 @@
rmi4_pdata->i2c_pull_up = of_property_read_bool(np,
"synaptics,i2c-pull-up");
+ rmi4_pdata->power_down_enable = of_property_read_bool(np,
+ "synaptics,power-down");
+ rmi4_pdata->disable_gpios = of_property_read_bool(np,
+ "synaptics,disable-gpios");
rmi4_pdata->x_flip = of_property_read_bool(np, "synaptics,x-flip");
rmi4_pdata->y_flip = of_property_read_bool(np, "synaptics,y-flip");
@@ -2003,7 +2007,7 @@
error_reg_en_vcc_i2c:
if (rmi4_data->board->i2c_pull_up)
- reg_set_optimum_mode_check(rmi4_data->vdd, 0);
+ reg_set_optimum_mode_check(rmi4_data->vcc_i2c, 0);
error_reg_opt_i2c:
regulator_disable(rmi4_data->vdd);
error_reg_en_vdd:
@@ -2020,6 +2024,85 @@
return 0;
}
+static int synaptics_rmi4_gpio_configure(struct synaptics_rmi4_data *rmi4_data,
+ bool on)
+{
+ int retval = 0;
+
+ if (on) {
+ if (gpio_is_valid(rmi4_data->board->irq_gpio)) {
+ /* configure touchscreen irq gpio */
+ retval = gpio_request(rmi4_data->board->irq_gpio,
+ "rmi4_irq_gpio");
+ if (retval) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "unable to request gpio [%d]\n",
+ rmi4_data->board->irq_gpio);
+ goto err_irq_gpio_req;
+ }
+ retval = gpio_direction_input(rmi4_data->board->\
+ irq_gpio);
+ if (retval) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "unable to set direction for gpio " \
+ "[%d]\n", rmi4_data->board->irq_gpio);
+ goto err_irq_gpio_dir;
+ }
+ } else {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "irq gpio not provided\n");
+ goto err_irq_gpio_req;
+ }
+
+ if (gpio_is_valid(rmi4_data->board->reset_gpio)) {
+ /* configure touchscreen reset out gpio */
+ retval = gpio_request(rmi4_data->board->reset_gpio,
+ "rmi4_reset_gpio");
+ if (retval) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "unable to request gpio [%d]\n",
+ rmi4_data->board->reset_gpio);
+ goto err_irq_gpio_dir;
+ }
+
+ retval = gpio_direction_output(rmi4_data->board->\
+ reset_gpio, 1);
+ if (retval) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "unable to set direction for gpio " \
+ "[%d]\n", rmi4_data->board->reset_gpio);
+ goto err_reset_gpio_dir;
+ }
+
+ gpio_set_value(rmi4_data->board->reset_gpio, 0);
+ usleep(RMI4_GPIO_SLEEP_LOW_US);
+ gpio_set_value(rmi4_data->board->reset_gpio, 1);
+ msleep(RESET_DELAY);
+ } else
+ synaptics_rmi4_reset_command(rmi4_data);
+
+ return 0;
+ } else {
+ if (rmi4_data->board->disable_gpios) {
+ if (gpio_is_valid(rmi4_data->board->irq_gpio))
+ gpio_free(rmi4_data->board->irq_gpio);
+ if (gpio_is_valid(rmi4_data->board->reset_gpio))
+ gpio_free(rmi4_data->board->reset_gpio);
+ }
+
+ return 0;
+ }
+
+err_reset_gpio_dir:
+ if (gpio_is_valid(rmi4_data->board->reset_gpio))
+ gpio_free(rmi4_data->board->reset_gpio);
+err_irq_gpio_dir:
+ if (gpio_is_valid(rmi4_data->board->irq_gpio))
+ gpio_free(rmi4_data->board->irq_gpio);
+err_irq_gpio_req:
+ return retval;
+}
+
/**
* synaptics_rmi4_probe()
*
@@ -2149,52 +2232,12 @@
goto err_power_device;
}
- if (gpio_is_valid(platform_data->irq_gpio)) {
- /* configure touchscreen irq gpio */
- retval = gpio_request(platform_data->irq_gpio, "rmi4_irq_gpio");
- if (retval) {
- dev_err(&client->dev, "unable to request gpio [%d]\n",
- platform_data->irq_gpio);
- goto err_irq_gpio_req;
- }
- retval = gpio_direction_input(platform_data->irq_gpio);
- if (retval) {
- dev_err(&client->dev,
- "unable to set direction for gpio [%d]\n",
- platform_data->irq_gpio);
- goto err_irq_gpio_dir;
- }
- } else {
- dev_err(&client->dev, "irq gpio not provided\n");
- goto err_irq_gpio_req;
+ retval = synaptics_rmi4_gpio_configure(rmi4_data, true);
+ if (retval < 0) {
+ dev_err(&client->dev, "Failed to configure gpios\n");
+ goto err_gpio_config;
}
- if (gpio_is_valid(platform_data->reset_gpio)) {
- /* configure touchscreen reset out gpio */
- retval = gpio_request(platform_data->reset_gpio,
- "rmi4_reset_gpio");
- if (retval) {
- dev_err(&client->dev, "unable to request gpio [%d]\n",
- platform_data->reset_gpio);
- goto err_irq_gpio_dir;
- }
-
- retval = gpio_direction_output(platform_data->reset_gpio, 1);
- if (retval) {
- dev_err(&client->dev,
- "unable to set direction for gpio [%d]\n",
- platform_data->reset_gpio);
- goto err_reset_gpio_dir;
- }
-
- gpio_set_value(platform_data->reset_gpio, 0);
- usleep(RMI4_GPIO_SLEEP_LOW_US);
- gpio_set_value(platform_data->reset_gpio, 1);
- msleep(RESET_DELAY);
- } else
- synaptics_rmi4_reset_command(rmi4_data);
-
-
init_waitqueue_head(&rmi4_data->wait);
mutex_init(&(rmi4_data->rmi4_io_ctrl_mutex));
@@ -2203,7 +2246,7 @@
dev_err(&client->dev,
"%s: Failed to query device\n",
__func__);
- goto err_reset_gpio_dir;
+ goto err_free_gpios;
}
input_set_abs_params(rmi4_data->input_dev,
@@ -2346,13 +2389,12 @@
kfree(fhandler);
}
}
-err_reset_gpio_dir:
- if (gpio_is_valid(platform_data->reset_gpio))
- gpio_free(platform_data->reset_gpio);
-err_irq_gpio_dir:
- if (gpio_is_valid(platform_data->irq_gpio))
- gpio_free(platform_data->irq_gpio);
-err_irq_gpio_req:
+err_free_gpios:
+ if (gpio_is_valid(rmi4_data->board->reset_gpio))
+ gpio_free(rmi4_data->board->reset_gpio);
+ if (gpio_is_valid(rmi4_data->board->irq_gpio))
+ gpio_free(rmi4_data->board->irq_gpio);
+err_gpio_config:
synaptics_rmi4_power_on(rmi4_data, false);
err_power_device:
synaptics_rmi4_regulator_configure(rmi4_data, false);
@@ -2592,24 +2634,48 @@
bool on)
{
int retval;
+ int load_ua;
if (on == false)
goto regulator_hpm;
- retval = reg_set_optimum_mode_check(rmi4_data->vdd, RMI4_LPM_LOAD_UA);
+ if (rmi4_data->board->i2c_pull_up) {
+ load_ua = rmi4_data->board->power_down_enable ?
+ 0 : RMI4_I2C_LPM_LOAD_UA;
+ retval = reg_set_optimum_mode_check(rmi4_data->vcc_i2c,
+ load_ua);
+ if (retval < 0) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "Regulator vcc_i2c set_opt failed " \
+ "rc=%d\n", retval);
+ goto fail_regulator_lpm;
+ }
+
+ if (rmi4_data->board->power_down_enable) {
+ retval = regulator_disable(rmi4_data->vcc_i2c);
+ if (retval) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "Regulator vcc_i2c disable failed " \
+ "rc=%d\n", retval);
+ goto fail_regulator_lpm;
+ }
+ }
+ }
+
+ load_ua = rmi4_data->board->power_down_enable ? 0 : RMI4_LPM_LOAD_UA;
+ retval = reg_set_optimum_mode_check(rmi4_data->vdd, load_ua);
if (retval < 0) {
dev_err(&rmi4_data->i2c_client->dev,
- "Regulator vcc_ana set_opt failed rc=%d\n",
+ "Regulator vdd_ana set_opt failed rc=%d\n",
retval);
goto fail_regulator_lpm;
}
- if (rmi4_data->board->i2c_pull_up) {
- retval = reg_set_optimum_mode_check(rmi4_data->vcc_i2c,
- RMI4_I2C_LPM_LOAD_UA);
- if (retval < 0) {
+ if (rmi4_data->board->power_down_enable) {
+ retval = regulator_disable(rmi4_data->vdd);
+ if (retval) {
dev_err(&rmi4_data->i2c_client->dev,
- "Regulator vcc_i2c set_opt failed rc=%d\n",
+ "Regulator vdd disable failed rc=%d\n",
retval);
goto fail_regulator_lpm;
}
@@ -2628,6 +2694,16 @@
goto fail_regulator_hpm;
}
+ if (rmi4_data->board->power_down_enable) {
+ retval = regulator_enable(rmi4_data->vdd);
+ if (retval) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "Regulator vdd enable failed rc=%d\n",
+ retval);
+ goto fail_regulator_hpm;
+ }
+ }
+
if (rmi4_data->board->i2c_pull_up) {
retval = reg_set_optimum_mode_check(rmi4_data->vcc_i2c,
RMI4_I2C_LOAD_UA);
@@ -2637,6 +2713,16 @@
retval);
goto fail_regulator_hpm;
}
+
+ if (rmi4_data->board->power_down_enable) {
+ retval = regulator_enable(rmi4_data->vcc_i2c);
+ if (retval) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "Regulator vcc_i2c enable failed " \
+ "rc=%d\n", retval);
+ goto fail_regulator_hpm;
+ }
+ }
}
return 0;
@@ -2650,10 +2736,13 @@
return retval;
fail_regulator_hpm:
- reg_set_optimum_mode_check(rmi4_data->vdd, RMI4_LPM_LOAD_UA);
- if (rmi4_data->board->i2c_pull_up)
- reg_set_optimum_mode_check(rmi4_data->vcc_i2c,
- RMI4_I2C_LPM_LOAD_UA);
+ load_ua = rmi4_data->board->power_down_enable ? 0 : RMI4_LPM_LOAD_UA;
+ reg_set_optimum_mode_check(rmi4_data->vdd, load_ua);
+ if (rmi4_data->board->i2c_pull_up) {
+ load_ua = rmi4_data->board->power_down_enable ?
+ 0 : RMI4_I2C_LPM_LOAD_UA;
+ reg_set_optimum_mode_check(rmi4_data->vcc_i2c, load_ua);
+ }
return retval;
}
@@ -2696,6 +2785,13 @@
return 0;
}
+ if (rmi4_data->board->disable_gpios) {
+ retval = synaptics_rmi4_gpio_configure(rmi4_data, false);
+ if (retval < 0) {
+ dev_err(dev, "failed to put gpios in suspend state\n");
+ return retval;
+ }
+ }
rmi4_data->suspended = true;
return 0;
@@ -2721,6 +2817,14 @@
return 0;
}
+ if (rmi4_data->board->disable_gpios) {
+ retval = synaptics_rmi4_gpio_configure(rmi4_data, true);
+ if (retval < 0) {
+ dev_err(dev, "failed to put gpios in active state\n");
+ return retval;
+ }
+ }
+
retval = synaptics_rmi4_regulator_lpm(rmi4_data, false);
if (retval < 0) {
dev_err(dev, "failed to enter active power mode\n");
@@ -2731,6 +2835,17 @@
rmi4_data->touch_stopped = false;
synaptics_rmi4_irq_enable(rmi4_data, true);
+ if (rmi4_data->board->power_down_enable ||
+ rmi4_data->board->disable_gpios) {
+ retval = synaptics_rmi4_reset_device(rmi4_data);
+ if (retval < 0) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "%s: Failed to issue reset command, " \
+ "rc = %d\n", __func__, retval);
+ return retval;
+ }
+ }
+
rmi4_data->suspended = false;
return 0;
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 fcdf34e..de5a16d 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
@@ -371,7 +371,7 @@
break;
case VIDIOC_MSM_ISP_SET_SRC_STATE:
mutex_lock(&vfe_dev->core_mutex);
- msm_isp_set_src_state(vfe_dev, arg);
+ rc = msm_isp_set_src_state(vfe_dev, arg);
mutex_unlock(&vfe_dev->core_mutex);
break;
case VIDIOC_MSM_ISP_REQUEST_STATS_STREAM:
@@ -415,7 +415,7 @@
if (resource_size(vfe_dev->vfe_mem) <
(reg_cfg_cmd->u.rw_info.reg_offset +
reg_cfg_cmd->u.rw_info.len)) {
- pr_err("%s: Invalid length\n", __func__);
+ pr_err("%s: VFE_WRITE: Invalid length\n", __func__);
return -EINVAL;
}
msm_camera_io_memcpy(vfe_dev->vfe_base +
@@ -427,16 +427,37 @@
case VFE_WRITE_MB: {
uint32_t *data_ptr = cfg_data +
reg_cfg_cmd->u.rw_info.cmd_data_offset/4;
+
+ if ((UINT_MAX - sizeof(*data_ptr) <
+ reg_cfg_cmd->u.rw_info.reg_offset) ||
+ (resource_size(vfe_dev->vfe_mem) <
+ reg_cfg_cmd->u.rw_info.reg_offset +
+ sizeof(*data_ptr))) {
+ pr_err("%s: VFE_WRITE_MB: Invalid length\n", __func__);
+ return -EINVAL;
+ }
msm_camera_io_w_mb(*data_ptr, vfe_dev->vfe_base +
reg_cfg_cmd->u.rw_info.reg_offset);
break;
}
case VFE_CFG_MASK: {
uint32_t temp;
+ if (resource_size(vfe_dev->vfe_mem) <
+ reg_cfg_cmd->u.mask_info.reg_offset)
+ return -EINVAL;
temp = msm_camera_io_r(vfe_dev->vfe_base +
reg_cfg_cmd->u.mask_info.reg_offset);
+
temp &= ~reg_cfg_cmd->u.mask_info.mask;
temp |= reg_cfg_cmd->u.mask_info.val;
+ if ((UINT_MAX - sizeof(temp) <
+ reg_cfg_cmd->u.mask_info.reg_offset) ||
+ (resource_size(vfe_dev->vfe_mem) <
+ reg_cfg_cmd->u.mask_info.reg_offset +
+ sizeof(temp))) {
+ pr_err("%s: VFE_CFG_MASK: Invalid length\n", __func__);
+ return -EINVAL;
+ }
msm_camera_io_w(temp, vfe_dev->vfe_base +
reg_cfg_cmd->u.mask_info.reg_offset);
break;
@@ -448,8 +469,10 @@
uint32_t *hi_tbl_ptr = NULL, *lo_tbl_ptr = NULL;
uint32_t hi_val, lo_val, lo_val1;
if (reg_cfg_cmd->cmd_type == VFE_WRITE_DMI_64BIT) {
- if (reg_cfg_cmd->u.dmi_info.hi_tbl_offset +
- reg_cfg_cmd->u.dmi_info.len > cmd_len) {
+ if ((UINT_MAX - reg_cfg_cmd->u.dmi_info.hi_tbl_offset <
+ reg_cfg_cmd->u.dmi_info.len) ||
+ (reg_cfg_cmd->u.dmi_info.hi_tbl_offset +
+ reg_cfg_cmd->u.dmi_info.len > cmd_len)) {
pr_err("Invalid Hi Table out of bounds\n");
return -EINVAL;
}
@@ -533,6 +556,12 @@
uint32_t *data_ptr = cfg_data +
reg_cfg_cmd->u.rw_info.cmd_data_offset/4;
for (i = 0; i < reg_cfg_cmd->u.rw_info.len/4; i++) {
+ if ((data_ptr < cfg_data) ||
+ (UINT_MAX / sizeof(*data_ptr) <
+ (data_ptr - cfg_data)) ||
+ (sizeof(*data_ptr) * (data_ptr - cfg_data) >
+ cmd_len))
+ return -EINVAL;
*data_ptr++ = msm_camera_io_r(vfe_dev->vfe_base +
reg_cfg_cmd->u.rw_info.reg_offset);
reg_cfg_cmd->u.rw_info.reg_offset += 4;
@@ -553,6 +582,11 @@
struct msm_vfe_reg_cfg_cmd *reg_cfg_cmd;
uint32_t *cfg_data;
+ if (!proc_cmd->num_cfg) {
+ pr_err("%s: Passed num_cfg as 0\n", __func__);
+ return -EINVAL;
+ }
+
reg_cfg_cmd = kzalloc(sizeof(struct msm_vfe_reg_cfg_cmd)*
proc_cmd->num_cfg, GFP_KERNEL);
if (!reg_cfg_cmd) {
@@ -900,11 +934,14 @@
}
}
-void msm_isp_set_src_state(struct vfe_device *vfe_dev, void *arg)
+int msm_isp_set_src_state(struct vfe_device *vfe_dev, void *arg)
{
struct msm_vfe_axi_src_state *src_state = arg;
+ if (src_state->input_src >= VFE_SRC_MAX)
+ return -EINVAL;
vfe_dev->axi_data.src_info[src_state->input_src].active =
src_state->src_active;
+ return 0;
}
int msm_isp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
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 ee901c3..3364306 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
@@ -65,7 +65,7 @@
int msm_isp_get_bit_per_pixel(uint32_t output_format);
enum msm_isp_pack_fmt msm_isp_get_pack_format(uint32_t output_format);
irqreturn_t msm_isp_process_irq(int irq_num, void *data);
-void msm_isp_set_src_state(struct vfe_device *vfe_dev, void *arg);
+int msm_isp_set_src_state(struct vfe_device *vfe_dev, void *arg);
void msm_isp_do_tasklet(unsigned long data);
void msm_isp_update_error_frame_count(struct vfe_device *vfe_dev);
void msm_isp_process_error_info(struct vfe_device *vfe_dev);
diff --git a/drivers/media/platform/msm/camera_v2/sensor/ov8825.c b/drivers/media/platform/msm/camera_v2/sensor/ov8825.c
index 3256c5c..e17c94e 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/ov8825.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/ov8825.c
@@ -21,55 +21,55 @@
.seq_type = SENSOR_VREG,
.seq_val = CAM_VIO,
.config_val = 0,
- .delay = 5,
+ .delay = 1,
},
{
.seq_type = SENSOR_VREG,
.seq_val = CAM_VANA,
.config_val = 0,
- .delay = 5,
+ .delay = 1,
},
{
.seq_type = SENSOR_VREG,
.seq_val = CAM_VDIG,
.config_val = 0,
- .delay = 5,
+ .delay = 1,
},
{
.seq_type = SENSOR_VREG,
.seq_val = CAM_VAF,
.config_val = 0,
- .delay = 15,
+ .delay = 5,
},
{
.seq_type = SENSOR_GPIO,
.seq_val = SENSOR_GPIO_STANDBY,
.config_val = GPIO_OUT_LOW,
- .delay = 15,
+ .delay = 1,
},
{
.seq_type = SENSOR_GPIO,
.seq_val = SENSOR_GPIO_RESET,
.config_val = GPIO_OUT_LOW,
- .delay = 40,
+ .delay = 5,
},
{
.seq_type = SENSOR_GPIO,
.seq_val = SENSOR_GPIO_STANDBY,
.config_val = GPIO_OUT_HIGH,
- .delay = 40,
+ .delay = 5,
},
{
.seq_type = SENSOR_GPIO,
.seq_val = SENSOR_GPIO_RESET,
.config_val = GPIO_OUT_HIGH,
- .delay = 40,
+ .delay = 10,
},
{
.seq_type = SENSOR_CLK,
.seq_val = SENSOR_CAM_MCLK,
.config_val = 24000000,
- .delay = 5,
+ .delay = 10,
},
{
.seq_type = SENSOR_I2C_MUX,
diff --git a/drivers/media/platform/msm/camera_v2/sensor/ov9724.c b/drivers/media/platform/msm/camera_v2/sensor/ov9724.c
index 56af02b..99bf03a 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/ov9724.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/ov9724.c
@@ -46,7 +46,7 @@
.seq_type = SENSOR_GPIO,
.seq_val = SENSOR_GPIO_RESET,
.config_val = GPIO_OUT_HIGH,
- .delay = 30,
+ .delay = 5,
},
{
.seq_type = SENSOR_GPIO,
@@ -58,13 +58,13 @@
.seq_type = SENSOR_GPIO,
.seq_val = SENSOR_GPIO_STANDBY,
.config_val = GPIO_OUT_HIGH,
- .delay = 30,
+ .delay = 10,
},
{
.seq_type = SENSOR_CLK,
.seq_val = SENSOR_CAM_MCLK,
.config_val = 24000000,
- .delay = 5,
+ .delay = 10,
},
{
.seq_type = SENSOR_I2C_MUX,
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index f94b6f1..36a2658 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -2436,6 +2436,7 @@
lock = &inst->bufq[CAPTURE_PORT].lock;
else
lock = &inst->bufq[OUTPUT_PORT].lock;
+ temp->vb->v4l2_planes[0].bytesused = 0;
mutex_lock(lock);
vb2_buffer_done(temp->vb, VB2_BUF_STATE_DONE);
mutex_unlock(lock);
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index 249f54d..494242d 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -201,7 +201,7 @@
HAL_VIDEO_CODEC_VP6 = 0x00000400,
HAL_VIDEO_CODEC_VP7 = 0x00000800,
HAL_VIDEO_CODEC_VP8 = 0x00001000,
- HAL_VIDEO_CODEC_HEVC = 0x00010000,
+ HAL_VIDEO_CODEC_HEVC = 0x00002000,
HAL_UNUSED_CODEC = 0x10000000,
};
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
index 3f63357..61c6e15 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
@@ -79,7 +79,7 @@
#define HFI_VIDEO_CODEC_VC1 0x00000100
#define HFI_VIDEO_CODEC_SPARK 0x00000200
#define HFI_VIDEO_CODEC_VP8 0x00001000
-#define HFI_VIDEO_CODEC_HEVC 0x00010000
+#define HFI_VIDEO_CODEC_HEVC 0x00002000
#define HFI_H264_PROFILE_BASELINE 0x00000001
#define HFI_H264_PROFILE_MAIN 0x00000002
diff --git a/drivers/mfd/wcd9xxx-core.c b/drivers/mfd/wcd9xxx-core.c
index 1eebe61..9c35a55 100644
--- a/drivers/mfd/wcd9xxx-core.c
+++ b/drivers/mfd/wcd9xxx-core.c
@@ -1195,15 +1195,54 @@
return 0;
}
+static int wcd9xxx_process_supplies(struct device *dev,
+ struct wcd9xxx_pdata *pdata, const char *supply_list,
+ int supply_cnt, bool is_ondemand, int index)
+{
+ int idx, ret = 0;
+ const char *name;
+
+ if (supply_cnt == 0) {
+ dev_dbg(dev, "%s: no supplies defined for %s\n", __func__,
+ supply_list);
+ return 0;
+ }
+
+ for (idx = 0; idx < supply_cnt; idx++) {
+ ret = of_property_read_string_index(dev->of_node,
+ supply_list, idx,
+ &name);
+ if (ret) {
+ dev_err(dev, "%s: of read string %s idx %d error %d\n",
+ __func__, supply_list, idx, ret);
+ goto err;
+ }
+
+ dev_dbg(dev, "%s: Found cdc supply %s as part of %s\n",
+ __func__, name, supply_list);
+ ret = wcd9xxx_dt_parse_vreg_info(dev,
+ &pdata->regulator[index + idx],
+ name, is_ondemand);
+ if (ret)
+ goto err;
+ }
+
+ return 0;
+
+err:
+ return ret;
+
+}
+
static struct wcd9xxx_pdata *wcd9xxx_populate_dt_pdata(struct device *dev)
{
struct wcd9xxx_pdata *pdata;
- int ret, static_cnt, ond_cnt, idx, i;
- const char *name = NULL;
+ int ret, static_cnt, ond_cnt, cp_supplies_cnt;
u32 mclk_rate = 0;
u32 dmic_sample_rate = 0;
const char *static_prop_name = "qcom,cdc-static-supplies";
const char *ond_prop_name = "qcom,cdc-on-demand-supplies";
+ const char *cp_supplies_name = "qcom,cdc-cp-supplies";
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
@@ -1223,44 +1262,34 @@
if (IS_ERR_VALUE(ond_cnt))
ond_cnt = 0;
- BUG_ON(static_cnt <= 0 || ond_cnt < 0);
- if ((static_cnt + ond_cnt) > ARRAY_SIZE(pdata->regulator)) {
+ /* cp-supplies list is an optional property */
+ cp_supplies_cnt = of_property_count_strings(dev->of_node,
+ cp_supplies_name);
+ if (IS_ERR_VALUE(cp_supplies_cnt))
+ cp_supplies_cnt = 0;
+
+ BUG_ON(static_cnt <= 0 || ond_cnt < 0 || cp_supplies_cnt < 0);
+ if ((static_cnt + ond_cnt + cp_supplies_cnt)
+ > ARRAY_SIZE(pdata->regulator)) {
dev_err(dev, "%s: Num of supplies %u > max supported %u\n",
__func__, static_cnt, ARRAY_SIZE(pdata->regulator));
goto err;
}
- for (idx = 0; idx < static_cnt; idx++) {
- ret = of_property_read_string_index(dev->of_node,
- static_prop_name, idx,
- &name);
- if (ret) {
- dev_err(dev, "%s: of read string %s idx %d error %d\n",
- __func__, static_prop_name, idx, ret);
- goto err;
- }
+ ret = wcd9xxx_process_supplies(dev, pdata, static_prop_name,
+ static_cnt, false, 0);
+ if (ret)
+ goto err;
- dev_dbg(dev, "%s: Found static cdc supply %s\n", __func__,
- name);
- ret = wcd9xxx_dt_parse_vreg_info(dev, &pdata->regulator[idx],
- name, false);
- if (ret)
- goto err;
- }
+ ret = wcd9xxx_process_supplies(dev, pdata, ond_prop_name,
+ ond_cnt, true, static_cnt);
+ if (ret)
+ goto err;
- for (i = 0; i < ond_cnt; i++, idx++) {
- ret = of_property_read_string_index(dev->of_node, ond_prop_name,
- i, &name);
- if (ret)
- goto err;
-
- dev_dbg(dev, "%s: Found on-demand cdc supply %s\n", __func__,
- name);
- ret = wcd9xxx_dt_parse_vreg_info(dev, &pdata->regulator[idx],
- name, true);
- if (ret)
- goto err;
- }
+ ret = wcd9xxx_process_supplies(dev, pdata, cp_supplies_name,
+ cp_supplies_cnt, false, static_cnt + ond_cnt);
+ if (ret)
+ goto err;
ret = wcd9xxx_dt_parse_micbias_info(dev, &pdata->micbias);
if (ret)
diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c
index 2f19863..205bf37 100644
--- a/drivers/slimbus/slim-msm-ngd.c
+++ b/drivers/slimbus/slim-msm-ngd.c
@@ -226,6 +226,8 @@
u8 *puc;
int ret = 0;
u8 la = txn->la;
+ u8 txn_mt;
+ u16 txn_mc = txn->mc;
u8 wbuf[SLIM_MSGQ_BUF_LEN];
if (!pm_runtime_enabled(dev->dev) && dev->state == MSM_CTRL_ASLEEP &&
@@ -402,6 +404,14 @@
puc[1] += dev->port_b;
}
dev->err = 0;
+ /*
+ * If it's a read txn, it may be freed if a response is received by
+ * received thread before reaching end of this function.
+ * mc, mt may have changed to convert standard slimbus code/type to
+ * satellite user-defined message. Reinitialize again
+ */
+ txn_mc = txn->mc;
+ txn_mt = txn->mt;
dev->wr_comp = &tx_sent;
ret = msm_send_msg_buf(dev, pbuf, txn->rl,
NGD_BASE(dev->ctrl.nr, dev->ver) + NGD_TX_MSG);
@@ -427,7 +437,7 @@
void __iomem *ngd = dev->base + NGD_BASE(dev->ctrl.nr,
dev->ver);
dev_err(dev->dev, "TX failed :MC:0x%x,mt:0x%x, ret:%d, ver:%d",
- txn->mc, txn->mt, ret, dev->ver);
+ txn_mc, txn_mt, ret, dev->ver);
conf = readl_relaxed(ngd);
stat = readl_relaxed(ngd + NGD_STATUS);
rx_msgq = readl_relaxed(ngd + NGD_RX_MSGQ_CFG);
@@ -438,10 +448,10 @@
pr_err("conf:0x%x,stat:0x%x,rxmsgq:0x%x", conf, stat, rx_msgq);
pr_err("int_stat:0x%x,int_en:0x%x,int_cll:0x%x", int_stat,
int_en, int_clr);
- } else if (txn->mt == SLIM_MSG_MT_DEST_REFERRED_USER &&
- (txn->mc == SLIM_USR_MC_CONNECT_SRC ||
- txn->mc == SLIM_USR_MC_CONNECT_SINK ||
- txn->mc == SLIM_USR_MC_DISCONNECT_PORT)) {
+ } else if (txn_mt == SLIM_MSG_MT_DEST_REFERRED_USER &&
+ (txn_mc == SLIM_USR_MC_CONNECT_SRC ||
+ txn_mc == SLIM_USR_MC_CONNECT_SINK ||
+ txn_mc == SLIM_USR_MC_DISCONNECT_PORT)) {
int timeout;
mutex_unlock(&dev->tx_lock);
msm_slim_put_ctrl(dev);
@@ -461,7 +471,7 @@
}
ngd_xfer_err:
mutex_unlock(&dev->tx_lock);
- if (txn->mc != SLIM_USR_MC_REPORT_SATELLITE)
+ if (txn_mc != SLIM_USR_MC_REPORT_SATELLITE)
msm_slim_put_ctrl(dev);
return ret ? ret : dev->err;
}
diff --git a/drivers/thermal/msm8974-tsens.c b/drivers/thermal/msm8974-tsens.c
index 69031dc..fcc5a8d 100644
--- a/drivers/thermal/msm8974-tsens.c
+++ b/drivers/thermal/msm8974-tsens.c
@@ -664,6 +664,15 @@
lower_thr = true;
}
if (upper_thr || lower_thr) {
+ unsigned long temp;
+ enum thermal_trip_type trip =
+ THERMAL_TRIP_CONFIGURABLE_LOW;
+
+ if (upper_thr)
+ trip = THERMAL_TRIP_CONFIGURABLE_HI;
+ tsens_tz_get_temp(tm->sensor[i].tz_dev, &temp);
+ thermal_sensor_trip(tm->sensor[i].tz_dev, trip, temp);
+
/* Notify user space */
queue_work(tm->tsens_wq, &tm->sensor[i].work);
rc = tsens_get_sw_id_mapping(
diff --git a/drivers/thermal/msm_thermal.c b/drivers/thermal/msm_thermal.c
index 974cadc..00df613 100644
--- a/drivers/thermal/msm_thermal.c
+++ b/drivers/thermal/msm_thermal.c
@@ -14,9 +14,11 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
+#include <linux/kthread.h>
#include <linux/mutex.h>
#include <linux/msm_tsens.h>
#include <linux/workqueue.h>
+#include <linux/completion.h>
#include <linux/cpu.h>
#include <linux/cpufreq.h>
#include <linux/msm_tsens.h>
@@ -29,6 +31,7 @@
#include <linux/sysfs.h>
#include <linux/types.h>
#include <linux/android_alarm.h>
+#include <linux/thermal.h>
#include <mach/cpufreq.h>
#include <mach/rpm-regulator.h>
#include <mach/rpm-regulator-smd.h>
@@ -45,7 +48,10 @@
static uint32_t wakeup_ms;
static struct alarm thermal_rtc;
static struct kobject *tt_kobj;
+static struct kobject *cc_kobj;
static struct work_struct timer_work;
+static struct task_struct *hotplug_task;
+static struct completion hotplug_notify_complete;
static int enabled;
static int rails_cnt;
@@ -67,6 +73,14 @@
static DEFINE_MUTEX(vdd_rstr_mutex);
static DEFINE_MUTEX(psm_mutex);
+struct cpu_info {
+ uint32_t cpu;
+ bool offline;
+ bool user_offline;
+ const char *sensor_type;
+ struct sensor_threshold thresh[2];
+};
+
struct rail {
const char *name;
uint32_t freq_req;
@@ -91,6 +105,7 @@
static struct psm_rail *psm_rails;
static struct rail *rails;
+static struct cpu_info cpus[NR_CPUS];
struct vdd_rstr_enable {
struct kobj_attribute ko_attr;
@@ -658,11 +673,67 @@
}
mutex_unlock(&core_control_mutex);
}
+/* Call with core_control_mutex locked */
+static int __ref update_offline_cores(int val)
+{
+ int cpu = 0;
+ int ret = 0;
+
+ if (!core_control_enabled)
+ return 0;
+
+ cpus_offlined = msm_thermal_info.core_control_mask & val;
+
+ for_each_possible_cpu(cpu) {
+ if (!(cpus_offlined & BIT(cpu)))
+ continue;
+ if (!cpu_online(cpu))
+ continue;
+ ret = cpu_down(cpu);
+ if (ret)
+ pr_err("%s: Unable to offline cpu%d\n",
+ KBUILD_MODNAME, cpu);
+ }
+ return ret;
+}
+
+static __ref int do_hotplug(void *data)
+{
+ int ret = 0;
+ int cpu = 0;
+ uint32_t mask = 0;
+
+ if (!core_control_enabled)
+ return -EINVAL;
+
+ while (!kthread_should_stop()) {
+ wait_for_completion(&hotplug_notify_complete);
+ INIT_COMPLETION(hotplug_notify_complete);
+ mask = 0;
+
+ mutex_lock(&core_control_mutex);
+ for_each_possible_cpu(cpu) {
+ if (cpus[cpu].offline || cpus[cpu].user_offline)
+ mask |= BIT(cpu);
+ }
+ if (mask != cpus_offlined)
+ update_offline_cores(mask);
+ mutex_unlock(&core_control_mutex);
+ sysfs_notify(cc_kobj, NULL, "cpus_offlined");
+ }
+
+ return ret;
+}
#else
static void do_core_control(long temp)
{
return;
}
+
+static __ref int do_hotplug(void *data)
+{
+ return 0;
+}
#endif
static int do_vdd_restriction(void)
@@ -848,7 +919,7 @@
if (core_control_enabled &&
(msm_thermal_info.core_control_mask & BIT(cpu)) &&
(cpus_offlined & BIT(cpu))) {
- pr_info(
+ pr_debug(
"%s: Preventing cpu%d from coming online.\n",
KBUILD_MODNAME, cpu);
return NOTIFY_BAD;
@@ -896,6 +967,112 @@
ts.tv_sec, ts.tv_usec);
}
+static int hotplug_notify(enum thermal_trip_type type, int temp, void *data)
+{
+ struct cpu_info *cpu_node = (struct cpu_info *)data;
+
+ pr_info("%s: %s reach temp threshold: %d\n", KBUILD_MODNAME,
+ cpu_node->sensor_type, temp);
+
+ if (!(msm_thermal_info.core_control_mask & BIT(cpu_node->cpu)))
+ return 0;
+ switch (type) {
+ case THERMAL_TRIP_CONFIGURABLE_HI:
+ if (!(cpu_node->offline))
+ cpu_node->offline = 1;
+ break;
+ case THERMAL_TRIP_CONFIGURABLE_LOW:
+ if (cpu_node->offline)
+ cpu_node->offline = 0;
+ break;
+ default:
+ break;
+ }
+ if (hotplug_task)
+ complete(&hotplug_notify_complete);
+ else
+ pr_err("%s: Hotplug task is not initialized\n", KBUILD_MODNAME);
+ return 0;
+}
+/* Adjust cpus offlined bit based on temperature reading. */
+static int hotplug_init_cpu_offlined(void)
+{
+ struct tsens_device tsens_dev;
+ long temp = 0;
+ int cpu = 0;
+
+ mutex_lock(&core_control_mutex);
+ for_each_possible_cpu(cpu) {
+ if (!(msm_thermal_info.core_control_mask & BIT(cpus[cpu].cpu)))
+ continue;
+ tsens_dev.sensor_num = sensor_get_id(\
+ (char *)cpus[cpu].sensor_type);
+ if (tsens_get_temp(&tsens_dev, &temp)) {
+ pr_err("%s: Unable to read TSENS sensor %d\n",
+ KBUILD_MODNAME, tsens_dev.sensor_num);
+ return -EINVAL;
+ }
+
+ if (temp >= msm_thermal_info.hotplug_temp_degC)
+ cpus[cpu].offline = 1;
+ else if (temp <= (msm_thermal_info.hotplug_temp_degC -
+ msm_thermal_info.hotplug_temp_hysteresis_degC))
+ cpus[cpu].offline = 0;
+ }
+ mutex_unlock(&core_control_mutex);
+
+ if (hotplug_task)
+ complete(&hotplug_notify_complete);
+ else {
+ pr_err("%s: Hotplug task is not initialized\n",
+ KBUILD_MODNAME);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static void hotplug_init(void)
+{
+ int cpu = 0;
+
+ if (hotplug_task)
+ return;
+
+ for_each_possible_cpu(cpu) {
+ if (!(msm_thermal_info.core_control_mask & BIT(cpus[cpu].cpu)))
+ continue;
+ cpus[cpu].cpu = (uint32_t)cpu;
+ cpus[cpu].thresh[0].temp = msm_thermal_info.hotplug_temp_degC;
+ cpus[cpu].thresh[0].trip = THERMAL_TRIP_CONFIGURABLE_HI;
+ cpus[cpu].thresh[0].notify = hotplug_notify;
+ cpus[cpu].thresh[0].data = (void *)&cpus[cpu];
+ sensor_set_trip(sensor_get_id((char *)cpus[cpu].sensor_type),
+ &cpus[cpu].thresh[0]);
+
+ cpus[cpu].thresh[1].temp = msm_thermal_info.hotplug_temp_degC -
+ msm_thermal_info.hotplug_temp_hysteresis_degC;
+ cpus[cpu].thresh[1].trip = THERMAL_TRIP_CONFIGURABLE_LOW;
+ cpus[cpu].thresh[1].notify = hotplug_notify;
+ cpus[cpu].thresh[1].data = (void *)&cpus[cpu];
+ sensor_set_trip(sensor_get_id((char *)cpus[cpu].sensor_type),
+ &cpus[cpu].thresh[1]);
+
+ }
+ init_completion(&hotplug_notify_complete);
+ hotplug_task = kthread_run(do_hotplug, NULL, "msm_thermal:hotplug");
+ if (IS_ERR(hotplug_task)) {
+ pr_err("%s: Failed to create do_hotplug thread\n",
+ KBUILD_MODNAME);
+ return;
+ }
+ /*
+ * Adjust cpus offlined bit when hotplug intitializes so that the new
+ * cpus offlined state is based on hotplug threshold range
+ */
+ if (hotplug_init_cpu_offlined())
+ kthread_stop(hotplug_task);
+}
+
/*
* We will reset the cpu frequencies limits here. The core online/offline
* status will be carried over to the process stopping the msm_thermal, as
@@ -922,9 +1099,10 @@
int ret = 0;
ret = param_set_bool(val, kp);
- if (!enabled)
+ if (!enabled) {
disable_msm_thermal();
- else
+ hotplug_init();
+ } else
pr_info("%s: no action for enabled = %d\n",
KBUILD_MODNAME, enabled);
@@ -941,37 +1119,6 @@
module_param_cb(enabled, &module_ops, &enabled, 0644);
MODULE_PARM_DESC(enabled, "enforce thermal limit on cpu");
-
-#ifdef CONFIG_SMP
-/* Call with core_control_mutex locked */
-static int __ref update_offline_cores(int val)
-{
- int cpu = 0;
- int ret = 0;
-
- cpus_offlined = msm_thermal_info.core_control_mask & val;
- if (!core_control_enabled)
- return 0;
-
- for_each_possible_cpu(cpu) {
- if (!(cpus_offlined & BIT(cpu)))
- continue;
- if (!cpu_online(cpu))
- continue;
- ret = cpu_down(cpu);
- if (ret)
- pr_err("%s: Unable to offline cpu%d\n",
- KBUILD_MODNAME, cpu);
- }
- return ret;
-}
-#else
-static int update_offline_cores(int val)
-{
- return 0;
-}
-#endif
-
static ssize_t show_cc_enabled(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
@@ -984,7 +1131,6 @@
int ret = 0;
int val = 0;
- mutex_lock(&core_control_mutex);
ret = kstrtoint(buf, 10, &val);
if (ret) {
pr_err("%s: Invalid input %s\n", KBUILD_MODNAME, buf);
@@ -998,14 +1144,17 @@
if (core_control_enabled) {
pr_info("%s: Core control enabled\n", KBUILD_MODNAME);
register_cpu_notifier(&msm_thermal_cpu_notifier);
- update_offline_cores(cpus_offlined);
+ if (hotplug_task)
+ complete(&hotplug_notify_complete);
+ else
+ pr_err("%s: Hotplug task is not initialized\n",
+ KBUILD_MODNAME);
} else {
pr_info("%s: Core control disabled\n", KBUILD_MODNAME);
unregister_cpu_notifier(&msm_thermal_cpu_notifier);
}
done_store_cc:
- mutex_unlock(&core_control_mutex);
return count;
}
@@ -1020,6 +1169,7 @@
{
int ret = 0;
uint32_t val = 0;
+ int cpu;
mutex_lock(&core_control_mutex);
ret = kstrtouint(buf, 10, &val);
@@ -1034,10 +1184,16 @@
goto done_cc;
}
- if (cpus_offlined == val)
- goto done_cc;
+ for_each_possible_cpu(cpu) {
+ if (!(msm_thermal_info.core_control_mask & BIT(cpu)))
+ continue;
+ cpus[cpu].user_offline = !!(val & BIT(cpu));
+ }
- update_offline_cores(val);
+ if (hotplug_task)
+ complete(&hotplug_notify_complete);
+ else
+ pr_err("%s: Hotplug task is not initialized\n", KBUILD_MODNAME);
done_cc:
mutex_unlock(&core_control_mutex);
return count;
@@ -1108,7 +1264,6 @@
static __init int msm_thermal_add_cc_nodes(void)
{
struct kobject *module_kobj = NULL;
- struct kobject *cc_kobj = NULL;
int ret = 0;
module_kobj = kset_find_obj(module_kset, KBUILD_MODNAME);
@@ -1190,8 +1345,7 @@
return -EINVAL;
enabled = 1;
- if (num_possible_cpus() > 1)
- core_control_enabled = 1;
+
INIT_DELAYED_WORK(&check_temp_work, check_temp);
schedule_delayed_work(&check_temp_work, 0);
@@ -1602,12 +1756,76 @@
return ret;
}
+static int probe_cc(struct device_node *node, struct msm_thermal_data *data,
+ struct platform_device *pdev)
+{
+ char *key = NULL;
+ int cpu_cnt = 0;
+ int ret = 0;
+ int cpu = 0;
+
+ key = "qcom,core-limit-temp";
+ ret = of_property_read_u32(node, key, &data->core_limit_temp_degC);
+ if (ret)
+ goto read_node_fail;
+
+ key = "qcom,core-temp-hysteresis";
+ ret = of_property_read_u32(node, key, &data->core_temp_hysteresis_degC);
+ if (ret)
+ goto read_node_fail;
+
+ key = "qcom,core-control-mask";
+ ret = of_property_read_u32(node, key, &data->core_control_mask);
+ if (ret)
+ goto read_node_fail;
+
+ key = "qcom,hotplug-temp";
+ ret = of_property_read_u32(node, key, &data->hotplug_temp_degC);
+ if (ret)
+ goto read_node_fail;
+
+ key = "qcom,hotplug-temp-hysteresis";
+ ret = of_property_read_u32(node, key,
+ &data->hotplug_temp_hysteresis_degC);
+ if (ret)
+ goto read_node_fail;
+
+ key = "qcom,cpu-sensors";
+ cpu_cnt = of_property_count_strings(node, key);
+ if (cpu_cnt != num_possible_cpus()) {
+ pr_err("%s: Wrong number of cpu\n", KBUILD_MODNAME);
+ goto read_node_fail;
+ }
+
+ for_each_possible_cpu(cpu) {
+ cpus[cpu].cpu = cpu;
+ cpus[cpu].offline = 0;
+ cpus[cpu].user_offline = 0;
+ ret = of_property_read_string_index(node, key, cpu,
+ &cpus[cpu].sensor_type);
+ if (ret)
+ goto read_node_fail;
+ }
+
+ if (num_possible_cpus() > 1)
+ core_control_enabled = 1;
+
+read_node_fail:
+ if (ret) {
+ dev_info(&pdev->dev,
+ "%s:Failed reading node=%s, key=%s. KTM continues\n",
+ KBUILD_MODNAME, node->full_name, key);
+ core_control_enabled = 0;
+ }
+
+ return ret;
+}
+
static int __devinit msm_thermal_dev_probe(struct platform_device *pdev)
{
int ret = 0;
char *key = NULL;
struct device_node *node = pdev->dev.of_node;
-
struct msm_thermal_data data;
memset(&data, 0, sizeof(struct msm_thermal_data));
@@ -1640,15 +1858,7 @@
key = "qcom,freq-control-mask";
ret = of_property_read_u32(node, key, &data.freq_control_mask);
- key = "qcom,core-limit-temp";
- ret = of_property_read_u32(node, key, &data.core_limit_temp_degC);
-
- key = "qcom,core-temp-hysteresis";
- ret = of_property_read_u32(node, key, &data.core_temp_hysteresis_degC);
-
- key = "qcom,core-control-mask";
- ret = of_property_read_u32(node, key, &data.core_control_mask);
-
+ ret = probe_cc(node, &data, pdev);
/*
* Probe optional properties below. Call probe_psm before
* probe_vdd_rstr because rpm_regulator_get has to be called
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index fd1a2fc..1cf901e 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -4,6 +4,7 @@
* Copyright (C) 2008 Intel Corp
* Copyright (C) 2008 Zhang Rui <rui.zhang@intel.com>
* Copyright (C) 2008 Sujith Thomas <sujith.thomas@intel.com>
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
@@ -60,6 +61,273 @@
static LIST_HEAD(thermal_cdev_list);
static DEFINE_MUTEX(thermal_list_lock);
+static LIST_HEAD(sensor_info_list);
+static DEFINE_MUTEX(sensor_list_lock);
+
+static struct sensor_info *get_sensor(uint32_t sensor_id)
+{
+ struct sensor_info *pos, *var;
+
+ list_for_each_entry_safe(pos, var, &sensor_info_list, sensor_list) {
+ if (pos->sensor_id == sensor_id)
+ break;
+ }
+
+ return pos;
+}
+
+int sensor_get_id(char *name)
+{
+ struct sensor_info *pos, *var;
+
+ list_for_each_entry_safe(pos, var, &sensor_info_list, sensor_list) {
+ if (!strcmp(pos->tz->type, name))
+ return pos->sensor_id;
+ }
+
+ return -ENODEV;
+}
+EXPORT_SYMBOL(sensor_get_id);
+
+static void __update_sensor_thresholds(struct sensor_info *sensor)
+{
+ int min = INT_MIN;
+ int max = INT_MAX;
+ struct sensor_threshold *pos, *var;
+ enum thermal_trip_type type;
+ int i;
+ unsigned long curr_temp;
+
+ for (i = 0; ((sensor->max_idx == -1) || (sensor->min_idx == -1)) &&
+ (sensor->tz->ops->get_trip_type) && (i < sensor->tz->trips);
+ i++) {
+ sensor->tz->ops->get_trip_type(sensor->tz, i, &type);
+ if (type == THERMAL_TRIP_CONFIGURABLE_HI)
+ sensor->max_idx = i;
+ if (type == THERMAL_TRIP_CONFIGURABLE_LOW)
+ sensor->min_idx = i;
+ }
+
+ get_cpu();
+ sensor->tz->ops->get_temp(sensor->tz, &curr_temp);
+ list_for_each_entry_safe(pos, var, &sensor->threshold_list, list) {
+ if ((pos->trip == THERMAL_TRIP_CONFIGURABLE_LOW) &&
+ (pos->temp < (int)curr_temp))
+ if (pos->temp > min)
+ min = pos->temp;
+ if ((pos->trip == THERMAL_TRIP_CONFIGURABLE_HI) &&
+ (pos->temp > (int)curr_temp))
+ if (pos->temp < max)
+ max = pos->temp;
+ }
+ put_cpu();
+
+ if (sensor->tz->ops->set_trip_temp) {
+ if (max != INT_MAX) {
+ sensor->tz->ops->set_trip_temp(sensor->tz,
+ sensor->max_idx, max);
+ sensor->threshold_max = max;
+ }
+ if (min != INT_MIN) {
+ sensor->tz->ops->set_trip_temp(sensor->tz,
+ sensor->min_idx, min);
+ sensor->threshold_min = min;
+ }
+ }
+
+ pr_debug("sensor %d, min: %d, max %d\n", sensor->sensor_id, min, max);
+}
+
+static void sensor_update_work(struct work_struct *work)
+{
+ struct sensor_info *sensor = container_of(work, struct sensor_info,
+ work);
+ mutex_lock(&sensor->lock);
+ __update_sensor_thresholds(sensor);
+ mutex_unlock(&sensor->lock);
+}
+
+/* May be called in an interrupt context.
+ * Do NOT call sensor_set_trip from this function
+ */
+int thermal_sensor_trip(struct thermal_zone_device *tz,
+ enum thermal_trip_type trip, unsigned long temp)
+{
+ struct sensor_threshold *pos, *var;
+ int ret = -ENODEV;
+
+ if (trip != THERMAL_TRIP_CONFIGURABLE_HI &&
+ trip != THERMAL_TRIP_CONFIGURABLE_LOW)
+ return 0;
+
+ if (list_empty(&tz->sensor.threshold_list))
+ return 0;
+
+ list_for_each_entry_safe(pos, var, &tz->sensor.threshold_list, list) {
+ if (pos->trip != trip)
+ continue;
+ if (((trip == THERMAL_TRIP_CONFIGURABLE_LOW) &&
+ (pos->temp <= tz->sensor.threshold_min) &&
+ (pos->temp >= (int) temp)) ||
+ ((trip == THERMAL_TRIP_CONFIGURABLE_HI) &&
+ (pos->temp >= tz->sensor.threshold_max) &&
+ (pos->temp <= (int)temp))) {
+ pos->notify(trip, temp, pos->data);
+ }
+ }
+
+ schedule_work(&tz->sensor.work);
+
+ return ret;
+}
+EXPORT_SYMBOL(thermal_sensor_trip);
+
+int sensor_set_trip(uint32_t sensor_id, struct sensor_threshold *threshold)
+{
+ struct sensor_threshold *pos, *var;
+ struct sensor_info *sensor = get_sensor(sensor_id);
+
+ if (!sensor)
+ return -ENODEV;
+
+ if (!threshold || !threshold->notify)
+ return -EFAULT;
+
+ mutex_lock(&sensor->lock);
+ list_for_each_entry_safe(pos, var, &sensor->threshold_list, list) {
+ if (pos == threshold)
+ break;
+ }
+
+ if (pos != threshold) {
+ INIT_LIST_HEAD(&threshold->list);
+ list_add(&threshold->list, &sensor->threshold_list);
+ }
+
+ __update_sensor_thresholds(sensor);
+ mutex_unlock(&sensor->lock);
+
+ return 0;
+
+}
+EXPORT_SYMBOL(sensor_set_trip);
+
+int sensor_cancel_trip(uint32_t sensor_id, struct sensor_threshold *threshold)
+{
+ struct sensor_threshold *pos, *var;
+ struct sensor_info *sensor = get_sensor(sensor_id);
+
+ if (!sensor)
+ return -ENODEV;
+
+ mutex_lock(&sensor->lock);
+ list_for_each_entry_safe(pos, var, &sensor->threshold_list, list) {
+ if (pos == threshold) {
+ list_del(&pos->list);
+ break;
+ }
+ }
+
+ __update_sensor_thresholds(sensor);
+ mutex_unlock(&sensor->lock);
+
+ return 0;
+}
+EXPORT_SYMBOL(sensor_cancel_trip);
+
+static int sensor_get_trip_temp(struct thermal_zone_device *tz,
+ int type, unsigned long *temp)
+{
+ struct sensor_info *sensor = get_sensor(tz->id);
+
+ if (!sensor)
+ return -EFAULT;
+
+ switch (type) {
+ case THERMAL_TRIP_CONFIGURABLE_HI:
+ *temp = tz->sensor.threshold_max;
+ break;
+ case THERMAL_TRIP_CONFIGURABLE_LOW:
+ *temp = tz->sensor.threshold_min;
+ break;
+ default:
+ tz->ops->get_trip_temp(tz, type, temp);
+ break;
+ }
+
+ return 0;
+}
+
+static int tz_notify_trip(enum thermal_trip_type type, int temp, void *data)
+{
+ struct thermal_zone_device *tz = (struct thermal_zone_device *)data;
+
+ pr_debug("sensor %d tripped: type %d temp %d\n",
+ tz->sensor.sensor_id, type, temp);
+
+ return 0;
+}
+
+int sensor_set_trip_temp(struct thermal_zone_device *tz,
+ int trip, long temp)
+{
+ int ret = 0;
+ enum thermal_trip_type type;
+
+ if (!tz->ops->get_trip_type)
+ return -EPERM;
+
+ tz->ops->get_trip_type(tz, trip, &type);
+ switch (type) {
+ case THERMAL_TRIP_CONFIGURABLE_HI:
+ tz->tz_threshold[0].temp = temp;
+ tz->tz_threshold[0].trip = THERMAL_TRIP_CONFIGURABLE_HI;
+ tz->tz_threshold[0].notify = tz_notify_trip;
+ tz->tz_threshold[0].data = tz;
+ ret = sensor_set_trip(tz->sensor.sensor_id,
+ &tz->tz_threshold[0]);
+ break;
+ case THERMAL_TRIP_CONFIGURABLE_LOW:
+ tz->tz_threshold[1].temp = temp;
+ tz->tz_threshold[1].trip = THERMAL_TRIP_CONFIGURABLE_LOW;
+ tz->tz_threshold[1].notify = tz_notify_trip;
+ tz->tz_threshold[1].data = tz;
+ ret = sensor_set_trip(tz->sensor.sensor_id,
+ &tz->tz_threshold[1]);
+ break;
+ default:
+ ret = tz->ops->set_trip_temp(tz, trip, temp);
+ break;
+ }
+
+ return ret;
+}
+
+int sensor_init(struct thermal_zone_device *tz)
+{
+ struct sensor_info *sensor = &tz->sensor;
+
+ sensor->sensor_id = tz->id;
+ sensor->tz = tz;
+ sensor->threshold_min = 0;
+ sensor->threshold_max = INT_MAX;
+ sensor->max_idx = -1;
+ sensor->min_idx = -1;
+ mutex_init(&sensor->lock);
+ INIT_LIST_HEAD(&sensor->sensor_list);
+ INIT_LIST_HEAD(&sensor->threshold_list);
+ INIT_LIST_HEAD(&tz->tz_threshold[0].list);
+ INIT_LIST_HEAD(&tz->tz_threshold[1].list);
+ tz->tz_threshold[0].notify = NULL;
+ tz->tz_threshold[0].data = NULL;
+ tz->tz_threshold[1].notify = NULL;
+ tz->tz_threshold[1].data = NULL;
+ list_add(&sensor->sensor_list, &sensor_info_list);
+ INIT_WORK(&sensor->work, sensor_update_work);
+
+ return 0;
+}
+
static int get_idr(struct idr *idr, struct mutex *lock, int *id)
{
int err;
@@ -243,7 +511,7 @@
if (!sscanf(attr->attr.name, "trip_point_%d_temp", &trip))
return -EINVAL;
- ret = tz->ops->get_trip_temp(tz, trip, &temperature);
+ ret = sensor_get_trip_temp(tz, trip, &temperature);
if (ret)
return ret;
@@ -268,7 +536,8 @@
if (!sscanf(buf, "%ld", &temperature))
return -EINVAL;
- ret = tz->ops->set_trip_temp(tz, trip, temperature);
+ ret = sensor_set_trip_temp(tz, trip, temperature);
+
if (ret)
return ret;
@@ -1313,6 +1582,7 @@
if (result)
break;
}
+ sensor_init(tz);
mutex_unlock(&thermal_list_lock);
INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check);
@@ -1372,6 +1642,10 @@
&trip_point_attrs[count * 2 + 1]);
}
thermal_remove_hwmon_sysfs(tz);
+ flush_work(&tz->sensor.work);
+ mutex_lock(&thermal_list_lock);
+ list_del(&tz->sensor.sensor_list);
+ mutex_unlock(&thermal_list_lock);
release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id);
idr_destroy(&tz->idr);
mutex_destroy(&tz->lock);
diff --git a/drivers/tty/serial/msm_serial_hs_lite.c b/drivers/tty/serial/msm_serial_hs_lite.c
index d520253..a4a4f28 100644
--- a/drivers/tty/serial/msm_serial_hs_lite.c
+++ b/drivers/tty/serial/msm_serial_hs_lite.c
@@ -47,6 +47,8 @@
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/wakelock.h>
+#include <linux/types.h>
+#include <asm/byteorder.h>
#include <mach/board.h>
#include <mach/msm_serial_hs_lite.h>
#include <mach/msm_bus.h>
@@ -166,12 +168,17 @@
static inline void msm_hsl_write(struct uart_port *port,
unsigned int val, unsigned int off)
{
- iowrite32(val, port->membase + off);
+ __iowmb();
+ __raw_writel_no_log((__force __u32)cpu_to_le32(val),
+ port->membase + off);
}
static inline unsigned int msm_hsl_read(struct uart_port *port,
unsigned int off)
{
- return ioread32(port->membase + off);
+ unsigned int v = le32_to_cpu((__force __le32)__raw_readl_no_log(
+ port->membase + off));
+ __iormb();
+ return v;
}
static unsigned int msm_serial_hsl_has_gsbi(struct uart_port *port)
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index db6fec9..98c6884 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -111,7 +111,33 @@
reg = dwc3_readl(dwc->regs, DWC3_GCTL);
reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));
reg |= DWC3_GCTL_PRTCAPDIR(mode);
+ /*
+ * Set this bit so that device attempts three more times at SS, even
+ * if it failed previously to operate in SS mode.
+ */
+ reg |= DWC3_GCTL_U2RSTECN;
+ if (mode == DWC3_GCTL_PRTCAP_HOST) {
+ /*
+ * Allow ITP generated off of ref clk based counter instead
+ * of UTMI/ULPI clk based counter, when superspeed only is
+ * active so that UTMI/ULPI PHY can be suspened.
+ */
+ reg |= DWC3_GCTL_SOFITPSYNC;
+ reg &= ~(DWC3_GCTL_PWRDNSCALEMASK);
+ reg |= DWC3_GCTL_PWRDNSCALE(2);
+ } else if (mode == DWC3_GCTL_PRTCAP_DEVICE) {
+ reg &= ~(DWC3_GCTL_PWRDNSCALEMASK);
+ reg |= DWC3_GCTL_PWRDNSCALE(2);
+ reg &= ~(DWC3_GCTL_SOFITPSYNC);
+ }
+ reg |= DWC3_GCTL_U2EXIT_LFPS;
dwc3_writel(dwc->regs, DWC3_GCTL, reg);
+ reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
+ reg |= DWC3_GUSB3PIPECTL_SUSPHY;
+ dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
+ reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
+ reg |= DWC3_GUSB2PHYCFG_SUSPHY;
+ dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
}
/**
@@ -127,6 +153,9 @@
reg |= DWC3_GCTL_CORESOFTRESET;
dwc3_writel(dwc->regs, DWC3_GCTL, reg);
+ if (dwc->revision >= DWC3_REVISION_230A)
+ dwc3_notify_event(dwc, DWC3_CONTROLLER_RESET_EVENT);
+
/* Assert USB3 PHY reset */
reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST;
@@ -155,6 +184,9 @@
reg = dwc3_readl(dwc->regs, DWC3_GCTL);
reg &= ~DWC3_GCTL_CORESOFTRESET;
dwc3_writel(dwc->regs, DWC3_GCTL, reg);
+
+ if (dwc->revision >= DWC3_REVISION_230A)
+ dwc3_notify_event(dwc, DWC3_CONTROLLER_POST_RESET_EVENT);
}
/**
@@ -473,6 +505,20 @@
dwc3_gadget_restart(dwc);
}
+static void (*notify_event) (struct dwc3 *, unsigned);
+void dwc3_set_notifier(void (*notify)(struct dwc3 *, unsigned))
+{
+ notify_event = notify;
+}
+EXPORT_SYMBOL(dwc3_set_notifier);
+
+void dwc3_notify_event(struct dwc3 *dwc, unsigned event)
+{
+ if (dwc->notify_event)
+ dwc->notify_event(dwc, event);
+}
+EXPORT_SYMBOL(dwc3_notify_event);
+
#define DWC3_ALIGN_MASK (16 - 1)
static u64 dwc3_dma_mask = DMA_BIT_MASK(64);
@@ -504,6 +550,7 @@
if (!dev->coherent_dma_mask)
dev->coherent_dma_mask = DMA_BIT_MASK(64);
+ dwc->notify_event = notify_event;
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!res) {
dev_err(dev, "missing IRQ\n");
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 2064c13..328f6f4 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -163,7 +163,10 @@
/* Global Configuration Register */
#define DWC3_GCTL_PWRDNSCALE(n) ((n) << 19)
+#define DWC3_GCTL_PWRDNSCALEMASK (0xFFF80000)
#define DWC3_GCTL_U2RSTECN (1 << 16)
+#define DWC3_GCTL_SOFITPSYNC (1 << 10)
+#define DWC3_GCTL_U2EXIT_LFPS (1 << 2)
#define DWC3_GCTL_RAMCLKSEL(x) (((x) & DWC3_GCTL_CLK_MASK) << 6)
#define DWC3_GCTL_CLK_BUS (0)
#define DWC3_GCTL_CLK_PIPE (1)
@@ -643,6 +646,9 @@
__le64 dma_adr[DWC3_MAX_HIBER_SCRATCHBUFS];
};
+#define DWC3_CONTROLLER_ERROR_EVENT 0
+#define DWC3_CONTROLLER_RESET_EVENT 1
+#define DWC3_CONTROLLER_POST_RESET_EVENT 2
/**
* struct dwc3 - representation of our controller
* @ctrl_req: usb control request which is used for ep0
@@ -771,6 +777,7 @@
/* Indicate if software connect was issued by the usb_gadget_driver */
bool softconnect;
+ void (*notify_event) (struct dwc3 *, unsigned);
};
/* -------------------------------------------------------------------------- */
@@ -922,6 +929,9 @@
void dwc3_post_host_reset_core_init(struct dwc3 *dwc);
int dwc3_event_buffers_setup(struct dwc3 *dwc);
+extern void dwc3_set_notifier(
+ void (*notify) (struct dwc3 *dwc3, unsigned event));
+extern void dwc3_notify_event(struct dwc3 *dwc3, unsigned event);
extern int dwc3_get_device_id(void);
extern void dwc3_put_device_id(int id);
diff --git a/drivers/usb/dwc3/debug.h b/drivers/usb/dwc3/debug.h
index b156c5f..4901f4b 100644
--- a/drivers/usb/dwc3/debug.h
+++ b/drivers/usb/dwc3/debug.h
@@ -46,6 +46,7 @@
extern void dbg_setup(u8, const struct usb_ctrlrequest*);
extern int dwc3_debugfs_init(struct dwc3 *);
extern void dwc3_debugfs_exit(struct dwc3 *);
+extern void dbg_print_reg(const char *name, int reg);
#else
static inline void dbg_event(u8, const char*, int)
{ }
@@ -57,6 +58,8 @@
{ }
static inline void dbg_setup(u8, const struct usb_ctrlrequest*)
{ }
+static inline void dbg_print_reg(const char *name, int reg)
+{ }
static inline int dwc3_debugfs_init(struct dwc3 *d)
{ return 0; }
static inline void dwc3_debugfs_exit(struct dwc3 *d)
diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c
index df95646..a2580fc 100644
--- a/drivers/usb/dwc3/debugfs.c
+++ b/drivers/usb/dwc3/debugfs.c
@@ -972,6 +972,28 @@
}
/**
+ * dbg_print_reg: prints a reg value
+ * @name: reg name
+ * @reg: reg value to be printed
+ */
+void dbg_print_reg(const char *name, int reg)
+{
+ unsigned long flags;
+
+ write_lock_irqsave(&dbg_dwc3_data.lck, flags);
+
+ scnprintf(dbg_dwc3_data.buf[dbg_dwc3_data.idx], DBG_DATA_MSG,
+ "%s = 0x%08x\n", name, reg);
+
+ dbg_inc(&dbg_dwc3_data.idx);
+
+ write_unlock_irqrestore(&dbg_dwc3_data.lck, flags);
+
+ if (dbg_dwc3_data.tty != 0)
+ pr_notice("%s = 0x%08x\n", name, reg);
+}
+
+/**
* store_events: configure if events are going to be also printed to console
*
*/
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index d3ea3be..d7721dc 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -50,6 +50,7 @@
#include "dwc3_otg.h"
#include "core.h"
#include "gadget.h"
+#include "debug.h"
/* ADC threshold values */
static int adc_low_threshold = 700;
@@ -140,6 +141,7 @@
#define QSCRATCH_REG_OFFSET (0x000F8800)
#define QSCRATCH_CTRL_REG (QSCRATCH_REG_OFFSET + 0x04)
#define QSCRATCH_GENERAL_CFG (QSCRATCH_REG_OFFSET + 0x08)
+#define QSCRATCH_RAM1_REG (QSCRATCH_REG_OFFSET + 0x0C)
#define HS_PHY_CTRL_REG (QSCRATCH_REG_OFFSET + 0x10)
#define PARAMETER_OVERRIDE_X_REG (QSCRATCH_REG_OFFSET + 0x14)
#define CHARGING_DET_CTRL_REG (QSCRATCH_REG_OFFSET + 0x18)
@@ -156,6 +158,8 @@
#define SS_CR_PROTOCOL_CAP_DATA_REG (QSCRATCH_REG_OFFSET + 0x48)
#define SS_CR_PROTOCOL_READ_REG (QSCRATCH_REG_OFFSET + 0x4C)
#define SS_CR_PROTOCOL_WRITE_REG (QSCRATCH_REG_OFFSET + 0x50)
+#define PWR_EVNT_IRQ_STAT_REG (QSCRATCH_REG_OFFSET + 0x58)
+#define PWR_EVNT_IRQ_MASK_REG (QSCRATCH_REG_OFFSET + 0x5C)
struct dwc3_msm_req_complete {
struct list_head list_item;
@@ -223,7 +227,7 @@
bool ext_inuse;
enum dwc3_id_state id_state;
unsigned long lpm_flags;
-#define MDWC3_CORECLK_OFF BIT(0)
+#define MDWC3_PHY_REF_AND_CORECLK_OFF BIT(0)
#define MDWC3_TCXO_SHUTDOWN BIT(1)
u32 qscratch_ctl_val;
@@ -410,6 +414,37 @@
}
/**
+ * Dump all QSCRATCH registers.
+ *
+ */
+static void dwc3_msm_dump_phy_info(struct dwc3_msm *mdwc)
+{
+
+ dbg_print_reg("SSPHY_CTRL_REG", dwc3_msm_read_reg(mdwc->base,
+ SS_PHY_CTRL_REG));
+ dbg_print_reg("HSPHY_CTRL_REG", dwc3_msm_read_reg(mdwc->base,
+ HS_PHY_CTRL_REG));
+ dbg_print_reg("QSCRATCH_CTRL_REG", dwc3_msm_read_reg(mdwc->base,
+ QSCRATCH_CTRL_REG));
+ dbg_print_reg("QSCRATCH_GENERAL_CFG", dwc3_msm_read_reg(mdwc->base,
+ QSCRATCH_GENERAL_CFG));
+ dbg_print_reg("PARAMETER_OVERRIDE_X_REG", dwc3_msm_read_reg(mdwc->base,
+ PARAMETER_OVERRIDE_X_REG));
+ dbg_print_reg("HS_PHY_IRQ_STAT_REG", dwc3_msm_read_reg(mdwc->base,
+ HS_PHY_IRQ_STAT_REG));
+ dbg_print_reg("SS_PHY_PARAM_CTRL_1", dwc3_msm_read_reg(mdwc->base,
+ SS_PHY_PARAM_CTRL_1));
+ dbg_print_reg("SS_PHY_PARAM_CTRL_2", dwc3_msm_read_reg(mdwc->base,
+ SS_PHY_PARAM_CTRL_2));
+ dbg_print_reg("QSCRATCH_RAM1_REG", dwc3_msm_read_reg(mdwc->base,
+ QSCRATCH_RAM1_REG));
+ dbg_print_reg("PWR_EVNT_IRQ_STAT_REG", dwc3_msm_read_reg(mdwc->base,
+ PWR_EVNT_IRQ_STAT_REG));
+ dbg_print_reg("PWR_EVNT_IRQ_MASK_REG", dwc3_msm_read_reg(mdwc->base,
+ PWR_EVNT_IRQ_MASK_REG));
+}
+
+/**
* Return DBM EP number according to usb endpoint number.
*
*/
@@ -1381,8 +1416,14 @@
}
/* Initialize QSCRATCH registers for HSPHY and SSPHY operation */
-static void dwc3_msm_qscratch_reg_init(struct dwc3_msm *mdwc)
+static void dwc3_msm_qscratch_reg_init(struct dwc3_msm *mdwc,
+ unsigned event_status)
{
+ if (event_status == DWC3_CONTROLLER_POST_RESET_EVENT) {
+ dwc3_msm_ss_phy_reg_init(mdwc);
+ return;
+ }
+
/* SSPHY Initialization: Use ref_clk from pads and set its parameters */
dwc3_msm_write_reg(mdwc->base, SS_PHY_CTRL_REG, 0x10210002);
msleep(30);
@@ -1393,7 +1434,7 @@
dwc3_msm_write_reg(mdwc->base, SS_PHY_CTRL_REG, 0x10210002);
usleep_range(2000, 2200);
/* Ref clock must be stable now, enable ref clock for HS mode */
- dwc3_msm_write_reg(mdwc->base, SS_PHY_CTRL_REG, 0x10210102);
+ dwc3_msm_write_reg(mdwc->base, SS_PHY_CTRL_REG, 0x11210102);
usleep_range(2000, 2200);
/*
* HSPHY Initialization: Enable UTMI clock and clamp enable HVINTs,
@@ -1401,8 +1442,8 @@
*/
dwc3_msm_write_reg(mdwc->base, HS_PHY_CTRL_REG, 0x5220bb2);
usleep_range(2000, 2200);
- /* Disable (bypass) VBUS and ID filters */
- dwc3_msm_write_reg(mdwc->base, QSCRATCH_GENERAL_CFG, 0x78);
+ /* Set XHCI_REV bit (2) to 1 - XHCI version 1.0 */
+ dwc3_msm_write_reg(mdwc->base, QSCRATCH_GENERAL_CFG, 0x4);
/*
* write HSPHY init value to QSCRATCH reg to set HSPHY parameters like
* VBUS valid threshold, disconnect valid threshold, DC voltage level,
@@ -1415,14 +1456,14 @@
PARAMETER_OVERRIDE_X_REG, 0x03FFFFFF,
mdwc->hsphy_init_seq & 0x03FFFFFF);
- /* Enable master clock for RAMs to allow BAM to access RAMs when
- * RAM clock gating is enabled via DWC3's GCTL. Otherwise, issues
+ /*
+ * Enable master clock for RAMs to allow BAM to access RAMs when
+ * RAM clock gating is enabled via DWC3's GCTL. Otherwise issues
* are seen where RAM clocks get turned OFF in SS mode
*/
dwc3_msm_write_reg(mdwc->base, CGCTL_REG,
dwc3_msm_read_reg(mdwc->base, CGCTL_REG) | 0x18);
- dwc3_msm_ss_phy_reg_init(mdwc);
/*
* This is required to restore the POR value after userspace
* is done with charger detection.
@@ -1431,6 +1472,31 @@
dwc3_msm_read_reg(mdwc->base, QSCRATCH_CTRL_REG);
}
+static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned event)
+{
+ struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
+
+ switch (event) {
+ case DWC3_CONTROLLER_ERROR_EVENT:
+ dev_info(mdwc->dev, "DWC3_CONTROLLER_ERROR_EVENT received\n");
+ dwc3_msm_dump_phy_info(mdwc);
+ break;
+ case DWC3_CONTROLLER_RESET_EVENT:
+ dev_dbg(mdwc->dev, "DWC3_CONTROLLER_RESET_EVENT received\n");
+ dwc3_msm_qscratch_reg_init(mdwc, DWC3_CONTROLLER_RESET_EVENT);
+ break;
+ case DWC3_CONTROLLER_POST_RESET_EVENT:
+ dev_dbg(mdwc->dev,
+ "DWC3_CONTROLLER_POST_RESET_EVENT received\n");
+ dwc3_msm_qscratch_reg_init(mdwc,
+ DWC3_CONTROLLER_POST_RESET_EVENT);
+ break;
+ default:
+ dev_dbg(mdwc->dev, "unknown dwc3 event\n");
+ break;
+ }
+}
+
static void dwc3_msm_block_reset(struct dwc3_ext_xceiv *xceiv, bool core_reset)
{
struct dwc3_msm *mdwc = container_of(xceiv, struct dwc3_msm, ext_xceiv);
@@ -1447,9 +1513,6 @@
return;
usleep_range(10000, 12000);
-
- /* Reinitialize QSCRATCH registers after block reset */
- dwc3_msm_qscratch_reg_init(mdwc);
}
/* Reset the DBM */
@@ -1687,6 +1750,7 @@
bool dcp;
bool host_bus_suspend;
bool host_ss_active;
+ bool host_ss_suspend;
dev_dbg(mdwc->dev, "%s: entering lpm\n", __func__);
@@ -1713,6 +1777,7 @@
(mdwc->charger.chg_type == DWC3_PROPRIETARY_CHARGER) ||
(mdwc->charger.chg_type == DWC3_FLOATED_CHARGER));
host_bus_suspend = mdwc->host_mode == 1;
+ host_ss_suspend = host_bus_suspend && host_ss_active;
if (!dcp && !host_bus_suspend)
dwc3_msm_write_reg(mdwc->base, QSCRATCH_CTRL_REG,
@@ -1724,13 +1789,17 @@
* 3. Set TEST_POWERED_DOWN in SS_PHY_CTRL_REG to enable PHY retention
* 4. Disable SSPHY ref clk
*/
- dwc3_msm_write_readback(mdwc->base, SS_PHY_CTRL_REG, (1 << 8), 0x0);
- dwc3_msm_write_readback(mdwc->base, SS_PHY_CTRL_REG, (1 << 28), 0x0);
- dwc3_msm_write_readback(mdwc->base, SS_PHY_CTRL_REG, (1 << 26),
+ if (!host_ss_suspend) {
+ dwc3_msm_write_readback(mdwc->base, SS_PHY_CTRL_REG, (1 << 8),
+ 0x0);
+ dwc3_msm_write_readback(mdwc->base, SS_PHY_CTRL_REG, (1 << 28),
+ 0x0);
+ dwc3_msm_write_readback(mdwc->base, SS_PHY_CTRL_REG, (1 << 26),
(1 << 26));
-
+ }
usleep_range(1000, 1200);
- clk_disable_unprepare(mdwc->ref_clk);
+ if (!host_ss_suspend)
+ clk_disable_unprepare(mdwc->ref_clk);
if (host_bus_suspend) {
/* Sequence for host bus suspend case:
@@ -1775,9 +1844,9 @@
if (!host_bus_suspend)
dwc3_msm_config_gdsc(mdwc, 0);
- if (!host_bus_suspend || !host_ss_active) {
+ if (!host_ss_suspend) {
clk_disable_unprepare(mdwc->core_clk);
- mdwc->lpm_flags |= MDWC3_CORECLK_OFF;
+ mdwc->lpm_flags |= MDWC3_PHY_REF_AND_CORECLK_OFF;
}
clk_disable_unprepare(mdwc->iface_clk);
@@ -1825,6 +1894,7 @@
int ret;
bool dcp;
bool host_bus_suspend;
+ bool resume_from_core_clk_off = false;
dev_dbg(mdwc->dev, "%s: exiting lpm\n", __func__);
@@ -1835,6 +1905,9 @@
pm_stay_awake(mdwc->dev);
+ if (mdwc->lpm_flags & MDWC3_PHY_REF_AND_CORECLK_OFF)
+ resume_from_core_clk_off = true;
+
if (mdwc->bus_perf_client) {
ret = msm_bus_scale_client_update_request(
mdwc->bus_perf_client, 1);
@@ -1873,13 +1946,14 @@
if (!host_bus_suspend && !dcp)
dwc3_hsusb_config_vddcx(mdwc, 1);
- clk_prepare_enable(mdwc->ref_clk);
+ if (mdwc->lpm_flags & MDWC3_PHY_REF_AND_CORECLK_OFF)
+ clk_prepare_enable(mdwc->ref_clk);
usleep_range(1000, 1200);
clk_prepare_enable(mdwc->iface_clk);
- if (mdwc->lpm_flags & MDWC3_CORECLK_OFF) {
+ if (mdwc->lpm_flags & MDWC3_PHY_REF_AND_CORECLK_OFF) {
clk_prepare_enable(mdwc->core_clk);
- mdwc->lpm_flags &= ~MDWC3_CORECLK_OFF;
+ mdwc->lpm_flags &= ~MDWC3_PHY_REF_AND_CORECLK_OFF;
}
if (host_bus_suspend) {
@@ -1892,10 +1966,6 @@
/* Disable DP and DM HV interrupt */
dwc3_msm_write_reg(mdwc->base, ALT_INTERRUPT_EN_REG, 0x000);
-
- /* Clear suspend bit in GUSB2PHYCONFIG register */
- dwc3_msm_write_readback(mdwc->base, DWC3_GUSB2PHYCFG(0),
- 0x40, 0x0);
} else {
/* Disable HV interrupt */
if (mdwc->otg_xceiv && (!mdwc->ext_xceiv.otg_capability))
@@ -1919,23 +1989,27 @@
}
- /* Assert SS PHY RESET */
- dwc3_msm_write_readback(mdwc->base, SS_PHY_CTRL_REG, (1 << 7),
+ if (resume_from_core_clk_off) {
+ /* Assert SS PHY RESET */
+ dwc3_msm_write_readback(mdwc->base, SS_PHY_CTRL_REG, (1 << 7),
(1 << 7));
- dwc3_msm_write_readback(mdwc->base, SS_PHY_CTRL_REG, (1 << 28),
+ dwc3_msm_write_readback(mdwc->base, SS_PHY_CTRL_REG, (1 << 28),
(1 << 28));
- dwc3_msm_write_readback(mdwc->base, SS_PHY_CTRL_REG, (1 << 8),
+ dwc3_msm_write_readback(mdwc->base, SS_PHY_CTRL_REG, (1 << 8),
(1 << 8));
- dwc3_msm_write_readback(mdwc->base, SS_PHY_CTRL_REG, (1 << 26), 0x0);
- /* 10usec delay required before de-asserting SS PHY RESET */
- udelay(10);
- dwc3_msm_write_readback(mdwc->base, SS_PHY_CTRL_REG, (1 << 7), 0x0);
+ dwc3_msm_write_readback(mdwc->base, SS_PHY_CTRL_REG, (1 << 26),
+ 0x0);
+ /* 10usec delay required before de-asserting SS PHY RESET */
+ udelay(10);
+ dwc3_msm_write_readback(mdwc->base, SS_PHY_CTRL_REG, (1 << 7),
+ 0x0);
- /*
- * Reinitilize SSPHY parameters as SS_PHY RESET will reset
- * the internal registers to default values.
- */
- dwc3_msm_ss_phy_reg_init(mdwc);
+ /*
+ * Reinitilize SSPHY parameters as SS_PHY RESET will reset
+ * the internal registers to default values.
+ */
+ dwc3_msm_ss_phy_reg_init(mdwc);
+ }
atomic_set(&mdwc->in_lpm, 0);
/* match disable_irq call from isr */
@@ -2072,7 +2146,7 @@
static struct dentry *dwc3_debugfs_root;
-static void dwc3_debugfs_init(struct dwc3_msm *mdwc)
+static void dwc3_msm_debugfs_init(struct dwc3_msm *mdwc)
{
dwc3_debugfs_root = debugfs_create_dir("msm_dwc3", NULL);
@@ -2871,8 +2945,6 @@
else if (!mdwc->hsphy_init_seq)
dev_warn(&pdev->dev, "incorrect hsphyinitseq.Using PORvalue\n");
- dwc3_msm_qscratch_reg_init(mdwc);
-
pm_runtime_set_active(mdwc->dev);
pm_runtime_enable(mdwc->dev);
@@ -2891,7 +2963,7 @@
ret = -ENODEV;
goto disable_hs_ldo;
}
-
+ dwc3_set_notifier(&dwc3_msm_notify_event);
/* usb_psy required only for vbus_notifications or charging support */
if (mdwc->ext_xceiv.otg_capability ||
!mdwc->charger.charging_disabled) {
@@ -2990,7 +3062,7 @@
device_init_wakeup(mdwc->dev, 1);
pm_stay_awake(mdwc->dev);
- dwc3_debugfs_init(mdwc);
+ dwc3_msm_debugfs_init(mdwc);
return 0;
diff --git a/drivers/usb/dwc3/dwc3_otg.c b/drivers/usb/dwc3/dwc3_otg.c
index d0d9d34..e912e86 100644
--- a/drivers/usb/dwc3/dwc3_otg.c
+++ b/drivers/usb/dwc3/dwc3_otg.c
@@ -56,6 +56,19 @@
reg = dwc3_readl(dwc->regs, DWC3_GCTL);
reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));
reg |= DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_HOST);
+ /*
+ * Allow ITP generated off of ref clk based counter instead
+ * of UTMI/ULPI clk based counter, when superspeed only is
+ * active so that UTMI/ULPI can be suspened.
+ */
+ reg |= DWC3_GCTL_SOFITPSYNC;
+ /*
+ * Set this bit so that device attempts three more times at SS,
+ * even if it failed previously to operate in SS mode.
+ */
+ reg |= DWC3_GCTL_U2RSTECN;
+ reg &= ~(DWC3_GCTL_PWRDNSCALEMASK);
+ reg |= DWC3_GCTL_PWRDNSCALE(2);
dwc3_writel(dwc->regs, DWC3_GCTL, reg);
}
}
@@ -126,6 +139,14 @@
reg = dwc3_readl(dwc->regs, DWC3_GCTL);
reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));
reg |= DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_DEVICE);
+ /*
+ * Set this bit so that device attempts three more times at SS,
+ * even if it failed previously to operate in SS mode.
+ */
+ reg |= DWC3_GCTL_U2RSTECN;
+ reg &= ~(DWC3_GCTL_PWRDNSCALEMASK);
+ reg |= DWC3_GCTL_PWRDNSCALE(2);
+ reg &= ~(DWC3_GCTL_SOFITPSYNC);
dwc3_writel(dwc->regs, DWC3_GCTL, reg);
}
}
@@ -847,7 +868,8 @@
* OCFG[1] - HNPCap = 0
* OCFG[0] - SRPCap = 0
*/
- dwc3_writel(dotg->regs, DWC3_OCFG, 0x4);
+ if (ext_xceiv && !ext_xceiv->otg_capability)
+ dwc3_writel(dotg->regs, DWC3_OCFG, 0x4);
/*
* OCTL[6] - PeriMode = 1
@@ -859,7 +881,8 @@
* OCTL[0] - HstSetHNPEn = 0
*/
if (!once) {
- dwc3_writel(dotg->regs, DWC3_OCTL, 0x40);
+ if (ext_xceiv && !ext_xceiv->otg_capability)
+ dwc3_writel(dotg->regs, DWC3_OCTL, 0x40);
once++;
}
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index acda980..8cf8a6d 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -63,6 +63,9 @@
MODULE_PARM_DESC(tx_fifo_resize_enable,
"Enable allocating Tx fifo for endpoints");
+static void dwc3_gadget_usb2_phy_suspend(struct dwc3 *dwc, int suspend);
+static void dwc3_gadget_usb3_phy_suspend(struct dwc3 *dwc, int suspend);
+
/**
* dwc3_gadget_set_test_mode - Enables USB2 Test Modes
* @dwc: pointer to our context structure
@@ -322,6 +325,16 @@
{
u32 timeout = 500;
u32 reg;
+ bool hsphy_suspend_enabled;
+ int ret;
+
+ /* Commands to controller will work only if PHY is not suspended */
+ hsphy_suspend_enabled = (dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)) &
+ DWC3_GUSB2PHYCFG_SUSPHY);
+
+ /* Disable suspend of the USB2 PHY */
+ if (hsphy_suspend_enabled)
+ dwc3_gadget_usb2_phy_suspend(dwc, false);
dwc3_writel(dwc->regs, DWC3_DGCMDPAR, param);
dwc3_writel(dwc->regs, DWC3_DGCMD, cmd | DWC3_DGCMD_CMDACT);
@@ -331,7 +344,8 @@
if (!(reg & DWC3_DGCMD_CMDACT)) {
dev_vdbg(dwc->dev, "Command Complete --> %d\n",
DWC3_DGCMD_STATUS(reg));
- return 0;
+ ret = 0;
+ break;
}
/*
@@ -339,10 +353,18 @@
* interrupt context.
*/
timeout--;
- if (!timeout)
- return -ETIMEDOUT;
+ if (!timeout) {
+ ret = -ETIMEDOUT;
+ break;
+ }
udelay(1);
} while (1);
+
+ /* Enable suspend of the USB2 PHY */
+ if (hsphy_suspend_enabled)
+ dwc3_gadget_usb2_phy_suspend(dwc, true);
+
+ return ret;
}
int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep,
@@ -351,12 +373,22 @@
struct dwc3_ep *dep = dwc->eps[ep];
u32 timeout = 500;
u32 reg;
+ bool hsphy_suspend_enabled;
+ int ret;
dev_vdbg(dwc->dev, "%s: cmd '%s' params %08x %08x %08x\n",
dep->name,
dwc3_gadget_ep_cmd_string(cmd), params->param0,
params->param1, params->param2);
+ /* Commands to controller will work only if PHY is not suspended */
+ hsphy_suspend_enabled = (dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)) &
+ DWC3_GUSB2PHYCFG_SUSPHY);
+
+ /* Disable suspend of the USB2 PHY */
+ if (hsphy_suspend_enabled)
+ dwc3_gadget_usb2_phy_suspend(dwc, false);
+
dwc3_writel(dwc->regs, DWC3_DEPCMDPAR0(ep), params->param0);
dwc3_writel(dwc->regs, DWC3_DEPCMDPAR1(ep), params->param1);
dwc3_writel(dwc->regs, DWC3_DEPCMDPAR2(ep), params->param2);
@@ -374,9 +406,10 @@
* event. Hence return error in this case.
*/
if (reg & 0x2000)
- return -EAGAIN;
+ ret = -EAGAIN;
else
- return 0;
+ ret = 0;
+ break;
}
/*
@@ -384,11 +417,19 @@
* interrupt context.
*/
timeout--;
- if (!timeout)
- return -ETIMEDOUT;
+ if (!timeout) {
+ ret = -ETIMEDOUT;
+ break;
+ }
udelay(1);
} while (1);
+
+ /* Enable suspend of the USB2 PHY */
+ if (hsphy_suspend_enabled)
+ dwc3_gadget_usb2_phy_suspend(dwc, true);
+
+ return ret;
}
dma_addr_t dwc3_trb_dma_offset(struct dwc3_ep *dep,
@@ -1677,6 +1718,9 @@
reg |= DWC3_DCTL_HIRD_THRES(28);
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+
+ dwc3_gadget_usb2_phy_suspend(dwc, true);
+ dwc3_gadget_usb3_phy_suspend(dwc, true);
}
reg = dwc3_readl(dwc->regs, DWC3_DCFG);
@@ -2572,6 +2616,35 @@
dev_vdbg(dwc->dev, "%s link %d\n", __func__, dwc->link_state);
}
+static void dwc3_dump_reg_info(struct dwc3 *dwc)
+{
+ dbg_event(0xFF, "REGDUMP", 0);
+
+ dbg_print_reg("GUSB3PIPCTL", dwc3_readl(dwc->regs,
+ DWC3_GUSB3PIPECTL(0)));
+ dbg_print_reg("GUSB2PHYCONFIG", dwc3_readl(dwc->regs,
+ DWC3_GUSB2PHYCFG(0)));
+ dbg_print_reg("GCTL", dwc3_readl(dwc->regs, DWC3_GCTL));
+ dbg_print_reg("GUCTL", dwc3_readl(dwc->regs, DWC3_GUCTL));
+ dbg_print_reg("GDBGLTSSM", dwc3_readl(dwc->regs, DWC3_GDBGLTSSM));
+ dbg_print_reg("DCFG", dwc3_readl(dwc->regs, DWC3_DCFG));
+ dbg_print_reg("DCTL", dwc3_readl(dwc->regs, DWC3_DCTL));
+ dbg_print_reg("DEVTEN", dwc3_readl(dwc->regs, DWC3_DEVTEN));
+ dbg_print_reg("DSTS", dwc3_readl(dwc->regs, DWC3_DSTS));
+ dbg_print_reg("DALPENA", dwc3_readl(dwc->regs, DWC3_DALEPENA));
+ dbg_print_reg("DGCMD", dwc3_readl(dwc->regs, DWC3_DGCMD));
+
+ dbg_print_reg("OCFG", dwc3_readl(dwc->regs, DWC3_OCFG));
+ dbg_print_reg("OCTL", dwc3_readl(dwc->regs, DWC3_OCTL));
+ dbg_print_reg("OEVT", dwc3_readl(dwc->regs, DWC3_OEVT));
+ dbg_print_reg("OSTS", dwc3_readl(dwc->regs, DWC3_OSTS));
+
+ dwc3_notify_event(dwc, DWC3_CONTROLLER_ERROR_EVENT);
+
+ panic("DWC3 Erratic error\n");
+
+}
+
static void dwc3_gadget_interrupt(struct dwc3 *dwc,
const struct dwc3_event_devt *event)
{
@@ -2600,6 +2673,7 @@
case DWC3_DEVICE_EVENT_ERRATIC_ERROR:
dbg_event(0xFF, "ERROR", 0);
dev_vdbg(dwc->dev, "Erratic Error\n");
+ dwc3_dump_reg_info(dwc);
break;
case DWC3_DEVICE_EVENT_CMD_CMPL:
dev_vdbg(dwc->dev, "Command Complete\n");
@@ -2824,8 +2898,8 @@
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
- dwc3_gadget_usb2_phy_suspend(dwc, false);
- dwc3_gadget_usb3_phy_suspend(dwc, false);
+ dwc3_gadget_usb2_phy_suspend(dwc, true);
+ dwc3_gadget_usb3_phy_suspend(dwc, true);
}
ret = device_register(&dwc->gadget.dev);
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 27d67e3..e068484 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -1220,6 +1220,15 @@
break;
if (w_value && !f->set_alt)
break;
+ /*
+ * We put interfaces in default settings (alt 0)
+ * upon set config#1. Call set_alt for non-zero
+ * alternate setting.
+ */
+ if (!w_value && cdev->config) {
+ value = 0;
+ break;
+ }
value = f->set_alt(f, w_index, w_value);
if (value == USB_GADGET_DELAYED_STATUS) {
DBG(cdev,
diff --git a/drivers/usb/gadget/f_qdss.c b/drivers/usb/gadget/f_qdss.c
index f90967f..3b94dd5 100644
--- a/drivers/usb/gadget/f_qdss.c
+++ b/drivers/usb/gadget/f_qdss.c
@@ -441,6 +441,10 @@
pr_debug("usb_qdss_disconnect_work\n");
+ status = uninit_data(qdss->data);
+ if (status)
+ pr_err("%s: uninit_data error\n", __func__);
+
/* notify qdss to cancell all active transfers*/
if (qdss->ch.notify) {
qdss->ch.notify(qdss->ch.priv, USB_QDSS_DISCONNECT, NULL,
@@ -458,22 +462,22 @@
{
struct f_qdss *qdss = func_to_qdss(f);
unsigned long flags;
- int status;
pr_debug("qdss_disable\n");
spin_lock_irqsave(&qdss->lock, flags);
+ if (!qdss->usb_connected) {
+ spin_unlock_irqrestore(&qdss->lock, flags);
+ return;
+ }
+
qdss->usb_connected = 0;
spin_unlock_irqrestore(&qdss->lock, flags);
/*cancell all active xfers*/
qdss_eps_disable(f);
- status = uninit_data(qdss->data);
- if (status)
- pr_err("%s: uninit_data error\n", __func__);
-
- schedule_work(&qdss->disconnect_w);
+ queue_work(qdss->wq, &qdss->disconnect_w);
}
static void usb_qdss_connect_work(struct work_struct *work)
@@ -521,6 +525,7 @@
if (gadget->speed != USB_SPEED_SUPER &&
gadget->speed != USB_SPEED_HIGH) {
pr_err("qdss_st_alt: qdss supportes HS or SS only\n");
+ ret = -EINVAL;
goto fail;
}
@@ -562,7 +567,7 @@
qdss->usb_connected = 1;
if (qdss->usb_connected && ch->app_conn)
- schedule_work(&qdss->connect_w);
+ queue_work(qdss->wq, &qdss->connect_w);
return 0;
fail:
@@ -610,7 +615,13 @@
spin_unlock_irqrestore(&d_lock, flags);
return -ENOMEM;
}
-
+ spin_unlock_irqrestore(&d_lock, flags);
+ qdss->wq = create_singlethread_workqueue(name);
+ if (!qdss->wq) {
+ kfree(qdss);
+ return -ENOMEM;
+ }
+ spin_lock_irqsave(&d_lock, flags);
ch = &qdss->ch;
ch->name = name;
list_add_tail(&ch->list, &usb_qdss_ch_list);
@@ -765,6 +776,13 @@
spin_unlock_irqrestore(&d_lock, flags);
return ERR_PTR(-ENOMEM);
}
+ spin_unlock_irqrestore(&d_lock, flags);
+ qdss->wq = create_singlethread_workqueue(name);
+ if (!qdss->wq) {
+ kfree(qdss);
+ return ERR_PTR(-ENOMEM);
+ }
+ spin_lock_irqsave(&d_lock, flags);
ch = &qdss->ch;
list_add_tail(&ch->list, &usb_qdss_ch_list);
} else {
@@ -781,7 +799,7 @@
/* the case USB cabel was connected befor qdss called qdss_open*/
if (qdss->usb_connected == 1)
- schedule_work(&qdss->connect_w);
+ queue_work(qdss->wq, &qdss->connect_w);
return ch;
}
@@ -819,7 +837,7 @@
_ch = list_entry(act, struct usb_qdss_ch, list);
qdss = container_of(_ch, struct f_qdss, ch);
spin_lock_irqsave(&d_lock, flags);
-
+ destroy_workqueue(qdss->wq);
if (!_ch->priv) {
list_del(&_ch->list);
kfree(qdss);
diff --git a/drivers/usb/gadget/f_qdss.h b/drivers/usb/gadget/f_qdss.h
index 93b5b1f..dcc80b7 100644
--- a/drivers/usb/gadget/f_qdss.h
+++ b/drivers/usb/gadget/f_qdss.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, 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
@@ -38,6 +38,7 @@
unsigned int data_enabled:1;
unsigned int ctrl_in_enabled:1;
unsigned int ctrl_out_enabled:1;
+ struct workqueue_struct *wq;
};
#endif
diff --git a/drivers/video/msm/mdss/dsi_panel_v2.c b/drivers/video/msm/mdss/dsi_panel_v2.c
index 441f086..b1a4293 100644
--- a/drivers/video/msm/mdss/dsi_panel_v2.c
+++ b/drivers/video/msm/mdss/dsi_panel_v2.c
@@ -189,13 +189,21 @@
if (enable == 2) {
dsi_panel_power(1);
gpio_request(panel_private->rst_gpio, "panel_reset");
+ gpio_set_value(panel_private->rst_gpio, 1);
if (gpio_is_valid(panel_private->disp_en_gpio)) {
gpio_request(panel_private->disp_en_gpio,
"panel_enable");
+ gpio_set_value(panel_private->disp_en_gpio, 1);
}
if (gpio_is_valid(panel_private->video_mode_gpio)) {
gpio_request(panel_private->video_mode_gpio,
"panel_video_mdoe");
+ if (pdata->panel_info.mipi.mode == DSI_VIDEO_MODE)
+ gpio_set_value(panel_private->video_mode_gpio,
+ 1);
+ else
+ gpio_set_value(panel_private->video_mode_gpio,
+ 0);
}
if (gpio_is_valid(panel_private->te_gpio))
gpio_request(panel_private->te_gpio, "panel_te");
@@ -650,6 +658,7 @@
const char *pdest;
u32 tmp;
int rc;
+ bool cont_splash_enabled = false;
pdest = of_get_property(pdev->dev.of_node,
"qcom,mdss-pan-dest", NULL);
@@ -671,6 +680,17 @@
"qcom,mdss-pan-underflow-clr", &tmp);
panel_data->panel_info.lcdc.underflow_clr = (!rc ? tmp : 0xff);
+ cont_splash_enabled = of_property_read_bool(pdev->dev.of_node,
+ "qcom,cont-splash-enabled");
+ if (!cont_splash_enabled) {
+ pr_debug("%s:%d Continuous splash flag not found.\n",
+ __func__, __LINE__);
+ panel_data->panel_info.cont_splash_enabled = 0;
+ } else {
+ pr_debug("%s:%d Continuous splash flag enabled.\n",
+ __func__, __LINE__);
+ panel_data->panel_info.cont_splash_enabled = 1;
+ }
return rc;
}
diff --git a/drivers/video/msm/mdss/mdp3.c b/drivers/video/msm/mdss/mdp3.c
index f6f722e..e899fa3 100644
--- a/drivers/video/msm/mdss/mdp3.c
+++ b/drivers/video/msm/mdss/mdp3.c
@@ -1173,6 +1173,11 @@
size_t size;
int rc;
+ if (pdata->panel_info.type != MIPI_VIDEO_PANEL) {
+ pr_debug("cmd mode panel, no need to copy splash image\n");
+ return 0;
+ }
+
rgb_size = MDP3_REG_READ(MDP3_REG_DMA_P_SIZE);
stride = MDP3_REG_READ(MDP3_REG_DMA_P_IBUF_Y_STRIDE);
stride = stride & 0x3FFF;
@@ -1210,8 +1215,8 @@
status = MDP3_REG_READ(MDP3_REG_DSI_VIDEO_EN);
rc = status & 0x1;
} else {
- status = MDP3_REG_READ(MDP3_REG_DMA_P_START);
- rc = status & 01;
+ status = MDP3_REG_READ(MDP3_REG_DMA_P_CONFIG);
+ rc = status & 0x80000;
}
mdp3_clk_update(MDP3_CLK_AHB, 0);
@@ -1285,7 +1290,13 @@
return 0;
}
rc = mdp3_continuous_splash_on(pdata);
+ } else {
+ if (mdp3_is_display_on(pdata)) {
+ pr_err("lk continuous splash, but kerenl not\n");
+ rc = mdp3_continuous_splash_on(pdata);
+ }
}
+
return rc;
}
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
index fd7c4aa..0a0c272 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.c
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -88,20 +88,11 @@
return bufq->count;
}
-static void mdp3_dispatch_vsync(struct work_struct *work)
-{
- struct mdp3_session_data *mdp3_session;
- mdp3_session = container_of(work, struct mdp3_session_data, vsync_work);
- if (mdp3_session && mdp3_session->mfd)
- sysfs_notify(&mdp3_session->mfd->fbi->dev->kobj, NULL,
- "vsync_event");
-}
-
void vsync_notify_handler(void *arg)
{
struct mdp3_session_data *session = (struct mdp3_session_data *)arg;
session->vsync_time = ktime_get();
- schedule_work(&session->vsync_work);
+ sysfs_notify_dirent(session->vsync_event_sd);
}
static int mdp3_ctrl_vsync_enable(struct msm_fb_data_type *mfd, int enable)
@@ -484,9 +475,6 @@
mdp3_fbmem_clear();
- if (panel->set_backlight)
- panel->set_backlight(panel, panel->panel_info.bl_max);
-
pr_debug("mdp3_ctrl_on dma start\n");
if (mfd->fbi->screen_base) {
rc = mdp3_session->dma->start(mdp3_session->dma,
@@ -529,18 +517,16 @@
mdp3_histogram_stop(mdp3_session, MDP_BLOCK_DMA_P);
- pr_debug("mdp3_ctrl_off turn panel off\n");
- if (panel->set_backlight)
- panel->set_backlight(panel, 0);
+ rc = mdp3_session->dma->stop(mdp3_session->dma, mdp3_session->intf);
+ if (rc)
+ pr_debug("fail to stop the MDP3 dma\n");
if (panel->event_handler)
rc = panel->event_handler(panel, MDSS_EVENT_PANEL_OFF, NULL);
if (rc)
pr_err("fail to turn off the panel\n");
- rc = mdp3_session->dma->stop(mdp3_session->dma, mdp3_session->intf);
- if (rc)
- pr_err("fail to stop the MDP3 dma\n");
+
mdp3_irq_deregister();
@@ -798,6 +784,64 @@
return ret;
}
+int mdp3_validate_start_req(struct mdp_histogram_start_req *req)
+{
+ if (req->frame_cnt >= MDP_HISTOGRAM_FRAME_COUNT_MAX) {
+ pr_err("%s invalid req frame_cnt\n", __func__);
+ return -EINVAL;
+ }
+ if (req->bit_mask >= MDP_HISTOGRAM_BIT_MASK_MAX) {
+ pr_err("%s invalid req bit mask\n", __func__);
+ return -EINVAL;
+ }
+ if (req->block != MDP_BLOCK_DMA_P ||
+ req->num_bins != MDP_HISTOGRAM_BIN_NUM) {
+ pr_err("mdp3_histogram_start invalid request\n");
+ return -EINVAL;
+ }
+ return 0;
+}
+
+int mdp3_validate_scale_config(struct mdp_bl_scale_data *data)
+{
+ if (data->scale > MDP_HISTOGRAM_BL_SCALE_MAX) {
+ pr_err("%s invalid bl_scale\n", __func__);
+ return -EINVAL;
+ }
+ if (data->min_lvl > MDP_HISTOGRAM_BL_LEVEL_MAX) {
+ pr_err("%s invalid bl_min_lvl\n", __func__);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+int mdp3_validate_csc_data(struct mdp_csc_cfg_data *data)
+{
+ int i;
+ for (i = 0; i < 9; i++) {
+ if (data->csc_data.csc_mv[i] >=
+ MDP_HISTOGRAM_CSC_MATRIX_MAX)
+ return -EINVAL;
+ }
+ for (i = 0; i < 3; i++) {
+ if (data->csc_data.csc_pre_bv[i] >=
+ MDP_HISTOGRAM_CSC_VECTOR_MAX)
+ return -EINVAL;
+ if (data->csc_data.csc_post_bv[i] >=
+ MDP_HISTOGRAM_CSC_VECTOR_MAX)
+ return -EINVAL;
+ }
+ for (i = 0; i < 6; i++) {
+ if (data->csc_data.csc_pre_lv[i] >=
+ MDP_HISTOGRAM_CSC_VECTOR_MAX)
+ return -EINVAL;
+ if (data->csc_data.csc_post_lv[i] >=
+ MDP_HISTOGRAM_CSC_VECTOR_MAX)
+ return -EINVAL;
+ }
+ return 0;
+}
+
static int mdp3_histogram_start(struct mdp3_session_data *session,
struct mdp_histogram_start_req *req)
{
@@ -805,11 +849,10 @@
struct mdp3_dma_histogram_config histo_config;
pr_debug("mdp3_histogram_start\n");
- if (req->block != MDP_BLOCK_DMA_P ||
- req->num_bins != MDP_HISTOGRAM_BIN_NUM) {
- pr_err("mdp3_histogram_start invalid request\n");
- return -EINVAL;
- }
+
+ ret = mdp3_validate_start_req(req);
+ if (ret)
+ return ret;
if (!session->dma->histo_op ||
!session->dma->config_histo) {
@@ -1009,10 +1052,20 @@
switch (mdp_pp.op) {
case mdp_bl_scale_cfg:
+ ret = mdp3_validate_scale_config(&mdp_pp.data.bl_scale_data);
+ if (ret) {
+ pr_err("%s: invalid scale config\n", __func__);
+ break;
+ }
ret = mdp3_bl_scale_config(mfd, (struct mdp_bl_scale_data *)
&mdp_pp.data.bl_scale_data);
break;
case mdp_op_csc_cfg:
+ ret = mdp3_validate_csc_data(&(mdp_pp.data.csc_cfg_data));
+ if (ret) {
+ pr_err("%s: invalid csc data\n", __func__);
+ break;
+ }
ret = mdp3_csc_config(mdp3_session,
&(mdp_pp.data.csc_cfg_data));
break;
@@ -1244,7 +1297,6 @@
}
memset(mdp3_session, 0, sizeof(struct mdp3_session_data));
mutex_init(&mdp3_session->lock);
- INIT_WORK(&mdp3_session->vsync_work, mdp3_dispatch_vsync);
mutex_init(&mdp3_session->histo_lock);
mdp3_session->dma = mdp3_get_dma_pipe(MDP3_DMA_CAP_ALL);
if (!mdp3_session->dma) {
@@ -1270,6 +1322,7 @@
goto init_done;
}
+ mdp3_session->dma->output_config.out_sel = intf_type;
mdp3_session->mfd = mfd;
mdp3_session->panel = dev_get_platdata(&mfd->pdev->dev);
mdp3_session->status = 0;
@@ -1291,6 +1344,14 @@
goto init_done;
}
+ mdp3_session->vsync_event_sd = sysfs_get_dirent(dev->kobj.sd, NULL,
+ "vsync_event");
+ if (!mdp3_session->vsync_event_sd) {
+ pr_err("vsync_event sysfs lookup failed\n");
+ rc = -ENODEV;
+ goto init_done;
+ }
+
kobject_uevent(&dev->kobj, KOBJ_ADD);
pr_debug("vsync kobject_uevent(KOBJ_ADD)\n");
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.h b/drivers/video/msm/mdss/mdp3_ctrl.h
index 9ea1c91..eb32797 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.h
+++ b/drivers/video/msm/mdss/mdp3_ctrl.h
@@ -43,10 +43,10 @@
ktime_t vsync_time;
struct timer_list vsync_timer;
int vsync_period;
+ struct sysfs_dirent *vsync_event_sd;
struct mdp_overlay overlay;
struct mdp3_buffer_queue bufq_in;
struct mdp3_buffer_queue bufq_out;
- struct work_struct vsync_work;
int histo_status;
struct mutex histo_lock;
int lut_sel;
diff --git a/drivers/video/msm/mdss/mdp3_dma.c b/drivers/video/msm/mdss/mdp3_dma.c
index c461887..f4421f2 100644
--- a/drivers/video/msm/mdss/mdp3_dma.c
+++ b/drivers/video/msm/mdss/mdp3_dma.c
@@ -503,7 +503,7 @@
struct mdp3_dma_histogram_config *histo_config)
{
unsigned long flag;
- u32 histo_bit_mask, histo_control;
+ u32 histo_bit_mask = 0, histo_control = 0;
u32 histo_isr_mask = MDP3_DMA_P_HIST_INTR_HIST_DONE_BIT |
MDP3_DMA_P_HIST_INTR_RESET_DONE_BIT;
@@ -639,7 +639,7 @@
return ret;
if (dma->histo_state != MDP3_DMA_HISTO_STATE_READY) {
- pr_err("mdp3_dmap_histo_get after dma shut down\n");
+ pr_debug("mdp3_dmap_histo_get after dma shut down\n");
return -EPERM;
}
@@ -702,9 +702,6 @@
unsigned long flag;
int ret;
- if (dma->histo_state == MDP3_DMA_HISTO_STATE_START)
- return -EINVAL;
-
spin_lock_irqsave(&dma->histo_lock, flag);
init_completion(&dma->histo_comp);
diff --git a/drivers/video/msm/mdss/mdp3_dma.h b/drivers/video/msm/mdss/mdp3_dma.h
index 732e740..6983e55 100644
--- a/drivers/video/msm/mdss/mdp3_dma.h
+++ b/drivers/video/msm/mdss/mdp3_dma.h
@@ -16,6 +16,12 @@
#include <linux/sched.h>
+#define MDP_HISTOGRAM_BL_SCALE_MAX 1024
+#define MDP_HISTOGRAM_BL_LEVEL_MAX 255
+#define MDP_HISTOGRAM_FRAME_COUNT_MAX 0x20
+#define MDP_HISTOGRAM_BIT_MASK_MAX 0x4
+#define MDP_HISTOGRAM_CSC_MATRIX_MAX 0x2000
+#define MDP_HISTOGRAM_CSC_VECTOR_MAX 0x200
#define MDP_HISTOGRAM_BIN_NUM 32
#define MDP_LUT_SIZE 256
diff --git a/drivers/video/msm/mdss/mdp3_ppp.c b/drivers/video/msm/mdss/mdp3_ppp.c
index 924ec5a..8e1dd66 100644
--- a/drivers/video/msm/mdss/mdp3_ppp.c
+++ b/drivers/video/msm/mdss/mdp3_ppp.c
@@ -344,7 +344,7 @@
int mdp3_ppp_turnon(struct msm_fb_data_type *mfd, int on_off)
{
struct mdss_panel_info *panel_info = mfd->panel_info;
- int ab = 0, ib = 0;
+ uint64_t ab = 0, ib = 0;
int rate = 0;
if (on_off) {
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 717241d..91257f2 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -39,6 +39,7 @@
#define MAX_DOWNSCALE_RATIO 4
#define MAX_UPSCALE_RATIO 20
#define MAX_DECIMATION 4
+#define MDP_MIN_VBP 4
#define C3_ALPHA 3 /* alpha */
#define C2_R_Cr 2 /* R/Cr */
@@ -364,6 +365,7 @@
struct mdss_overlay_private {
int vsync_pending;
ktime_t vsync_time;
+ struct sysfs_dirent *vsync_event_sd;
int borderfill_enable;
int overlay_play_enable;
int hw_refresh;
@@ -376,7 +378,6 @@
struct list_head overlay_list;
struct list_head pipes_used;
struct list_head pipes_cleanup;
- struct work_struct vsync_work;
bool mixer_swap;
};
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index edd4c19..4a426cf 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -242,6 +242,7 @@
u32 *clk_rate)
{
struct mdss_mdp_pipe *pipe;
+ struct mdss_panel_info *pinfo = NULL;
int fps = DEFAULT_FRAME_RATE;
u32 v_total;
int i;
@@ -252,22 +253,21 @@
*clk_rate = 0;
if (!mixer->rotator_mode) {
- int is_writeback = false;
if (mixer->type == MDSS_MDP_MIXER_TYPE_INTF) {
- struct mdss_panel_info *pinfo;
pinfo = &mixer->ctl->panel_data->panel_info;
fps = mdss_panel_get_framerate(pinfo);
v_total = mdss_panel_get_vtotal(pinfo);
if (pinfo->type == WRITEBACK_PANEL)
- is_writeback = true;
+ pinfo = NULL;
} else {
v_total = mixer->height;
-
- is_writeback = true;
}
*clk_rate = mixer->width * v_total * fps;
- if (is_writeback) {
+ if (pinfo && pinfo->lcdc.v_back_porch < MDP_MIN_VBP)
+ *clk_rate = MDSS_MDP_CLK_FUDGE_FACTOR(*clk_rate);
+
+ if (!pinfo) {
/* perf for bus writeback */
*bus_ab_quota = fps * mixer->width * mixer->height * 3;
*bus_ab_quota >>= MDSS_MDP_BUS_FACTOR_SHIFT;
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index 6252e17..938cb1f 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -1351,15 +1351,6 @@
mutex_unlock(&mdp5_data->ov_lock);
}
-static void mdss_mdp_overlay_dispatch_vsync(struct work_struct *work)
-{
- struct mdss_overlay_private *mdp5_data;
- mdp5_data = container_of(work, struct mdss_overlay_private, vsync_work);
- if (mdp5_data->ctl && mdp5_data->ctl->mfd)
- sysfs_notify(&mdp5_data->ctl->mfd->fbi->dev->kobj, NULL,
- "vsync_event");
-}
-
/* function is called in irq context should have minimum processing */
static void mdss_mdp_overlay_handle_vsync(struct mdss_mdp_ctl *ctl,
ktime_t t)
@@ -1376,7 +1367,7 @@
pr_debug("vsync on fb%d play_cnt=%d\n", mfd->index, ctl->play_cnt);
mdp5_data->vsync_time = t;
- schedule_work(&mdp5_data->vsync_work);
+ sysfs_notify_dirent(mdp5_data->vsync_event_sd);
}
int mdss_mdp_overlay_vsync_ctrl(struct msm_fb_data_type *mfd, int en)
@@ -2130,7 +2121,6 @@
INIT_LIST_HEAD(&mdp5_data->pipes_used);
INIT_LIST_HEAD(&mdp5_data->pipes_cleanup);
- INIT_WORK(&mdp5_data->vsync_work, mdss_mdp_overlay_dispatch_vsync);
mutex_init(&mdp5_data->ov_lock);
mdp5_data->hw_refresh = true;
mdp5_data->overlay_play_enable = true;
@@ -2153,6 +2143,14 @@
goto init_fail;
}
+ mdp5_data->vsync_event_sd = sysfs_get_dirent(dev->kobj.sd, NULL,
+ "vsync_event");
+ if (!mdp5_data->vsync_event_sd) {
+ pr_err("vsync_event sysfs lookup failed\n");
+ rc = -ENODEV;
+ goto init_fail;
+ }
+
pm_runtime_set_suspended(&mfd->pdev->dev);
pm_runtime_enable(&mfd->pdev->dev);
diff --git a/drivers/video/msm/mdss/mhl_sii8334.c b/drivers/video/msm/mdss/mhl_sii8334.c
index c66d50d..a759e86 100644
--- a/drivers/video/msm/mdss/mhl_sii8334.c
+++ b/drivers/video/msm/mdss/mhl_sii8334.c
@@ -357,14 +357,20 @@
static int mhl_sii_wait_for_rgnd(struct mhl_tx_ctrl *mhl_ctrl)
{
int timeout;
- /* let isr handle RGND interrupt */
+
pr_debug("%s:%u\n", __func__, __LINE__);
INIT_COMPLETION(mhl_ctrl->rgnd_done);
+ /*
+ * after toggling reset line and enabling disc
+ * tx can take a while to generate intr
+ */
timeout = wait_for_completion_interruptible_timeout
- (&mhl_ctrl->rgnd_done, HZ);
+ (&mhl_ctrl->rgnd_done, HZ * 3);
if (!timeout) {
- /* most likely nothing plugged in USB */
- /* USB HOST connected or already in USB mode */
+ /*
+ * most likely nothing plugged in USB
+ * USB HOST connected or already in USB mode
+ */
pr_warn("%s:%u timedout\n", __func__, __LINE__);
return -ENODEV;
}
@@ -380,9 +386,25 @@
struct i2c_client *client = mhl_ctrl->i2c_handle;
unsigned long flags;
- enable_irq(client->irq);
+ if (!mhl_ctrl->irq_req_done) {
+ rc = request_threaded_irq(mhl_ctrl->i2c_handle->irq, NULL,
+ &mhl_tx_isr,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ client->dev.driver->name, mhl_ctrl);
+ if (rc) {
+ pr_err("request_threaded_irq failed, status: %d\n",
+ rc);
+ return -EINVAL;
+ } else {
+ pr_debug("request_threaded_irq succeeded\n");
+ mhl_ctrl->irq_req_done = true;
+ }
+ } else {
+ enable_irq(client->irq);
+ }
+
/* wait for i2c interrupt line to be activated */
- msleep(300);
+ msleep(100);
if (id) {
/* When MHL cable is disconnected we get a sii8334
@@ -413,8 +435,10 @@
/* chipset PR recommends waiting for at least 100 ms
* the chipset needs longer to come out of D3 state.
*/
- msleep(300);
+ msleep(100);
mhl_init_reg_settings(mhl_ctrl, true);
+ /* allow tx to enable dev disc after D3 state */
+ msleep(100);
rc = mhl_sii_wait_for_rgnd(mhl_ctrl);
} else {
if (mhl_ctrl->cur_state == POWER_STATE_D3) {
@@ -493,6 +517,10 @@
uint8_t i;
struct i2c_client *client = mhl_ctrl->i2c_handle;
+ /* Read the chip rev ID */
+ mhl_ctrl->chip_rev_id = MHL_SII_PAGE0_RD(0x04);
+ pr_debug("MHL: chip rev ID read=[%x]\n", mhl_ctrl->chip_rev_id);
+
/*
* REG_SRST
*/
@@ -1428,40 +1456,6 @@
return IRQ_HANDLED;
}
-static int mhl_tx_chip_init(struct mhl_tx_ctrl *mhl_ctrl)
-{
- uint8_t chip_rev_id = 0x00;
- struct i2c_client *client = mhl_ctrl->i2c_handle;
- unsigned long flags;
-
-
- spin_lock_irqsave(&mhl_ctrl->lock, flags);
- mhl_ctrl->dwnstream_hpd = 0;
- mhl_ctrl->tx_powered_off = false;
- spin_unlock_irqrestore(&mhl_ctrl->lock, flags);
-
- /* Reset the TX chip */
- mhl_sii_reset_pin(mhl_ctrl, 0);
- msleep(20);
- mhl_sii_reset_pin(mhl_ctrl, 1);
- /* TX PR-guide requires a 100 ms wait here */
- msleep(100);
-
- /* Read the chip rev ID */
- chip_rev_id = MHL_SII_PAGE0_RD(0x04);
- pr_debug("MHL: chip rev ID read=[%x]\n", chip_rev_id);
- mhl_ctrl->chip_rev_id = chip_rev_id;
-
- /*
- * Need to disable MHL discovery if
- * MHL-USB handshake is implemented
- */
- mhl_init_reg_settings(mhl_ctrl, true);
- switch_mode(mhl_ctrl, POWER_STATE_D3, true);
- pr_debug("%s:%u: power_down\n", __func__, __LINE__);
- mhl_tx_down(mhl_ctrl);
- return 0;
-}
static int mhl_sii_reg_config(struct i2c_client *client, bool enable)
{
@@ -1791,30 +1785,12 @@
}
}
- rc = mhl_tx_chip_init(mhl_ctrl);
- if (rc) {
- pr_err("%s: tx chip init failed [%d]\n",
- __func__, rc);
- goto failed_probe;
- }
+ mhl_ctrl->dwnstream_hpd = 0;
+ mhl_ctrl->tx_powered_off = false;
+
init_completion(&mhl_ctrl->rgnd_done);
- pr_debug("%s: IRQ from GPIO INTR = %d\n",
- __func__, mhl_ctrl->i2c_handle->irq);
- pr_debug("%s: Driver name = [%s]\n", __func__,
- client->dev.driver->name);
- rc = request_threaded_irq(mhl_ctrl->i2c_handle->irq, NULL,
- &mhl_tx_isr,
- IRQF_TRIGGER_LOW | IRQF_ONESHOT,
- client->dev.driver->name, mhl_ctrl);
- if (rc) {
- pr_err("request_threaded_irq failed, status: %d\n",
- rc);
- goto failed_probe;
- } else {
- pr_debug("request_threaded_irq succeeded\n");
- }
mhl_ctrl->mhl_psy.name = "ext-vbus";
mhl_ctrl->mhl_psy.type = POWER_SUPPLY_TYPE_USB_DCP;
@@ -1940,15 +1916,21 @@
#if defined(CONFIG_PM) || defined(CONFIG_PM_SLEEP)
static int mhl_i2c_suspend_sub(struct i2c_client *client)
{
- enable_irq_wake(client->irq);
- disable_irq(client->irq);
+ struct mhl_tx_ctrl *mhl_ctrl = i2c_get_clientdata(client);
+
+ if (mhl_ctrl->irq_req_done) {
+ enable_irq_wake(client->irq);
+ disable_irq(client->irq);
+ }
return 0;
}
static int mhl_i2c_resume_sub(struct i2c_client *client)
{
- disable_irq_wake(client->irq);
- enable_irq(client->irq);
+ struct mhl_tx_ctrl *mhl_ctrl = i2c_get_clientdata(client);
+
+ if (mhl_ctrl->irq_req_done)
+ disable_irq_wake(client->irq);
return 0;
}
#endif /* defined(CONFIG_PM) || defined(CONFIG_PM_SLEEP) */
diff --git a/include/linux/input/ft5x06_ts.h b/include/linux/input/ft5x06_ts.h
index af8c332..4da38a4 100644
--- a/include/linux/input/ft5x06_ts.h
+++ b/include/linux/input/ft5x06_ts.h
@@ -23,7 +23,20 @@
#define FT5X36_ID 0x14
#define FT6X06_ID 0x06
+struct fw_upgrade_info {
+ bool auto_cal;
+ u16 delay_aa;
+ u16 delay_55;
+ u8 upgrade_id_1;
+ u8 upgrade_id_2;
+ u16 delay_readid;
+ u16 delay_erase_flash;
+};
+
struct ft5x06_ts_platform_data {
+ struct fw_upgrade_info info;
+ const char *name;
+ const char *fw_name;
u32 irqflags;
u32 irq_gpio;
u32 irq_gpio_flags;
@@ -38,6 +51,10 @@
u32 panel_miny;
u32 panel_maxx;
u32 panel_maxy;
+ u32 group_id;
+ u32 hard_rst_dly;
+ u32 soft_rst_dly;
+ u32 num_max_touches;
bool no_force_update;
bool i2c_pull_up;
int (*power_init) (bool);
diff --git a/include/linux/input/synaptics_dsx.h b/include/linux/input/synaptics_dsx.h
index 73016d6..5df022e 100644
--- a/include/linux/input/synaptics_dsx.h
+++ b/include/linux/input/synaptics_dsx.h
@@ -35,8 +35,11 @@
* struct synaptics_rmi4_platform_data - rmi4 platform data
* @x_flip: x flip flag
* @y_flip: y flip flag
+ * @i2c_pull_up: pull up i2c bus with regulator
+ * @power_down_enable: enable complete regulator shutdown in suspend
* @irq_gpio: attention interrupt gpio
* @irq_flags: flags used by the irq
+ * @reset_flags: flags used by reset line
* @reset_gpio: reset gpio
* @panel_x: panel maximum values on the x
* @panel_y: panel maximum values on the y
@@ -47,6 +50,8 @@
bool x_flip;
bool y_flip;
bool i2c_pull_up;
+ bool power_down_enable;
+ bool disable_gpios;
unsigned irq_gpio;
u32 irq_flags;
u32 reset_flags;
diff --git a/include/linux/mhl_8334.h b/include/linux/mhl_8334.h
index d1ee11c..71dec42 100644
--- a/include/linux/mhl_8334.h
+++ b/include/linux/mhl_8334.h
@@ -165,6 +165,7 @@
bool tx_powered_off;
uint8_t dwnstream_hpd;
bool mhl_det_discon;
+ bool irq_req_done;
};
int mhl_i2c_reg_read(struct i2c_client *client,
diff --git a/include/linux/msm_thermal.h b/include/linux/msm_thermal.h
index 2c1fa11..2ca9900 100644
--- a/include/linux/msm_thermal.h
+++ b/include/linux/msm_thermal.h
@@ -23,6 +23,8 @@
uint32_t freq_control_mask;
int32_t core_limit_temp_degC;
int32_t core_temp_hysteresis_degC;
+ int32_t hotplug_temp_degC;
+ int32_t hotplug_temp_hysteresis_degC;
uint32_t core_control_mask;
int32_t vdd_rstr_temp_degC;
int32_t vdd_rstr_temp_hyst_degC;
diff --git a/include/linux/qpnp/qpnp-adc.h b/include/linux/qpnp/qpnp-adc.h
index 4f39eaa..9a49c5e 100644
--- a/include/linux/qpnp/qpnp-adc.h
+++ b/include/linux/qpnp/qpnp-adc.h
@@ -218,6 +218,8 @@
* Uses a mapping table with 150K pullup.
* %SCALE_QRD_BATT_THERM: Conversion to temperature(decidegC) based on
* btm parameters.
+ * %SCALE_QRD_SKUAA_BATT_THERM: Conversion to temperature(decidegC) based on
+ * btm parametersi for SKUAA.
* %SCALE_NONE: Do not use this scaling type.
*/
enum qpnp_adc_scale_fn_type {
@@ -228,6 +230,7 @@
SCALE_XOTHERM,
SCALE_THERM_150K_PULLUP,
SCALE_QRD_BATT_THERM,
+ SCALE_QRD_SKUAA_BATT_THERM,
SCALE_NONE,
};
@@ -1121,6 +1124,23 @@
const struct qpnp_vadc_chan_properties *chan_prop,
struct qpnp_vadc_result *chan_rslt);
/**
+ * qpnp_adc_scale_qrd_skuaa_batt_therm() - Scales the pre-calibrated digital output
+ * of an ADC to the ADC reference and compensates for the
+ * gain and offset. Returns the temperature in decidegC.
+ * @dev: Structure device for qpnp vadc
+ * @adc_code: pre-calibrated digital ouput of the ADC.
+ * @adc_prop: adc properties of the pm8xxx adc such as bit resolution,
+ * reference voltage.
+ * @chan_prop: individual channel properties to compensate the i/p scaling,
+ * slope and offset.
+ * @chan_rslt: physical result to be stored.
+ */
+int32_t qpnp_adc_scale_qrd_skuaa_batt_therm(struct qpnp_vadc_chip *dev,
+ int32_t adc_code,
+ const struct qpnp_adc_properties *adc_prop,
+ const struct qpnp_vadc_chan_properties *chan_prop,
+ struct qpnp_vadc_result *chan_rslt);
+/**
* qpnp_adc_scale_batt_id() - Scales the pre-calibrated digital output
* of an ADC to the ADC reference and compensates for the
* gain and offset.
@@ -1366,7 +1386,13 @@
struct qpnp_vadc_chip *vadc, int32_t adc_code,
const struct qpnp_adc_properties *adc_prop,
const struct qpnp_vadc_chan_properties *chan_prop,
- struct qpnp_vadc_result *chan_rslt);
+ struct qpnp_vadc_result *chan_rslt)
+{ return -ENXIO; }
+static inline int32_t qpnp_adc_scale_qrd_skuaa_batt_therm(
+ struct qpnp_vadc_chip *vadc, int32_t adc_code,
+ const struct qpnp_adc_properties *adc_prop,
+ const struct qpnp_vadc_chan_properties *chan_prop,
+ struct qpnp_vadc_result *chan_rslt)
{ return -ENXIO; }
static inline int32_t qpnp_adc_scale_batt_id(struct qpnp_vadc_chip *vadc,
int32_t adc_code,
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index f740640..1bb3b06 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -97,6 +97,27 @@
((long)t-2732+5)/10 : ((long)t-2732-5)/10)
#define CELSIUS_TO_KELVIN(t) ((t)*10+2732)
+struct sensor_threshold {
+ int temp;
+ enum thermal_trip_type trip;
+ int (*notify)(enum thermal_trip_type type, int temp, void *data);
+ void *data;
+ struct list_head list;
+};
+
+struct sensor_info {
+ uint32_t sensor_id;
+ struct thermal_zone_device *tz;
+ int threshold_min;
+ int threshold_max;
+ int max_idx;
+ int min_idx;
+ struct list_head sensor_list;
+ struct list_head threshold_list;
+ struct mutex lock;
+ struct work_struct work;
+};
+
struct thermal_zone_device {
int id;
char type[THERMAL_NAME_LENGTH];
@@ -116,6 +137,8 @@
struct mutex lock; /* protect cooling devices list */
struct list_head node;
struct delayed_work poll_queue;
+ struct sensor_threshold tz_threshold[2];
+ struct sensor_info sensor;
};
/* Adding event notification support elements */
#define THERMAL_GENL_FAMILY_NAME "thermal_event"
@@ -163,6 +186,12 @@
const struct thermal_cooling_device_ops *);
void thermal_cooling_device_unregister(struct thermal_cooling_device *);
+int sensor_get_id(char *name);
+int sensor_set_trip(uint32_t sensor_id, struct sensor_threshold *threshold);
+int sensor_cancel_trip(uint32_t sensor_id, struct sensor_threshold *threshold);
+int thermal_sensor_trip(struct thermal_zone_device *tz,
+ enum thermal_trip_type trip, unsigned long temp);
+
#ifdef CONFIG_NET
extern int thermal_generate_netlink_event(u32 orig, enum events event);
#else
diff --git a/kernel/exit.c b/kernel/exit.c
index f01ca74..6096e80 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -880,7 +880,6 @@
static DEFINE_SPINLOCK(low_water_lock);
static int lowest_to_date = THREAD_SIZE;
unsigned long free;
- int islower = false;
free = stack_not_used(current);
@@ -889,16 +888,12 @@
spin_lock(&low_water_lock);
if (free < lowest_to_date) {
- lowest_to_date = free;
- islower = true;
- }
- spin_unlock(&low_water_lock);
-
- if (islower) {
printk(KERN_WARNING "%s used greatest stack depth: %lu bytes "
"left\n",
current->comm, free);
+ lowest_to_date = free;
}
+ spin_unlock(&low_water_lock);
}
#else
static inline void check_stack_usage(void) {}
diff --git a/sound/soc/codecs/msm8x10-wcd.c b/sound/soc/codecs/msm8x10-wcd.c
index 170dbe7..66b0094 100644
--- a/sound/soc/codecs/msm8x10-wcd.c
+++ b/sound/soc/codecs/msm8x10-wcd.c
@@ -126,6 +126,16 @@
ON_DEMAND_SUPPLIES_MAX,
};
+/*
+ * The delay list is per codec HW specification.
+ * Please add delay in the list in the future instead
+ * of magic number
+ */
+enum {
+ CODEC_DELAY_1_MS = 1000,
+ CODEC_DELAY_1_1_MS = 1100,
+};
+
struct hpf_work {
struct msm8x10_wcd_priv *msm8x10_wcd;
u32 decimator;
@@ -1148,13 +1158,8 @@
"ZERO", "ADC1", "ADC2", "DMIC1", "DMIC2"
};
-static const char * const anc_mux_text[] = {
- "ZERO", "ADC1", "ADC2", "ADC3", "ADC4", "ADC5", "ADC6", "ADC_MB",
- "RSVD_1", "DMIC1", "DMIC2", "DMIC3", "DMIC4", "DMIC5", "DMIC6"
-};
-
-static const char * const anc1_fb_mux_text[] = {
- "ZERO", "EAR_HPH_L", "EAR_LINE_1",
+static const char * const adc2_mux_text[] = {
+ "ZERO", "INP2", "INP3"
};
static const char * const iir1_inp1_text[] = {
@@ -1212,6 +1217,9 @@
SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_CONN_LO_DAC_CTL, 0, 3,
rx_rdac4_text);
+static const struct soc_enum adc2_enum =
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(adc2_mux_text), adc2_mux_text);
+
static const struct snd_kcontrol_new rx_mix1_inp1_mux =
SOC_DAPM_ENUM("RX1 MIX1 INP1 Mux", rx_mix1_inp1_chain_enum);
@@ -1242,6 +1250,9 @@
static const struct snd_kcontrol_new rx_dac4_mux =
SOC_DAPM_ENUM("RDAC4 MUX Mux", rx_rdac4_enum);
+static const struct snd_kcontrol_new tx_adc2_mux =
+ SOC_DAPM_ENUM("ADC2 MUX Mux", adc2_enum);
+
static int msm8x10_wcd_put_dec_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -1370,7 +1381,8 @@
if (w->reg == MSM8X10_WCD_A_TX_1_EN)
init_bit_shift = 7;
- else if (w->reg == MSM8X10_WCD_A_TX_2_EN)
+ else if ((w->reg == MSM8X10_WCD_A_TX_2_EN) ||
+ (w->reg == MSM8X10_WCD_A_TX_3_EN))
init_bit_shift = 6;
else {
dev_err(codec->dev, "%s: Error, invalid adc register\n",
@@ -1383,9 +1395,11 @@
msm8x10_wcd_codec_enable_adc_block(codec, 1);
snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift,
1 << init_bit_shift);
+ usleep_range(CODEC_DELAY_1_MS, CODEC_DELAY_1_1_MS);
break;
case SND_SOC_DAPM_POST_PMU:
snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift, 0x00);
+ usleep_range(CODEC_DELAY_1_MS, CODEC_DELAY_1_1_MS);
break;
case SND_SOC_DAPM_POST_PMD:
msm8x10_wcd_codec_enable_adc_block(codec, 0);
@@ -1930,9 +1944,14 @@
{"DEC2 MUX", "ADC2", "ADC2"},
{"DEC2 MUX", NULL, "CDC_CONN"},
+ {"ADC2", NULL, "ADC2 MUX"},
+ {"ADC2 MUX", "INP2", "ADC2_INP2"},
+ {"ADC2 MUX", "INP3", "ADC2_INP3"},
+
/* ADC Connections */
{"ADC1", NULL, "AMIC1"},
- {"ADC2", NULL, "AMIC2"},
+ {"ADC2_INP2", NULL, "AMIC2"},
+ {"ADC2_INP3", NULL, "AMIC3"},
{"IIR1", NULL, "IIR1 INP1 MUX"},
{"IIR1 INP1 MUX", "DEC1", "DEC1 MUX"},
@@ -2406,9 +2425,17 @@
SND_SOC_DAPM_ADC_E("ADC1", NULL, MSM8X10_WCD_A_TX_1_EN, 7, 0,
msm8x10_wcd_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_ADC_E("ADC2", NULL, MSM8X10_WCD_A_TX_2_EN, 7, 0,
+ SND_SOC_DAPM_ADC_E("ADC2_INP2", NULL, MSM8X10_WCD_A_TX_2_EN, 7, 0,
msm8x10_wcd_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_ADC_E("ADC2_INP3", NULL, MSM8X10_WCD_A_TX_3_EN, 7, 0,
+ msm8x10_wcd_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MIXER("ADC2", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_MUX("ADC2 MUX", SND_SOC_NOPM, 0, 0,
+ &tx_adc2_mux),
SND_SOC_DAPM_MICBIAS("MIC BIAS External", MSM8X10_WCD_A_MICB_1_CTL,
7, 0),
diff --git a/sound/soc/codecs/wcd9306.c b/sound/soc/codecs/wcd9306.c
index af2c53e..fcc264c 100644
--- a/sound/soc/codecs/wcd9306.c
+++ b/sound/soc/codecs/wcd9306.c
@@ -24,6 +24,7 @@
#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
#include <linux/mfd/wcd9xxx/wcd9306_registers.h>
#include <linux/mfd/wcd9xxx/pdata.h>
+#include <linux/regulator/consumer.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
@@ -189,6 +190,12 @@
0, /* AIF1_CAP */
};
+enum {
+ CP_REG_BUCK = 0,
+ CP_REG_BHELPER,
+ CP_REG_MAX,
+};
+
struct tapan_priv {
struct snd_soc_codec *codec;
u32 adc_count;
@@ -224,6 +231,9 @@
/* class h specific data */
struct wcd9xxx_clsh_cdc_data clsh_d;
+
+ /* pointers to regulators required for chargepump */
+ struct regulator *cp_regulators[CP_REG_MAX];
};
static const u32 comp_shift[] = {
@@ -758,6 +768,9 @@
int i;
for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
+ if (pdata->regulator[i].name == NULL)
+ continue;
+
if (!strncmp(pdata->regulator[i].name,
WCD9XXX_SUPPLY_BUCK_NAME,
sizeof(WCD9XXX_SUPPLY_BUCK_NAME))) {
@@ -768,8 +781,13 @@
buck_volt = pdata->regulator[i].min_uV;
break;
}
+ dev_err(codec->dev,
+ "%s: Failed to find regulator for %s\n",
+ __func__, WCD9XXX_SUPPLY_BUCK_NAME);
}
- pr_debug("%s: S4 voltage requested is %d\n", __func__, buck_volt);
+ dev_dbg(codec->dev,
+ "%s: S4 voltage requested is %d\n",
+ __func__, buck_volt);
return buck_volt;
}
@@ -2563,6 +2581,8 @@
{"EAR PA", NULL, "EAR_PA_MIXER"},
{"EAR_PA_MIXER", NULL, "DAC1"},
{"DAC1", NULL, "RX_BIAS"},
+ {"DAC1", NULL, "CDC_CP_VDD"},
+
{"ANC EAR", NULL, "ANC EAR PA"},
{"ANC EAR PA", NULL, "EAR_PA_MIXER"},
@@ -2576,10 +2596,12 @@
{"HPHL", NULL, "HPHL_PA_MIXER"},
{"HPHL_PA_MIXER", NULL, "HPHL DAC"},
{"HPHL DAC", NULL, "RX_BIAS"},
+ {"HPHL DAC", NULL, "CDC_CP_VDD"},
{"HPHR", NULL, "HPHR_PA_MIXER"},
{"HPHR_PA_MIXER", NULL, "HPHR DAC"},
{"HPHR DAC", NULL, "RX_BIAS"},
+ {"HPHR DAC", NULL, "CDC_CP_VDD"},
{"ANC HEADPHONE", NULL, "ANC HPHL"},
{"ANC HEADPHONE", NULL, "ANC HPHR"},
@@ -2641,6 +2663,8 @@
{"LINEOUT1 DAC", NULL, "RX_BIAS"},
{"LINEOUT2 DAC", NULL, "RX_BIAS"},
+ {"LINEOUT1 DAC", NULL, "CDC_CP_VDD"},
+ {"LINEOUT2 DAC", NULL, "CDC_CP_VDD"},
{"RX1 MIX1", NULL, "COMP1_CLK"},
{"RX2 MIX1", NULL, "COMP1_CLK"},
@@ -3766,6 +3790,59 @@
return ret;
}
+static int tapan_codec_chargepump_vdd_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct tapan_priv *priv = snd_soc_codec_get_drvdata(codec);
+ int ret = 0, i;
+
+ pr_info("%s: event = %d\n", __func__, event);
+
+
+ if (!priv->cp_regulators[CP_REG_BUCK]
+ && !priv->cp_regulators[CP_REG_BHELPER]) {
+ pr_err("%s: No power supply defined for ChargePump\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ for (i = 0; i < CP_REG_MAX ; i++) {
+ if (!priv->cp_regulators[i])
+ continue;
+
+ ret = regulator_enable(priv->cp_regulators[i]);
+ if (ret) {
+ pr_err("%s: CP Regulator enable failed, index = %d\n",
+ __func__, i);
+ continue;
+ } else {
+ pr_debug("%s: Enabled CP regulator, index %d\n",
+ __func__, i);
+ }
+ }
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ for (i = 0; i < CP_REG_MAX; i++) {
+ if (!priv->cp_regulators[i])
+ continue;
+
+ ret = regulator_disable(priv->cp_regulators[i]);
+ if (ret) {
+ pr_err("%s: CP Regulator disable failed, index = %d\n",
+ __func__, i);
+ return ret;
+ } else {
+ pr_debug("%s: Disabled CP regulator %d\n",
+ __func__, i);
+ }
+ }
+ break;
+ }
+ return 0;
+}
/* Todo: Have seperate dapm widgets for I2S and Slimbus.
* Might Need to have callbacks registered only for slimbus
@@ -3882,6 +3959,11 @@
tapan_codec_enable_rx_bias, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMD),
+ /* CDC_CP_VDD */
+ SND_SOC_DAPM_SUPPLY("CDC_CP_VDD", SND_SOC_NOPM, 0, 0,
+ tapan_codec_chargepump_vdd_event, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
/*EAR */
SND_SOC_DAPM_PGA_E("EAR PA", TAPAN_A_RX_EAR_EN, 4, 0, NULL, 0,
tapan_codec_enable_ear_pa, SND_SOC_DAPM_POST_PMU |
@@ -4710,6 +4792,21 @@
return 0;
}
+static struct regulator *tapan_codec_find_regulator(
+ struct snd_soc_codec *codec,
+ const char *name)
+{
+ int i;
+ struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
+
+ for (i = 0; i < core->num_of_supplies; i++) {
+ if (core->supplies[i].supply &&
+ !strcmp(core->supplies[i].supply, name))
+ return core->supplies[i].consumer;
+ }
+ return NULL;
+}
+
static int tapan_codec_probe(struct snd_soc_codec *codec)
{
struct wcd9xxx *control;
@@ -4752,6 +4849,11 @@
return ret;
}
+ tapan->cp_regulators[CP_REG_BUCK] = tapan_codec_find_regulator(codec,
+ WCD9XXX_SUPPLY_BUCK_NAME);
+ tapan->cp_regulators[CP_REG_BHELPER] = tapan_codec_find_regulator(codec,
+ "cdc-vdd-buckhelper");
+
tapan->clsh_d.buck_mv = tapan_codec_get_buck_mv(codec);
/*
* If 1.8 volts is requested on the vdd_cp line, then
@@ -4860,6 +4962,7 @@
static int tapan_codec_remove(struct snd_soc_codec *codec)
{
struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+ int index = 0;
WCD9XXX_BG_CLK_LOCK(&tapan->resmgr);
atomic_set(&kp_tapan_priv, 0);
@@ -4876,6 +4979,9 @@
/* cleanup resmgr */
wcd9xxx_resmgr_deinit(&tapan->resmgr);
+ for (index = 0; index < CP_REG_MAX; index++)
+ tapan->cp_regulators[index] = NULL;
+
kfree(tapan);
return 0;
}
diff --git a/sound/soc/msm/msm8x10.c b/sound/soc/msm/msm8x10.c
index b49b1e3..e1f1efc 100644
--- a/sound/soc/msm/msm8x10.c
+++ b/sound/soc/msm/msm8x10.c
@@ -52,6 +52,9 @@
static void __iomem *pcbcr;
static void __iomem *prcgr;
+static int msm_sec_mi2s_rx_ch = 1;
+static int msm_pri_mi2s_tx_ch = 1;
+
/*
* There is limitation for the clock root selection from
* either MI2S or DIG_CODEC.
@@ -182,10 +185,43 @@
return 0;
}
+static int msm_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_interval *rate = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_RATE);
+ struct snd_interval *channels = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_CHANNELS);
+
+ pr_debug("%s(): channel:%d\n", __func__, msm_pri_mi2s_tx_ch);
+ rate->min = rate->max = 48000;
+ channels->min = channels->max = msm_sec_mi2s_rx_ch;
+
+ return 0;
+}
+
+static int msm_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_interval *rate = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_RATE);
+ struct snd_interval *channels = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_CHANNELS);
+
+ pr_debug("%s(), channel:%d\n", __func__, msm_pri_mi2s_tx_ch);
+ rate->min = rate->max = 48000;
+ channels->min = channels->max = msm_pri_mi2s_tx_ch;
+
+ return 0;
+}
+
+
static const char *const btsco_rate_text[] = {"8000", "16000"};
static const struct soc_enum msm_btsco_enum[] = {
SOC_ENUM_SINGLE_EXT(2, btsco_rate_text),
};
+static const char *const sec_mi2s_rx_ch_text[] = {"One", "Two"};
+static const char *const pri_mi2s_tx_ch_text[] = {"One", "Two"};
static int msm_btsco_rate_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -215,6 +251,43 @@
return 0;
}
+static int msm_sec_mi2s_rx_ch_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ pr_debug("%s: msm_sec_mi2s_rx_ch = %d\n", __func__,
+ msm_sec_mi2s_rx_ch);
+ ucontrol->value.integer.value[0] = msm_sec_mi2s_rx_ch - 1;
+ return 0;
+}
+
+static int msm_sec_mi2s_rx_ch_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ msm_sec_mi2s_rx_ch = ucontrol->value.integer.value[0] + 1;
+
+ pr_debug("%s: msm_sec_mi2s_rx_ch = %d\n", __func__,
+ msm_sec_mi2s_rx_ch);
+ return 1;
+}
+
+static int msm_pri_mi2s_tx_ch_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ pr_debug("%s: msm_pri_mi2s_tx_ch = %d\n", __func__,
+ msm_pri_mi2s_tx_ch);
+ ucontrol->value.integer.value[0] = msm_pri_mi2s_tx_ch - 1;
+ return 0;
+}
+
+static int msm_pri_mi2s_tx_ch_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ msm_pri_mi2s_tx_ch = ucontrol->value.integer.value[0] + 1;
+
+ pr_debug("%s: msm_pri_mi2s_tx_ch = %d\n", __func__, msm_pri_mi2s_tx_ch);
+ return 1;
+}
+
static int msm_btsco_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
@@ -353,9 +426,18 @@
return ret;
}
+static const struct soc_enum msm_snd_enum[] = {
+ SOC_ENUM_SINGLE_EXT(2, sec_mi2s_rx_ch_text),
+ SOC_ENUM_SINGLE_EXT(2, pri_mi2s_tx_ch_text),
+};
+
static const struct snd_kcontrol_new msm_snd_controls[] = {
SOC_ENUM_EXT("Internal BTSCO SampleRate", msm_btsco_enum[0],
msm_btsco_rate_get, msm_btsco_rate_put),
+ SOC_ENUM_EXT("MI2S_RX Channels", msm_snd_enum[0],
+ msm_sec_mi2s_rx_ch_get, msm_sec_mi2s_rx_ch_put),
+ SOC_ENUM_EXT("MI2S_TX Channels", msm_snd_enum[1],
+ msm_pri_mi2s_tx_ch_get, msm_pri_mi2s_tx_ch_put),
};
static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
@@ -637,7 +719,7 @@
.no_pcm = 1,
.be_id = MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
.init = &msm_audrx_init,
- .be_hw_params_fixup = msm_be_hw_params_fixup,
+ .be_hw_params_fixup = msm_rx_be_hw_params_fixup,
.ops = &msm8x10_mi2s_be_ops,
.ignore_suspend = 1,
},
@@ -650,7 +732,7 @@
.codec_dai_name = "msm8x10_wcd_i2s_tx1",
.no_pcm = 1,
.be_id = MSM_BACKEND_DAI_PRI_MI2S_TX,
- .be_hw_params_fixup = msm_be_hw_params_fixup,
+ .be_hw_params_fixup = msm_tx_be_hw_params_fixup,
.ops = &msm8x10_mi2s_be_ops,
.ignore_suspend = 1,
},