Merge "arm/dt: msm8974: Disable Venus core logic collapse via its GDSC"
diff --git a/Documentation/devicetree/bindings/i2c/i2c-qup.txt b/Documentation/devicetree/bindings/i2c/i2c-qup.txt
index a7976e8..fd7b635 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-qup.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-qup.txt
@@ -28,10 +28,18 @@
recovery procedure.
- qcom,sda-gpio : I2C data GPIO number. Required for execution of bus
recovery procedure.
+ - qcom,active-only : Vote for core clock when the application processor goes
+ to active state and remove that vote when it goes to idle
+ state. This flag may improve service time of first i2c
+ request at the expense of power consumption. When this
+ entry is not present, voting is done by the runtime-pm
+ callbacks.
+ - qcom,master-id : Master endpoint number used for voting on clocks using
+ bus-scaling driver.
Example:
- i2c@f9966000 {
- cell-index = <0>;
+ i2c_3: i2c@f9966000 {
+ cell-index = <3>;
compatible = "qcom,i2c-qup";
reg = <0xf9966000 0x1000>;
reg-names = "qup_phys_addr";
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp.txt b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
index c409ea6..ae1f648 100644
--- a/Documentation/devicetree/bindings/leds/leds-qpnp.txt
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
@@ -50,7 +50,7 @@
RGB Led is a tri-colored led, Red, Blue & Green.
Required properties for RGB led:
-- qcom,mode: mode the led should operate in, options 0 = PWM, 1 = LPG
+- qcom,mode: mode the led should operate in, options "pwm" and "lpg"
- qcom,pwm-channel: pwm channel the led will operate on
Required properties for PWM mode only:
@@ -59,6 +59,8 @@
Required properties for LPG mode only:
- qcom,duty-pcts: array of values for duty cycle to go through
- qcom,start-idx: starting point duty-pcts array
+
+Optional properties for LPG mode only:
- qcom,pause-lo: pause at low end of cycle
- qcom,pause-hi: pause at high end of cycle
- qcom,ramp-step-ms: step between each cycle (ms)
@@ -76,12 +78,28 @@
- qcom,default-state: default state of the led, should be "on" or "off"
- 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"
+
+Required properties for PWM mode only:
+- qcom,pwm-channel: pwm channel the led will operate on
+- qcom,pwm-us: time the pwm device will modulate at (us)
+
+Required properties for LPG mode only:
+- qcom,pwm-channel: pwm channel the led will operate on
+- qcom,duty-pcts: array of values for duty cycle to go through
+- qcom,start-idx: starting point duty-pcts array
+
+Optional properties for LPG mode only:
+- qcom,pause-lo: pause at low end of cycle
+- qcom,pause-hi: pause at high end of cycle
+- qcom,ramp-step-ms: step between each cycle (ms)
+- qcom,lut-flags: flags to be used in lut configuration
Keypad backlight is a backlight source for buttons. It supports four rows
and the required rows are enabled by specifying values in the properties.
Required properties for keypad backlight:
-- qcom,mode: mode the led should operate in, options 0 = PWM, 1 = LPG
+- qcom,mode: mode the led should operate in, options "pwm" and "lpg"
- qcom,pwm-channel: pwm channel the led will operate on
- qcom,pwm-us: time the pwm device will modulate at (us)
- qcom,row-src-sel-val: select source for rows. One bit is used for each row.
@@ -89,6 +107,19 @@
- qcom,row-scan-val: select rows for scanning
- qcom,row-scan-en: row scan enable
+Required properties for PWM mode only:
+- qcom,pwm-us: time the pwm device will modulate at (us)
+
+Required properties for LPG mode only:
+- qcom,duty-pcts: array of values for duty cycle to go through
+- qcom,start-idx: starting point duty-pcts array
+
+Optional properties for LPG mode only:
+- qcom,pause-lo: pause at low end of cycle
+- qcom,pause-hi: pause at high end of cycle
+- qcom,ramp-step-ms: step between each cycle (ms)
+- qcom,lut-flags: flags to be used in lut configuration
+
Example:
qcom,leds@a200 {
@@ -105,12 +136,30 @@
};
};
+ qcom,leds@a300 {
+ status = "okay";
+ qcom,led_mpp_pwm {
+ label = "mpp";
+ linux,name = "green";
+ linux,default-trigger = "none";
+ qcom,default-state = "off";
+ qcom,max-current = <40>;
+ qcom,current-setting = <5>;
+ qcom,id = <6>;
+ qcom,mode = "pwm";
+ qcom,source-sel = <8>;
+ qcom,mode-ctrl = <0x60>;
+ qcom,pwm-channel = <0>;
+ qcom,pwm-us = <1000>;
+ };
+ };
+
qcom,leds@d000 {
status = "okay";
qcom,rgb_pwm {
label = "rgb";
linux,name = "led:rgb_red";
- qcom,mode = <0>;
+ qcom,mode = "pwm";
qcom,pwm-channel = <6>;
qcom,pwm-us = <1000>;
qcom,duty-ms = <20>;
@@ -128,7 +177,7 @@
qcom,rgb_lpg {
label = "rgb";
linux,name = "led:rgb_blue";
- qcom,mode = <1>;
+ qcom,mode = "lpg";
qcom,pwm-channel = <4>;
qcom,start-idx = <1>;
qcom,idx-len = <10>;
diff --git a/Documentation/devicetree/bindings/power/qpnp-charger.txt b/Documentation/devicetree/bindings/power/qpnp-charger.txt
index 359ee6c..43df9cc 100644
--- a/Documentation/devicetree/bindings/power/qpnp-charger.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-charger.txt
@@ -41,6 +41,8 @@
by default. This can then be overriden
writing the the module parameter
"charging_disabled".
+- qcom,duty-cycle-100p: Set this property to enable the 100% duty
+ cycle feature.
- qcom,use-default-batt-values: Set this flag to force reporting of
battery temperature of 250 decidegree
Celsius, state of charge to be 50%
@@ -63,6 +65,10 @@
detection, "bpd_thm_id" selects both.
If the property is not set the hw default will
be used.
+- otg-parent-supply Specify a phandle to a parent supply regulator
+ for the OTG regulator.
+- boost-parent-supply Specify a phandle to a parent supply regulator
+ for the boost regulator.
Sub node required structure:
- A qcom,chg node must be a child of an SPMI node that has specified
@@ -85,6 +91,7 @@
qcom,usb-chgpth:
- usbin-valid
+
qcom,chgr:
- chg-done
- chg-failed
@@ -141,6 +148,16 @@
- limit-error: Limiting error on SMBB boost.
- boost-pwr-ok: Status of boost power.
+Sub node optional properties:
+ qcom,usb-chgpth:
+ - regulator-name: A string used as a descriptive name
+ for the OTG regulator.
+ qcom,boost:
+ - regulator-min-microvolt: Minimum boost voltage setting.
+ - regulator-max-microvolt: Maximum boost voltage setting.
+ - regulator-name: A string used as a descriptive name
+ for the boost regulator.
+
Example:
pm8941-chg {
spmi-dev-container;
@@ -148,6 +165,9 @@
#address-cells = <1>;
#size-cells = <1>;
+ otg-parent-supply = <&pm8941_boost>;
+ boost-parent-supply = <&foo_parent_reg>;
+
qcom,vddmax-mv = <4200>;
qcom,vddsafe-mv = <4200>;
qcom,vinmin-mv = <4200>;
@@ -218,7 +238,7 @@
"batt-pres";
};
- qcom,usb-chgpth@1300 {
+ pm8941_chg_otg: qcom,usb-chgpth@1300 {
reg = <0x1300 0x100>;
interrupts = <0 0x13 0x0>,
<0 0x13 0x1>,
@@ -238,7 +258,7 @@
"coarse-det-dc";
};
- qcom,boost@1500 {
+ pm8941_chg_boost: qcom,boost@1500 {
reg = <0x1500 0x100>;
interrupts = <0x0 0x15 0x0>,
<0x0 0x15 0x1>;
@@ -251,3 +271,15 @@
reg = <0x1600 0x100>;
};
};
+
+In regulator specific device tree file:
+
+ &pm8941_chg_boost {
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-name = "8941_smbb_boost";
+ };
+
+ &pm8941_chg_otg {
+ regulator-name = "8941_smbb_otg";
+ };
diff --git a/arch/arm/boot/dts/fsm9900-rumi.dts b/arch/arm/boot/dts/fsm9900-rumi.dts
new file mode 100644
index 0000000..2b380c7
--- /dev/null
+++ b/arch/arm/boot/dts/fsm9900-rumi.dts
@@ -0,0 +1,31 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "fsm9900.dtsi"
+
+/ {
+ model = "Qualcomm FSM9900 Rumi";
+ compatible = "qcom,fsm9900-rumi", "qcom,fsm9900", "qcom-sim";
+ qcom,msm-id = <188 0 0>;
+
+ aliases {
+ serial0 = &uart0;
+ };
+};
+
+&soc {
+ uart0: serial@f9960000 {
+ status = "ok";
+ };
+};
diff --git a/arch/arm/boot/dts/fsm9900-sim.dts b/arch/arm/boot/dts/fsm9900-sim.dts
new file mode 100644
index 0000000..050929e
--- /dev/null
+++ b/arch/arm/boot/dts/fsm9900-sim.dts
@@ -0,0 +1,32 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "fsm9900.dtsi"
+
+/ {
+ model = "Qualcomm FSM9900 Simulator";
+ compatible = "qcom,fsm9900-sim", "qcom,fsm9900", "qcom-sim";
+ qcom,msm-id = <188 0 0>;
+
+ aliases {
+ serial0 = &uart0;
+ };
+};
+
+&soc {
+ uart0: serial@f9960000 {
+ interrupts = <0 116 0>;
+ status = "ok";
+ };
+};
diff --git a/arch/arm/boot/dts/fsm9900.dtsi b/arch/arm/boot/dts/fsm9900.dtsi
new file mode 100644
index 0000000..766db36
--- /dev/null
+++ b/arch/arm/boot/dts/fsm9900.dtsi
@@ -0,0 +1,94 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/include/ "skeleton64.dtsi"
+
+/ {
+ model = "Qualcomm FSM9900";
+ compatible = "qcom,fsm9900";
+ interrupt-parent = <&intc>;
+ soc: soc { };
+};
+
+&soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0 0 0xffffffff>;
+
+ intc: interrupt-controller@f9000000 {
+ compatible = "qcom,msm-qgic2";
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ reg = <0xF9000000 0x1000>,
+ <0xF9002000 0x1000>;
+ };
+
+ msmgpio: gpio@fd510000 {
+ compatible = "qcom,msm-gpio";
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ reg = <0xfd510000 0x4000>;
+ ngpio = <142>;
+ interrupts = <0 208 0>;
+ qcom,direct-connect-irqs = <5>;
+ };
+
+ timer {
+ compatible = "arm,armv7-timer";
+ interrupts = <1 2 0 1 3 0>;
+ clock-frequency = <19200000>;
+ };
+
+ serial@f9960000 {
+ compatible = "qcom,msm-lsuart-v14";
+ reg = <0xf9960000 0x1000>;
+ interrupts = <0 104 0>;
+ status = "disabled";
+ };
+
+ cpu-pmu {
+ compatible = "qcom,krait-pmu";
+ qcom,irq-is-percpu;
+ interrupts = <1 7 0xf00>;
+ };
+
+ qcom,msm-imem@fe805000 {
+ compatible = "qcom,msm-imem";
+ reg = <0xfe805000 0x1000>; /* Address and size of IMEM */
+ };
+
+ qcom,cache_erp {
+ compatible = "qcom,cache_erp";
+ interrupts = <1 9 0>, <0 2 0>;
+ interrupt-names = "l1_irq", "l2_irq";
+ };
+
+ qcom,cache_dump {
+ compatible = "qcom,cache_dump";
+ qcom,l1-dump-size = <0x100000>;
+ qcom,l2-dump-size = <0x500000>;
+ qcom,memory-reservation-type = "EBI1";
+ qcom,memory-reservation-size = <0x600000>; /* 6M EBI1 buffer */
+ };
+
+ qcom,ion {
+ compatible = "qcom,msm-ion";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ qcom,ion-heap@30 { /* SYSTEM HEAP */
+ reg = <30>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/mpq8092-regulator.dtsi b/arch/arm/boot/dts/mpq8092-regulator.dtsi
index e6866e5..63896e9 100644
--- a/arch/arm/boot/dts/mpq8092-regulator.dtsi
+++ b/arch/arm/boot/dts/mpq8092-regulator.dtsi
@@ -16,6 +16,14 @@
&spmi_bus {
qcom,pma8084@1 {
+ pma8084_s1: regulator@1400 {
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <900000>;
+ qcom,enable-time = <500>;
+ qcom,pull-down-enable = <1>;
+ qcom,system-load = <100000>;
+ status = "okay";
+ };
pma8084_s3: regulator@1a00 {
regulator-min-microvolt = <1350000>;
@@ -53,19 +61,21 @@
status = "okay";
};
- pma8084_s7: regulator@2600 {
- regulator-min-microvolt = <900000>;
- regulator-max-microvolt = <900000>;
+ pma8084_s8: regulator@2900 {
+ regulator-min-microvolt = <1050000>;
+ regulator-max-microvolt = <1050000>;
qcom,enable-time = <500>;
qcom,pull-down-enable = <1>;
status = "okay";
};
- pma8084_s8: regulator@2900 {
+ pma8084_s12: regulator@3500 {
regulator-min-microvolt = <900000>;
regulator-max-microvolt = <900000>;
qcom,enable-time = <500>;
qcom,pull-down-enable = <1>;
+ regulator-always-on;
+ qcom,system-load = <100000>;
status = "okay";
};
@@ -82,8 +92,8 @@
pma8084_l2: regulator@4100 {
parent-supply = <&pma8084_s3>;
- regulator-min-microvolt = <900000>;
- regulator-max-microvolt = <900000>;
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
qcom,enable-time = <200>;
qcom,pull-down-enable = <1>;
status = "okay";
@@ -100,23 +110,14 @@
pma8084_l4: regulator@4300 {
parent-supply = <&pma8084_s3>;
- regulator-min-microvolt = <1000000>;
- regulator-max-microvolt = <1000000>;
+ regulator-min-microvolt = <1300000>;
+ regulator-max-microvolt = <1300000>;
qcom,enable-time = <200>;
qcom,pull-down-enable = <1>;
status = "okay";
};
pma8084_l6: regulator@4500 {
- parent-supply = <&pma8084_s5>;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- qcom,enable-time = <200>;
- qcom,pull-down-enable = <1>;
- status = "okay";
- };
-
- pma8084_l8: regulator@4700 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
qcom,enable-time = <200>;
@@ -133,24 +134,6 @@
};
pma8084_l10: regulator@4900 {
- regulator-min-microvolt = <2000000>;
- regulator-max-microvolt = <2000000>;
- qcom,enable-time = <200>;
- qcom,pull-down-enable = <1>;
- status = "okay";
- };
-
- pma8084_l11: regulator@4a00 {
- parent-supply = <&pma8084_s3>;
- regulator-min-microvolt = <1300000>;
- regulator-max-microvolt = <1300000>;
- qcom,enable-time = <200>;
- qcom,pull-down-enable = <1>;
- status = "okay";
- };
-
- pma8084_l12: regulator@4b00 {
- parent-supply = <&pma8084_s5>;
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
qcom,enable-time = <200>;
@@ -158,25 +141,41 @@
status = "okay";
};
- pma8084_l13: regulator@4c00 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <2950000>;
+ pma8084_l11: regulator@4a00 {
+ parent-supply = <&pma8084_s3>;
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
qcom,enable-time = <200>;
qcom,pull-down-enable = <1>;
status = "okay";
};
+ pma8084_l12: regulator@4b00 {
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <2500000>;
+ qcom,enable-time = <200>;
+ qcom,pull-down-enable = <1>;
+ status = "okay";
+ };
+
+ pma8084_l13: regulator@4c00 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+ qcom,enable-time = <200>;
+ qcom,pull-down-enable = <1>;
+ regulator-always-on;
+ status = "okay";
+ };
+
pma8084_l14: regulator@4d00 {
- parent-supply = <&pma8084_s5>;
- regulator-min-microvolt = <1000000>;
- regulator-max-microvolt = <1000000>;
+ regulator-min-microvolt = <950000>;
+ regulator-max-microvolt = <950000>;
qcom,enable-time = <200>;
qcom,pull-down-enable = <1>;
status = "okay";
};
pma8084_l15: regulator@4e00 {
- parent-supply = <&pma8084_s5>;
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
qcom,enable-time = <200>;
@@ -185,7 +184,7 @@
};
pma8084_l16: regulator@4f00 {
- parent-supply = <&pma8084_s4>;
+ parent-supply = <&pma8084_s5>;
regulator-min-microvolt = <750000>;
regulator-max-microvolt = <750000>;
qcom,enable-time = <200>;
@@ -198,7 +197,6 @@
regulator-max-microvolt = <3150000>;
qcom,enable-time = <200>;
qcom,pull-down-enable = <1>;
- regulator-always-on;
qcom,system-load = <100000>;
status = "okay";
};
@@ -212,7 +210,7 @@
};
pma8084_l19: regulator@5200 {
- parent-supply = <&pma8084_s4>;
+ parent-supply = <&pma8084_s5>;
regulator-min-microvolt = <1500000>;
regulator-max-microvolt = <1500000>;
qcom,enable-time = <200>;
@@ -225,6 +223,7 @@
regulator-max-microvolt = <2950000>;
qcom,enable-time = <200>;
qcom,pull-down-enable = <1>;
+ regulator-always-on;
status = "okay";
};
@@ -233,14 +232,16 @@
regulator-max-microvolt = <2950000>;
qcom,enable-time = <200>;
qcom,pull-down-enable = <1>;
+ regulator-always-on;
status = "okay";
};
pma8084_l22: regulator@5500 {
- regulator-min-microvolt = <2500000>;
- regulator-max-microvolt = <2500000>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
qcom,enable-time = <200>;
qcom,pull-down-enable = <1>;
+ regulator-always-on;
status = "okay";
};
@@ -257,6 +258,31 @@
regulator-max-microvolt = <3075000>;
qcom,enable-time = <200>;
qcom,pull-down-enable = <1>;
+ regulator-always-on;
+ status = "okay";
+ };
+
+ pma8084_l25: regulator@5800 {
+ parent-supply = <&pma8084_s5>;
+ regulator-min-microvolt = <2000000>;
+ regulator-max-microvolt = <2000000>;
+ qcom,enable-time = <200>;
+ qcom,pull-down-enable = <1>;
+ status = "okay";
+ };
+ pma8084_l26: regulator@5900 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,enable-time = <200>;
+ qcom,pull-down-enable = <1>;
+ status = "okay";
+ };
+ pma8084_l27: regulator@5A00 {
+ parent-supply = <&pma8084_s3>;
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ qcom,enable-time = <200>;
+ qcom,pull-down-enable = <1>;
status = "okay";
};
@@ -274,6 +300,20 @@
status = "okay";
};
+ pma8084_lvs3: regulator@8200 {
+ parent-supply = <&pma8084_s4>;
+ qcom,enable-time = <200>;
+ qcom,pull-down-enable = <1>;
+ status = "okay";
+ };
+
+ pma8084_lvs4: regulator@8300 {
+ parent-supply = <&pma8084_s4>;
+ qcom,enable-time = <200>;
+ qcom,pull-down-enable = <1>;
+ status = "okay";
+ };
+
pma8084_mvs1: regulator@8400 {
qcom,enable-time = <200>;
qcom,pull-down-enable = <1>;
diff --git a/arch/arm/boot/dts/msm-pm8226.dtsi b/arch/arm/boot/dts/msm-pm8226.dtsi
index d6d919b..128d90c 100644
--- a/arch/arm/boot/dts/msm-pm8226.dtsi
+++ b/arch/arm/boot/dts/msm-pm8226.dtsi
@@ -211,6 +211,18 @@
label = "mpp";
};
+ qcom,leds@a300 {
+ compatible = "qcom,leds-qpnp";
+ reg = <0xa300 0x100>;
+ label = "mpp";
+ };
+
+ qcom,leds@a500 {
+ compatible = "qcom,leds-qpnp";
+ reg = <0xa500 0x100>;
+ label = "mpp";
+ };
+
pm8226_gpios: gpios {
spmi-dev-container;
compatible = "qcom,qpnp-pin";
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 34ea33d..85a5608 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -247,7 +247,7 @@
};
- qcom,usb-chgpth@1300 {
+ pm8941_chg_otg: qcom,usb-chgpth@1300 {
status = "disabled";
reg = <0x1300 0x100>;
interrupts = <0 0x13 0x0>,
@@ -269,7 +269,7 @@
"dcin-valid";
};
- qcom,boost@1500 {
+ pm8941_chg_boost: qcom,boost@1500 {
status = "disabled";
reg = <0x1500 0x100>;
interrupts = <0x0 0x15 0x0>,
diff --git a/arch/arm/boot/dts/msm8226-cdp.dts b/arch/arm/boot/dts/msm8226-cdp.dts
index b96a9e1..6bbdf9f 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dts
+++ b/arch/arm/boot/dts/msm8226-cdp.dts
@@ -254,11 +254,51 @@
qcom,max-current = <40>;
qcom,current-setting = <5>;
qcom,id = <6>;
- qcom,mode = <2>;
+ qcom,mode = "manual";
qcom,source-sel = <1>;
qcom,mode-ctrl = <0x60>;
};
};
+
+ qcom,leds@a300 {
+ status = "okay";
+ qcom,led_mpp_4 {
+ label = "mpp";
+ linux,name = "green";
+ linux,default-trigger = "none";
+ qcom,default-state = "off";
+ qcom,max-current = <40>;
+ qcom,current-setting = <5>;
+ qcom,id = <6>;
+ qcom,mode = "lpg";
+ qcom,source-sel = <8>;
+ qcom,mode-ctrl = <0x60>;
+ qcom,pwm-channel = <0>;
+ qcom,start-idx = <1>;
+ qcom,duty-pcts = [00 00 00 00 64
+ 64 00 00 00 00];
+ };
+ };
+
+ qcom,leds@a500 {
+ status = "okay";
+ qcom,led_mpp_6 {
+ label = "mpp";
+ linux,name = "red";
+ linux,default-trigger = "none";
+ qcom,default-state = "off";
+ qcom,max-current = <40>;
+ qcom,current-setting = <5>;
+ qcom,id = <6>;
+ qcom,mode-ctrl = <0x60>;
+ qcom,source-sel = <10>;
+ qcom,mode = "lpg";
+ qcom,pwm-channel = <5>;
+ qcom,start-idx = <1>;
+ qcom,duty-pcts = [00 00 00 00 64
+ 64 00 00 00 00];
+ };
+ };
};
qcom,pm8226@1 {
diff --git a/arch/arm/boot/dts/msm8226-mtp.dts b/arch/arm/boot/dts/msm8226-mtp.dts
index 65b71e9..967eb82 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dts
+++ b/arch/arm/boot/dts/msm8226-mtp.dts
@@ -242,11 +242,51 @@
qcom,max-current = <40>;
qcom,current-setting = <5>;
qcom,id = <6>;
- qcom,mode = <2>;
+ qcom,mode = "manual";
qcom,source-sel = <1>;
qcom,mode-ctrl = <0x60>;
};
};
+
+ qcom,leds@a300 {
+ status = "okay";
+ qcom,led_mpp_4 {
+ label = "mpp";
+ linux,name = "green";
+ linux,default-trigger = "none";
+ qcom,default-state = "off";
+ qcom,max-current = <40>;
+ qcom,current-setting = <5>;
+ qcom,id = <6>;
+ qcom,mode = "lpg";
+ qcom,source-sel = <8>;
+ qcom,mode-ctrl = <0x60>;
+ qcom,pwm-channel = <0>;
+ qcom,start-idx = <1>;
+ qcom,duty-pcts = [00 00 00 00 64
+ 64 00 00 00 00];
+ };
+ };
+
+ qcom,leds@a500 {
+ status = "okay";
+ qcom,led_mpp_6 {
+ label = "mpp";
+ linux,name = "red";
+ linux,default-trigger = "none";
+ qcom,default-state = "off";
+ qcom,max-current = <40>;
+ qcom,current-setting = <5>;
+ qcom,id = <6>;
+ qcom,mode-ctrl = <0x60>;
+ qcom,source-sel = <10>;
+ qcom,mode = "lpg";
+ qcom,pwm-channel = <5>;
+ qcom,start-idx = <1>;
+ qcom,duty-pcts = [00 00 00 00 64
+ 64 00 00 00 00];
+ };
+ };
};
qcom,pm8226@1 {
diff --git a/arch/arm/boot/dts/msm8226-qrd.dts b/arch/arm/boot/dts/msm8226-qrd.dts
index aba5c4a..f6e8f8b 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dts
+++ b/arch/arm/boot/dts/msm8226-qrd.dts
@@ -245,11 +245,51 @@
qcom,max-current = <40>;
qcom,current-setting = <5>;
qcom,id = <6>;
- qcom,mode = <2>;
+ qcom,mode = "manual";
qcom,source-sel = <1>;
qcom,mode-ctrl = <0x60>;
};
};
+
+ qcom,leds@a300 {
+ status = "okay";
+ qcom,led_mpp_4 {
+ label = "mpp";
+ linux,name = "green";
+ linux,default-trigger = "none";
+ qcom,default-state = "off";
+ qcom,max-current = <40>;
+ qcom,current-setting = <5>;
+ qcom,id = <6>;
+ qcom,mode = "lpg";
+ qcom,source-sel = <8>;
+ qcom,mode-ctrl = <0x60>;
+ qcom,pwm-channel = <0>;
+ qcom,start-idx = <1>;
+ qcom,duty-pcts = [00 00 00 00 64
+ 64 00 00 00 00];
+ };
+ };
+
+ qcom,leds@a500 {
+ status = "okay";
+ qcom,led_mpp_6 {
+ label = "mpp";
+ linux,name = "red";
+ linux,default-trigger = "none";
+ qcom,default-state = "off";
+ qcom,max-current = <40>;
+ qcom,current-setting = <5>;
+ qcom,id = <6>;
+ qcom,mode-ctrl = <0x60>;
+ qcom,source-sel = <10>;
+ qcom,mode = "lpg";
+ qcom,pwm-channel = <5>;
+ qcom,start-idx = <1>;
+ qcom,duty-pcts = [00 00 00 00 64
+ 64 00 00 00 00];
+ };
+ };
};
qcom,pm8226@1 {
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 753b5b9..dd3bcf6 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -271,6 +271,7 @@
compatible = "qcom,android-usb";
reg = <0xfe8050c8 0xc8>;
qcom,android-usb-cdrom;
+ qcom,android-usb-swfi-latency = <1>;
};
wcd9xxx_intc: wcd9xxx-irq {
diff --git a/arch/arm/boot/dts/msm8610-camera-sensor-cdp-mtp.dtsi b/arch/arm/boot/dts/msm8610-camera-sensor-cdp-mtp.dtsi
new file mode 100644
index 0000000..d057260
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-camera-sensor-cdp-mtp.dtsi
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+&i2c {
+
+ led_flash0: qcom,led-flash@60 {
+ cell-index = <0>;
+ reg = <0x60>;
+ qcom,slave-id = <0x60 0x00 0x0011>;
+ compatible = "qcom,led-flash";
+ qcom,flash-name = "adp1600";
+ qcom,flash-type = <1>;
+ qcom,gpio-no-mux = <0>;
+ gpios = <&msmgpio 18 0>,
+ <&msmgpio 19 0>;
+ qcom,gpio-flash-en = <0>;
+ qcom,gpio-flash-now = <1>;
+ qcom,gpio-req-tbl-num = <0 1>;
+ qcom,gpio-req-tbl-flags = <0 0>;
+ qcom,gpio-req-tbl-label = "FLASH_EN",
+ "FLASH_NOW";
+ };
+
+ actuator0: qcom,actuator@6e {
+ cell-index = <3>;
+ reg = <0x6c>;
+ compatible = "qcom,actuator";
+ qcom,cci-master = <0>;
+ };
+
+ qcom,camera@6f {
+ compatible = "qcom,ov8825";
+ reg = <0x6f>;
+ qcom,slave-id = <0x6c 0x300a 0x8825>;
+ qcom,csiphy-sd-index = <0>;
+ qcom,csid-sd-index = <0>;
+ qcom,actuator-src = <&actuator0>;
+ qcom,led-flash-src = <&led_flash0>;
+ qcom,mount-angle = <90>;
+ qcom,sensor-name = "ov8825";
+ cam_vdig-supply = <&pm8110_l2>;
+ cam_vana-supply = <&pm8110_l19>;
+ cam_vio-supply = <&pm8110_l14>;
+ cam_vaf-supply = <&pm8110_l16>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_vaf";
+ qcom,cam-vreg-type = <0 0 0 0>;
+ qcom,cam-vreg-min-voltage = <1200000 1800000 2850000 3000000>;
+ qcom,cam-vreg-max-voltage = <1200000 1800000 2850000 3000000>;
+ qcom,cam-vreg-op-mode = <200000 8000 80000 100000>;
+ qcom,gpio-no-mux = <0>;
+ gpios = <&msmgpio 13 0>,
+ <&msmgpio 21 0>,
+ <&msmgpio 20 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+ "CAM_RESET1",
+ "CAM_STANDBY";
+ qcom,csi-lane-assign = <0xe4>;
+ qcom,csi-lane-mask = <0x3>;
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <1>;
+ qcom,cci-master = <0>;
+ };
+
+ qcom,camera@6d {
+ compatible = "qcom,ov9724";
+ reg = <0x6d>;
+ qcom,slave-id = <0x20 0x0 0x9724>;
+ qcom,csiphy-sd-index = <1>;
+ qcom,csid-sd-index = <0>;
+ qcom,mount-angle = <90>;
+ qcom,sensor-name = "ov9724";
+ cam_vdig-supply = <&pm8110_l4>;
+ cam_vana-supply = <&pm8110_l19>;
+ cam_vio-supply = <&pm8110_l14>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+ qcom,cam-vreg-type = <0 1 0>;
+ qcom,cam-vreg-min-voltage = <1200000 0 2850000>;
+ qcom,cam-vreg-max-voltage = <1200000 0 2850000>;
+ qcom,cam-vreg-op-mode = <200000 0 80000>;
+ qcom,gpio-no-mux = <0>;
+ gpios = <&msmgpio 14 0>,
+ <&msmgpio 15 0>,
+ <&msmgpio 8 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+ "CAM_RESET",
+ "CAM_STANDBY";
+ qcom,gpio-set-tbl-num = <1 1>;
+ qcom,gpio-set-tbl-flags = <0 2>;
+ qcom,gpio-set-tbl-delay = <1000 4000>;
+ qcom,csi-lane-assign = <0xe4>;
+ qcom,csi-lane-mask = <0x1>;
+ qcom,sensor-position = <1>;
+ qcom,sensor-mode = <1>;
+ qcom,cci-master = <0>;
+ status = "ok";
+ };
+};
diff --git a/arch/arm/boot/dts/msm8610-camera.dtsi b/arch/arm/boot/dts/msm8610-camera.dtsi
new file mode 100644
index 0000000..b1c94dd
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-camera.dtsi
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+&soc{
+ qcom,msm-cam@fd8c0000 {
+ compatible = "qcom,msm-cam";
+ reg = <0xfd8C0000 0x10000>;
+ reg-names = "msm-cam";
+ };
+
+ qcom,csiphy@fda00c00 {
+ cell-index = <0>;
+ compatible = "qcom,csiphy";
+ reg = <0xfda00c00 0x1f4>;
+ reg-names = "csiphy";
+ interrupts = <0 78 0>;
+ interrupt-names = "csiphy";
+ };
+
+ qcom,csiphy@fda01000 {
+ cell-index = <1>;
+ compatible = "qcom,csiphy";
+ reg = <0xfda01000 0x1f4>;
+ reg-names = "csiphy";
+ interrupts = <0 79 0>;
+ interrupt-names = "csiphy";
+ };
+
+ qcom,csid@fda00000 {
+ cell-index = <0>;
+ compatible = "qcom,csid";
+ reg = <0xfda00000 0x100>;
+ reg-names = "csid";
+ interrupts = <0 50 0>;
+ interrupt-names = "csid";
+ qcom,csi-vdd-voltage = <1200000>;
+ qcom,mipi-csi-vdd-supply = <&pm8110_l4>;
+ };
+
+ qcom,csid@fda00400 {
+ cell-index = <1>;
+ compatible = "qcom,csid";
+ reg = <0xfda00400 0x100>;
+ reg-names = "csid";
+ interrupts = <0 51 0>;
+ interrupt-names = "csid";
+ qcom,csi-vdd-voltage = <1200000>;
+ qcom,mipi-csi-vdd-supply = <&pm8110_l4>;
+ };
+
+ qcom,ispif@fda00800 {
+ cell-index = <0>;
+ compatible = "qcom,ispif";
+ reg = <0xfda00800 0x200>;
+ reg-names = "ispif";
+ interrupts = <0 52 0>;
+ interrupt-names = "ispif";
+ };
+
+ qcom,vfe@fde00000 {
+ cell-index = <0>;
+ compatible = "qcom,vfe32";
+ reg = <0xfde00000 0x800>;
+ reg-names = "vfe", "vfe_vbif";
+ interrupts = <0 49 0>;
+ interrupt-names = "vfe";
+ vdd-supply = <&gdsc_vfe>;
+ };
+
+};
diff --git a/arch/arm/boot/dts/msm8610-cdp.dts b/arch/arm/boot/dts/msm8610-cdp.dts
index d7fe3cf..257a41c 100644
--- a/arch/arm/boot/dts/msm8610-cdp.dts
+++ b/arch/arm/boot/dts/msm8610-cdp.dts
@@ -14,6 +14,7 @@
/include/ "msm8610.dtsi"
/include/ "dsi-v2-panel-truly-wvga-video.dtsi"
+/include/ "msm8610-camera-sensor-cdp-mtp.dtsi"
/ {
model = "Qualcomm MSM 8610 CDP";
diff --git a/arch/arm/boot/dts/msm8610-mdss.dtsi b/arch/arm/boot/dts/msm8610-mdss.dtsi
index 1766422..af0e3e4 100644
--- a/arch/arm/boot/dts/msm8610-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8610-mdss.dtsi
@@ -21,7 +21,7 @@
cell-index = <0>;
compatible = "qcom,mdss-fb";
qcom,memory-reservation-type = "EBI1";
- qcom,memory-reservation-size = <0x800000>;
+ qcom,memory-reservation-size = <0x300000>;
};
};
diff --git a/arch/arm/boot/dts/msm8610-mtp.dts b/arch/arm/boot/dts/msm8610-mtp.dts
index e7fe9ca..abd4228 100644
--- a/arch/arm/boot/dts/msm8610-mtp.dts
+++ b/arch/arm/boot/dts/msm8610-mtp.dts
@@ -14,6 +14,7 @@
/include/ "msm8610.dtsi"
/include/ "dsi-v2-panel-truly-wvga-video.dtsi"
+/include/ "msm8610-camera-sensor-cdp-mtp.dtsi"
/ {
model = "Qualcomm MSM 8610 MTP";
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index ca3e7ca..689392c 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -33,6 +33,7 @@
soc: soc { };
};
+/include/ "msm8610-camera.dtsi"
/include/ "msm-iommu-v0.dtsi"
/include/ "msm8610-ion.dtsi"
/include/ "msm8610-gpu.dtsi"
@@ -472,7 +473,7 @@
qcom,i2c-bus-freq = <100000>;
};
- i2c@f9928000 { /* BLSP1 QUP6 */
+ i2c: i2c@f9928000 { /* BLSP1 QUP6 */
cell-index = <6>;
compatible = "qcom,i2c-qup";
#address-cells = <1>;
diff --git a/arch/arm/boot/dts/msm8974-fluid.dtsi b/arch/arm/boot/dts/msm8974-fluid.dtsi
index ad5f175..a822af5 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-fluid.dtsi
@@ -608,12 +608,6 @@
};
mpp@a400 { /* MPP 5 */
- /* SPI_ETH config */
- qcom,mode = <1>; /* DIG_OUT */
- qcom,output-type = <0>; /* CMOS */
- qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
- qcom,src-sel = <0>; /* CONSTANT */
- qcom,master-en = <1>; /* ENABLE MPP */
};
mpp@a500 { /* MPP 6 */
diff --git a/arch/arm/boot/dts/msm8974-leds.dtsi b/arch/arm/boot/dts/msm8974-leds.dtsi
index c4780b0..5e91f45 100644
--- a/arch/arm/boot/dts/msm8974-leds.dtsi
+++ b/arch/arm/boot/dts/msm8974-leds.dtsi
@@ -18,7 +18,7 @@
qcom,rgb_0 {
label = "rgb";
linux,name = "led:rgb_red";
- qcom,mode = <0>;
+ qcom,mode = "pwm";
qcom,pwm-channel = <6>;
qcom,pwm-us = <1000>;
qcom,max-current = <12>;
@@ -31,7 +31,7 @@
qcom,rgb_1 {
label = "rgb";
linux,name = "led:rgb_green";
- qcom,mode = <0>;
+ qcom,mode = "pwm";
qcom,pwm-channel = <5>;
qcom,pwm-us = <1000>;
qcom,max-current = <12>;
@@ -43,7 +43,7 @@
qcom,rgb_2 {
label = "rgb";
linux,name = "led:rgb_blue";
- qcom,mode = <0>;
+ qcom,mode = "pwm";
qcom,pwm-channel = <4>;
qcom,pwm-us = <1000>;
qcom,max-current = <12>;
diff --git a/arch/arm/boot/dts/msm8974-liquid.dtsi b/arch/arm/boot/dts/msm8974-liquid.dtsi
index c2dae28..b30d65c 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-liquid.dtsi
@@ -424,10 +424,6 @@
qcom,otg-capability;
};
-&pm8941_mvs1 {
- parent-supply = <&ext_5v>;
-};
-
&pm8941_mvs2 {
parent-supply = <&ext_5v>;
};
@@ -777,6 +773,7 @@
&pm8941_chg {
status = "ok";
+ otg-parent-supply = <&ext_5v>;
qcom,charging-disabled;
diff --git a/arch/arm/boot/dts/msm8974-mtp.dtsi b/arch/arm/boot/dts/msm8974-mtp.dtsi
index 4d28a1d..e798fc0 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-mtp.dtsi
@@ -637,13 +637,6 @@
};
mpp@a400 { /* MPP 5 */
- /* SPI_ETH config */
- qcom,mode = <1>; /* DIG_OUT */
- qcom,output-type = <0>; /* CMOS */
- qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
- qcom,src-sel = <0>; /* CONSTANT */
- qcom,out-strength = <1>; /* QPNP_PIN_OUT_STRENGTH_LOW */
- qcom,master-en = <1>; /* ENABLE MPP */
};
mpp@a500 { /* MPP 6 */
diff --git a/arch/arm/boot/dts/msm8974-regulator.dtsi b/arch/arm/boot/dts/msm8974-regulator.dtsi
index 35f3993..2114686 100644
--- a/arch/arm/boot/dts/msm8974-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974-regulator.dtsi
@@ -25,7 +25,7 @@
};
pm8941_mvs1: regulator@8300 {
- parent-supply = <&pm8941_boost>;
+ parent-supply = <&pm8941_chg_otg>;
qcom,enable-time = <1000>;
qcom,pull-down-enable = <1>;
interrupts = <0x1 0x83 0x2>;
@@ -552,3 +552,17 @@
regulator-always-on;
};
};
+
+&pm8941_chg {
+ otg-parent-supply = <&pm8941_boost>;
+};
+
+&pm8941_chg_boost {
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-name = "8941_smbb_boost";
+};
+
+&pm8941_chg_otg {
+ regulator-name = "8941_smbb_otg";
+};
diff --git a/arch/arm/boot/dts/msm8974-v2-mtp.dts b/arch/arm/boot/dts/msm8974-v2-mtp.dts
index 1735515..792a78c 100644
--- a/arch/arm/boot/dts/msm8974-v2-mtp.dts
+++ b/arch/arm/boot/dts/msm8974-v2-mtp.dts
@@ -36,5 +36,5 @@
};
&pm8941_chg {
- qcom,bpd-detection = "bpd_id";
+ qcom,bpd-detection = "bpd_thm";
};
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index ea95f72..4367807 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -767,6 +767,7 @@
interrupt-names = "qup_err_intr";
qcom,i2c-bus-freq = <100000>;
qcom,i2c-src-freq = <50000000>;
+ qcom,master-id = <84>;
};
i2c_1: i2c@f9923000 {
@@ -782,6 +783,7 @@
qcom,i2c-src-freq = <19200000>;
qcom,scl-gpio = <&msmgpio 3 0>;
qcom,sda-gpio = <&msmgpio 2 0>;
+ qcom,master-id = <86>;
status = "disabled";
};
@@ -796,6 +798,7 @@
interrupt-names = "qup_err_intr";
qcom,i2c-bus-freq = <100000>;
qcom,i2c-src-freq = <50000000>;
+ qcom,master-id = <86>;
};
spi_0: spi@f9923000 {
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index ca09370..bb1ea3d 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -256,7 +256,7 @@
qcom,dst-bam-physical-address = <0xf9a04000>;
qcom,dst-bam-pipe-index = <3>;
qcom,data-fifo-size = <0xD480>;
- qcom,descriptor-fifo-size = <0x1A80>;
+ qcom,descriptor-fifo-size = <0x3200>;
qcom,reset-bam-on-connect;
};
qcom,pipe4 {
@@ -269,7 +269,7 @@
qcom,dst-bam-physical-address = <0xf9a04000>;
qcom,dst-bam-pipe-index = <4>;
qcom,data-fifo-size = <0xD480>;
- qcom,descriptor-fifo-size = <0x1A80>;
+ qcom,descriptor-fifo-size = <0x3200>;
qcom,reset-bam-on-connect;
};
qcom,pipe5 {
@@ -282,7 +282,7 @@
qcom,dst-bam-physical-address = <0xf9a04000>;
qcom,dst-bam-pipe-index = <5>;
qcom,data-fifo-size = <0xD480>;
- qcom,descriptor-fifo-size = <0x1A80>;
+ qcom,descriptor-fifo-size = <0x3200>;
qcom,reset-bam-on-connect;
};
qcom,pipe6 {
@@ -295,7 +295,7 @@
qcom,dst-bam-physical-address = <0xf9a04000>;
qcom,dst-bam-pipe-index = <6>;
qcom,data-fifo-size = <0xD480>;
- qcom,descriptor-fifo-size = <0x1A80>;
+ qcom,descriptor-fifo-size = <0x3200>;
qcom,reset-bam-on-connect;
};
qcom,pipe7 {
@@ -307,8 +307,8 @@
qcom,peer-bam = <2>;
qcom,src-bam-physical-address = <0xf9a04000>;
qcom,src-bam-pipe-index = <7>;
- qcom,data-fifo-size = <0xD480>;
- qcom,descriptor-fifo-size = <0x1A80>;
+ qcom,data-fifo-size = <0xDFE>;
+ qcom,descriptor-fifo-size = <0xB30>;
qcom,reset-bam-on-connect;
};
};
diff --git a/arch/arm/configs/apq8084_defconfig b/arch/arm/configs/apq8084_defconfig
index c0084bf..549bc73 100644
--- a/arch/arm/configs/apq8084_defconfig
+++ b/arch/arm/configs/apq8084_defconfig
@@ -49,6 +49,7 @@
CONFIG_MSM_IPC_ROUTER=y
CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
CONFIG_MSM_IPC_ROUTER_SECURITY=y
+CONFIG_MSM_QMI_INTERFACE=y
# CONFIG_MSM_HW3D is not set
CONFIG_MSM_RPM_REGULATOR_SMD=y
CONFIG_MSM_SUBSYSTEM_RESTART=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 108a68f..6b62269 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -306,6 +306,7 @@
select ARCH_WANT_KMAP_ATOMIC_FLUSH
select MEMORY_HOLE_CARVEOUT
select DONT_MAP_HOLE_AFTER_MEMBANK0
+ select QMI_ENCDEC
config ARCH_MPQ8092
bool "MPQ8092"
@@ -2721,14 +2722,25 @@
related operations of OCMEM. Both local power management
and RPM assisted power management operations are supported.
-config MSM_OCMEM_POWER_DISABLE
- bool "OCMEM Disable Power Control"
+config MSM_OCMEM_DEBUG_ALWAYS_ON
+ bool "Keep OCMEM always turned ON"
depends on MSM_OCMEM_DEBUG
help
+ Always vote for all OCMEM clocks and keep all OCMEM
+ macros turned ON and never allow them to be turned OFF.
+ Both local power management and RPM assisted power modes
+ are supported for individual macro power control operations.
+
+config MSM_OCMEM_POWER_DISABLE
+ bool "OCMEM Disable Power Control"
+ depends on MSM_OCMEM
+ help
Disable all OCMEM power management.
- This keeps all OCMEM macros turned ON at all times thus
- never allowing them to be turned OFF. Both local power
- management and RPM assisted power modes are supported.
+ Skip all OCMEM power operations that turn ON or
+ turn OFF the macros. Both local power management and
+ RPM assisted power management operations are skipped.
+ Enable this configuration if OCMEM is being exclusively
+ used as GMEM or OCIMEM.
config SENSORS_ADSP
bool "Enable Sensors Driver Support for ADSP"
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index f969e31..372f8ba 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -85,7 +85,6 @@
#include "pm.h"
#include "pm-boot.h"
#include "devices-msm8x60.h"
-#include "smd_private.h"
#include "platsmp.h"
#define MHL_GPIO_INT 30
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index ccea956..e097faf 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -96,7 +96,6 @@
#include "rpm_resources.h"
#include <mach/mpm.h>
#include "clock.h"
-#include "smd_private.h"
#include "pm-boot.h"
#include "msm_watchdog.h"
#include "board-8930.h"
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index cb88cdc..b45e690 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -98,7 +98,6 @@
#include "rpm_resources.h"
#include <mach/mpm.h>
#include "clock.h"
-#include "smd_private.h"
#include "pm-boot.h"
#include "msm_watchdog.h"
#include "platsmp.h"
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index 76dbaef..c8a88d7 100644
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -1001,7 +1001,6 @@
},
};
-#ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
static struct gpiomux_setting sdc3_clk_actv_cfg = {
.func = GPIOMUX_FUNC_2,
.drv = GPIOMUX_DRV_8MA,
@@ -1082,9 +1081,6 @@
msm_gpiomux_install(msm8974_sdc3_configs,
ARRAY_SIZE(msm8974_sdc3_configs));
}
-#else
-static void msm_gpiomux_sdc3_install(void) {}
-#endif /* CONFIG_MMC_MSM_SDC3_SUPPORT */
#ifdef CONFIG_MMC_MSM_SDC4_SUPPORT
static struct gpiomux_setting sdc4_clk_actv_cfg = {
@@ -1219,7 +1215,11 @@
msm_gpiomux_install(msm_sensor_configs, ARRAY_SIZE(msm_sensor_configs));
msm_gpiomux_install(&sd_card_det, 1);
- msm_gpiomux_sdc3_install();
+
+ if (machine_is_apq8074() && (of_board_is_liquid() || \
+ of_board_is_dragonboard()))
+ msm_gpiomux_sdc3_install();
+
msm_gpiomux_sdc4_install();
msm_gpiomux_install(msm_taiko_config, ARRAY_SIZE(msm_taiko_config));
diff --git a/arch/arm/mach-msm/clock-local2.c b/arch/arm/mach-msm/clock-local2.c
index fff517a..24af44e 100644
--- a/arch/arm/mach-msm/clock-local2.c
+++ b/arch/arm/mach-msm/clock-local2.c
@@ -175,39 +175,19 @@
cf = rcg->current_freq;
- /* Enable source clock dependency for the new freq. */
- if (c->prepare_count) {
- rc = clk_prepare(nf->src_clk);
- if (rc)
- return rc;
- }
-
- spin_lock_irqsave(&c->lock, flags);
- if (c->count) {
- rc = clk_enable(nf->src_clk);
- if (rc) {
- spin_unlock_irqrestore(&c->lock, flags);
- clk_unprepare(nf->src_clk);
- return rc;
- }
- }
+ rc = __clk_pre_reparent(c, nf->src_clk, &flags);
+ if (rc)
+ return rc;
BUG_ON(!rcg->set_rate);
/* Perform clock-specific frequency switch operations. */
rcg->set_rate(rcg, nf);
-
- /* Release source requirements of the old freq. */
- if (c->count)
- clk_disable(cf->src_clk);
- spin_unlock_irqrestore(&c->lock, flags);
-
- if (c->prepare_count)
- clk_unprepare(cf->src_clk);
-
rcg->current_freq = nf;
c->parent = nf->src_clk;
+ __clk_post_reparent(c, cf->src_clk, &flags);
+
return 0;
}
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index 608018c..582bccf 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -475,7 +475,7 @@
mutex_lock(&clk->prepare_lock);
/* Return early if the rate isn't going to change */
- if (clk->rate == rate)
+ if (clk->rate == rate && !(clk->flags & CLKFLAG_NO_RATE_CACHE))
goto out;
trace_clock_set_rate(name, rate, raw_smp_processor_id());
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index d3ef0be..7b26bd6 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -510,6 +510,15 @@
bool mhl_enabled;
};
+/**
+ * msm_i2c_platform_data: i2c-qup driver configuration data
+ *
+ * @active_only when set, votes when system active and removes the vote when
+ * system goes idle (optimises for performance). When unset, voting using
+ * runtime pm (optimizes for power).
+ * @master_id master id number of the i2c core or its wrapper (BLSP/GSBI).
+ * When zero, clock path voting is disabled.
+ */
struct msm_i2c_platform_data {
int clk_freq;
uint32_t rmutex;
@@ -523,6 +532,8 @@
int use_gsbi_shared_mode;
int keep_ahb_clk_on;
void (*msm_i2c_config_gpio)(int iface, int config_type);
+ bool active_only;
+ uint32_t master_id;
};
struct msm_i2c_ssbi_platform_data {
diff --git a/arch/arm/mach-msm/include/mach/clk.h b/arch/arm/mach-msm/include/mach/clk.h
index 1809456..fae0777 100644
--- a/arch/arm/mach-msm/include/mach/clk.h
+++ b/arch/arm/mach-msm/include/mach/clk.h
@@ -25,6 +25,7 @@
#define CLKFLAG_MAX 0x00000800
#define CLKFLAG_INIT_DONE 0x00001000
#define CLKFLAG_INIT_ERR 0x00002000
+#define CLKFLAG_NO_RATE_CACHE 0x00004000
struct clk_lookup;
struct clk;
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index 676df66..7b73333 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -81,16 +81,6 @@
#define MSM_LPASS_CLK_CTL_BASE IOMEM(0xFA015000) /* 4K */
#define MSM_HFPLL_BASE IOMEM(0xFA016000) /* 4K */
#define MSM_TLMM_BASE IOMEM(0xFA017000) /* 16K */
-#define MSM_SHARED_RAM_BASE IOMEM(0xFA400000) /* 2M */
-#define MSM_SIC_NON_SECURE_BASE IOMEM(0xFA600000) /* 64K */
-#define MSM_HDMI_BASE IOMEM(0xFA800000) /* 4K */
-#define MSM_RPM_BASE IOMEM(0xFA801000) /* 4K */
-#define MSM_RPM_MPM_BASE IOMEM(0xFA802000) /* 4K */
-#define MSM_QFPROM_BASE IOMEM(0xFA700000) /* 4K */
-#define MSM_L2CC_BASE IOMEM(0xFA701000) /* 4K */
-#define MSM_APCS_GLB_BASE IOMEM(0xFA702000) /* 4K */
-#define MSM_SAW2_BASE IOMEM(0xFA703000) /* 4k */
-#define MSM_SAW3_BASE IOMEM(0xFA704000) /* 4k */
#define MSM_VIC_BASE IOMEM(0xFA100000) /* 4K */
#define MSM_CSR_BASE IOMEM(0xFA101000) /* 4K */
#define MSM_GPIO1_BASE IOMEM(0xFA102000) /* 4K */
@@ -99,7 +89,16 @@
#define MSM_CFG_CTL_BASE IOMEM(0xFA105000) /* 4K */
#define MSM_CLK_CTL_SH2_BASE IOMEM(0xFA106000) /* 4K */
#define MSM_MPM2_PSHOLD_BASE IOMEM(0xFA107000) /* 4k */
-#define MSM_MDC_BASE IOMEM(0xFA400000) /* 1M */
+#define MSM_SHARED_RAM_BASE IOMEM(0xFA400000) /* 2M */
+#define MSM_SIC_NON_SECURE_BASE IOMEM(0xFA600000) /* 64K */
+#define MSM_QFPROM_BASE IOMEM(0xFA700000) /* 4K */
+#define MSM_L2CC_BASE IOMEM(0xFA701000) /* 4K */
+#define MSM_APCS_GLB_BASE IOMEM(0xFA702000) /* 4K */
+#define MSM_SAW2_BASE IOMEM(0xFA703000) /* 4k */
+#define MSM_SAW3_BASE IOMEM(0xFA704000) /* 4k */
+#define MSM_HDMI_BASE IOMEM(0xFA800000) /* 4K */
+#define MSM_RPM_BASE IOMEM(0xFA801000) /* 4K */
+#define MSM_RPM_MPM_BASE IOMEM(0xFA802000) /* 4K */
#define MSM_AD5_BASE IOMEM(0xFA900000) /* 13M (D00000)
0xFB600000 */
/* MSM9625 has unaligned imem so we need to map excess 2K virtually
diff --git a/arch/arm/mach-msm/include/mach/msm_ipc_router.h b/arch/arm/mach-msm/include/mach/msm_ipc_router.h
index 894379e..5dc1095 100644
--- a/arch/arm/mach-msm/include/mach/msm_ipc_router.h
+++ b/arch/arm/mach-msm/include/mach/msm_ipc_router.h
@@ -46,9 +46,6 @@
spinlock_t port_lock;
struct comm_mode_info mode_info;
- struct list_head incomplete;
- struct mutex incomplete_lock;
-
struct list_head port_rx_q;
struct mutex port_rx_q_lock;
char rx_wakelock_name[MAX_WAKELOCK_NAME_SZ];
diff --git a/arch/arm/mach-msm/include/mach/msm_memtypes.h b/arch/arm/mach-msm/include/mach/msm_memtypes.h
index 3bf05e6..5c8f525 100644
--- a/arch/arm/mach-msm/include/mach/msm_memtypes.h
+++ b/arch/arm/mach-msm/include/mach/msm_memtypes.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2011, 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,6 +39,15 @@
MEMTYPE_MAX,
};
+enum {
+ SYS_MEMORY = 1, /* system memory*/
+ BOOT_REGION_MEMORY1, /* boot loader memory 1*/
+ BOOT_REGION_MEMORY2, /* boot loader memory 2,reserved*/
+ APPSBL_MEMORY, /* apps boot loader memory*/
+ APPS_MEMORY, /* apps usage memory*/
+};
+
+
void msm_reserve(void);
#define MEMTYPE_FLAGS_FIXED 0x1
diff --git a/arch/arm/mach-msm/include/mach/sps.h b/arch/arm/mach-msm/include/mach/sps.h
index c5ad35d..3332701 100644
--- a/arch/arm/mach-msm/include/mach/sps.h
+++ b/arch/arm/mach-msm/include/mach/sps.h
@@ -1271,6 +1271,15 @@
int sps_get_bam_debug_info(u32 dev, u32 option, u32 para,
u32 tb_sel, u32 desc_sel);
+/**
+ * Vote for or relinquish BAM DMA clock
+ *
+ * @clk_on - to turn on or turn off the clock
+ *
+ * @return 0 on success, negative value on error
+ *
+ */
+int sps_ctrl_bam_dma_clk(bool clk_on);
#else
static inline int sps_register_bam_device(const struct sps_bam_props
*bam_props, u32 *dev_handle)
@@ -1433,6 +1442,11 @@
{
return -EPERM;
}
+
+static inline int sps_ctrl_bam_dma_clk(bool clk_on)
+{
+ return -EPERM;
+}
#endif
#endif /* _SPS_H_ */
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index 73e960f..7fb2c88 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -69,7 +69,6 @@
MSM_CHIP_DEVICE(GPIO2, MSM7XXX),
MSM_CHIP_DEVICE(CLK_CTL, MSM7XXX),
MSM_CHIP_DEVICE(AD5, MSM7XXX),
- MSM_CHIP_DEVICE(MDC, MSM7XXX),
#if defined(CONFIG_DEBUG_MSM_UART1) || defined(CONFIG_DEBUG_MSM_UART2) || \
defined(CONFIG_DEBUG_MSM_UART3)
MSM_DEVICE(DEBUG_UART),
@@ -117,7 +116,6 @@
MSM_DEVICE(SIRC),
MSM_DEVICE(SCPLL),
MSM_DEVICE(AD5),
- MSM_DEVICE(MDC),
MSM_DEVICE(TCSR),
#if defined(CONFIG_DEBUG_MSM_UART1) || defined(CONFIG_DEBUG_MSM_UART2) || \
defined(CONFIG_DEBUG_MSM_UART3)
@@ -353,7 +351,6 @@
MSM_CHIP_DEVICE(CLK_CTL, MSM7X30),
MSM_CHIP_DEVICE(CLK_CTL_SH2, MSM7X30),
MSM_CHIP_DEVICE(AD5, MSM7X30),
- MSM_CHIP_DEVICE(MDC, MSM7X30),
MSM_CHIP_DEVICE(ACC0, MSM7X30),
MSM_CHIP_DEVICE(SAW0, MSM7X30),
MSM_CHIP_DEVICE(APCS_GCC, MSM7X30),
@@ -476,7 +473,6 @@
MSM_CHIP_DEVICE(SAW2, MSM8625),
MSM_CHIP_DEVICE(SAW3, MSM8625),
MSM_CHIP_DEVICE(AD5, MSM7XXX),
- MSM_CHIP_DEVICE(MDC, MSM7XXX),
#if defined(CONFIG_DEBUG_MSM_UART1) || defined(CONFIG_DEBUG_MSM_UART2) || \
defined(CONFIG_DEBUG_MSM_UART3)
MSM_DEVICE(DEBUG_UART),
diff --git a/arch/arm/mach-msm/ipc_router.c b/arch/arm/mach-msm/ipc_router.c
index f95ef3b..573b9a3 100644
--- a/arch/arm/mach-msm/ipc_router.c
+++ b/arch/arm/mach-msm/ipc_router.c
@@ -115,7 +115,6 @@
#define SRV_HASH_SIZE 32
static struct list_head server_list[SRV_HASH_SIZE];
static DEFINE_MUTEX(server_list_lock);
-static wait_queue_head_t newserver_wait;
struct msm_ipc_server {
struct list_head list;
@@ -182,9 +181,6 @@
static DEFINE_MUTEX(routing_table_lock);
static int routing_table_inited;
-static LIST_HEAD(msm_ipc_board_dev_list);
-static DEFINE_MUTEX(msm_ipc_board_dev_list_lock);
-
static void do_read_data(struct work_struct *work);
#define RR_STATE_IDLE 0
@@ -586,8 +582,6 @@
}
spin_lock_init(&port_ptr->port_lock);
- INIT_LIST_HEAD(&port_ptr->incomplete);
- mutex_init(&port_ptr->incomplete_lock);
INIT_LIST_HEAD(&port_ptr->port_rx_q);
mutex_init(&port_ptr->port_rx_q_lock);
init_waitqueue_head(&port_ptr->port_rx_wait_q);
@@ -3120,7 +3114,6 @@
}
mutex_unlock(&routing_table_lock);
- init_waitqueue_head(&newserver_wait);
init_waitqueue_head(&subsystem_restart_wait);
ret = msm_ipc_router_init_sockets();
if (ret < 0)
diff --git a/arch/arm/mach-msm/memory_topology.c b/arch/arm/mach-msm/memory_topology.c
index 97195e3..de90427 100644
--- a/arch/arm/mach-msm/memory_topology.c
+++ b/arch/arm/mach-msm/memory_topology.c
@@ -20,12 +20,44 @@
#include <mach/msm_memtypes.h>
#include <mach/socinfo.h>
#include <mach/msm_smem.h>
-#include "smd_private.h"
#if defined(CONFIG_ARCH_MSM8960)
#include "rpm_resources.h"
#endif
+struct smem_ram_ptn {
+ char name[16];
+ unsigned start;
+ unsigned size;
+
+ /* RAM Partition attribute: READ_ONLY, READWRITE etc. */
+ unsigned attr;
+
+ /* RAM Partition category: EBI0, EBI1, IRAM, IMEM */
+ unsigned category;
+
+ /* RAM Partition domain: APPS, MODEM, APPS & MODEM (SHARED) etc. */
+ unsigned domain;
+
+ /* RAM Partition type: system, bootloader, appsboot, apps etc. */
+ unsigned type;
+
+ /* reserved for future expansion without changing version number */
+ unsigned reserved2, reserved3, reserved4, reserved5;
+} __attribute__ ((__packed__));
+
+
+struct smem_ram_ptable {
+ #define _SMEM_RAM_PTABLE_MAGIC_1 0x9DA5E0A8
+ #define _SMEM_RAM_PTABLE_MAGIC_2 0xAF9EC4E2
+ unsigned magic[2];
+ unsigned version;
+ unsigned reserved1;
+ unsigned len;
+ struct smem_ram_ptn parts[32];
+ unsigned buf;
+} __attribute__ ((__packed__));
+
static struct mem_region_t {
u64 start;
u64 size;
diff --git a/arch/arm/mach-msm/ocmem_core.c b/arch/arm/mach-msm/ocmem_core.c
index 9b18c59..153864d 100644
--- a/arch/arm/mach-msm/ocmem_core.c
+++ b/arch/arm/mach-msm/ocmem_core.c
@@ -759,7 +759,7 @@
return -EINVAL;
}
-#if defined(CONFIG_MSM_OCMEM_POWER_DISABLE)
+#if defined(CONFIG_MSM_OCMEM_DEBUG_ALWAYS_ON)
static int ocmem_core_set_default_state(void)
{
int rc = 0;
@@ -775,7 +775,14 @@
return 0;
}
+#else
+static int ocmem_core_set_default_state(void)
+{
+ return 0;
+}
+#endif
+#if defined(CONFIG_MSM_OCMEM_POWER_DISABLE)
/* Initializes a region to be turned ON in wide mode */
static int ocmem_region_set_default_state(unsigned int r_num)
{
@@ -800,15 +807,9 @@
{
return 0;
}
-
-static int ocmem_core_set_default_state(void)
-{
- return 0;
-}
#endif
#if defined(CONFIG_MSM_OCMEM_POWER_DEBUG)
-
static int read_hw_region_state(unsigned region_num)
{
int state;
diff --git a/arch/arm/mach-msm/smd_private.h b/arch/arm/mach-msm/smd_private.h
index 4fe9592..2096063 100644
--- a/arch/arm/mach-msm/smd_private.h
+++ b/arch/arm/mach-msm/smd_private.h
@@ -155,27 +155,6 @@
struct smd_half_channel_access *get_half_ch_funcs(unsigned ch_type);
-struct smem_ram_ptn {
- char name[16];
- unsigned start;
- unsigned size;
-
- /* RAM Partition attribute: READ_ONLY, READWRITE etc. */
- unsigned attr;
-
- /* RAM Partition category: EBI0, EBI1, IRAM, IMEM */
- unsigned category;
-
- /* RAM Partition domain: APPS, MODEM, APPS & MODEM (SHARED) etc. */
- unsigned domain;
-
- /* RAM Partition type: system, bootloader, appsboot, apps etc. */
- unsigned type;
-
- /* reserved for future expansion without changing version number */
- unsigned reserved2, reserved3, reserved4, reserved5;
-} __attribute__ ((__packed__));
-
struct smd_channel {
volatile void __iomem *send; /* some variant of smd_half_channel */
volatile void __iomem *recv; /* some variant of smd_half_channel */
@@ -217,54 +196,6 @@
struct smd_half_channel_access *half_ch;
};
-struct smem_ram_ptable {
- #define _SMEM_RAM_PTABLE_MAGIC_1 0x9DA5E0A8
- #define _SMEM_RAM_PTABLE_MAGIC_2 0xAF9EC4E2
- unsigned magic[2];
- unsigned version;
- unsigned reserved1;
- unsigned len;
- struct smem_ram_ptn parts[32];
- unsigned buf;
-} __attribute__ ((__packed__));
-
-/* SMEM RAM Partition */
-enum {
- DEFAULT_ATTRB = ~0x0,
- READ_ONLY = 0x0,
- READWRITE,
-};
-
-enum {
- DEFAULT_CATEGORY = ~0x0,
- SMI = 0x0,
- EBI1,
- EBI2,
- QDSP6,
- IRAM,
- IMEM,
- EBI0_CS0,
- EBI0_CS1,
- EBI1_CS0,
- EBI1_CS1,
- SDRAM = 0xE,
-};
-
-enum {
- DEFAULT_DOMAIN = 0x0,
- APPS_DOMAIN,
- MODEM_DOMAIN,
- SHARED_DOMAIN,
-};
-
-enum {
- SYS_MEMORY = 1, /* system memory*/
- BOOT_REGION_MEMORY1, /* boot loader memory 1*/
- BOOT_REGION_MEMORY2, /* boot loader memory 2,reserved*/
- APPSBL_MEMORY, /* apps boot loader memory*/
- APPS_MEMORY, /* apps usage memory*/
-};
-
extern spinlock_t smem_lock;
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c
index 9870648..a18fb8b 100644
--- a/drivers/crypto/msm/qcedev.c
+++ b/drivers/crypto/msm/qcedev.c
@@ -1943,13 +1943,11 @@
podev->platform_support.bus_scale_table = NULL;
podev->platform_support.sha_hmac = 1;
- if (podev->ce_support.is_shared == false) {
- podev->platform_support.bus_scale_table =
- (struct msm_bus_scale_pdata *)
- msm_bus_cl_get_pdata(pdev);
- if (!podev->platform_support.bus_scale_table)
- pr_err("bus_scale_table is NULL\n");
- }
+ podev->platform_support.bus_scale_table =
+ (struct msm_bus_scale_pdata *)
+ msm_bus_cl_get_pdata(pdev);
+ if (!podev->platform_support.bus_scale_table)
+ pr_err("bus_scale_table is NULL\n");
} else {
platform_support =
(struct msm_ce_hw_support *)pdev->dev.platform_data;
diff --git a/drivers/crypto/msm/qcrypto.c b/drivers/crypto/msm/qcrypto.c
index a4bb2f1..375516b 100644
--- a/drivers/crypto/msm/qcrypto.c
+++ b/drivers/crypto/msm/qcrypto.c
@@ -3393,13 +3393,11 @@
cp->platform_support.bus_scale_table = NULL;
cp->platform_support.sha_hmac = 1;
- if (cp->ce_support.is_shared == false) {
- cp->platform_support.bus_scale_table =
- (struct msm_bus_scale_pdata *)
- msm_bus_cl_get_pdata(pdev);
- if (!cp->platform_support.bus_scale_table)
- pr_warn("bus_scale_table is NULL\n");
- }
+ cp->platform_support.bus_scale_table =
+ (struct msm_bus_scale_pdata *)
+ msm_bus_cl_get_pdata(pdev);
+ if (!cp->platform_support.bus_scale_table)
+ pr_warn("bus_scale_table is NULL\n");
} else {
platform_support =
(struct msm_ce_hw_support *)pdev->dev.platform_data;
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 992f88d..fb31dd6 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -674,7 +674,7 @@
list_del(&private->list);
mutex_unlock(&kgsl_driver.process_mutex);
- if (private->kobj.parent)
+ if (private->kobj.ktype)
kgsl_process_uninit_sysfs(private);
if (private->debug_root)
debugfs_remove_recursive(private->debug_root);
@@ -791,7 +791,7 @@
}
}
- if (!private->kobj.parent)
+ if (!private->kobj.ktype)
kgsl_process_init_sysfs(private);
if (!private->debug_root)
kgsl_process_init_debugfs(private);
diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index a77dacb..b96349e 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -37,6 +37,7 @@
#include <linux/of_gpio.h>
#include <mach/board.h>
#include <mach/gpiomux.h>
+#include <mach/msm_bus_board.h>
MODULE_LICENSE("GPL v2");
MODULE_VERSION("0.2");
@@ -142,6 +143,22 @@
.pull = GPIOMUX_PULL_NONE,
};
+/**
+ * qup_i2c_clk_path_vote: data to use bus scaling driver for clock path vote
+ *
+ * @client_hdl when zero, client is not registered with the bus scaling driver,
+ * and bus scaling functionality should not be used. When non zero, it
+ * is a bus scaling client id and may be used to vote for clock path.
+ * @reg_err when true, registration error was detected and an error message was
+ * logged. i2c will attempt to re-register but will log error only once.
+ * once registration succeed, the flag is set to false.
+ */
+struct qup_i2c_clk_path_vote {
+ u32 client_hdl;
+ struct msm_bus_scale_pdata *pdata;
+ bool reg_err;
+};
+
struct qup_i2c_dev {
struct device *dev;
void __iomem *base; /* virtual */
@@ -172,6 +189,7 @@
struct mutex mlock;
void *complete;
int i2c_gpios[ARRAY_SIZE(i2c_rsrcs)];
+ struct qup_i2c_clk_path_vote clk_path_vote;
};
#ifdef DEBUG
@@ -333,11 +351,160 @@
mb();
}
+#define MSM_I2C_CLK_PATH_SUSPEND (0)
+#define MSM_I2C_CLK_PATH_RESUME (1)
+#define MSM_I2C_CLK_PATH_MAX_BW(dev) ((dev->pdata->src_clk_rate * 8) / 1000)
+
+static int i2c_qup_clk_path_init(struct platform_device *pdev,
+ struct qup_i2c_dev *dev)
+{
+ struct msm_bus_vectors *paths = NULL;
+ struct msm_bus_paths *usecases = NULL;
+
+ if (!dev->pdata->master_id)
+ return 0;
+
+ dev_dbg(&pdev->dev, "initialises bus-scaling clock voting");
+
+ paths = devm_kzalloc(&pdev->dev, sizeof(*paths) * 2, GFP_KERNEL);
+ if (!paths) {
+ dev_err(&pdev->dev,
+ "msm_bus_paths.paths memory allocation failed");
+ return -ENOMEM;
+ }
+
+ usecases = devm_kzalloc(&pdev->dev, sizeof(*usecases) * 2, GFP_KERNEL);
+ if (!usecases) {
+ dev_err(&pdev->dev,
+ "msm_bus_scale_pdata.usecases memory allocation failed");
+ goto path_init_err;
+ }
+
+ dev->clk_path_vote.pdata = devm_kzalloc(&pdev->dev,
+ sizeof(*dev->clk_path_vote.pdata),
+ GFP_KERNEL);
+ if (!dev->clk_path_vote.pdata) {
+ dev_err(&pdev->dev,
+ "msm_bus_scale_pdata memory allocation failed");
+ goto path_init_err;
+ }
+
+ paths[MSM_I2C_CLK_PATH_SUSPEND] = (struct msm_bus_vectors) {
+ dev->pdata->master_id, MSM_BUS_SLAVE_EBI_CH0, 0, 0
+ };
+
+ paths[MSM_I2C_CLK_PATH_RESUME] = (struct msm_bus_vectors) {
+ dev->pdata->master_id, MSM_BUS_SLAVE_EBI_CH0, 0,
+ MSM_I2C_CLK_PATH_MAX_BW(dev)
+ };
+
+ usecases[MSM_I2C_CLK_PATH_SUSPEND] = (struct msm_bus_paths) {
+ .num_paths = 1,
+ .vectors = &paths[MSM_I2C_CLK_PATH_SUSPEND],
+ };
+
+ usecases[MSM_I2C_CLK_PATH_RESUME] = (struct msm_bus_paths) {
+ .num_paths = 1,
+ .vectors = &paths[MSM_I2C_CLK_PATH_RESUME],
+ };
+
+ *dev->clk_path_vote.pdata = (struct msm_bus_scale_pdata) {
+ .active_only = dev->pdata->active_only,
+ .name = pdev->name,
+ .num_usecases = 2,
+ .usecase = usecases,
+ };
+
+ return 0;
+
+path_init_err:
+ devm_kfree(&pdev->dev, paths);
+ devm_kfree(&pdev->dev, usecases);
+ devm_kfree(&pdev->dev, dev->clk_path_vote.pdata);
+ dev->clk_path_vote.pdata = NULL;
+ return -ENOMEM;
+}
+
+static void i2c_qup_clk_path_teardown(struct qup_i2c_dev *dev)
+{
+ if (dev->clk_path_vote.client_hdl) {
+ msm_bus_scale_unregister_client(dev->clk_path_vote.client_hdl);
+ dev->clk_path_vote.client_hdl = 0;
+ }
+}
+
+static void i2c_qup_clk_path_vote(struct qup_i2c_dev *dev)
+{
+ if (dev->clk_path_vote.client_hdl)
+ msm_bus_scale_client_update_request(
+ dev->clk_path_vote.client_hdl,
+ MSM_I2C_CLK_PATH_RESUME);
+}
+
+static void i2c_qup_clk_path_unvote(struct qup_i2c_dev *dev)
+{
+ if (dev->clk_path_vote.client_hdl)
+ msm_bus_scale_client_update_request(
+ dev->clk_path_vote.client_hdl,
+ MSM_I2C_CLK_PATH_SUSPEND);
+}
+
+/**
+ * i2c_qup_clk_path_postponed_register: reg with bus-scaling after it is probed
+ *
+ * Workaround: i2c driver may be probed before the bus scaling driver. Thus,
+ * this function should be called not from probe but from a later context.
+ * This function may be called more then once before register succeed. At
+ * this case only one error message will be logged. At boot time all clocks
+ * are on, so earlier i2c transactions should succeed.
+ */
+static void i2c_qup_clk_path_postponed_register(struct qup_i2c_dev *dev)
+{
+ /*
+ * bail out if path voting is diabled (master_id == 0) or if it is
+ * already registered (client_hdl != 0)
+ */
+ if (!dev->pdata->master_id || dev->clk_path_vote.client_hdl)
+ return;
+
+ dev->clk_path_vote.client_hdl = msm_bus_scale_register_client(
+ dev->clk_path_vote.pdata);
+
+ if (dev->clk_path_vote.client_hdl) {
+ if (dev->clk_path_vote.reg_err) {
+ /* log a success message if an error msg was logged */
+ dev->clk_path_vote.reg_err = false;
+ dev_info(dev->dev,
+ "msm_bus_scale_register_client(mstr-id:%d "
+ "actv-only:%d):0x%x",
+ dev->pdata->master_id, dev->pdata->active_only,
+ dev->clk_path_vote.client_hdl);
+ }
+
+ if (dev->pdata->active_only)
+ i2c_qup_clk_path_vote(dev);
+ } else {
+ /* guard to log only one error on multiple failure */
+ if (!dev->clk_path_vote.reg_err) {
+ dev->clk_path_vote.reg_err = true;
+
+ dev_info(dev->dev,
+ "msm_bus_scale_register_client(mstr-id:%d "
+ "actv-only:%d):0",
+ dev->pdata->master_id, dev->pdata->active_only);
+ }
+ }
+}
+
static void
qup_i2c_pwr_mgmt(struct qup_i2c_dev *dev, unsigned int state)
{
dev->pwr_state = state;
if (state != 0) {
+ i2c_qup_clk_path_postponed_register(dev);
+ if (!dev->pdata->active_only)
+ i2c_qup_clk_path_vote(dev);
+
clk_prepare_enable(dev->clk);
if (!dev->pdata->keep_ahb_clk_on)
clk_prepare_enable(dev->pclk);
@@ -347,6 +514,8 @@
qup_config_core_on_en(dev);
if (!dev->pdata->keep_ahb_clk_on)
clk_disable_unprepare(dev->pclk);
+ if (!dev->pdata->active_only)
+ i2c_qup_clk_path_unvote(dev);
}
}
@@ -1099,11 +1268,12 @@
enum msm_i2c_dt_entry_type {
DT_U32,
DT_GPIO,
+ DT_BOOL,
};
struct msm_i2c_dt_to_pdata_map {
const char *dt_name;
- int *ptr_data;
+ void *ptr_data;
enum msm_i2c_dt_entry_status status;
enum msm_i2c_dt_entry_type type;
int default_val;
@@ -1119,28 +1289,42 @@
{"qcom,i2c-bus-freq", &pdata->clk_freq , DT_REQUIRED , DT_U32 , 0},
{"cell-index" , &pdev->id , DT_REQUIRED , DT_U32 , -1},
{"qcom,i2c-src-freq", &pdata->src_clk_rate, DT_SUGGESTED, DT_U32, 0},
+ {"qcom,master-id" , &pdata->master_id , DT_SUGGESTED, DT_U32, 0},
{"qcom,scl-gpio" , gpios , DT_OPTIONAL , DT_GPIO, -1},
{"qcom,sda-gpio" , gpios + 1 , DT_OPTIONAL , DT_GPIO, -1},
+ {"qcom,active-only" , &pdata->active_only , DT_OPTIONAL , DT_BOOL, 0},
{NULL , NULL , 0 , 0 , 0},
};
for (itr = map; itr->dt_name ; ++itr) {
- if (itr->type == DT_GPIO) {
+ switch (itr->type) {
+ case DT_GPIO:
ret = of_get_named_gpio(node, itr->dt_name, 0);
if (ret >= 0) {
- *itr->ptr_data = ret;
+ *((int *) itr->ptr_data) = ret;
ret = 0;
}
- } else {
+ break;
+ case DT_U32:
ret = of_property_read_u32(node, itr->dt_name,
- itr->ptr_data);
+ (u32 *) itr->ptr_data);
+ break;
+ case DT_BOOL:
+ *((bool *) itr->ptr_data) =
+ of_property_read_bool(node, itr->dt_name);
+ ret = 0;
+ break;
+ default:
+ dev_err(&pdev->dev, "%d is an unknown DT entry type\n",
+ itr->type);
+ ret = -EBADE;
}
dev_dbg(&pdev->dev, "DT entry ret:%d name:%s val:%d\n",
- ret, itr->dt_name, *itr->ptr_data);
+ ret, itr->dt_name, *((int *)itr->ptr_data));
if (ret) {
- *itr->ptr_data = itr->default_val;
+ *((int *)itr->ptr_data) = itr->default_val;
if (itr->status < DT_OPTIONAL) {
dev_err(&pdev->dev, "Missing '%s' DT entry\n",
@@ -1326,6 +1510,14 @@
dev->clk_ctl = 0;
dev->pos = 0;
+ ret = i2c_qup_clk_path_init(pdev, dev);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Failed to init clock path-voting data structs. err:%d", ret);
+ /* disable i2c_qup_clk_path_xxx() functionality */
+ dev->pdata->master_id = 0;
+ }
+
if (dev->pdata->src_clk_rate <= 0) {
dev_info(&pdev->dev,
"No src_clk_rate specified in platfrom data\n");
@@ -1443,6 +1635,7 @@
err_reset_failed:
clk_disable_unprepare(dev->clk);
clk_disable_unprepare(dev->pclk);
+ i2c_qup_clk_path_teardown(dev);
err_gsbi_failed:
iounmap(dev->base);
err_ioremap_failed:
@@ -1488,6 +1681,11 @@
clk_put(dev->pclk);
}
clk_put(dev->clk);
+
+ if (dev->pdata->active_only)
+ i2c_qup_clk_path_unvote(dev);
+ i2c_qup_clk_path_teardown(dev);
+
if (dev->gsbi)
iounmap(dev->gsbi);
iounmap(dev->base);
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index 0f238b2..9101a3d 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -166,7 +166,8 @@
#define LED_MPP_EN_CTRL(base) (base + 0x46)
#define LED_MPP_SINK_CTRL(base) (base + 0x4C)
-#define LED_MPP_CURRENT_DEFAULT 10
+#define LED_MPP_CURRENT_DEFAULT 5
+#define LED_MPP_CURRENT_PER_SETTING 5
#define LED_MPP_SOURCE_SEL_DEFAULT LED_MPP_MODE_ENABLE
#define LED_MPP_SINK_MASK 0x07
@@ -258,6 +259,7 @@
enum led_mode {
PWM_MODE = 0,
LPG_MODE,
+ MANUAL_MODE,
};
static u8 wled_debug_regs[] = {
@@ -290,6 +292,24 @@
};
/**
+ * pwm_config_data - pwm configuration data
+ * @lut_params - lut parameters to be used by pwm driver
+ * @pwm_device - pwm device
+ * @pwm_channel - pwm channel to be configured for led
+ * @pwm_period_us - period for pwm, in us
+ * @mode - mode the led operates in
+ */
+struct pwm_config_data {
+ struct lut_params lut_params;
+ struct pwm_device *pwm_dev;
+ int pwm_channel;
+ u32 pwm_period_us;
+ struct pwm_duty_cycles *duty_cycles;
+ u8 mode;
+ u8 enable;
+};
+
+/**
* wled_config_data - wled configuration data
* @num_strings - number of wled strings supported
* @ovp_val - over voltage protection threshold
@@ -314,12 +334,18 @@
/**
* mpp_config_data - mpp configuration data
+ * @pwm_cfg - device pwm configuration
* @current_setting - current setting, 5ma-40ma in 5ma increments
+ * @source_sel - source selection
+ * @mode_ctrl - mode control
+ * @pwm_mode - pwm mode in use
*/
struct mpp_config_data {
+ struct pwm_config_data *pwm_cfg;
u8 current_setting;
u8 source_sel;
u8 mode_ctrl;
+ u8 pwm_mode;
};
/**
@@ -354,38 +380,25 @@
/**
* kpdbl_config_data - kpdbl configuration data
- * @pwm_device - pwm device
- * @pwm_channel - pwm channel to be configured for led
- * @pwm_period_us - period for pwm, in us
+ * @pwm_cfg - device pwm configuration
* @row_src_sel_val - select source, 0 for vph_pwr and 1 for vbst
* @row_scan_en - enable row scan
* @row_scan_val - map to enable needed rows
*/
struct kpdbl_config_data {
- struct pwm_device *pwm_dev;
- int pwm_channel;
- u32 pwm_period_us;
+ struct pwm_config_data *pwm_cfg;
u32 row_src_sel_val;
u32 row_scan_en;
u32 row_scan_val;
- u8 mode;
};
/**
* rgb_config_data - rgb configuration data
- * @lut_params - lut parameters to be used by pwm driver
- * @pwm_device - pwm device
- * @pwm_channel - pwm channel to be configured for led
- * @pwm_period_us - period for pwm, in us
- * @mode - mode the led operates in
+ * @pwm_cfg - device pwm configuration
+ * @enable - bits to enable led
*/
struct rgb_config_data {
- struct lut_params lut_params;
- struct pwm_device *pwm_dev;
- int pwm_channel;
- u32 pwm_period_us;
- struct pwm_duty_cycles *duty_cycles;
- u8 mode;
+ struct pwm_config_data *pwm_cfg;
u8 enable;
};
@@ -542,24 +555,33 @@
static int qpnp_mpp_set(struct qpnp_led_data *led)
{
int rc, val;
+ int duty_us;
if (led->cdev.brightness) {
- val = (led->cdev.brightness * LED_MPP_SINK_MASK) / LED_FULL;
- rc = qpnp_led_masked_write(led,
- LED_MPP_SINK_CTRL(led->base),
- LED_MPP_SINK_MASK, val);
- if (rc) {
- dev_err(&led->spmi_dev->dev,
- "Failed to write led enable reg\n");
- return rc;
+ if (led->mpp_cfg->pwm_mode == PWM_MODE) {
+ pwm_disable(led->mpp_cfg->pwm_cfg->pwm_dev);
+ duty_us = (led->mpp_cfg->pwm_cfg->pwm_period_us *
+ led->cdev.brightness) / LED_FULL;
+ /*config pwm for brightness scaling*/
+ rc = pwm_config(led->mpp_cfg->pwm_cfg->pwm_dev,
+ duty_us,
+ led->mpp_cfg->pwm_cfg->pwm_period_us);
+ if (rc < 0) {
+ dev_err(&led->spmi_dev->dev, "Failed to " \
+ "configure pwm for new values\n");
+ return rc;
+ }
}
+ if (led->mpp_cfg->pwm_mode != MANUAL_MODE)
+ pwm_enable(led->mpp_cfg->pwm_cfg->pwm_dev);
+
val = (led->mpp_cfg->source_sel & LED_MPP_SRC_MASK) |
(led->mpp_cfg->mode_ctrl & LED_MPP_MODE_CTRL_MASK);
rc = qpnp_led_masked_write(led,
- LED_MPP_MODE_CTRL(led->base), LED_MPP_MODE_MASK,
- val);
+ LED_MPP_MODE_CTRL(led->base), LED_MPP_MODE_MASK,
+ val);
if (rc) {
dev_err(&led->spmi_dev->dev,
"Failed to write led mode reg\n");
@@ -569,13 +591,15 @@
rc = qpnp_led_masked_write(led,
LED_MPP_EN_CTRL(led->base), LED_MPP_EN_MASK,
LED_MPP_EN_ENABLE);
- if (rc) {
- dev_err(&led->spmi_dev->dev,
- "Failed to write led enable " \
- "reg\n");
- return rc;
- }
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Failed to write led enable " \
+ "reg\n");
+ return rc;
+ }
} else {
+ if (led->mpp_cfg->pwm_mode != MANUAL_MODE)
+ pwm_disable(led->mpp_cfg->pwm_cfg->pwm_dev);
rc = qpnp_led_masked_write(led,
LED_MPP_MODE_CTRL(led->base),
LED_MPP_MODE_MASK,
@@ -831,21 +855,21 @@
if (led->cdev.brightness) {
rc = qpnp_led_masked_write(led, KPDBL_ENABLE(led->base),
KPDBL_MODULE_EN_MASK, KPDBL_MODULE_EN);
- duty_us = (led->kpdbl_cfg->pwm_period_us *
+ duty_us = (led->kpdbl_cfg->pwm_cfg->pwm_period_us *
led->cdev.brightness) / KPDBL_MAX_LEVEL;
- rc = pwm_config(led->kpdbl_cfg->pwm_dev, duty_us,
- led->kpdbl_cfg->pwm_period_us);
+ rc = pwm_config(led->kpdbl_cfg->pwm_cfg->pwm_dev, duty_us,
+ led->kpdbl_cfg->pwm_cfg->pwm_period_us);
if (rc < 0) {
dev_err(&led->spmi_dev->dev, "pwm config failed\n");
return rc;
}
- rc = pwm_enable(led->kpdbl_cfg->pwm_dev);
+ rc = pwm_enable(led->kpdbl_cfg->pwm_cfg->pwm_dev);
if (rc < 0) {
dev_err(&led->spmi_dev->dev, "pwm enable failed\n");
return rc;
}
} else {
- pwm_disable(led->kpdbl_cfg->pwm_dev);
+ pwm_disable(led->kpdbl_cfg->pwm_cfg->pwm_dev);
rc = qpnp_led_masked_write(led, KPDBL_ENABLE(led->base),
KPDBL_MODULE_EN_MASK, KPDBL_MODULE_DIS);
if (rc) {
@@ -866,11 +890,11 @@
int rc;
if (led->cdev.brightness) {
- if (led->rgb_cfg->mode == PWM_MODE) {
- duty_us = (led->rgb_cfg->pwm_period_us *
+ if (led->rgb_cfg->pwm_cfg->mode == PWM_MODE) {
+ duty_us = (led->rgb_cfg->pwm_cfg->pwm_period_us *
led->cdev.brightness) / LED_FULL;
- rc = pwm_config(led->rgb_cfg->pwm_dev, duty_us,
- led->rgb_cfg->pwm_period_us);
+ rc = pwm_config(led->rgb_cfg->pwm_cfg->pwm_dev, duty_us,
+ led->rgb_cfg->pwm_cfg->pwm_period_us);
if (rc < 0) {
dev_err(&led->spmi_dev->dev,
"pwm config failed\n");
@@ -885,13 +909,14 @@
"Failed to write led enable reg\n");
return rc;
}
- rc = pwm_enable(led->rgb_cfg->pwm_dev);
+
+ rc = pwm_enable(led->rgb_cfg->pwm_cfg->pwm_dev);
if (rc < 0) {
dev_err(&led->spmi_dev->dev, "pwm enable failed\n");
return rc;
}
} else {
- pwm_disable(led->rgb_cfg->pwm_dev);
+ pwm_disable(led->rgb_cfg->pwm_cfg->pwm_dev);
rc = qpnp_led_masked_write(led,
RGB_LED_EN_CTL(led->base),
led->rgb_cfg->enable, RGB_LED_DISABLE);
@@ -1299,6 +1324,63 @@
return 0;
}
+static int __devinit qpnp_pwm_init(struct pwm_config_data *pwm_cfg,
+ struct spmi_device *spmi_dev,
+ const char *name)
+{
+ int rc, start_idx, idx_len;
+
+ if (pwm_cfg->pwm_channel != -1) {
+ pwm_cfg->pwm_dev =
+ pwm_request(pwm_cfg->pwm_channel, name);
+
+ if (IS_ERR_OR_NULL(pwm_cfg->pwm_dev)) {
+ dev_err(&spmi_dev->dev,
+ "could not acquire PWM Channel %d, " \
+ "error %ld\n",
+ pwm_cfg->pwm_channel,
+ PTR_ERR(pwm_cfg->pwm_dev));
+ pwm_cfg->pwm_dev = NULL;
+ return -ENODEV;
+ }
+
+ if (pwm_cfg->mode == LPG_MODE) {
+ start_idx =
+ pwm_cfg->duty_cycles->start_idx;
+ idx_len =
+ pwm_cfg->duty_cycles->num_duty_pcts;
+
+ if (idx_len >= PWM_LUT_MAX_SIZE &&
+ start_idx) {
+ dev_err(&spmi_dev->dev,
+ "Wrong LUT size or index\n");
+ return -EINVAL;
+ }
+ if ((start_idx + idx_len) >
+ PWM_LUT_MAX_SIZE) {
+ dev_err(&spmi_dev->dev,
+ "Exceed LUT limit\n");
+ return -EINVAL;
+ }
+ rc = pwm_lut_config(pwm_cfg->pwm_dev,
+ PM_PWM_PERIOD_MIN, /* ignored by hardware */
+ pwm_cfg->duty_cycles->duty_pcts,
+ pwm_cfg->lut_params);
+ if (rc < 0) {
+ dev_err(&spmi_dev->dev, "Failed to " \
+ "configure pwm LUT\n");
+ return rc;
+ }
+ }
+ } else {
+ dev_err(&spmi_dev->dev,
+ "Invalid PWM channel\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int __devinit qpnp_kpdbl_init(struct qpnp_led_data *led)
{
int rc;
@@ -1348,24 +1430,12 @@
return rc;
}
- if (led->kpdbl_cfg->pwm_channel != -1) {
- led->kpdbl_cfg->pwm_dev =
- pwm_request(led->kpdbl_cfg->pwm_channel,
- led->cdev.name);
-
- if (IS_ERR_OR_NULL(led->kpdbl_cfg->pwm_dev)) {
- dev_err(&led->spmi_dev->dev,
- "could not acquire PWM Channel %d, " \
- "error %ld\n",
- led->kpdbl_cfg->pwm_channel,
- PTR_ERR(led->kpdbl_cfg->pwm_dev));
- led->kpdbl_cfg->pwm_dev = NULL;
- return -ENODEV;
- }
- } else {
+ rc = qpnp_pwm_init(led->kpdbl_cfg->pwm_cfg, led->spmi_dev,
+ led->cdev.name);
+ if (rc) {
dev_err(&led->spmi_dev->dev,
- "Invalid PWM channel\n");
- return -EINVAL;
+ "Failed to initialize pwm\n");
+ return rc;
}
/* dump kpdbl registers */
@@ -1376,7 +1446,7 @@
static int __devinit qpnp_rgb_init(struct qpnp_led_data *led)
{
- int rc, start_idx, idx_len;
+ int rc;
rc = qpnp_led_masked_write(led, RGB_LED_SRC_SEL(led->base),
RGB_LED_SRC_MASK, RGB_LED_SOURCE_VPH_PWR);
@@ -1386,55 +1456,13 @@
return rc;
}
- if (led->rgb_cfg->pwm_channel != -1) {
- led->rgb_cfg->pwm_dev =
- pwm_request(led->rgb_cfg->pwm_channel,
- led->cdev.name);
-
- if (IS_ERR_OR_NULL(led->rgb_cfg->pwm_dev)) {
- dev_err(&led->spmi_dev->dev,
- "could not acquire PWM Channel %d, " \
- "error %ld\n",
- led->rgb_cfg->pwm_channel,
- PTR_ERR(led->rgb_cfg->pwm_dev));
- led->rgb_cfg->pwm_dev = NULL;
- return -ENODEV;
- }
-
- if (led->rgb_cfg->mode == LPG_MODE) {
- start_idx =
- led->rgb_cfg->duty_cycles->start_idx;
- idx_len =
- led->rgb_cfg->duty_cycles->num_duty_pcts;
-
- if (idx_len >= PWM_LUT_MAX_SIZE &&
- start_idx) {
- dev_err(&led->spmi_dev->dev,
- "Wrong LUT size or index\n");
- return -EINVAL;
- }
- if ((start_idx + idx_len) >
- PWM_LUT_MAX_SIZE) {
- dev_err(&led->spmi_dev->dev,
- "Exceed LUT limit\n");
- return -EINVAL;
- }
- rc = pwm_lut_config(led->rgb_cfg->pwm_dev,
- PM_PWM_PERIOD_MIN, /* ignored by hardware */
- led->rgb_cfg->duty_cycles->duty_pcts,
- led->rgb_cfg->lut_params);
- if (rc < 0) {
- dev_err(&led->spmi_dev->dev, "Failed to " \
- "configure pwm LUT\n");
- return rc;
- }
- }
- } else {
+ rc = qpnp_pwm_init(led->rgb_cfg->pwm_cfg, led->spmi_dev,
+ led->cdev.name);
+ if (rc) {
dev_err(&led->spmi_dev->dev,
- "Invalid PWM channel\n");
- return -EINVAL;
+ "Failed to initialize pwm\n");
+ return rc;
}
-
/* Initialize led for use in auto trickle charging mode */
rc = qpnp_led_masked_write(led, RGB_LED_ATC_CTL(led->base),
led->rgb_cfg->enable, led->rgb_cfg->enable);
@@ -1442,6 +1470,36 @@
return 0;
}
+static int __devinit qpnp_mpp_init(struct qpnp_led_data *led)
+{
+ int rc, val;
+
+ val = (led->mpp_cfg->current_setting / LED_MPP_CURRENT_PER_SETTING) - 1;
+
+ if (val < 0)
+ val = 0;
+
+ rc = qpnp_led_masked_write(led, LED_MPP_SINK_CTRL(led->base),
+ LED_MPP_SINK_MASK, val);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Failed to write led enable reg\n");
+ return rc;
+ }
+
+ if (led->mpp_cfg->pwm_mode != MANUAL_MODE) {
+ rc = qpnp_pwm_init(led->mpp_cfg->pwm_cfg, led->spmi_dev,
+ led->cdev.name);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Failed to initialize pwm\n");
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
static int __devinit qpnp_led_initialize(struct qpnp_led_data *led)
{
int rc = 0;
@@ -1469,6 +1527,10 @@
"RGB initialize failed(%d)\n", rc);
break;
case QPNP_ID_LED_MPP:
+ rc = qpnp_mpp_init(led);
+ if (rc)
+ dev_err(&led->spmi_dev->dev,
+ "MPP initialize failed(%d)\n", rc);
break;
case QPNP_ID_KPDBL:
rc = qpnp_kpdbl_init(led);
@@ -1669,11 +1731,138 @@
return 0;
}
+static int __devinit qpnp_get_config_pwm(struct pwm_config_data *pwm_cfg,
+ struct spmi_device *spmi_dev,
+ struct device_node *node)
+{
+ struct property *prop;
+ int rc, i;
+ u32 val;
+ u8 *temp_cfg;
+
+ rc = of_property_read_u32(node, "qcom,pwm-channel", &val);
+ if (!rc)
+ pwm_cfg->pwm_channel = val;
+ else
+ return rc;
+
+ if (pwm_cfg->mode == PWM_MODE) {
+ rc = of_property_read_u32(node, "qcom,pwm-us", &val);
+ if (!rc)
+ pwm_cfg->pwm_period_us = val;
+ else
+ return rc;
+ }
+
+ if (pwm_cfg->mode == LPG_MODE) {
+ pwm_cfg->duty_cycles =
+ devm_kzalloc(&spmi_dev->dev,
+ sizeof(struct pwm_duty_cycles), GFP_KERNEL);
+ if (!pwm_cfg->duty_cycles) {
+ dev_err(&spmi_dev->dev,
+ "Unable to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ prop = of_find_property(node, "qcom,duty-pcts",
+ &pwm_cfg->duty_cycles->num_duty_pcts);
+ if (!prop) {
+ dev_err(&spmi_dev->dev, "Looking up property " \
+ "node qcom,duty-pcts failed\n");
+ return -ENODEV;
+ } else if (!pwm_cfg->duty_cycles->num_duty_pcts) {
+ dev_err(&spmi_dev->dev, "Invalid length of " \
+ "duty pcts\n");
+ return -EINVAL;
+ }
+
+ pwm_cfg->duty_cycles->duty_pcts =
+ devm_kzalloc(&spmi_dev->dev,
+ sizeof(int) * pwm_cfg->duty_cycles->num_duty_pcts,
+ GFP_KERNEL);
+ if (!pwm_cfg->duty_cycles->duty_pcts) {
+ dev_err(&spmi_dev->dev,
+ "Unable to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ temp_cfg = devm_kzalloc(&spmi_dev->dev,
+ pwm_cfg->duty_cycles->num_duty_pcts *
+ sizeof(u8), GFP_KERNEL);
+ if (!temp_cfg) {
+ dev_err(&spmi_dev->dev, "Failed to allocate " \
+ "memory for duty pcts\n");
+ return -ENOMEM;
+ }
+
+ memcpy(temp_cfg, prop->value,
+ pwm_cfg->duty_cycles->num_duty_pcts);
+
+ for (i = 0; i < pwm_cfg->duty_cycles->num_duty_pcts; i++)
+ pwm_cfg->duty_cycles->duty_pcts[i] =
+ (int) temp_cfg[i];
+
+ rc = of_property_read_u32(node, "qcom,start-idx", &val);
+ if (!rc) {
+ pwm_cfg->lut_params.start_idx = val;
+ pwm_cfg->duty_cycles->start_idx = val;
+ } else
+ return rc;
+
+ pwm_cfg->lut_params.lut_pause_hi = 0;
+ rc = of_property_read_u32(node, "qcom,pause-hi", &val);
+ if (!rc)
+ pwm_cfg->lut_params.lut_pause_hi = val;
+ else if (rc != -EINVAL)
+ return rc;
+
+ pwm_cfg->lut_params.lut_pause_lo = 0;
+ rc = of_property_read_u32(node, "qcom,pause-lo", &val);
+ if (!rc)
+ pwm_cfg->lut_params.lut_pause_lo = val;
+ else if (rc != -EINVAL)
+ return rc;
+
+ pwm_cfg->lut_params.ramp_step_ms =
+ QPNP_LUT_RAMP_STEP_DEFAULT;
+ rc = of_property_read_u32(node, "qcom,ramp-step-ms", &val);
+ if (!rc)
+ pwm_cfg->lut_params.ramp_step_ms = val;
+ else if (rc != -EINVAL)
+ return rc;
+
+ pwm_cfg->lut_params.flags = QPNP_LED_PWM_FLAGS;
+ rc = of_property_read_u32(node, "qcom,lut-flags", &val);
+ if (!rc)
+ pwm_cfg->lut_params.flags = (u8) val;
+ else if (rc != -EINVAL)
+ return rc;
+
+ pwm_cfg->lut_params.idx_len =
+ pwm_cfg->duty_cycles->num_duty_pcts;
+ }
+ return 0;
+};
+
+static int qpnp_led_get_mode(const char *mode)
+{
+ if (strncmp(mode, "manual", strlen(mode)) == 0)
+ return MANUAL_MODE;
+ else if (strncmp(mode, "pwm", strlen(mode)) == 0)
+ return PWM_MODE;
+ else if (strncmp(mode, "lpg", strlen(mode)) == 0)
+ return LPG_MODE;
+ else
+ return -EINVAL;
+};
+
static int __devinit qpnp_get_config_kpdbl(struct qpnp_led_data *led,
struct device_node *node)
{
int rc;
u32 val;
+ u8 led_mode;
+ const char *mode;
led->kpdbl_cfg = devm_kzalloc(&led->spmi_dev->dev,
sizeof(struct kpdbl_config_data), GFP_KERNEL);
@@ -1681,28 +1870,28 @@
dev_err(&led->spmi_dev->dev, "Unable to allocate memory\n");
return -ENOMEM;
}
-
- rc = of_property_read_u32(node, "qcom,mode", &val);
- if (!rc)
- led->kpdbl_cfg->mode = (u8) val;
- else
+ rc = of_property_read_string(node, "qcom,mode", &mode);
+ if (!rc) {
+ led_mode = qpnp_led_get_mode(mode);
+ if ((led_mode == MANUAL_MODE) || (led_mode == -EINVAL)) {
+ dev_err(&led->spmi_dev->dev, "Selected mode not " \
+ "supported for kpdbl.\n");
+ return -EINVAL;
+ }
+ led->kpdbl_cfg->pwm_cfg = devm_kzalloc(&led->spmi_dev->dev,
+ sizeof(struct pwm_config_data),
+ GFP_KERNEL);
+ if (!led->kpdbl_cfg->pwm_cfg) {
+ dev_err(&led->spmi_dev->dev,
+ "Unable to allocate memory\n");
+ return -ENOMEM;
+ }
+ led->kpdbl_cfg->pwm_cfg->mode = led_mode;
+ } else
return rc;
- if (led->kpdbl_cfg->mode == LPG_MODE) {
- dev_err(&led->spmi_dev->dev, "LPG mode not supported\n");
- return -EINVAL;
- }
-
- rc = of_property_read_u32(node, "qcom,pwm-channel", &val);
- if (!rc)
- led->kpdbl_cfg->pwm_channel = (u8) val;
- else
- return rc;
-
- rc = of_property_read_u32(node, "qcom,pwm-us", &val);
- if (!rc)
- led->kpdbl_cfg->pwm_period_us = val;
- else
+ rc = qpnp_get_config_pwm(led->kpdbl_cfg->pwm_cfg, led->spmi_dev, node);
+ if (rc < 0)
return rc;
rc = of_property_read_u32(node, "qcom,row-src-sel-val", &val);
@@ -1729,10 +1918,9 @@
static int __devinit qpnp_get_config_rgb(struct qpnp_led_data *led,
struct device_node *node)
{
- struct property *prop;
- int rc, i;
- u32 val;
- u8 *temp_cfg;
+ int rc;
+ u8 led_mode;
+ const char *mode;
led->rgb_cfg = devm_kzalloc(&led->spmi_dev->dev,
sizeof(struct rgb_config_data), GFP_KERNEL);
@@ -1750,113 +1938,29 @@
else
return -EINVAL;
- rc = of_property_read_u32(node, "qcom,mode", &val);
- if (!rc)
- led->rgb_cfg->mode = (u8) val;
- else
- return rc;
-
- rc = of_property_read_u32(node, "qcom,pwm-channel", &val);
- if (!rc)
- led->rgb_cfg->pwm_channel = val;
- else
- return rc;
-
- if (led->rgb_cfg->mode == PWM_MODE) {
- rc = of_property_read_u32(node, "qcom,pwm-us", &val);
- if (!rc)
- led->rgb_cfg->pwm_period_us = val;
- else
- return rc;
- }
-
- if (led->rgb_cfg->mode == LPG_MODE) {
- led->rgb_cfg->duty_cycles =
- devm_kzalloc(&led->spmi_dev->dev,
- sizeof(struct pwm_duty_cycles), GFP_KERNEL);
- if (!led->rgb_cfg->duty_cycles) {
- dev_err(&led->spmi_dev->dev,
- "Unable to allocate memory\n");
- return -ENOMEM;
- }
-
- prop = of_find_property(node, "qcom,duty-pcts",
- &led->rgb_cfg->duty_cycles->num_duty_pcts);
- if (!prop) {
- dev_err(&led->spmi_dev->dev, "Looking up property " \
- "node qcom,duty-pcts failed\n");
- return -ENODEV;
- } else if (!led->rgb_cfg->duty_cycles->num_duty_pcts) {
- dev_err(&led->spmi_dev->dev, "Invalid length of " \
- "duty pcts\n");
+ rc = of_property_read_string(node, "qcom,mode", &mode);
+ if (!rc) {
+ led_mode = qpnp_led_get_mode(mode);
+ if ((led_mode == MANUAL_MODE) || (led_mode == -EINVAL)) {
+ dev_err(&led->spmi_dev->dev, "Selected mode not " \
+ "supported for rgb.\n");
return -EINVAL;
}
-
- led->rgb_cfg->duty_cycles->duty_pcts =
- devm_kzalloc(&led->spmi_dev->dev,
- sizeof(int) * led->rgb_cfg->duty_cycles->num_duty_pcts,
- GFP_KERNEL);
- if (!led->rgb_cfg->duty_cycles->duty_pcts) {
+ led->rgb_cfg->pwm_cfg = devm_kzalloc(&led->spmi_dev->dev,
+ sizeof(struct pwm_config_data),
+ GFP_KERNEL);
+ if (!led->rgb_cfg->pwm_cfg) {
dev_err(&led->spmi_dev->dev,
"Unable to allocate memory\n");
return -ENOMEM;
}
+ led->rgb_cfg->pwm_cfg->mode = led_mode;
+ } else
+ return rc;
- temp_cfg = devm_kzalloc(&led->spmi_dev->dev,
- led->rgb_cfg->duty_cycles->num_duty_pcts *
- sizeof(u8), GFP_KERNEL);
- if (!temp_cfg) {
- dev_err(&led->spmi_dev->dev, "Failed to allocate " \
- "memory for duty pcts\n");
- return -ENOMEM;
- }
-
- memcpy(temp_cfg, prop->value,
- led->rgb_cfg->duty_cycles->num_duty_pcts);
-
- for (i = 0; i < led->rgb_cfg->duty_cycles->num_duty_pcts; i++)
- led->rgb_cfg->duty_cycles->duty_pcts[i] =
- (int) temp_cfg[i];
-
- rc = of_property_read_u32(node, "qcom,start-idx", &val);
- if (!rc) {
- led->rgb_cfg->lut_params.start_idx = val;
- led->rgb_cfg->duty_cycles->start_idx = val;
- } else
- return rc;
-
- led->rgb_cfg->lut_params.lut_pause_hi = 0;
- rc = of_property_read_u32(node, "qcom,pause-hi", &val);
- if (!rc)
- led->rgb_cfg->lut_params.lut_pause_hi = val;
- else if (rc != -EINVAL)
- return rc;
-
- led->rgb_cfg->lut_params.lut_pause_lo = 0;
- rc = of_property_read_u32(node, "qcom,pause-lo", &val);
- if (!rc)
- led->rgb_cfg->lut_params.lut_pause_lo = val;
- else if (rc != -EINVAL)
- return rc;
-
- led->rgb_cfg->lut_params.ramp_step_ms =
- QPNP_LUT_RAMP_STEP_DEFAULT;
- rc = of_property_read_u32(node, "qcom,ramp-step-ms", &val);
- if (!rc)
- led->rgb_cfg->lut_params.ramp_step_ms = val;
- else if (rc != -EINVAL)
- return rc;
-
- led->rgb_cfg->lut_params.flags = QPNP_LED_PWM_FLAGS;
- rc = of_property_read_u32(node, "qcom,lut-flags", &val);
- if (!rc)
- led->rgb_cfg->lut_params.flags = val;
- else if (rc != -EINVAL)
- return rc;
-
- led->rgb_cfg->lut_params.idx_len =
- led->rgb_cfg->duty_cycles->num_duty_pcts;
- }
+ rc = qpnp_get_config_pwm(led->rgb_cfg->pwm_cfg, led->spmi_dev, node);
+ if (rc < 0)
+ return rc;
return 0;
}
@@ -1866,6 +1970,8 @@
{
int rc;
u32 val;
+ u8 led_mode;
+ const char *mode;
led->mpp_cfg = devm_kzalloc(&led->spmi_dev->dev,
sizeof(struct mpp_config_data), GFP_KERNEL);
@@ -1895,6 +2001,33 @@
else if (rc != -EINVAL)
return rc;
+ rc = of_property_read_string(node, "qcom,mode", &mode);
+ if (!rc) {
+ led_mode = qpnp_led_get_mode(mode);
+ led->mpp_cfg->pwm_mode = led_mode;
+ if (led_mode == MANUAL_MODE)
+ return MANUAL_MODE;
+ else if (led_mode == -EINVAL) {
+ dev_err(&led->spmi_dev->dev, "Selected mode not " \
+ "supported for mpp.\n");
+ return -EINVAL;
+ }
+ led->mpp_cfg->pwm_cfg = devm_kzalloc(&led->spmi_dev->dev,
+ sizeof(struct pwm_config_data),
+ GFP_KERNEL);
+ if (!led->mpp_cfg->pwm_cfg) {
+ dev_err(&led->spmi_dev->dev,
+ "Unable to allocate memory\n");
+ return -ENOMEM;
+ }
+ led->mpp_cfg->pwm_cfg->mode = led_mode;
+ } else
+ return rc;
+
+ rc = qpnp_get_config_pwm(led->mpp_cfg->pwm_cfg, led->spmi_dev, node);
+ if (rc < 0)
+ return rc;
+
return 0;
}
@@ -2005,6 +2138,7 @@
if (rc < 0) {
dev_err(&led->spmi_dev->dev,
"Unable to read mpp config data\n");
+ goto fail_id_check;
}
} else if (strncmp(led_label, "kpdbl", sizeof("kpdbl")) == 0) {
rc = qpnp_get_config_kpdbl(led, temp);
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
index 5b385a0..d07387e 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
@@ -4606,11 +4606,11 @@
mpq_demux->sdmx_filter_count, mpq_demux->filters_status);
process_end_time = current_kernel_time();
- mpq_dmx_update_sdmx_stat(mpq_demux, prev_fill_count,
- &process_start_time, &process_end_time);
-
bytes_read = prev_fill_count - fill_count;
+ mpq_dmx_update_sdmx_stat(mpq_demux, bytes_read,
+ &process_start_time, &process_end_time);
+
MPQ_DVB_DBG_PRINT(
"%s: SDMX result=%d, input_fill_count=%u, read_offset=%u, read %d bytes from input, status=0x%X, errors=0x%X\n",
__func__, sdmx_res, fill_count, read_offset, bytes_read,
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
index 5e14d0c..a2ce428 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
@@ -54,14 +54,16 @@
#define TSPP_RAW_TTS_SIZE 192
#define TSPP_RAW_SIZE 188
-#define MAX_BAM_DESCRIPTOR_SIZE (32*1024 - 1)
+#define MAX_BAM_DESCRIPTOR_SIZE (32 * 1024 - 1)
+
+#define MAX_BAM_DESCRIPTOR_COUNT (8 * 1024 - 2)
#define TSPP_BUFFER_SIZE (500 * 1024) /* 500KB */
#define TSPP_DESCRIPTOR_SIZE (TSPP_RAW_TTS_SIZE)
#define TSPP_BUFFER_COUNT(buffer_size) \
- ((buffer_size) / TSPP_RAW_TTS_SIZE)
+ ((buffer_size) / TSPP_DESCRIPTOR_SIZE)
/* When TSPP notifies demux that new packets are received.
* Using max descriptor size (170 packets).
@@ -1799,6 +1801,11 @@
mpq_dmx_tspp_info.tsif[i].buffer_count =
TSPP_BUFFER_COUNT(tspp_out_buffer_size);
+ if (mpq_dmx_tspp_info.tsif[i].buffer_count >
+ MAX_BAM_DESCRIPTOR_COUNT)
+ mpq_dmx_tspp_info.tsif[i].buffer_count =
+ MAX_BAM_DESCRIPTOR_COUNT;
+
mpq_dmx_tspp_info.tsif[i].aggregate_ids =
vzalloc(mpq_dmx_tspp_info.tsif[i].buffer_count *
sizeof(int));
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 9bc77be..0a2906c 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -45,7 +45,6 @@
#include "qseecom_kernel.h"
#define QSEECOM_DEV "qseecom"
-#define QSEOS_VERSION_13 0x13
#define QSEOS_VERSION_14 0x14
#define QSEEE_VERSION_00 0x400000
#define QSEE_VERSION_01 0x401000
@@ -90,11 +89,6 @@
static dev_t qseecom_device_no;
static struct cdev qseecom_cdev;
-/* Data structures used in legacy support */
-static void *pil;
-static uint32_t pil_ref_cnt;
-static DEFINE_MUTEX(pil_access_lock);
-
static DEFINE_MUTEX(qsee_bw_mutex);
static DEFINE_MUTEX(app_access_lock);
static DEFINE_MUTEX(clk_access_lock);
@@ -3023,10 +3017,10 @@
}
qseecom.qseos_version = QSEOS_VERSION_14;
} else {
- qseecom.qseos_version = QSEOS_VERSION_13;
- qseecom.qsee_version = 0;
- pil = NULL;
- pil_ref_cnt = 0;
+ pr_err("QSEE legacy version is not supported:");
+ pr_err("Support for TZ1.3 and earlier is deprecated\n");
+ rc = -EINVAL;
+ goto err;
}
qseecom.commonlib_loaded = false;
qseecom.pdev = class_dev;
diff --git a/drivers/misc/tspp.c b/drivers/misc/tspp.c
index 501da4c8..e0fffbd 100644
--- a/drivers/misc/tspp.c
+++ b/drivers/misc/tspp.c
@@ -62,9 +62,8 @@
/*
* BAM descriptor FIFO size (in number of descriptors).
* Max number of descriptors allowed by SPS which is 8K-1.
- * Restrict it to half of this to save DMA memory.
*/
-#define TSPP_SPS_DESCRIPTOR_COUNT (4 * 1024 - 1)
+#define TSPP_SPS_DESCRIPTOR_COUNT (8 * 1024 - 1)
#define TSPP_PACKET_LENGTH 188
#define TSPP_MIN_BUFFER_SIZE (TSPP_PACKET_LENGTH)
@@ -2236,6 +2235,12 @@
return -EINVAL;
}
+ if (count > TSPP_NUM_BUFFERS) {
+ pr_err("%s: tspp requires a maximum of %i buffers\n",
+ __func__, TSPP_NUM_BUFFERS);
+ return -EINVAL;
+ }
+
channel = &pdev->channels[channel_id];
/* allow buffer allocation only if there was no previous buffer
diff --git a/drivers/platform/msm/ipa/a2_service.c b/drivers/platform/msm/ipa/a2_service.c
index fa71efc..0d77741 100644
--- a/drivers/platform/msm/ipa/a2_service.c
+++ b/drivers/platform/msm/ipa/a2_service.c
@@ -536,6 +536,8 @@
__func__);
return -EFAULT;
}
+ if (sps_ctrl_bam_dma_clk(true))
+ WARN_ON(1);
memset(&connect_params, 0, sizeof(struct ipa_sys_connect_params));
connect_params.client = IPA_CLIENT_A2_TETHERED_CONS;
connect_params.notify = ipa_tethered_notify;
@@ -606,6 +608,8 @@
ipa_bridge_teardown(IPA_BRIDGE_DIR_UL, IPA_BRIDGE_TYPE_TETHERED,
a2_mux_ctx->tethered_prod);
bridge_tethered_ul_failed:
+ if (sps_ctrl_bam_dma_clk(false))
+ WARN_ON(1);
return ret;
}
@@ -647,6 +651,8 @@
__func__, ret);
return ret;
}
+ if (sps_ctrl_bam_dma_clk(false))
+ WARN_ON(1);
verify_tx_queue_is_empty(__func__);
(void) ipa_rm_release_resource(IPA_RM_RESOURCE_A2_PROD);
if (a2_mux_ctx->disconnect_ack)
diff --git a/drivers/platform/msm/ipa/ipa.c b/drivers/platform/msm/ipa/ipa.c
index 35b2561..6495db4 100644
--- a/drivers/platform/msm/ipa/ipa.c
+++ b/drivers/platform/msm/ipa/ipa.c
@@ -1738,22 +1738,6 @@
result = -ENOMEM;
goto fail_rt_tbl_cache;
}
- ipa_ctx->tx_pkt_wrapper_cache =
- kmem_cache_create("IPA TX PKT WRAPPER",
- sizeof(struct ipa_tx_pkt_wrapper), 0, 0, NULL);
- if (!ipa_ctx->tx_pkt_wrapper_cache) {
- IPAERR(":ipa tx pkt wrapper cache create failed\n");
- result = -ENOMEM;
- goto fail_tx_pkt_wrapper_cache;
- }
- ipa_ctx->rx_pkt_wrapper_cache =
- kmem_cache_create("IPA RX PKT WRAPPER",
- sizeof(struct ipa_rx_pkt_wrapper), 0, 0, NULL);
- if (!ipa_ctx->rx_pkt_wrapper_cache) {
- IPAERR(":ipa rx pkt wrapper cache create failed\n");
- result = -ENOMEM;
- goto fail_rx_pkt_wrapper_cache;
- }
ipa_ctx->tree_node_cache =
kmem_cache_create("IPA TREE", sizeof(struct ipa_tree_node), 0, 0,
NULL);
@@ -1822,6 +1806,8 @@
mutex_init(&ipa_ctx->lock);
mutex_init(&ipa_ctx->nat_mem.lock);
+ skb_queue_head_init(&ipa_ctx->rx_list);
+
for (i = 0; i < IPA_A5_SYS_MAX; i++) {
INIT_LIST_HEAD(&ipa_ctx->sys[i].head_desc_list);
spin_lock_init(&ipa_ctx->sys[i].spinlock);
@@ -1835,15 +1821,15 @@
atomic_set(&ipa_ctx->sys[i].curr_polling_state, 0);
}
- ipa_ctx->rx_wq = create_singlethread_workqueue("ipa rx wq");
+ ipa_ctx->rx_wq = alloc_workqueue("ipa rx wq", WQ_MEM_RECLAIM |
+ WQ_CPU_INTENSIVE, 1);
if (!ipa_ctx->rx_wq) {
IPAERR(":fail to create rx wq\n");
result = -ENOMEM;
goto fail_rx_wq;
}
- ipa_ctx->tx_wq = alloc_workqueue("ipa tx wq", WQ_MEM_RECLAIM |
- WQ_CPU_INTENSIVE, 2);
+ ipa_ctx->tx_wq = create_singlethread_workqueue("ipa tx wq");
if (!ipa_ctx->tx_wq) {
IPAERR(":fail to create tx wq\n");
result = -ENOMEM;
@@ -1996,10 +1982,6 @@
fail_dma_pool:
kmem_cache_destroy(ipa_ctx->tree_node_cache);
fail_tree_node_cache:
- kmem_cache_destroy(ipa_ctx->rx_pkt_wrapper_cache);
-fail_rx_pkt_wrapper_cache:
- kmem_cache_destroy(ipa_ctx->tx_pkt_wrapper_cache);
-fail_tx_pkt_wrapper_cache:
kmem_cache_destroy(ipa_ctx->rt_tbl_cache);
fail_rt_tbl_cache:
kmem_cache_destroy(ipa_ctx->hdr_offset_cache);
diff --git a/drivers/platform/msm/ipa/ipa_bridge.c b/drivers/platform/msm/ipa/ipa_bridge.c
index 919a119..83c4db0 100644
--- a/drivers/platform/msm/ipa/ipa_bridge.c
+++ b/drivers/platform/msm/ipa/ipa_bridge.c
@@ -45,19 +45,23 @@
#define IPA_UL_DESC_FIFO_SZ 0x530
#define IPA_DL_DATA_FIFO_SZ 0x2400
#define IPA_DL_DESC_FIFO_SZ 0x8a0
+#define IPA_DL_EMB_DATA_FIFO_SZ 0x1800
+#define IPA_DL_EMB_DESC_FIFO_SZ 0x4e8
-#define IPA_SMEM_UL_DATA_FIFO_OFST 0x3dd0
-#define IPA_SMEM_UL_DESC_FIFO_OFST 0x49d0
-#define IPA_SMEM_DL_DATA_FIFO_OFST 0x4f00
-#define IPA_SMEM_DL_DESC_FIFO_OFST 0x7300
+#define IPA_SMEM_UL_DATA_FIFO_OFST 0
+#define IPA_SMEM_UL_DESC_FIFO_OFST 0xc00
+#define IPA_SMEM_DL_DATA_FIFO_OFST 0x1130
+#define IPA_SMEM_DL_DESC_FIFO_OFST 0x3530
+#define IPA_SMEM_UL_EMB_DATA_FIFO_OFST 0x3dd0
+#define IPA_SMEM_UL_EMB_DESC_FIFO_OFST 0x49d0
-#define IPA_OCIMEM_UL_DATA_FIFO_OFST 0
-#define IPA_OCIMEM_UL_DESC_FIFO_OFST (IPA_OCIMEM_UL_DATA_FIFO_OFST + \
- IPA_UL_DATA_FIFO_SZ)
-#define IPA_OCIMEM_DL_DATA_FIFO_OFST (IPA_OCIMEM_UL_DESC_FIFO_OFST + \
- IPA_UL_DESC_FIFO_SZ)
-#define IPA_OCIMEM_DL_DESC_FIFO_OFST (IPA_OCIMEM_DL_DATA_FIFO_OFST + \
- IPA_DL_DATA_FIFO_SZ)
+#define IPA_OCIMEM_DL_A2_DATA_FIFO_OFST 0
+#define IPA_OCIMEM_DL_A2_DESC_FIFO_OFST (IPA_OCIMEM_DL_A2_DATA_FIFO_OFST + \
+ IPA_DL_EMB_DATA_FIFO_SZ)
+#define IPA_OCIMEM_DL_IPA_DATA_FIFO_OFST (IPA_OCIMEM_DL_A2_DESC_FIFO_OFST + \
+ IPA_DL_EMB_DESC_FIFO_SZ)
+#define IPA_OCIMEM_DL_IPA_DESC_FIFO_OFST (IPA_OCIMEM_DL_IPA_DATA_FIFO_OFST + \
+ IPA_DL_EMB_DATA_FIFO_SZ)
enum ipa_pipe_type {
IPA_DL_FROM_A2,
@@ -116,7 +120,7 @@
if (dir == IPA_BRIDGE_DIR_UL)
sz = IPA_UL_DESC_FIFO_SZ;
else
- sz = IPA_DL_DESC_FIFO_SZ;
+ sz = IPA_DL_EMB_DESC_FIFO_SZ;
}
return sz;
@@ -136,7 +140,7 @@
if (dir == IPA_BRIDGE_DIR_UL)
sz = IPA_UL_DATA_FIFO_SZ;
else
- sz = IPA_DL_DATA_FIFO_SZ;
+ sz = IPA_DL_EMB_DATA_FIFO_SZ;
}
return sz;
@@ -162,6 +166,38 @@
return ep;
}
+int ipa_setup_ipa_dma_fifos(enum ipa_bridge_dir dir,
+ enum ipa_bridge_type type,
+ struct sps_mem_buffer *desc,
+ struct sps_mem_buffer *data)
+{
+ int ret;
+
+ ret = sps_setup_bam2bam_fifo(data,
+ IPA_OCIMEM_DL_IPA_DATA_FIFO_OFST,
+ ipa_get_data_fifo_sz(dir, type), 1);
+ if (ret) {
+ IPAERR("DAFIFO setup fail %d dir %d type %d\n",
+ ret, dir, type);
+ return ret;
+ }
+
+ ret = sps_setup_bam2bam_fifo(desc,
+ IPA_OCIMEM_DL_IPA_DESC_FIFO_OFST,
+ ipa_get_desc_fifo_sz(dir, type), 1);
+ if (ret) {
+ IPAERR("DEFIFO setup fail %d dir %d type %d\n",
+ ret, dir, type);
+ return ret;
+ }
+
+ IPADBG("dir=%d type=%d Dpa=%x Dsz=%u Dva=%p dpa=%x dsz=%u dva=%p\n",
+ dir, type, data->phys_base, data->size, data->base,
+ desc->phys_base, desc->size, desc->base);
+
+ return 0;
+}
+
int ipa_setup_a2_dma_fifos(enum ipa_bridge_dir dir,
enum ipa_bridge_type type,
struct sps_mem_buffer *desc,
@@ -169,7 +205,7 @@
{
int ret;
- if (type == IPA_BRIDGE_TYPE_EMBEDDED) {
+ if (type == IPA_BRIDGE_TYPE_TETHERED) {
if (dir == IPA_BRIDGE_DIR_UL) {
desc->base = ipa_ctx->smem_pipe_mem +
IPA_SMEM_UL_DESC_FIFO_OFST;
@@ -191,26 +227,17 @@
}
} else {
if (dir == IPA_BRIDGE_DIR_UL) {
- ret = sps_setup_bam2bam_fifo(data,
- IPA_OCIMEM_UL_DATA_FIFO_OFST,
- ipa_get_data_fifo_sz(dir, type), 1);
- if (ret) {
- IPAERR("DAFIFO setup fail %d dir %d type %d\n",
- ret, dir, type);
- return ret;
- }
-
- ret = sps_setup_bam2bam_fifo(desc,
- IPA_OCIMEM_UL_DESC_FIFO_OFST,
- ipa_get_desc_fifo_sz(dir, type), 1);
- if (ret) {
- IPAERR("DEFIFO setup fail %d dir %d type %d\n",
- ret, dir, type);
- return ret;
- }
+ desc->base = ipa_ctx->smem_pipe_mem +
+ IPA_SMEM_UL_EMB_DESC_FIFO_OFST;
+ desc->phys_base = smem_virt_to_phys(desc->base);
+ desc->size = ipa_get_desc_fifo_sz(dir, type);
+ data->base = ipa_ctx->smem_pipe_mem +
+ IPA_SMEM_UL_EMB_DATA_FIFO_OFST;
+ data->phys_base = smem_virt_to_phys(data->base);
+ data->size = ipa_get_data_fifo_sz(dir, type);
} else {
ret = sps_setup_bam2bam_fifo(data,
- IPA_OCIMEM_DL_DATA_FIFO_OFST,
+ IPA_OCIMEM_DL_A2_DATA_FIFO_OFST,
ipa_get_data_fifo_sz(dir, type), 1);
if (ret) {
IPAERR("DAFIFO setup fail %d dir %d type %d\n",
@@ -219,7 +246,7 @@
}
ret = sps_setup_bam2bam_fifo(desc,
- IPA_OCIMEM_DL_DESC_FIFO_OFST,
+ IPA_OCIMEM_DL_A2_DESC_FIFO_OFST,
ipa_get_desc_fifo_sz(dir, type), 1);
if (ret) {
IPAERR("DEFIFO setup fail %d dir %d type %d\n",
@@ -289,6 +316,15 @@
ipa_in_params.desc_fifo_sz = ipa_get_desc_fifo_sz(dir, type);
ipa_in_params.data_fifo_sz = ipa_get_data_fifo_sz(dir, type);
+ if (type == IPA_BRIDGE_TYPE_EMBEDDED && dir == IPA_BRIDGE_DIR_DL) {
+ if (ipa_setup_ipa_dma_fifos(dir, type, &ipa_in_params.desc,
+ &ipa_in_params.data)) {
+ IPAERR("fail to setup IPA-DMA FIFOs dir=%d type=%d\n",
+ dir, type);
+ goto fail_get_a2_prop;
+ }
+ }
+
if (ipa_connect(&ipa_in_params, &sps_out_params, clnt_hdl)) {
IPAERR("ipa connect failed dir=%d type=%d\n", dir, type);
goto fail_get_a2_prop;
diff --git a/drivers/platform/msm/ipa/ipa_client.c b/drivers/platform/msm/ipa/ipa_client.c
index d707648..7483a72 100644
--- a/drivers/platform/msm/ipa/ipa_client.c
+++ b/drivers/platform/msm/ipa/ipa_client.c
@@ -257,6 +257,26 @@
memset(&ipa_ctx->ep[ipa_ep_idx], 0, sizeof(struct ipa_ep_context));
+ if (IPA_CLIENT_IS_CONS(in->client)) {
+ ep->cmd = kzalloc(sizeof(struct ipa_ip_packet_init),
+ GFP_KERNEL);
+ if (!ep->cmd) {
+ IPAERR("failed to alloc immediate command object\n");
+ result = -ENOMEM;
+ goto fail;
+ }
+ ep->cmd->destination_pipe_index = ipa_ep_idx;
+ ep->dma_addr = dma_map_single(NULL, ep->cmd,
+ sizeof(struct ipa_ip_packet_init),
+ DMA_TO_DEVICE);
+ if (ep->dma_addr == 0 || ep->dma_addr == ~0) {
+ IPAERR("failed to DMA MAP pkt_init\n");
+ result = -ENOMEM;
+ kfree(ep->cmd);
+ goto fail;
+ }
+ }
+
ep->valid = 1;
ep->client = in->client;
ep->client_notify = in->notify;
@@ -433,6 +453,13 @@
return -EPERM;
}
+ if (IPA_CLIENT_IS_CONS(ep->client)) {
+ dma_unmap_single(NULL, ep->dma_addr,
+ sizeof(struct ipa_ip_packet_init),
+ DMA_TO_DEVICE);
+ kfree(ep->cmd);
+ }
+
ipa_enable_data_path(clnt_hdl);
memset(&ipa_ctx->ep[clnt_hdl], 0, sizeof(struct ipa_ep_context));
diff --git a/drivers/platform/msm/ipa/ipa_dp.c b/drivers/platform/msm/ipa/ipa_dp.c
index 1b6181f..c564922 100644
--- a/drivers/platform/msm/ipa/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_dp.c
@@ -19,18 +19,20 @@
#define list_next_entry(pos, member) \
list_entry(pos->member.next, typeof(*pos), member)
-#define IPA_LAST_DESC_CNT 0xFFFF
#define POLLING_INACTIVITY_RX 40
-#define POLLING_MIN_SLEEP_RX 950
-#define POLLING_MAX_SLEEP_RX 1050
-#define POLLING_INACTIVITY_TX 40
-#define POLLING_MIN_SLEEP_TX 400
-#define POLLING_MAX_SLEEP_TX 500
+#define POLLING_MIN_SLEEP_RX 2350
+#define POLLING_MAX_SLEEP_RX 2450
+#define POLLING_INACTIVITY_TX 10
+#define POLLING_MIN_SLEEP_TX 100
+#define POLLING_MAX_SLEEP_TX 200
+#define RX_MAX_IND 40
static void replenish_rx_work_func(struct work_struct *work);
static struct delayed_work replenish_rx_work;
static void ipa_wq_handle_rx(struct work_struct *work);
static DECLARE_WORK(rx_work, ipa_wq_handle_rx);
+static void ipa_wq_handle_tx(struct work_struct *work);
+static DECLARE_WORK(tx_work, ipa_wq_handle_tx);
/**
* ipa_write_done() - this function will be (eventually) called when a Tx
@@ -81,7 +83,7 @@
if (tx_pkt->callback)
tx_pkt->callback(tx_pkt->user1, tx_pkt->user2);
- kmem_cache_free(ipa_ctx->tx_pkt_wrapper_cache, tx_pkt);
+ kfree(tx_pkt);
}
int ipa_handle_tx_core(struct ipa_sys_context *sys, bool process_all,
@@ -119,23 +121,13 @@
IPADBG("--curr_cnt=%d\n", sys->len);
- if (unlikely(ipa_ctx->ipa_hw_type == IPA_HW_v1_0))
- dma_pool_free(ipa_ctx->dma_pool,
- tx_pkt->bounce,
- tx_pkt->mem.phys_base);
- else
+ if (tx_pkt->callback) {
dma_unmap_single(NULL, tx_pkt->mem.phys_base,
- tx_pkt->mem.size,
- DMA_TO_DEVICE);
-
- if (tx_pkt->callback)
+ tx_pkt->mem.size, DMA_TO_DEVICE);
tx_pkt->callback(tx_pkt->user1, tx_pkt->user2);
+ }
- if (tx_pkt->cnt > 1 && tx_pkt->cnt != IPA_LAST_DESC_CNT)
- dma_pool_free(ipa_ctx->dma_pool, tx_pkt->mult.base,
- tx_pkt->mult.phys_base);
-
- kmem_cache_free(ipa_ctx->tx_pkt_wrapper_cache, tx_pkt);
+ kfree(tx_pkt);
cnt++;
};
@@ -154,11 +146,6 @@
goto fail;
}
- ret = sps_get_config(sys->ep->ep_hdl, &sys->ep->connect);
- if (ret) {
- IPAERR("sps_get_config() failed %d\n", ret);
- goto fail;
- }
sys->event.options = SPS_O_EOT;
ret = sps_register_event(sys->ep->ep_hdl, &sys->event);
if (ret) {
@@ -205,9 +192,7 @@
static void ipa_wq_handle_tx(struct work_struct *work)
{
- struct ipa_tx_pkt_wrapper *tx_pkt;
- tx_pkt = container_of(work, struct ipa_tx_pkt_wrapper, work);
- ipa_handle_tx(tx_pkt->sys);
+ ipa_handle_tx(&ipa_ctx->sys[IPA_A5_LAN_WAN_OUT]);
}
/**
@@ -240,7 +225,7 @@
if (unlikely(!in_atomic))
mem_flag = GFP_KERNEL;
- tx_pkt = kmem_cache_zalloc(ipa_ctx->tx_pkt_wrapper_cache, mem_flag);
+ tx_pkt = kmalloc(sizeof(struct ipa_tx_pkt_wrapper), mem_flag);
if (!tx_pkt) {
IPAERR("failed to alloc tx wrapper\n");
goto fail_mem_alloc;
@@ -296,14 +281,11 @@
IPADBG("sending cmd=%d pyld_len=%d sps_flags=%x\n",
desc->opcode, desc->len, sps_flags);
IPA_DUMP_BUFF(desc->pyld, dma_address, desc->len);
- INIT_WORK(&tx_pkt->work, ipa_wq_write_done);
} else {
len = desc->len;
- INIT_WORK(&tx_pkt->work, ipa_wq_handle_tx);
}
- if (unlikely(ipa_ctx->polling_mode))
- INIT_WORK(&tx_pkt->work, ipa_wq_handle_tx);
+ INIT_WORK(&tx_pkt->work, ipa_wq_write_done);
spin_lock_irqsave(&sys->spinlock, irq_flags);
list_add_tail(&tx_pkt->link, &sys->head_desc_list);
@@ -327,192 +309,12 @@
else
dma_unmap_single(NULL, dma_address, desc->len, DMA_TO_DEVICE);
fail_dma_map:
- kmem_cache_free(ipa_ctx->tx_pkt_wrapper_cache, tx_pkt);
+ kfree(tx_pkt);
fail_mem_alloc:
return -EFAULT;
}
/**
- * ipa_send() - Send multiple descriptors in one HW transaction
- * @sys: system pipe context
- * @num_desc: number of packets
- * @desc: packets to send (may be immediate command or data)
- * @in_atomic: whether caller is in atomic context
- *
- * This function is used for system-to-bam connection.
- * - SPS driver expect struct sps_transfer which will contain all the data
- * for a transaction
- * - The sps_transfer struct will be pointing to bounce buffers for
- * its DMA command (immediate command and data)
- * - ipa_tx_pkt_wrapper will be used for each ipa
- * descriptor (allocated from wrappers cache)
- * - The wrapper struct will be configured for each ipa-desc payload and will
- * contain information which will be later used by the user callbacks
- * - each transfer will be made by calling to sps_transfer()
- * - Each packet (command or data) that will be sent will also be saved in
- * ipa_sys_context for later check that all data was sent
- *
- * Return codes: 0: success, -EFAULT: failure
- */
-int ipa_send(struct ipa_sys_context *sys, u32 num_desc, struct ipa_desc *desc,
- bool in_atomic)
-{
- struct ipa_tx_pkt_wrapper *tx_pkt;
- struct ipa_tx_pkt_wrapper *next_pkt;
- struct sps_transfer transfer = { 0 };
- struct sps_iovec *iovec;
- unsigned long irq_flags;
- dma_addr_t dma_addr;
- int i = 0;
- int j;
- int result;
- int fail_dma_wrap = 0;
- uint size = num_desc * sizeof(struct sps_iovec);
- u32 mem_flag = GFP_ATOMIC;
-
- if (unlikely(!in_atomic))
- mem_flag = GFP_KERNEL;
-
- transfer.iovec = dma_pool_alloc(ipa_ctx->dma_pool, mem_flag, &dma_addr);
- transfer.iovec_phys = dma_addr;
- transfer.iovec_count = num_desc;
- spin_lock_irqsave(&sys->spinlock, irq_flags);
- if (!transfer.iovec) {
- IPAERR("fail to alloc DMA mem for sps xfr buff\n");
- goto failure_coherent;
- }
-
- for (i = 0; i < num_desc; i++) {
- fail_dma_wrap = 0;
- tx_pkt = kmem_cache_zalloc(ipa_ctx->tx_pkt_wrapper_cache,
- mem_flag);
- if (!tx_pkt) {
- IPAERR("failed to alloc tx wrapper\n");
- goto failure;
- }
- /*
- * first desc of set is "special" as it holds the count and
- * other info
- */
- if (i == 0) {
- transfer.user = tx_pkt;
- tx_pkt->mult.phys_base = dma_addr;
- tx_pkt->mult.base = transfer.iovec;
- tx_pkt->mult.size = size;
- tx_pkt->cnt = num_desc;
- INIT_WORK(&tx_pkt->work, ipa_wq_handle_tx);
- }
-
- iovec = &transfer.iovec[i];
- iovec->flags = 0;
-
- INIT_LIST_HEAD(&tx_pkt->link);
- tx_pkt->type = desc[i].type;
-
- tx_pkt->mem.base = desc[i].pyld;
- tx_pkt->mem.size = desc[i].len;
-
- if (unlikely(ipa_ctx->ipa_hw_type == IPA_HW_v1_0)) {
- WARN_ON(tx_pkt->mem.size > 512);
-
- /*
- * Due to a HW limitation, we need to make sure that the
- * packet does not cross a 1KB boundary
- */
- tx_pkt->bounce =
- dma_pool_alloc(ipa_ctx->dma_pool,
- mem_flag,
- &tx_pkt->mem.phys_base);
- if (!tx_pkt->bounce) {
- tx_pkt->mem.phys_base = 0;
- } else {
- WARN_ON(!ipa_straddle_boundary(
- (u32)tx_pkt->mem.phys_base,
- (u32)tx_pkt->mem.phys_base +
- tx_pkt->mem.size - 1, 1024));
- memcpy(tx_pkt->bounce, tx_pkt->mem.base,
- tx_pkt->mem.size);
- }
- } else {
- tx_pkt->mem.phys_base =
- dma_map_single(NULL, tx_pkt->mem.base,
- tx_pkt->mem.size,
- DMA_TO_DEVICE);
- }
- if (!tx_pkt->mem.phys_base) {
- IPAERR("failed to alloc tx wrapper\n");
- fail_dma_wrap = 1;
- goto failure;
- }
-
- tx_pkt->sys = sys;
- tx_pkt->callback = desc[i].callback;
- tx_pkt->user1 = desc[i].user1;
- tx_pkt->user2 = desc[i].user2;
-
- /*
- * Point the iovec to the bounce buffer and
- * add this packet to system pipe context.
- */
- iovec->addr = tx_pkt->mem.phys_base;
- list_add_tail(&tx_pkt->link, &sys->head_desc_list);
-
- /*
- * Special treatment for immediate commands, where the structure
- * of the descriptor is different
- */
- if (desc[i].type == IPA_IMM_CMD_DESC) {
- iovec->size = desc[i].opcode;
- iovec->flags |= SPS_IOVEC_FLAG_IMME;
- } else {
- iovec->size = desc[i].len;
- }
-
- if (i == (num_desc - 1)) {
- iovec->flags |= SPS_IOVEC_FLAG_EOT;
- /* "mark" the last desc */
- tx_pkt->cnt = IPA_LAST_DESC_CNT;
- }
- }
-
- result = sps_transfer(sys->ep->ep_hdl, &transfer);
- if (result) {
- IPAERR("sps_transfer failed rc=%d\n", result);
- goto failure;
- }
-
- spin_unlock_irqrestore(&sys->spinlock, irq_flags);
- return 0;
-
-failure:
- tx_pkt = transfer.user;
- for (j = 0; j < i; j++) {
- next_pkt = list_next_entry(tx_pkt, link);
- list_del(&tx_pkt->link);
- if (unlikely(ipa_ctx->ipa_hw_type == IPA_HW_v1_0))
- dma_pool_free(ipa_ctx->dma_pool,
- tx_pkt->bounce,
- tx_pkt->mem.phys_base);
- else
- dma_unmap_single(NULL, tx_pkt->mem.phys_base,
- tx_pkt->mem.size,
- DMA_TO_DEVICE);
- kmem_cache_free(ipa_ctx->tx_pkt_wrapper_cache, tx_pkt);
- tx_pkt = next_pkt;
- }
- if (i < num_desc)
- /* last desc failed */
- if (fail_dma_wrap)
- kmem_cache_free(ipa_ctx->tx_pkt_wrapper_cache, tx_pkt);
- if (transfer.iovec_phys)
- dma_pool_free(ipa_ctx->dma_pool, transfer.iovec,
- transfer.iovec_phys);
-failure_coherent:
- spin_unlock_irqrestore(&sys->spinlock, irq_flags);
- return -EFAULT;
-}
-
-/**
* ipa_sps_irq_cmd_ack - callback function which will be called by SPS driver after an
* immediate command is complete.
* @user1: pointer to the descriptor of the transfer
@@ -543,7 +345,6 @@
*/
int ipa_send_cmd(u16 num_desc, struct ipa_desc *descr)
{
- struct ipa_desc *desc;
int result = 0;
ipa_inc_client_enable_clks();
@@ -563,22 +364,10 @@
}
wait_for_completion(&descr->xfer_done);
} else {
- desc = &descr[num_desc - 1];
- init_completion(&desc->xfer_done);
-
- if (desc->callback || desc->user1)
- WARN_ON(1);
-
- desc->callback = ipa_sps_irq_cmd_ack;
- desc->user1 = desc;
- if (ipa_send(&ipa_ctx->sys[IPA_A5_CMD], num_desc,
- descr, false)) {
- IPAERR("fail to send multiple immediate command set\n");
+ IPAERR("unsupported chaining multiple IC\n");
result = -EFAULT;
goto bail;
}
- wait_for_completion(&desc->xfer_done);
- }
IPA_STATS_INC_IC_CNT(num_desc, descr, ipa_ctx->stats.imm_cmds);
bail:
@@ -597,21 +386,13 @@
static void ipa_sps_irq_tx_notify(struct sps_event_notify *notify)
{
struct ipa_sys_context *sys = &ipa_ctx->sys[IPA_A5_LAN_WAN_OUT];
- struct ipa_tx_pkt_wrapper *tx_pkt;
int ret;
IPADBG("event %d notified\n", notify->event_id);
switch (notify->event_id) {
case SPS_EVENT_EOT:
- tx_pkt = notify->data.transfer.user;
if (!atomic_read(&sys->curr_polling_state)) {
- ret = sps_get_config(sys->ep->ep_hdl,
- &sys->ep->connect);
- if (ret) {
- IPAERR("sps_get_config() failed %d\n", ret);
- break;
- }
sys->ep->connect.options = SPS_O_AUTO_ENABLE |
SPS_O_ACK_TRANSFERS | SPS_O_POLL;
ret = sps_set_config(sys->ep->ep_hdl,
@@ -621,7 +402,7 @@
break;
}
atomic_set(&sys->curr_polling_state, 1);
- queue_work(ipa_ctx->tx_wq, &tx_pkt->work);
+ queue_work(ipa_ctx->tx_wq, &tx_work);
}
break;
default:
@@ -654,6 +435,47 @@
}
}
+static void ipa_handle_tag_rsp(struct ipa_a5_mux_hdr *mux_hdr)
+{
+ struct completion *compl;
+ struct ipa_tree_node *node;
+
+ /* retrieve the compl object from tag value */
+ mux_hdr++;
+ compl = (struct completion *) ntohl(*((u32 *)mux_hdr));
+ IPADBG("%x %x %p\n", *(u32 *)mux_hdr, *((u32 *)mux_hdr + 1), compl);
+
+ mutex_lock(&ipa_ctx->lock);
+ node = ipa_search(&ipa_ctx->tag_tree, (u32)compl);
+ if (node) {
+ complete_all(compl);
+ rb_erase(&node->node, &ipa_ctx->tag_tree);
+ kmem_cache_free(ipa_ctx->tree_node_cache, node);
+ } else {
+ WARN_ON(1);
+ }
+ mutex_unlock(&ipa_ctx->lock);
+}
+
+static void ipa_dejitter(bool limit)
+{
+ struct sk_buff *skb;
+ int len = skb_queue_len(&ipa_ctx->rx_list);
+ int i;
+ void *cookie;
+ ipa_notify_cb cb;
+
+ if (limit && len >= RX_MAX_IND)
+ len = RX_MAX_IND;
+
+ for (i = len; i > 0; i--) {
+ skb = __skb_dequeue(&ipa_ctx->rx_list);
+ cb = (ipa_notify_cb)*(u32 *)&(skb->cb[0]);
+ cookie = (void *)*(u32 *)&(skb->cb[4]);
+ cb(cookie, IPA_RECEIVE, (unsigned long)skb);
+ }
+}
+
/**
* ipa_handle_rx_core() - The core functionality of packet reception. This
* function is read from multiple code paths.
@@ -675,13 +497,9 @@
struct ipa_rx_pkt_wrapper *rx_pkt;
struct sk_buff *rx_skb;
struct sps_iovec iov;
- unsigned int pull_len;
- unsigned int padding;
int ret;
struct ipa_ep_context *ep;
int cnt = 0;
- struct completion *compl;
- struct ipa_tree_node *node;
unsigned int src_pipe;
while ((in_poll_state ? atomic_read(&sys->curr_polling_state) :
@@ -721,7 +539,7 @@
rx_skb->tail = rx_skb->data + rx_pkt->len;
rx_skb->len = rx_pkt->len;
rx_skb->truesize = rx_pkt->len + sizeof(struct sk_buff);
- kmem_cache_free(ipa_ctx->rx_pkt_wrapper_cache, rx_pkt);
+ kfree(rx_pkt);
mux_hdr = (struct ipa_a5_mux_hdr *)rx_skb->data;
@@ -736,29 +554,9 @@
IPA_STATS_INC_CNT(ipa_ctx->stats.rx_pkts);
IPA_STATS_EXCP_CNT(mux_hdr->flags, ipa_ctx->stats.rx_excp_pkts);
- if (unlikely(mux_hdr->flags & IPA_A5_MUX_HDR_EXCP_FLAG_TAG)) {
- if (ipa_ctx->ipa_hw_mode != IPA_HW_MODE_VIRTUAL) {
- /* retrieve the compl object from tag value */
- mux_hdr++;
- compl = (struct completion *)
- ntohl(*((u32 *)mux_hdr));
- IPADBG("%x %x %p\n", *(u32 *)mux_hdr,
- *((u32 *)mux_hdr + 1), compl);
-
- mutex_lock(&ipa_ctx->lock);
- node = ipa_search(&ipa_ctx->tag_tree,
- (u32)compl);
- if (node) {
- complete_all(compl);
- rb_erase(&node->node,
- &ipa_ctx->tag_tree);
- kmem_cache_free(
- ipa_ctx->tree_node_cache, node);
- } else {
- WARN_ON(1);
- }
- mutex_unlock(&ipa_ctx->lock);
- }
+ if (mux_hdr->flags & IPA_A5_MUX_HDR_EXCP_FLAG_TAG) {
+ if (ipa_ctx->ipa_hw_mode != IPA_HW_MODE_VIRTUAL)
+ ipa_handle_tag_rsp(mux_hdr);
dev_kfree_skb(rx_skb);
ipa_replenish_rx_cache();
++cnt;
@@ -769,38 +567,22 @@
* Any packets arriving over AMPDU_TX should be dispatched
* to the regular WLAN RX data-path.
*/
- if (unlikely(src_pipe == WLAN_AMPDU_TX_EP))
+ if (src_pipe == WLAN_AMPDU_TX_EP)
src_pipe = WLAN_PROD_TX_EP;
- if (unlikely(src_pipe >= IPA_NUM_PIPES ||
- !ipa_ctx->ep[src_pipe].valid ||
- !ipa_ctx->ep[src_pipe].client_notify)) {
- IPAERR("drop pipe=%d ep_valid=%d client_notify=%p\n",
- src_pipe, ipa_ctx->ep[src_pipe].valid,
- ipa_ctx->ep[src_pipe].client_notify);
- dev_kfree_skb(rx_skb);
- ipa_replenish_rx_cache();
- ++cnt;
- continue;
- }
+ WARN_ON(src_pipe >= IPA_NUM_PIPES);
ep = &ipa_ctx->ep[src_pipe];
- pull_len = sizeof(struct ipa_a5_mux_hdr);
-
- /*
- * IP packet starts on word boundary
- * remove the MUX header and any padding and pass the frame to
- * the client which registered a rx callback on the "src pipe"
- */
- padding = ep->cfg.hdr.hdr_len & 0x3;
- if (padding)
- pull_len += 4 - padding;
-
- IPADBG("pulling %d bytes from skb\n", pull_len);
- skb_pull(rx_skb, pull_len);
+ IPADBG("pulling %d bytes from skb\n", ep->pull_len);
+ skb_pull(rx_skb, ep->pull_len);
ipa_replenish_rx_cache();
- ep->client_notify(ep->priv, IPA_RECEIVE,
- (unsigned long)(rx_skb));
+ if (ep->client_notify) {
+ __skb_queue_tail(&ipa_ctx->rx_list, rx_skb);
+ *(u32 *)&(rx_skb->cb[0]) = (u32)ep->client_notify;
+ *(u32 *)&(rx_skb->cb[4]) = (u32)ep->priv;
+ } else {
+ dev_kfree_skb(rx_skb);
+ }
cnt++;
};
@@ -819,11 +601,6 @@
goto fail;
}
- ret = sps_get_config(sys->ep->ep_hdl, &sys->ep->connect);
- if (ret) {
- IPAERR("sps_get_config() failed %d\n", ret);
- goto fail;
- }
sys->event.options = SPS_O_EOT;
ret = sps_register_event(sys->ep->ep_hdl, &sys->event);
if (ret) {
@@ -870,12 +647,6 @@
switch (notify->event_id) {
case SPS_EVENT_EOT:
if (!atomic_read(&sys->curr_polling_state)) {
- ret = sps_get_config(sys->ep->ep_hdl,
- &sys->ep->connect);
- if (ret) {
- IPAERR("sps_get_config() failed %d\n", ret);
- break;
- }
sys->ep->connect.options = SPS_O_AUTO_ENABLE |
SPS_O_ACK_TRANSFERS | SPS_O_POLL;
ret = sps_set_config(sys->ep->ep_hdl,
@@ -925,8 +696,10 @@
} else {
inactive_cycles = 0;
}
+ ipa_dejitter(true);
} while (inactive_cycles <= POLLING_INACTIVITY_RX);
+ ipa_dejitter(false);
ipa_rx_switch_to_intr_mode(sys);
ipa_dec_client_disable_clks();
}
@@ -1062,6 +835,7 @@
break;
case 2:
sys_idx = ipa_ep_idx;
+ ipa_ctx->sys[sys_idx].max_len = sys_in->desc_fifo_sz / 8 - 2;
INIT_DELAYED_WORK(&ipa_ctx->sys[sys_idx].switch_to_intr_work,
switch_to_intr_tx_work_func);
break;
@@ -1176,9 +950,87 @@
dev_kfree_skb(skb);
}
-static void ipa_tx_cmd_comp(void *user1, void *user2)
+static int ipa_send_two(struct sk_buff *skb, struct ipa_sys_context *sys,
+ int dst_ep_idx)
{
- kfree(user1);
+ struct ipa_tx_pkt_wrapper *tx_pktc;
+ struct ipa_tx_pkt_wrapper *tx_pktd;
+ struct ipa_ep_context *ep = &ipa_ctx->ep[dst_ep_idx];
+ unsigned long irq_flags;
+ dma_addr_t dma_addrd;
+ int rc = -ENOMEM;
+
+ tx_pktc = kmalloc(sizeof(struct ipa_tx_pkt_wrapper), GFP_ATOMIC);
+ if (!tx_pktc) {
+ IPAERR("failed to alloc tx wrapper C\n");
+ goto fail_mem_alloc_c;
+ }
+
+ tx_pktd = kmalloc(sizeof(struct ipa_tx_pkt_wrapper), GFP_ATOMIC);
+ if (!tx_pktd) {
+ IPAERR("failed to alloc tx wrapper D\n");
+ goto fail_mem_alloc_d;
+ }
+
+ dma_addrd = dma_map_single(NULL, skb->data, skb->len, DMA_TO_DEVICE);
+ if (!dma_addrd) {
+ IPAERR("failed to DMA wrap\n");
+ goto fail_dma_map_d;
+ }
+
+ INIT_LIST_HEAD(&tx_pktc->link);
+ tx_pktc->callback = NULL;
+
+ INIT_LIST_HEAD(&tx_pktd->link);
+ tx_pktd->mem.phys_base = dma_addrd;
+ tx_pktd->mem.base = skb->data;
+ tx_pktd->mem.size = skb->len;
+ tx_pktd->callback = ipa_tx_comp_usr_notify_release;
+ tx_pktd->user1 = skb;
+ tx_pktd->user2 = (void *)dst_ep_idx;
+
+ spin_lock_irqsave(&sys->spinlock, irq_flags);
+ if (sys->len >= sys->max_len)
+ goto fail_oom;
+ list_add_tail(&tx_pktc->link, &sys->head_desc_list);
+ if (sps_transfer_one(sys->ep->ep_hdl, ep->dma_addr, IPA_IP_PACKET_INIT,
+ tx_pktc, SPS_IOVEC_FLAG_IMME |
+ SPS_IOVEC_FLAG_NO_SUBMIT))
+ IPAERR("sps_transfer_one 0 failed\n");
+ list_add_tail(&tx_pktd->link, &sys->head_desc_list);
+ if (sps_transfer_one(sys->ep->ep_hdl, dma_addrd, skb->len, tx_pktd,
+ SPS_IOVEC_FLAG_EOT | SPS_IOVEC_FLAG_INT))
+ IPAERR("sps_transfer_one 1 failed\n");
+ sys->len += 2;
+ spin_unlock_irqrestore(&sys->spinlock, irq_flags);
+ return 0;
+
+fail_oom:
+ dma_unmap_single(NULL, dma_addrd, skb->len, DMA_TO_DEVICE);
+fail_dma_map_d:
+ kfree(tx_pktd);
+fail_mem_alloc_d:
+ kfree(tx_pktc);
+fail_mem_alloc_c:
+ return rc;
+}
+
+static int ipa_send_data_hw_path(struct sk_buff *skb,
+ struct ipa_sys_context *sys, int dst_ep_idx)
+{
+ struct ipa_desc desc;
+
+ desc.pyld = skb->data;
+ desc.len = skb->len;
+ desc.type = IPA_DATA_DESC_SKB;
+ desc.callback = ipa_tx_comp_usr_notify_release;
+ desc.user1 = skb;
+ desc.user2 = (void *)dst_ep_idx;
+
+ if (ipa_send_one(sys, &desc, true))
+ return -EFAULT;
+
+ return 0;
}
/**
@@ -1211,76 +1063,42 @@
int ipa_tx_dp(enum ipa_client_type dst, struct sk_buff *skb,
struct ipa_tx_meta *meta)
{
- struct ipa_desc desc[2];
int ipa_ep_idx;
- struct ipa_ip_packet_init *cmd;
-
- memset(&desc, 0, 2 * sizeof(struct ipa_desc));
ipa_ep_idx = ipa_get_ep_mapping(ipa_ctx->mode, dst);
if (unlikely(ipa_ep_idx == -1)) {
IPAERR("dest EP does not exist.\n");
- goto fail_gen;
+ goto fail;
}
if (unlikely(ipa_ctx->ep[ipa_ep_idx].valid == 0)) {
IPAERR("dest EP not valid.\n");
- goto fail_gen;
+ goto fail;
}
if (IPA_CLIENT_IS_CONS(dst)) {
- cmd = kzalloc(sizeof(struct ipa_ip_packet_init), GFP_ATOMIC);
- if (!cmd) {
- IPAERR("failed to alloc immediate command object\n");
- goto fail_mem_alloc;
- }
-
- cmd->destination_pipe_index = ipa_ep_idx;
- if (meta && meta->mbim_stream_id_valid)
- cmd->metadata = meta->mbim_stream_id;
- desc[0].opcode = IPA_IP_PACKET_INIT;
- desc[0].pyld = cmd;
- desc[0].len = sizeof(struct ipa_ip_packet_init);
- desc[0].type = IPA_IMM_CMD_DESC;
- desc[0].callback = ipa_tx_cmd_comp;
- desc[0].user1 = cmd;
- desc[1].pyld = skb->data;
- desc[1].len = skb->len;
- desc[1].type = IPA_DATA_DESC_SKB;
- desc[1].callback = ipa_tx_comp_usr_notify_release;
- desc[1].user1 = skb;
- desc[1].user2 = (void *)ipa_ep_idx;
-
- if (ipa_send(&ipa_ctx->sys[IPA_A5_LAN_WAN_OUT], 2, desc,
- true)) {
- IPAERR("fail to send immediate command\n");
- goto fail_send;
+ if (ipa_send_two(skb, &ipa_ctx->sys[IPA_A5_LAN_WAN_OUT],
+ ipa_ep_idx)) {
+ IPAERR("fail to send pkt_init+skb dst=%d skb=%p\n",
+ dst, skb);
+ goto fail;
}
IPA_STATS_INC_CNT(ipa_ctx->stats.imm_cmds[IPA_IP_PACKET_INIT]);
} else if (dst == IPA_CLIENT_A5_WLAN_AMPDU_PROD) {
- desc[0].pyld = skb->data;
- desc[0].len = skb->len;
- desc[0].type = IPA_DATA_DESC_SKB;
- desc[0].callback = ipa_tx_comp_usr_notify_release;
- desc[0].user1 = skb;
- desc[0].user2 = (void *)ipa_ep_idx;
-
- if (ipa_send_one(&ipa_ctx->sys[IPA_A5_WLAN_AMPDU_OUT],
- &desc[0], true)) {
- IPAERR("fail to send skb\n");
- goto fail_gen;
+ if (ipa_send_data_hw_path(skb,
+ &ipa_ctx->sys[IPA_A5_WLAN_AMPDU_OUT],
+ ipa_ep_idx)) {
+ IPAERR("fail to send skb dst=%d skb=%p\n", dst, skb);
+ goto fail;
}
} else {
IPAERR("%d PROD is not supported.\n", dst);
- goto fail_gen;
+ goto fail;
}
return 0;
-fail_send:
- kfree(cmd);
-fail_mem_alloc:
-fail_gen:
+fail:
return -EFAULT;
}
EXPORT_SYMBOL(ipa_tx_dp);
@@ -1316,8 +1134,7 @@
rx_len_cached = sys->len;
while (rx_len_cached < IPA_RX_POOL_CEIL) {
- rx_pkt = kmem_cache_zalloc(ipa_ctx->rx_pkt_wrapper_cache,
- flag);
+ rx_pkt = kmalloc(sizeof(struct ipa_rx_pkt_wrapper), flag);
if (!rx_pkt) {
IPAERR("failed to alloc rx wrapper\n");
goto fail_kmem_cache_alloc;
@@ -1365,7 +1182,7 @@
fail_dma_mapping:
dev_kfree_skb(rx_pkt->skb);
fail_skb_alloc:
- kmem_cache_free(ipa_ctx->rx_pkt_wrapper_cache, rx_pkt);
+ kfree(rx_pkt);
fail_kmem_cache_alloc:
if (rx_len_cached == 0) {
IPA_STATS_INC_CNT(ipa_ctx->stats.rx_repl_repost);
@@ -1397,7 +1214,7 @@
dma_unmap_single(NULL, rx_pkt->dma_address, IPA_RX_SKB_SIZE,
DMA_FROM_DEVICE);
dev_kfree_skb(rx_pkt->skb);
- kmem_cache_free(ipa_ctx->rx_pkt_wrapper_cache, rx_pkt);
+ kfree(rx_pkt);
}
}
diff --git a/drivers/platform/msm/ipa/ipa_i.h b/drivers/platform/msm/ipa/ipa_i.h
index b57194e..a818931 100644
--- a/drivers/platform/msm/ipa/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_i.h
@@ -363,6 +363,9 @@
bool desc_fifo_client_allocated;
bool data_fifo_client_allocated;
bool suspended;
+ unsigned int pull_len;
+ struct ipa_ip_packet_init *cmd;
+ dma_addr_t dma_addr;
};
/**
@@ -378,6 +381,7 @@
struct ipa_sys_context {
struct list_head head_desc_list;
u32 len;
+ u32 max_len;
spinlock_t spinlock;
struct sps_register_event event;
struct ipa_ep_context *ep;
@@ -636,8 +640,6 @@
struct kmem_cache *hdr_cache;
struct kmem_cache *hdr_offset_cache;
struct kmem_cache *rt_tbl_cache;
- struct kmem_cache *tx_pkt_wrapper_cache;
- struct kmem_cache *rx_pkt_wrapper_cache;
struct kmem_cache *tree_node_cache;
unsigned long rt_idx_bitmap[IPA_IP_MAX];
struct mutex lock;
@@ -687,6 +689,7 @@
/* store HOLB configuration for WLAN TX pipes */
u32 hol_en;
u32 hol_timer;
+ struct sk_buff_head rx_list;
};
/**
@@ -775,8 +778,6 @@
u32 *consumer_handle);
int ipa_send_one(struct ipa_sys_context *sys, struct ipa_desc *desc,
bool in_atomic);
-int ipa_send(struct ipa_sys_context *sys, u32 num_desc, struct ipa_desc *desc,
- bool in_atomic);
int ipa_get_ep_mapping(enum ipa_operating_mode mode,
enum ipa_client_type client);
int ipa_get_client_mapping(enum ipa_operating_mode mode, int pipe_idx);
diff --git a/drivers/platform/msm/ipa/ipa_utils.c b/drivers/platform/msm/ipa/ipa_utils.c
index 264de0d..046c4d4 100644
--- a/drivers/platform/msm/ipa/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_utils.c
@@ -32,6 +32,24 @@
{ 19, -1, -1, -1, -1, 11, 15, 8, 6, 2, 1, 5, 14, 16, 17, 18, -1, 10, 9, 7, 3, 4 },
};
+static unsigned int ipa_calc_pull_len(u32 hdr_len)
+{
+ unsigned int pull_len, padding;
+
+ pull_len = sizeof(struct ipa_a5_mux_hdr);
+
+ /*
+ * IP packet starts on word boundary
+ * remove the MUX header and any padding and pass the frame to
+ * the client which registered a rx callback on the "src pipe"
+ */
+ padding = hdr_len & 0x3;
+ if (padding)
+ pull_len += 4 - padding;
+
+ return pull_len;
+}
+
/**
* ipa_cfg_route() - configure IPA route
* @route: IPA route
@@ -751,6 +769,9 @@
ipa_write_reg(ipa_ctx->mmio,
IPA_ENDP_INIT_HDR_n_OFST_v2(clnt_hdl), val);
+ if (IPA_CLIENT_IS_PROD(ep->client))
+ ep->pull_len = ipa_calc_pull_len(ipa_ep_cfg->hdr_len);
+
return 0;
}
EXPORT_SYMBOL(ipa_cfg_ep_hdr);
@@ -1263,4 +1284,3 @@
else
return 0;
}
-
diff --git a/drivers/platform/msm/sps/sps.c b/drivers/platform/msm/sps/sps.c
index 81d80e6..2e77114 100644
--- a/drivers/platform/msm/sps/sps.c
+++ b/drivers/platform/msm/sps/sps.c
@@ -1985,6 +1985,35 @@
EXPORT_SYMBOL(sps_get_unused_desc_num);
/**
+ * Vote for or relinquish BAM DMA clock
+ *
+ */
+int sps_ctrl_bam_dma_clk(bool clk_on)
+{
+ int ret;
+
+ SPS_DBG("sps:%s.", __func__);
+
+ if (!sps->is_ready)
+ return -EPROBE_DEFER;
+
+ if (clk_on == true) {
+ SPS_DBG("sps:vote for bam dma clk.\n");
+ ret = clk_prepare_enable(sps->bamdma_clk);
+ if (ret) {
+ SPS_ERR("sps:fail to enable bamdma_clk:ret=%d\n", ret);
+ return ret;
+ }
+ } else {
+ SPS_DBG("sps:relinquish bam dma clk.\n");
+ clk_disable_unprepare(sps->bamdma_clk);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(sps_ctrl_bam_dma_clk);
+
+/**
* Register a BAM device
*
*/
@@ -2525,11 +2554,13 @@
SPS_ERR("sps:sps_device_init err.");
#ifdef CONFIG_SPS_SUPPORT_BAMDMA
clk_disable_unprepare(sps->dfab_clk);
+ clk_disable_unprepare(sps->bamdma_clk);
#endif
goto sps_device_init_err;
}
#ifdef CONFIG_SPS_SUPPORT_BAMDMA
clk_disable_unprepare(sps->dfab_clk);
+ clk_disable_unprepare(sps->bamdma_clk);
#endif
sps->is_ready = true;
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index af5442a..5f049a6 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -137,6 +137,7 @@
int connect_complete;
bool lpm_wait_pipes;
int bus_suspend;
+ bool disconnected;
bool in_lpm[MAX_BAMS];
int (*wake_cb)(void *);
@@ -758,8 +759,16 @@
mutex_lock(&info.suspend_resume_mutex);
- /* If resume was called don't finish this work */
spin_lock(&usb_bam_ipa_handshake_info_lock);
+ /* If cable was disconnected, let disconnection seq do everything */
+ if (info.disconnected) {
+ spin_unlock(&usb_bam_ipa_handshake_info_lock);
+ mutex_unlock(&info.suspend_resume_mutex);
+ pr_debug("%s: Cable disconnected\n", __func__);
+ return;
+ }
+
+ /* If resume was called don't finish this work */
if (!info.bus_suspend) {
spin_unlock(&usb_bam_ipa_handshake_info_lock);
pr_err("%s: Bus suspend in progress\n", __func__);
@@ -785,8 +794,8 @@
ipa_rm_resource_cons[cur_bam]);
}
ipa_suspend_pipes();
- mutex_unlock(&info.suspend_resume_mutex);
usb_bam_start_lpm(0);
+ mutex_unlock(&info.suspend_resume_mutex);
return;
}
@@ -1158,11 +1167,21 @@
spin_unlock(&usb_bam_ipa_handshake_info_lock);
}
+ spin_lock(&usb_bam_ipa_handshake_info_lock);
+ /* If cable was disconnected, let disconnection seq do everything */
+ if (info.disconnected) {
+ spin_unlock(&usb_bam_ipa_handshake_info_lock);
+ pr_debug("%s: Cable disconnected\n", __func__);
+ return;
+ }
+
/* Don't go to LPM if data in the pipes */
if (!check_pipes_empty(src_idx, dst_idx)) {
+ spin_unlock(&usb_bam_ipa_handshake_info_lock);
pr_err("%s: pipes not empty, won't start suspend", __func__);
return;
}
+ spin_unlock(&usb_bam_ipa_handshake_info_lock);
queue_work(ctx.usb_bam_wq, &info.suspend_work);
}
@@ -1173,9 +1192,18 @@
mutex_lock(&info.suspend_resume_mutex);
spin_lock(&usb_bam_ipa_handshake_info_lock);
+ /* If cable was disconnected, let disconnection seq do everything */
+ if (info.disconnected) {
+ spin_unlock(&usb_bam_ipa_handshake_info_lock);
+ mutex_unlock(&info.suspend_resume_mutex);
+ pr_debug("%s: Cable disconnected\n", __func__);
+ return;
+ }
+
if (!info.bus_suspend) {
spin_unlock(&usb_bam_ipa_handshake_info_lock);
pr_err("%s: Resume started, not suspending", __func__);
+ mutex_unlock(&info.suspend_resume_mutex);
return;
}
@@ -1431,6 +1459,7 @@
spin_lock(&usb_bam_ipa_handshake_info_lock);
info.lpm_wait_handshake[HSUSB_BAM] = true;
info.connect_complete = 0;
+ info.disconnected = 0;
info.lpm_wait_pipes = 1;
info.bus_suspend = 0;
info.cons_stopped = 0;
@@ -1942,6 +1971,9 @@
/* Do the release handshake with the A2 via RM */
cur_bam = pipe_connect->bam_type;
info.lpm_wait_pipes = 1;
+ spin_lock(&usb_bam_ipa_handshake_info_lock);
+ info.disconnected = 1;
+ spin_unlock(&usb_bam_ipa_handshake_info_lock);
wait_for_prod_release(cur_bam);
/* close USB -> IPA pipe */
usb_bam_resume_core(cur_bam);
@@ -2004,8 +2036,8 @@
ipa_rm_resource_cons[cur_bam]);
}
pr_debug("%s Ended disconnect sequence\n", __func__);
- mutex_unlock(&info.suspend_resume_mutex);
usb_bam_start_lpm(1);
+ mutex_unlock(&info.suspend_resume_mutex);
return 0;
}
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 24825ea..a5da421 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -25,6 +25,9 @@
#include <linux/power_supply.h>
#include <linux/bitops.h>
#include <linux/ratelimit.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/regulator/machine.h>
/* Interrupt offsets */
#define INT_RT_STS(base) (base + 0x10)
@@ -92,8 +95,12 @@
#define SEC_ACCESS 0xD0
#define BAT_IF_VREF_BAT_THM_CTRL 0x4A
#define BAT_IF_BPD_CTRL 0x48
+#define BOOST_VSET 0x41
+#define BOOST_ENABLE_CONTROL 0x46
+#define COMP_OVR1 0xEA
#define REG_OFFSET_PERP_SUBTYPE 0x05
+
/* SMBB peripheral subtype values */
#define SMBB_CHGR_SUBTYPE 0x01
#define SMBB_BUCK_SUBTYPE 0x02
@@ -132,6 +139,7 @@
#define REV_BST_DETECTED BIT(0)
#define BAT_THM_EN BIT(1)
#define BAT_ID_EN BIT(0)
+#define BOOST_PWR_EN BIT(7)
/* Interrupt definitions */
/* smbb_chg_interrupts */
@@ -183,12 +191,18 @@
/* Workaround flags */
#define CHG_FLAGS_VCP_WA BIT(0)
+#define BOOST_FLASH_WA BIT(1)
struct qpnp_chg_irq {
unsigned int irq;
unsigned long disabled;
};
+struct qpnp_chg_regulator {
+ struct regulator_desc rdesc;
+ struct regulator_dev *rdev;
+};
+
/**
* struct qpnp_chg_chip - device information
* @dev: device pointer to access the parent
@@ -263,6 +277,7 @@
bool batt_present;
bool charging_disabled;
bool use_default_batt_values;
+ bool duty_cycle_100p;
unsigned int bpd_detection;
unsigned int max_bat_chg_current;
unsigned int warm_bat_chg_ma;
@@ -295,6 +310,8 @@
struct delayed_work arb_stop_work;
struct delayed_work eoc_work;
struct wake_lock eoc_wake_lock;
+ struct qpnp_chg_regulator otg_vreg;
+ struct qpnp_chg_regulator boost_vreg;
};
@@ -425,6 +442,25 @@
}
static int
+qpnp_chg_is_boost_en_set(struct qpnp_chg_chip *chip)
+{
+ u8 boost_en_ctl;
+ int rc;
+
+ rc = qpnp_chg_read(chip, &boost_en_ctl,
+ chip->boost_base + BOOST_ENABLE_CONTROL, 1);
+ if (rc) {
+ pr_err("spmi read failed: addr=%03X, rc=%d\n",
+ chip->boost_base + BOOST_ENABLE_CONTROL, rc);
+ return rc;
+ }
+
+ pr_debug("boost en 0x%x\n", boost_en_ctl);
+
+ return (boost_en_ctl & BOOST_PWR_EN) ? 1 : 0;
+}
+
+static int
qpnp_chg_is_batt_present(struct qpnp_chg_chip *chip)
{
u8 batt_pres_rt_sts;
@@ -610,6 +646,32 @@
disable ? CHGR_ON_BAT_FORCE_BIT : 0, 1);
}
+#define BUCK_DUTY_MASK_100P 0x30
+static int
+qpnp_buck_set_100_duty_cycle_enable(struct qpnp_chg_chip *chip, int enable)
+{
+ int rc;
+
+ pr_debug("enable: %d\n", enable);
+
+ rc = qpnp_chg_masked_write(chip,
+ chip->buck_base + SEC_ACCESS, 0xA5, 0xA5, 1);
+ if (rc) {
+ pr_debug("failed to write sec access rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = qpnp_chg_masked_write(chip,
+ chip->buck_base + BUCK_TEST_SMBC_MODES,
+ BUCK_DUTY_MASK_100P, enable ? 0x00 : 0x10, 1);
+ if (rc) {
+ pr_debug("failed enable 100p duty cycle rc=%d\n", rc);
+ return rc;
+ }
+
+ return rc;
+}
+
#define COMPATATOR_OVERRIDE_0 0x80
static int
qpnp_chg_toggle_chg_done_logic(struct qpnp_chg_chip *chip, int enable)
@@ -1215,21 +1277,6 @@
chip->bms_psy = power_supply_get_by_name("bms");
chip->usb_psy->get_property(chip->usb_psy,
- POWER_SUPPLY_PROP_SCOPE, &ret);
- if (ret.intval) {
- if ((ret.intval == POWER_SUPPLY_SCOPE_SYSTEM)
- && !qpnp_chg_is_otg_en_set(chip)) {
- switch_usb_to_host_mode(chip);
- return;
- }
- if ((ret.intval == POWER_SUPPLY_SCOPE_DEVICE)
- && qpnp_chg_is_otg_en_set(chip)) {
- switch_usb_to_charge_mode(chip);
- return;
- }
- }
-
- chip->usb_psy->get_property(chip->usb_psy,
POWER_SUPPLY_PROP_ONLINE, &ret);
/* Only honour requests while USB is present */
@@ -1457,6 +1504,48 @@
return qpnp_chg_write(chip, &temp, chip->chgr_base + CHGR_VDD_MAX, 1);
}
+#define BOOST_MIN_UV 4200000
+#define BOOST_MAX_UV 5500000
+#define BOOST_STEP_UV 50000
+#define BOOST_MIN 16
+#define N_BOOST_V ((BOOST_MAX_UV - BOOST_MIN_UV) / BOOST_STEP_UV + 1)
+static int
+qpnp_boost_vset(struct qpnp_chg_chip *chip, int voltage)
+{
+ u8 reg = 0;
+
+ if (voltage < BOOST_MIN_UV || voltage > BOOST_MAX_UV) {
+ pr_err("invalid voltage requested %d uV\n", voltage);
+ return -EINVAL;
+ }
+
+ reg = DIV_ROUND_UP(voltage - BOOST_MIN_UV, BOOST_STEP_UV) + BOOST_MIN;
+
+ pr_debug("voltage=%d setting %02x\n", voltage, reg);
+ return qpnp_chg_write(chip, ®, chip->boost_base + BOOST_VSET, 1);
+}
+
+static int
+qpnp_boost_vget_uv(struct qpnp_chg_chip *chip)
+{
+ int rc;
+ u8 boost_reg;
+
+ rc = qpnp_chg_read(chip, &boost_reg,
+ chip->boost_base + BOOST_VSET, 1);
+ if (rc) {
+ pr_err("failed to read BOOST_VSET rc=%d\n", rc);
+ return rc;
+ }
+
+ if (boost_reg < BOOST_MIN) {
+ pr_err("Invalid reading from 0x%x\n", boost_reg);
+ return -EINVAL;
+ }
+
+ return BOOST_MIN_UV + ((boost_reg - BOOST_MIN) * BOOST_STEP_UV);
+}
+
/* JEITA compliance logic */
static void
qpnp_chg_set_appropriate_vddmax(struct qpnp_chg_chip *chip)
@@ -1519,6 +1608,228 @@
}
}
+/* OTG regulator operations */
+static int
+qpnp_chg_regulator_otg_enable(struct regulator_dev *rdev)
+{
+ struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
+
+ return switch_usb_to_host_mode(chip);
+}
+
+static int
+qpnp_chg_regulator_otg_disable(struct regulator_dev *rdev)
+{
+ struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
+
+ return switch_usb_to_charge_mode(chip);
+}
+
+static int
+qpnp_chg_regulator_otg_is_enabled(struct regulator_dev *rdev)
+{
+ struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
+
+ return qpnp_chg_is_otg_en_set(chip);
+}
+
+static int
+qpnp_chg_regulator_boost_enable(struct regulator_dev *rdev)
+{
+ struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
+ int rc;
+
+ if (qpnp_chg_is_usb_chg_plugged_in(chip) &&
+ (chip->flags & BOOST_FLASH_WA)) {
+ qpnp_chg_usb_suspend_enable(chip, 1);
+
+ rc = qpnp_chg_masked_write(chip,
+ chip->usb_chgpth_base + SEC_ACCESS,
+ 0xFF,
+ 0xA5, 1);
+ if (rc) {
+ pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = qpnp_chg_masked_write(chip,
+ chip->usb_chgpth_base + COMP_OVR1,
+ 0xFF,
+ 0x2F, 1);
+ if (rc) {
+ pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
+ return rc;
+ }
+ }
+
+ return qpnp_chg_masked_write(chip,
+ chip->boost_base + BOOST_ENABLE_CONTROL,
+ BOOST_PWR_EN,
+ BOOST_PWR_EN, 1);
+}
+
+/* Boost regulator operations */
+#define ABOVE_VBAT_WEAK BIT(1)
+static int
+qpnp_chg_regulator_boost_disable(struct regulator_dev *rdev)
+{
+ struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
+ int rc;
+ u8 vbat_sts;
+
+ rc = qpnp_chg_masked_write(chip,
+ chip->boost_base + BOOST_ENABLE_CONTROL,
+ BOOST_PWR_EN,
+ 0, 1);
+ if (rc) {
+ pr_err("failed to disable boost rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = qpnp_chg_read(chip, &vbat_sts,
+ chip->chgr_base + CHGR_VBAT_STATUS, 1);
+ if (rc) {
+ pr_err("failed to read bat sts rc=%d\n", rc);
+ return rc;
+ }
+
+ if (!(vbat_sts & ABOVE_VBAT_WEAK) && (chip->flags & BOOST_FLASH_WA)) {
+ rc = qpnp_chg_masked_write(chip,
+ chip->chgr_base + SEC_ACCESS,
+ 0xFF,
+ 0xA5, 1);
+ if (rc) {
+ pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = qpnp_chg_masked_write(chip,
+ chip->chgr_base + COMP_OVR1,
+ 0xFF,
+ 0x20, 1);
+ if (rc) {
+ pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
+ return rc;
+ }
+
+ usleep(2000);
+
+ rc = qpnp_chg_masked_write(chip,
+ chip->chgr_base + SEC_ACCESS,
+ 0xFF,
+ 0xA5, 1);
+ if (rc) {
+ pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = qpnp_chg_masked_write(chip,
+ chip->chgr_base + COMP_OVR1,
+ 0xFF,
+ 0x00, 1);
+ if (rc) {
+ pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
+ return rc;
+ }
+ }
+
+ if (qpnp_chg_is_usb_chg_plugged_in(chip)
+ && (chip->flags & BOOST_FLASH_WA)) {
+ rc = qpnp_chg_masked_write(chip,
+ chip->usb_chgpth_base + SEC_ACCESS,
+ 0xFF,
+ 0xA5, 1);
+ if (rc) {
+ pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = qpnp_chg_masked_write(chip,
+ chip->usb_chgpth_base + COMP_OVR1,
+ 0xFF,
+ 0x00, 1);
+ if (rc) {
+ pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
+ return rc;
+ }
+
+ usleep(1000);
+
+ qpnp_chg_usb_suspend_enable(chip, 0);
+ }
+
+ return rc;
+}
+
+static int
+qpnp_chg_regulator_boost_is_enabled(struct regulator_dev *rdev)
+{
+ struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
+
+ return qpnp_chg_is_boost_en_set(chip);
+}
+
+static int
+qpnp_chg_regulator_boost_set_voltage(struct regulator_dev *rdev,
+ int min_uV, int max_uV, unsigned *selector)
+{
+ int uV = min_uV;
+ int rc;
+ struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
+
+ if (uV < BOOST_MIN_UV && max_uV >= BOOST_MIN_UV)
+ uV = BOOST_MIN_UV;
+
+
+ if (uV < BOOST_MIN_UV || uV > BOOST_MAX_UV) {
+ pr_err("request %d uV is out of bounds\n", uV);
+ return -EINVAL;
+ }
+
+ *selector = DIV_ROUND_UP(uV - BOOST_MIN_UV, BOOST_STEP_UV);
+ if ((*selector * BOOST_STEP_UV + BOOST_MIN_UV) > max_uV) {
+ pr_err("no available setpoint [%d, %d] uV\n", min_uV, max_uV);
+ return -EINVAL;
+ }
+
+ rc = qpnp_boost_vset(chip, uV);
+
+ return rc;
+}
+
+static int
+qpnp_chg_regulator_boost_get_voltage(struct regulator_dev *rdev)
+{
+ struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
+
+ return qpnp_boost_vget_uv(chip);
+}
+
+static int
+qpnp_chg_regulator_boost_list_voltage(struct regulator_dev *rdev,
+ unsigned selector)
+{
+ if (selector >= N_BOOST_V)
+ return 0;
+
+ return BOOST_MIN_UV + (selector * BOOST_STEP_UV);
+}
+
+static struct regulator_ops qpnp_chg_otg_reg_ops = {
+ .enable = qpnp_chg_regulator_otg_enable,
+ .disable = qpnp_chg_regulator_otg_disable,
+ .is_enabled = qpnp_chg_regulator_otg_is_enabled,
+};
+
+static struct regulator_ops qpnp_chg_boost_reg_ops = {
+ .enable = qpnp_chg_regulator_boost_enable,
+ .disable = qpnp_chg_regulator_boost_disable,
+ .is_enabled = qpnp_chg_regulator_boost_is_enabled,
+ .set_voltage = qpnp_chg_regulator_boost_set_voltage,
+ .get_voltage = qpnp_chg_regulator_boost_get_voltage,
+ .list_voltage = qpnp_chg_regulator_boost_list_voltage,
+};
+
#define CONSECUTIVE_COUNT 3
static void
qpnp_eoc_work(struct work_struct *work)
@@ -1705,6 +2016,8 @@
{
if (chip->revision > 0 && chip->type == SMBB)
chip->flags |= CHG_FLAGS_VCP_WA;
+ if (chip->type == SMBB)
+ chip->flags |= BOOST_FLASH_WA;
}
static int
@@ -1906,6 +2219,8 @@
{
int rc = 0;
u8 reg = 0;
+ struct regulator_init_data *init_data;
+ struct regulator_desc *rdesc;
switch (subtype) {
case SMBB_CHGR_SUBTYPE:
@@ -2022,6 +2337,38 @@
}
}
+ init_data = of_get_regulator_init_data(chip->dev,
+ spmi_resource->of_node);
+ if (!init_data) {
+ pr_err("unable to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ if (init_data->constraints.name) {
+ if (of_get_property(chip->dev->of_node,
+ "otg-parent-supply", NULL))
+ init_data->supply_regulator = "otg-parent";
+
+ rdesc = &(chip->otg_vreg.rdesc);
+ rdesc->owner = THIS_MODULE;
+ rdesc->type = REGULATOR_VOLTAGE;
+ rdesc->ops = &qpnp_chg_otg_reg_ops;
+ rdesc->name = init_data->constraints.name;
+
+ init_data->constraints.valid_ops_mask
+ |= REGULATOR_CHANGE_STATUS;
+
+ chip->otg_vreg.rdev = regulator_register(rdesc,
+ chip->dev, init_data, chip,
+ spmi_resource->of_node);
+ if (IS_ERR(chip->otg_vreg.rdev)) {
+ rc = PTR_ERR(chip->otg_vreg.rdev);
+ if (rc != -EPROBE_DEFER)
+ pr_err("OTG reg failed, rc=%d\n", rc);
+ return rc;
+ }
+ }
+
rc = qpnp_chg_masked_write(chip,
chip->usb_chgpth_base + USB_OVP_CTL,
USB_VALID_DEB_20MS,
@@ -2047,6 +2394,38 @@
break;
case SMBB_BOOST_SUBTYPE:
case SMBBP_BOOST_SUBTYPE:
+ init_data = of_get_regulator_init_data(chip->dev,
+ spmi_resource->of_node);
+ if (!init_data) {
+ pr_err("unable to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ if (init_data->constraints.name) {
+ if (of_get_property(chip->dev->of_node,
+ "boost-parent-supply", NULL))
+ init_data->supply_regulator = "boost-parent";
+
+ rdesc = &(chip->boost_vreg.rdesc);
+ rdesc->owner = THIS_MODULE;
+ rdesc->type = REGULATOR_VOLTAGE;
+ rdesc->ops = &qpnp_chg_boost_reg_ops;
+ rdesc->name = init_data->constraints.name;
+
+ init_data->constraints.valid_ops_mask
+ |= REGULATOR_CHANGE_STATUS
+ | REGULATOR_CHANGE_VOLTAGE;
+
+ chip->boost_vreg.rdev = regulator_register(rdesc,
+ chip->dev, init_data, chip,
+ spmi_resource->of_node);
+ if (IS_ERR(chip->boost_vreg.rdev)) {
+ rc = PTR_ERR(chip->boost_vreg.rdev);
+ if (rc != -EPROBE_DEFER)
+ pr_err("boost reg failed, rc=%d\n", rc);
+ return rc;
+ }
+ }
break;
case SMBB_MISC_SUBTYPE:
case SMBBP_MISC_SUBTYPE:
@@ -2149,6 +2528,18 @@
chip->charging_disabled = of_property_read_bool(chip->spmi->dev.of_node,
"qcom,charging-disabled");
+ /* Get the duty-cycle-100p property */
+ 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 =
of_property_read_bool(chip->spmi->dev.of_node,
@@ -2298,7 +2689,8 @@
chip->usb_chgpth_base = resource->start;
rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
if (rc) {
- pr_err("Failed to init subtype 0x%x rc=%d\n",
+ if (rc != -EPROBE_DEFER)
+ pr_err("Failed to init subtype 0x%x rc=%d\n",
subtype, rc);
goto fail_chg_enable;
}
@@ -2317,7 +2709,8 @@
chip->boost_base = resource->start;
rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
if (rc) {
- pr_err("Failed to init subtype 0x%x rc=%d\n",
+ if (rc != -EPROBE_DEFER)
+ pr_err("Failed to init subtype 0x%x rc=%d\n",
subtype, rc);
goto fail_chg_enable;
}
@@ -2470,6 +2863,12 @@
cancel_work_sync(&chip->adc_measure_work);
cancel_delayed_work_sync(&chip->eoc_work);
+ if (chip->otg_vreg.rdev)
+ regulator_unregister(chip->otg_vreg.rdev);
+
+ if (chip->boost_vreg.rdev)
+ regulator_unregister(chip->boost_vreg.rdev);
+
dev_set_drvdata(&spmi->dev, NULL);
kfree(chip);
diff --git a/drivers/thermal/msm8974-tsens.c b/drivers/thermal/msm8974-tsens.c
index f01a078..52608af 100644
--- a/drivers/thermal/msm8974-tsens.c
+++ b/drivers/thermal/msm8974-tsens.c
@@ -17,6 +17,7 @@
#include <linux/platform_device.h>
#include <linux/thermal.h>
#include <linux/interrupt.h>
+#include <linux/workqueue.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/io.h>
@@ -258,6 +259,7 @@
struct tsens_tm_device {
struct platform_device *pdev;
+ struct workqueue_struct *tsens_wq;
bool prev_reading_avail;
bool calibration_less_mode;
bool tsens_local_init;
@@ -655,7 +657,7 @@
}
if (upper_thr || lower_thr) {
/* Notify user space */
- schedule_work(&tm->sensor[i].work);
+ queue_work(tm->tsens_wq, &tm->sensor[i].work);
rc = tsens_get_sw_id_mapping(
tm->sensor[i].sensor_hw_num,
&sensor_sw_id);
@@ -673,7 +675,7 @@
static irqreturn_t tsens_isr(int irq, void *data)
{
- schedule_work(&tmdev->tsens_work);
+ queue_work(tmdev->tsens_wq, &tmdev->tsens_work);
return IRQ_HANDLED;
}
@@ -1506,6 +1508,12 @@
return -ENODEV;
tmdev->pdev = pdev;
+ tmdev->tsens_wq = alloc_workqueue("tsens_wq", WQ_HIGHPRI, 0);
+ if (!tmdev->tsens_wq) {
+ rc = -ENOMEM;
+ goto fail;
+ }
+
rc = tsens_calib_sensors();
if (rc < 0) {
pr_err("Calibration failed\n");
@@ -1520,6 +1528,8 @@
return 0;
fail:
+ if (tmdev->tsens_wq)
+ destroy_workqueue(tmdev->tsens_wq);
if (tmdev->tsens_calib_addr)
iounmap(tmdev->tsens_calib_addr);
if (tmdev->res_calib_mem)
@@ -1610,6 +1620,7 @@
release_mem_region(tmdev->res_tsens_mem->start,
tmdev->tsens_len);
free_irq(tmdev->tsens_irq, tmdev);
+ destroy_workqueue(tmdev->tsens_wq);
platform_set_drvdata(pdev, NULL);
return 0;
diff --git a/drivers/tty/n_smux.c b/drivers/tty/n_smux.c
index 8760603..d1545dc 100644
--- a/drivers/tty/n_smux.c
+++ b/drivers/tty/n_smux.c
@@ -1,6 +1,6 @@
/* drivers/tty/n_smux.c
*
- * 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
@@ -259,6 +259,8 @@
unsigned powerdown_enabled;
unsigned power_ctl_remote_req_received;
struct list_head power_queue;
+ unsigned remote_initiated_wakeup_count;
+ unsigned local_initiated_wakeup_count;
};
@@ -279,6 +281,7 @@
[SMUX_CMD_CLOSE_LCH] = "CLOSE",
[SMUX_CMD_STATUS] = "STATUS",
[SMUX_CMD_PWR_CTL] = "PWR",
+ [SMUX_CMD_DELAY] = "DELAY",
[SMUX_CMD_BYTE] = "Raw Byte",
};
@@ -1908,6 +1911,7 @@
/* wakeup system */
SMUX_PWR("smux: %s: Power %d->%d\n", __func__,
smux.power_state, SMUX_PWR_ON);
+ smux.remote_initiated_wakeup_count++;
smux.power_state = SMUX_PWR_ON;
queue_work(smux_tx_wq, &smux_wakeup_work);
queue_work(smux_tx_wq, &smux_tx_work);
@@ -2163,6 +2167,62 @@
}
/**
+ * Sends a delay command to the remote side.
+ *
+ * @ms: Time in milliseconds for the remote side to delay
+ *
+ * This command defines the delay that the remote side will use
+ * to slow the response time for DATA commands.
+ */
+void smux_set_loopback_data_reply_delay(uint32_t ms)
+{
+ struct smux_lch_t *ch = &smux_lch[SMUX_TEST_LCID];
+ struct smux_pkt_t *pkt;
+
+ pkt = smux_alloc_pkt();
+ if (!pkt) {
+ pr_err("%s: unable to allocate packet\n", __func__);
+ return;
+ }
+
+ pkt->hdr.lcid = ch->lcid;
+ pkt->hdr.cmd = SMUX_CMD_DELAY;
+ pkt->hdr.flags = 0;
+ pkt->hdr.payload_len = sizeof(uint32_t);
+ pkt->hdr.pad_len = 0;
+
+ if (smux_alloc_pkt_payload(pkt)) {
+ pr_err("%s: unable to allocate payload\n", __func__);
+ smux_free_pkt(pkt);
+ return;
+ }
+ memcpy(pkt->payload, &ms, sizeof(uint32_t));
+
+ smux_tx_queue(pkt, ch, 1);
+}
+
+/**
+ * Retrieve wakeup counts.
+ *
+ * @local_cnt: Pointer to local wakeup count
+ * @remote_cnt: Pointer to remote wakeup count
+ */
+void smux_get_wakeup_counts(int *local_cnt, int *remote_cnt)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&smux.tx_lock_lha2, flags);
+
+ if (local_cnt)
+ *local_cnt = smux.local_initiated_wakeup_count;
+
+ if (remote_cnt)
+ *remote_cnt = smux.remote_initiated_wakeup_count;
+
+ spin_unlock_irqrestore(&smux.tx_lock_lha2, flags);
+}
+
+/**
* Add channel to transmit-ready list and trigger transmit worker.
*
* @ch Channel to add
@@ -2744,6 +2804,7 @@
SMUX_PWR("smux: %s: Power %d->%d\n", __func__,
smux.power_state,
SMUX_PWR_TURNING_ON);
+ smux.local_initiated_wakeup_count++;
smux.power_state = SMUX_PWR_TURNING_ON;
spin_unlock_irqrestore(&smux.tx_lock_lha2,
flags);
diff --git a/drivers/tty/smux_private.h b/drivers/tty/smux_private.h
index 8fdec86..b9a2e89 100644
--- a/drivers/tty/smux_private.h
+++ b/drivers/tty/smux_private.h
@@ -1,6 +1,6 @@
/* drivers/tty/smux_private.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
@@ -122,6 +122,7 @@
SMUX_CMD_CLOSE_LCH = 0x2,
SMUX_CMD_STATUS = 0x3,
SMUX_CMD_PWR_CTL = 0x4,
+ SMUX_CMD_DELAY = 0x5,
SMUX_CMD_BYTE, /* for internal usage */
SMUX_NUM_COMMANDS
@@ -181,6 +182,8 @@
void smuxld_receive_buf(struct tty_struct *tty, const unsigned char *cp,
char *fp, int count);
bool smux_remote_is_active(void);
+void smux_set_loopback_data_reply_delay(uint32_t ms);
+void smux_get_wakeup_counts(int *local_cnt, int *remote_cnt);
/* testing parameters */
extern int smux_byte_loopback;
diff --git a/drivers/tty/smux_test.c b/drivers/tty/smux_test.c
index e1d9975..8d17674 100644
--- a/drivers/tty/smux_test.c
+++ b/drivers/tty/smux_test.c
@@ -1,6 +1,6 @@
/* drivers/tty/smux_test.c
*
- * 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
@@ -20,11 +20,17 @@
#include <linux/delay.h>
#include <linux/completion.h>
#include <linux/termios.h>
+#include <linux/sched.h>
#include <linux/smux.h>
#include <mach/subsystem_restart.h>
#include "smux_private.h"
#define DEBUG_BUFMAX 4096
+#define RED_ZONE_SIZE 16
+#define RED_ZONE_PRE_CH 0xAB
+#define RED_ZONE_POS_CH 0xBA
+#define SMUX_REMOTE_INACTIVITY_TIME_MS 50
+#define SMUX_REMOTE_DELAY_TIME_MS 250
/**
* Unit test assertion for logging test cases.
@@ -138,7 +144,7 @@
/**
* Allocates a new buffer for SMUX for every call.
*/
-int get_rx_buffer(void *priv, void **pkt_priv, void **buffer, int size)
+static int get_rx_buffer(void *priv, void **pkt_priv, void **buffer, int size)
{
void *rx_buf;
@@ -216,7 +222,7 @@
*
* @cb Mock callback data
*/
-void mock_cb_data_init(struct smux_mock_callback *cb)
+static void mock_cb_data_init(struct smux_mock_callback *cb)
{
init_completion(&cb->cb_completion);
spin_lock_init(&cb->lock);
@@ -232,7 +238,7 @@
*
* All packets are freed and counters reset to zero.
*/
-void mock_cb_data_reset(struct smux_mock_callback *cb)
+static void mock_cb_data_reset(struct smux_mock_callback *cb)
{
cb->cb_count = 0;
INIT_COMPLETION(cb->cb_completion);
@@ -341,7 +347,7 @@
* Mock object event callback. Used to logs events for analysis in the unit
* tests.
*/
-void smux_mock_cb(void *priv, int event, const void *metadata)
+static void smux_mock_cb(void *priv, int event, const void *metadata)
{
struct smux_mock_callback *cb_data_ptr;
struct mock_write_event *write_event_meta;
@@ -518,12 +524,17 @@
for (; vectors->data != NULL; ++vectors) {
const char *test_data = vectors->data;
const unsigned test_len = vectors->len;
+ unsigned long long start_t;
+ unsigned long long end_t;
+ unsigned long long val;
+ unsigned long rem;
i += scnprintf(buf + i, max - i,
- "Writing vector %p len %d\n",
+ "Writing vector %p len %d: ",
test_data, test_len);
/* write data */
+ start_t = sched_clock();
msm_smux_write(SMUX_TEST_LCID, (void *)0xCAFEFACE,
test_data, test_len);
UT_ASSERT_INT(ret, ==, 0);
@@ -538,6 +549,7 @@
(int)wait_for_completion_timeout(
&cb_data.cb_completion, HZ),
>, 0);
+ end_t = sched_clock();
UT_ASSERT_INT(cb_data.cb_count, >=, 1);
UT_ASSERT_INT(cb_data.event_write_done, ==, 1);
@@ -569,16 +581,28 @@
hex_dump_to_buffer(test_data, test_len,
16, 1, linebuff, sizeof(linebuff), 1);
i += scnprintf(buf + i, max - i,
- "Expected:\n%s\n\n", linebuff);
+ "Failed\nExpected:\n%s\n\n", linebuff);
hex_dump_to_buffer(read_event->meta.buffer,
read_event->meta.len,
16, 1, linebuff, sizeof(linebuff), 1);
i += scnprintf(buf + i, max - i,
- "Actual:\n%s\n", linebuff);
+ "Failed\nActual:\n%s\n", linebuff);
failed = 1;
break;
}
+
+ /* calculate throughput stats */
+ val = end_t - start_t;
+ rem = do_div(val, 1000);
+ i += scnprintf(buf + i, max - i,
+ "OK - %u us",
+ (unsigned int)val);
+
+ val = 1000000000LL * 2 * test_len;
+ rem = do_div(val, end_t - start_t);
+ i += scnprintf(buf + i, max - i,
+ " (%u kB/sec)\n", (unsigned int)val);
mock_cb_data_reset(&cb_data);
}
@@ -682,7 +706,7 @@
* Run a basic loopback test followed by a subsystem restart and then another
* loopback test.
*/
-static int smux_ut_remote_ssr_basic(char *buf, int max)
+static int smux_ut_ssr_remote_basic(char *buf, int max)
{
const struct test_vector test_data[] = {
{"hello\0world\n", sizeof("hello\0world\n")},
@@ -723,7 +747,7 @@
/**
* Verify Subsystem Restart Support During Port Open
*/
-static int smux_ut_remote_ssr_open(char *buf, int max)
+static int smux_ut_ssr_remote_open(char *buf, int max)
{
static struct smux_mock_callback cb_data;
static int cb_initialized;
@@ -805,7 +829,7 @@
*
* @returns Number of bytes written to @buf
*/
-static int smux_ut_remote_ssr_rx_buff_retry(char *buf, int max)
+static int smux_ut_ssr_remote_rx_buff_retry(char *buf, int max)
{
static struct smux_mock_callback cb_data;
static int cb_initialized;
@@ -897,9 +921,10 @@
mock_cb_data_reset(&cb_data);
return i;
}
+
/**
* Fill test pattern into provided buffer including an optional
- * redzone 16 bytes before and 16 bytes after the buffer.
+ * redzone before and after the buffer.
*
* buf ---------
* redzone
@@ -909,70 +934,75 @@
* redzone
* ---------
*
- * @buf Pointer to the buffer of size len or len+32 (redzone)
- * @len Length of the *data* buffer (excluding 32-byte redzone)
+ * @buf Pointer to the buffer of size len or len+2*RED_ZONE_SIZE (redzone)
+ * @len Length of the *data* buffer (excluding the extra redzone buffers)
* @redzone If true, adds redzone data
*
- * @returns pointer to buffer (buf + 16 if redzone enabled)
+ * @returns pointer to buffer (buf + RED_ZONE_SIZE if redzone enabled)
*/
-uint8_t *test_pattern_fill(char *buf, int len, int redzone)
+static uint8_t *test_pattern_fill(char *buf, int len, int redzone)
{
- void *ret;
+ char *buf_ptr;
uint8_t ch;
- ret = buf;
if (redzone) {
- memset((char *)buf, 0xAB, 16);
- memset((char *)buf + len, 0xBA, 16);
- ret += 16;
+ memset(buf, RED_ZONE_PRE_CH, RED_ZONE_SIZE);
+ buf += RED_ZONE_SIZE;
+ memset(buf + len, RED_ZONE_POS_CH, RED_ZONE_SIZE);
}
- /* fill with test pattern */
- for (ch = 0; len > 0; --len, ++ch)
- *buf++ = (char)ch;
+ for (ch = 0, buf_ptr = buf; len > 0; --len, ++ch)
+ *buf_ptr++ = (char)ch;
- return ret;
+ return buf;
}
/**
* Verify test pattern generated by test_pattern_fill.
*
* @buf_ptr Pointer to buffer pointer
- * @len Length of the *data* buffer (excluding 32-byte redzone)
+ * @len Length of the *data* buffer (excluding redzone bytes)
* @redzone If true, verifies redzone and adjusts *buf_ptr
* @errmsg Buffer for error message
* @errmsg_max Size of error message buffer
*
* @returns 0 for success; length of error message otherwise
*/
-unsigned test_pattern_verify(char **buf_ptr, int len, int redzone,
+static unsigned test_pattern_verify(char **buf_ptr, int len, int redzone,
char *errmsg, int errmsg_max)
{
int n;
int i = 0;
char linebuff[80];
+ char *zone_ptr;
if (redzone) {
- *buf_ptr -= 16;
+ *buf_ptr -= RED_ZONE_SIZE;
+ zone_ptr = *buf_ptr;
/* verify prefix redzone */
- for (n = 0; n < 16; ++n) {
- if (*buf_ptr[n] != 0xAB) {
- hex_dump_to_buffer(*buf_ptr, 16,
- 16, 1, linebuff, sizeof(linebuff), 1);
+ for (n = 0; n < RED_ZONE_SIZE; ++n) {
+ if (zone_ptr[n] != RED_ZONE_PRE_CH) {
+ hex_dump_to_buffer(zone_ptr, RED_ZONE_SIZE,
+ RED_ZONE_SIZE, 1, linebuff,
+ sizeof(linebuff), 1);
i += scnprintf(errmsg + i, errmsg_max - i,
- "Redzone violation: %s\n", linebuff);
+ "Pre-redzone violation: %s\n",
+ linebuff);
break;
}
}
/* verify postfix redzone */
- for (n = 0; n < 16; ++n) {
- if (*buf_ptr[len + n] != 0xBA) {
- hex_dump_to_buffer(&(*buf_ptr)[len], 16,
- 16, 1, linebuff, sizeof(linebuff), 1);
+ zone_ptr = *buf_ptr + RED_ZONE_SIZE + len;
+ for (n = 0; n < RED_ZONE_SIZE; ++n) {
+ if (zone_ptr[n] != RED_ZONE_POS_CH) {
+ hex_dump_to_buffer(zone_ptr, RED_ZONE_SIZE,
+ RED_ZONE_SIZE, 1, linebuff,
+ sizeof(linebuff), 1);
i += scnprintf(errmsg + i, errmsg_max - i,
- "Redzone violation: %s\n", linebuff);
+ "Post-redzone violation: %s\n",
+ linebuff);
break;
}
}
@@ -1001,6 +1031,7 @@
{0, 256},
{0, 512},
{0, 1024},
+ {0, 1500},
{0, 2048},
{0, 4096},
{0, 0},
@@ -1011,9 +1042,7 @@
/* generate test data */
for (tv = test_data; tv->len > 0; ++tv) {
- tv->data = kmalloc(tv->len + 32, GFP_KERNEL);
- pr_err("%s: allocating %p len %d\n",
- __func__, tv->data, tv->len);
+ tv->data = kmalloc(tv->len + 2 * RED_ZONE_SIZE, GFP_KERNEL);
if (!tv->data) {
i += scnprintf(buf + i, max - i,
"%s: Unable to allocate %d bytes\n",
@@ -1021,7 +1050,7 @@
failed = 1;
goto out;
}
- test_pattern_fill((uint8_t *)tv->data, tv->len, 1);
+ tv->data = test_pattern_fill((uint8_t *)tv->data, tv->len, 1);
}
/* run test */
@@ -1038,11 +1067,9 @@
}
for (tv = test_data; tv->len > 0; ++tv) {
- if (!tv->data) {
+ if (tv->data) {
i += test_pattern_verify((char **)&tv->data,
tv->len, 1, buf + i, max - i);
- pr_err("%s: freeing %p len %d\n", __func__,
- tv->data, tv->len);
kfree(tv->data);
}
}
@@ -1112,6 +1139,59 @@
}
/**
+ * Run a large packet test for throughput metrics.
+ *
+ * Repeatedly send a packet for 100 iterations to get throughput metrics.
+ */
+static int smux_ut_remote_throughput(char *buf, int max)
+{
+ struct test_vector test_data[] = {
+ {0, 1500},
+ {0, 0},
+ };
+ int failed = 0;
+ int i = 0;
+ int loop = 0;
+ struct test_vector *tv;
+ int ret;
+
+ /* generate test data */
+ for (tv = test_data; tv->len > 0; ++tv) {
+ tv->data = kmalloc(tv->len, GFP_KERNEL);
+ if (!tv->data) {
+ i += scnprintf(buf + i, max - i,
+ "%s: Unable to allocate %d bytes\n",
+ __func__, tv->len);
+ failed = 1;
+ goto out;
+ }
+ test_pattern_fill((uint8_t *)tv->data, tv->len, 0);
+ }
+
+ /* run test */
+ i += scnprintf(buf + i, max - i, "Running %s\n", __func__);
+ while (!failed && loop < 100) {
+ ret = msm_smux_set_ch_option(SMUX_TEST_LCID,
+ SMUX_CH_OPTION_REMOTE_LOOPBACK, 0);
+ UT_ASSERT_INT(ret, ==, 0);
+
+ i += smux_ut_basic_core(buf + i, max - i, test_data, __func__);
+ ++loop;
+ }
+
+out:
+ if (failed) {
+ pr_err("%s: Failed\n", __func__);
+ i += scnprintf(buf + i, max - i, "\tFailed\n");
+ }
+
+ for (tv = test_data; tv->len > 0; ++tv)
+ kfree(tv->data);
+
+ return i;
+}
+
+/**
* Verify set and get operations for each TIOCM bit.
*
* @buf Buffer for status message
@@ -2083,6 +2163,126 @@
return i;
}
+/**
+ * Verify Remote-initiated wakeup test case.
+ *
+ * @buf Output buffer for failure/status messages
+ * @max Size of @buf
+ */
+static int smux_ut_remote_initiated_wakeup(char *buf, int max)
+{
+ int i = 0;
+ int failed = 0;
+ static struct smux_mock_callback cb_data;
+ static int cb_initialized;
+ int ret;
+
+ if (!cb_initialized)
+ mock_cb_data_init(&cb_data);
+
+ smux_set_loopback_data_reply_delay(SMUX_REMOTE_DELAY_TIME_MS);
+ mock_cb_data_reset(&cb_data);
+ do {
+ unsigned long start_j;
+ unsigned transfer_time;
+ unsigned lwakeups_start;
+ unsigned rwakeups_start;
+ unsigned lwakeups_end;
+ unsigned rwakeups_end;
+ unsigned lwakeup_delta;
+ unsigned rwakeup_delta;
+
+ /* open port */
+ ret = msm_smux_open(SMUX_TEST_LCID, &cb_data, smux_mock_cb,
+ get_rx_buffer);
+ 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);
+ UT_ASSERT_INT(cb_data.event_connected, ==, 1);
+ mock_cb_data_reset(&cb_data);
+
+ /* do local wakeup test and send echo packet */
+ msleep(SMUX_REMOTE_INACTIVITY_TIME_MS);
+ smux_get_wakeup_counts(&lwakeups_start, &rwakeups_start);
+ msm_smux_write(SMUX_TEST_LCID, (void *)0x12345678,
+ "Hello", 5);
+ 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);
+ UT_ASSERT_INT(cb_data.event_write_done, ==, 1);
+ mock_cb_data_reset(&cb_data);
+
+ /* verify local initiated wakeup */
+ smux_get_wakeup_counts(&lwakeups_end, &rwakeups_end);
+ if (lwakeups_end > lwakeups_start)
+ i += scnprintf(buf + i, max - i,
+ "\tGood - have Apps-initiated wakeup\n");
+ else
+ i += scnprintf(buf + i, max - i,
+ "\tBad - no Apps-initiated wakeup\n");
+
+ /* verify remote wakeup and echo response */
+ smux_get_wakeup_counts(&lwakeups_start, &rwakeups_start);
+ start_j = jiffies;
+ INIT_COMPLETION(cb_data.cb_completion);
+ if (!cb_data.event_read_done)
+ UT_ASSERT_INT(
+ (int)wait_for_completion_timeout(
+ &cb_data.cb_completion,
+ SMUX_REMOTE_DELAY_TIME_MS * 2),
+ >, 0);
+ transfer_time = (unsigned)jiffies_to_msecs(jiffies - start_j);
+ UT_ASSERT_INT(cb_data.event_read_done, ==, 1);
+ UT_ASSERT_INT_IN_RANGE(transfer_time,
+ SMUX_REMOTE_DELAY_TIME_MS -
+ SMUX_REMOTE_INACTIVITY_TIME_MS,
+ SMUX_REMOTE_DELAY_TIME_MS +
+ SMUX_REMOTE_INACTIVITY_TIME_MS);
+ smux_get_wakeup_counts(&lwakeups_end, &rwakeups_end);
+
+ lwakeup_delta = lwakeups_end - lwakeups_end;
+ rwakeup_delta = rwakeups_end - rwakeups_end;
+ if (rwakeup_delta && lwakeup_delta) {
+ i += scnprintf(buf + i, max - i,
+ "\tBoth local and remote wakeup - re-run test (transfer time %d ms)\n",
+ transfer_time);
+ failed = 1;
+ break;
+ } else if (lwakeup_delta) {
+ i += scnprintf(buf + i, max - i,
+ "\tLocal wakeup only (transfer time %d ms) - FAIL\n",
+ transfer_time);
+ failed = 1;
+ break;
+ } else {
+ i += scnprintf(buf + i, max - i,
+ "\tRemote wakeup verified (transfer time %d ms) - OK\n",
+ transfer_time);
+ }
+ } while (0);
+
+ if (!failed) {
+ i += scnprintf(buf + i, max - i, "\tOK\n");
+ } else {
+ pr_err("%s: Failed\n", __func__);
+ i += scnprintf(buf + i, max - i, "\tFailed\n");
+ i += mock_cb_data_print(&cb_data, buf + i, max - i);
+ }
+
+ mock_cb_data_reset(&cb_data);
+ msm_smux_close(SMUX_TEST_LCID);
+ wait_for_completion_timeout(&cb_data.cb_completion, HZ);
+
+ mock_cb_data_reset(&cb_data);
+ smux_set_loopback_data_reply_delay(0);
+
+ return i;
+}
+
static char debug_buffer[DEBUG_BUFMAX];
static ssize_t debug_read(struct file *file, char __user *buf,
@@ -2148,15 +2348,18 @@
smux_ut_local_get_rx_buff_retry);
debug_create("ut_local_get_rx_buff_retry_auto", 0444, dent,
smux_ut_local_get_rx_buff_retry_auto);
- debug_create("ut_remote_ssr_basic", 0444, dent,
- smux_ut_remote_ssr_basic);
- debug_create("ut_remote_ssr_open", 0444, dent,
- smux_ut_remote_ssr_open);
- debug_create("ut_remote_ssr_rx_buff_retry", 0444, dent,
- smux_ut_remote_ssr_rx_buff_retry);
+ debug_create("ut_ssr_remote_basic", 0444, dent,
+ smux_ut_ssr_remote_basic);
+ debug_create("ut_ssr_remote_open", 0444, dent,
+ smux_ut_ssr_remote_open);
+ debug_create("ut_ssr_remote_rx_buff_retry", 0444, dent,
+ smux_ut_ssr_remote_rx_buff_retry);
debug_create("ut_remote_tx_stop", 0444, dent,
smux_ut_remote_tx_stop);
-
+ debug_create("ut_remote_throughput", 0444, dent,
+ smux_ut_remote_throughput);
+ debug_create("ut_remote_initiated_wakeup", 0444, dent,
+ smux_ut_remote_initiated_wakeup);
return 0;
}
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 678627a..65d0b7f 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -79,7 +79,7 @@
*****************************************************************************/
#define DMA_ADDR_INVALID (~(dma_addr_t)0)
-#define USB_MAX_TIMEOUT 100 /* 100msec timeout */
+#define USB_MAX_TIMEOUT 25 /* 25msec timeout */
#define EP_PRIME_CHECK_DELAY (jiffies + msecs_to_jiffies(1000))
#define MAX_PRIME_CHECK_RETRY 3 /*Wait for 3sec for EP prime failure */
diff --git a/drivers/usb/gadget/f_mbim.c b/drivers/usb/gadget/f_mbim.c
index a1b02be..e48f94c 100644
--- a/drivers/usb/gadget/f_mbim.c
+++ b/drivers/usb/gadget/f_mbim.c
@@ -1497,6 +1497,11 @@
mbim->not_port.notify_req->context = mbim;
mbim->not_port.notify_req->complete = mbim_notify_complete;
+ if (mbim->xport == USB_GADGET_XPORT_BAM2BAM_IPA)
+ mbb_desc.wMaxSegmentSize = cpu_to_le16(0x800);
+ else
+ mbb_desc.wMaxSegmentSize = cpu_to_le16(0xfe0);
+
/* copy descriptors, and track endpoint copies */
f->descriptors = usb_copy_descriptors(mbim_fs_function);
if (!f->descriptors)
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c
index 1288bfd..32d4011 100644
--- a/drivers/usb/gadget/f_rndis.c
+++ b/drivers/usb/gadget/f_rndis.c
@@ -71,7 +71,7 @@
MODULE_PARM_DESC(rndis_multipacket_dl_disable,
"Disable RNDIS Multi-packet support in DownLink");
-static unsigned int rndis_ul_max_pkt_per_xfer = 1;
+static unsigned int rndis_ul_max_pkt_per_xfer = 3;
module_param(rndis_ul_max_pkt_per_xfer, uint, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(rndis_ul_max_pkt_per_xfer,
"Maximum packets per transfer for UL aggregation");
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
index bff7eb1..e662bfc 100644
--- a/drivers/usb/gadget/rndis.c
+++ b/drivers/usb/gadget/rndis.c
@@ -1074,14 +1074,6 @@
struct sk_buff *skb2;
u32 msg_len, data_offset, data_len;
- /* some rndis hosts send extra byte to avoid zlp, ignore it */
- if (skb->len == 1) {
- if (num_pkts > rndis_ul_max_pkt_per_xfer_rcvd)
- rndis_ul_max_pkt_per_xfer_rcvd = num_pkts;
- dev_kfree_skb_any(skb);
- return 0;
- }
-
if (skb->len < sizeof *hdr) {
pr_err("invalid rndis pkt: skblen:%u hdr_len:%u",
skb->len, sizeof *hdr);
@@ -1115,7 +1107,8 @@
skb_pull(skb, data_offset + 8);
- if (msg_len == skb->len) {
+ if (data_len == skb->len ||
+ data_len == (skb->len - 1)) {
skb_trim(skb, data_len);
break;
}
diff --git a/include/linux/topology.h b/include/linux/topology.h
index 92a89f0..c2d9c17 100644
--- a/include/linux/topology.h
+++ b/include/linux/topology.h
@@ -118,7 +118,7 @@
#define SD_MC_INIT (struct sched_domain) { \
.min_interval = 1, \
.max_interval = 4, \
- .busy_factor = 64, \
+ .busy_factor = 1, \
.imbalance_pct = 125, \
.cache_nice_tries = 1, \
.busy_idx = 2, \
diff --git a/sound/soc/codecs/msm8x10-wcd.c b/sound/soc/codecs/msm8x10-wcd.c
index e1a904f..1a11997 100644
--- a/sound/soc/codecs/msm8x10-wcd.c
+++ b/sound/soc/codecs/msm8x10-wcd.c
@@ -1784,9 +1784,7 @@
} else {
snd_soc_update_bits(codec, MSM8X10_WCD_A_CDC_TOP_CLK_CTL,
0x0f, 0x00);
- snd_soc_update_bits(codec, MSM8X10_WCD_A_CDC_CLK_MCLK_CTL,
- 0x01, 0x01);
- snd_soc_update_bits(codec, MSM8X10_WCD_A_CDC_CLK_MCLK_CTL,
+ snd_soc_update_bits(codec, MSM8X10_WCD_A_CDC_CLK_PDM_CTL,
0x03, 0x00);
}
return 0;
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index cc22fd4..bfd496b 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -1551,6 +1551,9 @@
wcd9xxx_report_plug(mbhc, 1, SND_JACK_HEADPHONE);
wcd9xxx_schedule_hs_detect_plug(mbhc,
&mbhc->correct_plug_swch);
+ } else if (plug_type == PLUG_TYPE_HIGH_HPH) {
+ wcd9xxx_schedule_hs_detect_plug(mbhc,
+ &mbhc->correct_plug_swch);
} else {
pr_debug("%s: Valid plug found, determine plug type %d\n",
__func__, plug_type);
@@ -2151,6 +2154,9 @@
wcd9xxx_report_plug(mbhc, 1,
SND_JACK_HEADPHONE);
}
+ } else if (plug_type == PLUG_TYPE_HIGH_HPH) {
+ pr_debug("%s: High HPH detected, continue polling\n",
+ __func__);
} else {
if (plug_type == PLUG_TYPE_GND_MIC_SWAP) {
pt_gnd_mic_swap_cnt++;
@@ -2189,6 +2195,11 @@
}
}
+ if (plug_type == PLUG_TYPE_HIGH_HPH) {
+ pr_debug("%s: polling is done, still HPH, so enabling MIC trigger\n",
+ __func__);
+ wcd9xxx_find_plug_and_report(mbhc, plug_type);
+ }
/* Turn off override */
if (!correction)
wcd9xxx_turn_onoff_override(codec, false);
diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
index 9e3a1f8..6bccdb7 100644
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
@@ -622,10 +622,18 @@
int compressed_set_volume(unsigned volume)
{
int rc = 0;
+ int avg_vol = 0;
if (compressed_audio.prtd && compressed_audio.prtd->audio_client) {
- rc = q6asm_set_lrgain(compressed_audio.prtd->audio_client,
- (volume >> 16) & 0xFFFF,
- volume & 0xFFFF);
+ if (compressed_audio.prtd->channel_mode > 2) {
+ avg_vol = (((volume >> 16) & 0xFFFF) +
+ (volume & 0xFFFF)) / 2;
+ rc = q6asm_set_volume(
+ compressed_audio.prtd->audio_client, avg_vol);
+ } else {
+ rc = q6asm_set_lrgain(
+ compressed_audio.prtd->audio_client,
+ (volume >> 16) & 0xFFFF, volume & 0xFFFF);
+ }
if (rc < 0) {
pr_err("%s: Send Volume command failed rc=%d\n",
__func__, rc);
@@ -793,6 +801,11 @@
prtd->audio_client->perf_mode,
prtd->session_id,
substream->stream);
+ /* the number of channels are required to call volume api
+ accoridngly. So, get channels from hw params */
+ if ((params_channels(params) > 0) &&
+ (params_periods(params) <= runtime->hw.channels_max))
+ prtd->channel_mode = params_channels(params);
ret = compressed_set_volume(0);
if (ret < 0)
diff --git a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c
index e6934f6..9ace410 100644
--- a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c
+++ b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c
@@ -641,7 +641,7 @@
DOLBY_PARAM_PAYLOAD_SIZE * sizeof(uint32_t);
int port_id = dolby_dap_params_states.port_id;
if (port_id == DOLBY_INVALID_PORT_ID) {
- pr_err("%s, port_id not set, returning error", __func__);
+ pr_debug("%s, port_id not set, returning error", __func__);
ucontrol->value.integer.value[0] = 0;
return -EINVAL;
}
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 70db200..d7148f1 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -410,7 +410,8 @@
msm_bedais[i].port_id;
port_id = srs_port_id = msm_bedais[i].port_id;
srs_send_params(srs_port_id, 1, 0);
- if (DOLBY_ADM_COPP_TOPOLOGY_ID == topology)
+ if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
+ (!perf_mode))
if (dolby_dap_init(port_id,
msm_bedais[i].channel) < 0)
pr_err("%s: Err init dolby dap\n",
@@ -453,7 +454,8 @@
(test_bit(fedai_id, &msm_bedais[i].fe_sessions))) {
adm_close(msm_bedais[i].port_id,
test_bit(fedai_id, &msm_bedais[i].perf_mode));
- if (DOLBY_ADM_COPP_TOPOLOGY_ID == topology)
+ if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
+ (!test_bit(fedai_id, &msm_bedais[i].perf_mode)))
dolby_dap_deinit(msm_bedais[i].port_id);
}
}
@@ -544,7 +546,8 @@
perf_mode);
port_id = srs_port_id = msm_bedais[reg].port_id;
srs_send_params(srs_port_id, 1, 0);
- if (DOLBY_ADM_COPP_TOPOLOGY_ID == topology)
+ if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
+ (!perf_mode))
if (dolby_dap_init(port_id, channels) < 0)
pr_err("%s: Err init dolby dap\n",
__func__);
@@ -558,7 +561,8 @@
INVALID_SESSION) {
perf_mode = test_bit(val, &msm_bedais[reg].perf_mode);
adm_close(msm_bedais[reg].port_id, perf_mode);
- if (DOLBY_ADM_COPP_TOPOLOGY_ID == topology)
+ if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
+ (!perf_mode))
dolby_dap_deinit(msm_bedais[reg].port_id);
msm_pcm_routing_build_matrix(val,
fe_dai_map[val][session_type], path_type,
@@ -3451,9 +3455,10 @@
adm_close(bedai->port_id,
test_bit(i, &(bedai->perf_mode)));
srs_port_id = -1;
- clear_bit(i, &(bedai->perf_mode));
- if (DOLBY_ADM_COPP_TOPOLOGY_ID == topology)
+ if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
+ (!test_bit(i, &(bedai->perf_mode))))
dolby_dap_deinit(bedai->port_id);
+ clear_bit(i, &(bedai->perf_mode));
}
}
@@ -3539,7 +3544,8 @@
perf_mode);
port_id = srs_port_id = bedai->port_id;
srs_send_params(srs_port_id, 1, 0);
- if (DOLBY_ADM_COPP_TOPOLOGY_ID == topology)
+ if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
+ (!perf_mode))
if (dolby_dap_init(port_id, channels) < 0)
pr_err("%s: Err init dolby dap\n",
__func__);
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
index 9b3cc8d..f17fe5b 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
@@ -109,10 +109,9 @@
wait_queue_head_t in_wait;
struct mutex lock;
- struct mutex in_lock;
- struct mutex out_lock;
spinlock_t dsp_lock;
+ spinlock_t dsp_ul_lock;
uint32_t mode;
uint32_t rate_type;
@@ -272,7 +271,7 @@
return;
/* Copy up-link packet into out_queue. */
- spin_lock_irqsave(&prtd->dsp_lock, dsp_flags);
+ spin_lock_irqsave(&prtd->dsp_ul_lock, dsp_flags);
/* discarding UL packets till start is received */
if (!list_empty(&prtd->free_out_queue) && prtd->capture_start) {
@@ -325,10 +324,10 @@
pr_debug("ul_pkt: pkt_len =%d, frame.len=%d\n", pkt_len,
buf_node->frame.len);
prtd->pcm_capture_irq_pos += prtd->pcm_capture_count;
- spin_unlock_irqrestore(&prtd->dsp_lock, dsp_flags);
+ spin_unlock_irqrestore(&prtd->dsp_ul_lock, dsp_flags);
snd_pcm_period_elapsed(prtd->capture_substream);
} else {
- spin_unlock_irqrestore(&prtd->dsp_lock, dsp_flags);
+ spin_unlock_irqrestore(&prtd->dsp_ul_lock, dsp_flags);
pr_err("UL data dropped\n");
}
@@ -526,6 +525,7 @@
struct voip_buf_node *buf_node = NULL;
struct snd_pcm_runtime *runtime = substream->runtime;
struct voip_drv_info *prtd = runtime->private_data;
+ unsigned long dsp_flags;
int count = frames_to_bytes(runtime, frames);
pr_debug("%s: count = %d, frames=%d\n", __func__, count, (int)frames);
@@ -535,12 +535,13 @@
prtd->state == VOIP_STOPPED),
1 * HZ);
if (ret > 0) {
- mutex_lock(&prtd->in_lock);
if (count <= VOIP_MAX_VOC_PKT_SIZE) {
+ spin_lock_irqsave(&prtd->dsp_lock, dsp_flags);
buf_node =
list_first_entry(&prtd->free_in_queue,
struct voip_buf_node, list);
list_del(&buf_node->list);
+ spin_unlock_irqrestore(&prtd->dsp_lock, dsp_flags);
if (prtd->mode == MODE_PCM) {
ret = copy_from_user(&buf_node->frame.voc_pkt,
buf, count);
@@ -548,14 +549,15 @@
} else
ret = copy_from_user(&buf_node->frame,
buf, count);
+ spin_lock_irqsave(&prtd->dsp_lock, dsp_flags);
list_add_tail(&buf_node->list, &prtd->in_queue);
+ spin_unlock_irqrestore(&prtd->dsp_lock, dsp_flags);
} else {
pr_err("%s: Write cnt %d is > VOIP_MAX_VOC_PKT_SIZE\n",
__func__, count);
ret = -ENOMEM;
}
- mutex_unlock(&prtd->in_lock);
} else if (ret == 0) {
pr_err("%s: No free DL buffs\n", __func__);
ret = -ETIMEDOUT;
@@ -574,6 +576,7 @@
struct voip_buf_node *buf_node = NULL;
struct snd_pcm_runtime *runtime = substream->runtime;
struct voip_drv_info *prtd = runtime->private_data;
+ unsigned long dsp_flags;
count = frames_to_bytes(runtime, frames);
@@ -585,12 +588,13 @@
1 * HZ);
if (ret > 0) {
- mutex_lock(&prtd->out_lock);
if (count <= VOIP_MAX_VOC_PKT_SIZE) {
+ spin_lock_irqsave(&prtd->dsp_ul_lock, dsp_flags);
buf_node = list_first_entry(&prtd->out_queue,
struct voip_buf_node, list);
list_del(&buf_node->list);
+ spin_unlock_irqrestore(&prtd->dsp_ul_lock, dsp_flags);
if (prtd->mode == MODE_PCM)
ret = copy_to_user(buf,
&buf_node->frame.voc_pkt,
@@ -604,15 +608,17 @@
__func__, ret);
ret = -EFAULT;
}
+ spin_lock_irqsave(&prtd->dsp_ul_lock, dsp_flags);
list_add_tail(&buf_node->list,
&prtd->free_out_queue);
+ spin_unlock_irqrestore(&prtd->dsp_ul_lock, dsp_flags);
+
} else {
pr_err("%s: Read count %d > VOIP_MAX_VOC_PKT_SIZE\n",
__func__, count);
ret = -ENOMEM;
}
- mutex_unlock(&prtd->out_lock);
} else if (ret == 0) {
pr_err("%s: No UL data available\n", __func__);
@@ -646,6 +652,7 @@
struct snd_pcm_substream *p_substream, *c_substream;
struct snd_pcm_runtime *runtime;
struct voip_drv_info *prtd;
+ unsigned long dsp_flags;
if (substream == NULL) {
pr_err("substream is NULL\n");
@@ -684,7 +691,7 @@
goto capt;
}
if (p_dma_buf->area != NULL) {
- mutex_lock(&prtd->in_lock);
+ spin_lock_irqsave(&prtd->dsp_lock, dsp_flags);
list_for_each_safe(ptr, next, &prtd->in_queue) {
buf_node = list_entry(ptr,
struct voip_buf_node, list);
@@ -695,11 +702,11 @@
struct voip_buf_node, list);
list_del(&buf_node->list);
}
+ spin_unlock_irqrestore(&prtd->dsp_lock, dsp_flags);
dma_free_coherent(p_substream->pcm->card->dev,
runtime->hw.buffer_bytes_max, p_dma_buf->area,
p_dma_buf->addr);
p_dma_buf->area = NULL;
- mutex_unlock(&prtd->in_lock);
}
/* release out_queue and free_out_queue */
capt: c_substream = prtd->capture_substream;
@@ -713,7 +720,7 @@
goto done;
}
if (c_dma_buf->area != NULL) {
- mutex_lock(&prtd->out_lock);
+ spin_lock_irqsave(&prtd->dsp_ul_lock, dsp_flags);
list_for_each_safe(ptr, next, &prtd->out_queue) {
buf_node = list_entry(ptr,
struct voip_buf_node, list);
@@ -724,11 +731,11 @@
struct voip_buf_node, list);
list_del(&buf_node->list);
}
+ spin_unlock_irqrestore(&prtd->dsp_ul_lock, dsp_flags);
dma_free_coherent(c_substream->pcm->card->dev,
runtime->hw.buffer_bytes_max, c_dma_buf->area,
c_dma_buf->addr);
c_dma_buf->area = NULL;
- mutex_unlock(&prtd->out_lock);
}
done:
prtd->capture_substream = NULL;
@@ -899,19 +906,15 @@
for (i = 0; i < VOIP_MAX_Q_LEN; i++) {
buf_node = (void *)dma_buf->area + offset;
- mutex_lock(&voip_info.in_lock);
list_add_tail(&buf_node->list,
&voip_info.free_in_queue);
- mutex_unlock(&voip_info.in_lock);
offset = offset + sizeof(struct voip_buf_node);
}
} else {
for (i = 0; i < VOIP_MAX_Q_LEN; i++) {
buf_node = (void *) dma_buf->area + offset;
- mutex_lock(&voip_info.out_lock);
list_add_tail(&buf_node->list,
&voip_info.free_out_queue);
- mutex_unlock(&voip_info.out_lock);
offset = offset + sizeof(struct voip_buf_node);
}
}
@@ -1164,10 +1167,9 @@
memset(&voip_info, 0, sizeof(voip_info));
voip_info.mode = MODE_PCM;
mutex_init(&voip_info.lock);
- mutex_init(&voip_info.in_lock);
- mutex_init(&voip_info.out_lock);
spin_lock_init(&voip_info.dsp_lock);
+ spin_lock_init(&voip_info.dsp_ul_lock);
init_waitqueue_head(&voip_info.out_wait);
init_waitqueue_head(&voip_info.in_wait);
diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c
index ed4e090..5f9d4db 100644
--- a/sound/soc/msm/qdsp6v2/q6adm.c
+++ b/sound/soc/msm/qdsp6v2/q6adm.c
@@ -1187,24 +1187,7 @@
ret = -EINVAL;
goto fail_cmd;
}
- if (perf_mode) {
- for (i = 0; i < num_copps; i++) {
- int tmp;
-
- tmp = afe_get_port_index(port_id[i]);
- if (tmp >= 0 && tmp < AFE_MAX_PORTS) {
- rtac_add_adm_device(port_id[i], atomic_read(
- &this_adm.copp_low_latency_id[tmp]),
- path, session_id);
- pr_debug("%s, copp_id: %d\n", __func__,
- atomic_read(
- &this_adm.copp_low_latency_id[tmp]));
- } else {
- pr_debug("%s: Invalid port index %d",
- __func__, tmp);
- }
- }
- } else {
+ if (!perf_mode) {
for (i = 0; i < num_copps; i++)
send_adm_cal(port_id[i], path);
@@ -1473,8 +1456,8 @@
goto fail_cmd;
}
}
- if (!atomic_read(&this_adm.copp_cnt[index]) &&
- !atomic_read(&this_adm.copp_low_latency_cnt[index])) {
+
+ if (!perf_mode) {
pr_debug("%s: remove adm device from rtac\n", __func__);
rtac_remove_adm_device(port_id);
}
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index f05f772..6615940 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -1948,6 +1948,7 @@
goto fail_cmd;
}
pr_debug("%s: mmap handle 0x%x\n", __func__, this_afe.mmap_handle);
+ kfree(mmap_region_cmd);
return 0;
fail_cmd:
kfree(mmap_region_cmd);
@@ -2013,6 +2014,7 @@
if (ret)
pr_err("%s: AFE memory map cmd failed %d\n",
__func__, ret);
+ kfree(mmap_region_cmd);
return ret;
}
int q6afe_audio_client_buf_free_contiguous(unsigned int dir,