Merge "arm/dt: msm-pm8941: Update VADC channel node property"
diff --git a/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt b/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt
index 203730f..439418d 100644
--- a/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt
+++ b/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt
@@ -13,8 +13,10 @@
Required properties:
- compatible: Must be "qcom,cpr-regulator"
- reg: Register addresses for RBCPR and efuse
-- reg-names: Register names. Must be "rbcpr" and "efuse_phys"
+- reg-names: Register names. Must be "rbcpr", "pvs_efuse"
+ and "cpr_efuse"
- regulator-name: A string used to describe the regulator
+- interrupts: Interrupt line from RBCPR to interrupt controller.
- regulator-min-microvolt: Minimum corner value as min constraint, which
should be 1 for SVS corner
- regulator-max-microvolt: Maximum corner value as max constraint, which
@@ -23,9 +25,6 @@
represent total number of PVS bins. It should
not exceed a maximum of 5 for total number of
32 bins.
-- qcom,efuse-bit-pos: A list of integers whose length must equal
- to qcom,num-efuse-bits and each integer indicates
- bit position in efuse memory from LSB to MSB
- qcom,pvs-bin-process: A list of integers whose length is equal to 2 to
the power of qcom,num-efuse-bits. The location or
0-based index of an element in the list corresponds
@@ -44,8 +43,25 @@
0 (SVS voltage): 1050000 uV
1 (NORMAL voltage): 1150000 uV
2 (TURBO voltage): 1275000 uV
- 3 (SUPER_TURBO voltage): 1275000 uV
- vdd-apc-supply: Regulator to supply VDD APC power
+- qcom,vdd-apc-step-up-limit: Limit of vdd-apc-supply steps for scaling up.
+- qcom,vdd-apc-step-down-limit: Limit of vdd-apc-supply steps for scaling down.
+- qcom,cpr-ref-clk: The reference clock in kHz.
+- qcom,cpr-timer-delay: The delay in microseconds for the timer interval.
+- qcom,cpr-timer-cons-up: Consecutive number of timer interval (qcom,cpr-timer-delay)
+ occurred before issuing UP interrupt.
+- qcom,cpr-timer-cons-down: Consecutive number of timer interval (qcom,cpr-timer-delay)
+ occurred before issuing DOWN interrupt.
+- qcom,cpr-irq-line: Internal interrupt route signal of RBCPR, one of 0, 1 or 2.
+- qcom,cpr-step-quotient: Number of CPR quotient (RO count) per vdd-apc-supply step
+ to issue error_steps.
+- qcom,cpr-up-threshold: The threshold for CPR to issue interrupt when
+ error_steps is greater than it when stepping up.
+- qcom,cpr-down-threshold: The threshold for CPR to issue interrupt when
+ error_steps is greater than it when stepping down.
+- qcom,cpr-idle-clocks: Idle clock cycles RO can be in.
+- qcom,cpr-gcnt-time: The time for gate count in microseconds.
+- qcom,cpr-apc-volt-step: The voltage in microvolt per CPR step, such as 5000uV.
Optional properties:
@@ -61,28 +77,42 @@
2 => equal to slow speed corner ceiling
3 => equal to qcom,vdd-mx-vmax
This is required when vdd-mx-supply is present.
+- qcom,cpr-enable: Present: CPR enabled by default.
+ Not Present: CPR disable by default.
Example:
apc_vreg_corner: regulator@f9018000 {
status = "okay";
compatible = "qcom,cpr-regulator";
- reg = <0xf9018000 0x1000>,
- <0xfc4b80b0 8>;
- reg-names = "rbcpr", "efuse_phys";
+ reg = <0xf9018000 0x1000>, <0xfc4b80b0 8>, <0xfc4bc450 16>;
+ reg-names = "rbcpr", "pvs_efuse", "cpr_efuse";
+ interrupts = <0 15 0>;
regulator-name = "apc_corner";
regulator-min-microvolt = <1>;
- regulator-max-microvolt = <4>;
+ regulator-max-microvolt = <3>;
qcom,num-efuse-bits = <5>;
- qcom,efuse-bit-pos = <6 7 8 9 10>;
- qcom,pvs-bin-process = <0 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2
+ qcom,pvs-bin-process = <0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2
2 2 2 2 3 3 3 3 3 3 3 3 0 0 0 0>;
- qcom,pvs-corner-ceiling-slow = <1050000 1150000 1275000 1350000>;
- qcom,pvs-corner-ceiling-nom = <975000 1075000 1200000 1200000>;
- qcom,pvs-corner-ceiling-fast = <900000 1000000 1140000 1140000>;
+ qcom,pvs-corner-ceiling-slow = <1050000 1160000 1275000>;
+ qcom,pvs-corner-ceiling-nom = <975000 1075000 1200000>;
+ qcom,pvs-corner-ceiling-fast = <900000 1000000 1140000>;
vdd-apc-supply = <&pm8226_s2>;
vdd-mx-supply = <&pm8226_l3_ao>;
qcom,vdd-mx-vmax = <1350000>;
qcom,vdd-mx-vmin-method = <1>;
+ qcom,vdd-apc-step-up-limit = <1>;
+ qcom,vdd-apc-step-down-limit = <1>;
+ qcom,cpr-ref-clk = <19200>;
+ qcom,cpr-timer-delay = <5000>;
+ qcom,cpr-timer-cons-up = <1>;
+ qcom,cpr-timer-cons-down = <2>;
+ qcom,cpr-irq-line = <0>;
+ qcom,cpr-step-quotient = <15>;
+ qcom,cpr-up-threshold = <1>;
+ qcom,cpr-down-threshold = <2>;
+ qcom,cpr-idle-clocks = <5>;
+ qcom,cpr-gcnt-time = <1>;
+ qcom,cpr-apc-volt-step = <5000>;
};
diff --git a/Documentation/devicetree/bindings/input/gen_vkeys.txt b/Documentation/devicetree/bindings/input/gen_vkeys.txt
index 76cacd8..2f8d65e 100644
--- a/Documentation/devicetree/bindings/input/gen_vkeys.txt
+++ b/Documentation/devicetree/bindings/input/gen_vkeys.txt
@@ -11,7 +11,10 @@
- qcom,panel-maxx : Maximum x-coordinate of touch panel
- qcom,panel-maxy : Maximum y-coordinate of touch panel
- qcom,key-codes : Array of key codes for virtual keys
- - qcom,y-offset : Offset of y-location for virtual keys
+
+Optional properties:
+ - qcom,y-offset : Offset of y-location for virtual keys, default 0
+
Example:
gen-vkeys {
compatible = "qcom,gen-vkeys";
diff --git a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
index 4a312a8..ded8f77 100644
--- a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
+++ b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
@@ -30,7 +30,8 @@
- qcom,vdd_pll: Voltage to be set for the PLL's rail.
- reg-names: "cxrail_bhs_reg" - control register for modem power
domain.
-- qcom,is-loadable: Boolean- Present if the image needs to be loaded.
+- qcom,is-not-loadable: Boolean- Present if the image does not need to
+ be loaded.
- qcom,pil-self-auth: Boolean- True if authentication is required.
Example:
@@ -47,7 +48,7 @@
vdd_cx-supply = <&pm8841_s2>;
vdd_mx-supply = <&pm8841_s1>;
- qcom,is-loadable;
+ qcom,is-not-loadable;
qcom,firmware-name = "mba";
qcom,pil-self-auth;
diff --git a/arch/arm/boot/dts/apq8084.dtsi b/arch/arm/boot/dts/apq8084.dtsi
index 2543c40..7a1bbef 100644
--- a/arch/arm/boot/dts/apq8084.dtsi
+++ b/arch/arm/boot/dts/apq8084.dtsi
@@ -10,7 +10,7 @@
* GNU General Public License for more details.
*/
-/include/ "skeleton.dtsi"
+/include/ "skeleton64.dtsi"
/ {
model = "Qualcomm APQ 8084";
@@ -24,7 +24,7 @@
&soc {
#address-cells = <1>;
#size-cells = <1>;
- ranges;
+ ranges = <0 0 0 0xffffffff>;
intc: interrupt-controller@f9000000 {
compatible = "qcom,msm-qgic2";
diff --git a/arch/arm/boot/dts/msm8226-coresight.dtsi b/arch/arm/boot/dts/msm8226-coresight.dtsi
index e4a42fa..7c19bc0 100644
--- a/arch/arm/boot/dts/msm8226-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8226-coresight.dtsi
@@ -355,4 +355,18 @@
coresight-name = "coresight-cti-cpu3";
coresight-nr-inports = <0>;
};
+
+ hwevent: hwevent@fd828018 {
+ compatible = "qcom,coresight-hwevent";
+ reg = <0xfd828018 0x80>,
+ <0xf9011080 0x80>,
+ <0xfd4ab160 0x80>;
+ reg-names = "mmss-mux", "apcs-mux", "ppss-mux";
+
+ coresight-id = <29>;
+ coresight-name = "coresight-hwevent";
+ coresight-nr-inports = <0>;
+
+ qcom,hwevent-clks = "core_mmss_clk";
+ };
};
diff --git a/arch/arm/boot/dts/msm8226-regulator.dtsi b/arch/arm/boot/dts/msm8226-regulator.dtsi
index 7fa9081..6aeaf49 100644
--- a/arch/arm/boot/dts/msm8226-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8226-regulator.dtsi
@@ -30,23 +30,37 @@
apc_vreg_corner: regulator@f9018000 {
status = "okay";
compatible = "qcom,cpr-regulator";
- reg = <0xf9018000 0x1000>,
- <0xfc4b80b0 8>;
- reg-names = "rbcpr", "efuse_phys";
+ reg = <0xf9018000 0x1000>, <0xfc4b80b0 8>, <0xfc4bc450 16>;
+ reg-names = "rbcpr", "pvs_efuse", "cpr_efuse";
+ interrupts = <0 15 0>;
regulator-name = "apc_corner";
regulator-min-microvolt = <1>;
- regulator-max-microvolt = <4>;
+ regulator-max-microvolt = <3>;
qcom,num-efuse-bits = <5>;
- qcom,efuse-bit-pos = <6 7 8 9 10>;
- qcom,pvs-bin-process = <0 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2
+ qcom,pvs-bin-process = <0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2
2 2 2 2 3 3 3 3 3 3 3 3 0 0 0 0>;
- qcom,pvs-corner-ceiling-slow = <1050000 1150000 1275000 1350000>;
- qcom,pvs-corner-ceiling-nom = <975000 1075000 1200000 1200000>;
- qcom,pvs-corner-ceiling-fast = <900000 1000000 1140000 1140000>;
+ qcom,pvs-corner-ceiling-slow = <1155000 1160000 1275000>;
+ qcom,pvs-corner-ceiling-nom = <975000 1075000 1200000>;
+ qcom,pvs-corner-ceiling-fast = <900000 1000000 1140000>;
vdd-apc-supply = <&pm8226_s2>;
+
vdd-mx-supply = <&pm8226_l3_ao>;
qcom,vdd-mx-vmax = <1350000>;
qcom,vdd-mx-vmin-method = <1>;
+
+ qcom,cpr-ref-clk = <19200>;
+ qcom,cpr-timer-delay = <5000>;
+ qcom,cpr-timer-cons-up = <1>;
+ qcom,cpr-timer-cons-down = <2>;
+ qcom,cpr-irq-line = <0>;
+ qcom,cpr-step-quotient = <15>;
+ qcom,cpr-up-threshold = <1>;
+ qcom,cpr-down-threshold = <2>;
+ qcom,cpr-idle-clocks = <5>;
+ qcom,cpr-gcnt-time = <1>;
+ qcom,vdd-apc-step-up-limit = <1>;
+ qcom,vdd-apc-step-down-limit = <1>;
+ qcom,cpr-apc-volt-step = <5000>;
};
};
diff --git a/arch/arm/boot/dts/msm8610-cdp.dts b/arch/arm/boot/dts/msm8610-cdp.dts
index 1bf7c2b..ecedcb0 100644
--- a/arch/arm/boot/dts/msm8610-cdp.dts
+++ b/arch/arm/boot/dts/msm8610-cdp.dts
@@ -88,6 +88,49 @@
};
};
};
+
+ gen-vkeys {
+ compatible = "qcom,gen-vkeys";
+ label = "atmel_mxt_ts";
+ qcom,disp-maxx = <480>;
+ qcom,disp-maxy = <800>;
+ qcom,panel-maxx = <508>;
+ qcom,panel-maxy = <880>;
+ qcom,key-codes = <158 102 139>;
+ qcom,y-offset = <35>;
+ };
+
+ gpio_keys {
+ compatible = "gpio-keys";
+ input-name = "gpio-keys";
+
+ camera_snapshot {
+ label = "camera_snapshot";
+ gpios = <&msmgpio 73 0x1>;
+ linux,input-type = <1>;
+ linux,code = <0x2fe>;
+ gpio-key,wakeup;
+ debounce-interval = <15>;
+ };
+
+ camera_focus {
+ label = "camera_focus";
+ gpios = <&msmgpio 74 0x1>;
+ linux,input-type = <1>;
+ linux,code = <0x210>;
+ gpio-key,wakeup;
+ debounce-interval = <15>;
+ };
+
+ vol_up {
+ label = "volume_up";
+ gpios = <&msmgpio 72 0x1>;
+ linux,input-type = <1>;
+ linux,code = <115>;
+ gpio-key,wakeup;
+ debounce-interval = <15>;
+ };
+ };
};
&i2c_cdc {
@@ -165,38 +208,6 @@
};
};
};
-
- gpio_keys {
- compatible = "gpio-keys";
- input-name = "gpio-keys";
-
- camera_snapshot {
- label = "camera_snapshot";
- gpios = <&msmgpio 73 0x1>;
- linux,input-type = <1>;
- linux,code = <0x2fe>;
- gpio-key,wakeup;
- debounce-interval = <15>;
- };
-
- camera_focus {
- label = "camera_focus";
- gpios = <&msmgpio 74 0x1>;
- linux,input-type = <1>;
- linux,code = <0x210>;
- gpio-key,wakeup;
- debounce-interval = <15>;
- };
-
- vol_up {
- label = "volume_up";
- gpios = <&msmgpio 72 0x1>;
- linux,input-type = <1>;
- linux,code = <115>;
- gpio-key,wakeup;
- debounce-interval = <15>;
- };
- };
};
&spmi_bus {
@@ -207,17 +218,6 @@
qcom,vib-vtg-level-mV = <3100>;
};
};
-
- gen-vkeys {
- compatible = "qcom,gen-vkeys";
- label = "atmel_mxt_ts";
- qcom,disp-maxx = <480>;
- qcom,disp-maxy = <800>;
- qcom,panel-maxx = <508>;
- qcom,panel-maxy = <880>;
- qcom,key-codes = <158 102 139>;
- qcom,y-offset = <35>;
- };
};
&sdhc_1 {
diff --git a/arch/arm/boot/dts/msm8610-mtp.dts b/arch/arm/boot/dts/msm8610-mtp.dts
index 3fbc820..35e8909 100644
--- a/arch/arm/boot/dts/msm8610-mtp.dts
+++ b/arch/arm/boot/dts/msm8610-mtp.dts
@@ -88,6 +88,49 @@
};
};
};
+
+ gen-vkeys {
+ compatible = "qcom,gen-vkeys";
+ label = "atmel_mxt_ts";
+ qcom,disp-maxx = <480>;
+ qcom,disp-maxy = <800>;
+ qcom,panel-maxx = <508>;
+ qcom,panel-maxy = <880>;
+ qcom,key-codes = <158 102 139>;
+ qcom,y-offset = <35>;
+ };
+
+ gpio_keys {
+ compatible = "gpio-keys";
+ input-name = "gpio-keys";
+
+ camera_snapshot {
+ label = "camera_snapshot";
+ gpios = <&msmgpio 73 0x1>;
+ linux,input-type = <1>;
+ linux,code = <0x2fe>;
+ gpio-key,wakeup;
+ debounce-interval = <15>;
+ };
+
+ camera_focus {
+ label = "camera_focus";
+ gpios = <&msmgpio 74 0x1>;
+ linux,input-type = <1>;
+ linux,code = <0x210>;
+ gpio-key,wakeup;
+ debounce-interval = <15>;
+ };
+
+ vol_up {
+ label = "volume_up";
+ gpios = <&msmgpio 72 0x1>;
+ linux,input-type = <1>;
+ linux,code = <115>;
+ gpio-key,wakeup;
+ debounce-interval = <15>;
+ };
+ };
};
&i2c_cdc {
@@ -165,38 +208,6 @@
};
};
};
-
- gpio_keys {
- compatible = "gpio-keys";
- input-name = "gpio-keys";
-
- camera_snapshot {
- label = "camera_snapshot";
- gpios = <&msmgpio 73 0x1>;
- linux,input-type = <1>;
- linux,code = <0x2fe>;
- gpio-key,wakeup;
- debounce-interval = <15>;
- };
-
- camera_focus {
- label = "camera_focus";
- gpios = <&msmgpio 74 0x1>;
- linux,input-type = <1>;
- linux,code = <0x210>;
- gpio-key,wakeup;
- debounce-interval = <15>;
- };
-
- vol_up {
- label = "volume_up";
- gpios = <&msmgpio 72 0x1>;
- linux,input-type = <1>;
- linux,code = <115>;
- gpio-key,wakeup;
- debounce-interval = <15>;
- };
- };
};
&spmi_bus {
@@ -207,17 +218,6 @@
qcom,vib-vtg-level-mV = <3100>;
};
};
-
- gen-vkeys {
- compatible = "qcom,gen-vkeys";
- label = "atmel_mxt_ts";
- qcom,disp-maxx = <480>;
- qcom,disp-maxy = <800>;
- qcom,panel-maxx = <508>;
- qcom,panel-maxy = <880>;
- qcom,key-codes = <158 102 139>;
- qcom,y-offset = <35>;
- };
};
&sdhc_1 {
diff --git a/arch/arm/boot/dts/msm8610-regulator.dtsi b/arch/arm/boot/dts/msm8610-regulator.dtsi
index 3df428a..a90f053 100644
--- a/arch/arm/boot/dts/msm8610-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8610-regulator.dtsi
@@ -30,23 +30,37 @@
apc_vreg_corner: regulator@f9018000 {
status = "okay";
compatible = "qcom,cpr-regulator";
- reg = <0xf9018000 0x1000>,
- <0xfc4b80b0 8>;
- reg-names = "rbcpr", "efuse_phys";
+ reg = <0xf9018000 0x1000>, <0xfc4b80b0 8>, <0xfc4bc450 16>;
+ reg-names = "rbcpr", "pvs_efuse", "cpr_efuse";
+ interrupts = <0 15 0>;
regulator-name = "apc_corner";
regulator-min-microvolt = <1>;
- regulator-max-microvolt = <4>;
+ regulator-max-microvolt = <3>;
qcom,num-efuse-bits = <5>;
- qcom,efuse-bit-pos = <6 7 8 9 10>;
- qcom,pvs-bin-process = <0 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2
+ qcom,pvs-bin-process = <0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2
2 2 2 2 3 3 3 3 3 3 3 3 0 0 0 0>;
- qcom,pvs-corner-ceiling-slow = <1050000 1150000 1275000 1350000>;
- qcom,pvs-corner-ceiling-nom = <975000 1075000 1200000 1200000>;
- qcom,pvs-corner-ceiling-fast = <900000 1000000 1140000 1140000>;
+ qcom,pvs-corner-ceiling-slow = <1150000 1150000 1275000>;
+ qcom,pvs-corner-ceiling-nom = <975000 1075000 1200000>;
+ qcom,pvs-corner-ceiling-fast = <900000 1000000 1140000>;
vdd-apc-supply = <&pm8110_s2>;
+
vdd-mx-supply = <&pm8110_l3_ao>;
qcom,vdd-mx-vmax = <1350000>;
qcom,vdd-mx-vmin-method = <1>;
+
+ qcom,cpr-ref-clk = <19200>;
+ qcom,cpr-timer-delay = <5000>;
+ qcom,cpr-timer-cons-up = <1>;
+ qcom,cpr-timer-cons-down = <2>;
+ qcom,cpr-irq-line = <0>;
+ qcom,cpr-step-quotient = <15>;
+ qcom,cpr-up-threshold = <1>;
+ qcom,cpr-down-threshold = <2>;
+ qcom,cpr-idle-clocks = <5>;
+ qcom,cpr-gcnt-time = <1>;
+ qcom,vdd-apc-step-up-limit = <1>;
+ qcom,vdd-apc-step-down-limit = <1>;
+ qcom,cpr-apc-volt-step = <5000>;
};
};
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index 6a2855d..aff8759 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -144,6 +144,11 @@
qcom,adsp-state = <0>;
};
+ qcom,msm-audio-ion {
+ compatible = "qcom,msm-audio-ion";
+ qcom,smmu-enabled;
+ };
+
qcom,msm-imem@fe805000 {
compatible = "qcom,msm-imem";
reg = <0xfe805000 0x1000>; /* Address and size of IMEM */
@@ -725,7 +730,7 @@
qcom,msm-thermal {
compatible = "qcom,msm-thermal";
- qcom,sensor-id = <0>;
+ qcom,sensor-id = <5>;
qcom,poll-ms = <250>;
qcom,limit-temp = <60>;
qcom,temp-hysteresis = <10>;
diff --git a/arch/arm/boot/dts/msm8974-v1-cdp.dts b/arch/arm/boot/dts/msm8974-v1-cdp.dts
index cb58026..c3fd98d 100644
--- a/arch/arm/boot/dts/msm8974-v1-cdp.dts
+++ b/arch/arm/boot/dts/msm8974-v1-cdp.dts
@@ -18,7 +18,9 @@
/ {
model = "Qualcomm MSM 8974 CDP";
compatible = "qcom,msm8974-cdp", "qcom,msm8974", "qcom,cdp";
- qcom,msm-id = <126 1 0>;
+ qcom,msm-id = <126 1 0>,
+ <185 1 0>,
+ <186 1 0>;
};
&ehci {
diff --git a/arch/arm/boot/dts/msm8974-v1-fluid.dts b/arch/arm/boot/dts/msm8974-v1-fluid.dts
index 8ab24df..2b96ecb 100644
--- a/arch/arm/boot/dts/msm8974-v1-fluid.dts
+++ b/arch/arm/boot/dts/msm8974-v1-fluid.dts
@@ -18,7 +18,9 @@
/ {
model = "Qualcomm MSM 8974 FLUID";
compatible = "qcom,msm8974-fluid", "qcom,msm8974", "qcom,fluid";
- qcom,msm-id = <126 3 0>;
+ qcom,msm-id = <126 3 0>,
+ <185 3 0>,
+ <186 3 0>;
};
diff --git a/arch/arm/boot/dts/msm8974-v1-liquid.dts b/arch/arm/boot/dts/msm8974-v1-liquid.dts
index ccbd82f..29d6150 100644
--- a/arch/arm/boot/dts/msm8974-v1-liquid.dts
+++ b/arch/arm/boot/dts/msm8974-v1-liquid.dts
@@ -18,5 +18,7 @@
/ {
model = "Qualcomm MSM 8974 LIQUID";
compatible = "qcom,msm8974-liquid", "qcom,msm8974", "qcom,liquid";
- qcom,msm-id = <126 9 0>;
+ qcom,msm-id = <126 9 0>,
+ <185 9 0>,
+ <186 9 0>;
};
diff --git a/arch/arm/boot/dts/msm8974-v1-mtp.dts b/arch/arm/boot/dts/msm8974-v1-mtp.dts
index 09ea84b..8cbcca0 100644
--- a/arch/arm/boot/dts/msm8974-v1-mtp.dts
+++ b/arch/arm/boot/dts/msm8974-v1-mtp.dts
@@ -18,7 +18,9 @@
/ {
model = "Qualcomm MSM 8974 MTP";
compatible = "qcom,msm8974-mtp", "qcom,msm8974", "qcom,mtp";
- qcom,msm-id = <126 8 0>;
+ qcom,msm-id = <126 8 0>,
+ <185 8 0>,
+ <186 8 0>;
};
&pm8941_chg {
diff --git a/arch/arm/boot/dts/msm8974-v1-rumi.dts b/arch/arm/boot/dts/msm8974-v1-rumi.dts
index caf89ee..85aab17 100644
--- a/arch/arm/boot/dts/msm8974-v1-rumi.dts
+++ b/arch/arm/boot/dts/msm8974-v1-rumi.dts
@@ -18,5 +18,7 @@
/ {
model = "Qualcomm MSM 8974 RUMI";
compatible = "qcom,msm8974-rumi", "qcom,msm8974", "qcom,rumi";
- qcom,msm-id = <126 15 0>;
+ qcom,msm-id = <126 15 0>,
+ <185 15 0>,
+ <186 15 0>;
};
diff --git a/arch/arm/boot/dts/msm8974-v1-sim.dts b/arch/arm/boot/dts/msm8974-v1-sim.dts
index c4b29c2..fc9858d 100644
--- a/arch/arm/boot/dts/msm8974-v1-sim.dts
+++ b/arch/arm/boot/dts/msm8974-v1-sim.dts
@@ -18,5 +18,7 @@
/ {
model = "Qualcomm MSM 8974 Simulator";
compatible = "qcom,msm8974-sim", "qcom,msm8974", "qcom,sim";
- qcom,msm-id = <126 16 0>;
+ qcom,msm-id = <126 16 0>,
+ <185 16 0>,
+ <186 16 0>;
};
diff --git a/arch/arm/boot/dts/msm8974-v2-cdp.dts b/arch/arm/boot/dts/msm8974-v2-cdp.dts
index 4fa1f2a..85d478b 100644
--- a/arch/arm/boot/dts/msm8974-v2-cdp.dts
+++ b/arch/arm/boot/dts/msm8974-v2-cdp.dts
@@ -18,7 +18,9 @@
/ {
model = "Qualcomm MSM 8974v2 CDP";
compatible = "qcom,msm8974-cdp", "qcom,msm8974", "qcom,cdp";
- qcom,msm-id = <126 1 0x20000>;
+ qcom,msm-id = <126 1 0x20000>,
+ <185 1 0x20000>,
+ <186 1 0x20000>;
};
&usb3 {
diff --git a/arch/arm/boot/dts/msm8974-v2-fluid.dts b/arch/arm/boot/dts/msm8974-v2-fluid.dts
index c5779b1..d83d130 100644
--- a/arch/arm/boot/dts/msm8974-v2-fluid.dts
+++ b/arch/arm/boot/dts/msm8974-v2-fluid.dts
@@ -18,7 +18,9 @@
/ {
model = "Qualcomm MSM 8974v2 FLUID";
compatible = "qcom,msm8974-fluid", "qcom,msm8974", "qcom,fluid";
- qcom,msm-id = <126 3 0x20000>;
+ qcom,msm-id = <126 3 0x20000>,
+ <185 3 0x20000>,
+ <186 3 0x20000>;
};
&usb3 {
diff --git a/arch/arm/boot/dts/msm8974-v2-liquid.dts b/arch/arm/boot/dts/msm8974-v2-liquid.dts
index 7132f43..53983dc 100644
--- a/arch/arm/boot/dts/msm8974-v2-liquid.dts
+++ b/arch/arm/boot/dts/msm8974-v2-liquid.dts
@@ -18,7 +18,9 @@
/ {
model = "Qualcomm MSM 8974v2 LIQUID";
compatible = "qcom,msm8974-liquid", "qcom,msm8974", "qcom,liquid";
- qcom,msm-id = <126 9 0x20000>;
+ qcom,msm-id = <126 9 0x20000>,
+ <185 9 0x20000>,
+ <186 9 0x20000>;
};
&usb3 {
diff --git a/arch/arm/boot/dts/msm8974-v2-mtp.dts b/arch/arm/boot/dts/msm8974-v2-mtp.dts
index d38e663..c25c385 100644
--- a/arch/arm/boot/dts/msm8974-v2-mtp.dts
+++ b/arch/arm/boot/dts/msm8974-v2-mtp.dts
@@ -18,7 +18,9 @@
/ {
model = "Qualcomm MSM 8974v2 MTP";
compatible = "qcom,msm8974-mtp", "qcom,msm8974", "qcom,mtp";
- qcom,msm-id = <126 8 0x20000>;
+ qcom,msm-id = <126 8 0x20000>,
+ <185 8 0x20000>,
+ <186 8 0x20000>;
};
&usb3 {
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 71bbdc5..825fe8c 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -1127,7 +1127,6 @@
vdd_mx-supply = <&pm8841_s1>;
vdd_pll-supply = <&pm8941_l12>;
qcom,vdd_pll = <1800000>;
- qcom,is-loadable;
qcom,firmware-name = "mba";
qcom,pil-self-auth;
diff --git a/arch/arm/boot/dts/msm9625-coresight.dtsi b/arch/arm/boot/dts/msm9625-coresight.dtsi
index 8520b19..9b18b72 100644
--- a/arch/arm/boot/dts/msm9625-coresight.dtsi
+++ b/arch/arm/boot/dts/msm9625-coresight.dtsi
@@ -243,4 +243,15 @@
coresight-name = "coresight-cti-cpu";
coresight-nr-inports = <0>;
};
+
+ hwevent: hwevent@f9011038 {
+ compatible = "qcom,coresight-hwevent";
+ reg = <0xf9011038 0x8>,
+ <0xfd4ab160 0x80>;
+ reg-names = "apcs-mux", "ppss-mux";
+
+ coresight-id = <20>;
+ coresight-name = "coresight-hwevent";
+ coresight-nr-inports = <0>;
+ };
};
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index 5abfab8..6e258b5 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -763,6 +763,7 @@
qcom,mss {
compatible = "qcom,pil-q6v5-mss";
interrupts = <0 24 1>;
+ qcom,is-not-loadable;
/* GPIO inputs from mss */
qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_1_in 0 0>;
diff --git a/arch/arm/boot/dts/skeleton64.dtsi b/arch/arm/boot/dts/skeleton64.dtsi
new file mode 100644
index 0000000..5bf6a82
--- /dev/null
+++ b/arch/arm/boot/dts/skeleton64.dtsi
@@ -0,0 +1,18 @@
+/*
+ * Skeleton device tree; the bare minimum needed to boot; just include and
+ * add a compatible value. The bootloader will typically populate the memory
+ * node.
+ */
+
+/ {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ chosen { };
+ aliases { };
+ memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ device_type = "memory";
+ reg = <0 0 0 0>;
+ };
+};
diff --git a/arch/arm/configs/msm8226_defconfig b/arch/arm/configs/msm8226_defconfig
new file mode 100644
index 0000000..d0c32e8
--- /dev/null
+++ b/arch/arm/configs/msm8226_defconfig
@@ -0,0 +1,382 @@
+# 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
+CONFIG_IKCONFIG_PROC=y
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_DEBUG=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_PANIC_TIMEOUT=5
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_EFI_PARTITION=y
+CONFIG_ARCH_MSM=y
+CONFIG_ARCH_MSM8226=y
+# CONFIG_MSM_STACKED_MEMORY is not set
+CONFIG_CPU_HAS_L2_PMU=y
+# CONFIG_MSM_FIQ_SUPPORT is not set
+# CONFIG_MSM_PROC_COMM is not set
+CONFIG_MSM_SMD=y
+CONFIG_MSM_SMD_PKG4=y
+CONFIG_MSM_BAM_DMUX=y
+CONFIG_MSM_SMP2P=y
+CONFIG_MSM_SMP2P_TEST=y
+CONFIG_MSM_IPC_LOGGING=y
+CONFIG_MSM_IPC_ROUTER=y
+CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
+CONFIG_MSM_QMI_INTERFACE=y
+CONFIG_MSM_SUBSYSTEM_RESTART=y
+CONFIG_MSM_SYSMON_COMM=y
+CONFIG_MSM_PIL_LPASS_QDSP6V5=y
+CONFIG_MSM_PIL_MSS_QDSP6V5=y
+CONFIG_MSM_PIL_VENUS=y
+CONFIG_MSM_PIL_PRONTO=y
+CONFIG_MSM_TZ_LOG=y
+CONFIG_MSM_DIRECT_SCLK_ACCESS=y
+CONFIG_MSM_WATCHDOG_V2=y
+CONFIG_MSM_MEMORY_DUMP=y
+CONFIG_MSM_DLOAD_MODE=y
+CONFIG_MSM_ADSP_LOADER=m
+CONFIG_MSM_OCMEM=y
+CONFIG_MSM_OCMEM_LOCAL_POWER_CTRL=y
+CONFIG_MSM_OCMEM_DEBUG=y
+CONFIG_MSM_OCMEM_NONSECURE=y
+CONFIG_MSM_OCMEM_POWER_DISABLE=y
+CONFIG_SENSORS_ADSP=y
+CONFIG_MSM_RTB=y
+CONFIG_MSM_RTB_SEPARATE_CPUS=y
+CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
+CONFIG_MSM_BOOT_STATS=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
+CONFIG_SCHED_MC=y
+CONFIG_ARM_ARCH_TIMER=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+CONFIG_USE_OF=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+# CONFIG_PM_WAKELOCKS_GC is not set
+CONFIG_PM_RUNTIME=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+CONFIG_IPV6=y
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_SIP=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_LOG=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+CONFIG_BRIDGE_NF_EBTABLES=y
+CONFIG_BRIDGE_EBT_BROUTE=y
+CONFIG_BRIDGE=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_CLS_FW=y
+CONFIG_BT=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+CONFIG_BT_HCISMD=y
+CONFIG_CFG80211=y
+CONFIG_NL80211_TESTMODE=y
+CONFIG_CMA=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_CRYPT=y
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+# CONFIG_MSM_RMNET is not set
+CONFIG_MSM_RMNET_BAM=y
+CONFIG_WCNSS_CORE=y
+CONFIG_WCNSS_CORE_PRONTO=y
+CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=m
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ATMEL_MXT=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI4_DEV=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_GPIO=m
+CONFIG_SERIAL_MSM_HSL=y
+CONFIG_SERIAL_MSM_HSL_CONSOLE=y
+CONFIG_DIAG_CHAR=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_MSM=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_QUP=y
+CONFIG_SPI=y
+CONFIG_SPI_QUP=y
+CONFIG_SPI_SPIDEV=m
+CONFIG_SPMI=y
+CONFIG_MSM_BUS_SCALING=y
+CONFIG_SPMI_MSM_PMIC_ARB=y
+CONFIG_MSM_QPNP_INT=y
+CONFIG_SLIMBUS_MSM_NGD=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_QPNP_PIN=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_QPNP_CHARGER=y
+CONFIG_QPNP_BMS=y
+CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
+CONFIG_SENSORS_QPNP_ADC_CURRENT=y
+CONFIG_THERMAL=y
+CONFIG_THERMAL_TSENS8974=y
+CONFIG_THERMAL_MONITOR=y
+CONFIG_THERMAL_QPNP_ADC_TM=y
+CONFIG_WCD9306_CODEC=y
+CONFIG_REGULATOR_STUB=y
+CONFIG_REGULATOR_QPNP=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+# CONFIG_MSM_CAMERA is not set
+CONFIG_OV8825=y
+CONFIG_MSM_CAMERA_SENSOR=y
+CONFIG_MSM_CPP=y
+CONFIG_MSM_CCI=y
+CONFIG_MSM_CSI30_HEADER=y
+CONFIG_MSM_CSIPHY=y
+CONFIG_MSM_CSID=y
+CONFIG_MSM_ISPIF=y
+CONFIG_MSMB_CAMERA=y
+CONFIG_OV9724=y
+CONFIG_MSMB_JPEG=y
+CONFIG_SWITCH=y
+CONFIG_MSM_WFD=y
+CONFIG_MSM_VIDC_V4L2=y
+CONFIG_VIDEOBUF2_MSM_MEM=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_RADIO_IRIS=y
+CONFIG_RADIO_IRIS_TRANSPORT=m
+CONFIG_ION=y
+CONFIG_ION_MSM=y
+CONFIG_MSM_KGSL=y
+CONFIG_FB=y
+CONFIG_FB_MSM=y
+# CONFIG_FB_MSM_BACKLIGHT is not set
+CONFIG_FB_MSM_MDSS=y
+CONFIG_FB_MSM_MDSS_WRITEBACK=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_MSM8226=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_CI13XXX_MSM=y
+CONFIG_USB_G_ANDROID=y
+CONFIG_MMC=y
+CONFIG_MMC_PERF_PROFILING=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_CLKGATE=y
+CONFIG_MMC_EMBEDDED_SDIO=y
+CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_TEST=m
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_MSM=y
+CONFIG_MMC_SDHCI_MSM=y
+CONFIG_MMC_MSM_SPS_SUPPORT=y
+CONFIG_LEDS_QPNP=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_DRV_MSM is not set
+CONFIG_RTC_DRV_QPNP=y
+CONFIG_STAGING=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ASHMEM=y
+CONFIG_ANDROID_LOGGER=y
+CONFIG_ANDROID_RAM_CONSOLE=y
+CONFIG_ANDROID_TIMED_GPIO=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_SPS=y
+CONFIG_USB_BAM=y
+CONFIG_SPS_SUPPORT_NDP_BAM=y
+CONFIG_QPNP_PWM=y
+CONFIG_QPNP_POWER_ON=y
+CONFIG_MSM_IOMMU=y
+CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_TMC=y
+CONFIG_CORESIGHT_TPIU=y
+CONFIG_CORESIGHT_FUNNEL=y
+CONFIG_CORESIGHT_REPLICATOR=y
+CONFIG_CORESIGHT_STM=y
+CONFIG_CORESIGHT_ETM=y
+CONFIG_CORESIGHT_EVENT=m
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT4_FS=y
+CONFIG_FUSE_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+CONFIG_DEBUG_KMEMLEAK=y
+CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_ATOMIC_SLEEP=y
+CONFIG_DEBUG_STACK_USAGE=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_DEBUG_LIST=y
+CONFIG_FAULT_INJECTION=y
+CONFIG_FAIL_PAGE_ALLOC=y
+CONFIG_FAULT_INJECTION_DEBUG_FS=y
+CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y
+CONFIG_DEBUG_PAGEALLOC=y
+CONFIG_ENABLE_DEFAULT_TRACERS=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DEBUG_USER=y
+CONFIG_KEYS=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_TWOFISH=y
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_CCITT=y
+CONFIG_QPNP_VIBRATOR=y
+CONFIG_QSEECOM=y
+CONFIG_CRYPTO_HW=y
+CONFIG_CRYPTO_DEV_QCRYPTO=m
+CONFIG_CRYPTO_DEV_QCE=y
+CONFIG_CRYPTO_DEV_QCEDEV=m
\ No newline at end of file
diff --git a/arch/arm/configs/msm8610-perf_defconfig b/arch/arm/configs/msm8610-perf_defconfig
index e45024e..b385669 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -332,14 +332,6 @@
CONFIG_QPNP_PWM=y
CONFIG_QPNP_POWER_ON=y
CONFIG_MSM_IOMMU=y
-CONFIG_CORESIGHT=y
-CONFIG_CORESIGHT_TMC=y
-CONFIG_CORESIGHT_TPIU=y
-CONFIG_CORESIGHT_FUNNEL=y
-CONFIG_CORESIGHT_REPLICATOR=y
-CONFIG_CORESIGHT_STM=y
-CONFIG_CORESIGHT_ETM=y
-CONFIG_CORESIGHT_EVENT=m
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT3_FS=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index bff59db..5e38ef1 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -336,6 +336,7 @@
CONFIG_CORESIGHT_FUNNEL=y
CONFIG_CORESIGHT_REPLICATOR=y
CONFIG_CORESIGHT_STM=y
+CONFIG_CORESIGHT_HWEVENT=y
CONFIG_CORESIGHT_ETM=y
CONFIG_CORESIGHT_EVENT=m
CONFIG_EXT2_FS=y
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index 8ebe7d4..bae4ee9 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -475,3 +475,4 @@
CONFIG_CRYPTO_DEV_QCRYPTO=m
CONFIG_CRYPTO_DEV_QCE=y
CONFIG_CRYPTO_DEV_QCEDEV=y
+CONFIG_SND_SOC_MSM_HDMI_CODEC_RX=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index fd8a639..8036a44 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -455,6 +455,7 @@
CONFIG_CORESIGHT_FUNNEL=y
CONFIG_CORESIGHT_REPLICATOR=y
CONFIG_CORESIGHT_STM=y
+CONFIG_CORESIGHT_HWEVENT=y
CONFIG_CORESIGHT_ETM=y
CONFIG_CORESIGHT_ETM_PCSAVE_DEFAULT_ENABLE=y
CONFIG_CORESIGHT_EVENT=m
@@ -506,3 +507,4 @@
CONFIG_CRYPTO_DEV_QCRYPTO=m
CONFIG_CRYPTO_DEV_QCE=y
CONFIG_CRYPTO_DEV_QCEDEV=y
+CONFIG_SND_SOC_MSM_HDMI_CODEC_RX=y
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index 7e92748..7891990 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -285,6 +285,7 @@
CONFIG_CORESIGHT_FUNNEL=y
CONFIG_CORESIGHT_REPLICATOR=y
CONFIG_CORESIGHT_STM=y
+CONFIG_CORESIGHT_HWEVENT=y
CONFIG_CORESIGHT_ETM=y
CONFIG_CORESIGHT_EVENT=m
CONFIG_EXT3_FS=y
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index 6212a4d..ac5efc1 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -3123,6 +3123,7 @@
CLK_LOOKUP("core_clk", qdss_clk.c, "fc342000.cti"),
CLK_LOOKUP("core_clk", qdss_clk.c, "fc343000.cti"),
CLK_LOOKUP("core_clk", qdss_clk.c, "fc344000.cti"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "fd828018.hwevent"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc322000.tmc"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc318000.tpiu"),
@@ -3156,6 +3157,9 @@
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc342000.cti"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc343000.cti"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc344000.cti"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fd828018.hwevent"),
+
+ CLK_LOOKUP("core_mmss_clk", mmss_misc_ahb_clk.c, "fd828018.hwevent"),
/* HSUSB-OTG Clocks */
CLK_LOOKUP("xo", cxo_otg_clk.c, "f9a55000.usb"),
diff --git a/arch/arm/mach-msm/clock-9625.c b/arch/arm/mach-msm/clock-9625.c
index 313e04c..5bfc4bb 100644
--- a/arch/arm/mach-msm/clock-9625.c
+++ b/arch/arm/mach-msm/clock-9625.c
@@ -1924,6 +1924,7 @@
CLK_LOOKUP("core_clk", qdss_clk.c, "fc30f000.cti"),
CLK_LOOKUP("core_clk", qdss_clk.c, "fc310000.cti"),
CLK_LOOKUP("core_clk", qdss_clk.c, "fc333000.cti"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "f9011038.hwevent"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc322000.tmc"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc318000.tpiu"),
@@ -1945,7 +1946,7 @@
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc30f000.cti"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc310000.cti"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc333000.cti"),
-
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "f9011038.hwevent"),
};
#define PLL_AUX_OUTPUT_BIT 1
diff --git a/arch/arm/mach-msm/cpr-regulator.c b/arch/arm/mach-msm/cpr-regulator.c
index 08923e4..e51a1f5 100644
--- a/arch/arm/mach-msm/cpr-regulator.c
+++ b/arch/arm/mach-msm/cpr-regulator.c
@@ -24,26 +24,139 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
+#include <linux/interrupt.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/of_regulator.h>
#include <linux/regulator/cpr-regulator.h>
+/* Register Offsets for RB-CPR and Bit Definitions */
+
+/* RBCPR Gate Count and Target Registers */
+#define REG_RBCPR_GCNT_TARGET(n) (0x60 + 4 * n)
+
+#define RBCPR_GCNT_TARGET_GCNT_BITS 10
+#define RBCPR_GCNT_TARGET_GCNT_SHIFT 12
+#define RBCPR_GCNT_TARGET_GCNT_MASK ((1<<RBCPR_GCNT_TARGET_GCNT_BITS)-1)
+
+/* RBCPR Timer Control */
+#define REG_RBCPR_TIMER_INTERVAL 0x44
+#define REG_RBIF_TIMER_ADJUST 0x4C
+
+#define RBIF_TIMER_ADJ_CONS_UP_BITS 4
+#define RBIF_TIMER_ADJ_CONS_UP_MASK ((1<<RBIF_TIMER_ADJ_CONS_UP_BITS)-1)
+#define RBIF_TIMER_ADJ_CONS_DOWN_BITS 4
+#define RBIF_TIMER_ADJ_CONS_DOWN_MASK ((1<<RBIF_TIMER_ADJ_CONS_DOWN_BITS)-1)
+#define RBIF_TIMER_ADJ_CONS_DOWN_SHIFT 4
+
+/* RBCPR Config Register */
+#define REG_RBIF_LIMIT 0x48
+#define REG_RBCPR_STEP_QUOT 0x80
+#define REG_RBIF_SW_VLEVEL 0x94
+
+#define RBIF_LIMIT_CEILING_BITS 6
+#define RBIF_LIMIT_CEILING_MASK ((1<<RBIF_LIMIT_CEILING_BITS)-1)
+#define RBIF_LIMIT_CEILING_SHIFT 6
+#define RBIF_LIMIT_FLOOR_BITS 6
+#define RBIF_LIMIT_FLOOR_MASK ((1<<RBIF_LIMIT_FLOOR_BITS)-1)
+
+#define RBIF_LIMIT_CEILING_DEFAULT RBIF_LIMIT_CEILING_MASK
+#define RBIF_LIMIT_FLOOR_DEFAULT 0
+#define RBIF_SW_VLEVEL_DEFAULT 0x20
+
+#define RBCPR_STEP_QUOT_STEPQUOT_BITS 8
+#define RBCPR_STEP_QUOT_STEPQUOT_MASK ((1<<RBCPR_STEP_QUOT_STEPQUOT_BITS)-1)
+#define RBCPR_STEP_QUOT_IDLE_CLK_BITS 4
+#define RBCPR_STEP_QUOT_IDLE_CLK_MASK ((1<<RBCPR_STEP_QUOT_IDLE_CLK_BITS)-1)
+#define RBCPR_STEP_QUOT_IDLE_CLK_SHIFT 8
+
+/* RBCPR Control Register */
+#define REG_RBCPR_CTL 0x90
+
+#define RBCPR_CTL_LOOP_EN BIT(0)
+#define RBCPR_CTL_TIMER_EN BIT(3)
+#define RBCPR_CTL_SW_AUTO_CONT_ACK_EN BIT(5)
+#define RBCPR_CTL_SW_AUTO_CONT_NACK_DN_EN BIT(6)
+#define RBCPR_CTL_COUNT_MODE BIT(10)
+#define RBCPR_CTL_UP_THRESHOLD_BITS 4
+#define RBCPR_CTL_UP_THRESHOLD_MASK ((1<<RBCPR_CTL_UP_THRESHOLD_BITS)-1)
+#define RBCPR_CTL_UP_THRESHOLD_SHIFT 24
+#define RBCPR_CTL_DN_THRESHOLD_BITS 4
+#define RBCPR_CTL_DN_THRESHOLD_MASK ((1<<RBCPR_CTL_DN_THRESHOLD_BITS)-1)
+#define RBCPR_CTL_DN_THRESHOLD_SHIFT 28
+
+/* RBCPR Ack/Nack Response */
+#define REG_RBIF_CONT_ACK_CMD 0x98
+#define REG_RBIF_CONT_NACK_CMD 0x9C
+
+/* RBCPR Result status Register */
+#define REG_RBCPR_RESULT_0 0xA0
+
+#define RBCPR_RESULT0_ERROR_STEPS_SHIFT 2
+#define RBCPR_RESULT0_ERROR_STEPS_BITS 4
+#define RBCPR_RESULT0_ERROR_STEPS_MASK ((1<<RBCPR_RESULT0_ERROR_STEPS_BITS)-1)
+
+/* RBCPR Interrupt Control Register */
+#define REG_RBIF_IRQ_EN(n) (0x100 + 4 * n)
+#define REG_RBIF_IRQ_CLEAR 0x110
+#define REG_RBIF_IRQ_STATUS 0x114
+
+#define CPR_INT_DONE BIT(0)
+#define CPR_INT_MIN BIT(1)
+#define CPR_INT_DOWN BIT(2)
+#define CPR_INT_MID BIT(3)
+#define CPR_INT_UP BIT(4)
+#define CPR_INT_MAX BIT(5)
+#define CPR_INT_CLAMP BIT(6)
+#define CPR_INT_ALL (CPR_INT_DONE | CPR_INT_MIN | CPR_INT_DOWN | \
+ CPR_INT_MID | CPR_INT_UP | CPR_INT_MAX | CPR_INT_CLAMP)
+#define CPR_INT_DEFAULT (CPR_INT_UP | CPR_INT_DOWN)
+
+#define CPR_NUM_RING_OSC 8
+#define CPR_NUM_SAVE_REGS 10
+
+/* CPR eFuse parameters */
+#define CPR_FUSE_TARGET_QUOT_BITS 12
+#define CPR_FUSE_TARGET_QUOT_BITS_MASK ((1<<CPR_FUSE_TARGET_QUOT_BITS)-1)
+#define CPR_FUSE_RO_SEL_BITS 3
+#define CPR_FUSE_RO_SEL_BITS_MASK ((1<<CPR_FUSE_RO_SEL_BITS)-1)
+
+#define CPR_FUSE_TARGET_QUOT_TURBO_SHIFT 0
+#define CPR_FUSE_TARGET_QUOT_NOMINAL_SHIFT 12
+#define CPR_FUSE_TARGET_QUOT_SVS_SHIFT 24
+
+#define CPR_FUSE_DISABLE_CPR_SHIFT 36
+#define CPR_FUSE_LOCAL_APPROACH_SHIFT 37
+#define CPR_FUSE_REDUNDANT_SHIFT 57
+
+/* PVS eFuse parameters */
+#define PVS_FUSE_REDUNDANT_SHIFT 24
+#define PVS_FUSE_REDUNDANT_BITS 3
+#define PVS_FUSE_REDUNDANT_MASK ((1<<PVS_FUSE_REDUNDANT_BITS)-1)
+
+#define PVS_FUSE_BINS_SHIFT 6
+#define PVS_FUSE_BINS_REDUNDANT_SHIFT 27
+
+enum voltage_change_dir {
+ NO_CHANGE,
+ DOWN,
+ UP,
+};
+
struct cpr_regulator {
struct regulator_desc rdesc;
struct regulator_dev *rdev;
- bool enabled;
+ bool vreg_enabled;
int corner;
+ int ceiling_max;
/* Process voltage parameters */
- phys_addr_t efuse_phys;
+ phys_addr_t pvs_efuse;
u32 num_efuse_bits;
- u32 efuse_bit_pos[CPR_PVS_EFUSE_BITS_MAX];
u32 pvs_bin_process[CPR_PVS_EFUSE_BINS_MAX];
- u32 pvs_corner_ceiling[NUM_APC_PVS][CPR_CORNER_MAX];
+ u32 pvs_corner_v[NUM_APC_PVS][CPR_CORNER_MAX];
/* Process voltage variables */
u32 pvs_bin;
- u32 pvs_process;
- u32 *corner_ceiling;
+ u32 process;
/* APC voltage regulator */
struct regulator *vdd_apc;
@@ -53,13 +166,499 @@
int vdd_mx_vmax;
int vdd_mx_vmin_method;
int vdd_mx_vmin;
+
+ /* CPR parameters */
+ phys_addr_t cpr_fuse_addr;
+ u64 cpr_fuse_bits;
+ u64 cpr_fuse_bits_2;
+ bool cpr_fuse_disable;
+ bool cpr_fuse_local;
+ bool cpr_fuse_redundancy;
+ int cpr_fuse_target_quot[CPR_CORNER_MAX];
+ int cpr_fuse_ro_sel[CPR_CORNER_MAX];
+ int gcnt;
+
+ unsigned int cpr_irq;
+ void __iomem *rbcpr_base;
+ struct mutex cpr_mutex;
+
+ int ceiling_volt[CPR_CORNER_MAX];
+ int floor_volt[CPR_CORNER_MAX];
+ int last_volt[CPR_CORNER_MAX];
+ int step_volt;
+
+ int save_ctl[CPR_CORNER_MAX];
+ int save_irq[CPR_CORNER_MAX];
+
+ u32 save_regs[CPR_NUM_SAVE_REGS];
+ u32 save_reg_val[CPR_NUM_SAVE_REGS];
+
+ /* Config parameters */
+ bool enable;
+ u32 ref_clk_khz;
+ u32 timer_delay_us;
+ u32 timer_cons_up;
+ u32 timer_cons_down;
+ u32 irq_line;
+ u32 step_quotient;
+ u32 up_threshold;
+ u32 down_threshold;
+ u32 idle_clocks;
+ u32 gcnt_time_us;
+ u32 vdd_apc_step_up_limit;
+ u32 vdd_apc_step_down_limit;
};
+static int cpr_debug_enable;
+static int cpr_enable;
+static struct cpr_regulator *the_cpr;
+
+module_param_named(debug_enable, cpr_debug_enable, int, S_IRUGO | S_IWUSR);
+#define cpr_debug(message, ...) \
+ do { \
+ if (cpr_debug_enable) \
+ pr_info(message, ##__VA_ARGS__); \
+ } while (0)
+
+static bool cpr_is_allowed(struct cpr_regulator *cpr_vreg)
+{
+ if (cpr_vreg->cpr_fuse_disable || !cpr_enable)
+ return false;
+ else
+ return true;
+}
+
+static void cpr_write(struct cpr_regulator *cpr_vreg, u32 offset, u32 value)
+{
+ writel_relaxed(value, cpr_vreg->rbcpr_base + offset);
+}
+
+static u32 cpr_read(struct cpr_regulator *cpr_vreg, u32 offset)
+{
+ return readl_relaxed(cpr_vreg->rbcpr_base + offset);
+}
+
+static void cpr_masked_write(struct cpr_regulator *cpr_vreg, u32 offset,
+ u32 mask, u32 value)
+{
+ u32 reg_val;
+
+ reg_val = readl_relaxed(cpr_vreg->rbcpr_base + offset);
+ reg_val &= ~mask;
+ reg_val |= value & mask;
+ writel_relaxed(reg_val, cpr_vreg->rbcpr_base + offset);
+}
+
+static void cpr_irq_clr(struct cpr_regulator *cpr_vreg)
+{
+ cpr_write(cpr_vreg, REG_RBIF_IRQ_CLEAR, CPR_INT_ALL);
+}
+
+static void cpr_irq_clr_nack(struct cpr_regulator *cpr_vreg)
+{
+ cpr_irq_clr(cpr_vreg);
+ cpr_write(cpr_vreg, REG_RBIF_CONT_NACK_CMD, 1);
+}
+
+static void cpr_irq_clr_ack(struct cpr_regulator *cpr_vreg)
+{
+ cpr_irq_clr(cpr_vreg);
+ cpr_write(cpr_vreg, REG_RBIF_CONT_ACK_CMD, 1);
+}
+
+static void cpr_irq_set(struct cpr_regulator *cpr_vreg, u32 int_bits)
+{
+ cpr_write(cpr_vreg, REG_RBIF_IRQ_EN(cpr_vreg->irq_line), int_bits);
+}
+
+static void cpr_ctl_modify(struct cpr_regulator *cpr_vreg, u32 mask, u32 value)
+{
+ cpr_masked_write(cpr_vreg, REG_RBCPR_CTL, mask, value);
+}
+
+static void cpr_ctl_enable(struct cpr_regulator *cpr_vreg)
+{
+ u32 val;
+
+ if (cpr_is_allowed(cpr_vreg))
+ val = RBCPR_CTL_LOOP_EN;
+ else
+ val = 0;
+ cpr_ctl_modify(cpr_vreg, RBCPR_CTL_LOOP_EN, val);
+}
+
+static void cpr_ctl_disable(struct cpr_regulator *cpr_vreg)
+{
+ cpr_ctl_modify(cpr_vreg, RBCPR_CTL_LOOP_EN, 0);
+}
+
+static void cpr_regs_save(struct cpr_regulator *cpr_vreg)
+{
+ int i, offset;
+
+ for (i = 0; i < CPR_NUM_SAVE_REGS; i++) {
+ offset = cpr_vreg->save_regs[i];
+ cpr_vreg->save_reg_val[i] = cpr_read(cpr_vreg, offset);
+ }
+}
+
+static void cpr_regs_restore(struct cpr_regulator *cpr_vreg)
+{
+ int i, offset;
+ u32 val;
+
+ for (i = 0; i < CPR_NUM_SAVE_REGS; i++) {
+ offset = cpr_vreg->save_regs[i];
+ val = cpr_vreg->save_reg_val[i];
+ cpr_write(cpr_vreg, offset, val);
+ }
+}
+
+static void cpr_corner_save(struct cpr_regulator *cpr_vreg, int corner)
+{
+ cpr_vreg->save_ctl[corner] = cpr_read(cpr_vreg, REG_RBCPR_CTL);
+ cpr_vreg->save_irq[corner] =
+ cpr_read(cpr_vreg, REG_RBIF_IRQ_EN(cpr_vreg->irq_line));
+}
+
+static void cpr_corner_restore(struct cpr_regulator *cpr_vreg, int corner)
+{
+ u32 gcnt, ctl, irq, ro_sel;
+
+ ro_sel = cpr_vreg->cpr_fuse_ro_sel[corner];
+ gcnt = cpr_vreg->gcnt | cpr_vreg->cpr_fuse_target_quot[corner];
+ cpr_write(cpr_vreg, REG_RBCPR_GCNT_TARGET(ro_sel), gcnt);
+ ctl = cpr_vreg->save_ctl[corner];
+ cpr_write(cpr_vreg, REG_RBCPR_CTL, ctl);
+ irq = cpr_vreg->save_irq[corner];
+ cpr_irq_set(cpr_vreg, irq);
+ cpr_debug("gcnt = 0x%08x, ctl = 0x%08x, irq = 0x%08x\n",
+ gcnt, ctl, irq);
+}
+
+static void cpr_corner_switch(struct cpr_regulator *cpr_vreg, int corner)
+{
+ if (cpr_vreg->corner == corner)
+ return;
+
+ cpr_corner_restore(cpr_vreg, corner);
+}
+
+/* Module parameter ops */
+static int cpr_enable_param_set(const char *val, const struct kernel_param *kp)
+{
+ int rc;
+ int old_cpr_enable;
+
+ if (!the_cpr) {
+ pr_err("the_cpr = NULL\n");
+ return -ENXIO;
+ }
+
+ mutex_lock(&the_cpr->cpr_mutex);
+
+ old_cpr_enable = cpr_enable;
+ rc = param_set_int(val, kp);
+ if (rc) {
+ pr_err("param_set_int: rc = %d\n", rc);
+ goto _exit;
+ }
+
+ cpr_debug("%d -> %d [corner=%d]\n",
+ old_cpr_enable, cpr_enable, the_cpr->corner);
+
+ if (the_cpr->cpr_fuse_disable) {
+ /* Already disabled */
+ pr_info("CPR disabled by fuse\n");
+ goto _exit;
+ }
+
+ if ((old_cpr_enable != cpr_enable) && the_cpr->corner) {
+ if (cpr_enable) {
+ cpr_ctl_disable(the_cpr);
+ cpr_irq_clr(the_cpr);
+ cpr_corner_restore(the_cpr, the_cpr->corner);
+ cpr_ctl_enable(the_cpr);
+ } else {
+ cpr_ctl_disable(the_cpr);
+ cpr_irq_set(the_cpr, 0);
+ }
+ }
+
+_exit:
+ mutex_unlock(&the_cpr->cpr_mutex);
+ return 0;
+}
+
+static struct kernel_param_ops cpr_enable_ops = {
+ .set = cpr_enable_param_set,
+ .get = param_get_int,
+};
+
+module_param_cb(cpr_enable, &cpr_enable_ops, &cpr_enable, S_IRUGO | S_IWUSR);
+
+static int cpr_apc_set(struct cpr_regulator *cpr_vreg, u32 new_volt)
+{
+ int max_volt, rc;
+
+ max_volt = cpr_vreg->ceiling_max;
+ rc = regulator_set_voltage(cpr_vreg->vdd_apc, new_volt, max_volt);
+ if (rc)
+ pr_err("set: vdd_apc = %d uV: rc=%d\n", new_volt, rc);
+ return rc;
+}
+
+static int cpr_mx_get(struct cpr_regulator *cpr_vreg, int corner, int apc_volt)
+{
+ int vdd_mx;
+
+ switch (cpr_vreg->vdd_mx_vmin_method) {
+ case VDD_MX_VMIN_APC:
+ vdd_mx = apc_volt;
+ break;
+ case VDD_MX_VMIN_APC_CORNER_CEILING:
+ vdd_mx = cpr_vreg->ceiling_volt[corner];
+ break;
+ case VDD_MX_VMIN_APC_SLOW_CORNER_CEILING:
+ vdd_mx = cpr_vreg->pvs_corner_v[APC_PVS_SLOW]
+ [CPR_CORNER_TURBO];
+ break;
+ case VDD_MX_VMIN_MX_VMAX:
+ vdd_mx = cpr_vreg->vdd_mx_vmax;
+ break;
+ default:
+ vdd_mx = 0;
+ break;
+ }
+
+ return vdd_mx;
+}
+
+static int cpr_mx_set(struct cpr_regulator *cpr_vreg, int corner,
+ int vdd_mx_vmin)
+{
+ int rc;
+
+ rc = regulator_set_voltage(cpr_vreg->vdd_mx, vdd_mx_vmin,
+ cpr_vreg->vdd_mx_vmax);
+ cpr_debug("[corner:%d] %d uV\n", corner, vdd_mx_vmin);
+ if (!rc)
+ cpr_vreg->vdd_mx_vmin = vdd_mx_vmin;
+ else
+ pr_err("set: vdd_mx [%d] = %d uV: rc=%d\n",
+ corner, vdd_mx_vmin, rc);
+ return rc;
+}
+
+static int cpr_scale_voltage(struct cpr_regulator *cpr_vreg, int corner,
+ int new_apc_volt, enum voltage_change_dir dir)
+{
+ int rc = 0, vdd_mx_vmin = 0;
+
+ /* No MX scaling if no vdd_mx */
+ if (cpr_vreg->vdd_mx == NULL)
+ dir = NO_CHANGE;
+
+ if (dir != NO_CHANGE) {
+ /* Determine the vdd_mx voltage */
+ vdd_mx_vmin = cpr_mx_get(cpr_vreg, corner, new_apc_volt);
+ }
+
+ if (vdd_mx_vmin && dir == UP) {
+ if (vdd_mx_vmin != cpr_vreg->vdd_mx_vmin)
+ rc = cpr_mx_set(cpr_vreg, corner, vdd_mx_vmin);
+ }
+
+ if (!rc)
+ rc = cpr_apc_set(cpr_vreg, new_apc_volt);
+
+ if (!rc && vdd_mx_vmin && dir == DOWN) {
+ if (vdd_mx_vmin != cpr_vreg->vdd_mx_vmin)
+ rc = cpr_mx_set(cpr_vreg, corner, vdd_mx_vmin);
+ }
+
+ return rc;
+}
+
+static void cpr_scale(struct cpr_regulator *cpr_vreg,
+ enum voltage_change_dir dir)
+{
+ u32 reg_val, error_steps, reg_mask;
+ int last_volt, new_volt, corner;
+
+ corner = cpr_vreg->corner;
+
+ reg_val = cpr_read(cpr_vreg, REG_RBCPR_RESULT_0);
+
+ error_steps = (reg_val >> RBCPR_RESULT0_ERROR_STEPS_SHIFT)
+ & RBCPR_RESULT0_ERROR_STEPS_MASK;
+ last_volt = cpr_vreg->last_volt[corner];
+
+ cpr_debug("last_volt[corner:%d] = %d uV\n", corner, last_volt);
+
+ if (dir == UP) {
+ cpr_debug("Up: cpr status = 0x%08x (error_steps=%d)\n",
+ reg_val, error_steps);
+
+ if (last_volt >= cpr_vreg->ceiling_volt[corner]) {
+ cpr_debug("[corn:%d] @ ceiling: %d >= %d: NACK\n",
+ corner, last_volt,
+ cpr_vreg->ceiling_volt[corner]);
+ cpr_irq_clr_nack(cpr_vreg);
+
+ /* Maximize the UP threshold */
+ reg_mask = RBCPR_CTL_UP_THRESHOLD_MASK <<
+ RBCPR_CTL_UP_THRESHOLD_SHIFT;
+ reg_val = reg_mask;
+ cpr_ctl_modify(cpr_vreg, reg_mask, reg_val);
+ return;
+ }
+
+ if (error_steps > cpr_vreg->vdd_apc_step_up_limit) {
+ cpr_debug("%d is over up-limit(%d): Clamp\n",
+ error_steps,
+ cpr_vreg->vdd_apc_step_up_limit);
+ error_steps = cpr_vreg->vdd_apc_step_up_limit;
+ }
+
+ /* Calculate new voltage */
+ new_volt = last_volt + (error_steps * cpr_vreg->step_volt);
+ if (new_volt > cpr_vreg->ceiling_volt[corner]) {
+ cpr_debug("new_volt(%d) >= ceiling_volt(%d): Clamp\n",
+ new_volt, cpr_vreg->ceiling_volt[corner]);
+ new_volt = cpr_vreg->ceiling_volt[corner];
+ }
+
+ if (cpr_scale_voltage(cpr_vreg, corner, new_volt, dir)) {
+ cpr_irq_clr_nack(cpr_vreg);
+ return;
+ }
+ cpr_vreg->last_volt[corner] = new_volt;
+
+ /* Restore default threshold for DOWN */
+ reg_mask = RBCPR_CTL_DN_THRESHOLD_MASK <<
+ RBCPR_CTL_DN_THRESHOLD_SHIFT;
+ reg_val = cpr_vreg->down_threshold <<
+ RBCPR_CTL_DN_THRESHOLD_SHIFT;
+ /* and disable auto nack down */
+ reg_mask |= RBCPR_CTL_SW_AUTO_CONT_NACK_DN_EN;
+
+ cpr_ctl_modify(cpr_vreg, reg_mask, reg_val);
+
+ /* Re-enable default interrupts */
+ cpr_irq_set(cpr_vreg, CPR_INT_DEFAULT);
+
+ /* Ack */
+ cpr_irq_clr_ack(cpr_vreg);
+
+ cpr_debug("UP: -> new_volt = %d uV\n", new_volt);
+ } else if (dir == DOWN) {
+ cpr_debug("Down: cpr status = 0x%08x (error_steps=%d)\n",
+ reg_val, error_steps);
+
+ if (last_volt <= cpr_vreg->floor_volt[corner]) {
+ cpr_debug("[corn:%d] @ floor: %d <= %d: NACK\n",
+ corner, last_volt,
+ cpr_vreg->floor_volt[corner]);
+ cpr_irq_clr_nack(cpr_vreg);
+
+ /* Maximize the DOWN threshold */
+ reg_mask = RBCPR_CTL_DN_THRESHOLD_MASK <<
+ RBCPR_CTL_DN_THRESHOLD_SHIFT;
+ reg_val = reg_mask;
+
+ /* Enable auto nack down */
+ reg_mask |= RBCPR_CTL_SW_AUTO_CONT_NACK_DN_EN;
+ reg_val |= RBCPR_CTL_SW_AUTO_CONT_NACK_DN_EN;
+
+ cpr_ctl_modify(cpr_vreg, reg_mask, reg_val);
+
+ /* Disable DOWN interrupt */
+ cpr_irq_set(cpr_vreg, CPR_INT_DEFAULT & ~CPR_INT_DOWN);
+
+ return;
+ }
+
+ if (error_steps > cpr_vreg->vdd_apc_step_down_limit) {
+ cpr_debug("%d is over down-limit(%d): Clamp\n",
+ error_steps,
+ cpr_vreg->vdd_apc_step_down_limit);
+ error_steps = cpr_vreg->vdd_apc_step_down_limit;
+ }
+
+ /* Calculte new voltage */
+ new_volt = last_volt - (error_steps * cpr_vreg->step_volt);
+ if (new_volt < cpr_vreg->floor_volt[corner]) {
+ cpr_debug("new_volt(%d) < floor_volt(%d): Clamp\n",
+ new_volt, cpr_vreg->floor_volt[corner]);
+ new_volt = cpr_vreg->floor_volt[corner];
+ }
+
+ if (cpr_scale_voltage(cpr_vreg, corner, new_volt, dir)) {
+ cpr_irq_clr_nack(cpr_vreg);
+ return;
+ }
+ cpr_vreg->last_volt[corner] = new_volt;
+
+ /* Restore default threshold for UP */
+ reg_mask = RBCPR_CTL_UP_THRESHOLD_MASK <<
+ RBCPR_CTL_UP_THRESHOLD_SHIFT;
+ reg_val = cpr_vreg->up_threshold <<
+ RBCPR_CTL_UP_THRESHOLD_SHIFT;
+ cpr_ctl_modify(cpr_vreg, reg_mask, reg_val);
+
+ /* Ack */
+ cpr_irq_clr_ack(cpr_vreg);
+
+ cpr_debug("DOWN: -> new_volt = %d uV\n", new_volt);
+ }
+}
+
+static irqreturn_t cpr_irq_handler(int irq, void *dev)
+{
+ struct cpr_regulator *cpr_vreg = dev;
+ u32 reg_val;
+
+ mutex_lock(&cpr_vreg->cpr_mutex);
+
+ reg_val = cpr_read(cpr_vreg, REG_RBIF_IRQ_STATUS);
+ cpr_debug("IRQ_STATUS = 0x%02X\n", reg_val);
+
+ if (!cpr_is_allowed(cpr_vreg)) {
+ reg_val = cpr_read(cpr_vreg, REG_RBCPR_CTL);
+ pr_err("Interrupt broken? RBCPR_CTL = 0x%02X\n", reg_val);
+ goto _exit;
+ }
+
+ /* Following sequence of handling is as per each IRQ's priority */
+ if (reg_val & CPR_INT_UP) {
+ cpr_scale(cpr_vreg, UP);
+ } else if (reg_val & CPR_INT_DOWN) {
+ cpr_scale(cpr_vreg, DOWN);
+ } else if (reg_val & CPR_INT_MIN) {
+ cpr_irq_clr_nack(cpr_vreg);
+ } else if (reg_val & CPR_INT_MAX) {
+ cpr_irq_clr_nack(cpr_vreg);
+ } else if (reg_val & CPR_INT_MID) {
+ /* RBCPR_CTL_SW_AUTO_CONT_ACK_EN is enabled */
+ cpr_debug("IRQ occured for Mid Flag\n");
+ } else {
+ pr_err("IRQ occured for unknown flag (0x%08x)\n", reg_val);
+ }
+
+ /* Save register values for the corner */
+ cpr_corner_save(cpr_vreg, cpr_vreg->corner);
+
+_exit:
+ mutex_unlock(&cpr_vreg->cpr_mutex);
+ return IRQ_HANDLED;
+}
+
static int cpr_regulator_is_enabled(struct regulator_dev *rdev)
{
struct cpr_regulator *cpr_vreg = rdev_get_drvdata(rdev);
- return cpr_vreg->enabled;
+ return cpr_vreg->vreg_enabled;
}
static int cpr_regulator_enable(struct regulator_dev *rdev)
@@ -78,7 +677,7 @@
rc = regulator_enable(cpr_vreg->vdd_apc);
if (!rc)
- cpr_vreg->enabled = true;
+ cpr_vreg->vreg_enabled = true;
else
pr_err("regulator_enable: vdd_apc: rc=%d\n", rc);
@@ -98,7 +697,7 @@
if (rc)
pr_err("regulator_disable: vdd_mx: rc=%d\n", rc);
else
- cpr_vreg->enabled = false;
+ cpr_vreg->vreg_enabled = false;
} else {
pr_err("regulator_disable: vdd_apc: rc=%d\n", rc);
}
@@ -107,90 +706,44 @@
}
static int cpr_regulator_set_voltage(struct regulator_dev *rdev,
- int min_uV, int max_uV, unsigned *selector)
+ int corner, int corner_max, unsigned *selector)
{
struct cpr_regulator *cpr_vreg = rdev_get_drvdata(rdev);
int rc;
- int vdd_apc_min, vdd_apc_max, vdd_mx_vmin = 0;
- int change_dir = 0;
+ int new_volt;
+ enum voltage_change_dir change_dir = NO_CHANGE;
- if (cpr_vreg->vdd_mx) {
- if (min_uV > cpr_vreg->corner)
- change_dir = 1;
- else if (min_uV < cpr_vreg->corner)
- change_dir = -1;
- }
+ mutex_lock(&cpr_vreg->cpr_mutex);
- vdd_apc_min = cpr_vreg->corner_ceiling[min_uV];
- vdd_apc_max = cpr_vreg->corner_ceiling[CPR_CORNER_SUPER_TURBO];
-
- if (change_dir) {
- /* Determine the vdd_mx voltage */
- switch (cpr_vreg->vdd_mx_vmin_method) {
- case VDD_MX_VMIN_APC:
- vdd_mx_vmin = vdd_apc_min;
- break;
- case VDD_MX_VMIN_APC_CORNER_CEILING:
- vdd_mx_vmin = vdd_apc_min;
- break;
- case VDD_MX_VMIN_APC_SLOW_CORNER_CEILING:
- vdd_mx_vmin = cpr_vreg->pvs_corner_ceiling
- [APC_PVS_SLOW][min_uV];
- break;
- case VDD_MX_VMIN_MX_VMAX:
- default:
- vdd_mx_vmin = cpr_vreg->vdd_mx_vmax;
- break;
- }
- }
-
- if (change_dir > 0) {
- if (vdd_mx_vmin < cpr_vreg->vdd_mx_vmin) {
- /* Check and report the value in case */
- pr_err("Up: but new %d < old %d uV\n", vdd_mx_vmin,
- cpr_vreg->vdd_mx_vmin);
- }
-
- rc = regulator_set_voltage(cpr_vreg->vdd_mx, vdd_mx_vmin,
- cpr_vreg->vdd_mx_vmax);
- if (!rc) {
- cpr_vreg->vdd_mx_vmin = vdd_mx_vmin;
- } else {
- pr_err("set: vdd_mx [%d] = %d uV: rc=%d\n",
- min_uV, vdd_mx_vmin, rc);
- return rc;
- }
- }
-
- rc = regulator_set_voltage(cpr_vreg->vdd_apc,
- vdd_apc_min, vdd_apc_max);
- if (!rc) {
- cpr_vreg->corner = min_uV;
+ if (cpr_is_allowed(cpr_vreg)) {
+ cpr_ctl_disable(cpr_vreg);
+ new_volt = cpr_vreg->last_volt[corner];
} else {
- pr_err("set: vdd_apc [%d] = %d uV: rc=%d\n",
- min_uV, vdd_apc_min, rc);
- return rc;
+ new_volt = cpr_vreg->pvs_corner_v[cpr_vreg->process][corner];
}
- if (change_dir < 0) {
- if (vdd_mx_vmin > cpr_vreg->vdd_mx_vmin) {
- /* Check and report the value in case */
- pr_err("Down: but new %d >= old %d uV\n", vdd_mx_vmin,
- cpr_vreg->vdd_mx_vmin);
- }
+ cpr_debug("[corner:%d] = %d uV\n", corner, new_volt);
- rc = regulator_set_voltage(cpr_vreg->vdd_mx, vdd_mx_vmin,
- cpr_vreg->vdd_mx_vmax);
- if (!rc) {
- cpr_vreg->vdd_mx_vmin = vdd_mx_vmin;
- } else {
- pr_err("set: vdd_mx [%d] = %d uV: rc=%d\n",
- min_uV, vdd_mx_vmin, rc);
- return rc;
- }
+ if (corner > cpr_vreg->corner)
+ change_dir = UP;
+ else if (corner < cpr_vreg->corner)
+ change_dir = DOWN;
+
+ rc = cpr_scale_voltage(cpr_vreg, corner, new_volt, change_dir);
+ if (rc)
+ goto _exit;
+
+ if (cpr_is_allowed(cpr_vreg)) {
+ cpr_irq_clr(cpr_vreg);
+ cpr_corner_switch(cpr_vreg, corner);
+ cpr_ctl_enable(cpr_vreg);
}
- pr_debug("set [corner:%d] = %d uV: rc=%d\n", min_uV, vdd_apc_min, rc);
+ cpr_vreg->corner = corner;
+
+_exit:
+ mutex_unlock(&cpr_vreg->cpr_mutex);
+
return rc;
}
@@ -209,56 +762,202 @@
.get_voltage = cpr_regulator_get_voltage,
};
-static int __init cpr_regulator_pvs_init(struct cpr_regulator *cpr_vreg)
+#ifdef CONFIG_PM
+static int cpr_suspend(struct cpr_regulator *cpr_vreg)
+{
+ cpr_debug("suspend\n");
+
+ cpr_ctl_disable(cpr_vreg);
+ disable_irq(cpr_vreg->cpr_irq);
+
+ cpr_irq_clr(cpr_vreg);
+ cpr_regs_save(cpr_vreg);
+
+ return 0;
+}
+
+static int cpr_resume(struct cpr_regulator *cpr_vreg)
+
+{
+ cpr_debug("resume\n");
+
+ cpr_regs_restore(cpr_vreg);
+ cpr_irq_clr(cpr_vreg);
+
+ enable_irq(cpr_vreg->cpr_irq);
+ cpr_ctl_enable(cpr_vreg);
+
+ return 0;
+}
+
+static int cpr_regulator_suspend(struct platform_device *pdev,
+ pm_message_t state)
+{
+ struct cpr_regulator *cpr_vreg = platform_get_drvdata(pdev);
+
+ if (cpr_is_allowed(cpr_vreg))
+ return cpr_suspend(cpr_vreg);
+ else
+ return 0;
+}
+
+static int cpr_regulator_resume(struct platform_device *pdev)
+{
+ struct cpr_regulator *cpr_vreg = platform_get_drvdata(pdev);
+
+ if (cpr_is_allowed(cpr_vreg))
+ return cpr_resume(cpr_vreg);
+ else
+ return 0;
+}
+#else
+#define cpr_regulator_suspend NULL
+#define cpr_regulator_resume NULL
+#endif
+
+static void cpr_config(struct cpr_regulator *cpr_vreg)
+{
+ int i;
+ u32 val, gcnt;
+
+ /* Disable interrupt and CPR */
+ cpr_write(cpr_vreg, REG_RBIF_IRQ_EN(cpr_vreg->irq_line), 0);
+ cpr_write(cpr_vreg, REG_RBCPR_CTL, 0);
+
+ /* Program the default HW Ceiling, Floor and vlevel */
+ val = ((RBIF_LIMIT_CEILING_DEFAULT & RBIF_LIMIT_CEILING_MASK)
+ << RBIF_LIMIT_CEILING_SHIFT)
+ | (RBIF_LIMIT_FLOOR_DEFAULT & RBIF_LIMIT_FLOOR_MASK);
+ cpr_write(cpr_vreg, REG_RBIF_LIMIT, val);
+ cpr_write(cpr_vreg, REG_RBIF_SW_VLEVEL, RBIF_SW_VLEVEL_DEFAULT);
+
+ /* Clear the target quotient value and gate count of all ROs */
+ for (i = 0; i < CPR_NUM_RING_OSC; i++)
+ cpr_write(cpr_vreg, REG_RBCPR_GCNT_TARGET(i), 0);
+
+ /* Init and save gcnt */
+ gcnt = (cpr_vreg->ref_clk_khz * cpr_vreg->gcnt_time_us) / 1000;
+ gcnt = (gcnt & RBCPR_GCNT_TARGET_GCNT_MASK) <<
+ RBCPR_GCNT_TARGET_GCNT_SHIFT;
+ cpr_vreg->gcnt = gcnt;
+
+ /* Program the step quotient and idle clocks */
+ val = ((cpr_vreg->idle_clocks & RBCPR_STEP_QUOT_IDLE_CLK_MASK)
+ << RBCPR_STEP_QUOT_IDLE_CLK_SHIFT) |
+ (cpr_vreg->step_quotient & RBCPR_STEP_QUOT_STEPQUOT_MASK);
+ cpr_write(cpr_vreg, REG_RBCPR_STEP_QUOT, val);
+
+ /* Program the delay count for the timer */
+ val = (cpr_vreg->ref_clk_khz * cpr_vreg->timer_delay_us) / 1000;
+ cpr_write(cpr_vreg, REG_RBCPR_TIMER_INTERVAL, val);
+ pr_info("Timer count: 0x%0x (for %d us)\n", val,
+ cpr_vreg->timer_delay_us);
+
+ /* Program Consecutive Up & Down */
+ val = ((cpr_vreg->timer_cons_down & RBIF_TIMER_ADJ_CONS_DOWN_MASK)
+ << RBIF_TIMER_ADJ_CONS_DOWN_SHIFT) |
+ (cpr_vreg->timer_cons_up & RBIF_TIMER_ADJ_CONS_UP_MASK);
+ cpr_write(cpr_vreg, REG_RBIF_TIMER_ADJUST, val);
+
+ /* Program the control register */
+ cpr_vreg->up_threshold &= RBCPR_CTL_UP_THRESHOLD_MASK;
+ cpr_vreg->down_threshold &= RBCPR_CTL_DN_THRESHOLD_MASK;
+ val = (cpr_vreg->up_threshold << RBCPR_CTL_UP_THRESHOLD_SHIFT)
+ | (cpr_vreg->down_threshold << RBCPR_CTL_DN_THRESHOLD_SHIFT);
+ val |= RBCPR_CTL_TIMER_EN | RBCPR_CTL_COUNT_MODE;
+ val |= RBCPR_CTL_SW_AUTO_CONT_ACK_EN;
+ cpr_write(cpr_vreg, REG_RBCPR_CTL, val);
+
+ /* Registers to save & restore for suspend */
+ cpr_vreg->save_regs[0] = REG_RBCPR_TIMER_INTERVAL;
+ cpr_vreg->save_regs[1] = REG_RBCPR_STEP_QUOT;
+ cpr_vreg->save_regs[2] = REG_RBIF_TIMER_ADJUST;
+ cpr_vreg->save_regs[3] = REG_RBIF_LIMIT;
+ cpr_vreg->save_regs[4] = REG_RBIF_SW_VLEVEL;
+ cpr_vreg->save_regs[5] = REG_RBIF_IRQ_EN(cpr_vreg->irq_line);
+ cpr_vreg->save_regs[6] = REG_RBCPR_CTL;
+ cpr_vreg->save_regs[7] = REG_RBCPR_GCNT_TARGET
+ (cpr_vreg->cpr_fuse_ro_sel[CPR_CORNER_SVS]);
+ cpr_vreg->save_regs[8] = REG_RBCPR_GCNT_TARGET
+ (cpr_vreg->cpr_fuse_ro_sel[CPR_CORNER_NORMAL]);
+ cpr_vreg->save_regs[9] = REG_RBCPR_GCNT_TARGET
+ (cpr_vreg->cpr_fuse_ro_sel[CPR_CORNER_TURBO]);
+
+ cpr_irq_set(cpr_vreg, CPR_INT_DEFAULT);
+
+ cpr_corner_save(cpr_vreg, CPR_CORNER_SVS);
+ cpr_corner_save(cpr_vreg, CPR_CORNER_NORMAL);
+ cpr_corner_save(cpr_vreg, CPR_CORNER_TURBO);
+}
+
+static int __init cpr_pvs_init(struct cpr_regulator *cpr_vreg)
{
void __iomem *efuse_base;
- u32 efuse_bits;
- int i, bit_pos;
- u32 vmax;
+ u32 efuse_bits, redundant, shift, mask;
+ int i, process;
- efuse_base = ioremap(cpr_vreg->efuse_phys, 4);
+ efuse_base = ioremap(cpr_vreg->pvs_efuse, 4);
if (!efuse_base) {
- pr_err("Unable to map efuse_phys 0x%x\n",
- cpr_vreg->efuse_phys);
+ pr_err("Unable to map pvs_efuse 0x%08x\n",
+ cpr_vreg->pvs_efuse);
return -EINVAL;
}
efuse_bits = readl_relaxed(efuse_base);
/* Construct PVS process # from the efuse bits */
- for (i = 0; i < cpr_vreg->num_efuse_bits; i++) {
- bit_pos = cpr_vreg->efuse_bit_pos[i];
- cpr_vreg->pvs_bin |= (efuse_bits & BIT(bit_pos)) ? BIT(i) : 0;
- }
+ redundant = (efuse_bits >> PVS_FUSE_REDUNDANT_SHIFT)
+ & PVS_FUSE_REDUNDANT_MASK;
+ if (redundant == 2)
+ shift = PVS_FUSE_BINS_REDUNDANT_SHIFT;
+ else
+ shift = PVS_FUSE_BINS_SHIFT;
+ mask = (1 << cpr_vreg->num_efuse_bits) - 1;
+ cpr_vreg->pvs_bin = (efuse_bits >> shift) & mask;
- cpr_vreg->pvs_process = cpr_vreg->pvs_bin_process[cpr_vreg->pvs_bin];
- if (cpr_vreg->pvs_process >= NUM_APC_PVS)
- cpr_vreg->pvs_process = APC_PVS_NO;
-
- /* Use ceiling voltage of Turbo@Slow for all corners of APC_PVS_NO
- but use SuperTurbo@Slow for its SuperTurbo */
- vmax = cpr_vreg->pvs_corner_ceiling[APC_PVS_SLOW][CPR_CORNER_TURBO];
- for (i = CPR_CORNER_SVS; i <= CPR_CORNER_TURBO; i++)
- cpr_vreg->pvs_corner_ceiling[APC_PVS_NO][i] = vmax;
- cpr_vreg->pvs_corner_ceiling[APC_PVS_NO][CPR_CORNER_SUPER_TURBO]
- = cpr_vreg->pvs_corner_ceiling[APC_PVS_SLOW]
- [CPR_CORNER_SUPER_TURBO];
-
- cpr_vreg->corner_ceiling =
- cpr_vreg->pvs_corner_ceiling[cpr_vreg->pvs_process];
+ /* Set ceiling max and use it for APC_PVS_NO */
+ cpr_vreg->ceiling_max =
+ cpr_vreg->pvs_corner_v[APC_PVS_SLOW][CPR_CORNER_TURBO];
iounmap(efuse_base);
- pr_info("PVS Info: efuse_phys=0x%08X, n_bits=%d\n",
- cpr_vreg->efuse_phys, cpr_vreg->num_efuse_bits);
- pr_info("PVS Info: efuse=0x%08X, bin=%d, process=%d\n",
- efuse_bits, cpr_vreg->pvs_bin, cpr_vreg->pvs_process);
+ process = cpr_vreg->pvs_bin_process[cpr_vreg->pvs_bin];
+ pr_info("[0x%08X] = 0x%08X, n_bits=%d, bin=%d (%d) [redundant=%d]\n",
+ cpr_vreg->pvs_efuse, efuse_bits, cpr_vreg->num_efuse_bits,
+ cpr_vreg->pvs_bin, process, redundant);
+ for (i = APC_PVS_SLOW; i < NUM_APC_PVS; i++) {
+ pr_info("[%d] [%d %d %d] uV\n", i,
+ cpr_vreg->pvs_corner_v[i][CPR_CORNER_SVS],
+ cpr_vreg->pvs_corner_v[i][CPR_CORNER_NORMAL],
+ cpr_vreg->pvs_corner_v[i][CPR_CORNER_TURBO]);
+ }
+
+ if (process == APC_PVS_NO || process >= NUM_APC_PVS) {
+ pr_err("Bin=%d (%d) is out of spec. Assume SLOW.\n",
+ cpr_vreg->pvs_bin, process);
+ process = APC_PVS_SLOW;
+ }
+
+ cpr_vreg->process = process;
return 0;
}
-static int __init cpr_regulator_apc_init(struct platform_device *pdev,
- struct cpr_regulator *cpr_vreg)
+#define CPR_PROP_READ_U32(of_node, cpr_property, cpr_config, rc) \
+do { \
+ if (!rc) { \
+ rc = of_property_read_u32(of_node, \
+ "qcom," cpr_property, \
+ cpr_config); \
+ if (rc) { \
+ pr_err("Missing " #cpr_property \
+ ": rc = %d\n", rc); \
+ } \
+ } \
+} while (0)
+
+static int __init cpr_apc_init(struct platform_device *pdev,
+ struct cpr_regulator *cpr_vreg)
{
struct device_node *of_node = pdev->dev.of_node;
int rc;
@@ -308,9 +1007,9 @@
return 0;
}
-static void cpr_regulator_apc_exit(struct cpr_regulator *cpr_vreg)
+static void cpr_apc_exit(struct cpr_regulator *cpr_vreg)
{
- if (cpr_vreg->enabled) {
+ if (cpr_vreg->vreg_enabled) {
regulator_disable(cpr_vreg->vdd_apc);
if (cpr_vreg->vdd_mx)
@@ -318,8 +1017,231 @@
}
}
-static int __init cpr_regulator_parse_dt(struct platform_device *pdev,
- struct cpr_regulator *cpr_vreg)
+static int __init cpr_init_cpr_efuse(struct cpr_regulator *cpr_vreg)
+{
+ void __iomem *efuse_base;
+ u32 ro_sel, val;
+ u64 fuse_bits;
+ int ro_sel_shift[CPR_CORNER_MAX];
+
+ efuse_base = ioremap(cpr_vreg->cpr_fuse_addr, 16);
+ if (!efuse_base) {
+ pr_err("Unable to map cpr_fuse_addr 0x%08x\n",
+ cpr_vreg->cpr_fuse_addr);
+ return -EINVAL;
+ }
+
+ cpr_vreg->cpr_fuse_bits = readll_relaxed(efuse_base);
+ cpr_vreg->cpr_fuse_bits_2 = readll_relaxed(efuse_base + 8);
+
+ iounmap(efuse_base);
+
+ /* Read the control bits of eFuse */
+ cpr_vreg->cpr_fuse_disable = (cpr_vreg->cpr_fuse_bits >>
+ CPR_FUSE_DISABLE_CPR_SHIFT) & 0x01;
+ cpr_vreg->cpr_fuse_local = (cpr_vreg->cpr_fuse_bits >>
+ CPR_FUSE_LOCAL_APPROACH_SHIFT) & 0x01;
+ cpr_vreg->cpr_fuse_redundancy = (cpr_vreg->cpr_fuse_bits >>
+ CPR_FUSE_REDUNDANT_SHIFT) & 0x01;
+
+ pr_info("[0x%08X] = 0x%llx\n", cpr_vreg->cpr_fuse_addr,
+ cpr_vreg->cpr_fuse_bits);
+ pr_info("disable = %d, local = %d, redundancy = %d\n",
+ cpr_vreg->cpr_fuse_disable,
+ cpr_vreg->cpr_fuse_local,
+ cpr_vreg->cpr_fuse_redundancy);
+ pr_info("[0x%08X] = 0x%llx\n", cpr_vreg->cpr_fuse_addr + 8,
+ cpr_vreg->cpr_fuse_bits_2);
+
+ if (cpr_vreg->cpr_fuse_redundancy == 0) {
+ fuse_bits = cpr_vreg->cpr_fuse_bits;
+ ro_sel_shift[CPR_CORNER_SVS] = 54;
+ ro_sel_shift[CPR_CORNER_NORMAL] = 38;
+ ro_sel_shift[CPR_CORNER_TURBO] = 41;
+ } else {
+ fuse_bits = cpr_vreg->cpr_fuse_bits_2;
+ ro_sel_shift[CPR_CORNER_SVS] = 46;
+ ro_sel_shift[CPR_CORNER_NORMAL] = 36;
+ ro_sel_shift[CPR_CORNER_TURBO] = 39;
+ }
+
+ /* SVS */
+ ro_sel = (fuse_bits >> ro_sel_shift[CPR_CORNER_SVS])
+ & CPR_FUSE_RO_SEL_BITS_MASK;
+ val = (fuse_bits >> CPR_FUSE_TARGET_QUOT_SVS_SHIFT)
+ & CPR_FUSE_TARGET_QUOT_BITS_MASK;
+ cpr_vreg->cpr_fuse_target_quot[CPR_CORNER_SVS] = val;
+ cpr_vreg->cpr_fuse_ro_sel[CPR_CORNER_SVS] = ro_sel;
+ pr_info("SVS: ro_sel = %d, target quot = 0x%04x\n", ro_sel, val);
+
+ /* Nominal */
+ ro_sel = (fuse_bits >> ro_sel_shift[CPR_CORNER_NORMAL])
+ & CPR_FUSE_RO_SEL_BITS_MASK;
+ val = (fuse_bits >> CPR_FUSE_TARGET_QUOT_NOMINAL_SHIFT)
+ & CPR_FUSE_TARGET_QUOT_BITS_MASK;
+ cpr_vreg->cpr_fuse_target_quot[CPR_CORNER_NORMAL] = val;
+ cpr_vreg->cpr_fuse_ro_sel[CPR_CORNER_NORMAL] = ro_sel;
+ pr_info("Nominal: ro_sel = %d, target quot = 0x%04x\n", ro_sel, val);
+
+ /* Turbo */
+ ro_sel = (fuse_bits >> ro_sel_shift[CPR_CORNER_TURBO])
+ & CPR_FUSE_RO_SEL_BITS_MASK;
+ val = (fuse_bits >> CPR_FUSE_TARGET_QUOT_TURBO_SHIFT)
+ & CPR_FUSE_TARGET_QUOT_BITS_MASK;
+ cpr_vreg->cpr_fuse_target_quot[CPR_CORNER_TURBO] = val;
+ cpr_vreg->cpr_fuse_ro_sel[CPR_CORNER_TURBO] = ro_sel;
+ pr_info("Turbo: ro_sel = %d, target quot = 0x%04x\n", ro_sel, val);
+
+ if (!cpr_vreg->cpr_fuse_bits) {
+ cpr_vreg->cpr_fuse_disable = 1;
+ pr_err("cpr_fuse_bits = 0: set cpr_fuse_disable = 1\n");
+ }
+
+ return 0;
+}
+
+static int __init cpr_init_cpr_voltages(struct cpr_regulator *cpr_vreg)
+{
+ int i;
+
+ /* Construct CPR voltage limits */
+ for (i = CPR_CORNER_SVS; i < CPR_CORNER_MAX; i++) {
+ cpr_vreg->floor_volt[i] =
+ cpr_vreg->pvs_corner_v[APC_PVS_FAST][i];
+ cpr_vreg->ceiling_volt[i] =
+ cpr_vreg->pvs_corner_v[APC_PVS_SLOW][i];
+ cpr_vreg->last_volt[i] =
+ cpr_vreg->pvs_corner_v[cpr_vreg->process][i];
+ }
+
+ return 0;
+}
+
+static int __init cpr_init_cpr_parameters(struct platform_device *pdev,
+ struct cpr_regulator *cpr_vreg)
+{
+ struct device_node *of_node = pdev->dev.of_node;
+ int rc = 0;
+
+ CPR_PROP_READ_U32(of_node, "cpr-ref-clk",
+ &cpr_vreg->ref_clk_khz, rc);
+ if (rc)
+ return rc;
+ CPR_PROP_READ_U32(of_node, "cpr-timer-delay",
+ &cpr_vreg->timer_delay_us, rc);
+ if (rc)
+ return rc;
+ CPR_PROP_READ_U32(of_node, "cpr-timer-cons-up",
+ &cpr_vreg->timer_cons_up, rc);
+ if (rc)
+ return rc;
+ CPR_PROP_READ_U32(of_node, "cpr-timer-cons-down",
+ &cpr_vreg->timer_cons_down, rc);
+ if (rc)
+ return rc;
+ CPR_PROP_READ_U32(of_node, "cpr-irq-line",
+ &cpr_vreg->irq_line, rc);
+ if (rc)
+ return rc;
+ CPR_PROP_READ_U32(of_node, "cpr-step-quotient",
+ &cpr_vreg->step_quotient, rc);
+ if (rc)
+ return rc;
+ CPR_PROP_READ_U32(of_node, "cpr-up-threshold",
+ &cpr_vreg->up_threshold, rc);
+ if (rc)
+ return rc;
+ CPR_PROP_READ_U32(of_node, "cpr-down-threshold",
+ &cpr_vreg->down_threshold, rc);
+ if (rc)
+ return rc;
+ CPR_PROP_READ_U32(of_node, "cpr-idle-clocks",
+ &cpr_vreg->idle_clocks, rc);
+ if (rc)
+ return rc;
+ CPR_PROP_READ_U32(of_node, "cpr-gcnt-time",
+ &cpr_vreg->gcnt_time_us, rc);
+ if (rc)
+ return rc;
+ CPR_PROP_READ_U32(of_node, "vdd-apc-step-up-limit",
+ &cpr_vreg->vdd_apc_step_up_limit, rc);
+ if (rc)
+ return rc;
+ CPR_PROP_READ_U32(of_node, "vdd-apc-step-down-limit",
+ &cpr_vreg->vdd_apc_step_down_limit, rc);
+ if (rc)
+ return rc;
+ CPR_PROP_READ_U32(of_node, "cpr-apc-volt-step",
+ &cpr_vreg->step_volt, rc);
+ if (rc)
+ return rc;
+
+ /* Init module parameter with the DT value */
+ cpr_vreg->enable = of_property_read_bool(of_node, "qcom,cpr-enable");
+ cpr_enable = (int) cpr_vreg->enable;
+ pr_info("CPR is %s by default.\n",
+ cpr_vreg->enable ? "enabled" : "disabled");
+
+ return rc;
+}
+
+static int __init cpr_init_cpr(struct platform_device *pdev,
+ struct cpr_regulator *cpr_vreg)
+{
+ struct resource *res;
+ int rc = 0;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "cpr_efuse");
+ if (!res || !res->start) {
+ pr_err("cpr_efuse missing: res=%p\n", res);
+ return -EINVAL;
+ }
+ cpr_vreg->cpr_fuse_addr = res->start;
+
+ rc = cpr_init_cpr_efuse(cpr_vreg);
+ if (rc)
+ return rc;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rbcpr");
+ if (!res || !res->start) {
+ pr_err("missing rbcpr address: res=%p\n", res);
+ return -EINVAL;
+ }
+ cpr_vreg->rbcpr_base = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+
+ /* Init all voltage set points of APC regulator for CPR */
+ cpr_init_cpr_voltages(cpr_vreg);
+
+ /* Init CPR configuration parameters */
+ rc = cpr_init_cpr_parameters(pdev, cpr_vreg);
+ if (rc)
+ return rc;
+
+ /* Get and Init interrupt */
+ cpr_vreg->cpr_irq = platform_get_irq(pdev, 0);
+ if (!cpr_vreg->cpr_irq) {
+ pr_err("missing CPR IRQ\n");
+ return -EINVAL;
+ }
+
+ /* Configure CPR HW but keep it disabled */
+ cpr_config(cpr_vreg);
+
+ rc = request_threaded_irq(cpr_vreg->cpr_irq, NULL, cpr_irq_handler,
+ IRQF_TRIGGER_RISING, "cpr", cpr_vreg);
+ if (rc) {
+ pr_err("CPR: request irq failed for IRQ %d\n",
+ cpr_vreg->cpr_irq);
+ return rc;
+ }
+
+ return 0;
+}
+
+static int __init cpr_pvs_parse_dt(struct platform_device *pdev,
+ struct cpr_regulator *cpr_vreg)
{
struct device_node *of_node = pdev->dev.of_node;
struct resource *res;
@@ -327,13 +1249,12 @@
size_t pvs_bins;
/* Parse process voltage parameters */
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- "efuse_phys");
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pvs_efuse");
if (!res || !res->start) {
- pr_err("efuse_phys missing: res=%p\n", res);
+ pr_err("pvs_efuse missing: res=%p\n", res);
return -EINVAL;
}
- cpr_vreg->efuse_phys = res->start;
+ cpr_vreg->pvs_efuse = res->start;
rc = of_property_read_u32(of_node, "qcom,num-efuse-bits",
&cpr_vreg->num_efuse_bits);
@@ -349,14 +1270,6 @@
return -EINVAL;
}
- rc = of_property_read_u32_array(of_node, "qcom,efuse-bit-pos",
- cpr_vreg->efuse_bit_pos,
- cpr_vreg->num_efuse_bits);
- if (rc < 0) {
- pr_err("efuse-bit-pos missing: rc=%d\n", rc);
- return rc;
- }
-
pvs_bins = 1 << cpr_vreg->num_efuse_bits;
rc = of_property_read_u32_array(of_node, "qcom,pvs-bin-process",
cpr_vreg->pvs_bin_process,
@@ -368,7 +1281,7 @@
rc = of_property_read_u32_array(of_node,
"qcom,pvs-corner-ceiling-slow",
- &cpr_vreg->pvs_corner_ceiling[APC_PVS_SLOW][CPR_CORNER_SVS],
+ &cpr_vreg->pvs_corner_v[APC_PVS_SLOW][CPR_CORNER_SVS],
CPR_CORNER_MAX - CPR_CORNER_SVS);
if (rc < 0) {
pr_err("pvs-corner-ceiling-slow missing: rc=%d\n", rc);
@@ -377,7 +1290,7 @@
rc = of_property_read_u32_array(of_node,
"qcom,pvs-corner-ceiling-nom",
- &cpr_vreg->pvs_corner_ceiling[APC_PVS_NOM][CPR_CORNER_SVS],
+ &cpr_vreg->pvs_corner_v[APC_PVS_NOM][CPR_CORNER_SVS],
CPR_CORNER_MAX - CPR_CORNER_SVS);
if (rc < 0) {
pr_err("pvs-corner-ceiling-norm missing: rc=%d\n", rc);
@@ -386,7 +1299,7 @@
rc = of_property_read_u32_array(of_node,
"qcom,pvs-corner-ceiling-fast",
- &cpr_vreg->pvs_corner_ceiling[APC_PVS_FAST][CPR_CORNER_SVS],
+ &cpr_vreg->pvs_corner_v[APC_PVS_FAST][CPR_CORNER_SVS],
CPR_CORNER_MAX - CPR_CORNER_SVS);
if (rc < 0) {
pr_err("pvs-corner-ceiling-fast missing: rc=%d\n", rc);
@@ -426,25 +1339,33 @@
return -ENOMEM;
}
- rc = cpr_regulator_parse_dt(pdev, cpr_vreg);
+ rc = cpr_pvs_parse_dt(pdev, cpr_vreg);
if (rc) {
pr_err("Wrong DT parameter specified: rc=%d\n", rc);
return rc;
}
- rc = cpr_regulator_pvs_init(cpr_vreg);
+ rc = cpr_pvs_init(cpr_vreg);
if (rc) {
pr_err("Initialize PVS wrong: rc=%d\n", rc);
return rc;
}
- rc = cpr_regulator_apc_init(pdev, cpr_vreg);
+ rc = cpr_apc_init(pdev, cpr_vreg);
if (rc) {
if (rc != -EPROBE_DEFER)
pr_err("Initialize APC wrong: rc=%d\n", rc);
return rc;
}
+ rc = cpr_init_cpr(pdev, cpr_vreg);
+ if (rc) {
+ pr_err("Initialize CPR failed: rc=%d\n", rc);
+ return rc;
+ }
+
+ mutex_init(&cpr_vreg->cpr_mutex);
+
rdesc = &cpr_vreg->rdesc;
rdesc->owner = THIS_MODULE;
rdesc->type = REGULATOR_VOLTAGE;
@@ -457,17 +1378,12 @@
rc = PTR_ERR(cpr_vreg->rdev);
pr_err("regulator_register failed: rc=%d\n", rc);
- cpr_regulator_apc_exit(cpr_vreg);
+ cpr_apc_exit(cpr_vreg);
return rc;
}
platform_set_drvdata(pdev, cpr_vreg);
-
- pr_info("PVS [%d %d %d %d] uV\n",
- cpr_vreg->corner_ceiling[CPR_CORNER_SVS],
- cpr_vreg->corner_ceiling[CPR_CORNER_NORMAL],
- cpr_vreg->corner_ceiling[CPR_CORNER_TURBO],
- cpr_vreg->corner_ceiling[CPR_CORNER_SUPER_TURBO]);
+ the_cpr = cpr_vreg;
return 0;
}
@@ -478,7 +1394,13 @@
cpr_vreg = platform_get_drvdata(pdev);
if (cpr_vreg) {
- cpr_regulator_apc_exit(cpr_vreg);
+ /* Disable CPR */
+ if (cpr_is_allowed(cpr_vreg)) {
+ cpr_ctl_disable(cpr_vreg);
+ cpr_irq_set(cpr_vreg, 0);
+ }
+
+ cpr_apc_exit(cpr_vreg);
regulator_unregister(cpr_vreg->rdev);
}
@@ -498,6 +1420,8 @@
},
.probe = cpr_regulator_probe,
.remove = __devexit_p(cpr_regulator_remove),
+ .suspend = cpr_regulator_suspend,
+ .resume = cpr_regulator_resume,
};
/**
diff --git a/arch/arm/mach-msm/include/mach/subsystem_restart.h b/arch/arm/mach-msm/include/mach/subsystem_restart.h
index 893db0b..35b1f76 100644
--- a/arch/arm/mach-msm/include/mach/subsystem_restart.h
+++ b/arch/arm/mach-msm/include/mach/subsystem_restart.h
@@ -41,7 +41,8 @@
* @powerup: Start a subsystem
* @crash_shutdown: Shutdown a subsystem when the system crashes (can't sleep)
* @ramdump: Collect a ramdump of the subsystem
- * @is_loadable: Indicate if subsystem firmware is loadable via pil framework
+ * @is_not_loadable: Indicate if subsystem firmware is not loadable via pil
+ * framework
*/
struct subsys_desc {
const char *name;
@@ -57,7 +58,7 @@
void (*crash_shutdown)(const struct subsys_desc *desc);
int (*ramdump)(int, const struct subsys_desc *desc);
unsigned int err_ready_irq;
- int is_loadable;
+ int is_not_loadable;
};
#if defined(CONFIG_MSM_SUBSYSTEM_RESTART)
diff --git a/arch/arm/mach-msm/msm_dcvs.c b/arch/arm/mach-msm/msm_dcvs.c
index 9e0be63..1a919fc 100644
--- a/arch/arm/mach-msm/msm_dcvs.c
+++ b/arch/arm/mach-msm/msm_dcvs.c
@@ -1,4 +1,4 @@
-/* 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
@@ -1026,6 +1026,9 @@
uint32_t ret1;
uint32_t ret2;
+ if (!msm_dcvs_enabled)
+ return ret;
+
offset = get_core_offset(type, type_core_num);
if (offset < 0)
return ret;
@@ -1277,6 +1280,9 @@
struct kobject *module_kobj = NULL;
int ret = 0;
+ if (!msm_dcvs_enabled)
+ return ret;
+
module_kobj = kset_find_obj(module_kset, KBUILD_MODNAME);
if (!module_kobj) {
pr_err("%s: cannot find kobject for module %s\n",
@@ -1343,6 +1349,7 @@
ret = msm_dcvs_scm_init(SZ_32K);
if (ret) {
__err("Unable to initialize DCVS err=%d\n", ret);
+ msm_dcvs_enabled = 0;
goto done;
}
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index d657b05..979458e 100644
--- a/arch/arm/mach-msm/pil-q6v5-mss.c
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -506,7 +506,7 @@
{
struct mba_data *drv = subsys_to_drv(subsys);
- if (!subsys->is_loadable)
+ if (subsys->is_not_loadable)
return 0;
pil_shutdown(&drv->desc);
pil_shutdown(&drv->q6->desc);
@@ -518,7 +518,7 @@
struct mba_data *drv = subsys_to_drv(subsys);
int ret;
- if (!subsys->is_loadable)
+ if (subsys->is_not_loadable)
return 0;
/*
* At this time, the modem is shutdown. Therefore this function cannot
@@ -605,7 +605,7 @@
int ret;
struct mba_data *drv = subsys_to_drv(desc);
- if (!desc->is_loadable)
+ if (desc->is_not_loadable)
return 0;
ret = pil_boot(&drv->q6->desc);
@@ -628,7 +628,7 @@
{
struct mba_data *drv = subsys_to_drv(desc);
- if (!desc->is_loadable)
+ if (desc->is_not_loadable)
return;
pil_shutdown(&drv->desc);
@@ -836,17 +836,18 @@
static int __devinit pil_mss_driver_probe(struct platform_device *pdev)
{
struct mba_data *drv;
- int ret, err_fatal_gpio, is_loadable;
+ int ret, err_fatal_gpio, is_not_loadable;
drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
if (!drv)
return -ENOMEM;
platform_set_drvdata(pdev, drv);
- is_loadable = of_property_read_bool(pdev->dev.of_node,
- "qcom,is-loadable");
- if (is_loadable) {
- drv->subsys_desc.is_loadable = 1;
+ is_not_loadable = of_property_read_bool(pdev->dev.of_node,
+ "qcom,is-not-loadable");
+ if (is_not_loadable) {
+ drv->subsys_desc.is_not_loadable = 1;
+ } else {
ret = pil_mss_loadable_init(drv, pdev);
if (ret)
return ret;
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_acdb.c b/arch/arm/mach-msm/qdsp6v2/audio_acdb.c
index ea22c12..b5ccc31 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_acdb.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_acdb.c
@@ -786,7 +786,7 @@
goto done;
}
- if (size <= 0) {
+ if ((size <= 0) || (size > sizeof(data))) {
pr_err("%s: Invalid size sent to driver: %d\n",
__func__, size);
result = -EFAULT;
diff --git a/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c b/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c
index c9bc3d7..5303009 100644
--- a/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c
+++ b/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c
@@ -22,10 +22,15 @@
#include <linux/of_device.h>
#include <linux/msm_audio_ion.h>
+#include <linux/iommu.h>
+#include <mach/iommu_domains.h>
+
struct msm_audio_ion_private {
bool smmu_enabled;
- /*u32 group_id;*/
- /*u32 domain_id;*/
+ bool audioheap_enabled;
+ struct iommu_group *group;
+ u32 domain_id;
+ struct iommu_domain *domain;
};
static struct msm_audio_ion_private msm_audio_ion_data = {0,};
@@ -49,10 +54,22 @@
goto err;
}
- *handle = ion_alloc(*client, bufsz, SZ_4K, (0x1<<ION_AUDIO_HEAP_ID), 0);
+ *handle = ion_alloc(*client, bufsz, SZ_4K,
+ ION_HEAP(ION_AUDIO_HEAP_ID), 0);
if (IS_ERR_OR_NULL((void *) (*handle))) {
- pr_err("%s: ION memory allocation for AUDIO failed\n",
- __func__);
+ pr_debug("system heap is used");
+ msm_audio_ion_data.audioheap_enabled = 0;
+ *handle = ion_alloc(*client, bufsz, SZ_4K,
+ ION_HEAP(ION_SYSTEM_HEAP_ID), 0);
+
+ } else {
+ pr_debug("audio heap is used");
+ msm_audio_ion_data.audioheap_enabled = 1;
+ }
+
+ if (IS_ERR_OR_NULL((void *) (*handle))) {
+ pr_err("%s: ION memory allocation for AUDIO failed rc=%d, smmu_enabled=%d\n",
+ __func__, rc, msm_audio_ion_data.smmu_enabled);
goto err_ion_client;
}
@@ -63,15 +80,17 @@
goto err_ion_handle;
}
- /*Need to add condition SMMU enable or not */
*vaddr = ion_map_kernel(*client, *handle);
if (IS_ERR_OR_NULL((void *)*vaddr)) {
pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
goto err_ion_handle;
}
+ pr_debug("%s: mapped address = %p, size=%d\n", __func__, *vaddr, bufsz);
- if (bufsz != 0)
+ if (bufsz != 0) {
+ pr_debug("%s: memset to 0 %p %d\n", __func__, *vaddr, bufsz);
memset((void *)*vaddr, 0, bufsz);
+ }
return 0;
@@ -81,7 +100,6 @@
msm_audio_ion_client_destroy(*client);
err:
return -EINVAL;
-
}
int msm_audio_ion_import(const char *name, struct ion_client **client,
@@ -125,13 +143,6 @@
goto err_ion_handle;
}
- /*Need to add condition SMMU enable or not */
- *vaddr = ion_map_kernel(*client, *handle);
- if (IS_ERR_OR_NULL((void *)*vaddr)) {
- pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
- goto err_ion_handle;
- }
-
if (bufsz != 0)
memset((void *)*vaddr, 0, bufsz);
@@ -142,12 +153,20 @@
msm_audio_ion_client_destroy(*client);
err:
return -EINVAL;
-
}
int msm_audio_ion_free(struct ion_client *client, struct ion_handle *handle)
{
- /* add condition for SMMU enabled */
+ if (msm_audio_ion_data.smmu_enabled) {
+ /* Need to populate book kept infomation */
+ pr_debug("client=%p, domain=%p, domain_id=%d, group=%p",
+ client, msm_audio_ion_data.domain,
+ msm_audio_ion_data.domain_id, msm_audio_ion_data.group);
+
+ ion_unmap_iommu(client, handle,
+ msm_audio_ion_data.domain_id, 0);
+ }
+
ion_unmap_kernel(client, handle);
ion_free(client, handle);
@@ -155,6 +174,91 @@
return 0;
}
+int msm_audio_ion_mmap(struct audio_buffer *ab,
+ struct vm_area_struct *vma)
+{
+ struct sg_table *table;
+ unsigned long addr = vma->vm_start;
+ unsigned long offset = vma->vm_pgoff * PAGE_SIZE;
+ struct scatterlist *sg;
+ unsigned int i;
+ struct page *page;
+ int ret;
+
+ pr_debug("%s\n", __func__);
+
+ table = ion_sg_table(ab->client, ab->handle);
+
+ if (IS_ERR(table)) {
+ pr_err("%s: Unable to get sg_table from ion: %ld\n",
+ __func__, PTR_ERR(table));
+ return PTR_ERR(table);
+ } else if (!table) {
+ pr_err("%s: sg_list is NULL\n", __func__);
+ return -EINVAL;
+ }
+
+ /* uncached */
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+
+ /* We need to check if a page is associated with this sg list because:
+ * If the allocation came from a carveout we currently don't have
+ * pages associated with carved out memory. This might change in the
+ * future and we can remove this check and the else statement.
+ */
+ page = sg_page(table->sgl);
+ if (page) {
+ pr_debug("%s: page is NOT null\n", __func__);
+ for_each_sg(table->sgl, sg, table->nents, i) {
+ unsigned long remainder = vma->vm_end - addr;
+ unsigned long len = sg_dma_len(sg);
+
+ page = sg_page(sg);
+
+ if (offset >= sg_dma_len(sg)) {
+ offset -= sg_dma_len(sg);
+ continue;
+ } else if (offset) {
+ page += offset / PAGE_SIZE;
+ len = sg_dma_len(sg) - offset;
+ offset = 0;
+ }
+ len = min(len, remainder);
+ pr_debug("vma=%p, addr=%x len=%ld vm_start=%x vm_end=%x vm_page_prot=%ld\n",
+ vma, (unsigned int)addr, len,
+ (unsigned int)vma->vm_start,
+ (unsigned int)vma->vm_end,
+ (unsigned long int)vma->vm_page_prot);
+ remap_pfn_range(vma, addr, page_to_pfn(page), len,
+ vma->vm_page_prot);
+ addr += len;
+ if (addr >= vma->vm_end)
+ return 0;
+ }
+ } else {
+ ion_phys_addr_t phys_addr;
+ size_t phys_len;
+ pr_debug("%s: page is NULL\n", __func__);
+
+ ret = ion_phys(ab->client, ab->handle, &phys_addr, &phys_len);
+ if (ret) {
+ pr_err("%s: Unable to get phys address from ION buffer: %d\n"
+ , __func__ , ret);
+ return ret;
+ }
+ pr_debug("phys=%x len=%d\n", (unsigned int)phys_addr, phys_len);
+ pr_debug("vma=%p, vm_start=%x vm_end=%x vm_pgoff=%ld vm_page_prot=%ld\n",
+ vma, (unsigned int)vma->vm_start,
+ (unsigned int)vma->vm_end, vma->vm_pgoff,
+ (unsigned long int)vma->vm_page_prot);
+ ret = remap_pfn_range(vma, vma->vm_start,
+ __phys_to_pfn(phys_addr) + vma->vm_pgoff,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot);
+ }
+ return 0;
+}
+
bool msm_audio_ion_is_smmu_available(void)
{
@@ -165,18 +269,17 @@
struct ion_client *msm_audio_ion_client_create(unsigned int heap_mask,
const char *name)
{
- pr_debug("%s: smmu_enabled = %d\n", __func__,
- msm_audio_ion_data.smmu_enabled);
-
-
- return msm_ion_client_create(heap_mask, name);
+ struct ion_client *pclient = NULL;
+ /*IOMMU group and domain are moved to probe()*/
+ pclient = msm_ion_client_create(heap_mask, name);
+ return pclient;
}
void msm_audio_ion_client_destroy(struct ion_client *client)
{
- pr_debug("%s: smmu_enabled = %d\n", __func__,
- msm_audio_ion_data.smmu_enabled);
+ pr_debug("%s: client = %p smmu_enabled = %d\n", __func__,
+ client, msm_audio_ion_data.smmu_enabled);
ion_client_destroy(client);
}
@@ -192,9 +295,9 @@
bufsz should be 0 and fd shouldn't be 0 as of now
*/
*handle = ion_import_dma_buf(client, fd);
- pr_err("%s: DMA Buf name=%s, fd=%d handle=%p\n", __func__,
+ pr_debug("%s: DMA Buf name=%s, fd=%d handle=%p\n", __func__,
name, fd, *handle);
- if (IS_ERR_OR_NULL((void *) (*handle))) {
+ if (IS_ERR_OR_NULL((void *)(*handle))) {
pr_err("%s: ion import dma buffer failed\n",
__func__);
goto err_ion_handle;
@@ -245,6 +348,41 @@
return 0;
}
+int msm_audio_ion_cache_operations(struct audio_buffer *abuff, int cache_op)
+{
+ unsigned long ionflag = 0;
+ int rc = 0;
+ int msm_cache_ops = 0;
+
+ if (!abuff) {
+ pr_err("Invalid params: %p, %p\n", __func__, abuff);
+ return -EINVAL;
+ }
+ rc = ion_handle_get_flags(abuff->client, abuff->handle,
+ &ionflag);
+ if (rc) {
+ pr_err("ion_handle_get_flags failed: %d\n", rc);
+ goto cache_op_failed;
+ }
+
+ /* has to be CACHED */
+ if (ION_IS_CACHED(ionflag)) {
+ /* ION_IOC_INV_CACHES or ION_IOC_CLEAN_CACHES */
+ msm_cache_ops = cache_op;
+ rc = msm_ion_do_cache_op(abuff->client,
+ abuff->handle,
+ (unsigned long *) abuff->data,
+ (unsigned long)abuff->size,
+ msm_cache_ops);
+ if (rc) {
+ pr_err("cache operation failed %d\n", rc);
+ goto cache_op_failed;
+ }
+ }
+cache_op_failed:
+ return rc;
+}
+
static int msm_audio_ion_get_phys(struct ion_client *client,
struct ion_handle *handle,
@@ -255,18 +393,25 @@
msm_audio_ion_data.smmu_enabled);
if (msm_audio_ion_data.smmu_enabled) {
- /* SMMU enabled case ion_map_iommu()*/
+ rc = ion_map_iommu(client, handle, msm_audio_ion_data.domain_id,
+ 0 /*partition_num*/, SZ_4K /*align*/, 0/*iova_length*/,
+ addr, (unsigned long *)len,
+ 0, 0);
+ if (rc) {
+ pr_err("%s: ION map iommu failed %d\n", __func__, rc);
+ return rc;
+ }
+ pr_debug("client=%p, domain=%p, domain_id=%d, group=%p",
+ client, msm_audio_ion_data.domain,
+ msm_audio_ion_data.domain_id, msm_audio_ion_data.group);
} else {
/* SMMU is disabled*/
rc = ion_phys(client, handle, addr, len);
}
- pr_debug("%s: addr= 0x%p, len= %d\n", __func__, addr, *len);
+ pr_debug("phys=%x, len=%d, rc=%d\n", (unsigned int)*addr, *len, rc);
return rc;
}
-
-
-
static int msm_audio_ion_probe(struct platform_device *pdev)
{
int rc = 0;
@@ -283,13 +428,53 @@
msm_audio_ion_dt);
msm_audio_ion_data.smmu_enabled = smmu_enabled;
+ if (smmu_enabled) {
+ msm_audio_ion_data.group = iommu_group_find("lpass_audio");
+ if (!msm_audio_ion_data.group) {
+ pr_debug("Failed to find group lpass_audio deferred\n");
+ goto fail_group;
+ }
+ msm_audio_ion_data.domain =
+ iommu_group_get_iommudata(msm_audio_ion_data.group);
+ if (IS_ERR_OR_NULL(msm_audio_ion_data.domain)) {
+ pr_err("Failed to get domain data for group %p",
+ msm_audio_ion_data.group);
+ goto fail_group;
+ }
+ msm_audio_ion_data.domain_id =
+ msm_find_domain_no(msm_audio_ion_data.domain);
+ if (msm_audio_ion_data.domain_id < 0) {
+ pr_err("Failed to get domain index for domain %p",
+ msm_audio_ion_data.domain);
+ goto fail_group;
+ }
+ pr_debug("domain=%p, domain_id=%d, group=%p",
+ msm_audio_ion_data.domain,
+ msm_audio_ion_data.domain_id, msm_audio_ion_data.group);
+
+ /* iommu_attach_group() will make AXI clock ON. For future PL
+ this will require to be called in once per session */
+ rc = iommu_attach_group(msm_audio_ion_data.domain,
+ msm_audio_ion_data.group);
+ if (rc) {
+ pr_err("%s:ION attach group failed %d\n", __func__, rc);
+ return rc;
+ }
+
+ }
+
pr_debug("%s: SMMU-Enabled = %d\n", __func__, smmu_enabled);
return rc;
+
+fail_group:
+ return -EPROBE_DEFER;
}
static int msm_audio_ion_remove(struct platform_device *pdev)
{
- pr_debug("%s: msm audio ion is unloaded\n", __func__);
+ pr_debug("%s: msm audio ion is unloaded, domain=%p, group=%p\n",
+ __func__, msm_audio_ion_data.domain, msm_audio_ion_data.group);
+ iommu_detach_group(msm_audio_ion_data.domain, msm_audio_ion_data.group);
return 0;
}
diff --git a/arch/arm/mach-msm/subsystem_restart.c b/arch/arm/mach-msm/subsystem_restart.c
index 9479d46c..26f0210 100644
--- a/arch/arm/mach-msm/subsystem_restart.c
+++ b/arch/arm/mach-msm/subsystem_restart.c
@@ -495,7 +495,7 @@
if (ret)
return ret;
- if (!subsys->desc->is_loadable)
+ if (subsys->desc->is_not_loadable)
return 0;
ret = wait_for_err_ready(subsys);
diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index c3ff7dc..2776c58 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.c
@@ -69,7 +69,7 @@
type = *(uint32_t *)(buf);
data_len = *(uint32_t *)(buf + 4);
if (type < DIAG_CTRL_MSG_REG ||
- type > DIAG_CTRL_MSG_F3_MASK_V2) {
+ type > DIAG_CTRL_MSG_LAST) {
pr_alert("diag: In %s, Invalid Msg type %d proc %d",
__func__, type, smd_info->peripheral);
break;
diff --git a/drivers/char/diag/diagfwd_cntl.h b/drivers/char/diag/diagfwd_cntl.h
index 9c2c691..f58ab24 100644
--- a/drivers/char/diag/diagfwd_cntl.h
+++ b/drivers/char/diag/diagfwd_cntl.h
@@ -29,6 +29,12 @@
#define DIAG_CTRL_MSG_EVENT_MASK_V2 10
/* Send Diag F3 mask */
#define DIAG_CTRL_MSG_F3_MASK_V2 11
+#define DIAG_CTRL_MSG_NUM_PRESETS 12
+#define DIAG_CTRL_MSG_SET_PRESET_ID 13
+#define DIAG_CTRL_MSG_LOG_MASK_WITH_PRESET_ID 14
+#define DIAG_CTRL_MSG_EVENT_MASK_WITH_PRESET_ID 15
+#define DIAG_CTRL_MSG_F3_MASK_WITH_PRESET_ID 16
+#define DIAG_CTRL_MSG_LAST DIAG_CTRL_MSG_F3_MASK_WITH_PRESET_ID
/* Denotes that we support sending/receiving the feature mask */
#define F_DIAG_INT_FEATURE_MASK 0x01
diff --git a/drivers/coresight/coresight-tpiu.c b/drivers/coresight/coresight-tpiu.c
index 7ea71d3..8597e29 100644
--- a/drivers/coresight/coresight-tpiu.c
+++ b/drivers/coresight/coresight-tpiu.c
@@ -218,6 +218,24 @@
return 0;
}
+static int tpiu_reg_set_optimum_mode(struct regulator *reg,
+ unsigned int reg_hpm)
+{
+ if (regulator_count_voltages(reg) <= 0)
+ return 0;
+
+ return regulator_set_optimum_mode(reg, reg_hpm);
+}
+
+static int tpiu_reg_set_voltage(struct regulator *reg, unsigned int reg_low,
+ unsigned int reg_high)
+{
+ if (regulator_count_voltages(reg) <= 0)
+ return 0;
+
+ return regulator_set_voltage(reg, reg_low, reg_high);
+}
+
static int __tpiu_enable_to_sdc(struct tpiu_drvdata *drvdata)
{
int ret;
@@ -225,11 +243,11 @@
if (!drvdata->reg)
return -EINVAL;
- ret = regulator_set_optimum_mode(drvdata->reg, drvdata->reg_hpm);
+ ret = tpiu_reg_set_optimum_mode(drvdata->reg, drvdata->reg_hpm);
if (ret < 0)
return ret;
- ret = regulator_set_voltage(drvdata->reg, drvdata->reg_low,
- drvdata->reg_high);
+ ret = tpiu_reg_set_voltage(drvdata->reg, drvdata->reg_low,
+ drvdata->reg_high);
if (ret)
goto err0;
ret = regulator_enable(drvdata->reg);
@@ -248,9 +266,9 @@
return 0;
err1:
- regulator_set_voltage(drvdata->reg, 0, drvdata->reg_high);
+ tpiu_reg_set_voltage(drvdata->reg, 0, drvdata->reg_high);
err0:
- regulator_set_optimum_mode(drvdata->reg, 0);
+ tpiu_reg_set_optimum_mode(drvdata->reg, 0);
return ret;
}
@@ -325,8 +343,8 @@
msm_tlmm_misc_reg_write(TLMM_ETM_MODE_REG, 0);
regulator_disable(drvdata->reg);
- regulator_set_optimum_mode(drvdata->reg, 0);
- regulator_set_voltage(drvdata->reg, 0, drvdata->reg_high);
+ tpiu_reg_set_optimum_mode(drvdata->reg, 0);
+ tpiu_reg_set_voltage(drvdata->reg, 0, drvdata->reg_high);
}
static void tpiu_disable(struct coresight_device *csdev)
@@ -531,7 +549,7 @@
prop = of_get_property(node, "qcom,vdd-voltage-level", &len);
if (!prop || (len != (2 * sizeof(__be32)))) {
of_node_put(reg_node);
- return -EINVAL;
+ dev_err(dev, "sdc voltage levels not specified\n");
} else {
drvdata->reg_low = be32_to_cpup(&prop[0]);
drvdata->reg_high = be32_to_cpup(&prop[1]);
@@ -540,7 +558,7 @@
prop = of_get_property(node, "qcom,vdd-current-level", &len);
if (!prop || (len != (2 * sizeof(__be32)))) {
of_node_put(reg_node);
- return -EINVAL;
+ dev_err(dev, "sdc current levels not specified\n");
} else {
drvdata->reg_lpm = be32_to_cpup(&prop[0]);
drvdata->reg_hpm = be32_to_cpup(&prop[1]);
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index d95c12b..f071801 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -813,7 +813,8 @@
struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
if (!adreno_dev->drawctxt_active ||
- KGSL_STATE_ACTIVE != device->state) {
+ KGSL_STATE_ACTIVE != device->state ||
+ !device->active_cnt) {
kgsl_mmu_device_setstate(&device->mmu, flags);
return;
}
diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c
index 967e4ab..144c3d6 100644
--- a/drivers/gpu/msm/adreno_snapshot.c
+++ b/drivers/gpu/msm/adreno_snapshot.c
@@ -822,7 +822,8 @@
int remain, void *priv)
{
struct kgsl_snapshot_replay_mem_list *header = snapshot;
- struct kgsl_process_private *private;
+ struct kgsl_process_private *private = NULL;
+ struct kgsl_process_private *tmp_private;
unsigned int ptbase;
struct rb_node *node;
struct kgsl_mem_entry *entry = NULL;
@@ -831,10 +832,12 @@
ptbase = kgsl_mmu_get_current_ptbase(&device->mmu);
mutex_lock(&kgsl_driver.process_mutex);
- list_for_each_entry(private, &kgsl_driver.process_list, list) {
- if (kgsl_mmu_pt_equal(&device->mmu, private->pagetable,
- ptbase))
+ list_for_each_entry(tmp_private, &kgsl_driver.process_list, list) {
+ if (kgsl_mmu_pt_equal(&device->mmu, tmp_private->pagetable,
+ ptbase)) {
+ private = tmp_private;
break;
+ }
}
mutex_unlock(&kgsl_driver.process_mutex);
if (!private) {
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 2b674ab..07f8ef5 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -677,78 +677,44 @@
}
EXPORT_SYMBOL(kgsl_late_resume_driver);
-/* file operations */
-static struct kgsl_process_private *
-kgsl_get_process_private(struct kgsl_device_private *cur_dev_priv)
+/**
+ * kgsl_destroy_process_private() - Cleanup function to free process private
+ * @kref: - Pointer to object being destroyed's kref struct
+ * Free struct object and all other resources attached to it.
+ * Since the function can be used when not all resources inside process
+ * private have been allocated, there is a check to (before each resource
+ * cleanup) see if the struct member being cleaned is in fact allocated or not.
+ * If the value is not NULL, resource is freed.
+ */
+static void kgsl_destroy_process_private(struct kref *kref)
{
- struct kgsl_process_private *private;
- mutex_lock(&kgsl_driver.process_mutex);
- list_for_each_entry(private, &kgsl_driver.process_list, list) {
- if (private->pid == task_tgid_nr(current)) {
- private->refcnt++;
- goto out;
- }
- }
-
- /* no existing process private found for this dev_priv, create one */
- private = kzalloc(sizeof(struct kgsl_process_private), GFP_KERNEL);
- if (private == NULL) {
- KGSL_DRV_ERR(cur_dev_priv->device, "kzalloc(%d) failed\n",
- sizeof(struct kgsl_process_private));
- goto out;
- }
-
- spin_lock_init(&private->mem_lock);
- private->refcnt = 1;
- private->pid = task_tgid_nr(current);
- private->mem_rb = RB_ROOT;
-
- idr_init(&private->mem_idr);
-
- if (kgsl_mmu_enabled())
- {
- unsigned long pt_name;
- struct kgsl_mmu *mmu = &cur_dev_priv->device->mmu;
-
- pt_name = task_tgid_nr(current);
- private->pagetable = kgsl_mmu_getpagetable(mmu, pt_name);
- if (private->pagetable == NULL) {
- kfree(private);
- private = NULL;
- goto out;
- }
- }
-
- list_add(&private->list, &kgsl_driver.process_list);
-
- kgsl_process_init_sysfs(private);
- kgsl_process_init_debugfs(private);
-
-out:
- mutex_unlock(&kgsl_driver.process_mutex);
- return private;
-}
-
-static void
-kgsl_put_process_private(struct kgsl_device *device,
- struct kgsl_process_private *private)
-{
struct kgsl_mem_entry *entry = NULL;
int next = 0;
- if (!private)
+
+ struct kgsl_process_private *private = container_of(kref,
+ struct kgsl_process_private, refcount);
+
+ /*
+ * Remove this process from global process list
+ * We do not acquire a lock first as it is expected that
+ * kgsl_destroy_process_private() is only going to be called
+ * through kref_put() which is only called after acquiring
+ * the lock.
+ */
+ if (!private) {
+ KGSL_CORE_ERR("Cannot destroy null process private\n");
+ mutex_unlock(&kgsl_driver.process_mutex);
return;
-
- mutex_lock(&kgsl_driver.process_mutex);
-
- if (--private->refcnt)
- goto unlock;
-
- kgsl_process_uninit_sysfs(private);
- debugfs_remove_recursive(private->debug_root);
-
+ }
list_del(&private->list);
+ mutex_unlock(&kgsl_driver.process_mutex);
+
+ if (private->kobj.parent)
+ kgsl_process_uninit_sysfs(private);
+ if (private->debug_root)
+ debugfs_remove_recursive(private->debug_root);
while (1) {
rcu_read_lock();
@@ -766,9 +732,110 @@
}
kgsl_mmu_putpagetable(private->pagetable);
idr_destroy(&private->mem_idr);
+
kfree(private);
-unlock:
+ return;
+}
+
+static void
+kgsl_put_process_private(struct kgsl_device *device,
+ struct kgsl_process_private *private)
+{
+ mutex_lock(&kgsl_driver.process_mutex);
+
+ /*
+ * kref_put() returns 1 when the refcnt has reached 0 and the destroy
+ * function is called. Mutex is released in the destroy function if
+ * its called, so only release mutex if kref_put() return 0
+ */
+ if (!kref_put(&private->refcount, kgsl_destroy_process_private))
+ mutex_unlock(&kgsl_driver.process_mutex);
+ return;
+}
+
+/**
+ * find_process_private() - Helper function to search for process private
+ * @cur_dev_priv: Pointer to device private structure which contains pointers
+ * to device and process_private structs.
+ * Returns: Pointer to the found/newly created private struct
+ */
+static struct kgsl_process_private *
+kgsl_find_process_private(struct kgsl_device_private *cur_dev_priv)
+{
+ struct kgsl_process_private *private;
+
+ /* Search in the process list */
+ mutex_lock(&kgsl_driver.process_mutex);
+ list_for_each_entry(private, &kgsl_driver.process_list, list) {
+ if (private->pid == task_tgid_nr(current)) {
+ kref_get(&private->refcount);
+ goto done;
+ }
+ }
+
+ /* no existing process private found for this dev_priv, create one */
+ private = kzalloc(sizeof(struct kgsl_process_private), GFP_KERNEL);
+ if (private == NULL) {
+ KGSL_DRV_ERR(cur_dev_priv->device, "kzalloc(%d) failed\n",
+ sizeof(struct kgsl_process_private));
+ goto done;
+ }
+
+ kref_init(&private->refcount);
+
+ private->pid = task_tgid_nr(current);
+ spin_lock_init(&private->mem_lock);
+ mutex_init(&private->process_private_mutex);
+ /* Add the newly created process struct obj to the process list */
+ list_add(&private->list, &kgsl_driver.process_list);
+done:
mutex_unlock(&kgsl_driver.process_mutex);
+ return private;
+}
+
+/**
+ * kgsl_get_process_private() - Used to find the process private structure
+ * @cur_dev_priv: Current device pointer
+ * Finds or creates a new porcess private structire and initializes its members
+ * Returns: Pointer to the private process struct obj found/created or
+ * NULL if pagetable creation for this process private obj failed.
+ */
+static struct kgsl_process_private *
+kgsl_get_process_private(struct kgsl_device_private *cur_dev_priv)
+{
+ struct kgsl_process_private *private;
+
+ private = kgsl_find_process_private(cur_dev_priv);
+
+ mutex_lock(&private->process_private_mutex);
+
+ if (!private->mem_rb.rb_node) {
+ private->mem_rb = RB_ROOT;
+ idr_init(&private->mem_idr);
+ }
+
+ if ((!private->pagetable) && kgsl_mmu_enabled()) {
+ unsigned long pt_name;
+ struct kgsl_mmu *mmu = &cur_dev_priv->device->mmu;
+
+ pt_name = task_tgid_nr(current);
+ private->pagetable = kgsl_mmu_getpagetable(mmu, pt_name);
+ if (private->pagetable == NULL) {
+ mutex_unlock(&private->process_private_mutex);
+ kgsl_put_process_private(cur_dev_priv->device,
+ private);
+ return NULL;
+ }
+ }
+
+ if (!private->kobj.parent)
+ kgsl_process_init_sysfs(private);
+ if (!private->debug_root)
+ kgsl_process_init_debugfs(private);
+
+ mutex_unlock(&private->process_private_mutex);
+
+ return private;
}
static int kgsl_release(struct inode *inodep, struct file *filep)
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index debba18..94cc551 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -46,7 +46,11 @@
#define KGSL_PAGETABLE_ENTRY_SIZE 4
/* Pagetable Virtual Address base */
+#ifndef CONFIG_MSM_KGSL_CFF_DUMP
#define KGSL_PAGETABLE_BASE 0x10000000
+#else
+#define KGSL_PAGETABLE_BASE 0xE0000000
+#endif
/* Extra accounting entries needed in the pagetable */
#define KGSL_PT_EXTRA_ENTRIES 16
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index ac82820..42c1475 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -280,6 +280,12 @@
unsigned int refcnt;
pid_t pid;
spinlock_t mem_lock;
+
+ /* General refcount for process private struct obj */
+ struct kref refcount;
+ /* Mutex to synchronize access to each process_private struct obj */
+ struct mutex process_private_mutex;
+
struct rb_root mem_rb;
struct idr mem_idr;
struct kgsl_pagetable *pagetable;
diff --git a/drivers/gpu/msm/kgsl_events.c b/drivers/gpu/msm/kgsl_events.c
index d872783..3b01e54 100644
--- a/drivers/gpu/msm/kgsl_events.c
+++ b/drivers/gpu/msm/kgsl_events.c
@@ -143,6 +143,15 @@
cur = kgsl_readtimestamp(device, context, KGSL_TIMESTAMP_RETIRED);
id = context->id;
+ /*
+ * Increment the refcount to avoid freeing the context while
+ * cancelling its events
+ */
+ kgsl_context_get(context);
+
+ /* Remove ourselves from the master pending list */
+ list_del_init(&context->events_list);
+
list_for_each_entry_safe(event, event_tmp, &context->events, list) {
/*
* "cancel" the events by calling their callback.
@@ -165,9 +174,7 @@
kgsl_active_count_put(device);
}
-
- /* Remove ourselves from the master pending list */
- list_del_init(&context->events_list);
+ kgsl_context_put(context);
}
/**
@@ -313,12 +320,18 @@
events_list) {
/*
+ * Increment the refcount to make sure that the list_del_init
+ * is called with a valid context's list
+ */
+ kgsl_context_get(context);
+ /*
* If kgsl_timestamp_expired_context returns 0 then it no longer
* has any pending events and can be removed from the list
*/
if (kgsl_process_context_events(device, context) == 0)
list_del_init(&context->events_list);
+ kgsl_context_put(context);
}
mutex_unlock(&device->mutex);
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index 3057723..513fb90 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -1345,13 +1345,27 @@
* we're better off with extra room.
*/
if (mmu->pt_per_process) {
+#ifndef CONFIG_MSM_KGSL_CFF_DUMP
mmu->pt_base = PAGE_OFFSET;
mmu->pt_size = KGSL_IOMMU_GLOBAL_MEM_BASE
- kgsl_mmu_get_base_addr(mmu) - SZ_1M;
mmu->use_cpu_map = true;
+#else
+ mmu->pt_base = KGSL_PAGETABLE_BASE;
+ mmu->pt_size = KGSL_IOMMU_GLOBAL_MEM_BASE +
+ KGSL_IOMMU_GLOBAL_MEM_SIZE -
+ KGSL_PAGETABLE_BASE;
+ mmu->use_cpu_map = false;
+#endif
} else {
mmu->pt_base = KGSL_PAGETABLE_BASE;
+#ifndef CONFIG_MSM_KGSL_CFF_DUMP
mmu->pt_size = SZ_2G;
+#else
+ mmu->pt_size = KGSL_IOMMU_GLOBAL_MEM_BASE +
+ KGSL_IOMMU_GLOBAL_MEM_SIZE -
+ KGSL_PAGETABLE_BASE;
+#endif
mmu->use_cpu_map = false;
}
diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h
index ef5b0f4..02cde94 100644
--- a/drivers/gpu/msm/kgsl_mmu.h
+++ b/drivers/gpu/msm/kgsl_mmu.h
@@ -410,7 +410,7 @@
*/
static inline int kgsl_mmu_use_cpu_map(struct kgsl_mmu *mmu)
{
- return mmu->pt_per_process;
+ return mmu->use_cpu_map;
}
/*
diff --git a/drivers/input/touchscreen/gen_vkeys.c b/drivers/input/touchscreen/gen_vkeys.c
index 21e4829..efddf61 100644
--- a/drivers/input/touchscreen/gen_vkeys.c
+++ b/drivers/input/touchscreen/gen_vkeys.c
@@ -24,6 +24,8 @@
#define HEIGHT_SCALE_NUM 8
#define HEIGHT_SCALE_DENOM 10
+#define VKEY_Y_OFFSET_DEFAULT 0
+
/* numerator and denomenator for border equations */
#define BORDER_ADJUST_NUM 3
#define BORDER_ADJUST_DENOM 4
@@ -59,7 +61,7 @@
{
struct device_node *np = dev->of_node;
struct property *prop;
- int rc;
+ int rc, val;
rc = of_property_read_string(np, "label", &pdata->name);
if (rc) {
@@ -106,10 +108,13 @@
}
}
- rc = of_property_read_u32(np, "qcom,y-offset", &pdata->y_offset);
- if (rc) {
+ pdata->y_offset = VKEY_Y_OFFSET_DEFAULT;
+ rc = of_property_read_u32(np, "qcom,y-offset", &val);
+ if (!rc)
+ pdata->y_offset = val;
+ else if (rc != -EINVAL) {
dev_err(dev, "Failed to read y position offset\n");
- return -EINVAL;
+ return rc;
}
return 0;
}
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c
index 59b9746..509567c 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c
@@ -70,7 +70,7 @@
}
static struct msm_cam_clk_info jpeg_8x_clk_info[] = {
- {"core_clk", 228570000},
+ {"core_clk", JPEG_CLK_RATE},
{"iface_clk", -1},
{"bus_clk0", -1},
{"camss_top_ahb_clk", -1},
@@ -135,8 +135,8 @@
{
.src = MSM_BUS_MASTER_JPEG,
.dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 1027648000,
- .ib = 1105920000,
+ .ab = JPEG_CLK_RATE * 2.5,
+ .ib = JPEG_CLK_RATE * 2.5,
},
};
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.h b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.h
index cd80d2e..a14b8ee 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.h
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.h
@@ -1,4 +1,4 @@
-/* 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
@@ -19,6 +19,7 @@
#include <linux/iommu.h>
#include <mach/iommu.h>
#include "msm_jpeg_sync.h"
+#define JPEG_CLK_RATE 266670000
void msm_jpeg_platform_p2v(struct msm_jpeg_device *pgmn_dev, struct file *file,
struct ion_handle **ionhandle, int domain_num);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 39d73ca..ade8597 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -61,8 +61,29 @@
if (inst->session_type == type &&
inst->state >= MSM_VIDC_OPEN_DONE &&
inst->state < MSM_VIDC_STOP_DONE) {
- num_mbs_per_sec += NUM_MBS_PER_SEC(inst->prop.height,
- inst->prop.width, inst->prop.fps);
+ int stride, scanlines, rc;
+ struct hfi_device *hdev;
+
+ hdev = inst->core->device;
+ if (!hdev) {
+ dprintk(VIDC_ERR,
+ "No hdev (probably in bad state)\n");
+ return -EINVAL;
+ }
+
+ rc = call_hfi_op(hdev, get_stride_scanline,
+ COLOR_FMT_NV12,
+ inst->prop.width, inst->prop.height,
+ &stride, &scanlines);
+ if (rc) {
+ dprintk(VIDC_WARN,
+ "Failed to determine stride/scan when getting load. Perf. might be affected\n");
+ stride = inst->prop.width;
+ scanlines = inst->prop.height;
+ }
+
+ num_mbs_per_sec += NUM_MBS_PER_SEC(stride, scanlines,
+ inst->prop.fps);
}
mutex_unlock(&inst->lock);
}
diff --git a/drivers/platform/msm/ipa/ipa_dp.c b/drivers/platform/msm/ipa/ipa_dp.c
index 76aaad0..1b6181f 100644
--- a/drivers/platform/msm/ipa/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_dp.c
@@ -232,7 +232,7 @@
struct ipa_tx_pkt_wrapper *tx_pkt;
unsigned long irq_flags;
int result;
- u16 sps_flags = SPS_IOVEC_FLAG_EOT | SPS_IOVEC_FLAG_INT;
+ u16 sps_flags = SPS_IOVEC_FLAG_EOT;
dma_addr_t dma_address;
u16 len;
u32 mem_flag = GFP_ATOMIC;
@@ -469,8 +469,7 @@
}
if (i == (num_desc - 1)) {
- iovec->flags |= (SPS_IOVEC_FLAG_EOT |
- SPS_IOVEC_FLAG_INT);
+ iovec->flags |= SPS_IOVEC_FLAG_EOT;
/* "mark" the last desc */
tx_pkt->cnt = IPA_LAST_DESC_CNT;
}
@@ -1018,11 +1017,8 @@
ipa_ctx->ep[ipa_ep_idx].connect.dest_pipe_index =
ipa_ctx->a5_pipe_index++;
ipa_ctx->ep[ipa_ep_idx].connect.src_pipe_index = ipa_ep_idx;
- ipa_ctx->ep[ipa_ep_idx].connect.options =
- SPS_O_AUTO_ENABLE | SPS_O_EOT | SPS_O_ACK_TRANSFERS |
+ ipa_ctx->ep[ipa_ep_idx].connect.options = SPS_O_ACK_TRANSFERS |
SPS_O_NO_DISABLE;
- if (ipa_ctx->polling_mode)
- ipa_ctx->ep[ipa_ep_idx].connect.options |= SPS_O_POLL;
} else {
ipa_ctx->ep[ipa_ep_idx].connect.mode = SPS_MODE_DEST;
ipa_ctx->ep[ipa_ep_idx].connect.source = SPS_DEV_HANDLE_MEM;
@@ -1031,13 +1027,16 @@
ipa_ctx->ep[ipa_ep_idx].connect.src_pipe_index =
ipa_ctx->a5_pipe_index++;
ipa_ctx->ep[ipa_ep_idx].connect.dest_pipe_index = ipa_ep_idx;
- ipa_ctx->ep[ipa_ep_idx].connect.options =
- SPS_O_AUTO_ENABLE | SPS_O_EOT;
- if (ipa_ctx->polling_mode)
+ if (sys_in->client == IPA_CLIENT_A5_LAN_WAN_PROD)
ipa_ctx->ep[ipa_ep_idx].connect.options |=
- SPS_O_ACK_TRANSFERS | SPS_O_POLL;
+ SPS_O_ACK_TRANSFERS;
}
+ ipa_ctx->ep[ipa_ep_idx].connect.options |= (SPS_O_AUTO_ENABLE |
+ SPS_O_EOT);
+ if (ipa_ctx->polling_mode)
+ ipa_ctx->ep[ipa_ep_idx].connect.options |= SPS_O_POLL;
+
ipa_ctx->ep[ipa_ep_idx].connect.desc.size = sys_in->desc_fifo_sz;
ipa_ctx->ep[ipa_ep_idx].connect.desc.base =
dma_alloc_coherent(NULL, ipa_ctx->ep[ipa_ep_idx].connect.desc.size,
@@ -1346,7 +1345,7 @@
ret = sps_transfer_one(sys->ep->ep_hdl, rx_pkt->dma_address,
IPA_RX_SKB_SIZE, rx_pkt,
- SPS_IOVEC_FLAG_INT);
+ 0);
if (ret) {
IPAERR("sps_transfer_one failed %d\n", ret);
diff --git a/drivers/platform/msm/ipa/teth_bridge.c b/drivers/platform/msm/ipa/teth_bridge.c
index 9062ab8..add9522 100644
--- a/drivers/platform/msm/ipa/teth_bridge.c
+++ b/drivers/platform/msm/ipa/teth_bridge.c
@@ -128,8 +128,10 @@
* @teth_wq: dedicated workqueue, used for setting up the HW bridge and for
* sending packets using the SW bridge when the system is waking up from power
* collapse
- * @a2_ipa_hdr_len: A2 to IPA header length, used to configure the A2 endpoint
- * for header removal
+ * @a2_ipa_hdr_len: A2 to IPA header length, used for configuring the A2
+ * endpoint for header removal
+ * @ipa_a2_hdr_len: IPA to A2 header length, used for configuring the A2
+ * endpoint for header removal
* @hdr_del: array to store the headers handles in order to delete them later
* @routing_del: array of routing rules handles, one array for IPv4 and one for
* IPv6
@@ -160,6 +162,7 @@
struct stats stats;
struct workqueue_struct *teth_wq;
u16 a2_ipa_hdr_len;
+ u16 ipa_a2_hdr_len;
struct ipa_ioc_del_hdr *hdr_del;
struct ipa_ioc_del_rt_rule *routing_del[TETH_IP_FAMILIES];
struct ipa_ioc_del_flt_rule *filtering_del[TETH_IP_FAMILIES];
@@ -287,6 +290,7 @@
}
hdr_cfg.hdr_len = ipa_a2_hdr_len;
+ teth_ctx->ipa_a2_hdr_len = ipa_a2_hdr_len;
res = ipa_cfg_ep_hdr(teth_ctx->ipa_a2_pipe_hdl, &hdr_cfg);
if (res) {
TETH_ERR("Header insertion config for IPA->A2 pipe failed\n");
@@ -1225,6 +1229,28 @@
enum ipa_rm_event event,
unsigned long data)
{
+ switch (event) {
+ case IPA_RM_RESOURCE_GRANTED:
+ complete(&teth_ctx->is_bridge_prod_up);
+ break;
+
+ case IPA_RM_RESOURCE_RELEASED:
+ complete(&teth_ctx->is_bridge_prod_down);
+ break;
+
+ default:
+ TETH_ERR("Unsupported notification!\n");
+ WARN_ON(1);
+ break;
+ }
+
+ return;
+}
+
+static void a2_prod_notify_cb(void *notify_cb_data,
+ enum ipa_rm_event event,
+ unsigned long data)
+{
int res;
struct ipa_ep_cfg ipa_ep_cfg;
@@ -1243,15 +1269,15 @@
/* Reset the various endpoints configuration */
memset(&ipa_ep_cfg, 0, sizeof(ipa_ep_cfg));
+ ipa_ep_cfg.hdr.hdr_len = teth_ctx->ipa_a2_hdr_len;
ipa_cfg_ep(teth_ctx->ipa_a2_pipe_hdl, &ipa_ep_cfg);
+ memset(&ipa_ep_cfg, 0, sizeof(ipa_ep_cfg));
ipa_ep_cfg.hdr.hdr_len = teth_ctx->a2_ipa_hdr_len;
ipa_cfg_ep(teth_ctx->a2_ipa_pipe_hdl, &ipa_ep_cfg);
- complete(&teth_ctx->is_bridge_prod_up);
break;
case IPA_RM_RESOURCE_RELEASED:
- complete(&teth_ctx->is_bridge_prod_down);
break;
default:
@@ -1283,6 +1309,7 @@
int teth_bridge_init(ipa_notify_cb *usb_notify_cb_ptr, void **private_data_ptr)
{
int res = 0;
+ struct ipa_rm_register_params a2_prod_reg_params;
TETH_DBG_FUNC_ENTRY();
if (usb_notify_cb_ptr == NULL) {
@@ -1323,10 +1350,22 @@
goto fail_add_dependency_3;
}
+ /* Register for A2_PROD resource notifications */
+ a2_prod_reg_params.user_data = NULL;
+ a2_prod_reg_params.notify_cb = a2_prod_notify_cb;
+ res = ipa_rm_register(IPA_RM_RESOURCE_A2_PROD, &a2_prod_reg_params);
+ if (res) {
+ TETH_ERR("ipa_rm_register() failed\n");
+ goto fail_add_dependency_4;
+ }
+
/* Return 0 as EINPROGRESS is a valid return value at this point */
res = 0;
goto bail;
+fail_add_dependency_4:
+ ipa_rm_delete_dependency(IPA_RM_RESOURCE_A2_PROD,
+ IPA_RM_RESOURCE_USB_CONS);
fail_add_dependency_3:
ipa_rm_delete_dependency(IPA_RM_RESOURCE_USB_PROD,
IPA_RM_RESOURCE_A2_CONS);
@@ -1368,6 +1407,7 @@
teth_ctx->comp_hw_bridge_in_progress = false;
memset(&teth_ctx->stats, 0, sizeof(teth_ctx->stats));
teth_ctx->a2_ipa_hdr_len = 0;
+ teth_ctx->ipa_a2_hdr_len = 0;
memset(teth_ctx->hdr_del,
0,
sizeof(struct ipa_ioc_del_hdr) + TETH_TOTAL_HDR_ENTRIES *
@@ -1402,6 +1442,7 @@
int teth_bridge_disconnect(void)
{
int res;
+ struct ipa_rm_register_params a2_prod_reg_params;
TETH_DBG_FUNC_ENTRY();
if (!teth_ctx->is_connected) {
@@ -1478,6 +1519,13 @@
TETH_ERR(
"Failed deleting ipa_rm dependency BRIDGE_PROD <-> A2_CONS\n");
+ /* Deregister from A2_PROD notifications */
+ a2_prod_reg_params.user_data = NULL;
+ a2_prod_reg_params.notify_cb = a2_prod_notify_cb;
+ res = ipa_rm_deregister(IPA_RM_RESOURCE_A2_PROD, &a2_prod_reg_params);
+ if (res)
+ TETH_ERR("Failed deregistering from A2_prod notifications.\n");
+
teth_ctx->is_connected = false;
bail:
TETH_DBG_FUNC_EXIT();
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index 2d1b763..64e8d7a 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -1744,10 +1744,12 @@
spin_lock(&usb_bam_lock);
- ctx.inactivity_timer_ms[bam] = timer_d;
/* Apply new timer setting if bam has running pipes */
- if (ctx.pipes_enabled_per_bam[bam] > 0)
- usb_bam_set_inactivity_timer(bam);
+ if (ctx.inactivity_timer_ms[bam] != timer_d) {
+ ctx.inactivity_timer_ms[bam] = timer_d;
+ if (ctx.pipes_enabled_per_bam[bam] > 0)
+ usb_bam_set_inactivity_timer(bam);
+ }
spin_unlock(&usb_bam_lock);
}
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
index 63fb0a5..5cdb666 100644
--- a/drivers/power/power_supply_sysfs.c
+++ b/drivers/power/power_supply_sysfs.c
@@ -176,6 +176,7 @@
POWER_SUPPLY_ATTR(type),
POWER_SUPPLY_ATTR(scope),
POWER_SUPPLY_ATTR(system_temp_level),
+ POWER_SUPPLY_ATTR(resistance),
/* Properties of type `const char *' */
POWER_SUPPLY_ATTR(model_name),
POWER_SUPPLY_ATTR(manufacturer),
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index eec6d39..7bc3214 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -135,6 +135,7 @@
struct sf_lut *rbatt_sf_lut;
int default_rbatt_mohm;
int rbatt_capacitive_mohm;
+ int rbatt_mohm;
struct delayed_work calculate_soc_delayed_work;
struct work_struct recalc_work;
@@ -184,7 +185,6 @@
unsigned int vadc_v0625;
unsigned int vadc_v1250;
- int ibat_max_ua;
int prev_uuc_iavg_ma;
int prev_pc_unusable;
int ibat_at_cv_ua;
@@ -218,7 +218,7 @@
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_CAPACITY,
POWER_SUPPLY_PROP_CURRENT_NOW,
- POWER_SUPPLY_PROP_CURRENT_MAX,
+ POWER_SUPPLY_PROP_RESISTANCE,
POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
};
@@ -1169,6 +1169,12 @@
params->rbatt_mohm = get_rbatt(chip, soc_rbatt, batt_temp);
pr_debug("rbatt_mohm = %d\n", params->rbatt_mohm);
+ if (params->rbatt_mohm != chip->rbatt_mohm
+ && chip->bms_psy.name != NULL) {
+ chip->rbatt_mohm = params->rbatt_mohm;
+ power_supply_changed(&chip->bms_psy);
+ }
+
calculate_iavg(chip, params->cc_uah, ¶ms->iavg_ua,
params->delta_time_s);
@@ -1389,9 +1395,6 @@
ocv_est_uv = vbat_uv + (ibat_ua * params->rbatt_mohm)/1000;
- chip->ibat_max_ua = (ocv_est_uv - chip->v_cutoff_uv) * 1000
- / (params->rbatt_mohm);
-
pc_est = calculate_pc(chip, ocv_est_uv, batt_temp);
soc_est = div_s64((s64)params->fcc_uah * pc_est - params->uuc_uah*100,
(s64)params->fcc_uah - params->uuc_uah);
@@ -1925,10 +1928,10 @@
return report_state_of_charge(chip);
}
-/* Returns estimated max current that the battery can supply in uA */
-static int get_prop_bms_current_max(struct qpnp_bms_chip *chip)
+/* Returns estimated battery resistance */
+static int get_prop_bms_batt_resistance(struct qpnp_bms_chip *chip)
{
- return chip->ibat_max_ua;
+ return chip->rbatt_mohm * 1000;
}
/* Returns instantaneous current in uA */
@@ -1985,8 +1988,8 @@
case POWER_SUPPLY_PROP_CURRENT_NOW:
val->intval = get_prop_bms_current_now(chip);
break;
- case POWER_SUPPLY_PROP_CURRENT_MAX:
- val->intval = get_prop_bms_current_max(chip);
+ case POWER_SUPPLY_PROP_RESISTANCE:
+ val->intval = get_prop_bms_batt_resistance(chip);
break;
case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
val->intval = get_prop_bms_charge_full_design(chip);
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index de2e5c1..089c129 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -818,7 +818,6 @@
POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_CAPACITY,
- POWER_SUPPLY_PROP_CURRENT_MAX,
POWER_SUPPLY_PROP_CURRENT_NOW,
POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
POWER_SUPPLY_PROP_TEMP,
@@ -958,21 +957,6 @@
return POWER_SUPPLY_STATUS_DISCHARGING;
}
-static int
-get_prop_current_max(struct qpnp_chg_chip *chip)
-{
- union power_supply_propval ret = {0,};
-
- if (chip->bms_psy) {
- chip->bms_psy->get_property(chip->bms_psy,
- POWER_SUPPLY_PROP_CURRENT_MAX, &ret);
- return ret.intval;
- } else {
- pr_debug("No BMS supply registered return 0\n");
- }
-
- return 0;
-}
static int
get_prop_current_now(struct qpnp_chg_chip *chip)
@@ -1151,9 +1135,6 @@
case POWER_SUPPLY_PROP_CAPACITY:
val->intval = get_prop_capacity(chip);
break;
- case POWER_SUPPLY_PROP_CURRENT_MAX:
- val->intval = get_prop_current_max(chip);
- break;
case POWER_SUPPLY_PROP_CURRENT_NOW:
val->intval = get_prop_current_now(chip);
break;
diff --git a/drivers/regulator/qpnp-regulator.c b/drivers/regulator/qpnp-regulator.c
index 2d10f89..c9d0500 100644
--- a/drivers/regulator/qpnp-regulator.c
+++ b/drivers/regulator/qpnp-regulator.c
@@ -514,8 +514,10 @@
{
struct qpnp_regulator *vreg = rdev_get_drvdata(rdev);
- if (vreg->ocp_irq)
+ if (vreg->ocp_irq) {
+ vreg->ocp_count = 0;
vreg->vs_enable_time = ktime_get();
+ }
return qpnp_regulator_common_enable(rdev);
}
diff --git a/include/linux/msm_audio_ion.h b/include/linux/msm_audio_ion.h
index 83e5dff..38b27bf 100644
--- a/include/linux/msm_audio_ion.h
+++ b/include/linux/msm_audio_ion.h
@@ -13,7 +13,12 @@
#ifndef _LINUX_MSM_AUDIO_ION_H
#define _LINUX_MSM_AUDIO_ION_H
-
+#ifdef CONFIG_SND_SOC_QDSP6V2
+#include <sound/q6asm-v2.h>
+#else
+#include <sound/q6asm.h>
+#endif
+#include <sound/pcm.h>
#include <linux/msm_ion.h>
@@ -26,9 +31,11 @@
unsigned long *ionflag, size_t bufsz,
ion_phys_addr_t *paddr, size_t *pa_len, void **vaddr);
int msm_audio_ion_free(struct ion_client *client, struct ion_handle *handle);
-
+int msm_audio_ion_mmap(struct audio_buffer *substream,
+ struct vm_area_struct *vma);
bool msm_audio_ion_is_smmu_available(void);
+int msm_audio_ion_cache_operations(struct audio_buffer *abuff, int cache_op);
#ifdef CONFIG_SND_SOC_QDSP6V2
struct ion_client *msm_audio_ion_client_create(unsigned int heap_mask,
diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h
index 2ad040e..e8de769 100644
--- a/include/linux/msm_kgsl.h
+++ b/include/linux/msm_kgsl.h
@@ -769,7 +769,7 @@
struct kgsl_perfcounter_read_group {
unsigned int groupid;
unsigned int countable;
- uint64_t value;
+ unsigned long long value;
};
struct kgsl_perfcounter_read {
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 6e30ca2..1de9aaa 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -127,6 +127,7 @@
POWER_SUPPLY_PROP_TYPE, /* use power_supply.type instead */
POWER_SUPPLY_PROP_SCOPE,
POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL,
+ POWER_SUPPLY_PROP_RESISTANCE,
/* Properties of type `const char *' */
POWER_SUPPLY_PROP_MODEL_NAME,
POWER_SUPPLY_PROP_MANUFACTURER,
diff --git a/include/linux/regulator/cpr-regulator.h b/include/linux/regulator/cpr-regulator.h
index b6fc091..6387913 100644
--- a/include/linux/regulator/cpr-regulator.h
+++ b/include/linux/regulator/cpr-regulator.h
@@ -35,7 +35,6 @@
CPR_CORNER_SVS = 1,
CPR_CORNER_NORMAL,
CPR_CORNER_TURBO,
- CPR_CORNER_SUPER_TURBO,
CPR_CORNER_MAX,
};
diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h
index 2d34d70..2138689 100644
--- a/include/sound/q6asm-v2.h
+++ b/include/sound/q6asm-v2.h
@@ -165,6 +165,8 @@
wait_queue_head_t cmd_wait;
wait_queue_head_t time_wait;
bool perf_mode;
+ /* audio cache operations fptr*/
+ int (*fptr_cache_ops)(struct audio_buffer *abuff, int cache_op);
};
void q6asm_audio_client_free(struct audio_client *ac);
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index 51334f2..2a60b88 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -2388,7 +2388,7 @@
{
struct msm8974_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
int ret;
- if (pdata->us_euro_gpio) {
+ if (pdata->us_euro_gpio >= 0) {
dev_dbg(card->dev, "%s : us_euro gpio request %d", __func__,
pdata->us_euro_gpio);
ret = gpio_request(pdata->us_euro_gpio, "TAIKO_CODEC_US_EURO");
@@ -2524,7 +2524,7 @@
pdata->us_euro_gpio = of_get_named_gpio(pdev->dev.of_node,
"qcom,us-euro-gpios", 0);
if (pdata->us_euro_gpio < 0) {
- dev_err(&pdev->dev, "Looking up %s property in node %s failed",
+ dev_info(&pdev->dev, "property %s not detected in node %s",
"qcom,us-euro-gpios",
pdev->dev.of_node->full_name);
} else {
diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
index 9dbbf20..ec5359c 100644
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
@@ -29,6 +29,7 @@
#include <sound/pcm_params.h>
#include <asm/dma.h>
#include <linux/dma-mapping.h>
+#include <linux/msm_audio_ion.h>
#include <sound/timer.h>
@@ -728,25 +729,14 @@
static int msm_compr_mmap(struct snd_pcm_substream *substream,
struct vm_area_struct *vma)
{
- int result = 0;
struct snd_pcm_runtime *runtime = substream->runtime;
- struct compr_audio *compr = runtime->private_data;
- struct msm_audio *prtd = &compr->prtd;
-
- pr_debug("%s\n", __func__);
+ struct msm_audio *prtd = runtime->private_data;
+ struct audio_client *ac = prtd->audio_client;
+ struct audio_port_data *apd = ac->port;
+ struct audio_buffer *ab = &(apd[IN].buf[0]);
prtd->mmap_flag = 1;
- runtime->render_flag = SNDRV_NON_DMA_MODE;
- if (runtime->dma_addr && runtime->dma_bytes) {
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
- result = remap_pfn_range(vma, vma->vm_start,
- runtime->dma_addr >> PAGE_SHIFT,
- runtime->dma_bytes,
- vma->vm_page_prot);
- } else {
- pr_err("Physical address or size of buf is NULL");
- return -EINVAL;
- }
- return result;
+
+ return msm_audio_ion_mmap(ab, vma);
}
static int msm_compr_hw_params(struct snd_pcm_substream *substream,
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
index 27b3f56..7055c57 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
@@ -29,6 +29,8 @@
#include <linux/dma-mapping.h>
#include <linux/of_device.h>
+#include <linux/msm_audio_ion.h>
+
#include <sound/compress_params.h>
#include <sound/compress_offload.h>
#include <sound/compress_driver.h>
@@ -421,24 +423,14 @@
static int msm_pcm_mmap(struct snd_pcm_substream *substream,
struct vm_area_struct *vma)
{
- int result = 0;
struct snd_pcm_runtime *runtime = substream->runtime;
struct msm_audio *prtd = runtime->private_data;
-
- pr_debug("%s\n", __func__);
+ struct audio_client *ac = prtd->audio_client;
+ struct audio_port_data *apd = ac->port;
+ struct audio_buffer *ab = &(apd[IN].buf[0]);
prtd->mmap_flag = 1;
- if (runtime->dma_addr && runtime->dma_bytes) {
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
- result = remap_pfn_range(vma, vma->vm_start,
- runtime->dma_addr >> PAGE_SHIFT,
- runtime->dma_bytes,
- vma->vm_page_prot);
- } else {
- pr_err("Physical address or size of buf is NULL");
- return -EINVAL;
- }
- return result;
+ return msm_audio_ion_mmap(ab, vma);
}
static int msm_pcm_hw_params(struct snd_pcm_substream *substream,
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index 9fbf749..f4ca5b8 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -27,6 +27,7 @@
#include <sound/control.h>
#include <asm/dma.h>
#include <linux/dma-mapping.h>
+#include <linux/msm_audio_ion.h>
#include <linux/of_device.h>
#include <sound/pcm_params.h>
@@ -628,25 +629,14 @@
static int msm_pcm_mmap(struct snd_pcm_substream *substream,
struct vm_area_struct *vma)
{
- int result = 0;
struct snd_pcm_runtime *runtime = substream->runtime;
struct msm_audio *prtd = runtime->private_data;
-
- pr_debug("%s\n", __func__);
+ struct audio_client *ac = prtd->audio_client;
+ struct audio_port_data *apd = ac->port;
+ struct audio_buffer *ab = &(apd[IN].buf[0]);
prtd->mmap_flag = 1;
- if (runtime->dma_addr && runtime->dma_bytes) {
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
- result = remap_pfn_range(vma, vma->vm_start,
- runtime->dma_addr >> PAGE_SHIFT,
- runtime->dma_bytes,
- vma->vm_page_prot);
- } else {
- pr_err("Physical address or size of buf is NULL");
- return -EINVAL;
- }
-
- return result;
+ return msm_audio_ion_mmap(ab, vma);
}
static int msm_pcm_hw_params(struct snd_pcm_substream *substream,
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index af8e873..c2fd2d7 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -331,6 +331,7 @@
mutex_unlock(&session_lock);
ac->session = 0;
ac->perf_mode = 0;
+ ac->fptr_cache_ops = NULL;
return;
}
@@ -610,6 +611,7 @@
ac->priv = priv;
ac->io_mode = SYNC_IO_MODE;
ac->perf_mode = false;
+ ac->fptr_cache_ops = NULL;
ac->apr = apr_register("ADSP", "ASM", \
(apr_fn)q6asm_callback,\
((ac->session) << 8 | 0x0001),\