Merge "defconfig: msm8610: enable options for QView"
diff --git a/Documentation/devicetree/bindings/input/misc/bmp180.txt b/Documentation/devicetree/bindings/input/misc/bmp180.txt
new file mode 100644
index 0000000..13e0839
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/misc/bmp180.txt
@@ -0,0 +1,35 @@
+Bosch BMP18x-series altimeter driver
+
+Required properties:
+
+ - compatible : Should be "bosch,bmp180".
+ - reg : i2c slave address of the device.
+ - vdd-supply : Analog power supply needed to power device.
+ - vddio-supply : Digital IO power supply needed for IO and I2C.
+ - bosch,chip-id : Chip id for the bmp18x altimeter sensor.
+ - bosch,oversample : Sensor default oversampling value.
+ Default oversampling value to be used at startup.
+ Value range is 0-3 with rising sensitivity.
+ - bosch,period : Temperature measurement period (milliseconds).
+ Set to zero if unsure.
+
+Optional properties:
+
+ - bosch,sw-oversample : Boolean to enable software oversampling if
+ this property is defined. Only take effect when
+ default_oversampling is 3.
+
+Example:
+ i2c@f9925000 {
+ bmp180@77 {
+ status = "okay";
+ reg = <0x77>;
+ compatible = "bosch,bmp180";
+ vdd-supply = <&pm8110_l19>;
+ vddio-supply = <&pm8110_l14>;
+ bosch,chip-id = <0x55>;
+ bosch,oversample = <3>;
+ bosch,period = <1000>;
+ bosch,sw-oversample;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/input/misc/mma8x5x.txt b/Documentation/devicetree/bindings/input/misc/mma8x5x.txt
new file mode 100644
index 0000000..854939c
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/misc/mma8x5x.txt
@@ -0,0 +1,39 @@
+Freescale MMA8x5x 3-Axis Orientation/Motion Detection Sensor series
+(MMA8451/MMA8452/MMA8453/MMA8652/MMA8653)
+
+The Freescale 3-Axis Orientation/Motion Detection Sensor is
+connected to host processor via i2c.
+The sensor can be polling for acceleration data or configure to
+generates interrupts when a motion is detected.
+
+Required properties:
+
+ - compatible : should be "fsl,mma8x5x"
+ - reg : i2c slave address of the device
+ - vdd-supply : power supply needed to power up the device.
+ - vio-supply : power supply needed for device IO and to pullup i2c bus.
+ - fsl,sensors-position : select from 0 to 7 depends on how the sensor is
+ mounting on the board, this will decide how the 3-axis reading
+ of data will be translated to X/Y/Z axis of acceleration data.
+
+Optional properties:
+ Sensor can work on polling mode or interrupt mode, following interrupt
+ is required if the sensor need to work on interrupt mode.
+ - interrupt-parent : parent of interrupt.
+ - interrupts : sensor signal interrupt to indicate new data ready or
+ a motion is detected.
+ - fsl,irq-gpio : First irq gpio which is to provide interrupts to host, same
+ as "interrupts" node. It will also contain active low or active
+ high information.
+
+Example:
+ fsl@1c {
+ compatible = "fsl,mma8x5x";
+ reg = <0x1c>;
+ interrupt-parent = <&msmgpio>;
+ interrupts = <81 0x2>;
+ vdd-supply = <&pm8110_l19>;
+ vio-supply = <&pm8110_l14>;
+ fsl,sensors-position = <5>;
+ fsl,irq-gpio = <&msmgpio 0x81 0x02>;
+ };
\ No newline at end of file
diff --git a/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt
index 6fe88a9..4c6ae93 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt
@@ -35,6 +35,8 @@
needed during wakeup.
- atmel,no-force-update : flag that signifies whether force configuration
update is applicable or not
+ - atmel,no-lpm-support : flag that signifies whether low power mode is
+ supported or not on this platform
Example:
i2c@f9966000 {
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp.txt b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
index ff95d43..e9c5061 100644
--- a/Documentation/devicetree/bindings/leds/leds-qpnp.txt
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
@@ -81,7 +81,9 @@
- qcom,source-sel: select power source, default 1 (enabled)
- qcom,mode-ctrl: select operation mode, default 0x60 = Mode Sink
- qcom,mode: mode the led should operate in, options "pwm", "lpg" and "manual"
+- qcom,vin-ctrl: select input source, supported values are 0 to 3
- qcom,use-blink: Use blink sysfs entry for switching into lpg mode. For optimal use, set default mode to pwm. All required lpg parameters must be supplied.
+- qcom,min-brightness - Lowest possible brightness supported on this LED other than 0.
Required properties for PWM mode only:
- qcom,pwm-channel: pwm channel the led will operate on
@@ -136,6 +138,8 @@
qcom,id = <6>;
qcom,source-sel = <1>;
qcom,mode-ctrl = <0x10>;
+ qcom,vin-ctrl = <0x03>;
+ qcom,min-brightness = <20>;
};
};
diff --git a/Documentation/devicetree/bindings/media/video/msm-cci.txt b/Documentation/devicetree/bindings/media/video/msm-cci.txt
index 583fbfa..8e988be 100644
--- a/Documentation/devicetree/bindings/media/video/msm-cci.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-cci.txt
@@ -95,6 +95,11 @@
#gpio-cells specifying specific gpio (controller specific)
- qcom,gpio-reset : should contain index to gpio used by sensors reset_n
- qcom,gpio-standby : should contain index to gpio used by sensors standby_n
+- qcom,gpio-vio : should contain index to gpio used by sensors io vreg enable
+- qcom,gpio-vana : should contain index to gpio used by sensors analog vreg enable
+- qcom,gpio-vdig : should contain index to gpio used by sensors digital vreg enable
+- qcom,gpio-vaf : should contain index to gpio used by sensors af vreg enable
+- qcom,gpio-af-pwdm : should contain index to gpio used by sensors af pwdm_n
- qcom,gpio-req-tbl-num : should contain index to gpios specific to this sensor
- qcom,gpio-req-tbl-flags : should contain direction of gpios present in
qcom,gpio-req-tbl-num property (in the same order)
diff --git a/Documentation/devicetree/bindings/power/qpnp-bms.txt b/Documentation/devicetree/bindings/power/qpnp-bms.txt
index 3cac311..3e7a578 100644
--- a/Documentation/devicetree/bindings/power/qpnp-bms.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-bms.txt
@@ -77,6 +77,10 @@
number of the FCC measurement cycles required to
generate an FCC update. This is applicable only
if the FCC learning is enabled.
+- qcom,fcc-resolution: An integer which defines the fcc resolution used
+ for storing the FCC(mAh) in the 8-bit BMS register.
+ For example - A value of 10 indicates:
+ FCC value (in mAh) = (8-bit register value) * 10.
Parent node optional properties:
- qcom,ignore-shutdown-soc: A boolean that controls whether BMS will
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index b4bcaf6..a3a3807 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -8,6 +8,7 @@
apm Applied Micro Circuits Corporation (APM)
arm ARM Ltd.
atmel Atmel Corporation
+bosch Bosch Sensortec GmbH
cavium Cavium, Inc.
chrp Common Hardware Reference Platform
cortina Cortina Systems, Inc.
diff --git a/arch/arm/boot/dts/apq8026-v1.dtsi b/arch/arm/boot/dts/apq8026-v1.dtsi
index f15a96f..7fbfcb5 100644
--- a/arch/arm/boot/dts/apq8026-v1.dtsi
+++ b/arch/arm/boot/dts/apq8026-v1.dtsi
@@ -22,3 +22,8 @@
model = "Qualcomm APQ 8026";
compatible = "qcom,apq8026";
};
+
+&tsens {
+ qcom,sensors = <4>;
+ qcom,slope = <2901 2846 3038 2955>;
+};
diff --git a/arch/arm/boot/dts/apq8026-v2.dtsi b/arch/arm/boot/dts/apq8026-v2.dtsi
index d87b500..4c0d3ce 100644
--- a/arch/arm/boot/dts/apq8026-v2.dtsi
+++ b/arch/arm/boot/dts/apq8026-v2.dtsi
@@ -22,3 +22,8 @@
model = "Qualcomm APQ 8026";
compatible = "qcom,apq8026";
};
+
+&tsens {
+ qcom,sensors = <6>;
+ qcom,slope = <2901 2846 3038 2955 2901 2846>;
+};
diff --git a/arch/arm/boot/dts/apq8084.dtsi b/arch/arm/boot/dts/apq8084.dtsi
index 350257c..3014813 100644
--- a/arch/arm/boot/dts/apq8084.dtsi
+++ b/arch/arm/boot/dts/apq8084.dtsi
@@ -198,7 +198,7 @@
tsens: tsens@fc4a8000 {
compatible = "qcom,msm-tsens";
reg = <0xfc4a8000 0x2000>,
- <0xfc4b8000 0x1000>;
+ <0xfc4bc000 0x1000>;
reg-names = "tsens_physical", "tsens_eeprom_physical";
interrupts = <0 184 0>;
qcom,sensors = <11>;
diff --git a/arch/arm/boot/dts/mpq8092-iommu.dtsi b/arch/arm/boot/dts/mpq8092-iommu.dtsi
index 4fb2b24..3a86814 100644
--- a/arch/arm/boot/dts/mpq8092-iommu.dtsi
+++ b/arch/arm/boot/dts/mpq8092-iommu.dtsi
@@ -212,3 +212,7 @@
0x10
0x0>;
};
+
+&vpu_iommu {
+ status = "ok";
+};
diff --git a/arch/arm/boot/dts/mpq8092-rumi.dtsi b/arch/arm/boot/dts/mpq8092-rumi.dtsi
index 2016998..cc345d8 100644
--- a/arch/arm/boot/dts/mpq8092-rumi.dtsi
+++ b/arch/arm/boot/dts/mpq8092-rumi.dtsi
@@ -24,13 +24,13 @@
};
qcom,sdcc@f9824000 {
- status = "disabled";
qcom,clk-rates = <400000 19200000>;
+ status = "ok";
};
qcom,sdcc@f98a4000 {
- status = "disabled";
qcom,clk-rates = <400000 19200000>;
+ status = "ok";
};
qcom,sps@f998000 {
diff --git a/arch/arm/boot/dts/mpq8092.dtsi b/arch/arm/boot/dts/mpq8092.dtsi
index 7dd3ea8..04f0945 100644
--- a/arch/arm/boot/dts/mpq8092.dtsi
+++ b/arch/arm/boot/dts/mpq8092.dtsi
@@ -291,6 +291,10 @@
status = "ok";
};
+&gdsc_vpu {
+ status = "ok";
+};
+
&gdsc_oxili_gx {
status = "ok";
};
diff --git a/arch/arm/boot/dts/msm-pm8226.dtsi b/arch/arm/boot/dts/msm-pm8226.dtsi
index 2008e1e..0f93c8e 100644
--- a/arch/arm/boot/dts/msm-pm8226.dtsi
+++ b/arch/arm/boot/dts/msm-pm8226.dtsi
@@ -32,10 +32,13 @@
reg = <0x800 0x100>;
interrupts = <0x0 0x8 0x0>,
<0x0 0x8 0x1>,
- <0x0 0x8 0x4>;
- interrupt-names = "kpdpwr", "resin", "resin-bark";
+ <0x0 0x8 0x4>,
+ <0x0 0x8 0x5>;
+ interrupt-names = "kpdpwr", "resin",
+ "resin-bark", "kpdpwr-resin-bark";
qcom,pon-dbc-delay = <15625>;
qcom,system-reset;
+ qcom,s3-debounce = <32>;
qcom,pon_1 {
qcom,pon-type = <0>;
@@ -52,6 +55,15 @@
qcom,s2-type = <1>;
linux,code = <114>;
};
+
+ qcom,pon_3 {
+ qcom,pon-type = <3>;
+ qcom,support-reset = <1>;
+ qcom,pull-up = <1>;
+ qcom,s1-timer = <6720>;
+ qcom,s2-timer = <2000>;
+ qcom,s2-type = <7>;
+ };
};
pm8226_chg: qcom,charger {
diff --git a/arch/arm/boot/dts/msm8226-cdp.dtsi b/arch/arm/boot/dts/msm8226-cdp.dtsi
index 259dfdb..7acb1fe 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8226-cdp.dtsi
@@ -114,8 +114,6 @@
&sdcc1 {
vdd-supply = <&pm8226_l17>;
- qcom,vdd-always-on;
- qcom,vdd-lpm-sup;
qcom,vdd-voltage-level = <2950000 2950000>;
qcom,vdd-current-level = <800 500000>;
@@ -140,8 +138,6 @@
&sdhc_1 {
vdd-supply = <&pm8226_l17>;
- qcom,vdd-always-on;
- qcom,vdd-lpm-sup;
qcom,vdd-voltage-level = <2950000 2950000>;
qcom,vdd-current-level = <800 500000>;
diff --git a/arch/arm/boot/dts/msm8226-mtp.dtsi b/arch/arm/boot/dts/msm8226-mtp.dtsi
index 4b2a4ad..ddb61bc 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8226-mtp.dtsi
@@ -131,8 +131,6 @@
&sdcc1 {
vdd-supply = <&pm8226_l17>;
- qcom,vdd-always-on;
- qcom,vdd-lpm-sup;
qcom,vdd-voltage-level = <2950000 2950000>;
qcom,vdd-current-level = <800 500000>;
@@ -157,8 +155,6 @@
&sdhc_1 {
vdd-supply = <&pm8226_l17>;
- qcom,vdd-always-on;
- qcom,vdd-lpm-sup;
qcom,vdd-voltage-level = <2950000 2950000>;
qcom,vdd-current-level = <800 500000>;
diff --git a/arch/arm/boot/dts/msm8226-qrd.dtsi b/arch/arm/boot/dts/msm8226-qrd.dtsi
index 8af5ef5..669f54a 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8226-qrd.dtsi
@@ -129,8 +129,6 @@
&sdcc1 {
vdd-supply = <&pm8226_l17>;
- qcom,vdd-always-on;
- qcom,vdd-lpm-sup;
qcom,vdd-voltage-level = <2950000 2950000>;
qcom,vdd-current-level = <800 500000>;
@@ -155,8 +153,6 @@
&sdhc_1 {
vdd-supply = <&pm8226_l17>;
- qcom,vdd-always-on;
- qcom,vdd-lpm-sup;
qcom,vdd-voltage-level = <2950000 2950000>;
qcom,vdd-current-level = <800 500000>;
diff --git a/arch/arm/boot/dts/msm8226-regulator.dtsi b/arch/arm/boot/dts/msm8226-regulator.dtsi
index 3e89c3a..571ddc3 100644
--- a/arch/arm/boot/dts/msm8226-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8226-regulator.dtsi
@@ -44,8 +44,8 @@
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 = <1155000 1160000 1275000>;
- qcom,pvs-corner-ceiling-nom = <975000 1075000 1200000>;
- qcom,pvs-corner-ceiling-fast = <900000 1000000 1140000>;
+ qcom,pvs-corner-ceiling-nom = <1050000 1075000 1200000>;
+ qcom,pvs-corner-ceiling-fast = <1050000 1050000 1140000>;
vdd-apc-supply = <&pm8226_s2>;
vdd-mx-supply = <&pm8226_l3_ao>;
diff --git a/arch/arm/boot/dts/msm8226-v1.dtsi b/arch/arm/boot/dts/msm8226-v1.dtsi
index d471bec..1db1f12 100644
--- a/arch/arm/boot/dts/msm8226-v1.dtsi
+++ b/arch/arm/boot/dts/msm8226-v1.dtsi
@@ -17,3 +17,8 @@
*/
/include/ "msm8226.dtsi"
+
+&tsens {
+ qcom,sensors = <4>;
+ qcom,slope = <2901 2846 3038 2955>;
+};
diff --git a/arch/arm/boot/dts/msm8226-v2.dtsi b/arch/arm/boot/dts/msm8226-v2.dtsi
index 2148e1d..b44cb681 100644
--- a/arch/arm/boot/dts/msm8226-v2.dtsi
+++ b/arch/arm/boot/dts/msm8226-v2.dtsi
@@ -43,8 +43,8 @@
qcom,pvs-bin-process = <1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2
2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3>;
qcom,pvs-corner-ceiling-slow = <1160000 1160000 1280000>;
- qcom,pvs-corner-ceiling-nom = <980000 1080000 1200000>;
- qcom,pvs-corner-ceiling-fast = <900000 1000000 1140000>;
+ qcom,pvs-corner-ceiling-nom = <1050000 1080000 1200000>;
+ qcom,pvs-corner-ceiling-fast = <1050000 1050000 1140000>;
qcom,cpr-step-quotient = <30>;
qcom,cpr-up-threshold = <0>;
qcom,cpr-down-threshold = <5>;
@@ -63,3 +63,8 @@
reg-names = "rcg_base", "pte_efuse";
};
};
+
+&tsens {
+ qcom,sensors = <6>;
+ qcom,slope = <2901 2846 3038 2955 2901 2846>;
+};
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index cd0063b..b836100 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -1025,7 +1025,7 @@
tsens: tsens@fc4a8000 {
compatible = "qcom,msm-tsens";
reg = <0xfc4a8000 0x2000>,
- <0xfc4b8000 0x1000>;
+ <0xfc4bc000 0x1000>;
reg-names = "tsens_physical", "tsens_eeprom_physical";
interrupts = <0 184 0>;
qcom,sensors = <4>;
diff --git a/arch/arm/boot/dts/msm8610-cdp.dts b/arch/arm/boot/dts/msm8610-cdp.dts
index 6b61317..ce4ada5 100644
--- a/arch/arm/boot/dts/msm8610-cdp.dts
+++ b/arch/arm/boot/dts/msm8610-cdp.dts
@@ -222,9 +222,13 @@
qcom,default-state = "on";
qcom,max-current = <40>;
qcom,id = <6>;
- qcom,source-sel = <1>;
+ qcom,source-sel = <8>;
qcom,mode-ctrl = <0x10>;
- qcom,mode = "manual";
+ qcom,pwm-channel = <0>;
+ qcom,pwm-us = <14>;
+ qcom,vin-ctrl = <0x03>;
+ qcom,mode = "pwm";
+ qcom,min-brightness = <19>;
};
};
};
@@ -242,8 +246,6 @@
&sdhc_1 {
vdd-supply = <&pm8110_l17>;
- qcom,vdd-always-on;
- qcom,vdd-lpm-sup;
qcom,vdd-voltage-level = <2900000 2900000>;
qcom,vdd-current-level = <200 400000>;
diff --git a/arch/arm/boot/dts/msm8610-mtp.dts b/arch/arm/boot/dts/msm8610-mtp.dts
index 16fc2e7..221ace4 100644
--- a/arch/arm/boot/dts/msm8610-mtp.dts
+++ b/arch/arm/boot/dts/msm8610-mtp.dts
@@ -42,6 +42,7 @@
atmel,display-coords = <0 0 480 800>;
atmel,i2c-pull-up;
atmel,no-force-update;
+ atmel,no-lpm-support;
atmel,cfg_1 {
atmel,family-id = <0x81>;
atmel,variant-id = <0x15>;
@@ -105,6 +106,27 @@
invn,gpio-en = <&pm8110_gpios 2 0x2>;
invn,poll-interval = <200>;
};
+
+ bmp180@77 {
+ reg = <0x77>;
+ compatible = "bosch,bmp18x";
+ vdd-supply = <&pm8110_l19>;
+ vddio-supply = <&pm8110_l14>;
+ bosch,chip-id = <0x55>;
+ bosch,oversample = <3>;
+ bosch,period = <1000>;
+ };
+
+ mma8x5x@1d {
+ reg = <0x1d>;
+ compatible = "fsl,mma8x5x";
+ interrupt-parent = <&msmgpio>;
+ interrupts = <81 0x2>;
+ vdd-supply = <&pm8110_l19>;
+ vio-supply = <&pm8110_l14>;
+ fsl,irq-gpio = <&msmgpio 81 0x00>;
+ fsl,sensors-position = <5>;
+ };
};
gen-vkeys {
@@ -239,9 +261,13 @@
qcom,default-state = "on";
qcom,max-current = <40>;
qcom,id = <6>;
- qcom,source-sel = <1>;
+ qcom,source-sel = <8>;
qcom,mode-ctrl = <0x10>;
- qcom,mode = "manual";
+ qcom,pwm-channel = <0>;
+ qcom,pwm-us = <14>;
+ qcom,vin-ctrl = <0x03>;
+ qcom,mode = "pwm";
+ qcom,min-brightness = <19>;
};
};
};
@@ -259,8 +285,6 @@
&sdhc_1 {
vdd-supply = <&pm8110_l17>;
- qcom,vdd-always-on;
- qcom,vdd-lpm-sup;
qcom,vdd-voltage-level = <2900000 2900000>;
qcom,vdd-current-level = <200 400000>;
diff --git a/arch/arm/boot/dts/msm8610-qrd-skuab.dts b/arch/arm/boot/dts/msm8610-qrd-skuab.dts
index 62ef933..24c2490 100644
--- a/arch/arm/boot/dts/msm8610-qrd-skuab.dts
+++ b/arch/arm/boot/dts/msm8610-qrd-skuab.dts
@@ -38,6 +38,34 @@
qcom,ext-spk-amp-gpio = <&msmgpio 92 0x0>;
};
+ i2c@f9923000{
+ focaltech@38{
+ compatible = "focaltech,5x06";
+ reg = <0x38>;
+ interrupt-parent = <&msmgpio>;
+ interrupts = <1 0x2>;
+ vdd-supply = <&pm8110_l19>;
+ vcc_i2c-supply = <&pm8110_l14>;
+ focaltech,family-id = <0x06>;
+ focaltech,reset-gpio = <&msmgpio 0 0x00>;
+ focaltech,irq-gpio = <&msmgpio 1 0x00>;
+ focaltech,display-coords = <0 0 480 854>;
+ focaltech,panel-coords = <0 0 480 946>;
+ focaltech,button-map= <139 102 158>;
+ focaltech,no-force-update;
+ focaltech,i2c-pull-up;
+ };
+ };
+ gen-vkeys {
+ compatible = "qcom,gen-vkeys";
+ label = "ft5x06_ts";
+ qcom,disp-maxx = <480>;
+ qcom,disp-maxy = <854>;
+ qcom,panel-maxx = <481>;
+ qcom,panel-maxy = <946>;
+ qcom,key-codes = <139 102 158>;
+ qcom,y-offset = <0>;
+ };
i2c@f9925000 {
fsl@1c {
compatible = "fsl,mma8x5x";
diff --git a/arch/arm/boot/dts/msm8610-qrd.dtsi b/arch/arm/boot/dts/msm8610-qrd.dtsi
index 5a30d40..ea47d45 100644
--- a/arch/arm/boot/dts/msm8610-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8610-qrd.dtsi
@@ -213,9 +213,13 @@
qcom,default-state = "on";
qcom,max-current = <40>;
qcom,id = <6>;
- qcom,source-sel = <1>;
+ qcom,source-sel = <8>;
qcom,mode-ctrl = <0x10>;
- qcom,mode = "manual";
+ qcom,pwm-channel = <0>;
+ qcom,pwm-us = <14>;
+ qcom,vin-ctrl = <0x03>;
+ qcom,mode = "pwm";
+ qcom,min-brightness = <19>;
};
};
};
@@ -233,8 +237,6 @@
&sdhc_1 {
vdd-supply = <&pm8110_l17>;
- qcom,vdd-always-on;
- qcom,vdd-lpm-sup;
qcom,vdd-voltage-level = <2900000 2900000>;
qcom,vdd-current-level = <200 400000>;
diff --git a/arch/arm/boot/dts/msm8610-regulator.dtsi b/arch/arm/boot/dts/msm8610-regulator.dtsi
index 38f587b..cf54098 100644
--- a/arch/arm/boot/dts/msm8610-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8610-regulator.dtsi
@@ -197,6 +197,7 @@
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
qcom,init-voltage = <1200000>;
+ regulator-always-on;
status = "okay";
};
};
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index 9a796e2..ee444e3 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -253,8 +253,6 @@
interrupt-names = "core_irq", "bam_irq";
vdd-supply = <&pm8110_l17>;
- qcom,vdd-always-on;
- qcom,vdd-lpm-sup;
qcom,vdd-voltage-level = <2900000 2900000>;
qcom,vdd-current-level = <9000 400000>;
@@ -755,7 +753,7 @@
tsens: tsens@fc4a8000 {
compatible = "qcom,msm-tsens";
reg = <0xfc4a8000 0x2000>,
- <0xfc4b8000 0x1000>;
+ <0xfc4bc000 0x1000>;
reg-names = "tsens_physical", "tsens_eeprom_physical";
interrupts = <0 184 0>;
qcom,sensors = <2>;
@@ -915,6 +913,11 @@
<55 512 393600 3936000>;
};
+ cpu-pmu {
+ compatible = "arm,cortex-a7-pmu";
+ qcom,irq-is-percpu;
+ interrupts = <1 7 0xf00>;
+ };
};
&gdsc_vfe {
diff --git a/arch/arm/boot/dts/msm8974-fluid.dtsi b/arch/arm/boot/dts/msm8974-fluid.dtsi
index 57ce130..af21e43 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-fluid.dtsi
@@ -406,6 +406,7 @@
qcom,min-fcc-learning-soc = <20>;
qcom,min-fcc-ocv-pc = <30>;
qcom,min-fcc-learning-samples = <5>;
+ qcom,fcc-resolution = <10>;
status = "ok";
};
diff --git a/arch/arm/boot/dts/msm8974-mtp.dtsi b/arch/arm/boot/dts/msm8974-mtp.dtsi
index 7b43d9b..8e3b7cc 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-mtp.dtsi
@@ -355,6 +355,7 @@
qcom,min-fcc-learning-soc = <20>;
qcom,min-fcc-ocv-pc = <30>;
qcom,min-fcc-learning-samples = <5>;
+ qcom,fcc-resolution = <10>;
status = "ok";
};
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 791f048..aaa5f3e 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -1364,7 +1364,7 @@
tsens: tsens@fc4a8000 {
compatible = "qcom,msm-tsens";
reg = <0xfc4a8000 0x2000>,
- <0xfc4b8000 0x1000>;
+ <0xfc4bc000 0x1000>;
reg-names = "tsens_physical", "tsens_eeprom_physical";
interrupts = <0 184 0>;
qcom,sensors = <11>;
diff --git a/arch/arm/boot/dts/msm9625-pm.dtsi b/arch/arm/boot/dts/msm9625-pm.dtsi
index 24c6143..e18e143 100644
--- a/arch/arm/boot/dts/msm9625-pm.dtsi
+++ b/arch/arm/boot/dts/msm9625-pm.dtsi
@@ -271,8 +271,9 @@
<37 71>;
};
- qcom,pm-8x60 {
+ qcom,pm-8x60@fe805664 {
compatible = "qcom,pm-8x60";
+ reg = <0xfe805664 0x40>;
qcom,pc-mode = "tz_l2_ext";
qcom,use-sync-timer;
};
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index f5e930d..5520401 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -511,7 +511,7 @@
tsens@fc4a8000 {
compatible = "qcom,msm-tsens";
reg = <0xfc4a8000 0x2000>,
- <0xfc4b8000 0x1000>;
+ <0xfc4bc000 0x1000>;
reg-names = "tsens_physical", "tsens_eeprom_physical";
interrupts = <0 184 0>;
qcom,sensors = <5>;
diff --git a/arch/arm/boot/dts/msmkrypton.dtsi b/arch/arm/boot/dts/msmkrypton.dtsi
index 35d6d2a..3743c54 100644
--- a/arch/arm/boot/dts/msmkrypton.dtsi
+++ b/arch/arm/boot/dts/msmkrypton.dtsi
@@ -128,6 +128,15 @@
status = "disabled";
};
+ qcom,sps@f9980000 {
+ compatible = "qcom,msm_sps";
+ reg = <0xf9984000 0x15000>,
+ <0xf9999000 0xb000>,
+ <0xfe803000 0xd000>,
+ <0xfe805000 0x1000>;
+ interrupts = <0 94 0>;
+ };
+
spi_6: spi@f9928000 { /* BLSP1 QUP6 */
cell-index = <0>;
compatible = "qcom,spi-qup-v2";
diff --git a/arch/arm/configs/msm8226_defconfig b/arch/arm/configs/msm8226_defconfig
index fa86cc8..6c59c38 100644
--- a/arch/arm/configs/msm8226_defconfig
+++ b/arch/arm/configs/msm8226_defconfig
@@ -71,6 +71,7 @@
CONFIG_MSM_RTB_SEPARATE_CPUS=y
CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
CONFIG_MSM_BOOT_STATS=y
+CONFIG_MSM_XPU_ERR_FATAL=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_SMP=y
diff --git a/arch/arm/configs/msm8610-perf_defconfig b/arch/arm/configs/msm8610-perf_defconfig
index bf92d6c..f2d1e29 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -244,6 +244,8 @@
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_QUP=y
CONFIG_INPUT_MPU3050=y
+CONFIG_BMP18X=y
+CONFIG_BMP18X_I2C=y
CONFIG_MSM_BUSPM_DEV=m
CONFIG_SPI=y
CONFIG_SPI_QUP=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 9231ca7..9ce4f5d 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -242,6 +242,8 @@
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_QUP=y
CONFIG_INPUT_MPU3050=y
+CONFIG_BMP18X=y
+CONFIG_BMP18X_I2C=y
CONFIG_MSM_BUSPM_DEV=m
CONFIG_SPI=y
CONFIG_SPI_QUP=y
diff --git a/arch/arm/configs/msmkrypton_defconfig b/arch/arm/configs/msmkrypton_defconfig
index f073d2b..6609c32 100644
--- a/arch/arm/configs/msmkrypton_defconfig
+++ b/arch/arm/configs/msmkrypton_defconfig
@@ -104,6 +104,9 @@
CONFIG_SPI_SPIDEV=m
CONFIG_DEBUG_GPIO=y
CONFIG_GPIO_SYSFS=y
+CONFIG_SPS=y
+CONFIG_SPS_SUPPORT_BAMDMA=y
+CONFIG_SPS_SUPPORT_NDP_BAM=y
CONFIG_MMC=y
CONFIG_MMC_PERF_PROFILING=y
CONFIG_MMC_UNSAFE_RESUME=y
diff --git a/arch/arm/mach-msm/clock-8084.c b/arch/arm/mach-msm/clock-8084.c
index c54c3db..184338e 100644
--- a/arch/arm/mach-msm/clock-8084.c
+++ b/arch/arm/mach-msm/clock-8084.c
@@ -137,7 +137,8 @@
CLK_DUMMY("", gcc_lpass_mport_axi_clk.c, "", OFF),
CLK_DUMMY("", gcc_lpass_q6_axi_clk.c, "", OFF),
CLK_DUMMY("", gcc_lpass_sway_clk.c, "", OFF),
- CLK_DUMMY("", gcc_mmss_bimc_gfx_clk.c, "", OFF),
+ CLK_DUMMY("mem_iface_clk", gcc_mmss_bimc_gfx_clk.c,
+ "fdb00000.qcom,kgsl-3d0", OFF),
CLK_DUMMY("", gcc_mmss_vpu_maple_sys_noc_axi_clk.c, "", OFF),
CLK_DUMMY("", gcc_ocmem_noc_cfg_ahb_clk.c, "", OFF),
CLK_DUMMY("", gcc_msg_ram_ahb_clk.c, "", OFF),
@@ -337,9 +338,11 @@
CLK_DUMMY("iface_clk", ocmemcx_ocmemnoc_clk.c,
"fdd00000.qcom,ocmem", OFF),
CLK_DUMMY("", oxili_ocmemgx_clk.c, "", OFF),
- CLK_DUMMY("", oxili_gfx3d_clk.c, "", OFF),
+ CLK_DUMMY("core_clk", oxili_gfx3d_clk.c,
+ "fdb00000.qcom,kgsl-3d0", OFF),
CLK_DUMMY("", oxili_rbbmtimer_clk.c, "", OFF),
- CLK_DUMMY("", oxilicx_ahb_clk.c, "", OFF),
+ CLK_DUMMY("iface_clk", oxilicx_ahb_clk.c,
+ "fdb00000.qcom,kgsl-3d0", OFF),
CLK_DUMMY("", venus0_ahb_clk.c, "", OFF),
CLK_DUMMY("", venus0_axi_clk.c, "", OFF),
CLK_DUMMY("", venus0_core0_vcodec_clk.c, "", OFF),
diff --git a/arch/arm/mach-msm/clock-dsi-8610.c b/arch/arm/mach-msm/clock-dsi-8610.c
index 44b332e..73196fe 100644
--- a/arch/arm/mach-msm/clock-dsi-8610.c
+++ b/arch/arm/mach-msm/clock-dsi-8610.c
@@ -192,7 +192,7 @@
status = readl_relaxed(dsi_base + DSI_DSIPHY_PLL_CTRL_0);
if (!status & DSI_PLL_RDY_BIT) {
pr_err("DSI PLL not ready\n");
- clk_disable(dsi_ahb_clk);
+ clk_disable_unprepare(dsi_ahb_clk);
return HANDOFF_DISABLED_CLK;
}
@@ -370,35 +370,19 @@
return HANDOFF_ENABLED_CLK;
}
-int dsi_prepare(struct clk *clk)
-{
- return clk_prepare(dsi_ahb_clk);
-}
-
-void dsi_unprepare(struct clk *clk)
-{
- clk_unprepare(dsi_ahb_clk);
-}
-
struct clk_ops clk_ops_dsi_dsiclk = {
- .prepare = dsi_prepare,
- .unprepare = dsi_unprepare,
.set_rate = dsi_dsiclk_set_rate,
.round_rate = dsi_dsiclk_round_rate,
.handoff = dsi_dsiclk_handoff,
};
struct clk_ops clk_ops_dsi_byteclk = {
- .prepare = dsi_prepare,
- .unprepare = dsi_unprepare,
.set_rate = dsi_byteclk_set_rate,
.round_rate = dsi_byteclk_round_rate,
.handoff = dsi_byteclk_handoff,
};
struct clk_ops clk_ops_dsi_vco = {
- .prepare = dsi_prepare,
- .unprepare = dsi_unprepare,
.enable = dsi_pll_vco_enable,
.disable = dsi_pll_vco_disable,
.set_rate = dsi_pll_vco_set_rate,
diff --git a/arch/arm/mach-msm/clock-krypton.c b/arch/arm/mach-msm/clock-krypton.c
index aaee003..0b615cc 100644
--- a/arch/arm/mach-msm/clock-krypton.c
+++ b/arch/arm/mach-msm/clock-krypton.c
@@ -46,6 +46,8 @@
CLK_DUMMY("mem_clk", bimc_msmbus_clk.c, "msm_bimc", OFF),
CLK_DUMMY("mem_a_clk", bimc_msmbus_a_clk.c, "msm_bimc", OFF),
CLK_DUMMY("mem_clk", bimc_acpu_a_clk.c, "", OFF),
+ CLK_DUMMY("dfab_clk", DFAB_CLK, "msm_sps", OFF),
+ CLK_DUMMY("dma_bam_pclk", DMA_BAM_P_CLK, "msm_sps", OFF),
CLK_DUMMY("clktype", gcc_imem_axi_clk , "drivername", OFF),
CLK_DUMMY("clktype", gcc_imem_cfg_ahb_clk , "drivername", OFF),
diff --git a/arch/arm/mach-msm/clock-rpm.c b/arch/arm/mach-msm/clock-rpm.c
index 8356207..1d7a5e2 100644
--- a/arch/arm/mach-msm/clock-rpm.c
+++ b/arch/arm/mach-msm/clock-rpm.c
@@ -42,7 +42,7 @@
int rc;
struct msm_rpm_iv_pair iv = { .id = r->rpm_status_id, };
rc = msm_rpm_get_status(&iv, 1);
- return (rc < 0) ? rc : iv.value * r->factor;
+ return (rc < 0) ? rc : iv.value * 1000;
}
static int clk_rpmrs_handoff(struct rpm_clk *r)
@@ -54,7 +54,7 @@
return rc;
if (!r->branch)
- r->c.rate = iv.value * r->factor;
+ r->c.rate = iv.value * 1000;
return 0;
}
@@ -122,7 +122,7 @@
unsigned long *active_khz, unsigned long *sleep_khz)
{
/* Convert the rate (hz) to khz */
- *active_khz = DIV_ROUND_UP(rate, r->factor);
+ *active_khz = DIV_ROUND_UP(rate, 1000);
/*
* Active-only clocks don't care what the rate is during sleep. So,
diff --git a/arch/arm/mach-msm/clock-rpm.h b/arch/arm/mach-msm/clock-rpm.h
index b20c3d6..d283861 100644
--- a/arch/arm/mach-msm/clock-rpm.h
+++ b/arch/arm/mach-msm/clock-rpm.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-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
@@ -39,9 +39,7 @@
const bool active_only;
bool enabled;
bool branch; /* true: RPM only accepts 1 for ON and 0 for OFF */
- unsigned factor;
struct clk_rpmrs_data *rpmrs_data;
-
struct rpm_clk *peer;
struct clk c;
};
@@ -69,7 +67,6 @@
.rpm_status_id = (stat_id), \
.rpm_key = (key), \
.peer = &active, \
- .factor = 1000, \
.rpmrs_data = (rpmrsdata),\
.c = { \
.ops = &clk_ops_rpm, \
@@ -85,7 +82,6 @@
.rpm_key = (key), \
.peer = &name, \
.active_only = true, \
- .factor = 1000, \
.rpmrs_data = (rpmrsdata),\
.c = { \
.ops = &clk_ops_rpm, \
@@ -104,7 +100,6 @@
.rpm_status_id = (stat_id), \
.rpm_key = (key), \
.peer = &active, \
- .factor = 1000, \
.branch = true, \
.rpmrs_data = (rpmrsdata),\
.c = { \
@@ -121,7 +116,6 @@
.rpm_key = (key), \
.peer = &name, \
.active_only = true, \
- .factor = 1000, \
.branch = true, \
.rpmrs_data = (rpmrsdata),\
.c = { \
@@ -132,46 +126,13 @@
}, \
};
-#define __DEFINE_CLK_RPM_QDSS(name, active, type, r_id, stat_id, \
- key, rpmrsdata) \
- static struct rpm_clk active; \
- static struct rpm_clk name = { \
- .rpm_res_type = (type), \
- .rpm_clk_id = (r_id), \
- .rpm_status_id = (stat_id), \
- .rpm_key = (key), \
- .peer = &active, \
- .factor = 1, \
- .rpmrs_data = (rpmrsdata),\
- .c = { \
- .ops = &clk_ops_rpm, \
- .dbg_name = #name, \
- CLK_INIT(name.c), \
- }, \
- }; \
- static struct rpm_clk active = { \
- .rpm_res_type = (type), \
- .rpm_clk_id = (r_id), \
- .rpm_status_id = (stat_id), \
- .rpm_key = (key), \
- .peer = &name, \
- .active_only = true, \
- .factor = 1, \
- .rpmrs_data = (rpmrsdata),\
- .c = { \
- .ops = &clk_ops_rpm, \
- .dbg_name = #active, \
- CLK_INIT(active.c), \
- }, \
- };
-
#define DEFINE_CLK_RPM(name, active, r_id, dep) \
__DEFINE_CLK_RPM(name, active, 0, MSM_RPM_ID_##r_id##_CLK, \
MSM_RPM_STATUS_ID_##r_id##_CLK, dep, 0, &clk_rpmrs_data)
#define DEFINE_CLK_RPM_QDSS(name, active) \
- __DEFINE_CLK_RPM_QDSS(name, active, 0, MSM_RPM_ID_QDSS_CLK, \
- MSM_RPM_STATUS_ID_QDSS_CLK, 0, &clk_rpmrs_data)
+ __DEFINE_CLK_RPM(name, active, 0, MSM_RPM_ID_QDSS_CLK, \
+ MSM_RPM_STATUS_ID_QDSS_CLK, 0, 0, &clk_rpmrs_data)
#define DEFINE_CLK_RPM_BRANCH(name, active, r_id, r) \
__DEFINE_CLK_RPM_BRANCH(name, active, 0, MSM_RPM_ID_##r_id##_CLK, \
@@ -186,8 +147,8 @@
RPM_SMD_KEY_ENABLE, &clk_rpmrs_data_smd)
#define DEFINE_CLK_RPM_SMD_QDSS(name, active, type, r_id) \
- __DEFINE_CLK_RPM_QDSS(name, active, type, r_id, \
- 0, RPM_SMD_KEY_STATE, &clk_rpmrs_data_smd)
+ __DEFINE_CLK_RPM(name, active, type, r_id, \
+ 0, 0, RPM_SMD_KEY_STATE, &clk_rpmrs_data_smd)
/*
* The RPM XO buffer clock management code aggregates votes for pin-control mode
* and software mode separately. Software-enable has higher priority over pin-
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 7b26bd6..6370bd4 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -183,7 +183,7 @@
};
struct msm_camera_gpio_num_info {
- uint16_t gpio_num[2];
+ uint16_t gpio_num[7];
};
struct msm_camera_gpio_conf {
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index c979e0c..7cfbd93 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -327,30 +327,43 @@
static inline int msm_soc_version_supports_iommu_v0(void)
{
+ static int soc_supports_v0 = -1;
#ifdef CONFIG_OF
struct device_node *node;
+#endif
+ if (soc_supports_v0 != -1)
+ return soc_supports_v0;
+
+#ifdef CONFIG_OF
node = of_find_compatible_node(NULL, NULL, "qcom,msm-smmu-v1");
if (node) {
+ soc_supports_v0 = 0;
of_node_put(node);
return 0;
}
node = of_find_compatible_node(NULL, NULL, "qcom,msm-smmu-v0");
if (node) {
+ soc_supports_v0 = 1;
of_node_put(node);
return 1;
}
#endif
if (cpu_is_msm8960() &&
- SOCINFO_VERSION_MAJOR(socinfo_get_version()) < 2)
+ SOCINFO_VERSION_MAJOR(socinfo_get_version()) < 2) {
+ soc_supports_v0 = 0;
return 0;
+ }
if (cpu_is_msm8x60() &&
(SOCINFO_VERSION_MAJOR(socinfo_get_version()) != 2 ||
SOCINFO_VERSION_MINOR(socinfo_get_version()) < 1)) {
+ soc_supports_v0 = 0;
return 0;
}
+
+ soc_supports_v0 = 1;
return 1;
}
#endif
diff --git a/arch/arm/mach-msm/include/mach/ocmem_priv.h b/arch/arm/mach-msm/include/mach/ocmem_priv.h
index 6f83c53..32d58d4 100644
--- a/arch/arm/mach-msm/include/mach/ocmem_priv.h
+++ b/arch/arm/mach-msm/include/mach/ocmem_priv.h
@@ -174,8 +174,8 @@
/* Request Power State */
unsigned power_state;
struct ocmem_eviction_data *edata;
- /* Request that triggered eviction */
- struct ocmem_req *e_handle;
+ /* Eviction data of the request being evicted */
+ struct ocmem_eviction_data *eviction_info;
};
struct ocmem_handle {
diff --git a/arch/arm/mach-msm/ocmem_sched.c b/arch/arm/mach-msm/ocmem_sched.c
index a3fd6b2..cbf7933 100644
--- a/arch/arm/mach-msm/ocmem_sched.c
+++ b/arch/arm/mach-msm/ocmem_sched.c
@@ -1192,19 +1192,23 @@
}
/* Remove the request from eviction lists */
-static void cancel_restore(struct ocmem_req *e_handle,
- struct ocmem_req *req)
+static void cancel_restore(struct ocmem_req *req)
{
- struct ocmem_eviction_data *edata = e_handle->edata;
+ struct ocmem_eviction_data *edata;
- if (!edata || !req)
+ if (!req)
+ return;
+
+ edata = req->eviction_info;
+
+ if (!edata)
return;
if (list_empty(&edata->req_list))
return;
list_del_init(&req->eviction_list);
- req->e_handle = NULL;
+ req->eviction_info = NULL;
return;
}
@@ -1499,8 +1503,8 @@
}
/* Remove the request from any restore lists */
- if (req->e_handle)
- cancel_restore(req->e_handle, req);
+ if (req->eviction_info)
+ cancel_restore(req);
/* Remove the request from any pending opreations */
if (TEST_STATE(req, R_ENQUEUED)) {
@@ -1747,12 +1751,7 @@
goto shrink_fail;
}
- if (!req->e_handle) {
- pr_err("Unable to find evicting request\n");
- goto shrink_fail;
- }
-
- edata = req->e_handle->edata;
+ edata = req->eviction_info;
if (!edata) {
pr_err("Unable to find eviction data\n");
@@ -1905,7 +1904,7 @@
&e_req->eviction_list,
&edata->req_list);
atomic_inc(&edata->pending);
- e_req->e_handle = req;
+ e_req->eviction_info = edata;
}
}
} else {
@@ -2037,7 +2036,7 @@
pr_debug("ocmem: restoring evicted request %p\n",
req);
req->edata = NULL;
- req->e_handle = NULL;
+ req->eviction_info = NULL;
req->op = SCHED_ALLOCATE;
inc_ocmem_stat(zone_of(req), NR_RESTORES);
sched_enqueue(req);
@@ -2076,8 +2075,11 @@
struct ocmem_eviction_data *edata = evictions[id];
int rc = 0;
- if (!edata)
+ if (!edata) {
+ pr_err("Client %s invoked restore without any eviction\n",
+ get_name(id));
return -EINVAL;
+ }
mutex_lock(&free_mutex);
rc = __restore_common(edata);
diff --git a/arch/arm/mach-msm/perf_debug.c b/arch/arm/mach-msm/perf_debug.c
index 643d945..0a799aa 100644
--- a/arch/arm/mach-msm/perf_debug.c
+++ b/arch/arm/mach-msm/perf_debug.c
@@ -33,6 +33,7 @@
"8 Perf: Add cortex A7 perf support\n"
"9 ARM: dts: msm: add perf-events support for msm8226\n"
"10 Perf: Fix counts across power collapse\n"
+ "11 ARM: dts: msm: add perf-events support for msm8x10, msm8x12\n"
;
static ssize_t desc_read(struct file *fp, char __user *buf,
diff --git a/arch/arm/mach-msm/pil-dsps.c b/arch/arm/mach-msm/pil-dsps.c
index 73b58ab..f0a5ebf 100644
--- a/arch/arm/mach-msm/pil-dsps.c
+++ b/arch/arm/mach-msm/pil-dsps.c
@@ -23,6 +23,7 @@
#include <mach/msm_smsm.h>
#include <mach/ramdump.h>
#include <mach/msm_smem.h>
+#include <mach/msm_bus_board.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
@@ -317,6 +318,8 @@
goto err_subsys;
}
+ scm_pas_init(MSM_BUS_MASTER_SPS);
+
ret = smsm_state_cb_register(SMSM_DSPS_STATE, SMSM_RESET,
dsps_smsm_state_cb, drv);
if (ret)
diff --git a/arch/arm/mach-msm/pil-gss.c b/arch/arm/mach-msm/pil-gss.c
index 840c90f..b209a25 100644
--- a/arch/arm/mach-msm/pil-gss.c
+++ b/arch/arm/mach-msm/pil-gss.c
@@ -571,6 +571,8 @@
goto err_smem;
}
+ scm_pas_init(MSM_BUS_MASTER_SPS);
+
ret = devm_request_irq(&pdev->dev, drv->irq, gss_wdog_bite_irq,
IRQF_TRIGGER_RISING, "gss_a5_wdog", drv);
if (ret < 0)
diff --git a/arch/arm/mach-msm/pil-modem.c b/arch/arm/mach-msm/pil-modem.c
index 8398206..f6a853e 100644
--- a/arch/arm/mach-msm/pil-modem.c
+++ b/arch/arm/mach-msm/pil-modem.c
@@ -25,6 +25,7 @@
#include <mach/subsystem_restart.h>
#include <mach/msm_smsm.h>
#include <mach/ramdump.h>
+#include <mach/msm_bus_board.h>
#include "modem_notifier.h"
#include "peripheral-loader.h"
@@ -490,6 +491,8 @@
goto err_ramdump;
}
+ scm_pas_init(MSM_BUS_MASTER_SPS);
+
ret = devm_request_irq(&pdev->dev, drv->irq, modem_wdog_bite_irq,
IRQF_TRIGGER_RISING, "modem_watchdog", drv);
if (ret)
diff --git a/arch/arm/mach-msm/pil-pronto.c b/arch/arm/mach-msm/pil-pronto.c
index 80c0862..6e4aa02 100644
--- a/arch/arm/mach-msm/pil-pronto.c
+++ b/arch/arm/mach-msm/pil-pronto.c
@@ -31,6 +31,7 @@
#include <mach/msm_smsm.h>
#include <mach/ramdump.h>
#include <mach/msm_smem.h>
+#include <mach/msm_bus_board.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
@@ -504,6 +505,8 @@
if (IS_ERR(drv->cxo))
return PTR_ERR(drv->cxo);
+ scm_pas_init(MSM_BUS_MASTER_CRYPTO_CORE0);
+
ret = pil_desc_init(desc);
if (ret)
return ret;
diff --git a/arch/arm/mach-msm/pil-q6v3.c b/arch/arm/mach-msm/pil-q6v3.c
index a369878..58d4301 100644
--- a/arch/arm/mach-msm/pil-q6v3.c
+++ b/arch/arm/mach-msm/pil-q6v3.c
@@ -24,6 +24,7 @@
#include <mach/subsystem_restart.h>
#include <mach/scm.h>
#include <mach/ramdump.h>
+#include <mach/msm_bus_board.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
@@ -393,6 +394,8 @@
goto err_subsys;
}
+ scm_pas_init(MSM_BUS_MASTER_SPS);
+
ret = devm_request_irq(&pdev->dev, drv->irq, lpass_wdog_bite_irq,
IRQF_TRIGGER_RISING, "lpass_wdog", drv);
if (ret) {
diff --git a/arch/arm/mach-msm/pil-q6v4-lpass.c b/arch/arm/mach-msm/pil-q6v4-lpass.c
index 7acb599..6ec8430 100644
--- a/arch/arm/mach-msm/pil-q6v4-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v4-lpass.c
@@ -26,6 +26,7 @@
#include <mach/subsystem_notif.h>
#include <mach/ramdump.h>
#include <mach/msm_smem.h>
+#include <mach/msm_bus_board.h>
#include "smd_private.h"
#include "sysmon.h"
@@ -356,6 +357,8 @@
goto err_notif_riva;
}
+ scm_pas_init(MSM_BUS_MASTER_SPS);
+
drv->modem_notif_hdle = subsys_notif_register_notifier("modem", &mnb);
if (IS_ERR(drv->modem_notif_hdle)) {
ret = PTR_ERR(drv->modem_notif_hdle);
diff --git a/arch/arm/mach-msm/pil-q6v4-mss.c b/arch/arm/mach-msm/pil-q6v4-mss.c
index c4b6038..6ee5965 100644
--- a/arch/arm/mach-msm/pil-q6v4-mss.c
+++ b/arch/arm/mach-msm/pil-q6v4-mss.c
@@ -24,6 +24,7 @@
#include <mach/msm_smsm.h>
#include <mach/ramdump.h>
#include <mach/msm_smem.h>
+#include <mach/msm_bus_board.h>
#include "smd_private.h"
#include "peripheral-loader.h"
@@ -462,6 +463,8 @@
if (ret)
goto err_irq;
+ scm_pas_init(MSM_BUS_MASTER_SPS);
+
ret = smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_RESET,
smsm_state_cb, drv);
if (ret)
diff --git a/arch/arm/mach-msm/pil-q6v5-lpass.c b/arch/arm/mach-msm/pil-q6v5-lpass.c
index 6cd6ffe..3b88b10 100644
--- a/arch/arm/mach-msm/pil-q6v5-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v5-lpass.c
@@ -30,6 +30,7 @@
#include <mach/scm.h>
#include <mach/ramdump.h>
#include <mach/msm_smem.h>
+#include <mach/msm_bus_board.h>
#include "peripheral-loader.h"
#include "pil-q6v5.h"
@@ -472,6 +473,8 @@
dev_info(&pdev->dev, "using non-secure boot\n");
}
+ scm_pas_init(MSM_BUS_MASTER_CRYPTO_CORE0);
+
ret = pil_desc_init(desc);
if (ret)
return ret;
diff --git a/arch/arm/mach-msm/pil-riva.c b/arch/arm/mach-msm/pil-riva.c
index bf7438b..9a364b7 100644
--- a/arch/arm/mach-msm/pil-riva.c
+++ b/arch/arm/mach-msm/pil-riva.c
@@ -25,6 +25,7 @@
#include <mach/subsystem_restart.h>
#include <mach/ramdump.h>
#include <mach/msm_smem.h>
+#include <mach/msm_bus_board.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
@@ -534,6 +535,8 @@
goto err_subsys;
}
+ scm_pas_init(MSM_BUS_MASTER_SPS);
+
ret = devm_request_irq(&pdev->dev, drv->irq, riva_wdog_bite_irq_hdlr,
IRQF_TRIGGER_RISING, "riva_wdog", drv);
if (ret < 0)
diff --git a/arch/arm/mach-msm/pil-tzapps.c b/arch/arm/mach-msm/pil-tzapps.c
index 1410117..d9f5700 100644
--- a/arch/arm/mach-msm/pil-tzapps.c
+++ b/arch/arm/mach-msm/pil-tzapps.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-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
@@ -16,6 +16,7 @@
#include <linux/err.h>
#include <mach/subsystem_restart.h>
+#include <mach/msm_bus_board.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
@@ -97,6 +98,9 @@
pil_desc_release(desc);
return PTR_ERR(drv->subsys);
}
+
+ scm_pas_init(MSM_BUS_MASTER_SPS);
+
return 0;
}
diff --git a/arch/arm/mach-msm/pil-venus.c b/arch/arm/mach-msm/pil-venus.c
index 4e9e54b..a7ebbf7 100644
--- a/arch/arm/mach-msm/pil-venus.c
+++ b/arch/arm/mach-msm/pil-venus.c
@@ -605,6 +605,8 @@
if (!drv->ramdump_dev)
return -ENOMEM;
+ scm_pas_init(MSM_BUS_MASTER_CRYPTO_CORE0);
+
rc = pil_desc_init(desc);
if (rc)
goto err_ramdump;
diff --git a/arch/arm/mach-msm/pil-vidc.c b/arch/arm/mach-msm/pil-vidc.c
index 629907f..3dbddae 100644
--- a/arch/arm/mach-msm/pil-vidc.c
+++ b/arch/arm/mach-msm/pil-vidc.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
@@ -17,6 +17,7 @@
#include <linux/clk.h>
#include <mach/subsystem_restart.h>
+#include <mach/msm_bus_board.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
@@ -122,6 +123,9 @@
pil_desc_release(desc);
return PTR_ERR(drv->subsys);
}
+
+ scm_pas_init(MSM_BUS_MASTER_SPS);
+
return 0;
}
diff --git a/arch/arm/mach-msm/scm-pas.c b/arch/arm/mach-msm/scm-pas.c
index b244c6f..57acdc4 100644
--- a/arch/arm/mach-msm/scm-pas.c
+++ b/arch/arm/mach-msm/scm-pas.c
@@ -255,9 +255,14 @@
}
EXPORT_SYMBOL(pas_supported);
-static int __init scm_pas_init(void)
+void scm_pas_init(enum msm_bus_fabric_master_type id)
{
int i, rate;
+ static int is_inited;
+
+ if (is_inited)
+ return;
+
for (i = 0; i < NUM_CLKS; i++) {
scm_clocks[i] = clk_get_sys("scm", scm_clock_names[i]);
if (IS_ERR(scm_clocks[i]))
@@ -268,20 +273,14 @@
rate = clk_round_rate(scm_clocks[CORE_CLK_SRC], 1);
clk_set_rate(scm_clocks[CORE_CLK_SRC], rate);
- if (soc_class_is_msm8974() || cpu_is_msm8226() || cpu_is_msm8610()) {
- scm_pas_bw_tbl[0].vectors[0].src = MSM_BUS_MASTER_CRYPTO_CORE0;
- scm_pas_bw_tbl[1].vectors[0].src = MSM_BUS_MASTER_CRYPTO_CORE0;
- } else {
- if (!IS_ERR(scm_clocks[BUS_CLK]))
- clk_set_rate(scm_clocks[BUS_CLK], 64000000);
- else
- pr_warn("unable to get bus clock\n");
- }
+ scm_pas_bw_tbl[0].vectors[0].src = id;
+ scm_pas_bw_tbl[1].vectors[0].src = id;
+
+ clk_set_rate(scm_clocks[BUS_CLK], 64000000);
scm_perf_client = msm_bus_scale_register_client(&scm_pas_bus_pdata);
if (!scm_perf_client)
pr_warn("unable to register bus client\n");
- return 0;
+ is_inited = 1;
}
-module_init(scm_pas_init);
diff --git a/arch/arm/mach-msm/scm-pas.h b/arch/arm/mach-msm/scm-pas.h
index f13757c..48bc558 100644
--- a/arch/arm/mach-msm/scm-pas.h
+++ b/arch/arm/mach-msm/scm-pas.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-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
@@ -9,6 +9,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
+
+#include <mach/msm_bus_board.h>
+
#ifndef __MSM_SCM_PAS_H
#define __MSM_SCM_PAS_H
@@ -31,6 +34,7 @@
extern int pas_auth_and_reset(enum pas_id id);
extern int pas_shutdown(enum pas_id id);
extern int pas_supported(enum pas_id id);
+extern void scm_pas_init(enum msm_bus_fabric_master_type id);
#else
static inline int pas_init_image(enum pas_id id, const u8 *metadata,
size_t size)
@@ -53,6 +57,9 @@
{
return 0;
}
+static inline void scm_pas_init(enum msm_bus_fabric_master_type id)
+{
+}
#endif
#endif
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index e65b5ba..c2efc34 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -360,9 +360,13 @@
PTE_SET_FN(nx, pte_mknexec)
SET_MEMORY_FN(ro, pte_set_ro)
+EXPORT_SYMBOL(set_memory_ro);
SET_MEMORY_FN(rw, pte_set_rw)
+EXPORT_SYMBOL(set_memory_rw);
SET_MEMORY_FN(x, pte_set_x)
+EXPORT_SYMBOL(set_memory_x);
SET_MEMORY_FN(nx, pte_set_nx)
+EXPORT_SYMBOL(set_memory_nx);
/*
* Adjust the PMD section entries according to the CPU in use.
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index 83d94f1..7f7b4d7 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -395,21 +395,26 @@
static int get_args(uint32_t kernel, uint32_t sc, remote_arg_t *pra,
remote_arg_t *rpra, remote_arg_t *upra,
struct fastrpc_buf *ibuf, struct fastrpc_buf **abufs,
- int *nbufs)
+ int *nbufs, int *fds)
{
+ struct fastrpc_apps *me = &gfa;
struct smq_invoke_buf *list;
struct fastrpc_buf *pbuf = ibuf, *obufs = 0;
struct smq_phy_page *pages;
+ struct ion_handle **handles;
void *args;
int i, rlen, size, used, inh, bufs = 0, err = 0;
int inbufs = REMOTE_SCALARS_INBUFS(sc);
int outbufs = REMOTE_SCALARS_OUTBUFS(sc);
+ unsigned long iova, len;
list = smq_invoke_buf_start(rpra, sc);
pages = smq_phy_page_start(sc, list);
used = ALIGN(pbuf->used, BALIGN);
args = (void *)((char *)pbuf->virt + used);
rlen = pbuf->size - used;
+ if (fds)
+ handles = (struct ion_handle **)(fds + inbufs + outbufs);
for (i = 0; i < inbufs + outbufs; ++i) {
rpra[i].buf.len = pra[i].buf.len;
@@ -418,6 +423,22 @@
if (list[i].num) {
rpra[i].buf.pv = pra[i].buf.pv;
continue;
+ } else if (me->smmu.enabled && fds && (fds[i] >= 0)) {
+ len = buf_page_size(pra[i].buf.len);
+ handles[i] = ion_import_dma_buf(me->iclient, fds[i]);
+ VERIFY(err, 0 == IS_ERR_OR_NULL(handles[i]));
+ if (err)
+ goto bail;
+ VERIFY(err, 0 == ion_map_iommu(me->iclient, handles[i],
+ me->smmu.domain_id, 0, SZ_4K, 0,
+ &iova, &len, 0, 0));
+ if (err)
+ goto bail;
+ rpra[i].buf.pv = pra[i].buf.pv;
+ list[i].num = 1;
+ pages[list[i].pgidx].addr = iova;
+ pages[list[i].pgidx].size = len;
+ continue;
}
if (rlen < pra[i].buf.len) {
struct fastrpc_buf *b;
@@ -770,15 +791,17 @@
static int fastrpc_release_current_dsp_process(void);
static int fastrpc_internal_invoke(struct fastrpc_apps *me, uint32_t kernel,
- struct fastrpc_ioctl_invoke *invoke, remote_arg_t *pra)
+ struct fastrpc_ioctl_invoke *invoke, remote_arg_t *pra,
+ int *fds)
{
remote_arg_t *rpra = 0;
struct fastrpc_device *dev = 0;
struct smq_invoke_ctx *ctx = 0;
struct fastrpc_buf obuf, *abufs = 0, *b;
+ struct ion_handle **handles;
int interrupted = 0;
uint32_t sc;
- int i, nbufs = 0, err = 0;
+ int i, bufs, nbufs = 0, err = 0;
sc = invoke->sc;
obuf.handle = 0;
@@ -798,7 +821,7 @@
goto bail;
rpra = (remote_arg_t *)obuf.virt;
VERIFY(err, 0 == get_args(kernel, sc, pra, rpra, invoke->pra,
- &obuf, &abufs, &nbufs));
+ &obuf, &abufs, &nbufs, fds));
if (err)
goto bail;
}
@@ -828,8 +851,19 @@
}
context_free(ctx);
- if (me->smmu.enabled)
+ if (me->smmu.enabled) {
+ bufs = REMOTE_SCALARS_LENGTH(sc);
+ if (fds) {
+ handles = (struct ion_handle **)(fds + bufs);
+ for (i = 0; i < bufs; i++)
+ if (!IS_ERR_OR_NULL(handles[i])) {
+ ion_unmap_iommu(me->iclient, handles[i],
+ me->smmu.domain_id, 0);
+ ion_free(me->iclient, handles[i]);
+ }
+ }
iommu_detach_group(me->smmu.domain, me->smmu.group);
+ }
for (i = 0, b = abufs; i < nbufs; ++i, ++b)
free_mem(b);
@@ -856,7 +890,7 @@
ioctl.handle = 1;
ioctl.sc = REMOTE_SCALARS_MAKE(0, 1, 0);
ioctl.pra = ra;
- VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 1, &ioctl, ra)));
+ VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 1, &ioctl, ra, 0)));
return err;
}
@@ -874,7 +908,7 @@
ioctl.handle = 1;
ioctl.sc = REMOTE_SCALARS_MAKE(1, 1, 0);
ioctl.pra = ra;
- VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 1, &ioctl, ra)));
+ VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 1, &ioctl, ra, 0)));
return err;
}
@@ -912,7 +946,7 @@
ioctl.handle = 1;
ioctl.sc = REMOTE_SCALARS_MAKE(2, 2, 1);
ioctl.pra = ra;
- VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 1, &ioctl, ra)));
+ VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 1, &ioctl, ra, 0)));
mmap->vaddrout = routargs.vaddrout;
if (err)
goto bail;
@@ -941,7 +975,7 @@
ioctl.handle = 1;
ioctl.sc = REMOTE_SCALARS_MAKE(3, 1, 0);
ioctl.pra = ra;
- VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 1, &ioctl, ra)));
+ VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 1, &ioctl, ra, 0)));
return err;
}
@@ -1107,33 +1141,49 @@
unsigned long ioctl_param)
{
struct fastrpc_apps *me = &gfa;
- struct fastrpc_ioctl_invoke invoke;
+ struct fastrpc_ioctl_invoke_fd invokefd;
+ struct fastrpc_ioctl_invoke *invoke = &invokefd.inv;
struct fastrpc_ioctl_mmap mmap;
struct fastrpc_ioctl_munmap munmap;
remote_arg_t *pra = 0;
void *param = (char *)ioctl_param;
struct file_data *fdata = (struct file_data *)file->private_data;
- int bufs, err = 0;
+ int *fds = 0;
+ int bufs, size = 0, err = 0;
switch (ioctl_num) {
+ case FASTRPC_IOCTL_INVOKE_FD:
case FASTRPC_IOCTL_INVOKE:
- VERIFY(err, 0 == copy_from_user(&invoke, param,
- sizeof(invoke)));
+ invokefd.fds = 0;
+ size = (ioctl_num == FASTRPC_IOCTL_INVOKE) ?
+ sizeof(*invoke) : sizeof(invokefd);
+ VERIFY(err, 0 == copy_from_user(&invokefd, param, size));
if (err)
goto bail;
- bufs = REMOTE_SCALARS_INBUFS(invoke.sc) +
- REMOTE_SCALARS_OUTBUFS(invoke.sc);
+ bufs = REMOTE_SCALARS_INBUFS(invoke->sc) +
+ REMOTE_SCALARS_OUTBUFS(invoke->sc);
if (bufs) {
- bufs = bufs * sizeof(*pra);
- VERIFY(err, 0 != (pra = kmalloc(bufs, GFP_KERNEL)));
+ size = bufs * sizeof(*pra);
+ if (invokefd.fds)
+ size = size + bufs * sizeof(*fds) +
+ bufs * sizeof(struct ion_handle *);
+ VERIFY(err, 0 != (pra = kzalloc(size, GFP_KERNEL)));
if (err)
goto bail;
}
- VERIFY(err, 0 == copy_from_user(pra, invoke.pra, bufs));
+ VERIFY(err, 0 == copy_from_user(pra, invoke->pra,
+ bufs * sizeof(*pra)));
if (err)
goto bail;
- VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 0, &invoke,
- pra)));
+ if (invokefd.fds) {
+ fds = (int *)(pra + bufs);
+ VERIFY(err, 0 == copy_from_user(fds, invokefd.fds,
+ bufs * sizeof(*fds)));
+ if (err)
+ goto bail;
+ }
+ VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 0, invoke,
+ pra, fds)));
if (err)
goto bail;
break;
diff --git a/drivers/char/adsprpc_shared.h b/drivers/char/adsprpc_shared.h
index f2804ad..da70eb5 100644
--- a/drivers/char/adsprpc_shared.h
+++ b/drivers/char/adsprpc_shared.h
@@ -19,6 +19,7 @@
#define FASTRPC_IOCTL_INVOKE _IOWR('R', 1, struct fastrpc_ioctl_invoke)
#define FASTRPC_IOCTL_MMAP _IOWR('R', 2, struct fastrpc_ioctl_mmap)
#define FASTRPC_IOCTL_MUNMAP _IOWR('R', 3, struct fastrpc_ioctl_munmap)
+#define FASTRPC_IOCTL_INVOKE_FD _IOWR('R', 4, struct fastrpc_ioctl_invoke_fd)
#define FASTRPC_SMD_GUID "fastrpcsmd-apps-dsp"
#define DEVICE_NAME "adsprpc-smd"
@@ -94,6 +95,11 @@
remote_arg_t *pra; /* remote arguments list */
};
+struct fastrpc_ioctl_invoke_fd {
+ struct fastrpc_ioctl_invoke inv;
+ int *fds; /* fd list */
+};
+
struct fastrpc_ioctl_munmap {
uint32_t vaddrout; /* address to unmap */
int size; /* size */
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index d01496e..0c67ed8 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -20,6 +20,8 @@
#include <linux/workqueue.h>
#include <linux/pm_runtime.h>
#include <linux/platform_device.h>
+#include <linux/pm_wakeup.h>
+#include <linux/spinlock.h>
#include <asm/current.h>
#ifdef CONFIG_DIAG_OVER_USB
#include <mach/usbdiag.h>
@@ -39,6 +41,12 @@
struct mutex dci_event_mask_mutex;
struct mutex dci_health_mutex;
+spinlock_t ws_lock;
+unsigned long ws_lock_flags;
+
+/* Number of milliseconds anticipated to process the DCI data */
+#define DCI_WAKEUP_TIMEOUT 1
+
#define DCI_CHK_CAPACITY(entry, new_data_len) \
((entry->data_len + new_data_len > entry->total_capacity) ? 1 : 0) \
@@ -96,6 +104,11 @@
read_bytes += 5 + dci_pkt_len;
buf += 5 + dci_pkt_len; /* advance to next DCI pkt */
}
+ /* Release wakeup source when there are no more clients to
+ process DCI data */
+ if (driver->num_dci_client == 0)
+ diag_dci_try_deactivate_wakeup_source(smd_info->ch);
+
/* wake up all sleeping DCI clients which have some data */
for (i = 0; i < MAX_DCI_CLIENTS; i++) {
if (driver->dci_client_tbl[i].client &&
@@ -1101,6 +1114,9 @@
diag_smd_notify);
driver->smd_dci[index].ch_save =
driver->smd_dci[index].ch;
+ driver->dci_device = &pdev->dev;
+ driver->dci_device->power.wakeup = wakeup_source_register
+ ("DIAG_DCI_WS");
if (err)
pr_err("diag: In %s, cannot open DCI port, Id = %d, err: %d\n",
__func__, pdev->id, err);
@@ -1123,6 +1139,9 @@
diag_smd_notify);
driver->smd_dci_cmd[index].ch_save =
driver->smd_dci_cmd[index].ch;
+ driver->dci_cmd_device = &pdev->dev;
+ driver->dci_cmd_device->power.wakeup = wakeup_source_register
+ ("DIAG_DCI_CMD_WS");
if (err)
pr_err("diag: In %s, cannot open DCI port, Id = %d, err: %d\n",
__func__, pdev->id, err);
@@ -1174,10 +1193,13 @@
driver->dci_tag = 0;
driver->dci_client_id = 0;
driver->num_dci_client = 0;
+ driver->dci_device = NULL;
+ driver->dci_cmd_device = NULL;
mutex_init(&driver->dci_mutex);
mutex_init(&dci_log_mask_mutex);
mutex_init(&dci_event_mask_mutex);
mutex_init(&dci_health_mutex);
+ spin_lock_init(&ws_lock);
for (i = 0; i < NUM_SMD_DCI_CHANNELS; i++) {
success = diag_smd_constructor(&driver->smd_dci[i], i,
@@ -1408,3 +1430,26 @@
driver->dci_client_tbl[i].real_time = real_time;
return i;
}
+
+void diag_dci_try_activate_wakeup_source(smd_channel_t *channel)
+{
+ spin_lock_irqsave(&ws_lock, ws_lock_flags);
+ if (channel == driver->smd_dci[MODEM_DATA].ch) {
+ pm_wakeup_event(driver->dci_device, DCI_WAKEUP_TIMEOUT);
+ pm_stay_awake(driver->dci_device);
+ } else if (channel == driver->smd_dci_cmd[MODEM_DATA].ch) {
+ pm_wakeup_event(driver->dci_cmd_device, DCI_WAKEUP_TIMEOUT);
+ pm_stay_awake(driver->dci_cmd_device);
+ }
+ spin_unlock_irqrestore(&ws_lock, ws_lock_flags);
+}
+
+void diag_dci_try_deactivate_wakeup_source(smd_channel_t *channel)
+{
+ spin_lock_irqsave(&ws_lock, ws_lock_flags);
+ if (channel == driver->smd_dci[MODEM_DATA].ch)
+ pm_relax(driver->dci_device);
+ else if (channel == driver->smd_dci_cmd[MODEM_DATA].ch)
+ pm_relax(driver->dci_cmd_device);
+ spin_unlock_irqrestore(&ws_lock, ws_lock_flags);
+}
diff --git a/drivers/char/diag/diag_dci.h b/drivers/char/diag/diag_dci.h
index 2335d37..520995b 100644
--- a/drivers/char/diag/diag_dci.h
+++ b/drivers/char/diag/diag_dci.h
@@ -138,4 +138,7 @@
void diag_dci_smd_record_info(int read_bytes);
uint8_t diag_dci_get_cumulative_real_time(void);
int diag_dci_set_real_time(int client_id, uint8_t real_time);
+/* Functions related to DCI wakeup sources */
+void diag_dci_try_activate_wakeup_source(smd_channel_t *channel);
+void diag_dci_try_deactivate_wakeup_source(smd_channel_t *channel);
#endif
diff --git a/drivers/char/diag/diag_debugfs.c b/drivers/char/diag/diag_debugfs.c
index 0badda6..3d1a6cd 100644
--- a/drivers/char/diag/diag_debugfs.c
+++ b/drivers/char/diag/diag_debugfs.c
@@ -176,6 +176,26 @@
bytes_in_buf += bytes_written;
bytes_remaining -= bytes_written;
#endif
+ if (driver->dci_device) {
+ bytes_written = scnprintf(buf+bytes_in_buf,
+ bytes_remaining,
+ "dci power active, relax: %lu, %lu\n",
+ driver->dci_device->power.wakeup->active_count,
+ driver->dci_device->power.wakeup->relax_count);
+ bytes_in_buf += bytes_written;
+ bytes_remaining -= bytes_written;
+ }
+ if (driver->dci_cmd_device) {
+ bytes_written = scnprintf(buf+bytes_in_buf,
+ bytes_remaining,
+ "dci cmd power active, relax: %lu, %lu\n",
+ driver->dci_cmd_device->power.wakeup->
+ active_count,
+ driver->dci_cmd_device->power.wakeup->
+ relax_count);
+ bytes_in_buf += bytes_written;
+ bytes_remaining -= bytes_written;
+ }
}
temp_data += diag_dbgfs_dci_data_index;
for (i = diag_dbgfs_dci_data_index; i < DIAG_DCI_DEBUG_CNT; i++) {
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index b7784b5..3ae56c5 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -333,6 +333,8 @@
unsigned hdlc_count;
unsigned hdlc_escape;
int in_busy_pktdata;
+ struct device *dci_device;
+ struct device *dci_cmd_device;
/* Variables for non real time mode */
int real_time_mode;
int real_time_update_busy;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 8df1b49..5e06f19 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -1453,19 +1453,25 @@
driver->data_ready[index] ^= DCI_DATA_TYPE;
for (i = 0; i < NUM_SMD_DCI_CHANNELS; i++) {
driver->smd_dci[i].in_busy_1 = 0;
- if (driver->smd_dci[i].ch)
+ if (driver->smd_dci[i].ch) {
+ diag_dci_try_deactivate_wakeup_source(
+ driver->smd_dci[i].ch);
queue_work(driver->diag_dci_wq,
&(driver->smd_dci[i].diag_read_smd_work));
+ }
}
if (driver->supports_separate_cmdrsp) {
for (i = 0; i < NUM_SMD_DCI_CMD_CHANNELS; i++) {
if (!driver->separate_cmdrsp[i])
continue;
driver->smd_dci_cmd[i].in_busy_1 = 0;
- if (driver->smd_dci_cmd[i].ch)
+ if (driver->smd_dci_cmd[i].ch) {
+ diag_dci_try_deactivate_wakeup_source(
+ driver->smd_dci_cmd[i].ch);
queue_work(driver->diag_dci_wq,
&(driver->smd_dci_cmd[i].
diag_read_smd_work));
+ }
}
}
goto exit;
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 6e7080e..de4433b 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -390,10 +390,18 @@
(smd_info->type == SMD_DATA_TYPE))
buf = smd_info->buf_in_2;
+ if (!buf && (smd_info->type == SMD_DCI_TYPE ||
+ smd_info->type == SMD_DCI_CMD_TYPE))
+ diag_dci_try_deactivate_wakeup_source(smd_info->ch);
+
if (smd_info->ch && buf) {
temp_buf = buf;
pkt_len = smd_cur_packet_size(smd_info->ch);
+ if (pkt_len == 0 && (smd_info->type == SMD_DCI_TYPE ||
+ smd_info->type == SMD_DCI_CMD_TYPE))
+ diag_dci_try_deactivate_wakeup_source(smd_info->ch);
+
while (pkt_len && (pkt_len != total_recd)) {
loop_count++;
r = smd_read_avail(smd_info->ch);
@@ -412,7 +420,7 @@
} else {
pr_debug("diag: In %s, return from wait_event ch closed\n",
__func__);
- return;
+ goto fail_return;
}
}
total_recd += r;
@@ -425,13 +433,13 @@
} else {
pr_err("diag: In %s, SMD sending in packets more than %d bytes\n",
__func__, MAX_IN_BUF_SIZE);
- return;
+ goto fail_return;
}
}
if (pkt_len < r) {
pr_err("diag: In %s, SMD sending incorrect pkt\n",
__func__);
- return;
+ goto fail_return;
}
if (pkt_len > r) {
pr_debug("diag: In %s, SMD sending partial pkt %d %d %d %d %d %d\n",
@@ -462,6 +470,13 @@
(driver->logging_mode == MEMORY_DEVICE_MODE)) {
chk_logging_wakeup();
}
+ return;
+
+fail_return:
+ if (smd_info->type == SMD_DCI_TYPE ||
+ smd_info->type == SMD_DCI_CMD_TYPE)
+ diag_dci_try_deactivate_wakeup_source(smd_info->ch);
+ return;
}
void diag_read_smd_work_fn(struct work_struct *work)
@@ -1705,10 +1720,12 @@
wake_up(&driver->smd_wait_q);
if (smd_info->type == SMD_DCI_TYPE ||
- smd_info->type == SMD_DCI_CMD_TYPE)
+ smd_info->type == SMD_DCI_CMD_TYPE) {
+ if (event == SMD_EVENT_DATA)
+ diag_dci_try_activate_wakeup_source(smd_info->ch);
queue_work(driver->diag_dci_wq,
&(smd_info->diag_read_smd_work));
- else
+ } else
queue_work(driver->diag_wq, &(smd_info->diag_read_smd_work));
}
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c
index d069f2e..0e4b309 100644
--- a/drivers/crypto/msm/qcedev.c
+++ b/drivers/crypto/msm/qcedev.c
@@ -1937,7 +1937,7 @@
rc = misc_register(&podev->miscdevice);
qce_hw_support(podev->qce, &podev->ce_support);
if (podev->ce_support.bam) {
- podev->platform_support.ce_shared = podev->ce_support.is_shared;
+ podev->platform_support.ce_shared = 0;
podev->platform_support.shared_ce_resource = 0;
podev->platform_support.hw_key_support =
podev->ce_support.hw_key;
diff --git a/drivers/gpio/qpnp-pin.c b/drivers/gpio/qpnp-pin.c
index 64341e9..ed001f0 100644
--- a/drivers/gpio/qpnp-pin.c
+++ b/drivers/gpio/qpnp-pin.c
@@ -589,6 +589,9 @@
}
mutex_unlock(&qpnp_pin_chips_lock);
+ if (!q_spec)
+ return -ENODEV;
+
rc = _qpnp_pin_config(q_chip, q_spec, param);
return rc;
@@ -1225,6 +1228,8 @@
if (!res) {
dev_err(&spmi->dev, "%s: node %s is missing has no base address definition\n",
__func__, d_node->of_node->full_name);
+ rc = -EINVAL;
+ goto err_probe;
}
rc = of_property_read_u32(d_node->of_node,
diff --git a/drivers/gpu/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c
index f990ada..118c39a 100644
--- a/drivers/gpu/ion/msm/msm_ion.c
+++ b/drivers/gpu/ion/msm/msm_ion.c
@@ -264,6 +264,9 @@
}
}
+ if (!outer_cache_op)
+ return -EINVAL;
+
outer_cache_op(buff_phys_start + offset,
buff_phys_start + offset + length);
diff --git a/drivers/hwmon/qpnp-adc-common.c b/drivers/hwmon/qpnp-adc-common.c
index 8e350f0..4e77ca2 100644
--- a/drivers/hwmon/qpnp-adc-common.c
+++ b/drivers/hwmon/qpnp-adc-common.c
@@ -923,8 +923,12 @@
pr_err("Invalid channel fast average setup\n");
return -EINVAL;
}
- calibration_param = of_get_property(child,
- "qcom,calibration-type", NULL);
+ rc = of_property_read_string(child, "qcom,calibration-type",
+ &calibration_param);
+ if (rc) {
+ pr_err("Invalid calibration type\n");
+ return -EINVAL;
+ }
if (!strncmp(calibration_param, "absolute", 8))
calib_type = CALIB_ABSOLUTE;
else if (!strncmp(calibration_param, "ratiometric", 11))
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index 309944e..53e43d1 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -866,6 +866,11 @@
amux_prescaling =
vadc->adc->adc_channels[dt_index].chan_path_prescaling;
+ if (amux_prescaling >= PATH_SCALING_NONE) {
+ rc = -EINVAL;
+ goto fail_unlock;
+ }
+
vadc->adc->amux_prop->chan_prop->offset_gain_numerator =
qpnp_vadc_amux_scaling_ratio[amux_prescaling].num;
vadc->adc->amux_prop->chan_prop->offset_gain_denominator =
@@ -1016,6 +1021,11 @@
amux_prescaling =
vadc->adc->adc_channels[dt_index].chan_path_prescaling;
+ if (amux_prescaling >= PATH_SCALING_NONE) {
+ rc = -EINVAL;
+ goto fail;
+ }
+
vadc->adc->amux_prop->chan_prop->offset_gain_numerator =
qpnp_vadc_amux_scaling_ratio[amux_prescaling].num;
vadc->adc->amux_prop->chan_prop->offset_gain_denominator =
diff --git a/drivers/input/misc/bmp18x-core.c b/drivers/input/misc/bmp18x-core.c
index bac9059..4b5b710 100644
--- a/drivers/input/misc/bmp18x-core.c
+++ b/drivers/input/misc/bmp18x-core.c
@@ -441,7 +441,7 @@
mutex_unlock(&data->lock);
}
- return success;
+ return count;
}
static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO,
show_enable, set_enable);
@@ -573,7 +573,7 @@
int err = 0;
if (pdata && pdata->init_hw) {
- err = pdata->init_hw();
+ err = pdata->init_hw(data_bus);
if (err) {
printk(KERN_ERR "%s: init_hw failed!\n",
BMP18X_NAME);
@@ -633,7 +633,7 @@
kfree(data);
exit:
if (pdata && pdata->deinit_hw)
- pdata->deinit_hw();
+ pdata->deinit_hw(data_bus);
return err;
}
EXPORT_SYMBOL(bmp18x_probe);
@@ -655,9 +655,9 @@
int bmp18x_disable(struct device *dev)
{
struct bmp18x_platform_data *pdata = dev->platform_data;
-
+ struct bmp18x_data *data = dev_get_drvdata(dev);
if (pdata && pdata->deinit_hw)
- pdata->deinit_hw();
+ pdata->deinit_hw(&data->data_bus);
return 0;
}
@@ -666,9 +666,9 @@
int bmp18x_enable(struct device *dev)
{
struct bmp18x_platform_data *pdata = dev->platform_data;
-
+ struct bmp18x_data *data = dev_get_drvdata(dev);
if (pdata && pdata->init_hw)
- return pdata->init_hw();
+ return pdata->init_hw(&data->data_bus);
return 0;
}
diff --git a/drivers/input/misc/bmp18x-i2c.c b/drivers/input/misc/bmp18x-i2c.c
index 6c01ad3..abbe6e5 100644
--- a/drivers/input/misc/bmp18x-i2c.c
+++ b/drivers/input/misc/bmp18x-i2c.c
@@ -22,8 +22,137 @@
#include <linux/module.h>
#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/regulator/consumer.h>
#include "bmp18x.h"
+struct sensor_regulator {
+ struct regulator *vreg;
+ const char *name;
+ u32 min_uV;
+ u32 max_uV;
+};
+
+struct sensor_regulator bmp_vreg[] = {
+ {NULL, "vdd", 2850000, 2850000},
+ {NULL, "vddio", 1800000, 1800000},
+};
+
+
+static int bmp18x_config_regulator(struct i2c_client *client, bool on)
+{
+ int rc = 0, i;
+ int num_vreg = ARRAY_SIZE(bmp_vreg);
+
+ if (on) {
+ for (i = 0; i < num_vreg; i++) {
+ bmp_vreg[i].vreg = regulator_get(&client->dev,
+ bmp_vreg[i].name);
+ if (IS_ERR(bmp_vreg[i].vreg)) {
+ rc = PTR_ERR(bmp_vreg[i].vreg);
+ dev_err(&client->dev, "%s:regulator get failed rc=%d\n",
+ __func__, rc);
+ bmp_vreg[i].vreg = NULL;
+ goto error_vdd;
+ }
+ if (regulator_count_voltages(bmp_vreg[i].vreg) > 0) {
+ rc = regulator_set_voltage(bmp_vreg[i].vreg,
+ bmp_vreg[i].min_uV, bmp_vreg[i].max_uV);
+ if (rc) {
+ dev_err(&client->dev, "%s:set_voltage failed rc=%d\n",
+ __func__, rc);
+ regulator_put(bmp_vreg[i].vreg);
+ bmp_vreg[i].vreg = NULL;
+ goto error_vdd;
+ }
+ }
+ rc = regulator_enable(bmp_vreg[i].vreg);
+ if (rc) {
+ dev_err(&client->dev, "%s: regulator_enable failed rc =%d\n",
+ __func__, rc);
+ if (regulator_count_voltages(bmp_vreg[i].vreg)
+ > 0) {
+ regulator_set_voltage(bmp_vreg[i].vreg,
+ 0, bmp_vreg[i].max_uV);
+ }
+ regulator_put(bmp_vreg[i].vreg);
+ bmp_vreg[i].vreg = NULL;
+ goto error_vdd;
+ }
+ }
+ return rc;
+ } else {
+ i = num_vreg;
+ }
+error_vdd:
+ while (--i >= 0) {
+ if (!IS_ERR_OR_NULL(bmp_vreg[i].vreg)) {
+ if (regulator_count_voltages(
+ bmp_vreg[i].vreg) > 0) {
+ regulator_set_voltage(bmp_vreg[i].vreg, 0,
+ bmp_vreg[i].max_uV);
+ }
+ regulator_disable(bmp_vreg[i].vreg);
+ regulator_put(bmp_vreg[i].vreg);
+ bmp_vreg[i].vreg = NULL;
+ }
+ }
+ return rc;
+}
+
+static int bmp18x_init_hw(struct bmp18x_data_bus *data_bus)
+{
+ if (data_bus->client)
+ return bmp18x_config_regulator(data_bus->client, 1);
+ return 0;
+}
+
+static void bmp18x_deinit_hw(struct bmp18x_data_bus *data_bus)
+{
+ if (data_bus->client)
+ bmp18x_config_regulator(data_bus->client, 0);
+}
+
+#ifdef CONFIG_OF
+static int bmp18x_parse_dt(struct device *dev,
+ struct bmp18x_platform_data *pdata)
+{
+ int ret = 0;
+ u32 val;
+
+ ret = of_property_read_u32(dev->of_node, "bosch,chip-id", &val);
+ if (ret) {
+ dev_err(dev, "no chip_id from dt\n");
+ return ret;
+ }
+ pdata->chip_id = (u8)val;
+
+ ret = of_property_read_u32(dev->of_node, "bosch,oversample", &val);
+ if (ret) {
+ dev_err(dev, "no default_oversampling from dt\n");
+ return ret;
+ }
+ pdata->default_oversampling = (u8)val;
+
+ ret = of_property_read_u32(dev->of_node, "bosch,period",
+ &pdata->temp_measurement_period);
+ if (ret) {
+ dev_err(dev, "no temp_measurement_period from dt\n");
+ return ret;
+ }
+
+ pdata->default_sw_oversampling = of_property_read_bool(dev->of_node,
+ "bosch,sw-oversample");
+ return 0;
+}
+#else
+static int bmp18x_parse_dt(struct device *dev,
+ struct bmp18x_platform_data *pdata)
+{
+ return -EINVAL;
+}
+#endif
+
static int bmp18x_i2c_read_block(void *client, u8 reg, int len, char *buf)
{
return i2c_smbus_read_i2c_block_data(client, reg, len, buf);
@@ -52,7 +181,25 @@
.bops = &bmp18x_i2c_bus_ops,
.client = client
};
+ struct bmp18x_platform_data *pdata;
+ int ret;
+ if (client->dev.of_node) {
+ pdata = devm_kzalloc(&client->dev,
+ sizeof(struct bmp18x_platform_data), GFP_KERNEL);
+ if (!pdata) {
+ dev_err(&client->dev, "Failed to allocate memory\n");
+ return -ENOMEM;
+ }
+ ret = bmp18x_parse_dt(&client->dev, pdata);
+ if (ret) {
+ dev_err(&client->dev, "Failed to parse device tree\n");
+ return ret;
+ }
+ pdata->init_hw = bmp18x_init_hw;
+ pdata->deinit_hw = bmp18x_deinit_hw;
+ client->dev.platform_data = pdata;
+ }
return bmp18x_probe(&client->dev, &data_bus);
}
@@ -89,6 +236,11 @@
};
MODULE_DEVICE_TABLE(i2c, bmp18x_id);
+static const struct of_device_id bmp18x_of_match[] = {
+ { .compatible = "bosch,bmp180", },
+ { },
+};
+
static struct i2c_driver bmp18x_i2c_driver = {
.driver = {
.owner = THIS_MODULE,
@@ -96,6 +248,7 @@
#ifdef CONFIG_PM
.pm = &bmp18x_i2c_pm_ops,
#endif
+ .of_match_table = bmp18x_of_match,
},
.id_table = bmp18x_id,
.probe = bmp18x_i2c_probe,
diff --git a/drivers/input/misc/bmp18x.h b/drivers/input/misc/bmp18x.h
index f9d55ec..d1b1ee7 100644
--- a/drivers/input/misc/bmp18x.h
+++ b/drivers/input/misc/bmp18x.h
@@ -34,14 +34,6 @@
* @init_hw: Callback for hw specific startup
* @deinit_hw: Callback for hw specific shutdown
*/
-struct bmp18x_platform_data {
- u8 chip_id;
- u8 default_oversampling;
- u8 default_sw_oversampling;
- u32 temp_measurement_period;
- int (*init_hw)(void);
- void (*deinit_hw)(void);
-};
struct bmp18x_bus_ops {
int (*read_block)(void *client, u8 reg, int len, char *buf);
@@ -50,10 +42,19 @@
};
struct bmp18x_data_bus {
- const struct bmp18x_bus_ops *bops;
+ const struct bmp18x_bus_ops *bops;
void *client;
};
+struct bmp18x_platform_data {
+ u8 chip_id;
+ u8 default_oversampling;
+ u8 default_sw_oversampling;
+ u32 temp_measurement_period;
+ int (*init_hw)(struct bmp18x_data_bus *);
+ void (*deinit_hw)(struct bmp18x_data_bus *);
+};
+
int bmp18x_probe(struct device *dev, struct bmp18x_data_bus *data_bus);
int bmp18x_remove(struct device *dev);
#ifdef CONFIG_PM
diff --git a/drivers/input/misc/mma8x5x.c b/drivers/input/misc/mma8x5x.c
index 8a0d4ab..f1ea705 100644
--- a/drivers/input/misc/mma8x5x.c
+++ b/drivers/input/misc/mma8x5x.c
@@ -2,6 +2,9 @@
* mma8x5x.c - Linux kernel modules for 3-Axis Orientation/Motion
* Detection Sensor MMA8451/MMA8452/MMA8453
*
+ * Copyright (c) 2013, The Linux Foundation. All Rights Reserved.
+ * Linux Foundation chooses to take subject only to the GPLv2 license
+ * terms, and distributes only under these terms.
* Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -18,23 +21,16 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-
+#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/init.h>
#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/pm.h>
-#include <linux/mutex.h>
#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/hwmon-sysfs.h>
-#include <linux/err.h>
-#include <linux/hwmon.h>
+#include <linux/i2c.h>
#include <linux/input-polldev.h>
#include <linux/regulator/consumer.h>
+#include <linux/of_gpio.h>
-#define MMA8X5X_I2C_ADDR 0x1D
+#define ACCEL_INPUT_DEV_NAME "accelerometer"
#define MMA8451_ID 0x1A
#define MMA8452_ID 0x2A
#define MMA8453_ID 0x3A
@@ -151,6 +147,8 @@
int position;
u8 chip_id;
int mode;
+ int int_pin;
+ u32 int_flags;
};
/* Addresses scanned */
static const unsigned short normal_i2c[] = {0x1c, 0x1d, I2C_CLIENT_END};
@@ -391,7 +389,8 @@
MMA8X5X_CTRL_REG1, val|0x01);
if (!ret) {
pdata->active = MMA_ACTIVED;
- printk(KERN_INFO "mma enable setting active\n");
+ dev_dbg(dev,
+ "%s:mma enable setting active.\n", __func__);
}
} else if (enable == 0 && pdata->active == MMA_ACTIVED) {
val = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG1);
@@ -399,7 +398,8 @@
MMA8X5X_CTRL_REG1, val & 0xFE);
if (!ret) {
pdata->active = MMA_STANDBY;
- printk(KERN_INFO "mma enable setting inactive\n");
+ dev_dbg(dev,
+ "%s:mma enable setting inactive.\n", __func__);
}
}
mutex_unlock(&pdata->data_lock);
@@ -458,11 +458,36 @@
chip_id = i2c_smbus_read_byte_data(client, MMA8X5X_WHO_AM_I);
if (!mma8x5x_check_id(chip_id))
return -ENODEV;
- printk(KERN_INFO "check %s i2c address 0x%x\n",
- mma8x5x_id2name(chip_id), client->addr);
+ dev_dbg(&client->dev, "%s,check %s i2c address 0x%x.\n",
+ __func__, mma8x5x_id2name(chip_id), client->addr);
strlcpy(info->type, "mma8x5x", I2C_NAME_SIZE);
return 0;
}
+
+static int mma8x5x_parse_dt(struct device *dev, struct mma8x5x_data *data)
+{
+ int rc;
+ struct device_node *np = dev->of_node;
+ u32 temp_val;
+
+ data->int_pin = of_get_named_gpio_flags(np, "fsl,irq-gpio",
+ 0, &data->int_flags);
+ if (data->int_pin < 0) {
+ dev_err(dev, "Unable to read irq-gpio\n");
+ return data->int_pin;
+ }
+
+ rc = of_property_read_u32(np, "fsl,sensors-position", &temp_val);
+ if (!rc)
+ data->position = temp_val;
+ else {
+ dev_err(dev, "Unable to read sensors-position\n");
+ return rc;
+ }
+
+ return 0;
+}
+
static int __devinit mma8x5x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -500,11 +525,22 @@
dev_err(&client->dev, "alloc data memory error!\n");
goto err_out;
}
+
+ if (client->dev.of_node) {
+ result = mma8x5x_parse_dt(&client->dev, pdata);
+ if (result)
+ return result;
+ } else {
+ pdata->position = CONFIG_SENSORS_MMA_POSITION;
+ pdata->int_pin = -1;
+ pdata->int_flags = 0;
+ }
+
/* Initialize the MMA8X5X chip */
pdata->client = client;
pdata->chip_id = chip_id;
pdata->mode = MODE_2G;
- pdata->position = CONFIG_SENSORS_MMA_POSITION;
+
mutex_init(&pdata->data_lock);
i2c_set_clientdata(client, pdata);
/* Initialize the MMA8X5X chip */
@@ -522,7 +558,7 @@
poll_dev->poll_interval_max = POLL_INTERVAL_MAX;
poll_dev->private = pdata;
idev = poll_dev->input;
- idev->name = "accelerometer";
+ idev->name = ACCEL_INPUT_DEV_NAME;
idev->uniq = mma8x5x_id2name(pdata->chip_id);
idev->id.bustype = BUS_I2C;
idev->evbit[0] = BIT_MASK(EV_ABS);
@@ -541,7 +577,10 @@
result = -EINVAL;
goto err_create_sysfs;
}
- printk(KERN_INFO "mma8x5x device driver probe successfully\n");
+ dev_info(&client->dev,
+ "%s:mma8x5x device driver probe successfully, position =%d\n",
+ __func__, pdata->position);
+
return 0;
err_create_sysfs:
input_unregister_polled_device(pdata->poll_dev);
@@ -626,7 +665,7 @@
res = i2c_add_driver(&mma8x5x_driver);
if (res < 0) {
- printk(KERN_INFO "add mma8x5x i2c driver failed\n");
+ pr_info("%s:add mma8x5x i2c driver failed\n", __func__);
return -ENODEV;
}
return res;
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 479b788..5415f4e 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -393,6 +393,9 @@
bool update_cfg;
const char *fw_name;
bool no_force_update;
+ bool lpm_support;
+ bool regs_enabled;
+
#if defined(CONFIG_SECURE_TOUCH)
atomic_t st_enabled;
atomic_t st_pending_irqs;
@@ -2158,6 +2161,11 @@
if (on == false)
goto power_off;
+ if (data->regs_enabled) {
+ dev_dbg(&data->client->dev, "regs are already enabled\n");
+ return 0;
+ }
+
rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
if (rc < 0) {
dev_err(&data->client->dev,
@@ -2206,6 +2214,8 @@
}
}
+ data->regs_enabled = true;
+
msleep(130);
return 0;
@@ -2226,6 +2236,12 @@
return rc;
power_off:
+
+ if (!data->regs_enabled) {
+ dev_dbg(&data->client->dev, "regs are already disabled\n");
+ return 0;
+ }
+
reg_set_optimum_mode_check(data->vcc_ana, 0);
regulator_disable(data->vcc_ana);
if (data->pdata->digital_pwr_regulator) {
@@ -2236,6 +2252,9 @@
reg_set_optimum_mode_check(data->vcc_i2c, 0);
regulator_disable(data->vcc_i2c);
}
+
+ data->regs_enabled = false;
+
msleep(50);
return 0;
}
@@ -2435,8 +2454,9 @@
struct input_dev *input_dev = data->input_dev;
int error;
- mutex_lock(&input_dev->mutex);
+ disable_irq(data->irq);
+ mutex_lock(&input_dev->mutex);
if (input_dev->users) {
error = mxt_stop(data);
if (error < 0) {
@@ -2444,16 +2464,24 @@
mutex_unlock(&input_dev->mutex);
return error;
}
-
}
mutex_unlock(&input_dev->mutex);
+ mxt_release_all(data);
/* put regulators in low power mode */
- error = mxt_regulator_lpm(data, true);
- if (error < 0) {
- dev_err(dev, "failed to enter low power mode\n");
- return error;
+ if (data->lpm_support) {
+ error = mxt_regulator_lpm(data, true);
+ if (error < 0) {
+ dev_err(dev, "failed to enter low power mode\n");
+ return error;
+ }
+ } else {
+ error = mxt_power_on(data, false);
+ if (error < 0) {
+ dev_err(dev, "failed to disable regulators\n");
+ return error;
+ }
}
return 0;
@@ -2466,13 +2494,25 @@
struct input_dev *input_dev = data->input_dev;
int error;
- /* put regulators in high power mode */
- error = mxt_regulator_lpm(data, false);
- if (error < 0) {
- dev_err(dev, "failed to enter high power mode\n");
- return error;
+ /* put regulators back in active power mode */
+ if (data->lpm_support) {
+ error = mxt_regulator_lpm(data, false);
+ if (error < 0) {
+ dev_err(dev, "failed to enter high power mode\n");
+ return error;
+ }
+ } else {
+ error = mxt_power_on(data, true);
+ if (error < 0) {
+ dev_err(dev, "failed to enable regulators\n");
+ return error;
+ }
+ mxt_power_on_delay(data);
}
+ mxt_write_object(data, MXT_GEN_COMMAND_T6, MXT_COMMAND_RESET, 1);
+ mxt_reset_delay(data);
+
mutex_lock(&input_dev->mutex);
if (input_dev->users) {
@@ -2495,6 +2535,8 @@
mutex_unlock(&input_dev->mutex);
+ enable_irq(data->irq);
+
return 0;
}
@@ -2672,6 +2714,9 @@
pdata->no_force_update = of_property_read_bool(np,
"atmel,no-force-update");
+ pdata->no_lpm_support = of_property_read_bool(np,
+ "atmel,no-lpm-support");
+
/* reset, irq gpio info */
pdata->reset_gpio = of_get_named_gpio_flags(np, "atmel,reset-gpio",
0, &pdata->reset_gpio_flags);
@@ -2877,6 +2922,7 @@
data->input_dev = input_dev;
data->pdata = pdata;
data->no_force_update = pdata->no_force_update;
+ data->lpm_support = !pdata->no_lpm_support;
__set_bit(EV_ABS, input_dev->evbit);
__set_bit(EV_KEY, input_dev->evbit);
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index fbcc243..e84b477 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -170,11 +170,13 @@
#define LED_MPP_SINK_CTRL(base) (base + 0x4C)
#define LED_MPP_CURRENT_DEFAULT 5
+#define LED_MPP_VIN_CTRL_DEFAULT 0
#define LED_MPP_CURRENT_PER_SETTING 5
#define LED_MPP_SOURCE_SEL_DEFAULT LED_MPP_MODE_ENABLE
#define LED_MPP_SINK_MASK 0x07
#define LED_MPP_MODE_MASK 0x7F
+#define LED_MPP_VIN_MASK 0x03
#define LED_MPP_EN_MASK 0x80
#define LED_MPP_SRC_MASK 0x0F
#define LED_MPP_MODE_CTRL_MASK 0x70
@@ -348,6 +350,8 @@
* @current_setting - current setting, 5ma-40ma in 5ma increments
* @source_sel - source selection
* @mode_ctrl - mode control
+ * @vin_ctrl - input control
+ * @min_brightness - minimum brightness supported
* @pwm_mode - pwm mode in use
*/
struct mpp_config_data {
@@ -355,6 +359,8 @@
u8 current_setting;
u8 source_sel;
u8 mode_ctrl;
+ u8 vin_ctrl;
+ u8 min_brightness;
u8 pwm_mode;
};
@@ -576,6 +582,13 @@
int duty_us;
if (led->cdev.brightness) {
+ if (led->cdev.brightness < led->mpp_cfg->min_brightness) {
+ dev_warn(&led->spmi_dev->dev,
+ "brightness is less than supported..." \
+ "set to minimum supported\n");
+ led->cdev.brightness = led->mpp_cfg->min_brightness;
+ }
+
if (led->mpp_cfg->pwm_mode != MANUAL_MODE) {
if (!led->mpp_cfg->pwm_cfg->blinking) {
led->mpp_cfg->pwm_cfg->mode =
@@ -2093,6 +2106,14 @@
if (val < 0)
val = 0;
+ rc = qpnp_led_masked_write(led, LED_MPP_VIN_CTRL(led->base),
+ LED_MPP_VIN_MASK, led->mpp_cfg->vin_ctrl);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Failed to write led vin control reg\n");
+ return rc;
+ }
+
rc = qpnp_led_masked_write(led, LED_MPP_SINK_CTRL(led->base),
LED_MPP_SINK_MASK, val);
if (rc) {
@@ -2677,6 +2698,20 @@
else if (rc != -EINVAL)
return rc;
+ led->mpp_cfg->vin_ctrl = LED_MPP_VIN_CTRL_DEFAULT;
+ rc = of_property_read_u32(node, "qcom,vin-ctrl", &val);
+ if (!rc)
+ led->mpp_cfg->vin_ctrl = (u8) val;
+ else if (rc != -EINVAL)
+ return rc;
+
+ led->mpp_cfg->min_brightness = 0;
+ rc = of_property_read_u32(node, "qcom,min-brightness", &val);
+ if (!rc)
+ led->mpp_cfg->min_brightness = (u8) val;
+ else if (rc != -EINVAL)
+ return rc;
+
rc = of_property_read_string(node, "qcom,mode", &mode);
if (!rc) {
led_mode = qpnp_led_get_mode(mode);
diff --git a/drivers/media/platform/msm/camera_v2/msm.c b/drivers/media/platform/msm/camera_v2/msm.c
index 8d53e35..07f3b40 100644
--- a/drivers/media/platform/msm/camera_v2/msm.c
+++ b/drivers/media/platform/msm/camera_v2/msm.c
@@ -519,6 +519,7 @@
struct msm_session *session;
unsigned int session_id;
unsigned int stream_id;
+ unsigned long spin_flags = 0;
event_data = (struct msm_v4l2_event_data *)
((struct v4l2_event *)arg)->u.data;
@@ -564,9 +565,13 @@
break;
}
+ spin_lock_irqsave(&(session->command_ack_q.lock),
+ spin_flags);
ret_cmd->event = *(struct v4l2_event *)arg;
msm_enqueue(&cmd_ack->command_q, &ret_cmd->list);
wake_up(&cmd_ack->wait);
+ spin_unlock_irqrestore(&(session->command_ack_q.lock),
+ spin_flags);
}
break;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/hi256.c b/drivers/media/platform/msm/camera_v2/sensor/hi256.c
index f1df703..de651df 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/hi256.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/hi256.c
@@ -1000,15 +1000,25 @@
{0x30, 0x06},
{0x31, 0x40},
{0x03, 0x20},
- {0x88, 0x05},
- {0x89, 0x7e},
- {0x8a, 0x40},
+ {0x88, 0x01},
+ {0x89, 0x5f},
+ {0x8a, 0x90},
{0x03, 0x20},
{0x10, 0x9c},
{0x03, 0x22},
{0x10, 0xe9},
};
+static struct msm_camera_i2c_reg_conf hi256_sleep_settings[] = {
+ {0x03, 0x00},
+ {0x01, 0xf1},
+ {0x03, 0x02},
+ {0x55, 0x10},
+ {0x01, 0xf1},
+ {0x01, 0xf3},
+ {0x01, 0xf1},
+};
+
static const struct i2c_device_id hi256_i2c_id[] = {
{HI256_SENSOR_NAME, (kernel_ulong_t)&hi256_s_ctrl},
@@ -1073,6 +1083,13 @@
}
+static int32_t hi256_sensor_power_down(struct msm_sensor_ctrl_t *s_ctrl)
+{
+ hi256_i2c_write_table(s_ctrl, &hi256_sleep_settings[0],
+ ARRAY_SIZE(hi256_sleep_settings));
+ return msm_sensor_power_down(s_ctrl);
+}
+
static int32_t hi256_platform_probe(struct platform_device *pdev)
{
int32_t rc;
@@ -1393,7 +1410,7 @@
static struct msm_sensor_fn_t hi256_sensor_func_tbl = {
.sensor_config = hi256_sensor_config,
.sensor_power_up = msm_sensor_power_up,
- .sensor_power_down = msm_sensor_power_down,
+ .sensor_power_down = hi256_sensor_power_down,
.sensor_match_id = hi256_sensor_match_id,
};
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c
index 40d1155..3792247 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c
@@ -338,17 +338,11 @@
enum msm_camera_i2c_data_type data_type)
{
int32_t rc;
- int i;
S_I2C_DBG("%s: addr: 0x%x data: 0x%x dt: %d\n",
__func__, addr, data, data_type);
- for (i = 0; i < I2C_POLL_MAX_ITERATION; i++) {
- rc = msm_camera_cci_i2c_compare(client,
- addr, data, data_type);
- if (rc == 0 || rc < 0)
- break;
- usleep_range(10000, 11000);
- }
+ rc = msm_camera_cci_i2c_compare(client,
+ addr, data, data_type);
return rc;
}
diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
index 7f474bb..adbfbe7 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
@@ -569,7 +569,92 @@
CDBG("%s qcom,gpio-reset %d\n", __func__,
gconf->gpio_num_info->gpio_num[SENSOR_GPIO_STANDBY]);
}
- return rc;
+
+ rc = of_property_read_u32(of_node, "qcom,gpio-vio", &val);
+ if (!rc) {
+ if (val >= gpio_array_size) {
+ pr_err("%s:%d qcom,gpio-vio invalid %d\n",
+ __func__, __LINE__, val);
+ goto ERROR;
+ }
+ gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VIO] =
+ gpio_array[val];
+ CDBG("%s qcom,gpio-vio %d\n", __func__,
+ gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VIO]);
+ } else if (rc != -EINVAL) {
+ pr_err("%s:%d read qcom,gpio-vio failed rc %d\n",
+ __func__, __LINE__, rc);
+ goto ERROR;
+ }
+
+ rc = of_property_read_u32(of_node, "qcom,gpio-vana", &val);
+ if (!rc) {
+ if (val >= gpio_array_size) {
+ pr_err("%s:%d qcom,gpio-vana invalid %d\n",
+ __func__, __LINE__, val);
+ goto ERROR;
+ }
+ gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VANA] =
+ gpio_array[val];
+ CDBG("%s qcom,gpio-vana %d\n", __func__,
+ gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VANA]);
+ } else if (rc != -EINVAL) {
+ pr_err("%s:%d read qcom,gpio-vana failed rc %d\n",
+ __func__, __LINE__, rc);
+ goto ERROR;
+ }
+
+ rc = of_property_read_u32(of_node, "qcom,gpio-vdig", &val);
+ if (!rc) {
+ if (val >= gpio_array_size) {
+ pr_err("%s:%d qcom,gpio-vdig invalid %d\n",
+ __func__, __LINE__, val);
+ goto ERROR;
+ }
+ gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VDIG] =
+ gpio_array[val];
+ CDBG("%s qcom,gpio-vdig %d\n", __func__,
+ gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VDIG]);
+ } else if (rc != -EINVAL) {
+ pr_err("%s:%d read qcom,gpio-vdig failed rc %d\n",
+ __func__, __LINE__, rc);
+ goto ERROR;
+ }
+
+ rc = of_property_read_u32(of_node, "qcom,gpio-vaf", &val);
+ if (!rc) {
+ if (val >= gpio_array_size) {
+ pr_err("%s:%d qcom,gpio-vaf invalid %d\n",
+ __func__, __LINE__, val);
+ goto ERROR;
+ }
+ gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VAF] =
+ gpio_array[val];
+ CDBG("%s qcom,gpio-vaf %d\n", __func__,
+ gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VAF]);
+ } else if (rc != -EINVAL) {
+ pr_err("%s:%d read qcom,gpio-vaf failed rc %d\n",
+ __func__, __LINE__, rc);
+ goto ERROR;
+ }
+
+ rc = of_property_read_u32(of_node, "qcom,gpio-af-pwdm", &val);
+ if (!rc) {
+ if (val >= gpio_array_size) {
+ pr_err("%s:%d qcom,gpio-af-pwdm invalid %d\n",
+ __func__, __LINE__, val);
+ goto ERROR;
+ }
+ gconf->gpio_num_info->gpio_num[SENSOR_GPIO_AF_PWDM] =
+ gpio_array[val];
+ CDBG("%s qcom,gpio-af-pwdm %d\n", __func__,
+ gconf->gpio_num_info->gpio_num[SENSOR_GPIO_AF_PWDM]);
+ } else if (rc != -EINVAL) {
+ pr_err("%s:%d read qcom,gpio-af-pwdm failed rc %d\n",
+ __func__, __LINE__, rc);
+ goto ERROR;
+ }
+ return 0;
ERROR:
kfree(gconf->gpio_num_info);
@@ -1162,6 +1247,15 @@
return;
}
+static int msm_sensor_get_af_status(struct msm_sensor_ctrl_t *s_ctrl,
+ void __user *argp)
+{
+ /* TO-DO: Need to set AF status register address and expected value
+ We need to check the AF status in the sensor register and
+ set the status in the *status variable accordingly*/
+ return 0;
+}
+
static long msm_sensor_subdev_ioctl(struct v4l2_subdev *sd,
unsigned int cmd, void *arg)
{
@@ -1174,6 +1268,8 @@
switch (cmd) {
case VIDIOC_MSM_SENSOR_CFG:
return s_ctrl->func_tbl->sensor_config(s_ctrl, argp);
+ case VIDIOC_MSM_SENSOR_GET_AF_STATUS:
+ return msm_sensor_get_af_status(s_ctrl, argp);
case VIDIOC_MSM_SENSOR_RELEASE:
msm_sensor_stop_stream(s_ctrl);
return 0;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/mt9m114.c b/drivers/media/platform/msm/camera_v2/sensor/mt9m114.c
index c1cf862..de4fcd0 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/mt9m114.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/mt9m114.c
@@ -1424,8 +1424,51 @@
break;
}
break;
- }
- default:
+ }
+ case CFG_SET_SATURATION: {
+ int32_t sat_lev;
+ if (copy_from_user(&sat_lev, (void *)cdata->cfg.setting,
+ sizeof(int32_t))) {
+ pr_err("%s:%d failed\n", __func__, __LINE__);
+ rc = -EFAULT;
+ break;
+ }
+ pr_debug("%s: Saturation Value is %d", __func__, sat_lev);
+ break;
+ }
+ case CFG_SET_CONTRAST: {
+ int32_t con_lev;
+ if (copy_from_user(&con_lev, (void *)cdata->cfg.setting,
+ sizeof(int32_t))) {
+ pr_err("%s:%d failed\n", __func__, __LINE__);
+ rc = -EFAULT;
+ break;
+ }
+ pr_debug("%s: Contrast Value is %d", __func__, con_lev);
+ break;
+ }
+ case CFG_SET_SHARPNESS: {
+ int32_t shp_lev;
+ if (copy_from_user(&shp_lev, (void *)cdata->cfg.setting,
+ sizeof(int32_t))) {
+ pr_err("%s:%d failed\n", __func__, __LINE__);
+ rc = -EFAULT;
+ break;
+ }
+ pr_debug("%s: Sharpness Value is %d", __func__, shp_lev);
+ break;
+ }
+ case CFG_SET_AUTOFOCUS: {
+ /* TO-DO: set the Auto Focus */
+ pr_debug("%s: Setting Auto Focus", __func__);
+ break;
+ }
+ case CFG_CANCEL_AUTOFOCUS: {
+ /* TO-DO: Cancel the Auto Focus */
+ pr_debug("%s: Cancelling Auto Focus", __func__);
+ break;
+ }
+ default:
rc = -EFAULT;
break;
}
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c
index 982e4d4..d92a9c1 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.c
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.c
@@ -360,6 +360,25 @@
return ret;
}
+static u32 get_hfi_buf_mode(enum buffer_mode_type hal_buf_mode)
+{
+ u32 buf_mode;
+ switch (hal_buf_mode) {
+ case HAL_BUFFER_MODE_STATIC:
+ buf_mode = HFI_BUFFER_MODE_STATIC;
+ break;
+ case HAL_BUFFER_MODE_RING:
+ buf_mode = HFI_BUFFER_MODE_RING;
+ break;
+ default:
+ dprintk(VIDC_ERR, "Invalid buffer mode :0x%x\n",
+ hal_buf_mode);
+ buf_mode = 0;
+ break;
+ }
+ return buf_mode;
+}
+
int create_pkt_cmd_session_set_buffers(
struct hfi_cmd_session_set_buffers_packet *pkt,
u32 session_id,
@@ -1277,6 +1296,39 @@
pkt->size += sizeof(u32) + sizeof(struct hfi_enable);
break;
}
+ case HAL_PARAM_BUFFER_ALLOC_MODE:
+ {
+ u32 buffer_type;
+ u32 buffer_mode;
+ struct hfi_buffer_alloc_mode *hfi;
+ struct hal_buffer_alloc_mode *alloc_info = pdata;
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE;
+ hfi = (struct hfi_buffer_alloc_mode *)
+ &pkt->rg_property_data[1];
+ buffer_type = get_hfi_buffer(alloc_info->buffer_type);
+ if (buffer_type)
+ hfi->buffer_type = buffer_type;
+ else
+ return -EINVAL;
+ buffer_mode = get_hfi_buf_mode(alloc_info->buffer_mode);
+ if (buffer_mode)
+ hfi->buffer_mode = buffer_mode;
+ else
+ return -EINVAL;
+ pkt->size += sizeof(u32) + sizeof(struct hfi_buffer_alloc_mode);
+ break;
+ }
+ case HAL_PARAM_VDEC_FRAME_ASSEMBLY:
+ {
+ struct hfi_enable *hfi;
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_PARAM_VDEC_FRAME_ASSEMBLY;
+ hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+ hfi->enable = ((struct hfi_enable *) pdata)->enable;
+ pkt->size += sizeof(u32) + sizeof(struct hfi_enable);
+ break;
+ }
/* FOLLOWING PROPERTIES ARE NOT IMPLEMENTED IN CORE YET */
case HAL_CONFIG_BUFFER_REQUIREMENTS:
case HAL_CONFIG_PRIORITY:
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index 7039929..96bf9f4 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -68,6 +68,10 @@
"Extradata aspect ratio",
"Extradata mpeg2 seqdisp",
};
+static const char *const mpeg_vidc_video_alloc_mode_type[] = {
+ "Buffer Allocation Static",
+ "Buffer Allocation Ring Buffer",
+};
static const char *const perf_level[] = {
"Nominal",
@@ -249,6 +253,33 @@
.qmenu = perf_level,
.step = 0,
},
+ {
+ .id = V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE,
+ .name = "Buffer allocation mode",
+ .type = V4L2_CTRL_TYPE_MENU,
+ .minimum = V4L2_MPEG_VIDC_VIDEO_STATIC,
+ .maximum = V4L2_MPEG_VIDC_VIDEO_RING,
+ .default_value = V4L2_MPEG_VIDC_VIDEO_STATIC,
+ .menu_skip_mask = ~(
+ (1 << V4L2_MPEG_VIDC_VIDEO_STATIC) |
+ (1 << V4L2_MPEG_VIDC_VIDEO_RING)
+ ),
+ .qmenu = mpeg_vidc_video_alloc_mode_type,
+ .step = 0,
+ .cluster = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDC_VIDEO_FRAME_ASSEMBLY,
+ .name = "Video frame assembly",
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .minimum = V4L2_MPEG_VIDC_FRAME_ASSEMBLY_DISABLE,
+ .maximum = V4L2_MPEG_VIDC_FRAME_ASSEMBLY_ENABLE,
+ .default_value = V4L2_MPEG_VIDC_FRAME_ASSEMBLY_DISABLE,
+ .step = 1,
+ .menu_skip_mask = 0,
+ .qmenu = NULL,
+ .cluster = 0,
+ },
};
#define NUM_CTRLS ARRAY_SIZE(msm_vdec_ctrls)
@@ -1357,13 +1388,29 @@
}
break;
+ case V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE:
+ {
+ struct hal_buffer_alloc_mode mode;
+ property_id = HAL_PARAM_BUFFER_ALLOC_MODE;
+ mode.buffer_mode = ctrl->val;
+ mode.buffer_type = HAL_BUFFER_INPUT;
+ pdata = &mode;
+ break;
+ }
+ case V4L2_CID_MPEG_VIDC_VIDEO_FRAME_ASSEMBLY:
+ {
+ property_id = HAL_PARAM_VDEC_FRAME_ASSEMBLY;
+ hal_property.enable = ctrl->val;
+ pdata = &hal_property;
+ break;
+ }
default:
break;
}
if (!rc && property_id) {
dprintk(VIDC_DBG,
- "Control: HAL property = %d, ctrl_id = 0x%x, ctrl_value = %d\n",
+ "Control: HAL property=0x%x,ctrl: id=0x%x,value=0x%x\n",
property_id, ctrl->id, ctrl->val);
rc = call_hfi_op(hdev, session_set_property, (void *)
inst->session, property_id, pdata);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 77f838c..5f0ec4e 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -69,6 +69,20 @@
return false;
}
+static bool is_thumbnail_session(struct msm_vidc_inst *inst)
+{
+ if (inst->session_type == MSM_VIDC_DECODER) {
+ int rc = 0;
+ struct v4l2_control ctrl = {
+ .id = V4L2_CID_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE
+ };
+ rc = v4l2_g_ctrl(&inst->ctrl_handler, &ctrl);
+ if (!rc && ctrl.value)
+ return true;
+ }
+ return false;
+}
+
static int msm_comm_get_load(struct msm_vidc_core *core,
enum session_type type)
{
@@ -83,7 +97,9 @@
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,
+ if (!is_thumbnail_session(inst))
+ num_mbs_per_sec += NUM_MBS_PER_SEC(
+ inst->prop.height,
inst->prop.width, inst->prop.fps);
}
mutex_unlock(&inst->lock);
@@ -728,6 +744,15 @@
vb = response->clnt_data;
inst = (struct msm_vidc_inst *)response->session_id;
if (vb) {
+ vb->v4l2_planes[0].bytesused = response->input_done.filled_len;
+ vb->v4l2_planes[0].data_offset = response->input_done.offset;
+ if (vb->v4l2_planes[0].data_offset > vb->v4l2_planes[0].length)
+ dprintk(VIDC_ERR, "Error: data_offset overflow\n");
+ if (vb->v4l2_planes[0].bytesused > vb->v4l2_planes[0].length)
+ dprintk(VIDC_ERR, "Error: buffer overflow\n");
+ if ((u8 *)vb->v4l2_planes[0].m.userptr !=
+ response->input_done.packet_buffer)
+ dprintk(VIDC_ERR, "Error: unexpected buffer address\n");
mutex_lock(&inst->bufq[OUTPUT_PORT].lock);
vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
mutex_unlock(&inst->bufq[OUTPUT_PORT].lock);
@@ -1889,10 +1914,19 @@
memset(&frame_data, 0 , sizeof(struct vidc_frame_data));
frame_data.alloc_len = vb->v4l2_planes[0].length;
frame_data.filled_len = vb->v4l2_planes[0].bytesused;
+ frame_data.offset = vb->v4l2_planes[0].data_offset;
frame_data.device_addr = vb->v4l2_planes[0].m.userptr;
frame_data.timestamp = time_usec;
frame_data.flags = 0;
frame_data.clnt_data = (u32)vb;
+ if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
+ (frame_data.filled_len > frame_data.alloc_len ||
+ frame_data.offset > frame_data.alloc_len)) {
+ dprintk(VIDC_ERR,
+ "Buffer will overflow, not queueing it\n");
+ rc = -EINVAL;
+ goto err_bad_input;
+ }
if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
frame_data.buffer_type = HAL_BUFFER_INPUT;
if (vb->v4l2_buf.flags & V4L2_BUF_FLAG_EOS) {
@@ -1911,8 +1945,11 @@
V4L2_QCOM_BUF_TIMESTAMP_INVALID)
frame_data.timestamp = LLONG_MAX;
dprintk(VIDC_DBG,
- "Sending etb to hal: Alloc: %d :filled: %d\n",
- frame_data.alloc_len, frame_data.filled_len);
+ "Sending etb to hal: device_addr: 0x%x"
+ "Alloc: %d, filled: %d, offset: %d\n",
+ frame_data.device_addr,
+ frame_data.alloc_len, frame_data.filled_len,
+ frame_data.offset);
rc = call_hfi_op(hdev, session_etb, (void *)
inst->session, &frame_data);
if (!rc)
@@ -1965,6 +2002,7 @@
rc = -EINVAL;
}
}
+err_bad_input:
if (rc)
dprintk(VIDC_ERR, "Failed to queue buffer\n");
err_no_mem:
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 8ee9c32..47b88db 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -1423,6 +1423,10 @@
break;
case HAL_SYS_DEBUG_CONFIG:
break;
+ case HAL_PARAM_BUFFER_ALLOC_MODE:
+ break;
+ case HAL_PARAM_VDEC_FRAME_ASSEMBLY:
+ break;
/*FOLLOWING PROPERTIES ARE NOT IMPLEMENTED IN CORE YET*/
case HAL_CONFIG_BUFFER_REQUIREMENTS:
case HAL_CONFIG_PRIORITY:
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index 389c13f..288b386 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -172,6 +172,8 @@
HAL_PARAM_VENC_H264_VUI_TIMING_INFO,
HAL_PARAM_VENC_H264_GENERATE_AUDNAL,
HAL_PARAM_VENC_MAX_NUM_B_FRAMES,
+ HAL_PARAM_BUFFER_ALLOC_MODE,
+ HAL_PARAM_VDEC_FRAME_ASSEMBLY,
};
enum hal_domain {
@@ -860,6 +862,16 @@
HAL_UNUSED_SEQCHG = 0x10000000,
};
+enum buffer_mode_type {
+ HAL_BUFFER_MODE_STATIC = 0x00000000,
+ HAL_BUFFER_MODE_RING,
+};
+
+struct hal_buffer_alloc_mode {
+ enum hal_buffer buffer_type;
+ enum buffer_mode_type buffer_mode;
+};
+
/* HAL Response */
enum command_response {
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 2e9db1f..90d9826 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1579,9 +1579,7 @@
if (err)
goto out;
- if (mmc_can_poweroff_notify(host->card))
- err = mmc_poweroff_notify(host->card, EXT_CSD_POWER_OFF_SHORT);
- else if (mmc_card_can_sleep(host))
+ if (mmc_card_can_sleep(host))
err = mmc_card_sleep(host);
else if (!mmc_host_is_spi(host))
mmc_deselect_cards(host);
diff --git a/drivers/platform/msm/ipa/ipa_client.c b/drivers/platform/msm/ipa/ipa_client.c
index f20f37f..3aaec07 100644
--- a/drivers/platform/msm/ipa/ipa_client.c
+++ b/drivers/platform/msm/ipa/ipa_client.c
@@ -45,7 +45,7 @@
if (ipa_ctx->ipa_hw_type == IPA_HW_v1_1) {
ipa_write_reg(ipa_ctx->mmio,
IPA_ENDP_INIT_CTRL_n_OFST(clnt_hdl), 1);
- usleep(IPA_PKT_FLUSH_TO_US);
+ udelay(IPA_PKT_FLUSH_TO_US);
if (IPA_CLIENT_IS_CONS(ep->client) &&
ep->cfg.aggr.aggr_en == IPA_ENABLE_AGGR &&
ep->cfg.aggr.aggr_time_limit)
diff --git a/drivers/platform/msm/ipa/ipa_utils.c b/drivers/platform/msm/ipa/ipa_utils.c
index e38b796..4a5fa4d 100644
--- a/drivers/platform/msm/ipa/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_utils.c
@@ -1396,12 +1396,8 @@
if (__ratelimit(&_rs)) {
ipa_inc_client_enable_clks();
pr_err("IPA BAM START\n");
- sps_get_bam_debug_info(ipa_ctx->bam_handle, 5, 1048575, 0, 0);
+ sps_get_bam_debug_info(ipa_ctx->bam_handle, 5, 479182, 0, 0);
sps_get_bam_debug_info(ipa_ctx->bam_handle, 93, 0, 0, 0);
- pr_err("BAM-DMA BAM START\n");
- sps_get_bam_debug_info(sps_dma_get_bam_handle(), 5, 1044480,
- 0, 0);
- sps_get_bam_debug_info(sps_dma_get_bam_handle(), 93, 0, 0, 0);
ipa_dec_client_disable_clks();
}
}
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index 14d5b6a..08995cc 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -64,11 +64,10 @@
/* Extra bms registers */
#define SOC_STORAGE_REG 0xB0
#define IAVG_STORAGE_REG 0xB1
-#define BMS_BATT_REMOVED_REG 0xB2
-#define BMS1_BMS_DATA_REG_3 0xB3
-#define CHARGE_INCREASE_STORAGE 0xB4
-#define FCC_BATT_TEMP_STORAGE 0xB5
-#define FCC_STORAGE_LSB 0xBC /* LSB=0xBC, MSB=0xBD */
+#define BMS_FCC_COUNT 0xB2
+#define BMS_FCC_BASE_REG 0xB3 /* FCC updates - 0xB3 to 0xB7 */
+#define BMS_CHGCYL_BASE_REG 0xB8 /* FCC chgcyl - 0xB8 to 0xBC */
+#define CHARGE_INCREASE_STORAGE 0xBD
#define CHARGE_CYCLE_STORAGE_LSB 0xBE /* LSB=0xBE, MSB=0xBF */
/* IADC Channel Select */
@@ -84,8 +83,11 @@
#define IAVG_SAMPLES 16
/* FCC learning constants */
+#define MAX_FCC_CYCLES 5
#define DELTA_FCC_PERCENT 5
#define VALID_FCC_CHGCYL_RANGE 50
+#define CHGCYL_RESOLUTION 20
+#define FCC_DEFAULT_TEMP 250
#define QPNP_BMS_DEV_NAME "qcom,qpnp-bms"
@@ -116,9 +118,8 @@
int last_good_ocv_uv;
};
-struct fcc_data {
+struct fcc_sample {
int fcc_new;
- int batt_temp;
int chargecycles;
};
@@ -244,7 +245,8 @@
int ocv_low_threshold_uv;
unsigned long last_recalc_time;
- struct fcc_data *fcc_table;
+ struct fcc_sample *fcc_learning_samples;
+ u8 fcc_sample_count;
int enable_fcc_learning;
int min_fcc_learning_soc;
int min_fcc_ocv_pc;
@@ -259,8 +261,8 @@
int fcc_new_batt_temp;
uint16_t charge_cycles;
u8 charge_increase;
- int fcc_new_sysfs;
- int fcc_update_complete;
+ int fcc_resolution;
+ bool battery_removed;
struct bms_irq sw_cc_thr_irq;
struct bms_irq ocv_thr_irq;
};
@@ -285,45 +287,10 @@
POWER_SUPPLY_PROP_CYCLE_COUNT,
};
+static int discard_backup_fcc_data(struct qpnp_bms_chip *chip);
+static void backup_charge_cycle(struct qpnp_bms_chip *chip);
+
static bool bms_reset;
-static int min_fcc_cycles = -EINVAL;
-static int last_fcc_update_count;
-static int battery_removed;
-
-static int
-bms_ro_ops_set(const char *val, const struct kernel_param *kp)
-{
- return -EINVAL;
-}
-
-static int
-bms_last_fcc_count_set(const char *val, const struct kernel_param *kp)
-{
- int rc;
-
- if (battery_removed) {
- last_fcc_update_count = 0;
- return 0;
- }
- rc = param_set_int(val, kp);
- if (rc)
- pr_err("Failed to set last_fcc_update_count rc=%d\n", rc);
-
- return rc;
-}
-
-static struct kernel_param_ops bms_ro_param_ops = {
- .set = bms_ro_ops_set,
- .get = param_get_int,
-};
-static struct kernel_param_ops bms_last_fcc_count_param_ops = {
- .set = bms_last_fcc_count_set,
- .get = param_get_int,
-};
-module_param_cb(min_fcc_cycles, &bms_ro_param_ops, &min_fcc_cycles, 0644);
-module_param_cb(battery_removed, &bms_ro_param_ops, &battery_removed, 0644);
-module_param_cb(last_fcc_update_count, &bms_last_fcc_count_param_ops,
- &last_fcc_update_count, 0644);
static int qpnp_read_wrapper(struct qpnp_bms_chip *chip, u8 *val,
u16 base, int count)
@@ -871,6 +838,19 @@
chip->last_cc_uah = INT_MIN;
chip->last_ocv_temp = batt_temp;
chip->prev_batt_terminal_uv = 0;
+ if (chip->enable_fcc_learning) {
+ chip->adjusted_fcc_temp_lut = NULL;
+ chip->fcc_new_mah = -EINVAL;
+ /* reset the charge-cycle and charge-increase registers */
+ chip->charge_increase = 0;
+ chip->charge_cycles = 0;
+ backup_charge_cycle(chip);
+ /* discard all the FCC learnt data and reset the local table */
+ discard_backup_fcc_data(chip);
+ memset(chip->fcc_learning_samples, 0,
+ chip->min_fcc_learning_samples *
+ sizeof(struct fcc_sample));
+ }
}
#define OCV_RAW_UNINITIALIZED 0xFFFF
@@ -2624,26 +2604,85 @@
kfree(old);
}
-
-static void backup_fcc_new(struct qpnp_bms_chip *chip)
+static int read_fcc_data_from_backup(struct qpnp_bms_chip *chip)
{
- int rc = 0;
- u8 temp = 0;
+ int rc, i;
+ u8 fcc = 0, chgcyl = 0;
- if (chip->fcc_new_mah > 0) {
- rc = qpnp_write_wrapper(chip, (u8 *)&chip->fcc_new_mah,
- chip->base + FCC_STORAGE_LSB, 2);
- if (rc)
- pr_err("Unable to backup new_fcc\n");
-
- temp = chip->fcc_new_batt_temp / 10;
- rc = qpnp_write_wrapper(chip, &temp,
- chip->base + FCC_BATT_TEMP_STORAGE, 1);
- if (rc)
- pr_err("Unable to backup fcc temp.\n");
+ for (i = 0; i < chip->min_fcc_learning_samples; i++) {
+ rc = qpnp_read_wrapper(chip, &fcc,
+ chip->base + BMS_FCC_BASE_REG + i, 1);
+ rc |= qpnp_read_wrapper(chip, &chgcyl,
+ chip->base + BMS_CHGCYL_BASE_REG + i, 1);
+ if (rc) {
+ pr_err("Unable to read FCC data\n");
+ return rc;
+ }
+ if (fcc == 0 || (fcc == 0xFF && chgcyl == 0xFF)) {
+ /* FCC invalid/not present */
+ chip->fcc_learning_samples[i].fcc_new = 0;
+ chip->fcc_learning_samples[i].chargecycles = 0;
+ } else {
+ /* valid FCC data */
+ chip->fcc_sample_count++;
+ chip->fcc_learning_samples[i].fcc_new =
+ fcc * chip->fcc_resolution;
+ chip->fcc_learning_samples[i].chargecycles =
+ chgcyl * CHGCYL_RESOLUTION;
+ }
}
+
+ return 0;
}
+static int discard_backup_fcc_data(struct qpnp_bms_chip *chip)
+{
+ int rc = 0, i;
+ u8 temp_u8 = 0;
+
+ chip->fcc_sample_count = 0;
+ for (i = 0; i < chip->min_fcc_learning_samples; i++) {
+ rc = qpnp_write_wrapper(chip, &temp_u8,
+ chip->base + BMS_FCC_BASE_REG + i, 1);
+ rc |= qpnp_write_wrapper(chip, &temp_u8,
+ chip->base + BMS_CHGCYL_BASE_REG + i, 1);
+ if (rc) {
+ pr_err("Unable to clear FCC data\n");
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+static void
+average_fcc_samples_and_readjust_fcc_table(struct qpnp_bms_chip *chip)
+{
+ int i, temp_fcc_avg = 0, temp_fcc_delta = 0, new_fcc_avg = 0;
+ struct fcc_sample *ft;
+
+ for (i = 0; i < chip->min_fcc_learning_samples; i++)
+ temp_fcc_avg += chip->fcc_learning_samples[i].fcc_new;
+
+ temp_fcc_avg /= chip->min_fcc_learning_samples;
+ temp_fcc_delta = div_u64(temp_fcc_avg * DELTA_FCC_PERCENT, 100);
+
+ /* fix the fcc if its an outlier i.e. > 5% of the average */
+ for (i = 0; i < chip->min_fcc_learning_samples; i++) {
+ ft = &chip->fcc_learning_samples[i];
+ if (abs(ft->fcc_new - temp_fcc_avg) > temp_fcc_delta)
+ new_fcc_avg += temp_fcc_avg;
+ else
+ new_fcc_avg += ft->fcc_new;
+ }
+ new_fcc_avg /= chip->min_fcc_learning_samples;
+
+ chip->fcc_new_mah = new_fcc_avg;
+ chip->fcc_new_batt_temp = FCC_DEFAULT_TEMP;
+ pr_info("FCC update: New fcc_mah=%d, fcc_batt_temp=%d\n",
+ new_fcc_avg, FCC_DEFAULT_TEMP);
+ readjust_fcc_table(chip);
+}
static void backup_charge_cycle(struct qpnp_bms_chip *chip)
{
@@ -2651,7 +2690,7 @@
if (chip->charge_increase >= 0) {
rc = qpnp_write_wrapper(chip, &chip->charge_increase,
- chip->base + CHARGE_INCREASE_STORAGE, 1);
+ chip->base + CHARGE_INCREASE_STORAGE, 1);
if (rc)
pr_err("Unable to backup charge_increase\n");
}
@@ -2664,9 +2703,31 @@
}
}
-static void restore_fcc_data(struct qpnp_bms_chip *chip)
+static bool chargecycles_in_range(struct qpnp_bms_chip *chip)
{
- int rc = 0;
+ int i, min_cycle, max_cycle, valid_range;
+
+ /* find the smallest and largest charge cycle */
+ max_cycle = min_cycle = chip->fcc_learning_samples[0].chargecycles;
+ for (i = 1; i < chip->min_fcc_learning_samples; i++) {
+ if (min_cycle > chip->fcc_learning_samples[i].chargecycles)
+ min_cycle = chip->fcc_learning_samples[i].chargecycles;
+ if (max_cycle < chip->fcc_learning_samples[i].chargecycles)
+ max_cycle = chip->fcc_learning_samples[i].chargecycles;
+ }
+
+ /* check if chargecyles are in range to continue with FCC update */
+ valid_range = DIV_ROUND_UP(VALID_FCC_CHGCYL_RANGE,
+ CHGCYL_RESOLUTION) * CHGCYL_RESOLUTION;
+ if (abs(max_cycle - min_cycle) > valid_range)
+ return false;
+
+ return true;
+}
+
+static int read_chgcycle_data_from_backup(struct qpnp_bms_chip *chip)
+{
+ int rc;
uint16_t temp_u16 = 0;
u8 temp_u8 = 0;
@@ -2680,25 +2741,18 @@
if (!rc && temp_u16 != 0xFFFF)
chip->charge_cycles = temp_u16;
- rc = qpnp_read_wrapper(chip, (u8 *)&temp_u16,
- chip->base + FCC_STORAGE_LSB, 2);
- if (!rc && temp_u16 != 0xFFFF) {
- chip->fcc_new_mah = temp_u16;
- } else {
- pr_debug("Backed-up FCC not initialized, FCC not updated\n");
- return;
- }
+ return rc;
+}
- rc = qpnp_read_wrapper(chip, &temp_u8,
- chip->base + FCC_BATT_TEMP_STORAGE, 1);
- if (!rc && temp_u8 != 0xFF) {
- chip->fcc_new_batt_temp = (s8)temp_u8 * 10;
- } else {
- pr_debug("Backed-up temp. not initialized, FCC not updated\n");
- return;
- }
- /* readjust the FCC table if fcc and temp are valid */
- readjust_fcc_table(chip);
+static void
+attempt_learning_new_fcc(struct qpnp_bms_chip *chip)
+{
+ pr_debug("Total FCC sample count=%d\n", chip->fcc_sample_count);
+
+ /* update FCC if we have the required samples */
+ if ((chip->fcc_sample_count == chip->min_fcc_learning_samples) &&
+ chargecycles_in_range(chip))
+ average_fcc_samples_and_readjust_fcc_table(chip);
}
static int calculate_real_soc(struct qpnp_bms_chip *chip,
@@ -2712,82 +2766,80 @@
return ((rc_uah - cc_uah) * 100) / fcc_uah;
}
-static void update_fcc_table_for_temp(struct qpnp_bms_chip *chip,
- int batt_temp_final)
-{
- int i, fcc_t1, fcc_t2, fcc_final;
- struct fcc_data *ft;
+#define MAX_U8_VALUE ((u8)(~0U))
- /* Interpolate all the FCC entries to the same temperature */
- for (i = 0; i < chip->min_fcc_learning_samples; i++) {
- ft = &chip->fcc_table[i];
- if (ft->batt_temp == batt_temp_final)
- continue;
- fcc_t1 = interpolate_fcc(chip->fcc_temp_lut, ft->batt_temp);
- fcc_t2 = interpolate_fcc(chip->fcc_temp_lut, batt_temp_final);
- fcc_final = (ft->fcc_new / fcc_t1) * fcc_t2;
- ft->fcc_new = fcc_final;
- ft->batt_temp = batt_temp_final;
+static int backup_new_fcc(struct qpnp_bms_chip *chip, int fcc_mah,
+ int chargecycles)
+{
+ int rc, min_cycle, i;
+ u8 fcc_new, chgcyl, pos = 0;
+ struct fcc_sample *ft;
+
+ if ((fcc_mah > (chip->fcc_resolution * MAX_U8_VALUE)) ||
+ (chargecycles > (CHGCYL_RESOLUTION * MAX_U8_VALUE))) {
+ pr_warn("FCC/Chgcyl beyond storage limit. FCC=%d, chgcyl=%d\n",
+ fcc_mah, chargecycles);
+ return -EINVAL;
}
+
+ if (chip->fcc_sample_count == chip->min_fcc_learning_samples) {
+ /* search best location - oldest entry */
+ min_cycle = chip->fcc_learning_samples[0].chargecycles;
+ for (i = 1; i < chip->min_fcc_learning_samples; i++) {
+ if (min_cycle >
+ chip->fcc_learning_samples[i].chargecycles)
+ pos = i;
+ }
+ } else {
+ /* find an empty location */
+ for (i = 0; i < chip->min_fcc_learning_samples; i++) {
+ ft = &chip->fcc_learning_samples[i];
+ if (ft->fcc_new == 0 || (ft->fcc_new == 0xFF &&
+ ft->chargecycles == 0xFF)) {
+ pos = i;
+ break;
+ }
+ }
+ chip->fcc_sample_count++;
+ }
+ chip->fcc_learning_samples[pos].fcc_new = fcc_mah;
+ chip->fcc_learning_samples[pos].chargecycles = chargecycles;
+
+ fcc_new = DIV_ROUND_UP(fcc_mah, chip->fcc_resolution);
+ rc = qpnp_write_wrapper(chip, (u8 *)&fcc_new,
+ chip->base + BMS_FCC_BASE_REG + pos, 1);
+ if (rc)
+ return rc;
+
+ chgcyl = DIV_ROUND_UP(chargecycles, CHGCYL_RESOLUTION);
+ rc = qpnp_write_wrapper(chip, (u8 *)&chgcyl,
+ chip->base + BMS_CHGCYL_BASE_REG + pos, 1);
+ if (rc)
+ return rc;
+
+ pr_debug("Backup new FCC: fcc_new=%d, chargecycle=%d, pos=%d\n",
+ fcc_new, chgcyl, pos);
+
+ return rc;
}
static void update_fcc_learning_table(struct qpnp_bms_chip *chip,
- int fcc_uah, int new_fcc_uah, int chargecycles, int batt_temp)
+ int new_fcc_uah, int chargecycles, int batt_temp)
{
- int i, count, new_fcc_avg = 0, temp_fcc_avg = 0, temp_fcc_delta = 0;
- struct fcc_data *ft;
+ int rc, fcc_default, fcc_temp;
- count = last_fcc_update_count % chip->min_fcc_learning_samples;
- ft = &chip->fcc_table[count];
- ft->fcc_new = chip->fcc_new_sysfs = new_fcc_uah;
- ft->batt_temp = batt_temp;
- ft->chargecycles = chargecycles;
- last_fcc_update_count++;
- /* update userspace */
- sysfs_notify(&chip->dev->kobj, NULL, "fcc_data");
+ /* convert the fcc at batt_temp to new fcc at FCC_DEFAULT_TEMP */
+ fcc_default = calculate_fcc(chip, FCC_DEFAULT_TEMP) / 1000;
+ fcc_temp = calculate_fcc(chip, batt_temp) / 1000;
+ new_fcc_uah = (new_fcc_uah / fcc_temp) * fcc_default;
- pr_debug("Updated fcc table. new_fcc=%d, chargecycle=%d, temp=%d fcc_update_count=%d\n",
- new_fcc_uah, chargecycles, batt_temp, last_fcc_update_count);
-
- if (last_fcc_update_count < chip->min_fcc_learning_samples) {
- pr_debug("Not enough FCC samples. Current count = %d\n",
- last_fcc_update_count);
- return; /* Not enough samples to update fcc */
+ rc = backup_new_fcc(chip, new_fcc_uah / 1000, chargecycles);
+ if (rc) {
+ pr_err("Unable to backup new FCC\n");
+ return;
}
-
- /* reject entries if they are > 50 chargecycles apart */
- for (i = 0; i < chip->min_fcc_learning_samples; i++) {
- if ((chip->fcc_table[i].chargecycles + VALID_FCC_CHGCYL_RANGE)
- < chargecycles) {
- pr_debug("Charge cycle too old (> %d cycles apart)\n",
- VALID_FCC_CHGCYL_RANGE);
- return; /* Samples old, > 50 cycles apart*/
- }
- }
- /* update the fcc table for temperature difference*/
- update_fcc_table_for_temp(chip, batt_temp);
-
- for (i = 0; i < chip->min_fcc_learning_samples; i++)
- temp_fcc_avg += chip->fcc_table[i].fcc_new;
-
- temp_fcc_avg /= chip->min_fcc_learning_samples;
- temp_fcc_delta = div_u64(temp_fcc_avg * DELTA_FCC_PERCENT, 100);
-
- /* fix the fcc if its an outlier i.e. > 5% of the average */
- for (i = 0; i < chip->min_fcc_learning_samples; i++) {
- ft = &chip->fcc_table[i];
- if (abs(ft->fcc_new - temp_fcc_avg) > temp_fcc_delta)
- ft->fcc_new = temp_fcc_avg;
- new_fcc_avg += ft->fcc_new;
- }
- new_fcc_avg /= chip->min_fcc_learning_samples;
-
- chip->fcc_new_mah = new_fcc_avg / 1000;
- chip->fcc_new_batt_temp = batt_temp;
- pr_info("FCC update: New fcc_mah=%d, fcc_batt_temp=%d\n",
- new_fcc_avg, batt_temp);
- readjust_fcc_table(chip);
- backup_fcc_new(chip);
+ /* check if FCC can be updated */
+ attempt_learning_new_fcc(chip);
}
static bool is_new_fcc_valid(int new_fcc_uah, int fcc_uah)
@@ -2841,8 +2893,8 @@
chip->start_cc_uah, chip->end_cc_uah, new_fcc_uah);
if (is_new_fcc_valid(new_fcc_uah, fcc_uah))
- update_fcc_learning_table(chip, fcc_uah,
- new_fcc_uah, chip->charge_cycles, batt_temp);
+ update_fcc_learning_table(chip, new_fcc_uah,
+ chip->charge_cycles, batt_temp);
}
}
@@ -3013,123 +3065,6 @@
return 0;
}
-static ssize_t fcc_data_set(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct qpnp_bms_chip *chip = dev_get_drvdata(dev);
- static int i;
- int fcc_new = 0, rc;
-
- if (chip->fcc_update_complete) {
- pr_debug("Invalid FCC update\n");
- return count;
- }
-
- i %= chip->min_fcc_learning_samples;
- rc = sscanf(buf, "%d", &fcc_new);
- if (rc != 1)
- return -EINVAL;
- chip->fcc_table[i].fcc_new = fcc_new;
- pr_debug("Rcvd: [%d] fcc_new=%d\n", i, fcc_new);
- i++;
-
- return count;
-}
-
-static ssize_t fcc_data_get(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- int count = 0;
- struct qpnp_bms_chip *chip = dev_get_drvdata(dev);
-
- count = snprintf(buf, PAGE_SIZE, "%d", chip->fcc_new_sysfs);
- pr_debug("Sent: fcc_new=%d\n", chip->fcc_new_sysfs);
- chip->fcc_update_complete = 1;
-
- return count;
-}
-
-static ssize_t fcc_temp_set(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- static int i;
- int batt_temp = 0, rc;
- struct qpnp_bms_chip *chip = dev_get_drvdata(dev);
-
- if (chip->fcc_update_complete)
- return count;
-
- i %= chip->min_fcc_learning_samples;
- rc = sscanf(buf, "%d", &batt_temp);
- if (rc != 1)
- return -EINVAL;
- chip->fcc_table[i].batt_temp = batt_temp;
- pr_debug("Rcvd: [%d] batt_temp=%d\n", i, batt_temp);
- i++;
-
- return count;
-}
-
-static ssize_t fcc_chgcyl_set(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- static int i;
- int chargecycle = 0, rc;
- struct qpnp_bms_chip *chip = dev_get_drvdata(dev);
-
- if (chip->fcc_update_complete)
- return count;
-
- i %= chip->min_fcc_learning_samples;
- rc = sscanf(buf, "%d", &chargecycle);
- if (rc != 1)
- return -EINVAL;
- chip->fcc_table[i].chargecycles = chargecycle;
- pr_debug("Rcvd: [%d] chargecycle=%d\n", i, chargecycle);
- i++;
-
- return count;
-}
-
-static ssize_t fcc_list_get(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct qpnp_bms_chip *chip = dev_get_drvdata(dev);
- struct fcc_data *ft;
- int i = 0, j, count = 0;
-
- if (last_fcc_update_count < chip->min_fcc_learning_samples)
- i = last_fcc_update_count;
- else
- i = chip->min_fcc_learning_samples;
-
- for (j = 0; j < i; j++) {
- ft = &chip->fcc_table[j];
- count += snprintf(buf + count, PAGE_SIZE - count,
- "%d %d %d\n", ft->fcc_new, ft->chargecycles,
- ft->batt_temp);
- }
-
- return count;
-}
-
-static DEVICE_ATTR(fcc_data, 0664, fcc_data_get, fcc_data_set);
-static DEVICE_ATTR(fcc_temp, 0664, NULL, fcc_temp_set);
-static DEVICE_ATTR(fcc_chgcyl, 0664, NULL, fcc_chgcyl_set);
-static DEVICE_ATTR(fcc_list, 0664, fcc_list_get, NULL);
-
-static struct attribute *fcc_attrs[] = {
- &dev_attr_fcc_data.attr,
- &dev_attr_fcc_temp.attr,
- &dev_attr_fcc_chgcyl.attr,
- &dev_attr_fcc_list.attr,
- NULL
-};
-
-static const struct attribute_group fcc_attr_group = {
- .attrs = fcc_attrs,
-};
-
#define OCV_USE_LIMIT_EN BIT(7)
static int set_ocv_voltage_thresholds(struct qpnp_bms_chip *chip,
int low_voltage_threshold,
@@ -3213,10 +3148,19 @@
}
}
- pr_debug("shutdown_soc = %d shutdown_iavg = %d shutdown_soc_invalid = %d\n",
+ /* read the SOC storage to determine if there was a battery removal */
+ rc = qpnp_read_wrapper(chip, &temp, chip->base + SOC_STORAGE_REG, 1);
+ if (!rc) {
+ if (temp == SOC_INVALID)
+ chip->battery_removed = true;
+ }
+
+
+ pr_debug("shutdown_soc = %d shutdown_iavg = %d shutdown_soc_invalid = %d, battery_removed = %d\n",
chip->shutdown_soc,
chip->shutdown_iavg_ma,
- chip->shutdown_soc_invalid);
+ chip->shutdown_soc_invalid,
+ chip->battery_removed);
}
static irqreturn_t bms_ocv_thr_irq_handler(int irq, void *_chip)
@@ -3325,6 +3269,12 @@
} \
} while (0)
+#define SPMI_PROP_READ_BOOL(chip_prop, qpnp_spmi_property) \
+do { \
+ chip->chip_prop = of_property_read_bool(chip->spmi->dev.of_node,\
+ "qcom," qpnp_spmi_property); \
+} while (0)
+
static inline int bms_read_properties(struct qpnp_bms_chip *chip)
{
int rc;
@@ -3371,8 +3321,7 @@
if (chip->adjust_soc_low_threshold >= 45)
chip->adjust_soc_low_threshold = 45;
- chip->enable_fcc_learning = of_property_read_bool(
- chip->spmi->dev.of_node, "qcom,enable-fcc-learning");
+ SPMI_PROP_READ_BOOL(enable_fcc_learning, "enable-fcc-learning");
if (chip->enable_fcc_learning) {
SPMI_PROP_READ(min_fcc_learning_soc,
"min-fcc-learning-soc", rc);
@@ -3380,12 +3329,16 @@
"min-fcc-ocv-pc", rc);
SPMI_PROP_READ(min_fcc_learning_samples,
"min-fcc-learning-samples", rc);
- chip->fcc_table = kzalloc((sizeof(struct fcc_data) *
- chip->min_fcc_learning_samples), GFP_KERNEL);
+ SPMI_PROP_READ(fcc_resolution,
+ "fcc-resolution", rc);
+ if (chip->min_fcc_learning_samples > MAX_FCC_CYCLES)
+ chip->min_fcc_learning_samples = MAX_FCC_CYCLES;
+ chip->fcc_learning_samples = devm_kzalloc(&chip->spmi->dev,
+ (sizeof(struct fcc_sample) *
+ chip->min_fcc_learning_samples), GFP_KERNEL);
pr_debug("min-fcc-soc=%d, min-fcc-pc=%d, min-fcc-cycles=%d\n",
chip->min_fcc_learning_soc, chip->min_fcc_ocv_pc,
chip->min_fcc_learning_samples);
- min_fcc_cycles = chip->min_fcc_learning_samples;
}
pr_debug("dts data: r_sense_uohm:%d, v_cutoff_uv:%d, max_v:%d\n",
@@ -3662,28 +3615,6 @@
return 0;
}
-static void check_battery_removal(struct qpnp_bms_chip *chip)
-{
- int rc;
- u8 temp = 0;
-
- /* check if battery was removed at PON */
- rc = qpnp_read_wrapper(chip, &temp,
- chip->base + BMS_BATT_REMOVED_REG, 1);
- if (temp == 0xFF) {
- pr_debug("New battery inserted at PON\n");
- temp = battery_removed = 1;
- rc = qpnp_write_wrapper(chip, &temp,
- chip->base + BMS_BATT_REMOVED_REG, 1);
- if (rc)
- pr_err("Unable to set BMS_BATT_REMOVED_REG\n");
- } else {
- if (rc)
- pr_err("Unable to read BMS_BATT_REMOVED_REG\n");
- battery_removed = 0;
- }
-}
-
static int __devinit qpnp_bms_probe(struct spmi_device *spmi)
{
struct qpnp_bms_chip *chip;
@@ -3711,6 +3642,12 @@
goto error_read;
}
+ mutex_init(&chip->bms_output_lock);
+ mutex_init(&chip->last_ocv_uv_mutex);
+ mutex_init(&chip->vbat_monitor_mutex);
+ mutex_init(&chip->soc_invalidation_mutex);
+ mutex_init(&chip->last_soc_mutex);
+
warm_reset = qpnp_pon_is_warm_reset();
rc = warm_reset;
if (rc < 0)
@@ -3768,12 +3705,6 @@
bms_initialize_constants(chip);
- mutex_init(&chip->bms_output_lock);
- mutex_init(&chip->last_ocv_uv_mutex);
- mutex_init(&chip->vbat_monitor_mutex);
- mutex_init(&chip->soc_invalidation_mutex);
- mutex_init(&chip->last_soc_mutex);
-
wakeup_source_init(&chip->soc_wake_source.source, "qpnp_soc_wake");
wake_lock_init(&chip->low_voltage_wake_lock, WAKE_LOCK_SUSPEND,
"qpnp_low_voltage_lock");
@@ -3786,20 +3717,26 @@
read_shutdown_soc_and_iavg(chip);
if (chip->enable_fcc_learning) {
- restore_fcc_data(chip);
- rc = sysfs_create_group(&spmi->dev.kobj, &fcc_attr_group);
- if (rc) {
- pr_err("Unable to create sysfs entries\n");
- goto error_setup;
+ if (chip->battery_removed) {
+ rc = discard_backup_fcc_data(chip);
+ if (rc)
+ pr_err("Could not discard backed-up FCC data\n");
+ } else {
+ rc = read_chgcycle_data_from_backup(chip);
+ if (rc)
+ pr_err("Unable to restore charge-cycle data\n");
+
+ rc = read_fcc_data_from_backup(chip);
+ if (rc)
+ pr_err("Unable to restore FCC-learning data\n");
+ else
+ attempt_learning_new_fcc(chip);
}
}
dev_set_drvdata(&spmi->dev, chip);
device_init_wakeup(&spmi->dev, 1);
- check_battery_removal(chip);
-
-
rc = setup_vbat_monitoring(chip);
if (rc < 0) {
pr_err("failed to set up voltage notifications: %d\n", rc);
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 23941a9..3679aa9 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -1143,7 +1143,7 @@
val->intval = qpnp_chg_is_dc_chg_plugged_in(chip);
break;
case POWER_SUPPLY_PROP_CURRENT_MAX:
- val->intval = chip->maxinput_dc_ma;
+ val->intval = chip->maxinput_dc_ma * 1000;
break;
default:
return -EINVAL;
@@ -2767,13 +2767,6 @@
chip->duty_cycle_100p = of_property_read_bool(
chip->spmi->dev.of_node,
"qcom,duty-cycle-100p");
- if (chip->duty_cycle_100p) {
- rc = qpnp_buck_set_100_duty_cycle_enable(chip, 1);
- if (rc) {
- pr_err("failed to enable duty cycle %d\n", rc);
- return rc;
- }
- }
/* Get the fake-batt-values property */
chip->use_default_batt_values =
@@ -2939,6 +2932,16 @@
0xFF,
0x80, 1);
+ if (chip->duty_cycle_100p) {
+ rc = qpnp_buck_set_100_duty_cycle_enable(chip,
+ 1);
+ if (rc) {
+ pr_err("failed to set duty cycle %d\n",
+ rc);
+ goto fail_chg_enable;
+ }
+ }
+
break;
case SMBB_BAT_IF_SUBTYPE:
case SMBBP_BAT_IF_SUBTYPE:
diff --git a/drivers/spmi/qpnp-int.c b/drivers/spmi/qpnp-int.c
index 082c9ff..eedb1e5 100644
--- a/drivers/spmi/qpnp-int.c
+++ b/drivers/spmi/qpnp-int.c
@@ -578,11 +578,14 @@
unsigned long hwirq, busno;
int irq;
+ if (!spec || !spmi_ctrl)
+ return -EINVAL;
+
pr_debug("spec slave = %u per = %u irq = %u\n",
spec->slave, spec->per, spec->irq);
busno = spmi_ctrl->nr;
- if (!spec || !spmi_ctrl || busno >= QPNPINT_MAX_BUSSES)
+ if (busno >= QPNPINT_MAX_BUSSES)
return -EINVAL;
hwirq = qpnpint_encode_hwirq(spec);
diff --git a/drivers/thermal/msm8974-tsens.c b/drivers/thermal/msm8974-tsens.c
index 52608af..6933163 100644
--- a/drivers/thermal/msm8974-tsens.c
+++ b/drivers/thermal/msm8974-tsens.c
@@ -77,6 +77,9 @@
#define TSENS_EEPROM_8X10_1(n) ((n) + 0x1a4)
#define TSENS_EEPROM_8X10_1_OFFSET 8
+#define TSENS_EEPROM_8X10_2(n) ((n) + 0x1a8)
+#define TSENS_EEPROM_8X10_SPARE_1(n) ((n) + 0xd8)
+#define TSENS_EEPROM_8X10_SPARE_2(n) ((n) + 0xdc)
/* TSENS calibration Mask data */
#define TSENS_BASE1_MASK 0xff
@@ -207,6 +210,8 @@
#define TSENS_8X10_TSENS_CAL_SEL 0x70000000
#define TSENS1_8X10_POINT1_MASK 0x3f
#define TSENS1_8X10_POINT2_MASK 0xfc0
+#define TSENS_8X10_REDUN_SEL_MASK 0x6000000
+#define TSENS_8X10_REDUN_SEL_SHIFT 25
#define TSENS_BIT_APPEND 0x3
#define TSENS_CAL_DEGC_POINT1 30
@@ -559,6 +564,9 @@
unsigned int reg_cntl;
int code, hi_code, lo_code, code_err_chk, sensor_sw_id = 0, rc = 0;
+ if (!tm_sensor || trip < 0 || !temp)
+ return -EINVAL;
+
rc = tsens_get_sw_id_mapping(tm_sensor->sensor_hw_num, &sensor_sw_id);
if (rc < 0) {
pr_err("tsens mapping index not found\n");
@@ -721,17 +729,30 @@
int i, tsens_base0_data = 0, tsens0_point1 = 0, tsens1_point1 = 0;
int tsens0_point2 = 0, tsens1_point2 = 0;
int tsens_base1_data = 0, tsens_calibration_mode = 0;
- uint32_t calib_data[2];
+ uint32_t calib_data[2], calib_redun_sel;
uint32_t calib_tsens_point1_data[2], calib_tsens_point2_data[2];
if (tmdev->calibration_less_mode)
goto calibration_less_mode;
- calib_data[0] = readl_relaxed(
+ calib_redun_sel = readl_relaxed(
+ TSENS_EEPROM_8X10_2(tmdev->tsens_calib_addr));
+ calib_redun_sel = calib_redun_sel & TSENS_8X10_REDUN_SEL_MASK;
+ calib_redun_sel >>= TSENS_8X10_REDUN_SEL_SHIFT;
+ pr_debug("calib_redun_sel:%x\n", calib_redun_sel);
+
+ if (calib_redun_sel == TSENS_QFPROM_BACKUP_SEL) {
+ calib_data[0] = readl_relaxed(
+ TSENS_EEPROM_8X10_SPARE_1(tmdev->tsens_calib_addr));
+ calib_data[1] = readl_relaxed(
+ TSENS_EEPROM_8X10_SPARE_2(tmdev->tsens_calib_addr));
+ } else {
+ calib_data[0] = readl_relaxed(
TSENS_EEPROM_8X10_1(tmdev->tsens_calib_addr));
- calib_data[1] = readl_relaxed(
- (TSENS_EEPROM_8X10_1(tmdev->tsens_calib_addr) +
+ calib_data[1] = readl_relaxed(
+ (TSENS_EEPROM_8X10_1(tmdev->tsens_calib_addr) +
TSENS_EEPROM_8X10_1_OFFSET));
+ }
tsens_calibration_mode = (calib_data[0] & TSENS_8X10_TSENS_CAL_SEL)
>> TSENS_8X10_CAL_SEL_SHIFT;
@@ -1325,7 +1346,7 @@
static int get_device_tree_data(struct platform_device *pdev)
{
- const struct device_node *of_node = pdev->dev.of_node;
+ struct device_node *of_node = pdev->dev.of_node;
struct resource *res_mem = NULL;
u32 *tsens_slope_data;
u32 *sensor_id;
@@ -1353,8 +1374,13 @@
return rc;
};
- tsens_calib_mode = of_get_property(of_node,
- "qcom,calib-mode", NULL);
+ rc = of_property_read_string(of_node,
+ "qcom,calib-mode", &tsens_calib_mode);
+ if (rc) {
+ dev_err(&pdev->dev, "missing calib-mode\n");
+ return -ENODEV;
+ }
+
if (!strncmp(tsens_calib_mode, "fuse_map1", 9))
calib_type = TSENS_CALIB_FUSE_MAP_8974;
else if (!strncmp(tsens_calib_mode, "fuse_map2", 9))
diff --git a/drivers/tty/n_smux.c b/drivers/tty/n_smux.c
index 3794aa9..c8e5163 100644
--- a/drivers/tty/n_smux.c
+++ b/drivers/tty/n_smux.c
@@ -297,6 +297,8 @@
[SMUX_HIGH_WM_HIT] = "HIGH_WM_HIT",
[SMUX_RX_RETRY_HIGH_WM_HIT] = "RX_RETRY_HIGH_WM_HIT",
[SMUX_RX_RETRY_LOW_WM_HIT] = "RX_RETRY_LOW_WM_HIT",
+ [SMUX_LOCAL_CLOSED] = "LOCAL_CLOSED",
+ [SMUX_REMOTE_CLOSED] = "REMOTE_CLOSED",
};
static const char * const smux_local_state[] = {
@@ -553,6 +555,8 @@
/* Close all ports */
for (i = 0 ; i < SMUX_NUM_LOGICAL_CHANNELS; i++) {
+ union notifier_metadata meta;
+ int send_disconnect = 0;
ch = &smux_lch[i];
SMUX_DBG("smux: %s: cleaning up lcid %d\n", __func__, i);
@@ -563,14 +567,19 @@
smux_purge_ch_tx_queue(ch, 1);
spin_unlock(&ch->tx_lock_lhb2);
+ meta.disconnected.is_ssr = smux.in_reset;
/* Notify user of disconnect and reset channel state */
if (ch->local_state == SMUX_LCH_LOCAL_OPENED ||
ch->local_state == SMUX_LCH_LOCAL_CLOSING) {
- union notifier_metadata meta;
-
- meta.disconnected.is_ssr = smux.in_reset;
- schedule_notify(ch->lcid, SMUX_DISCONNECTED, &meta);
+ schedule_notify(ch->lcid, SMUX_LOCAL_CLOSED, &meta);
+ send_disconnect = 1;
}
+ if (ch->remote_state != SMUX_LCH_REMOTE_CLOSED) {
+ schedule_notify(ch->lcid, SMUX_REMOTE_CLOSED, &meta);
+ send_disconnect = 1;
+ }
+ if (send_disconnect)
+ schedule_notify(ch->lcid, SMUX_DISCONNECTED, &meta);
ch->local_state = SMUX_LCH_LOCAL_CLOSED;
ch->remote_state = SMUX_LCH_REMOTE_CLOSED;
@@ -857,6 +866,10 @@
IPC_LOG_STR("smux: %s ch:%d\n", event_to_str(event), lcid);
ch = &smux_lch[lcid];
+ if (!ch->notify) {
+ SMUX_DBG("%s: [%d]lcid notify fn is NULL\n", __func__, lcid);
+ return ret;
+ }
notify_handle = kzalloc(sizeof(struct smux_notify_handle),
GFP_ATOMIC);
if (!notify_handle) {
@@ -1235,6 +1248,7 @@
SMUX_LCH_LOCAL_CLOSING,
SMUX_LCH_LOCAL_CLOSED);
ch->local_state = SMUX_LCH_LOCAL_CLOSED;
+ schedule_notify(lcid, SMUX_LOCAL_CLOSED, &meta_disconnected);
if (ch->remote_state == SMUX_LCH_REMOTE_CLOSED)
schedule_notify(lcid, SMUX_DISCONNECTED,
&meta_disconnected);
@@ -1422,6 +1436,7 @@
}
}
+ schedule_notify(lcid, SMUX_REMOTE_CLOSED, &meta_disconnected);
if (ch->local_state == SMUX_LCH_LOCAL_CLOSED)
schedule_notify(lcid, SMUX_DISCONNECTED,
&meta_disconnected);
@@ -2360,8 +2375,11 @@
union notifier_metadata meta_disconnected;
meta_disconnected.disconnected.is_ssr = smux.in_reset;
- schedule_notify(ch->lcid, SMUX_DISCONNECTED,
+ schedule_notify(ch->lcid, SMUX_LOCAL_CLOSED,
&meta_disconnected);
+ if (ch->remote_state == SMUX_LCH_REMOTE_CLOSED)
+ schedule_notify(ch->lcid, SMUX_DISCONNECTED,
+ &meta_disconnected);
}
}
@@ -3089,11 +3107,15 @@
*
* @returns 0 for success, <0 otherwise
*
- * A channel must be fully closed (either not previously opened or
- * msm_smux_close() has been called and the SMUX_DISCONNECTED has been
- * received.
+ * The local channel state must be closed (either not previously
+ * opened or msm_smux_close() has been called and the SMUX_LOCAL_CLOSED
+ * notification has been received).
*
- * One the remote side is opened, the client will receive a SMUX_CONNECTED
+ * If open is called before the SMUX_LOCAL_CLOSED has been received,
+ * then the function will return -EAGAIN and the client will need to
+ * retry the open later.
+ *
+ * Once the remote side is opened, the client will receive a SMUX_CONNECTED
* event.
*/
int msm_smux_open(uint8_t lcid, void *priv,
@@ -3170,7 +3192,8 @@
* @returns 0 for success, <0 otherwise
*
* Once the close event has been acknowledge by the remote side, the client
- * will receive a SMUX_DISCONNECTED notification.
+ * will receive an SMUX_LOCAL_CLOSED notification. If the remote side is also
+ * closed, then an SMUX_DISCONNECTED notification will also be sent.
*/
int msm_smux_close(uint8_t lcid)
{
diff --git a/drivers/tty/smux_test.c b/drivers/tty/smux_test.c
index 8d17674..130b65e 100644
--- a/drivers/tty/smux_test.c
+++ b/drivers/tty/smux_test.c
@@ -194,6 +194,8 @@
int event_high_wm;
int event_rx_retry_high_wm;
int event_rx_retry_low_wm;
+ int event_local_closed;
+ int event_remote_closed;
/* TIOCM changes */
int event_tiocm;
@@ -249,6 +251,8 @@
cb->event_high_wm = 0;
cb->event_rx_retry_high_wm = 0;
cb->event_rx_retry_low_wm = 0;
+ cb->event_local_closed = 0;
+ cb->event_remote_closed = 0;
cb->event_tiocm = 0;
cb->tiocm_meta.tiocm_old = 0;
cb->tiocm_meta.tiocm_new = 0;
@@ -311,6 +315,8 @@
"\tevent_high_wm=%d\n"
"\tevent_rx_retry_high_wm=%d\n"
"\tevent_rx_retry_low_wm=%d\n"
+ "\tevent_local_closed=%d\n"
+ "\tevent_remote_closed=%d\n"
"\tevent_tiocm=%d\n"
"\tevent_read_done=%d\n"
"\tevent_read_failed=%d\n"
@@ -329,6 +335,8 @@
cb->event_high_wm,
cb->event_rx_retry_high_wm,
cb->event_rx_retry_low_wm,
+ cb->event_local_closed,
+ cb->event_remote_closed,
cb->event_tiocm,
cb->event_read_done,
cb->event_read_failed,
@@ -467,6 +475,22 @@
spin_unlock_irqrestore(&cb_data_ptr->lock, flags);
break;
+ case SMUX_LOCAL_CLOSED:
+ spin_lock_irqsave(&cb_data_ptr->lock, flags);
+ ++cb_data_ptr->event_local_closed;
+ cb_data_ptr->event_disconnected_ssr =
+ ((struct smux_meta_disconnected *)metadata)->is_ssr;
+ spin_unlock_irqrestore(&cb_data_ptr->lock, flags);
+ break;
+
+ case SMUX_REMOTE_CLOSED:
+ spin_lock_irqsave(&cb_data_ptr->lock, flags);
+ ++cb_data_ptr->event_remote_closed;
+ cb_data_ptr->event_disconnected_ssr =
+ ((struct smux_meta_disconnected *)metadata)->is_ssr;
+ spin_unlock_irqrestore(&cb_data_ptr->lock, flags);
+ break;
+
default:
pr_err("%s: unknown event %d\n", __func__, event);
};
@@ -609,13 +633,18 @@
/* close port */
ret = msm_smux_close(SMUX_TEST_LCID);
UT_ASSERT_INT(ret, ==, 0);
- UT_ASSERT_INT(
- (int)wait_for_completion_timeout(
- &cb_data.cb_completion, HZ),
- >, 0);
- UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+ while (cb_data.cb_count < 3) {
+ UT_ASSERT_INT(
+ (int)wait_for_completion_timeout(
+ &cb_data.cb_completion, HZ),
+ >, 0);
+ INIT_COMPLETION(cb_data.cb_completion);
+ }
+ UT_ASSERT_INT(cb_data.cb_count, ==, 3);
UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
+ UT_ASSERT_INT(cb_data.event_local_closed, ==, 1);
+ UT_ASSERT_INT(cb_data.event_remote_closed, ==, 1);
break;
}
@@ -783,13 +812,18 @@
/* verify SSR events */
UT_ASSERT_INT(ret, ==, 0);
- UT_ASSERT_INT(
- (int)wait_for_completion_timeout(
- &cb_data.cb_completion, 5*HZ),
- >, 0);
- UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+ while (cb_data.cb_count < 3) {
+ UT_ASSERT_INT(
+ (int)wait_for_completion_timeout(
+ &cb_data.cb_completion, 10*HZ),
+ >, 0);
+ INIT_COMPLETION(cb_data.cb_completion);
+ }
+ UT_ASSERT_INT(cb_data.cb_count, ==, 3);
UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 1);
+ UT_ASSERT_INT(cb_data.event_local_closed, ==, 1);
+ UT_ASSERT_INT(cb_data.event_remote_closed, ==, 1);
mock_cb_data_reset(&cb_data);
/* close port */
@@ -894,6 +928,8 @@
break;
UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 1);
+ UT_ASSERT_INT(cb_data.event_local_closed, ==, 1);
+ UT_ASSERT_INT(cb_data.event_remote_closed, ==, 1);
mock_cb_data_reset(&cb_data);
/* close port */
@@ -1272,13 +1308,18 @@
/* close port */
ret = msm_smux_close(SMUX_TEST_LCID);
UT_ASSERT_INT(ret, ==, 0);
- UT_ASSERT_INT(
- (int)wait_for_completion_timeout(
- &cb_data.cb_completion, HZ),
- >, 0);
- UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+ while (cb_data.cb_count < 3) {
+ UT_ASSERT_INT(
+ (int)wait_for_completion_timeout(
+ &cb_data.cb_completion, HZ),
+ >, 0);
+ INIT_COMPLETION(cb_data.cb_completion);
+ }
+ UT_ASSERT_INT(cb_data.cb_count, ==, 3);
UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
+ UT_ASSERT_INT(cb_data.event_local_closed, ==, 1);
+ UT_ASSERT_INT(cb_data.event_remote_closed, ==, 1);
break;
}
@@ -1442,13 +1483,18 @@
/* close port */
ret = msm_smux_close(SMUX_TEST_LCID);
UT_ASSERT_INT(ret, ==, 0);
- UT_ASSERT_INT(
- (int)wait_for_completion_timeout(
- &cb_data.cb_completion, HZ),
- >, 0);
- UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+ while (cb_data.cb_count < 3) {
+ UT_ASSERT_INT(
+ (int)wait_for_completion_timeout(
+ &cb_data.cb_completion, HZ),
+ >, 0);
+ INIT_COMPLETION(cb_data.cb_completion);
+ }
+ UT_ASSERT_INT(cb_data.cb_count, ==, 3);
UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
+ UT_ASSERT_INT(cb_data.event_local_closed, ==, 1);
+ UT_ASSERT_INT(cb_data.event_remote_closed, ==, 1);
break;
}
@@ -1552,13 +1598,18 @@
/* close port */
ret = msm_smux_close(SMUX_TEST_LCID);
UT_ASSERT_INT(ret, ==, 0);
- UT_ASSERT_INT(
- (int)wait_for_completion_timeout(
- &cb_data.cb_completion, HZ),
- >, 0);
- UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+ while (cb_data.cb_count < 3) {
+ UT_ASSERT_INT(
+ (int)wait_for_completion_timeout(
+ &cb_data.cb_completion, HZ),
+ >, 0);
+ INIT_COMPLETION(cb_data.cb_completion);
+ }
+ UT_ASSERT_INT(cb_data.cb_count, ==, 3);
UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
+ UT_ASSERT_INT(cb_data.event_local_closed, ==, 1);
+ UT_ASSERT_INT(cb_data.event_remote_closed, ==, 1);
break;
}
@@ -1884,13 +1935,18 @@
/* close port */
ret = msm_smux_close(SMUX_TEST_LCID);
UT_ASSERT_INT(ret, ==, 0);
- UT_ASSERT_INT(
- (int)wait_for_completion_timeout(
- &cb_data.cb_completion, HZ),
- >, 0);
- UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+ while (cb_data.cb_count < 3) {
+ UT_ASSERT_INT(
+ (int)wait_for_completion_timeout(
+ &cb_data.cb_completion, HZ),
+ >, 0);
+ INIT_COMPLETION(cb_data.cb_completion);
+ }
+ UT_ASSERT_INT(cb_data.cb_count, ==, 3);
UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
+ UT_ASSERT_INT(cb_data.event_local_closed, ==, 1);
+ UT_ASSERT_INT(cb_data.event_remote_closed, ==, 1);
break;
}
@@ -2010,13 +2066,18 @@
/* close port */
ret = msm_smux_close(SMUX_TEST_LCID);
UT_ASSERT_INT(ret, ==, 0);
- UT_ASSERT_INT(
- (int)wait_for_completion_timeout(
- &cb_data.cb_completion, HZ),
- >, 0);
- UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+ while (cb_data.cb_count < 3) {
+ UT_ASSERT_INT(
+ (int)wait_for_completion_timeout(
+ &cb_data.cb_completion, HZ),
+ >, 0);
+ INIT_COMPLETION(cb_data.cb_completion);
+ }
+ UT_ASSERT_INT(cb_data.cb_count, ==, 3);
UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
+ UT_ASSERT_INT(cb_data.event_local_closed, ==, 1);
+ UT_ASSERT_INT(cb_data.event_remote_closed, ==, 1);
break;
}
@@ -2139,13 +2200,18 @@
/* close port */
ret = msm_smux_close(SMUX_TEST_LCID);
UT_ASSERT_INT(ret, ==, 0);
- UT_ASSERT_INT(
- (int)wait_for_completion_timeout(
- &cb_data.cb_completion, HZ),
- >, 0);
- UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+ while (cb_data.cb_count < 3) {
+ UT_ASSERT_INT(
+ (int)wait_for_completion_timeout(
+ &cb_data.cb_completion, HZ),
+ >, 0);
+ INIT_COMPLETION(cb_data.cb_completion);
+ }
+ UT_ASSERT_INT(cb_data.cb_count, ==, 3);
UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
+ UT_ASSERT_INT(cb_data.event_local_closed, ==, 1);
+ UT_ASSERT_INT(cb_data.event_remote_closed, ==, 1);
break;
}
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 2487e3f..0f8a7f0 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -36,6 +36,7 @@
#include <linux/usb/msm_hsusb.h>
#include <linux/usb/msm_ext_chg.h>
#include <linux/regulator/consumer.h>
+#include <linux/pm_wakeup.h>
#include <linux/power_supply.h>
#include <linux/qpnp/qpnp-adc.h>
#include <linux/cdev.h>
@@ -196,7 +197,6 @@
bool lpm_irq_seen;
struct delayed_work resume_work;
struct work_struct restart_usb_work;
- struct wake_lock wlock;
struct dwc3_charger charger;
struct usb_phy *otg_xceiv;
struct delayed_work chg_work;
@@ -246,8 +246,6 @@
#define USB_SSPHY_1P8_VOL_MAX 1800000 /* uV */
#define USB_SSPHY_1P8_HPM_LOAD 23000 /* uA */
-static struct dwc3_msm *context;
-
static struct usb_ext_notification *usb_ext;
/**
@@ -343,8 +341,8 @@
tmp &= mask; /* clear other bits */
if (tmp != val)
- dev_err(context->dev, "%s: write: %x to QSCRATCH: %x FAILED\n",
- __func__, val, offset);
+ pr_err("%s: write: %x to QSCRATCH: %x FAILED\n",
+ __func__, val, offset);
}
/**
@@ -413,12 +411,12 @@
* Return DBM EP number according to usb endpoint number.
*
*/
-static int dwc3_msm_find_matching_dbm_ep(u8 usb_ep)
+static int dwc3_msm_find_matching_dbm_ep(struct dwc3_msm *mdwc, u8 usb_ep)
{
int i;
- for (i = 0; i < context->dbm_num_eps; i++)
- if (context->ep_num_mapping[i] == usb_ep)
+ for (i = 0; i < mdwc->dbm_num_eps; i++)
+ if (mdwc->ep_num_mapping[i] == usb_ep)
return i;
return -ENODEV; /* Not found */
@@ -428,13 +426,13 @@
* Return number of configured DBM endpoints.
*
*/
-static int dwc3_msm_configured_dbm_ep_num(void)
+static int dwc3_msm_configured_dbm_ep_num(struct dwc3_msm *mdwc)
{
int i;
int count = 0;
- for (i = 0; i < context->dbm_num_eps; i++)
- if (context->ep_num_mapping[i])
+ for (i = 0; i < mdwc->dbm_num_eps; i++)
+ if (mdwc->ep_num_mapping[i])
count++;
return count;
@@ -448,12 +446,13 @@
* @size - size of the event buffer.
*
*/
-static int dwc3_msm_event_buffer_config(u32 addr, u16 size)
+static int dwc3_msm_event_buffer_config(struct dwc3_msm *mdwc,
+ u32 addr, u16 size)
{
- dev_dbg(context->dev, "%s\n", __func__);
+ dev_dbg(mdwc->dev, "%s\n", __func__);
- dwc3_msm_write_reg(context->base, DBM_GEVNTADR, addr);
- dwc3_msm_write_reg_field(context->base, DBM_GEVNTSIZ,
+ dwc3_msm_write_reg(mdwc->base, DBM_GEVNTADR, addr);
+ dwc3_msm_write_reg_field(mdwc->base, DBM_GEVNTSIZ,
DBM_GEVNTSIZ_MASK, size);
return 0;
@@ -463,19 +462,19 @@
* Reset the DBM registers upon initialization.
*
*/
-static int dwc3_msm_dbm_soft_reset(int enter_reset)
+static int dwc3_msm_dbm_soft_reset(struct dwc3_msm *mdwc, int enter_reset)
{
- dev_dbg(context->dev, "%s\n", __func__);
+ dev_dbg(mdwc->dev, "%s\n", __func__);
if (enter_reset) {
- dev_dbg(context->dev, "enter DBM reset\n");
- dwc3_msm_write_reg_field(context->base, DBM_SOFT_RESET,
+ dev_dbg(mdwc->dev, "enter DBM reset\n");
+ dwc3_msm_write_reg_field(mdwc->base, DBM_SOFT_RESET,
DBM_SFT_RST_MASK, 1);
} else {
- dev_dbg(context->dev, "exit DBM reset\n");
- dwc3_msm_write_reg_field(context->base, DBM_SOFT_RESET,
+ dev_dbg(mdwc->dev, "exit DBM reset\n");
+ dwc3_msm_write_reg_field(mdwc->base, DBM_SOFT_RESET,
DBM_SFT_RST_MASK, 0);
/*enable DBM*/
- dwc3_msm_write_reg_field(context->base, QSCRATCH_GENERAL_CFG,
+ dwc3_msm_write_reg_field(mdwc->base, QSCRATCH_GENERAL_CFG,
DBM_EN_MASK, 0x1);
}
@@ -492,21 +491,21 @@
* @enter_reset - should we enter a reset state or get out of it.
*
*/
-static int dwc3_msm_dbm_ep_soft_reset(u8 dbm_ep, bool enter_reset)
+static int dwc3_msm_dbm_ep_soft_reset(struct dwc3_msm *mdwc,
+ u8 dbm_ep, bool enter_reset)
{
- dev_dbg(context->dev, "%s\n", __func__);
+ dev_dbg(mdwc->dev, "%s\n", __func__);
- if (dbm_ep >= context->dbm_num_eps) {
- dev_err(context->dev,
- "%s: Invalid DBM ep index\n", __func__);
+ if (dbm_ep >= mdwc->dbm_num_eps) {
+ dev_err(mdwc->dev, "%s: Invalid DBM ep index\n", __func__);
return -ENODEV;
}
if (enter_reset) {
- dwc3_msm_write_reg_field(context->base, DBM_SOFT_RESET,
+ dwc3_msm_write_reg_field(mdwc->base, DBM_SOFT_RESET,
DBM_SFT_RST_EPS_MASK & 1 << dbm_ep, 1);
} else {
- dwc3_msm_write_reg_field(context->base, DBM_SOFT_RESET,
+ dwc3_msm_write_reg_field(mdwc->base, DBM_SOFT_RESET,
DBM_SFT_RST_EPS_MASK & 1 << dbm_ep, 0);
}
@@ -525,43 +524,43 @@
*
* @return int - DBM ep number.
*/
-static int dwc3_msm_dbm_ep_config(u8 usb_ep, u8 bam_pipe,
+static int dwc3_msm_dbm_ep_config(struct dwc3_msm *mdwc, u8 usb_ep, u8 bam_pipe,
bool producer, bool disable_wb,
bool internal_mem, bool ioc)
{
u8 dbm_ep;
u32 ep_cfg;
- dev_dbg(context->dev, "%s\n", __func__);
+ dev_dbg(mdwc->dev, "%s\n", __func__);
- dbm_ep = dwc3_msm_find_matching_dbm_ep(usb_ep);
+ dbm_ep = dwc3_msm_find_matching_dbm_ep(mdwc, usb_ep);
if (dbm_ep < 0) {
- dev_err(context->dev,
+ dev_err(mdwc->dev,
"%s: Invalid usb ep index\n", __func__);
return -ENODEV;
}
/* First, reset the dbm endpoint */
- dwc3_msm_dbm_ep_soft_reset(dbm_ep, 0);
+ dwc3_msm_dbm_ep_soft_reset(mdwc, dbm_ep, 0);
/* Set ioc bit for dbm_ep if needed */
- dwc3_msm_write_reg_field(context->base, DBM_DBG_CNFG,
+ dwc3_msm_write_reg_field(mdwc->base, DBM_DBG_CNFG,
DBM_ENABLE_IOC_MASK & 1 << dbm_ep, ioc ? 1 : 0);
ep_cfg = (producer ? DBM_PRODUCER : 0) |
(disable_wb ? DBM_DISABLE_WB : 0) |
(internal_mem ? DBM_INT_RAM_ACC : 0);
- dwc3_msm_write_reg_field(context->base, DBM_EP_CFG(dbm_ep),
+ dwc3_msm_write_reg_field(mdwc->base, DBM_EP_CFG(dbm_ep),
DBM_PRODUCER | DBM_DISABLE_WB | DBM_INT_RAM_ACC, ep_cfg >> 8);
- dwc3_msm_write_reg_field(context->base, DBM_EP_CFG(dbm_ep), USB3_EPNUM,
+ dwc3_msm_write_reg_field(mdwc->base, DBM_EP_CFG(dbm_ep), USB3_EPNUM,
usb_ep);
- dwc3_msm_write_reg_field(context->base, DBM_EP_CFG(dbm_ep),
+ dwc3_msm_write_reg_field(mdwc->base, DBM_EP_CFG(dbm_ep),
DBM_BAM_PIPE_NUM, bam_pipe);
- dwc3_msm_write_reg_field(context->base, DBM_PIPE_CFG, 0x000000ff,
+ dwc3_msm_write_reg_field(mdwc->base, DBM_PIPE_CFG, 0x000000ff,
0xe4);
- dwc3_msm_write_reg_field(context->base, DBM_EP_CFG(dbm_ep), DBM_EN_EP,
+ dwc3_msm_write_reg_field(mdwc->base, DBM_EP_CFG(dbm_ep), DBM_EN_EP,
1);
return dbm_ep;
@@ -573,35 +572,34 @@
* @usb_ep - USB ep number.
*
*/
-static int dwc3_msm_dbm_ep_unconfig(u8 usb_ep)
+static int dwc3_msm_dbm_ep_unconfig(struct dwc3_msm *mdwc, u8 usb_ep)
{
u8 dbm_ep;
u32 data;
- dev_dbg(context->dev, "%s\n", __func__);
+ dev_dbg(mdwc->dev, "%s\n", __func__);
- dbm_ep = dwc3_msm_find_matching_dbm_ep(usb_ep);
+ dbm_ep = dwc3_msm_find_matching_dbm_ep(mdwc, usb_ep);
if (dbm_ep < 0) {
- dev_err(context->dev,
- "%s: Invalid usb ep index\n", __func__);
+ dev_err(mdwc->dev, "%s: Invalid usb ep index\n", __func__);
return -ENODEV;
}
- context->ep_num_mapping[dbm_ep] = 0;
+ mdwc->ep_num_mapping[dbm_ep] = 0;
- data = dwc3_msm_read_reg(context->base, DBM_EP_CFG(dbm_ep));
+ data = dwc3_msm_read_reg(mdwc->base, DBM_EP_CFG(dbm_ep));
data &= (~0x1);
- dwc3_msm_write_reg(context->base, DBM_EP_CFG(dbm_ep), data);
+ dwc3_msm_write_reg(mdwc->base, DBM_EP_CFG(dbm_ep), data);
/* Reset the dbm endpoint */
- dwc3_msm_dbm_ep_soft_reset(dbm_ep, true);
+ dwc3_msm_dbm_ep_soft_reset(mdwc, dbm_ep, true);
/*
* 10 usec delay is required before deasserting DBM endpoint reset
* according to hardware programming guide.
*/
udelay(10);
- dwc3_msm_dbm_ep_soft_reset(dbm_ep, false);
+ dwc3_msm_dbm_ep_soft_reset(mdwc, dbm_ep, false);
return 0;
}
@@ -620,15 +618,17 @@
{
u8 dbm_ep;
struct dwc3_ep *dep = to_dwc3_ep(ep);
+ struct dwc3 *dwc = dep->dwc;
+ struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
u8 bam_pipe = dst_pipe_idx;
- dev_dbg(context->dev, "%s\n", __func__);
+ dev_dbg(mdwc->dev, "%s\n", __func__);
dbm_ep = bam_pipe;
- context->ep_num_mapping[dbm_ep] = dep->number;
+ mdwc->ep_num_mapping[dbm_ep] = dep->number;
- dwc3_msm_write_reg(context->base, DBM_DATA_FIFO(dbm_ep), addr);
- dwc3_msm_write_reg_field(context->base, DBM_DATA_FIFO_SIZE(dbm_ep),
+ dwc3_msm_write_reg(mdwc->base, DBM_DATA_FIFO(dbm_ep), addr);
+ dwc3_msm_write_reg_field(mdwc->base, DBM_DATA_FIFO_SIZE(dbm_ep),
DBM_DATA_FIFO_SIZE_MASK, size);
return 0;
@@ -648,12 +648,12 @@
struct usb_request *request)
{
struct dwc3_ep *dep = to_dwc3_ep(ep);
+ struct dwc3 *dwc = dep->dwc;
+ struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
struct dwc3_msm_req_complete *req_complete = NULL;
/* Find original request complete function and remove it from list */
- list_for_each_entry(req_complete,
- &context->req_complete_list,
- list_item) {
+ list_for_each_entry(req_complete, &mdwc->req_complete_list, list_item) {
if (req_complete->req == request)
break;
}
@@ -672,14 +672,14 @@
dep->busy_slot++;
/* Unconfigure dbm ep */
- dwc3_msm_dbm_ep_unconfig(dep->number);
+ dwc3_msm_dbm_ep_unconfig(mdwc, dep->number);
/*
* If this is the last endpoint we unconfigured, than reset also
* the event buffers.
*/
- if (0 == dwc3_msm_configured_dbm_ep_num())
- dwc3_msm_event_buffer_config(0, 0);
+ if (0 == dwc3_msm_configured_dbm_ep_num(mdwc))
+ dwc3_msm_event_buffer_config(mdwc, 0, 0);
/*
* Call original complete function, notice that dwc->lock is already
@@ -792,6 +792,7 @@
struct dwc3_request *req = to_dwc3_request(request);
struct dwc3_ep *dep = to_dwc3_ep(ep);
struct dwc3 *dwc = dep->dwc;
+ struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
struct dwc3_msm_req_complete *req_complete;
unsigned long flags;
int ret = 0;
@@ -804,23 +805,23 @@
if (!(request->udc_priv & MSM_SPS_MODE)) {
/* Not SPS mode, call original queue */
- dev_vdbg(dwc->dev, "%s: not sps mode, use regular queue\n",
+ dev_vdbg(mdwc->dev, "%s: not sps mode, use regular queue\n",
__func__);
- return (context->original_ep_ops[dep->number])->queue(ep,
+ return (mdwc->original_ep_ops[dep->number])->queue(ep,
request,
gfp_flags);
}
if (!dep->endpoint.desc) {
- dev_err(dwc->dev,
+ dev_err(mdwc->dev,
"%s: trying to queue request %p to disabled ep %s\n",
__func__, request, ep->name);
return -EPERM;
}
if (dep->number == 0 || dep->number == 1) {
- dev_err(dwc->dev,
+ dev_err(mdwc->dev,
"%s: trying to queue dbm request %p to control ep %s\n",
__func__, request, ep->name);
return -EPERM;
@@ -829,7 +830,7 @@
if (dep->busy_slot != dep->free_slot || !list_empty(&dep->request_list)
|| !list_empty(&dep->req_queued)) {
- dev_err(dwc->dev,
+ dev_err(mdwc->dev,
"%s: trying to queue dbm request %p tp ep %s\n",
__func__, request, ep->name);
return -EPERM;
@@ -844,12 +845,12 @@
*/
req_complete = kzalloc(sizeof(*req_complete), GFP_KERNEL);
if (!req_complete) {
- dev_err(dep->dwc->dev, "%s: not enough memory\n", __func__);
+ dev_err(mdwc->dev, "%s: not enough memory\n", __func__);
return -ENOMEM;
}
req_complete->req = request;
req_complete->orig_complete = request->complete;
- list_add_tail(&req_complete->list_item, &context->req_complete_list);
+ list_add_tail(&req_complete->list_item, &mdwc->req_complete_list);
request->complete = dwc3_msm_req_complete_func;
/*
@@ -861,11 +862,11 @@
internal_mem = ((request->udc_priv & MSM_INTERNAL_MEM) ? true : false);
ioc = ((request->udc_priv & MSM_ETD_IOC) ? true : false);
- ret = dwc3_msm_dbm_ep_config(dep->number,
+ ret = dwc3_msm_dbm_ep_config(mdwc, dep->number,
bam_pipe, producer,
disable_wb, internal_mem, ioc);
if (ret < 0) {
- dev_err(context->dev,
+ dev_err(mdwc->dev,
"error %d after calling dwc3_msm_dbm_ep_config\n",
ret);
return ret;
@@ -885,13 +886,13 @@
ret = __dwc3_msm_ep_queue(dep, req);
spin_unlock_irqrestore(&dwc->lock, flags);
if (ret < 0) {
- dev_err(context->dev,
+ dev_err(mdwc->dev,
"error %d after calling __dwc3_msm_ep_queue\n", ret);
return ret;
}
speed = dwc3_readl(dwc->regs, DWC3_DSTS) & DWC3_DSTS_CONNECTSPD;
- dwc3_msm_write_reg(context->base, DBM_GEN_CFG, speed >> 2);
+ dwc3_msm_write_reg(mdwc->base, DBM_GEN_CFG, speed >> 2);
return 0;
}
@@ -913,25 +914,27 @@
int msm_ep_config(struct usb_ep *ep)
{
struct dwc3_ep *dep = to_dwc3_ep(ep);
+ struct dwc3 *dwc = dep->dwc;
+ struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
struct usb_ep_ops *new_ep_ops;
- dwc3_msm_event_buffer_config(dwc3_msm_read_reg(context->base,
- DWC3_GEVNTADRLO(0)),
- dwc3_msm_read_reg(context->base, DWC3_GEVNTSIZ(0)));
+ dwc3_msm_event_buffer_config(mdwc,
+ dwc3_msm_read_reg(mdwc->base, DWC3_GEVNTADRLO(0)),
+ dwc3_msm_read_reg(mdwc->base, DWC3_GEVNTSIZ(0)));
/* Save original ep ops for future restore*/
- if (context->original_ep_ops[dep->number]) {
- dev_err(context->dev,
+ if (mdwc->original_ep_ops[dep->number]) {
+ dev_err(mdwc->dev,
"ep [%s,%d] already configured as msm endpoint\n",
ep->name, dep->number);
return -EPERM;
}
- context->original_ep_ops[dep->number] = ep->ops;
+ mdwc->original_ep_ops[dep->number] = ep->ops;
/* Set new usb ops as we like */
new_ep_ops = kzalloc(sizeof(struct usb_ep_ops), GFP_KERNEL);
if (!new_ep_ops) {
- dev_err(context->dev,
+ dev_err(mdwc->dev,
"%s: unable to allocate mem for new usb ep ops\n",
__func__);
return -ENOMEM;
@@ -963,18 +966,20 @@
int msm_ep_unconfig(struct usb_ep *ep)
{
struct dwc3_ep *dep = to_dwc3_ep(ep);
+ struct dwc3 *dwc = dep->dwc;
+ struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
struct usb_ep_ops *old_ep_ops;
/* Restore original ep ops */
- if (!context->original_ep_ops[dep->number]) {
- dev_err(context->dev,
+ if (!mdwc->original_ep_ops[dep->number]) {
+ dev_err(mdwc->dev,
"ep [%s,%d] was not configured as msm endpoint\n",
ep->name, dep->number);
return -EINVAL;
}
old_ep_ops = (struct usb_ep_ops *)ep->ops;
- ep->ops = context->original_ep_ops[dep->number];
- context->original_ep_ops[dep->number] = NULL;
+ ep->ops = mdwc->original_ep_ops[dep->number];
+ mdwc->original_ep_ops[dep->number] = NULL;
kfree(old_ep_ops);
/*
@@ -1019,14 +1024,16 @@
* This performs full hardware reset and re-initialization which
* might be required by some DBM client driver during uninit/cleanup.
*/
-void msm_dwc3_restart_usb_session(void)
+void msm_dwc3_restart_usb_session(struct usb_gadget *gadget)
{
- struct dwc3_msm *mdwc = context;
+ struct dwc3 *dwc = container_of(gadget, struct dwc3, gadget);
+ struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
+
+ if (mdwc)
+ return;
dev_dbg(mdwc->dev, "%s\n", __func__);
queue_work(system_nrt_wq, &mdwc->restart_usb_work);
-
- return;
}
EXPORT_SYMBOL(msm_dwc3_restart_usb_session);
@@ -1058,10 +1065,9 @@
EXPORT_SYMBOL(msm_register_usb_ext_notification);
/* HSPHY */
-static int dwc3_hsusb_config_vddcx(int high)
+static int dwc3_hsusb_config_vddcx(struct dwc3_msm *dwc, int high)
{
int min_vol, max_vol, ret;
- struct dwc3_msm *dwc = context;
max_vol = dwc->vdd_high_vol_level;
min_vol = high ? dwc->vdd_low_vol_level : dwc->vdd_no_vol_level;
@@ -1077,10 +1083,9 @@
return ret;
}
-static int dwc3_hsusb_ldo_init(int init)
+static int dwc3_hsusb_ldo_init(struct dwc3_msm *dwc, int init)
{
int rc = 0;
- struct dwc3_msm *dwc = context;
if (!init) {
regulator_set_voltage(dwc->hsusb_1p8, 0, USB_HSPHY_1P8_VOL_MAX);
@@ -1121,10 +1126,9 @@
return rc;
}
-static int dwc3_hsusb_ldo_enable(int on)
+static int dwc3_hsusb_ldo_enable(struct dwc3_msm *dwc, int on)
{
int rc = 0;
- struct dwc3_msm *dwc = context;
dev_dbg(dwc->dev, "reg (%s)\n", on ? "HPM" : "LPM");
@@ -1182,10 +1186,9 @@
}
/* SSPHY */
-static int dwc3_ssusb_config_vddcx(int high)
+static int dwc3_ssusb_config_vddcx(struct dwc3_msm *dwc, int high)
{
int min_vol, max_vol, ret;
- struct dwc3_msm *dwc = context;
max_vol = dwc->vdd_high_vol_level;
min_vol = high ? dwc->vdd_low_vol_level : dwc->vdd_no_vol_level;
@@ -1201,10 +1204,9 @@
}
/* 3.3v supply not needed for SS PHY */
-static int dwc3_ssusb_ldo_init(int init)
+static int dwc3_ssusb_ldo_init(struct dwc3_msm *dwc, int init)
{
int rc = 0;
- struct dwc3_msm *dwc = context;
if (!init) {
regulator_set_voltage(dwc->ssusb_1p8, 0, USB_SSPHY_1P8_VOL_MAX);
@@ -1224,12 +1226,11 @@
return rc;
}
-static int dwc3_ssusb_ldo_enable(int on)
+static int dwc3_ssusb_ldo_enable(struct dwc3_msm *dwc, int on)
{
int rc = 0;
- struct dwc3_msm *dwc = context;
- dev_dbg(context->dev, "reg (%s)\n", on ? "HPM" : "LPM");
+ dev_dbg(dwc->dev, "reg (%s)\n", on ? "HPM" : "LPM");
if (!on)
goto disable_regulators;
@@ -1266,37 +1267,36 @@
* Config Global Distributed Switch Controller (GDSC)
* to support controller power collapse
*/
-static int dwc3_msm_config_gdsc(struct dwc3_msm *msm, int on)
+static int dwc3_msm_config_gdsc(struct dwc3_msm *mdwc, int on)
{
int ret = 0;
- if (IS_ERR(msm->dwc3_gdsc))
+ if (IS_ERR(mdwc->dwc3_gdsc))
return 0;
- if (!msm->dwc3_gdsc) {
- msm->dwc3_gdsc = devm_regulator_get(msm->dev,
+ if (!mdwc->dwc3_gdsc) {
+ mdwc->dwc3_gdsc = devm_regulator_get(mdwc->dev,
"USB3_GDSC");
- if (IS_ERR(msm->dwc3_gdsc))
+ if (IS_ERR(mdwc->dwc3_gdsc))
return 0;
}
if (on) {
- ret = regulator_enable(msm->dwc3_gdsc);
+ ret = regulator_enable(mdwc->dwc3_gdsc);
if (ret) {
- dev_err(msm->dev, "unable to enable usb3 gdsc\n");
+ dev_err(mdwc->dev, "unable to enable usb3 gdsc\n");
return ret;
}
} else {
- regulator_disable(msm->dwc3_gdsc);
+ regulator_disable(mdwc->dwc3_gdsc);
}
return 0;
}
-static int dwc3_msm_link_clk_reset(bool assert)
+static int dwc3_msm_link_clk_reset(struct dwc3_msm *mdwc, bool assert)
{
int ret = 0;
- struct dwc3_msm *mdwc = context;
if (assert) {
/* Using asynchronous block reset to the hardware */
@@ -1322,7 +1322,7 @@
}
/* Reinitialize SSPHY parameters by overriding using QSCRATCH CR interface */
-static void dwc3_msm_ss_phy_reg_init(struct dwc3_msm *msm)
+static void dwc3_msm_ss_phy_reg_init(struct dwc3_msm *mdwc)
{
u32 data = 0;
@@ -1331,14 +1331,14 @@
* in HS mode instead of SS mode. Workaround it by asserting
* LANE0.TX_ALT_BLOCK.EN_ALT_BUS to enable TX to use alt bus mode
*/
- data = dwc3_msm_ssusb_read_phycreg(msm->base, 0x102D);
+ data = dwc3_msm_ssusb_read_phycreg(mdwc->base, 0x102D);
data |= (1 << 7);
- dwc3_msm_ssusb_write_phycreg(msm->base, 0x102D, data);
+ dwc3_msm_ssusb_write_phycreg(mdwc->base, 0x102D, data);
- data = dwc3_msm_ssusb_read_phycreg(msm->base, 0x1010);
+ data = dwc3_msm_ssusb_read_phycreg(mdwc->base, 0x1010);
data &= ~0xFF0;
data |= 0x20;
- dwc3_msm_ssusb_write_phycreg(msm->base, 0x1010, data);
+ dwc3_msm_ssusb_write_phycreg(mdwc->base, 0x1010, data);
/*
* Fix RX Equalization setting as follows
@@ -1347,13 +1347,13 @@
* LANE0.RX_OVRD_IN_HI.RX_EQ set to 3
* LANE0.RX_OVRD_IN_HI.RX_EQ_OVRD set to 1
*/
- data = dwc3_msm_ssusb_read_phycreg(msm->base, 0x1006);
+ data = dwc3_msm_ssusb_read_phycreg(mdwc->base, 0x1006);
data &= ~(1 << 6);
data |= (1 << 7);
data &= ~(0x7 << 8);
data |= (0x3 << 8);
data |= (0x1 << 11);
- dwc3_msm_ssusb_write_phycreg(msm->base, 0x1006, data);
+ dwc3_msm_ssusb_write_phycreg(mdwc->base, 0x1006, data);
/*
* Set EQ and TX launch amplitudes as follows
@@ -1361,12 +1361,12 @@
* LANE0.TX_OVRD_DRV_LO.AMPLITUDE set to 127
* LANE0.TX_OVRD_DRV_LO.EN set to 1.
*/
- data = dwc3_msm_ssusb_read_phycreg(msm->base, 0x1002);
+ data = dwc3_msm_ssusb_read_phycreg(mdwc->base, 0x1002);
data &= ~0x3F80;
data |= (0x16 << 7);
data &= ~0x7F;
data |= (0x7F | (1 << 14));
- dwc3_msm_ssusb_write_phycreg(msm->base, 0x1002, data);
+ dwc3_msm_ssusb_write_phycreg(mdwc->base, 0x1002, data);
/*
* Set the QSCRATCH SS_PHY_PARAM_CTRL1 parameters as follows
@@ -1374,73 +1374,73 @@
* TX_DEEMPH_3_5DB [13:8] to 22
* LOS_BIAS [2:0] to 0x5
*/
- dwc3_msm_write_readback(msm->base, SS_PHY_PARAM_CTRL_1,
+ dwc3_msm_write_readback(mdwc->base, SS_PHY_PARAM_CTRL_1,
0x07f03f07, 0x07f01605);
}
/* Initialize QSCRATCH registers for HSPHY and SSPHY operation */
-static void dwc3_msm_qscratch_reg_init(struct dwc3_msm *msm)
+static void dwc3_msm_qscratch_reg_init(struct dwc3_msm *mdwc)
{
/* SSPHY Initialization: Use ref_clk from pads and set its parameters */
- dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210002);
+ dwc3_msm_write_reg(mdwc->base, SS_PHY_CTRL_REG, 0x10210002);
msleep(30);
/* Assert SSPHY reset */
- dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210082);
+ dwc3_msm_write_reg(mdwc->base, SS_PHY_CTRL_REG, 0x10210082);
usleep_range(2000, 2200);
/* De-assert SSPHY reset - power and ref_clock must be ON */
- dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210002);
+ dwc3_msm_write_reg(mdwc->base, SS_PHY_CTRL_REG, 0x10210002);
usleep_range(2000, 2200);
/* Ref clock must be stable now, enable ref clock for HS mode */
- dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210102);
+ dwc3_msm_write_reg(mdwc->base, SS_PHY_CTRL_REG, 0x10210102);
usleep_range(2000, 2200);
/*
* HSPHY Initialization: Enable UTMI clock and clamp enable HVINTs,
* and disable RETENTION (power-on default is ENABLED)
*/
- dwc3_msm_write_reg(msm->base, HS_PHY_CTRL_REG, 0x5220bb2);
+ dwc3_msm_write_reg(mdwc->base, HS_PHY_CTRL_REG, 0x5220bb2);
usleep_range(2000, 2200);
/* Disable (bypass) VBUS and ID filters */
- dwc3_msm_write_reg(msm->base, QSCRATCH_GENERAL_CFG, 0x78);
+ dwc3_msm_write_reg(mdwc->base, QSCRATCH_GENERAL_CFG, 0x78);
/*
* write HSPHY init value to QSCRATCH reg to set HSPHY parameters like
* VBUS valid threshold, disconnect valid threshold, DC voltage level,
* preempasis and rise/fall time.
*/
if (override_phy_init)
- msm->hsphy_init_seq = override_phy_init;
- if (msm->hsphy_init_seq)
- dwc3_msm_write_readback(msm->base,
+ mdwc->hsphy_init_seq = override_phy_init;
+ if (mdwc->hsphy_init_seq)
+ dwc3_msm_write_readback(mdwc->base,
PARAMETER_OVERRIDE_X_REG, 0x03FFFFFF,
- msm->hsphy_init_seq & 0x03FFFFFF);
+ mdwc->hsphy_init_seq & 0x03FFFFFF);
/* Enable master clock for RAMs to allow BAM to access RAMs when
* RAM clock gating is enabled via DWC3's GCTL. Otherwise, issues
* are seen where RAM clocks get turned OFF in SS mode
*/
- dwc3_msm_write_reg(msm->base, CGCTL_REG,
- dwc3_msm_read_reg(msm->base, CGCTL_REG) | 0x18);
+ dwc3_msm_write_reg(mdwc->base, CGCTL_REG,
+ dwc3_msm_read_reg(mdwc->base, CGCTL_REG) | 0x18);
- dwc3_msm_ss_phy_reg_init(msm);
+ dwc3_msm_ss_phy_reg_init(mdwc);
/*
* This is required to restore the POR value after userspace
* is done with charger detection.
*/
- msm->qscratch_ctl_val = dwc3_msm_read_reg(msm->base, QSCRATCH_CTRL_REG);
+ mdwc->qscratch_ctl_val =
+ dwc3_msm_read_reg(mdwc->base, QSCRATCH_CTRL_REG);
}
-static void dwc3_msm_block_reset(bool core_reset)
+static void dwc3_msm_block_reset(struct dwc3_ext_xceiv *xceiv, bool core_reset)
{
-
- struct dwc3_msm *mdwc = context;
+ struct dwc3_msm *mdwc = container_of(xceiv, struct dwc3_msm, ext_xceiv);
int ret = 0;
if (core_reset) {
- ret = dwc3_msm_link_clk_reset(1);
+ ret = dwc3_msm_link_clk_reset(mdwc, 1);
if (ret)
return;
usleep_range(1000, 1200);
- ret = dwc3_msm_link_clk_reset(0);
+ ret = dwc3_msm_link_clk_reset(mdwc, 0);
if (ret)
return;
@@ -1451,9 +1451,9 @@
}
/* Reset the DBM */
- dwc3_msm_dbm_soft_reset(1);
+ dwc3_msm_dbm_soft_reset(mdwc, 1);
usleep_range(1000, 1200);
- dwc3_msm_dbm_soft_reset(0);
+ dwc3_msm_dbm_soft_reset(mdwc, 0);
}
static void dwc3_chg_enable_secondary_det(struct dwc3_msm *mdwc)
@@ -1664,7 +1664,7 @@
static void dwc3_start_chg_det(struct dwc3_charger *charger, bool start)
{
- struct dwc3_msm *mdwc = context;
+ struct dwc3_msm *mdwc = container_of(charger, struct dwc3_msm, charger);
if (start == false) {
dev_dbg(mdwc->dev, "canceling charging detection work\n");
@@ -1796,13 +1796,13 @@
if (mdwc->otg_xceiv && mdwc->ext_xceiv.otg_capability && !dcp &&
!host_bus_suspend)
- dwc3_hsusb_ldo_enable(0);
+ dwc3_hsusb_ldo_enable(mdwc, 0);
- dwc3_ssusb_ldo_enable(0);
- dwc3_ssusb_config_vddcx(0);
+ dwc3_ssusb_ldo_enable(mdwc, 0);
+ dwc3_ssusb_config_vddcx(mdwc, 0);
if (!host_bus_suspend && !dcp)
- dwc3_hsusb_config_vddcx(0);
- wake_unlock(&mdwc->wlock);
+ dwc3_hsusb_config_vddcx(mdwc, 0);
+ pm_relax(mdwc->dev);
atomic_set(&mdwc->in_lpm, 1);
dev_info(mdwc->dev, "DWC3 in low power mode\n");
@@ -1830,7 +1830,7 @@
return 0;
}
- wake_lock(&mdwc->wlock);
+ pm_stay_awake(mdwc->dev);
if (mdwc->bus_perf_client) {
ret = msm_bus_scale_client_update_request(
@@ -1861,13 +1861,13 @@
if (mdwc->otg_xceiv && mdwc->ext_xceiv.otg_capability && !dcp &&
!host_bus_suspend)
- dwc3_hsusb_ldo_enable(1);
+ dwc3_hsusb_ldo_enable(mdwc, 1);
- dwc3_ssusb_ldo_enable(1);
- dwc3_ssusb_config_vddcx(1);
+ dwc3_ssusb_ldo_enable(mdwc, 1);
+ dwc3_ssusb_config_vddcx(mdwc, 1);
if (!host_bus_suspend && !dcp)
- dwc3_hsusb_config_vddcx(1);
+ dwc3_hsusb_config_vddcx(mdwc, 1);
clk_prepare_enable(mdwc->ref_clk);
usleep_range(1000, 1200);
@@ -2221,9 +2221,9 @@
static void dwc3_init_adc_work(struct work_struct *w);
-static void dwc3_ext_notify_online(int on)
+static void dwc3_ext_notify_online(void *ctx, int on)
{
- struct dwc3_msm *mdwc = context;
+ struct dwc3_msm *mdwc = ctx;
bool notify_otg = false;
if (!mdwc) {
@@ -2271,7 +2271,7 @@
disable_irq(mdwc->pmic_id_irq);
ret = usb_ext->notify(usb_ext->ctxt, mdwc->id_state,
- dwc3_ext_notify_online);
+ dwc3_ext_notify_online, mdwc);
dev_dbg(mdwc->dev, "%s: external handler returned %d\n",
__func__, ret);
@@ -2367,7 +2367,12 @@
static ssize_t adc_enable_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return snprintf(buf, PAGE_SIZE, "%s\n", context->id_adc_detect ?
+ struct dwc3_msm *mdwc = dev_get_drvdata(dev);
+
+ if (!mdwc)
+ return -EINVAL;
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", mdwc->id_adc_detect ?
"enabled" : "disabled");
}
@@ -2375,13 +2380,18 @@
struct device_attribute *attr, const char
*buf, size_t size)
{
+ struct dwc3_msm *mdwc = dev_get_drvdata(dev);
+
+ if (!mdwc)
+ return -EINVAL;
+
if (!strnicmp(buf, "enable", 6)) {
- if (!context->id_adc_detect)
- dwc3_init_adc_work(&context->init_adc_work.work);
+ if (!mdwc->id_adc_detect)
+ dwc3_init_adc_work(&mdwc->init_adc_work.work);
return size;
} else if (!strnicmp(buf, "disable", 7)) {
qpnp_adc_tm_usbid_end();
- context->id_adc_detect = false;
+ mdwc->id_adc_detect = false;
return size;
}
@@ -2393,25 +2403,27 @@
static int dwc3_msm_ext_chg_open(struct inode *inode, struct file *file)
{
- struct dwc3_msm *mdwc = context;
+ struct dwc3_msm *mdwc =
+ container_of(inode->i_cdev, struct dwc3_msm, ext_chg_cdev);
pr_debug("dwc3-msm ext chg open\n");
-
+ file->private_data = mdwc;
mdwc->ext_chg_opened = true;
+
return 0;
}
static long
dwc3_msm_ext_chg_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
- struct dwc3_msm *mdwc = context;
+ struct dwc3_msm *mdwc = file->private_data;
struct msm_usb_chg_info info = {0};
int ret = 0, val;
switch (cmd) {
case MSM_USB_EXT_CHG_INFO:
info.chg_block_type = USB_CHG_BLOCK_QSCRATCH;
- info.page_offset = (context->io_res->start +
+ info.page_offset = (mdwc->io_res->start +
QSCRATCH_REG_OFFSET) & ~PAGE_MASK;
/*
* The charger block register address space is only
@@ -2454,7 +2466,7 @@
static int dwc3_msm_ext_chg_mmap(struct file *file, struct vm_area_struct *vma)
{
- struct dwc3_msm *mdwc = context;
+ struct dwc3_msm *mdwc = file->private_data;
unsigned long vsize = vma->vm_end - vma->vm_start;
int ret;
@@ -2475,7 +2487,7 @@
static int dwc3_msm_ext_chg_release(struct inode *inode, struct file *file)
{
- struct dwc3_msm *mdwc = context;
+ struct dwc3_msm *mdwc = file->private_data;
pr_debug("dwc3-msm ext chg release\n");
@@ -2540,7 +2552,7 @@
static int __devinit dwc3_msm_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
- struct dwc3_msm *msm;
+ struct dwc3_msm *mdwc;
struct resource *res;
void __iomem *tcsr;
unsigned long flags;
@@ -2548,39 +2560,38 @@
int len = 0;
u32 tmp[3];
- msm = devm_kzalloc(&pdev->dev, sizeof(*msm), GFP_KERNEL);
- if (!msm) {
+ mdwc = devm_kzalloc(&pdev->dev, sizeof(*mdwc), GFP_KERNEL);
+ if (!mdwc) {
dev_err(&pdev->dev, "not enough memory\n");
return -ENOMEM;
}
- platform_set_drvdata(pdev, msm);
- context = msm;
- msm->dev = &pdev->dev;
+ platform_set_drvdata(pdev, mdwc);
+ mdwc->dev = &pdev->dev;
- INIT_LIST_HEAD(&msm->req_complete_list);
- INIT_DELAYED_WORK(&msm->chg_work, dwc3_chg_detect_work);
- INIT_DELAYED_WORK(&msm->resume_work, dwc3_resume_work);
- INIT_WORK(&msm->restart_usb_work, dwc3_restart_usb_work);
- INIT_WORK(&msm->id_work, dwc3_id_work);
- INIT_DELAYED_WORK(&msm->init_adc_work, dwc3_init_adc_work);
- init_completion(&msm->ext_chg_wait);
+ INIT_LIST_HEAD(&mdwc->req_complete_list);
+ INIT_DELAYED_WORK(&mdwc->chg_work, dwc3_chg_detect_work);
+ INIT_DELAYED_WORK(&mdwc->resume_work, dwc3_resume_work);
+ INIT_WORK(&mdwc->restart_usb_work, dwc3_restart_usb_work);
+ INIT_WORK(&mdwc->id_work, dwc3_id_work);
+ INIT_DELAYED_WORK(&mdwc->init_adc_work, dwc3_init_adc_work);
+ init_completion(&mdwc->ext_chg_wait);
- ret = dwc3_msm_config_gdsc(msm, 1);
+ ret = dwc3_msm_config_gdsc(mdwc, 1);
if (ret) {
dev_err(&pdev->dev, "unable to configure usb3 gdsc\n");
return ret;
}
- msm->xo_clk = clk_get(&pdev->dev, "xo");
- if (IS_ERR(msm->xo_clk)) {
+ mdwc->xo_clk = clk_get(&pdev->dev, "xo");
+ if (IS_ERR(mdwc->xo_clk)) {
dev_err(&pdev->dev, "%s unable to get TCXO buffer handle\n",
__func__);
- ret = PTR_ERR(msm->xo_clk);
+ ret = PTR_ERR(mdwc->xo_clk);
goto disable_dwc3_gdsc;
}
- ret = clk_prepare_enable(msm->xo_clk);
+ ret = clk_prepare_enable(mdwc->xo_clk);
if (ret) {
dev_err(&pdev->dev, "%s failed to vote for TCXO buffer%d\n",
__func__, ret);
@@ -2591,62 +2602,62 @@
* DWC3 Core requires its CORE CLK (aka master / bus clk) to
* run at 125Mhz in SSUSB mode and >60MHZ for HSUSB mode.
*/
- msm->core_clk = devm_clk_get(&pdev->dev, "core_clk");
- if (IS_ERR(msm->core_clk)) {
+ mdwc->core_clk = devm_clk_get(&pdev->dev, "core_clk");
+ if (IS_ERR(mdwc->core_clk)) {
dev_err(&pdev->dev, "failed to get core_clk\n");
- ret = PTR_ERR(msm->core_clk);
+ ret = PTR_ERR(mdwc->core_clk);
goto disable_xo;
}
- clk_set_rate(msm->core_clk, 125000000);
- clk_prepare_enable(msm->core_clk);
+ clk_set_rate(mdwc->core_clk, 125000000);
+ clk_prepare_enable(mdwc->core_clk);
- msm->iface_clk = devm_clk_get(&pdev->dev, "iface_clk");
- if (IS_ERR(msm->iface_clk)) {
+ mdwc->iface_clk = devm_clk_get(&pdev->dev, "iface_clk");
+ if (IS_ERR(mdwc->iface_clk)) {
dev_err(&pdev->dev, "failed to get iface_clk\n");
- ret = PTR_ERR(msm->iface_clk);
+ ret = PTR_ERR(mdwc->iface_clk);
goto disable_core_clk;
}
- clk_prepare_enable(msm->iface_clk);
+ clk_prepare_enable(mdwc->iface_clk);
- msm->sleep_clk = devm_clk_get(&pdev->dev, "sleep_clk");
- if (IS_ERR(msm->sleep_clk)) {
+ mdwc->sleep_clk = devm_clk_get(&pdev->dev, "sleep_clk");
+ if (IS_ERR(mdwc->sleep_clk)) {
dev_err(&pdev->dev, "failed to get sleep_clk\n");
- ret = PTR_ERR(msm->sleep_clk);
+ ret = PTR_ERR(mdwc->sleep_clk);
goto disable_iface_clk;
}
- clk_prepare_enable(msm->sleep_clk);
+ clk_prepare_enable(mdwc->sleep_clk);
- msm->hsphy_sleep_clk = devm_clk_get(&pdev->dev, "sleep_a_clk");
- if (IS_ERR(msm->hsphy_sleep_clk)) {
+ mdwc->hsphy_sleep_clk = devm_clk_get(&pdev->dev, "sleep_a_clk");
+ if (IS_ERR(mdwc->hsphy_sleep_clk)) {
dev_err(&pdev->dev, "failed to get sleep_a_clk\n");
- ret = PTR_ERR(msm->hsphy_sleep_clk);
+ ret = PTR_ERR(mdwc->hsphy_sleep_clk);
goto disable_sleep_clk;
}
- clk_prepare_enable(msm->hsphy_sleep_clk);
+ clk_prepare_enable(mdwc->hsphy_sleep_clk);
- msm->utmi_clk = devm_clk_get(&pdev->dev, "utmi_clk");
- if (IS_ERR(msm->utmi_clk)) {
+ mdwc->utmi_clk = devm_clk_get(&pdev->dev, "utmi_clk");
+ if (IS_ERR(mdwc->utmi_clk)) {
dev_err(&pdev->dev, "failed to get utmi_clk\n");
- ret = PTR_ERR(msm->utmi_clk);
+ ret = PTR_ERR(mdwc->utmi_clk);
goto disable_sleep_a_clk;
}
- clk_prepare_enable(msm->utmi_clk);
+ clk_prepare_enable(mdwc->utmi_clk);
- msm->ref_clk = devm_clk_get(&pdev->dev, "ref_clk");
- if (IS_ERR(msm->ref_clk)) {
+ mdwc->ref_clk = devm_clk_get(&pdev->dev, "ref_clk");
+ if (IS_ERR(mdwc->ref_clk)) {
dev_err(&pdev->dev, "failed to get ref_clk\n");
- ret = PTR_ERR(msm->ref_clk);
+ ret = PTR_ERR(mdwc->ref_clk);
goto disable_utmi_clk;
}
- clk_prepare_enable(msm->ref_clk);
+ clk_prepare_enable(mdwc->ref_clk);
of_get_property(node, "qcom,vdd-voltage-level", &len);
if (len == sizeof(tmp)) {
of_property_read_u32_array(node, "qcom,vdd-voltage-level",
tmp, len/sizeof(*tmp));
- msm->vdd_no_vol_level = tmp[0];
- msm->vdd_low_vol_level = tmp[1];
- msm->vdd_high_vol_level = tmp[2];
+ mdwc->vdd_no_vol_level = tmp[0];
+ mdwc->vdd_low_vol_level = tmp[1];
+ mdwc->vdd_high_vol_level = tmp[2];
} else {
dev_err(&pdev->dev, "no qcom,vdd-voltage-level property\n");
ret = -EINVAL;
@@ -2654,99 +2665,100 @@
}
/* SS PHY */
- msm->ssusb_vddcx = devm_regulator_get(&pdev->dev, "ssusb_vdd_dig");
- if (IS_ERR(msm->ssusb_vddcx)) {
+ mdwc->ssusb_vddcx = devm_regulator_get(&pdev->dev, "ssusb_vdd_dig");
+ if (IS_ERR(mdwc->ssusb_vddcx)) {
dev_err(&pdev->dev, "unable to get ssusb vddcx\n");
- ret = PTR_ERR(msm->ssusb_vddcx);
+ ret = PTR_ERR(mdwc->ssusb_vddcx);
goto disable_ref_clk;
}
- ret = dwc3_ssusb_config_vddcx(1);
+ ret = dwc3_ssusb_config_vddcx(mdwc, 1);
if (ret) {
dev_err(&pdev->dev, "ssusb vddcx configuration failed\n");
goto disable_ref_clk;
}
- ret = regulator_enable(context->ssusb_vddcx);
+ ret = regulator_enable(mdwc->ssusb_vddcx);
if (ret) {
dev_err(&pdev->dev, "unable to enable the ssusb vddcx\n");
goto unconfig_ss_vddcx;
}
- ret = dwc3_ssusb_ldo_init(1);
+ ret = dwc3_ssusb_ldo_init(mdwc, 1);
if (ret) {
dev_err(&pdev->dev, "ssusb vreg configuration failed\n");
goto disable_ss_vddcx;
}
- ret = dwc3_ssusb_ldo_enable(1);
+ ret = dwc3_ssusb_ldo_enable(mdwc, 1);
if (ret) {
dev_err(&pdev->dev, "ssusb vreg enable failed\n");
goto free_ss_ldo_init;
}
/* HS PHY */
- msm->hsusb_vddcx = devm_regulator_get(&pdev->dev, "hsusb_vdd_dig");
- if (IS_ERR(msm->hsusb_vddcx)) {
+ mdwc->hsusb_vddcx = devm_regulator_get(&pdev->dev, "hsusb_vdd_dig");
+ if (IS_ERR(mdwc->hsusb_vddcx)) {
dev_err(&pdev->dev, "unable to get hsusb vddcx\n");
- ret = PTR_ERR(msm->hsusb_vddcx);
+ ret = PTR_ERR(mdwc->hsusb_vddcx);
goto disable_ss_ldo;
}
- ret = dwc3_hsusb_config_vddcx(1);
+ ret = dwc3_hsusb_config_vddcx(mdwc, 1);
if (ret) {
dev_err(&pdev->dev, "hsusb vddcx configuration failed\n");
goto disable_ss_ldo;
}
- ret = regulator_enable(context->hsusb_vddcx);
+ ret = regulator_enable(mdwc->hsusb_vddcx);
if (ret) {
dev_err(&pdev->dev, "unable to enable the hsusb vddcx\n");
goto unconfig_hs_vddcx;
}
- ret = dwc3_hsusb_ldo_init(1);
+ ret = dwc3_hsusb_ldo_init(mdwc, 1);
if (ret) {
dev_err(&pdev->dev, "hsusb vreg configuration failed\n");
goto disable_hs_vddcx;
}
- ret = dwc3_hsusb_ldo_enable(1);
+ ret = dwc3_hsusb_ldo_enable(mdwc, 1);
if (ret) {
dev_err(&pdev->dev, "hsusb vreg enable failed\n");
goto free_hs_ldo_init;
}
- msm->id_state = msm->ext_xceiv.id = DWC3_ID_FLOAT;
- msm->ext_xceiv.otg_capability = of_property_read_bool(node,
+ mdwc->id_state = mdwc->ext_xceiv.id = DWC3_ID_FLOAT;
+ mdwc->ext_xceiv.otg_capability = of_property_read_bool(node,
"qcom,otg-capability");
- msm->charger.charging_disabled = of_property_read_bool(node,
+ mdwc->charger.charging_disabled = of_property_read_bool(node,
"qcom,charging-disabled");
- msm->charger.skip_chg_detect = of_property_read_bool(node,
+ mdwc->charger.skip_chg_detect = of_property_read_bool(node,
"qcom,skip-charger-detection");
/*
* DWC3 has separate IRQ line for OTG events (ID/BSV) and for
* DP and DM linestate transitions during low power mode.
*/
- msm->hs_phy_irq = platform_get_irq_byname(pdev, "hs_phy_irq");
- if (msm->hs_phy_irq < 0) {
+ mdwc->hs_phy_irq = platform_get_irq_byname(pdev, "hs_phy_irq");
+ if (mdwc->hs_phy_irq < 0) {
dev_dbg(&pdev->dev, "pget_irq for hs_phy_irq failed\n");
- msm->hs_phy_irq = 0;
+ mdwc->hs_phy_irq = 0;
} else {
- ret = devm_request_irq(&pdev->dev, msm->hs_phy_irq,
+ ret = devm_request_irq(&pdev->dev, mdwc->hs_phy_irq,
msm_dwc3_irq, IRQF_TRIGGER_RISING,
- "msm_dwc3", msm);
+ "msm_dwc3", mdwc);
if (ret) {
dev_err(&pdev->dev, "irqreq HSPHYINT failed\n");
goto disable_hs_ldo;
}
- enable_irq_wake(msm->hs_phy_irq);
+ enable_irq_wake(mdwc->hs_phy_irq);
}
- if (msm->ext_xceiv.otg_capability) {
- msm->pmic_id_irq = platform_get_irq_byname(pdev, "pmic_id_irq");
- if (msm->pmic_id_irq > 0) {
+ if (mdwc->ext_xceiv.otg_capability) {
+ mdwc->pmic_id_irq =
+ platform_get_irq_byname(pdev, "pmic_id_irq");
+ if (mdwc->pmic_id_irq > 0) {
/* check if PMIC ID IRQ is supported */
ret = qpnp_misc_irqs_available(&pdev->dev);
@@ -2754,14 +2766,15 @@
/* qpnp hasn't probed yet; defer dwc probe */
goto disable_hs_ldo;
} else if (ret == 0) {
- msm->pmic_id_irq = 0;
+ mdwc->pmic_id_irq = 0;
} else {
ret = devm_request_irq(&pdev->dev,
- msm->pmic_id_irq,
+ mdwc->pmic_id_irq,
dwc3_pmic_id_irq,
IRQF_TRIGGER_RISING |
IRQF_TRIGGER_FALLING,
- "dwc3_msm_pmic_id", msm);
+ "dwc3_msm_pmic_id",
+ mdwc);
if (ret) {
dev_err(&pdev->dev, "irqreq IDINT failed\n");
goto disable_hs_ldo;
@@ -2769,21 +2782,21 @@
local_irq_save(flags);
/* Update initial ID state */
- msm->id_state =
- !!irq_read_line(msm->pmic_id_irq);
- if (msm->id_state == DWC3_ID_GROUND)
+ mdwc->id_state =
+ !!irq_read_line(mdwc->pmic_id_irq);
+ if (mdwc->id_state == DWC3_ID_GROUND)
queue_work(system_nrt_wq,
- &msm->id_work);
+ &mdwc->id_work);
local_irq_restore(flags);
- enable_irq_wake(msm->pmic_id_irq);
+ enable_irq_wake(mdwc->pmic_id_irq);
}
}
- if (msm->pmic_id_irq <= 0) {
+ if (mdwc->pmic_id_irq <= 0) {
/* If no PMIC ID IRQ, use ADC for ID pin detection */
- queue_work(system_nrt_wq, &msm->init_adc_work.work);
+ queue_work(system_nrt_wq, &mdwc->init_adc_work.work);
device_create_file(&pdev->dev, &dev_attr_adc_enable);
- msm->pmic_id_irq = 0;
+ mdwc->pmic_id_irq = 0;
}
}
@@ -2813,59 +2826,60 @@
goto disable_hs_ldo;
}
- msm->base = devm_ioremap_nocache(&pdev->dev, res->start,
+ mdwc->base = devm_ioremap_nocache(&pdev->dev, res->start,
resource_size(res));
- if (!msm->base) {
+ if (!mdwc->base) {
dev_err(&pdev->dev, "ioremap failed\n");
ret = -ENODEV;
goto disable_hs_ldo;
}
- msm->io_res = res; /* used to calculate chg block offset */
+ mdwc->io_res = res; /* used to calculate chg block offset */
if (of_property_read_u32(node, "qcom,dwc-hsphy-init",
- &msm->hsphy_init_seq))
+ &mdwc->hsphy_init_seq))
dev_dbg(&pdev->dev, "unable to read hsphy init seq\n");
- else if (!msm->hsphy_init_seq)
+ else if (!mdwc->hsphy_init_seq)
dev_warn(&pdev->dev, "incorrect hsphyinitseq.Using PORvalue\n");
- dwc3_msm_qscratch_reg_init(msm);
+ dwc3_msm_qscratch_reg_init(mdwc);
- pm_runtime_set_active(msm->dev);
- pm_runtime_enable(msm->dev);
+ pm_runtime_set_active(mdwc->dev);
+ pm_runtime_enable(mdwc->dev);
if (of_property_read_u32(node, "qcom,dwc-usb3-msm-dbm-eps",
- &msm->dbm_num_eps)) {
+ &mdwc->dbm_num_eps)) {
dev_err(&pdev->dev,
"unable to read platform data num of dbm eps\n");
- msm->dbm_num_eps = DBM_MAX_EPS;
+ mdwc->dbm_num_eps = DBM_MAX_EPS;
}
- if (msm->dbm_num_eps > DBM_MAX_EPS) {
+ if (mdwc->dbm_num_eps > DBM_MAX_EPS) {
dev_err(&pdev->dev,
"Driver doesn't support number of DBM EPs. "
"max: %d, dbm_num_eps: %d\n",
- DBM_MAX_EPS, msm->dbm_num_eps);
+ DBM_MAX_EPS, mdwc->dbm_num_eps);
ret = -ENODEV;
goto disable_hs_ldo;
}
/* usb_psy required only for vbus_notifications or charging support */
- if (msm->ext_xceiv.otg_capability || !msm->charger.charging_disabled) {
- msm->usb_psy.name = "usb";
- msm->usb_psy.type = POWER_SUPPLY_TYPE_USB;
- msm->usb_psy.supplied_to = dwc3_msm_pm_power_supplied_to;
- msm->usb_psy.num_supplicants = ARRAY_SIZE(
+ if (mdwc->ext_xceiv.otg_capability ||
+ !mdwc->charger.charging_disabled) {
+ mdwc->usb_psy.name = "usb";
+ mdwc->usb_psy.type = POWER_SUPPLY_TYPE_USB;
+ mdwc->usb_psy.supplied_to = dwc3_msm_pm_power_supplied_to;
+ mdwc->usb_psy.num_supplicants = ARRAY_SIZE(
dwc3_msm_pm_power_supplied_to);
- msm->usb_psy.properties = dwc3_msm_pm_power_props_usb;
- msm->usb_psy.num_properties =
+ mdwc->usb_psy.properties = dwc3_msm_pm_power_props_usb;
+ mdwc->usb_psy.num_properties =
ARRAY_SIZE(dwc3_msm_pm_power_props_usb);
- msm->usb_psy.get_property = dwc3_msm_power_get_property_usb;
- msm->usb_psy.set_property = dwc3_msm_power_set_property_usb;
- msm->usb_psy.external_power_changed =
+ mdwc->usb_psy.get_property = dwc3_msm_power_get_property_usb;
+ mdwc->usb_psy.set_property = dwc3_msm_power_set_property_usb;
+ mdwc->usb_psy.external_power_changed =
dwc3_msm_external_power_changed;
- ret = power_supply_register(&pdev->dev, &msm->usb_psy);
+ ret = power_supply_register(&pdev->dev, &mdwc->usb_psy);
if (ret < 0) {
dev_err(&pdev->dev,
"%s:power_supply_register usb failed\n",
@@ -2883,27 +2897,28 @@
}
}
- msm->bus_scale_table = msm_bus_cl_get_pdata(pdev);
- if (!msm->bus_scale_table) {
+ mdwc->bus_scale_table = msm_bus_cl_get_pdata(pdev);
+ if (!mdwc->bus_scale_table) {
dev_err(&pdev->dev, "bus scaling is disabled\n");
} else {
- msm->bus_perf_client =
- msm_bus_scale_register_client(msm->bus_scale_table);
+ mdwc->bus_perf_client =
+ msm_bus_scale_register_client(mdwc->bus_scale_table);
ret = msm_bus_scale_client_update_request(
- msm->bus_perf_client, 1);
+ mdwc->bus_perf_client, 1);
if (ret)
dev_err(&pdev->dev, "Failed to vote for bus scaling\n");
}
- msm->otg_xceiv = usb_get_transceiver();
+ mdwc->otg_xceiv = usb_get_transceiver();
/* Register with OTG if present, ignore USB2 OTG using other PHY */
- if (msm->otg_xceiv && !(msm->otg_xceiv->flags & ENABLE_SECONDARY_PHY)) {
+ if (mdwc->otg_xceiv &&
+ !(mdwc->otg_xceiv->flags & ENABLE_SECONDARY_PHY)) {
/* Skip charger detection for simulator targets */
- if (!msm->charger.skip_chg_detect) {
- msm->charger.start_detection = dwc3_start_chg_det;
- ret = dwc3_set_charger(msm->otg_xceiv->otg,
- &msm->charger);
- if (ret || !msm->charger.notify_detection_complete) {
+ if (!mdwc->charger.skip_chg_detect) {
+ mdwc->charger.start_detection = dwc3_start_chg_det;
+ ret = dwc3_set_charger(mdwc->otg_xceiv->otg,
+ &mdwc->charger);
+ if (ret || !mdwc->charger.notify_detection_complete) {
dev_err(&pdev->dev,
"failed to register charger: %d\n",
ret);
@@ -2911,129 +2926,130 @@
}
}
- if (msm->ext_xceiv.otg_capability)
- msm->ext_xceiv.ext_block_reset = dwc3_msm_block_reset;
- ret = dwc3_set_ext_xceiv(msm->otg_xceiv->otg, &msm->ext_xceiv);
- if (ret || !msm->ext_xceiv.notify_ext_events) {
+ if (mdwc->ext_xceiv.otg_capability)
+ mdwc->ext_xceiv.ext_block_reset = dwc3_msm_block_reset;
+ ret = dwc3_set_ext_xceiv(mdwc->otg_xceiv->otg,
+ &mdwc->ext_xceiv);
+ if (ret || !mdwc->ext_xceiv.notify_ext_events) {
dev_err(&pdev->dev, "failed to register xceiver: %d\n",
ret);
goto put_xcvr;
}
} else {
dev_dbg(&pdev->dev, "No OTG, DWC3 running in host only mode\n");
- msm->host_mode = 1;
- msm->vbus_otg = devm_regulator_get(&pdev->dev, "vbus_dwc3");
- if (IS_ERR(msm->vbus_otg)) {
+ mdwc->host_mode = 1;
+ mdwc->vbus_otg = devm_regulator_get(&pdev->dev, "vbus_dwc3");
+ if (IS_ERR(mdwc->vbus_otg)) {
dev_dbg(&pdev->dev, "Failed to get vbus regulator\n");
- msm->vbus_otg = 0;
+ mdwc->vbus_otg = 0;
} else {
- ret = regulator_enable(msm->vbus_otg);
+ ret = regulator_enable(mdwc->vbus_otg);
if (ret) {
- msm->vbus_otg = 0;
+ mdwc->vbus_otg = 0;
dev_err(&pdev->dev, "Failed to enable vbus_otg\n");
}
}
- msm->otg_xceiv = NULL;
+ mdwc->otg_xceiv = NULL;
}
- if (msm->ext_xceiv.otg_capability && msm->charger.start_detection) {
- ret = dwc3_msm_setup_cdev(msm);
+ if (mdwc->ext_xceiv.otg_capability && mdwc->charger.start_detection) {
+ ret = dwc3_msm_setup_cdev(mdwc);
if (ret)
dev_err(&pdev->dev, "Fail to setup dwc3 setup cdev\n");
}
- wake_lock_init(&msm->wlock, WAKE_LOCK_SUSPEND, "msm_dwc3");
- wake_lock(&msm->wlock);
- dwc3_debugfs_init(msm);
+ device_init_wakeup(mdwc->dev, 1);
+ pm_stay_awake(mdwc->dev);
+ dwc3_debugfs_init(mdwc);
return 0;
put_xcvr:
- usb_put_transceiver(msm->otg_xceiv);
+ usb_put_transceiver(mdwc->otg_xceiv);
put_psupply:
- if (msm->usb_psy.dev)
- power_supply_unregister(&msm->usb_psy);
+ if (mdwc->usb_psy.dev)
+ power_supply_unregister(&mdwc->usb_psy);
disable_hs_ldo:
- dwc3_hsusb_ldo_enable(0);
+ dwc3_hsusb_ldo_enable(mdwc, 0);
free_hs_ldo_init:
- dwc3_hsusb_ldo_init(0);
+ dwc3_hsusb_ldo_init(mdwc, 0);
disable_hs_vddcx:
- regulator_disable(context->hsusb_vddcx);
+ regulator_disable(mdwc->hsusb_vddcx);
unconfig_hs_vddcx:
- dwc3_hsusb_config_vddcx(0);
+ dwc3_hsusb_config_vddcx(mdwc, 0);
disable_ss_ldo:
- dwc3_ssusb_ldo_enable(0);
+ dwc3_ssusb_ldo_enable(mdwc, 0);
free_ss_ldo_init:
- dwc3_ssusb_ldo_init(0);
+ dwc3_ssusb_ldo_init(mdwc, 0);
disable_ss_vddcx:
- regulator_disable(context->ssusb_vddcx);
+ regulator_disable(mdwc->ssusb_vddcx);
unconfig_ss_vddcx:
- dwc3_ssusb_config_vddcx(0);
+ dwc3_ssusb_config_vddcx(mdwc, 0);
disable_ref_clk:
- clk_disable_unprepare(msm->ref_clk);
+ clk_disable_unprepare(mdwc->ref_clk);
disable_utmi_clk:
- clk_disable_unprepare(msm->utmi_clk);
+ clk_disable_unprepare(mdwc->utmi_clk);
disable_sleep_a_clk:
- clk_disable_unprepare(msm->hsphy_sleep_clk);
+ clk_disable_unprepare(mdwc->hsphy_sleep_clk);
disable_sleep_clk:
- clk_disable_unprepare(msm->sleep_clk);
+ clk_disable_unprepare(mdwc->sleep_clk);
disable_iface_clk:
- clk_disable_unprepare(msm->iface_clk);
+ clk_disable_unprepare(mdwc->iface_clk);
disable_core_clk:
- clk_disable_unprepare(msm->core_clk);
+ clk_disable_unprepare(mdwc->core_clk);
disable_xo:
- clk_disable_unprepare(msm->xo_clk);
+ clk_disable_unprepare(mdwc->xo_clk);
put_xo:
- clk_put(msm->xo_clk);
+ clk_put(mdwc->xo_clk);
disable_dwc3_gdsc:
- dwc3_msm_config_gdsc(msm, 0);
+ dwc3_msm_config_gdsc(mdwc, 0);
return ret;
}
static int __devexit dwc3_msm_remove(struct platform_device *pdev)
{
- struct dwc3_msm *msm = platform_get_drvdata(pdev);
+ struct dwc3_msm *mdwc = platform_get_drvdata(pdev);
- if (!msm->ext_chg_device) {
- device_destroy(msm->ext_chg_class, msm->ext_chg_dev);
- cdev_del(&msm->ext_chg_cdev);
- class_destroy(msm->ext_chg_class);
- unregister_chrdev_region(msm->ext_chg_dev, 1);
+ if (!mdwc->ext_chg_device) {
+ device_destroy(mdwc->ext_chg_class, mdwc->ext_chg_dev);
+ cdev_del(&mdwc->ext_chg_cdev);
+ class_destroy(mdwc->ext_chg_class);
+ unregister_chrdev_region(mdwc->ext_chg_dev, 1);
}
- if (msm->id_adc_detect)
+ if (mdwc->id_adc_detect)
qpnp_adc_tm_usbid_end();
if (dwc3_debugfs_root)
debugfs_remove_recursive(dwc3_debugfs_root);
- if (msm->otg_xceiv) {
- dwc3_start_chg_det(&msm->charger, false);
- usb_put_transceiver(msm->otg_xceiv);
+ if (mdwc->otg_xceiv) {
+ dwc3_start_chg_det(&mdwc->charger, false);
+ usb_put_transceiver(mdwc->otg_xceiv);
}
- if (msm->usb_psy.dev)
- power_supply_unregister(&msm->usb_psy);
- if (msm->vbus_otg)
- regulator_disable(msm->vbus_otg);
+ if (mdwc->usb_psy.dev)
+ power_supply_unregister(&mdwc->usb_psy);
+ if (mdwc->vbus_otg)
+ regulator_disable(mdwc->vbus_otg);
- pm_runtime_disable(msm->dev);
- wake_lock_destroy(&msm->wlock);
+ pm_runtime_disable(mdwc->dev);
+ device_init_wakeup(mdwc->dev, 0);
- dwc3_hsusb_ldo_enable(0);
- dwc3_hsusb_ldo_init(0);
- regulator_disable(msm->hsusb_vddcx);
- dwc3_hsusb_config_vddcx(0);
- dwc3_ssusb_ldo_enable(0);
- dwc3_ssusb_ldo_init(0);
- regulator_disable(msm->ssusb_vddcx);
- dwc3_ssusb_config_vddcx(0);
- clk_disable_unprepare(msm->core_clk);
- clk_disable_unprepare(msm->iface_clk);
- clk_disable_unprepare(msm->sleep_clk);
- clk_disable_unprepare(msm->hsphy_sleep_clk);
- clk_disable_unprepare(msm->ref_clk);
- clk_disable_unprepare(msm->xo_clk);
- clk_put(msm->xo_clk);
+ dwc3_hsusb_ldo_enable(mdwc, 0);
+ dwc3_hsusb_ldo_init(mdwc, 0);
+ regulator_disable(mdwc->hsusb_vddcx);
+ dwc3_hsusb_config_vddcx(mdwc, 0);
+ dwc3_ssusb_ldo_enable(mdwc, 0);
+ dwc3_ssusb_ldo_init(mdwc, 0);
+ regulator_disable(mdwc->ssusb_vddcx);
+ dwc3_ssusb_config_vddcx(mdwc, 0);
+ clk_disable_unprepare(mdwc->core_clk);
+ clk_disable_unprepare(mdwc->iface_clk);
+ clk_disable_unprepare(mdwc->sleep_clk);
+ clk_disable_unprepare(mdwc->hsphy_sleep_clk);
+ clk_disable_unprepare(mdwc->ref_clk);
+ clk_disable_unprepare(mdwc->xo_clk);
+ clk_put(mdwc->xo_clk);
- dwc3_msm_config_gdsc(msm, 0);
+ dwc3_msm_config_gdsc(mdwc, 0);
return 0;
}
diff --git a/drivers/usb/dwc3/dwc3_otg.c b/drivers/usb/dwc3/dwc3_otg.c
index 1bc7757..a7bea63 100644
--- a/drivers/usb/dwc3/dwc3_otg.c
+++ b/drivers/usb/dwc3/dwc3_otg.c
@@ -218,7 +218,7 @@
*/
if (ext_xceiv && ext_xceiv->otg_capability &&
ext_xceiv->ext_block_reset)
- ext_xceiv->ext_block_reset(true);
+ ext_xceiv->ext_block_reset(ext_xceiv, true);
dwc3_otg_set_peripheral_regs(dotg);
@@ -285,7 +285,7 @@
* DBM reset is required, hence perform only DBM reset here */
if (ext_xceiv && ext_xceiv->otg_capability &&
ext_xceiv->ext_block_reset)
- ext_xceiv->ext_block_reset(false);
+ ext_xceiv->ext_block_reset(ext_xceiv, false);
dwc3_otg_set_peripheral_regs(dotg);
usb_gadget_vbus_connect(otg->gadget);
diff --git a/drivers/usb/dwc3/dwc3_otg.h b/drivers/usb/dwc3/dwc3_otg.h
index 28573a1..7adf874 100644
--- a/drivers/usb/dwc3/dwc3_otg.h
+++ b/drivers/usb/dwc3/dwc3_otg.h
@@ -114,7 +114,8 @@
void (*notify_ext_events)(struct usb_otg *otg,
enum dwc3_ext_events ext_event);
/* for block reset USB core */
- void (*ext_block_reset)(bool core_reset);
+ void (*ext_block_reset)(struct dwc3_ext_xceiv *ext_xceiv,
+ bool core_reset);
};
/* for external transceiver driver */
diff --git a/drivers/usb/gadget/f_qdss.c b/drivers/usb/gadget/f_qdss.c
index cece500..f90967f 100644
--- a/drivers/usb/gadget/f_qdss.c
+++ b/drivers/usb/gadget/f_qdss.c
@@ -790,6 +790,7 @@
void usb_qdss_close(struct usb_qdss_ch *ch)
{
struct f_qdss *qdss = ch->priv_usb;
+ struct usb_gadget *gadget = qdss->cdev->gadget;
unsigned long flags;
pr_debug("usb_qdss_close\n");
@@ -801,7 +802,7 @@
ch->app_conn = 0;
spin_unlock_irqrestore(&d_lock, flags);
- msm_dwc3_restart_usb_session();
+ msm_dwc3_restart_usb_session(gadget);
}
EXPORT_SYMBOL(usb_qdss_close);
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 2a98e49..fa1932b 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -36,6 +36,7 @@
#include <linux/usb/quirks.h>
#include <linux/usb/msm_hsusb.h>
#include <linux/usb/msm_hsusb_hw.h>
+#include <linux/usb/msm_ext_chg.h>
#include <linux/regulator/consumer.h>
#include <linux/mfd/pm8xxx/pm8921-charger.h>
#include <linux/mfd/pm8xxx/misc.h>
@@ -888,7 +889,7 @@
bool floated_charger;
u32 phy_ctrl_val = 0, cmd_val;
unsigned ret;
- u32 portsc;
+ u32 portsc, config2;
if (atomic_read(&motg->in_lpm))
return 0;
@@ -906,6 +907,17 @@
prop_charger = motg->chg_type == USB_PROPRIETARY_CHARGER;
floated_charger = motg->chg_type == USB_FLOATED_CHARGER;
+ /* Enable line state difference wakeup fix for only device and host
+ * bus suspend scenarios. Otherwise PHY can not be suspended when
+ * a charger that pulls DP/DM high is connected.
+ */
+ config2 = readl_relaxed(USB_GENCONFIG2);
+ if (device_bus_suspend)
+ config2 |= GENCFG2_LINESTATE_DIFF_WAKEUP_EN;
+ else
+ config2 &= ~GENCFG2_LINESTATE_DIFF_WAKEUP_EN;
+ writel_relaxed(config2, USB_GENCONFIG2);
+
/*
* Abort suspend when,
* 1. charging detection in progress due to cable plug-in
@@ -2450,11 +2462,46 @@
}
}
+static void msm_otg_wait_for_ext_chg_done(struct msm_otg *motg)
+{
+ struct usb_phy *phy = &motg->phy;
+ unsigned long t;
+
+ /*
+ * Defer next cable connect event till external charger
+ * detection is completed.
+ */
+
+ if (motg->ext_chg_active) {
+
+ pr_debug("before msm_otg ext chg wait\n");
+
+ t = wait_for_completion_timeout(&motg->ext_chg_wait,
+ msecs_to_jiffies(3000));
+ if (!t)
+ pr_err("msm_otg ext chg wait timeout\n");
+ else
+ pr_debug("msm_otg ext chg wait done\n");
+ }
+
+ if (motg->ext_chg_opened) {
+ if (phy->flags & ENABLE_DP_MANUAL_PULLUP) {
+ ulpi_write(phy, ULPI_MISC_A_VBUSVLDEXT |
+ ULPI_MISC_A_VBUSVLDEXTSEL,
+ ULPI_CLR(ULPI_MISC_A));
+ }
+ /* clear charging register bits */
+ ulpi_write(phy, 0x3F, 0x86);
+ /* re-enable DP and DM pull-down resistors*/
+ ulpi_write(phy, 0x6, 0xB);
+ }
+}
+
static void msm_otg_sm_work(struct work_struct *w)
{
struct msm_otg *motg = container_of(w, struct msm_otg, sm_work);
struct usb_otg *otg = motg->phy.otg;
- bool work = 0, srp_reqd;
+ bool work = 0, srp_reqd, dcp;
pm_runtime_resume(otg->phy->dev);
pr_debug("%s work\n", otg_state_string(otg->phy->state));
@@ -2504,12 +2551,16 @@
case USB_DCP_CHARGER:
/* Enable VDP_SRC */
ulpi_write(otg->phy, 0x2, 0x85);
+ if (motg->ext_chg_opened) {
+ init_completion(
+ &motg->ext_chg_wait);
+ motg->ext_chg_active = true;
+ }
/* fall through */
case USB_PROPRIETARY_CHARGER:
msm_otg_notify_charger(motg,
IDEV_CHG_MAX);
- pm_runtime_put_noidle(otg->phy->dev);
- pm_runtime_suspend(otg->phy->dev);
+ pm_runtime_put_sync(otg->phy->dev);
break;
case USB_FLOATED_CHARGER:
msm_otg_notify_charger(motg,
@@ -2569,9 +2620,12 @@
clear_bit(B_FALSE_SDP, &motg->inputs);
clear_bit(A_BUS_REQ, &motg->inputs);
cancel_delayed_work_sync(&motg->chg_work);
+ dcp = (motg->chg_type == USB_DCP_CHARGER);
motg->chg_state = USB_CHG_STATE_UNDEFINED;
motg->chg_type = USB_INVALID_CHARGER;
msm_otg_notify_charger(motg, 0);
+ if (dcp)
+ msm_otg_wait_for_ext_chg_done(motg);
msm_otg_reset(otg->phy);
/*
* There is a small window where ID interrupt
@@ -3554,6 +3608,9 @@
case POWER_SUPPLY_PROP_ONLINE:
val->intval = motg->online;
break;
+ case POWER_SUPPLY_PROP_TYPE:
+ val->intval = psy->type;
+ break;
default:
return -EINVAL;
}
@@ -3578,6 +3635,9 @@
case POWER_SUPPLY_PROP_CURRENT_MAX:
motg->current_max = val->intval;
break;
+ case POWER_SUPPLY_PROP_TYPE:
+ psy->type = val->intval;
+ break;
default:
return -EINVAL;
}
@@ -3610,6 +3670,7 @@
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_CURRENT_MAX,
POWER_SUPPLY_PROP_SCOPE,
+ POWER_SUPPLY_PROP_TYPE,
};
const struct file_operations msm_otg_bus_fops = {
@@ -3830,6 +3891,168 @@
return 0;
}
+static int msm_otg_ext_chg_open(struct inode *inode, struct file *file)
+{
+ struct msm_otg *motg = the_msm_otg;
+
+ pr_debug("msm_otg ext chg open\n");
+
+ motg->ext_chg_opened = true;
+ file->private_data = (void *)motg;
+ return 0;
+}
+
+static long
+msm_otg_ext_chg_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct msm_otg *motg = file->private_data;
+ struct msm_usb_chg_info info = {0};
+ int ret = 0, val;
+
+ switch (cmd) {
+ case MSM_USB_EXT_CHG_INFO:
+ info.chg_block_type = USB_CHG_BLOCK_ULPI;
+ info.page_offset = motg->io_res->start & ~PAGE_MASK;
+ /* mmap() works on PAGE granularity */
+ info.length = PAGE_SIZE;
+
+ if (copy_to_user((void __user *)arg, &info, sizeof(info))) {
+ pr_err("%s: copy to user failed\n\n", __func__);
+ ret = -EFAULT;
+ }
+ break;
+ case MSM_USB_EXT_CHG_BLOCK_LPM:
+ if (get_user(val, (int __user *)arg)) {
+ pr_err("%s: get_user failed\n\n", __func__);
+ ret = -EFAULT;
+ break;
+ }
+ pr_debug("%s: LPM block request %d\n", __func__, val);
+ if (val) { /* block LPM */
+ if (motg->chg_type == USB_DCP_CHARGER) {
+ /*
+ * If device is already suspended, resume it.
+ * The PM usage counter is incremented in
+ * runtime resume method. if device is not
+ * suspended, cancel the scheduled suspend
+ * and increment the PM usage counter.
+ */
+ if (pm_runtime_suspended(motg->phy.dev))
+ pm_runtime_resume(motg->phy.dev);
+ else
+ pm_runtime_get_sync(motg->phy.dev);
+ } else {
+ motg->ext_chg_active = false;
+ complete(&motg->ext_chg_wait);
+ ret = -ENODEV;
+ }
+ } else {
+ motg->ext_chg_active = false;
+ complete(&motg->ext_chg_wait);
+ pm_runtime_put(motg->phy.dev);
+ }
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int msm_otg_ext_chg_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct msm_otg *motg = file->private_data;
+ unsigned long vsize = vma->vm_end - vma->vm_start;
+ int ret;
+
+ if (vma->vm_pgoff || vsize > PAGE_SIZE)
+ return -EINVAL;
+
+ vma->vm_pgoff = __phys_to_pfn(motg->io_res->start);
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+ ret = io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+ vsize, vma->vm_page_prot);
+ if (ret < 0) {
+ pr_err("%s: failed with return val %d\n", __func__, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int msm_otg_ext_chg_release(struct inode *inode, struct file *file)
+{
+ struct msm_otg *motg = file->private_data;
+
+ pr_debug("msm_otg ext chg release\n");
+
+ motg->ext_chg_opened = false;
+
+ return 0;
+}
+
+static const struct file_operations msm_otg_ext_chg_fops = {
+ .owner = THIS_MODULE,
+ .open = msm_otg_ext_chg_open,
+ .unlocked_ioctl = msm_otg_ext_chg_ioctl,
+ .mmap = msm_otg_ext_chg_mmap,
+ .release = msm_otg_ext_chg_release,
+};
+
+static int msm_otg_setup_ext_chg_cdev(struct msm_otg *motg)
+{
+ int ret;
+
+ if (motg->pdata->enable_sec_phy || motg->pdata->mode == USB_HOST ||
+ motg->pdata->otg_control != OTG_PMIC_CONTROL ||
+ psy != &motg->usb_psy) {
+ pr_debug("usb ext chg is not supported by msm otg\n");
+ return -ENODEV;
+ }
+
+ ret = alloc_chrdev_region(&motg->ext_chg_dev, 0, 1, "usb_ext_chg");
+ if (ret < 0) {
+ pr_err("Fail to allocate usb ext char dev region\n");
+ return ret;
+ }
+ motg->ext_chg_class = class_create(THIS_MODULE, "msm_ext_chg");
+ if (ret < 0) {
+ pr_err("Fail to create usb ext chg class\n");
+ goto unreg_chrdev;
+ }
+ cdev_init(&motg->ext_chg_cdev, &msm_otg_ext_chg_fops);
+ motg->ext_chg_cdev.owner = THIS_MODULE;
+
+ ret = cdev_add(&motg->ext_chg_cdev, motg->ext_chg_dev, 1);
+ if (ret < 0) {
+ pr_err("Fail to add usb ext chg cdev\n");
+ goto destroy_class;
+ }
+ motg->ext_chg_device = device_create(motg->ext_chg_class,
+ NULL, motg->ext_chg_dev, NULL,
+ "usb_ext_chg");
+ if (IS_ERR(motg->ext_chg_device)) {
+ pr_err("Fail to create usb ext chg device\n");
+ ret = PTR_ERR(motg->ext_chg_device);
+ motg->ext_chg_device = NULL;
+ goto del_cdev;
+ }
+
+ init_completion(&motg->ext_chg_wait);
+ pr_debug("msm otg ext chg cdev setup success\n");
+ return 0;
+
+del_cdev:
+ cdev_del(&motg->ext_chg_cdev);
+destroy_class:
+ class_destroy(motg->ext_chg_class);
+unreg_chrdev:
+ unregister_chrdev_region(motg->ext_chg_dev, 1);
+
+ return ret;
+}
+
struct msm_otg_platform_data *msm_otg_dt_to_pdata(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
@@ -4031,6 +4254,7 @@
goto put_pclk;
}
+ motg->io_res = res;
motg->regs = ioremap(res->start, resource_size(res));
if (!motg->regs) {
dev_err(&pdev->dev, "ioremap failed\n");
@@ -4294,6 +4518,10 @@
if (legacy_power_supply && pdata->otg_control == OTG_PMIC_CONTROL)
pm8921_charger_register_vbus_sn(&msm_otg_set_vbus_state);
+ ret = msm_otg_setup_ext_chg_cdev(motg);
+ if (ret)
+ dev_dbg(&pdev->dev, "fail to setup cdev\n");
+
return 0;
remove_phy:
@@ -4355,6 +4583,13 @@
if (phy->otg->host || phy->otg->gadget)
return -EBUSY;
+ if (!motg->ext_chg_device) {
+ device_destroy(motg->ext_chg_class, motg->ext_chg_dev);
+ cdev_del(&motg->ext_chg_cdev);
+ class_destroy(motg->ext_chg_class);
+ unregister_chrdev_region(motg->ext_chg_dev, 1);
+ }
+
if (pdev->dev.of_node)
msm_otg_setup_devices(pdev, motg->pdata->mode, false);
if (motg->pdata->otg_control == OTG_PMIC_CONTROL)
@@ -4446,8 +4681,25 @@
if (phy->state == OTG_STATE_UNDEFINED)
return -EAGAIN;
- else
- return 0;
+
+ if (motg->ext_chg_active) {
+ dev_dbg(dev, "Deferring LPM\n");
+ /*
+ * Charger detection may happen in user space.
+ * Delay entering LPM by 3 sec. Otherwise we
+ * have to exit LPM when user space begins
+ * charger detection.
+ *
+ * This timer will be canceled when user space
+ * votes against LPM by incrementing PM usage
+ * counter. We enter low power mode when
+ * PM usage counter is decremented.
+ */
+ pm_schedule_suspend(dev, 3000);
+ return -EAGAIN;
+ }
+
+ return 0;
}
static int msm_otg_runtime_suspend(struct device *dev)
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
index 04cd78c..7edf3d2 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.c
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -871,7 +871,7 @@
ret = session->dma->get_histo(session->dma);
if (ret) {
- pr_err("mdp3_histogram_collect error = %d\n", ret);
+ pr_debug("mdp3_histogram_collect error = %d\n", ret);
return ret;
}
@@ -920,11 +920,53 @@
return ret;
}
+static int mdp3_csc_config(struct mdp3_session_data *session,
+ struct mdp_csc_cfg_data *data)
+{
+ struct mdp3_dma_color_correct_config config;
+ struct mdp3_dma_ccs ccs;
+ int ret = -EINVAL;
+
+ if (!data->csc_data.csc_mv || !data->csc_data.csc_pre_bv ||
+ !data->csc_data.csc_post_bv || !data->csc_data.csc_pre_lv ||
+ !data->csc_data.csc_post_lv) {
+ pr_err("%s : Invalid csc vectors", __func__);
+ return -EINVAL;
+ }
+
+ session->cc_vect_sel = (session->cc_vect_sel + 1) % 2;
+
+ config.ccs_enable = 1;
+ config.ccs_sel = session->cc_vect_sel;
+ config.pre_limit_sel = session->cc_vect_sel;
+ config.post_limit_sel = session->cc_vect_sel;
+ config.pre_bias_sel = session->cc_vect_sel;
+ config.post_bias_sel = session->cc_vect_sel;
+ config.ccs_dirty = true;
+
+ ccs.mv = data->csc_data.csc_mv;
+ ccs.pre_bv = data->csc_data.csc_pre_bv;
+ ccs.post_bv = data->csc_data.csc_post_bv;
+ ccs.pre_lv = data->csc_data.csc_pre_lv;
+ ccs.post_lv = data->csc_data.csc_post_lv;
+
+ mutex_lock(&session->lock);
+ ret = session->dma->config_ccs(session->dma, &config, &ccs);
+ mutex_unlock(&session->lock);
+ return ret;
+}
+
static int mdp3_pp_ioctl(struct msm_fb_data_type *mfd,
void __user *argp)
{
int ret = -EINVAL;
struct msmfb_mdp_pp mdp_pp;
+ struct mdp3_session_data *mdp3_session;
+
+ if (!mfd || !mfd->mdp.private1)
+ return -EINVAL;
+
+ mdp3_session = mfd->mdp.private1;
ret = copy_from_user(&mdp_pp, argp, sizeof(mdp_pp));
if (ret)
@@ -935,6 +977,11 @@
ret = mdp3_bl_scale_config(mfd, (struct mdp_bl_scale_data *)
&mdp_pp.data.bl_scale_data);
break;
+ case mdp_op_csc_cfg:
+ ret = mdp3_csc_config(mdp3_session,
+ &(mdp_pp.data.csc_cfg_data));
+ break;
+
default:
pr_err("Unsupported request to MDP_PP IOCTL.\n");
ret = -EINVAL;
@@ -1022,6 +1069,7 @@
lut_config.lut_enable = 7;
lut_config.lut_sel = mdp3_session->lut_sel;
lut_config.lut_position = 0;
+ lut_config.lut_dirty = true;
lut.color0_lut = r;
lut.color1_lut = g;
lut.color2_lut = b;
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.h b/drivers/video/msm/mdss/mdp3_ctrl.h
index 0bbc2ac..9ea1c91 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.h
+++ b/drivers/video/msm/mdss/mdp3_ctrl.h
@@ -50,6 +50,7 @@
int histo_status;
struct mutex histo_lock;
int lut_sel;
+ int cc_vect_sel;
};
int mdp3_ctrl_init(struct msm_fb_data_type *mfd);
diff --git a/drivers/video/msm/mdss/mdp3_dma.c b/drivers/video/msm/mdss/mdp3_dma.c
index 3b65405..2e9c787 100644
--- a/drivers/video/msm/mdss/mdp3_dma.c
+++ b/drivers/video/msm/mdss/mdp3_dma.c
@@ -219,6 +219,25 @@
}
}
+static void mdp3_dma_clk_auto_gating(struct mdp3_dma *dma, int enable)
+{
+ u32 cgc;
+ int clock_bit = 10;
+
+ clock_bit += dma->dma_sel;
+
+ if (enable) {
+ cgc = MDP3_REG_READ(MDP3_REG_CGC_EN);
+ cgc |= BIT(clock_bit);
+ MDP3_REG_WRITE(MDP3_REG_CGC_EN, cgc);
+
+ } else {
+ cgc = MDP3_REG_READ(MDP3_REG_CGC_EN);
+ cgc &= ~BIT(clock_bit);
+ MDP3_REG_WRITE(MDP3_REG_CGC_EN, cgc);
+ }
+}
+
static int mdp3_dma_sync_config(struct mdp3_dma *dma,
struct mdp3_dma_source *source_config)
{
@@ -347,11 +366,109 @@
return 0;
}
+static void mdp3_ccs_update(struct mdp3_dma *dma)
+{
+ u32 cc_config;
+ int updated = 0;
+
+ cc_config = MDP3_REG_READ(MDP3_REG_DMA_P_COLOR_CORRECT_CONFIG);
+
+ if (dma->ccs_config.ccs_dirty) {
+ cc_config &= DMA_CCS_CONFIG_MASK;
+ if (dma->ccs_config.ccs_enable)
+ cc_config |= BIT(3);
+ else
+ cc_config &= ~BIT(3);
+ cc_config |= dma->ccs_config.ccs_sel << 5;
+ cc_config |= dma->ccs_config.pre_bias_sel << 6;
+ cc_config |= dma->ccs_config.post_bias_sel << 7;
+ cc_config |= dma->ccs_config.pre_limit_sel << 8;
+ cc_config |= dma->ccs_config.post_limit_sel << 9;
+ dma->ccs_config.ccs_dirty = false;
+ updated = 1;
+ }
+
+ if (dma->lut_config.lut_dirty) {
+ cc_config &= DMA_LUT_CONFIG_MASK;
+ cc_config |= dma->lut_config.lut_enable;
+ cc_config |= dma->lut_config.lut_position << 4;
+ cc_config |= dma->lut_config.lut_sel << 10;
+ dma->lut_config.lut_dirty = false;
+ updated = 1;
+ }
+ if (updated) {
+ MDP3_REG_WRITE(MDP3_REG_DMA_P_COLOR_CORRECT_CONFIG, cc_config);
+
+ /* Make sure ccs configuration update is done before continuing
+ with the DMA transfer */
+ wmb();
+ }
+}
+
+static int mdp3_dmap_ccs_config(struct mdp3_dma *dma,
+ struct mdp3_dma_color_correct_config *config,
+ struct mdp3_dma_ccs *ccs)
+{
+ int i;
+ u32 addr;
+
+ if (!ccs)
+ return -EINVAL;
+
+ if (config->ccs_enable) {
+ addr = MDP3_REG_DMA_P_CSC_MV1;
+ if (config->ccs_sel)
+ addr = MDP3_REG_DMA_P_CSC_MV2;
+ for (i = 0; i < 9; i++) {
+ MDP3_REG_WRITE(addr, ccs->mv[i]);
+ addr += 4;
+ }
+
+ addr = MDP3_REG_DMA_P_CSC_PRE_BV1;
+ if (config->pre_bias_sel)
+ addr = MDP3_REG_DMA_P_CSC_PRE_BV2;
+ for (i = 0; i < 3; i++) {
+ MDP3_REG_WRITE(addr, ccs->pre_bv[i]);
+ addr += 4;
+ }
+
+ addr = MDP3_REG_DMA_P_CSC_POST_BV1;
+ if (config->post_bias_sel)
+ addr = MDP3_REG_DMA_P_CSC_POST_BV2;
+ for (i = 0; i < 3; i++) {
+ MDP3_REG_WRITE(addr, ccs->post_bv[i]);
+ addr += 4;
+ }
+
+ addr = MDP3_REG_DMA_P_CSC_PRE_LV1;
+ if (config->pre_limit_sel)
+ addr = MDP3_REG_DMA_P_CSC_PRE_LV2;
+ for (i = 0; i < 6; i++) {
+ MDP3_REG_WRITE(addr, ccs->pre_lv[i]);
+ addr += 4;
+ }
+
+ addr = MDP3_REG_DMA_P_CSC_POST_LV1;
+ if (config->post_limit_sel)
+ addr = MDP3_REG_DMA_P_CSC_POST_LV2;
+ for (i = 0; i < 6; i++) {
+ MDP3_REG_WRITE(addr, ccs->post_lv[i]);
+ addr += 4;
+ }
+ }
+ dma->ccs_config = *config;
+
+ if (dma->output_config.out_sel != MDP3_DMA_OUTPUT_SEL_DSI_CMD)
+ mdp3_ccs_update(dma);
+
+ return 0;
+}
+
static int mdp3_dmap_lut_config(struct mdp3_dma *dma,
struct mdp3_dma_lut_config *config,
struct mdp3_dma_lut *lut)
{
- u32 cc_config, addr, color;
+ u32 addr, color;
int i;
if (config->lut_enable && lut) {
@@ -368,119 +485,11 @@
}
}
- cc_config = MDP3_REG_READ(MDP3_REG_DMA_P_COLOR_CORRECT_CONFIG);
- cc_config &= DMA_LUT_CONFIG_MASK;
- cc_config |= config->lut_enable;
- cc_config |= config->lut_position << 4;
- cc_config |= config->lut_sel << 10;
- MDP3_REG_WRITE(MDP3_REG_DMA_P_COLOR_CORRECT_CONFIG, cc_config);
- wmb();
-
dma->lut_config = *config;
- return 0;
-}
-static int mdp3_dmap_ccs_config(struct mdp3_dma *dma,
- struct mdp3_dma_color_correct_config *config,
- struct mdp3_dma_ccs *ccs)
-{
- int i;
- u32 cc_config, addr;
+ if (dma->output_config.out_sel != MDP3_DMA_OUTPUT_SEL_DSI_CMD)
+ mdp3_ccs_update(dma);
- cc_config = MDP3_REG_READ(MDP3_REG_DMA_P_COLOR_CORRECT_CONFIG);
- cc_config &= DMA_CCS_CONFIG_MASK;
- cc_config |= BIT(3);
- cc_config |= config->ccs_sel << 5;
- cc_config |= config->pre_bias_sel << 6;
- cc_config |= config->post_bias_sel << 7;
- cc_config |= config->pre_limit_sel << 8;
- cc_config |= config->post_limit_sel << 9;
-
- MDP3_REG_WRITE(MDP3_REG_DMA_P_COLOR_CORRECT_CONFIG, cc_config);
-
- if (config->ccs_enable && ccs) {
- if (ccs->mv1) {
- addr = MDP3_REG_DMA_P_CSC_MV1;
- for (i = 0; i < 9; i++) {
- MDP3_REG_WRITE(addr, ccs->mv1[i]);
- addr += 4;
- }
- }
-
- if (ccs->mv2) {
- addr = MDP3_REG_DMA_P_CSC_MV2;
- for (i = 0; i < 9; i++) {
- MDP3_REG_WRITE(addr, ccs->mv2[i]);
- addr += 4;
- }
- }
-
- if (ccs->pre_bv1) {
- addr = MDP3_REG_DMA_P_CSC_PRE_BV1;
- for (i = 0; i < 3; i++) {
- MDP3_REG_WRITE(addr, ccs->pre_bv1[i]);
- addr += 4;
- }
- }
-
- if (ccs->pre_bv2) {
- addr = MDP3_REG_DMA_P_CSC_PRE_BV2;
- for (i = 0; i < 3; i++) {
- MDP3_REG_WRITE(addr, ccs->pre_bv2[i]);
- addr += 4;
- }
- }
-
- if (ccs->post_bv1) {
- addr = MDP3_REG_DMA_P_CSC_POST_BV1;
- for (i = 0; i < 3; i++) {
- MDP3_REG_WRITE(addr, ccs->post_bv1[i]);
- addr += 4;
- }
- }
-
- if (ccs->post_bv2) {
- addr = MDP3_REG_DMA_P_CSC_POST_BV2;
- for (i = 0; i < 3; i++) {
- MDP3_REG_WRITE(addr, ccs->post_bv2[i]);
- addr += 4;
- }
- }
-
- if (ccs->pre_lv1) {
- addr = MDP3_REG_DMA_P_CSC_PRE_LV1;
- for (i = 0; i < 6; i++) {
- MDP3_REG_WRITE(addr, ccs->pre_lv1[i]);
- addr += 4;
- }
- }
-
- if (ccs->pre_lv2) {
- addr = MDP3_REG_DMA_P_CSC_PRE_LV2;
- for (i = 0; i < 6; i++) {
- MDP3_REG_WRITE(addr, ccs->pre_lv2[i]);
- addr += 4;
- }
- }
-
- if (ccs->post_lv1) {
- addr = MDP3_REG_DMA_P_CSC_POST_LV1;
- for (i = 0; i < 6; i++) {
- MDP3_REG_WRITE(addr, ccs->post_lv1[i]);
- addr += 4;
- }
- }
-
- if (ccs->post_lv2) {
- addr = MDP3_REG_DMA_P_CSC_POST_LV2;
- for (i = 0; i < 6; i++) {
- MDP3_REG_WRITE(addr, ccs->post_lv2[i]);
- addr += 4;
- }
- }
- }
-
- dma->ccs_config = *config;
return 0;
}
@@ -528,8 +537,10 @@
spin_lock_irqsave(&dma->dma_lock, flag);
MDP3_REG_WRITE(MDP3_REG_DMA_P_IBUF_ADDR, (u32)buf);
dma->source_config.buf = buf;
- if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD)
+ if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
+ mdp3_ccs_update(dma);
MDP3_REG_WRITE(MDP3_REG_DMA_P_START, 1);
+ }
if (!intf->active) {
pr_debug("mdp3_dmap_update start interface\n");
@@ -610,7 +621,7 @@
ret = wait_for_completion_killable_timeout(&dma->histo_comp, timeout);
if (ret == 0) {
- pr_err("mdp3_dmap_histo_get time out\n");
+ pr_debug("mdp3_dmap_histo_get time out\n");
ret = -ETIMEDOUT;
} else if (ret < 0) {
pr_err("mdp3_dmap_histo_get interrupted\n");
@@ -682,7 +693,6 @@
{
unsigned long flag;
int ret;
- u32 cgc;
if (dma->histo_state == MDP3_DMA_HISTO_STATE_START)
return -EINVAL;
@@ -690,9 +700,8 @@
spin_lock_irqsave(&dma->histo_lock, flag);
init_completion(&dma->histo_comp);
- cgc = MDP3_REG_READ(MDP3_REG_CGC_EN);
- cgc &= ~BIT(10);
- MDP3_REG_WRITE(MDP3_REG_CGC_EN, cgc);
+
+ mdp3_dma_clk_auto_gating(dma, 0);
MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_INTR_ENABLE, BIT(0)|BIT(1));
MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_RESET_SEQ_START, 1);
@@ -714,8 +723,7 @@
ret = 0;
}
mdp3_dma_callback_disable(dma, MDP3_DMA_CALLBACK_TYPE_HIST_RESET_DONE);
- cgc |= BIT(10);
- MDP3_REG_WRITE(MDP3_REG_CGC_EN, cgc);
+ mdp3_dma_clk_auto_gating(dma, 1);
return ret;
}
@@ -732,6 +740,7 @@
MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_INTR_ENABLE, 0);
wmb();
dma->histo_state = MDP3_DMA_HISTO_STATE_IDLE;
+ complete(&dma->histo_comp);
spin_unlock_irqrestore(&dma->histo_lock, flag);
diff --git a/drivers/video/msm/mdss/mdp3_dma.h b/drivers/video/msm/mdss/mdp3_dma.h
index 518bd58..c652818 100644
--- a/drivers/video/msm/mdss/mdp3_dma.h
+++ b/drivers/video/msm/mdss/mdp3_dma.h
@@ -176,16 +176,11 @@
};
struct mdp3_dma_ccs {
- u32 *mv1; /*set1 matrix vector, 3x3 */
- u32 *mv2;
- u32 *pre_bv1; /*pre-bias vector for set1, 1x3*/
- u32 *pre_bv2;
- u32 *post_bv1; /*post-bias vecotr for set1, */
- u32 *post_bv2;
- u32 *pre_lv1; /*pre-limit vector for set 1, 1x6*/
- u32 *pre_lv2;
- u32 *post_lv1;
- u32 *post_lv2;
+ u32 *mv; /*set1 matrix vector, 3x3 */
+ u32 *pre_bv; /*pre-bias vector for set1, 1x3*/
+ u32 *post_bv; /*post-bias vecotr for set1, */
+ u32 *pre_lv; /*pre-limit vector for set 1, 1x6*/
+ u32 *post_lv;
};
struct mdp3_dma_lut {
@@ -198,6 +193,7 @@
int lut_enable;
u32 lut_sel;
u32 lut_position;
+ bool lut_dirty;
};
struct mdp3_dma_color_correct_config {
@@ -207,6 +203,7 @@
u32 post_bias_sel;
u32 pre_bias_sel;
u32 ccs_sel;
+ bool ccs_dirty;
};
struct mdp3_dma_histogram_config {
diff --git a/drivers/video/msm/mdss/mdp3_ppp_hwio.c b/drivers/video/msm/mdss/mdp3_ppp_hwio.c
index 309effc..8dd3d55 100644
--- a/drivers/video/msm/mdss/mdp3_ppp_hwio.c
+++ b/drivers/video/msm/mdss/mdp3_ppp_hwio.c
@@ -57,6 +57,8 @@
int64_t Od;
int64_t Odprime;
int64_t Oreq;
+ int64_t init_phase_temp;
+ int64_t delta;
uint32_t mult;
/*
@@ -149,7 +151,24 @@
Oreq = (Osprime & int_mask) - one;
/* calculate initial phase */
- init_phase = (int)((Osprime - Oreq) >> 4);
+ init_phase_temp = Osprime - Oreq;
+ delta = ((int64_t) (org) << PQF_PLUS_4) - Oreq;
+ init_phase_temp -= delta;
+
+ /* limit to valid range before the left shift */
+ delta = (init_phase_temp & (1LL << 63)) ?
+ 4 : -4;
+ delta <<= PQF_PLUS_4;
+ while (abs((int)(init_phase_temp >>
+ PQF_PLUS_4)) > 4)
+ init_phase_temp += delta;
+
+ /*
+ * right shift to account for extra bits of
+ * precision
+ */
+ init_phase = (int)(init_phase_temp >> 4);
+
}
} else {
/*
@@ -181,7 +200,18 @@
Oreq = (Osprime & int_mask) - one;
/* calculate initial phase */
- init_phase = (int)((Osprime - Oreq) >> 4);
+ init_phase_temp = Osprime - Oreq;
+ delta = ((int64_t) (org) << PQF_PLUS_4) - Oreq;
+ init_phase_temp -= delta;
+
+ /* limit to valid range before the left shift */
+ delta = (init_phase_temp & (1LL << 63)) ? 4 : -4;
+ delta <<= PQF_PLUS_4;
+ while (abs((int)(init_phase_temp >> PQF_PLUS_4)) > 4)
+ init_phase_temp += delta;
+
+ /* right shift to account for extra bits of precision */
+ init_phase = (int)(init_phase_temp >> 4);
}
}
@@ -331,13 +361,43 @@
return rgb;
}
-static uint8_t *mdp_adjust_rot_addr(struct ppp_blit_op *iBuf,
+uint8_t *mdp_bg_adjust_rot_addr(struct ppp_blit_op *iBuf,
+ uint8_t *addr, uint32_t bpp, uint32_t uv)
+{
+ uint32_t dest_ystride = iBuf->bg.prop.width * bpp;
+ uint32_t h_slice = 1, min_val;
+
+ if (uv && ((iBuf->bg.color_fmt == MDP_Y_CBCR_H2V2) ||
+ (iBuf->bg.color_fmt == MDP_Y_CRCB_H2V2)))
+ h_slice = 2;
+
+ if (((iBuf->mdp_op & MDPOP_ROT90) == MDPOP_ROT90) ^
+ ((iBuf->mdp_op & MDPOP_LR) == MDPOP_LR)) {
+ min_val = (iBuf->bg.roi.width + iBuf->bg.roi.x) % 16;
+ if (!min_val)
+ min_val = 16;
+ addr +=
+ (iBuf->bg.roi.width -
+ MIN(min_val, iBuf->bg.roi.width)) * bpp;
+ }
+ if ((iBuf->mdp_op & MDPOP_UD) == MDPOP_UD) {
+ min_val = (iBuf->bg.roi.height + iBuf->bg.roi.y) % 16;
+ if (!min_val)
+ min_val = 16;
+ addr +=
+ ((iBuf->bg.roi.height -
+ MIN(min_val, iBuf->bg.roi.height))/h_slice) *
+ dest_ystride;
+ }
+
+ return addr;
+}
+
+uint8_t *mdp_dst_adjust_rot_addr(struct ppp_blit_op *iBuf,
uint8_t *addr, uint32_t bpp, uint32_t uv)
{
uint32_t dest_ystride = iBuf->dst.prop.width * bpp;
uint32_t h_slice = 1;
- if (0)
- return 0;
if (uv && ((iBuf->dst.color_fmt == MDP_Y_CBCR_H2V2) ||
(iBuf->dst.color_fmt == MDP_Y_CRCB_H2V2)))
@@ -350,16 +410,10 @@
MIN(16, iBuf->dst.roi.width)) * bpp;
}
if ((iBuf->mdp_op & MDPOP_UD) == MDPOP_UD) {
- if (1) {
- addr +=
- ((iBuf->dst.roi.height -
- MIN(16, iBuf->dst.roi.height))/h_slice) *
- dest_ystride;
- } else {
- addr +=
- (iBuf->dst.roi.width -
- MIN(16, iBuf->dst.roi.width)) * bpp;
- }
+ addr +=
+ ((iBuf->dst.roi.height -
+ MIN(16, iBuf->dst.roi.height))/h_slice) *
+ dest_ystride;
}
return addr;
@@ -378,8 +432,10 @@
img->p0 += (x + y * ALIGN(width, 32)) * bpp;
else
img->p0 += (x + y * width) * bpp;
- if (layer != 0)
- img->p0 = mdp_adjust_rot_addr(blit_op, img->p0, bpp, 0);
+ if (layer == 1)
+ img->p0 = mdp_bg_adjust_rot_addr(blit_op, img->p0, bpp, 0);
+ else if (layer == 2)
+ img->p0 = mdp_dst_adjust_rot_addr(blit_op, img->p0, bpp, 0);
if (img->p1) {
/*
@@ -394,8 +450,14 @@
else
img->p1 += ((x / h_slice) * h_slice +
((y == 0) ? 0 : ((y + 1) / v_slice - 1) * width)) * bpp;
- if (layer != 0)
- img->p1 = mdp_adjust_rot_addr(blit_op, img->p1, bpp, 1);
+
+ if (layer == 1) {
+ img->p0 = mdp_bg_adjust_rot_addr(blit_op,
+ img->p0, bpp, 0);
+ } else if (layer == 2) {
+ img->p0 = mdp_dst_adjust_rot_addr(blit_op,
+ img->p0, bpp, 0);
+ }
}
}
@@ -1044,7 +1106,6 @@
}
if (*pppop_reg_ptr & PPP_OP_BLEND_ON) {
- blit_op->bg = blit_op->dst;
config_ppp_background(&blit_op->bg);
if (blit_op->dst.color_fmt == MDP_YCRYCB_H2V1) {
@@ -1152,9 +1213,11 @@
blit_op->dst.p1 = NULL;
}
+ blit_op->bg = blit_op->dst;
/* Jumping from Y-Plane to Chroma Plane */
/* first pixel addr calculation */
mdp_adjust_start_addr(blit_op, &blit_op->src, sv_slice, sh_slice, 0);
+ mdp_adjust_start_addr(blit_op, &blit_op->bg, dv_slice, dh_slice, 1);
mdp_adjust_start_addr(blit_op, &blit_op->dst, dv_slice, dh_slice, 2);
config_ppp_scale(blit_op, &ppp_operation_reg);
diff --git a/drivers/video/msm/mdss/mhl_sii8334.c b/drivers/video/msm/mdss/mhl_sii8334.c
index 3f03725..82b56e3 100644
--- a/drivers/video/msm/mdss/mhl_sii8334.c
+++ b/drivers/video/msm/mdss/mhl_sii8334.c
@@ -373,7 +373,7 @@
/* USB_HANDSHAKING FUNCTIONS */
static int mhl_sii_device_discovery(void *data, int id,
- void (*usb_notify_cb)(int online))
+ void (*usb_notify_cb)(void *, int), void *ctx)
{
int rc;
struct mhl_tx_ctrl *mhl_ctrl = data;
@@ -398,8 +398,10 @@
return -EINVAL;
}
- if (!mhl_ctrl->notify_usb_online)
+ if (!mhl_ctrl->notify_usb_online) {
mhl_ctrl->notify_usb_online = usb_notify_cb;
+ mhl_ctrl->notify_ctx = ctx;
+ }
if (!mhl_ctrl->disc_enabled) {
spin_lock_irqsave(&mhl_ctrl->lock, flags);
@@ -904,7 +906,7 @@
mhl_ctrl->mhl_mode = 1;
power_supply_changed(&mhl_ctrl->mhl_psy);
if (mhl_ctrl->notify_usb_online)
- mhl_ctrl->notify_usb_online(1);
+ mhl_ctrl->notify_usb_online(mhl_ctrl->notify_ctx, 1);
} else {
pr_debug("%s: non-mhl sink\n", __func__);
mhl_ctrl->mhl_mode = 0;
@@ -1004,7 +1006,7 @@
mhl_msm_disconnection(mhl_ctrl);
power_supply_changed(&mhl_ctrl->mhl_psy);
if (mhl_ctrl->notify_usb_online)
- mhl_ctrl->notify_usb_online(0);
+ mhl_ctrl->notify_usb_online(mhl_ctrl->notify_ctx, 0);
return 0;
}
@@ -1019,7 +1021,7 @@
mhl_msm_disconnection(mhl_ctrl);
power_supply_changed(&mhl_ctrl->mhl_psy);
if (mhl_ctrl->notify_usb_online)
- mhl_ctrl->notify_usb_online(0);
+ mhl_ctrl->notify_usb_online(mhl_ctrl->notify_ctx, 0);
return 0;
}
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index cfc690e..5b69884 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -39,8 +39,8 @@
enum coresight_clk_rate {
CORESIGHT_CLK_RATE_OFF,
- CORESIGHT_CLK_RATE_TRACE,
- CORESIGHT_CLK_RATE_HSTRACE,
+ CORESIGHT_CLK_RATE_TRACE = 1000,
+ CORESIGHT_CLK_RATE_HSTRACE = 2000,
};
enum coresight_dev_type {
diff --git a/include/linux/i2c/atmel_mxt_ts.h b/include/linux/i2c/atmel_mxt_ts.h
index b903dfb..e9fbf90 100644
--- a/include/linux/i2c/atmel_mxt_ts.h
+++ b/include/linux/i2c/atmel_mxt_ts.h
@@ -77,6 +77,7 @@
int *key_codes;
bool need_calibration;
bool no_force_update;
+ bool no_lpm_support;
u8 bl_addr;
u8(*read_chg) (void);
diff --git a/include/linux/mhl_8334.h b/include/linux/mhl_8334.h
index 7297ff3..560f75b 100644
--- a/include/linux/mhl_8334.h
+++ b/include/linux/mhl_8334.h
@@ -137,7 +137,8 @@
uint8_t chip_rev_id;
int mhl_mode;
struct completion rgnd_done;
- void (*notify_usb_online)(int online);
+ void (*notify_usb_online)(void *ctx, int online);
+ void *notify_ctx;
struct usb_ext_notification *mhl_info;
bool disc_enabled;
struct power_supply mhl_psy;
diff --git a/include/linux/smux.h b/include/linux/smux.h
index 56b18fa..1157cef 100644
--- a/include/linux/smux.h
+++ b/include/linux/smux.h
@@ -1,6 +1,6 @@
/* include/linux/smux.h
*
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -79,6 +79,8 @@
SMUX_HIGH_WM_HIT, /* @metadata is NULL */
SMUX_RX_RETRY_HIGH_WM_HIT, /* @metadata is NULL */
SMUX_RX_RETRY_LOW_WM_HIT, /* @metadata is NULL */
+ SMUX_LOCAL_CLOSED,
+ SMUX_REMOTE_CLOSED,
};
/**
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 1c9884c..f04d2bf 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -26,6 +26,7 @@
#include <linux/pm_qos.h>
#include <linux/hrtimer.h>
#include <linux/power_supply.h>
+#include <linux/cdev.h>
/*
* The following are bit fields describing the usb_request.udc_priv word.
* These bit fields are set by function drivers that wish to queue
@@ -347,6 +348,7 @@
struct clk *phy_reset_clk;
struct clk *core_clk;
long core_clk_rate;
+ struct resource *io_res;
void __iomem *regs;
#define ID 0
#define B_SESS_VLD 1
@@ -434,6 +436,14 @@
unsigned int online;
unsigned int host_mode;
unsigned int current_max;
+
+ dev_t ext_chg_dev;
+ struct cdev ext_chg_cdev;
+ struct class *ext_chg_class;
+ struct device *ext_chg_device;
+ bool ext_chg_opened;
+ bool ext_chg_active;
+ struct completion ext_chg_wait;
};
struct ci13xxx_platform_data {
@@ -496,7 +506,7 @@
/**
* struct usb_ext_notification: event notification structure
* @notify: pointer to client function to call when ID event is detected.
- * The last parameter is provided by driver to be called back when
+ * The function parameter is provided by driver to be called back when
* external client indicates it is done using the USB. This function
* should return 0 if handled successfully, otherise an error code.
* @ctxt: client-specific context pointer
@@ -510,7 +520,7 @@
* called with the online parameter set to false.
*/
struct usb_ext_notification {
- int (*notify)(void *, int, void (*)(int online));
+ int (*notify)(void *, int, void (*)(void *, int online), void *);
void *ctxt;
};
#ifdef CONFIG_USB_BAM
@@ -540,7 +550,7 @@
int msm_data_fifo_config(struct usb_ep *ep, u32 addr, u32 size,
u8 dst_pipe_idx);
-void msm_dwc3_restart_usb_session(void);
+void msm_dwc3_restart_usb_session(struct usb_gadget *gadget);
int msm_register_usb_ext_notification(struct usb_ext_notification *info);
#else
@@ -560,7 +570,7 @@
return -ENODEV;
}
-static inline void msm_dwc3_restart_usb_session(void)
+static inline void msm_dwc3_restart_usb_session(struct usb_gadget *gadget)
{
return;
}
diff --git a/include/linux/usb/msm_hsusb_hw.h b/include/linux/usb/msm_hsusb_hw.h
index ba75cb9..064d210 100644
--- a/include/linux/usb/msm_hsusb_hw.h
+++ b/include/linux/usb/msm_hsusb_hw.h
@@ -24,6 +24,7 @@
#define USB_HS_GPTIMER_BASE (MSM_USB_BASE + 0x80)
#define GENCFG2_SESS_VLD_CTRL_EN BIT(7)
+#define GENCFG2_LINESTATE_DIFF_WAKEUP_EN BIT(12)
#define USB_USBCMD (MSM_USB_BASE + 0x0140)
#define USB_USBSTS (MSM_USB_BASE + 0x0144)
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 81187aa..7ad0c16 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -1856,6 +1856,21 @@
V4L2_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO_DISABLED = 0,
V4L2_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO_ENABLED = 1
};
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE \
+ (V4L2_CID_MPEG_MSM_VIDC_BASE+30)
+enum v4l2_mpeg_vidc_video_alloc_mode_type {
+ V4L2_MPEG_VIDC_VIDEO_STATIC = 0,
+ V4L2_MPEG_VIDC_VIDEO_RING = 1,
+};
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_FRAME_ASSEMBLY \
+ (V4L2_CID_MPEG_MSM_VIDC_BASE+31)
+enum v4l2_mpeg_vidc_video_assembly {
+ V4L2_MPEG_VIDC_FRAME_ASSEMBLY_DISABLE = 0,
+ V4L2_MPEG_VIDC_FRAME_ASSEMBLY_ENABLE = 1,
+};
+
/* Camera class control IDs */
#define V4L2_CID_CAMERA_CLASS_BASE (V4L2_CTRL_CLASS_CAMERA | 0x900)
#define V4L2_CID_CAMERA_CLASS (V4L2_CTRL_CLASS_CAMERA | 1)
diff --git a/include/media/msm_cam_sensor.h b/include/media/msm_cam_sensor.h
index 6358f8a..2805401 100644
--- a/include/media/msm_cam_sensor.h
+++ b/include/media/msm_cam_sensor.h
@@ -46,6 +46,8 @@
#define MAX_EEPROM_NAME 32
+#define MAX_AF_ITERATIONS 3
+
enum msm_camera_i2c_reg_addr_type {
MSM_CAMERA_I2C_BYTE_ADDR = 1,
MSM_CAMERA_I2C_WORD_ADDR,
@@ -78,6 +80,11 @@
enum msm_sensor_power_seq_gpio_t {
SENSOR_GPIO_RESET,
SENSOR_GPIO_STANDBY,
+ SENSOR_GPIO_AF_PWDM,
+ SENSOR_GPIO_VIO,
+ SENSOR_GPIO_VANA,
+ SENSOR_GPIO_VDIG,
+ SENSOR_GPIO_VAF,
SENSOR_GPIO_MAX,
};
@@ -133,6 +140,11 @@
REG_GPIO,
};
+enum sensor_af_t {
+ SENSOR_AF_FOCUSSED,
+ SENSOR_AF_NOT_FOCUSSED,
+};
+
struct msm_sensor_power_setting {
enum msm_sensor_power_seq_type_t seq_type;
uint16_t seq_val;
@@ -346,6 +358,11 @@
CFG_SET_RESOLUTION,
CFG_SET_STOP_STREAM,
CFG_SET_START_STREAM,
+ CFG_SET_SATURATION,
+ CFG_SET_CONTRAST,
+ CFG_SET_SHARPNESS,
+ CFG_SET_AUTOFOCUS,
+ CFG_CANCEL_AUTOFOCUS,
};
enum msm_actuator_cfg_type_t {
@@ -509,6 +526,9 @@
#define VIDIOC_MSM_EEPROM_CFG \
_IOWR('V', BASE_VIDIOC_PRIVATE + 8, struct msm_eeprom_cfg_data)
+#define VIDIOC_MSM_SENSOR_GET_AF_STATUS \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 9, uint32_t)
+
#define MSM_V4L2_PIX_FMT_META v4l2_fourcc('M', 'E', 'T', 'A') /* META */
#endif /* __LINUX_MSM_CAM_SENSOR_H */
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 69e4cca..212924f 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -2639,17 +2639,31 @@
case SND_SOC_DAPM_PRE_PMU:
(*dmic_clk_cnt)++;
- if (*dmic_clk_cnt == 1)
+ if (*dmic_clk_cnt == 1) {
+ snd_soc_update_bits(codec,
+ TABLA_A_CDC_DMIC_CLK0_MODE, 0x7, 0x0);
+ snd_soc_update_bits(codec,
+ TABLA_A_CDC_DMIC_CLK1_MODE, 0x7, 0x0);
+ snd_soc_update_bits(codec,
+ TABLA_A_CDC_DMIC_CLK2_MODE, 0x7, 0x0);
snd_soc_update_bits(codec, TABLA_A_CDC_CLK_DMIC_CTL,
dmic_clk_en, dmic_clk_en);
+ }
break;
case SND_SOC_DAPM_POST_PMD:
(*dmic_clk_cnt)--;
- if (*dmic_clk_cnt == 0)
+ if (*dmic_clk_cnt == 0) {
snd_soc_update_bits(codec, TABLA_A_CDC_CLK_DMIC_CTL,
dmic_clk_en, 0);
+ snd_soc_update_bits(codec,
+ TABLA_A_CDC_DMIC_CLK0_MODE, 0x7, 0x4);
+ snd_soc_update_bits(codec,
+ TABLA_A_CDC_DMIC_CLK1_MODE, 0x7, 0x4);
+ snd_soc_update_bits(codec,
+ TABLA_A_CDC_DMIC_CLK2_MODE, 0x7, 0x4);
+ }
break;
}
return 0;
@@ -8772,6 +8786,13 @@
tabla_2_higher_codec_reg_init_val[i].mask,
tabla_2_higher_codec_reg_init_val[i].val);
}
+ snd_soc_update_bits(codec, TABLA_A_CDC_DMIC_CLK0_MODE, 0x7, 0x4);
+ snd_soc_update_bits(codec, TABLA_A_CDC_DMIC_CLK1_MODE, 0x7, 0x4);
+ snd_soc_update_bits(codec, TABLA_A_CDC_DMIC_CLK2_MODE, 0x7, 0x4);
+ snd_soc_update_bits(codec, TABLA_A_PIN_CTL_OE0, 0x90, 0x90);
+ snd_soc_update_bits(codec, TABLA_A_PIN_CTL_OE1, 0x8, 0x8);
+ snd_soc_update_bits(codec, TABLA_A_PIN_CTL_DATA0, 0x90, 0x0);
+ snd_soc_update_bits(codec, TABLA_A_PIN_CTL_DATA1, 0x8, 0x0);
}
static void tabla_update_reg_address(struct tabla_priv *priv)
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index e34dec1..d0c00a7 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -220,11 +220,15 @@
pr_debug("%s: leave\n", __func__);
}
-/* called under codec_resource_lock acquisition */
-static void __wcd9xxx_switch_micbias(struct wcd9xxx_mbhc *mbhc,
+/*
+ * called under codec_resource_lock acquisition
+ * return old status
+ */
+static bool __wcd9xxx_switch_micbias(struct wcd9xxx_mbhc *mbhc,
int vddio_switch, bool restartpolling,
bool checkpolling)
{
+ bool ret;
int cfilt_k_val;
bool override;
struct snd_soc_codec *codec;
@@ -234,9 +238,11 @@
if (mbhc->micbias_enable) {
pr_debug("%s: micbias is already on\n", __func__);
- return;
+ ret = mbhc->mbhc_micbias_switched;
+ return ret;
}
+ ret = mbhc->mbhc_micbias_switched;
if (vddio_switch && !mbhc->mbhc_micbias_switched &&
(!checkpolling || mbhc->polling_active)) {
if (restartpolling)
@@ -343,11 +349,13 @@
mbhc->mbhc_micbias_switched = false;
pr_debug("%s: VDDIO switch disabled\n", __func__);
}
+
+ return ret;
}
static void wcd9xxx_switch_micbias(struct wcd9xxx_mbhc *mbhc, int vddio_switch)
{
- return __wcd9xxx_switch_micbias(mbhc, vddio_switch, true, true);
+ __wcd9xxx_switch_micbias(mbhc, vddio_switch, true, true);
}
static s16 wcd9xxx_get_current_v(struct wcd9xxx_mbhc *mbhc,
@@ -1124,10 +1132,15 @@
/*
* wcd9xxx_find_plug_type : Find out and return the best plug type with given
* list of wcd9xxx_mbhc_detect structure.
+ * param mbhc wcd9xxx_mbhc structure
+ * param dt collected measurements
+ * param size array size of dt
+ * param event_state mbhc->event_state when dt is collected
*/
static enum wcd9xxx_mbhc_plug_type
wcd9xxx_find_plug_type(struct wcd9xxx_mbhc *mbhc,
- struct wcd9xxx_mbhc_detect *dt, const int size)
+ struct wcd9xxx_mbhc_detect *dt, const int size,
+ unsigned long event_state)
{
int i;
int ch;
@@ -1140,6 +1153,8 @@
const s16 hs_max = plug_type->v_hs_max;
const s16 no_mic = plug_type->v_no_mic;
+ pr_debug("%s: event_state 0x%lx\n", __func__, event_state);
+
for (i = 0, d = dt, ch = 0; i < size; i++, d++) {
vdce = wcd9xxx_codec_sta_dce_v(mbhc, true, d->dce);
if (d->vddio)
@@ -1181,7 +1196,10 @@
goto exit;
}
}
- if (ch != size && ch > 0) {
+
+ if (event_state & (1 << MBHC_EVENT_PA_HPHL)) {
+ pr_debug("%s: HPHL PA was ON\n", __func__);
+ } else if (ch != size && ch > 0) {
pr_debug("%s: Invalid, inconsistent HPHL\n", __func__);
type = PLUG_TYPE_INVALID;
goto exit;
@@ -1221,12 +1239,18 @@
maxv))
type = PLUG_TYPE_GND_MIC_SWAP;
}
- if (((type == PLUG_TYPE_HEADSET || type == PLUG_TYPE_HEADPHONE) &&
- ch != size) || (type == PLUG_TYPE_GND_MIC_SWAP && ch)) {
- pr_debug("%s: Invalid, not fully inserted, TYPE %d\n",
- __func__, type);
- type = PLUG_TYPE_INVALID;
+
+ /* if HPHL PA was on, we cannot use hphl status */
+ if (!(event_state & (1UL << MBHC_EVENT_PA_HPHL))) {
+ if (((type == PLUG_TYPE_HEADSET ||
+ type == PLUG_TYPE_HEADPHONE) && ch != size) ||
+ (type == PLUG_TYPE_GND_MIC_SWAP && ch)) {
+ pr_debug("%s: Invalid, not fully inserted, TYPE %d\n",
+ __func__, type);
+ type = PLUG_TYPE_INVALID;
+ }
}
+
if (type == PLUG_TYPE_HEADSET && dvddio) {
if ((dvddio->_vdces > hs_max) ||
(dvddio->_vdces > minv + WCD9XXX_THRESHOLD_MIC_THRESHOLD)) {
@@ -1294,6 +1318,7 @@
wcd9xxx_codec_get_plug_type(struct wcd9xxx_mbhc *mbhc, bool highhph)
{
int i;
+ bool vddioon;
struct wcd9xxx_mbhc_plug_type_cfg *plug_type_ptr;
struct wcd9xxx_mbhc_detect rt[NUM_DCE_PLUG_INS_DETECT];
enum wcd9xxx_mbhc_plug_type type = PLUG_TYPE_INVALID;
@@ -1308,6 +1333,13 @@
/* GND and MIC swap detection requires at least 2 rounds of DCE */
BUG_ON(NUM_DCE_PLUG_INS_DETECT < 2);
+ /*
+ * There are chances vddio switch is on and cfilt voltage is adjusted
+ * to vddio voltage even after plug type removal reported.
+ */
+ vddioon = __wcd9xxx_switch_micbias(mbhc, 0, false, false);
+ pr_debug("%s: vddio switch was %s\n", __func__, vddioon ? "on" : "off");
+
plug_type_ptr =
WCD9XXX_MBHC_CAL_PLUG_TYPE_PTR(mbhc->mbhc_cfg->calibration);
@@ -1350,7 +1382,11 @@
wcd9xxx_codec_hphr_gnd_switch(codec, false);
}
- type = wcd9xxx_find_plug_type(mbhc, rt, ARRAY_SIZE(rt));
+ if (vddioon)
+ __wcd9xxx_switch_micbias(mbhc, 1, false, false);
+
+ type = wcd9xxx_find_plug_type(mbhc, rt, ARRAY_SIZE(rt),
+ mbhc->event_state);
pr_debug("%s: leave\n", __func__);
return type;
@@ -2134,6 +2170,7 @@
unsigned long timeout;
int retry = 0, pt_gnd_mic_swap_cnt = 0;
bool correction = false;
+ bool wrk_complete = true;
pr_debug("%s: enter\n", __func__);
@@ -2159,12 +2196,14 @@
++retry;
rmb();
if (mbhc->hs_detect_work_stop) {
+ wrk_complete = false;
pr_debug("%s: stop requested\n", __func__);
break;
}
msleep(HS_DETECT_PLUG_INERVAL_MS);
if (wcd9xxx_swch_level_remove(mbhc)) {
+ wrk_complete = false;
pr_debug("%s: Switch level is low\n", __func__);
break;
}
@@ -2238,7 +2277,9 @@
if (plug_type == PLUG_TYPE_HIGH_HPH) {
pr_debug("%s: polling is done, still HPH, so enabling MIC trigger\n",
__func__);
+ WCD9XXX_BCL_LOCK(mbhc->resmgr);
wcd9xxx_find_plug_and_report(mbhc, plug_type);
+ WCD9XXX_BCL_UNLOCK(mbhc->resmgr);
}
/* Turn off override */
if (!correction)
@@ -2248,10 +2289,11 @@
if (mbhc->mbhc_cfg->detect_extn_cable) {
WCD9XXX_BCL_LOCK(mbhc->resmgr);
- if (mbhc->current_plug == PLUG_TYPE_HEADPHONE ||
+ if ((mbhc->current_plug == PLUG_TYPE_HEADPHONE &&
+ wrk_complete) ||
mbhc->current_plug == PLUG_TYPE_GND_MIC_SWAP ||
mbhc->current_plug == PLUG_TYPE_INVALID ||
- plug_type == PLUG_TYPE_INVALID) {
+ (plug_type == PLUG_TYPE_INVALID && wrk_complete)) {
/* Enable removal detection */
wcd9xxx_cleanup_hs_polling(mbhc);
wcd9xxx_enable_hs_detect(mbhc, 0, 0, false);
diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
index 9f4e189..aa6ef6b 100644
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
@@ -127,6 +127,7 @@
int i = 0;
int time_stamp_flag = 0;
int buffer_length = 0;
+ int stop_playback = 0;
pr_debug("%s opcode =%08x\n", __func__, opcode);
switch (opcode) {
@@ -151,9 +152,15 @@
/*
* check for underrun
*/
+ snd_pcm_stream_lock_irq(substream);
if (runtime->status->hw_ptr >= runtime->control->appl_ptr) {
- pr_info("render stopped");
runtime->render_flag |= SNDRV_RENDER_STOPPED;
+ stop_playback = 1;
+ }
+ snd_pcm_stream_unlock_irq(substream);
+
+ if (stop_playback) {
+ pr_err("underrun! render stopped\n");
break;
}
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index 2e5ff35..be62727 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -95,7 +95,6 @@
static int voice_alloc_and_map_oob_mem(struct voice_data *v);
static struct voice_data *voice_get_session_by_idx(int idx);
-static int voice_get_idx_for_session(u32 session_id);
static u16 voice_get_mvm_handle(struct voice_data *v)
{
@@ -240,7 +239,7 @@
return v;
}
-static int voice_get_idx_for_session(u32 session_id)
+int voice_get_idx_for_session(u32 session_id)
{
int idx = 0;
diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h
index 4a3ff2a..42b1800 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.h
+++ b/sound/soc/msm/qdsp6v2/q6voice.h
@@ -1384,4 +1384,6 @@
int voc_start_playback(uint32_t set, uint16_t port_id);
int voc_start_record(uint32_t port_id, uint32_t set);
+int voice_get_idx_for_session(u32 session_id);
+
#endif
diff --git a/sound/soc/msm/qdsp6v2/rtac.c b/sound/soc/msm/qdsp6v2/rtac.c
index 1f2a487..a4983d3 100644
--- a/sound/soc/msm/qdsp6v2/rtac.c
+++ b/sound/soc/msm/qdsp6v2/rtac.c
@@ -24,7 +24,7 @@
#include <sound/q6asm-v2.h>
#include <sound/q6afe-v2.h>
#include <sound/apr_audio-v2.h>
-
+#include <q6voice.h>
#include "audio_acdb.h"
@@ -352,13 +352,13 @@
return;
}
-static int get_voice_index_cvs(u32 cvs_handle)
+static u32 get_voice_session_id_cvs(u32 cvs_handle)
{
u32 i;
for (i = 0; i < rtac_voice_data.num_of_voice_combos; i++) {
if (rtac_voice_data.voice[i].cvs_handle == cvs_handle)
- return i;
+ return voice_session_id[i];
}
pr_err("%s: No voice index for CVS handle %d found returning 0\n",
@@ -366,13 +366,13 @@
return 0;
}
-static int get_voice_index_cvp(u32 cvp_handle)
+static u32 get_voice_session_id_cvp(u32 cvp_handle)
{
u32 i;
for (i = 0; i < rtac_voice_data.num_of_voice_combos; i++) {
if (rtac_voice_data.voice[i].cvp_handle == cvp_handle)
- return i;
+ return voice_session_id[i];
}
pr_err("%s: No voice index for CVP handle %d found returning 0\n",
@@ -383,9 +383,11 @@
static int get_voice_index(u32 mode, u32 handle)
{
if (mode == RTAC_CVP)
- return get_voice_index_cvp(handle);
+ return voice_get_idx_for_session(
+ get_voice_session_id_cvp(handle));
if (mode == RTAC_CVS)
- return get_voice_index_cvs(handle);
+ return voice_get_idx_for_session(
+ get_voice_session_id_cvs(handle));
pr_err("%s: Invalid mode %d, returning 0\n",
__func__, mode);
@@ -847,8 +849,7 @@
payload_size);
voice_params.src_svc = 0;
voice_params.src_domain = APR_DOMAIN_APPS;
- voice_params.src_port = voice_session_id[
- get_voice_index(mode, dest_port)];
+ voice_params.src_port = get_voice_index(mode, dest_port);
voice_params.dest_svc = 0;
voice_params.dest_domain = APR_DOMAIN_MODEM;
voice_params.dest_port = (u16)dest_port;