Merge "msm:pm2: Add top CSR programming for 8x25Q"
diff --git a/Documentation/ABI/testing/sysfs-bus-pil b/Documentation/ABI/testing/sysfs-bus-pil
deleted file mode 100644
index 797b2ea..0000000
--- a/Documentation/ABI/testing/sysfs-bus-pil
+++ /dev/null
@@ -1,18 +0,0 @@
-What: /sys/bus/pil/devices/.../name
-Date: March 2012
-Contact: Stephen Boyd <sboyd@codeaurora.org>
-Description:
- Shows the name of the peripheral used in pil_get().
-
-What: /sys/bus/pil/devices/.../state
-Date: March 2012
-Contact: Stephen Boyd <sboyd@codeaurora.org>
-Description:
- Shows the state state of a peripheral. Current states
- supported are:
-
- OFFLINE - peripheral is offline
- ONLINE - peripheral is online
-
- This file supports poll() to detect when a peripheral changes
- state.
diff --git a/Documentation/devicetree/bindings/arm/msm/bam_dmux.txt b/Documentation/devicetree/bindings/arm/msm/bam_dmux.txt
index d82284d..53a67a4 100644
--- a/Documentation/devicetree/bindings/arm/msm/bam_dmux.txt
+++ b/Documentation/devicetree/bindings/arm/msm/bam_dmux.txt
@@ -5,10 +5,14 @@
- reg : the location and size of the BAM hardware
- interrupts : the BAM hardware to apps processor interrupt line
+Optional properties:
+-qcom,satellite-mode: the hardware needs to be configured in satellite mode
+
Example:
qcom,bam_dmux@fc834000 {
compatible = "qcom,bam_dmux";
reg = <0xfc834000 0x7000>;
interrupts = <0 29 1>;
+ qcom,satellite-mode;
};
diff --git a/Documentation/devicetree/bindings/arm/msm/memory-reserve.txt b/Documentation/devicetree/bindings/arm/msm/memory-reserve.txt
index 5f18893..c1b79ae 100644
--- a/Documentation/devicetree/bindings/arm/msm/memory-reserve.txt
+++ b/Documentation/devicetree/bindings/arm/msm/memory-reserve.txt
@@ -41,6 +41,17 @@
The EXPORT_COMPAT is to ensure that memory is only carved out if the
driver is actually enabled, otherwise the memory will not be used.
+If a reservation is needed that isn't associated directly with any one
+driver, the compatible string "qcom,msm-contig-mem" can be used. For
+example:
+
+ qcom,msm-contig-mem {
+ compatible = "qcom,msm-contig-mem";
+ qcom,memory-reservation-type = "EBI1";
+ qcom,memory-reservation-size = <0x280000>; /* 2.5M EBI1 buffer */
+ };
+
+
In order to specify the size and address of the fixed memory which has
previously been removed the memory-fixed binding can be used. This assumes
that the region has been removed by a separate memblock-remove property
diff --git a/Documentation/devicetree/bindings/arm/msm/pm-8x60.txt b/Documentation/devicetree/bindings/arm/msm/pm-8x60.txt
new file mode 100644
index 0000000..b429072
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/pm-8x60.txt
@@ -0,0 +1,28 @@
+* MSM PM-8x60
+
+PM-8x60 is the low power management device for MSM (Snapdragon class) chipsets.
+This device sets up different components to do low power modes and registers with
+the kernel to be notified of idle and suspend states and when called, follows
+through the set of instructions in putting the application cores to the lowest
+power mode possible.
+
+The required properties for PM-8x60 are:
+
+- compatible: "qcom,pm-8x60"
+
+The optional properties are:
+
+- qcom,use-sync-timer: Indicates whether the target uses the synchronized QTimer.
+- qcom,pc-mode: Indicates the type of power collapse used by the target. The
+ valid values for this are:
+ 0 (Power collapse terminates in TZ; integrated L2 cache controller)
+ 1, (Power collapse doesn't terminate in TZ; external L2 cache controller)
+ 2 (Power collapse terminates in TZ; external L2 cache controller)
+
+Example:
+
+qcom,pm-8x60 {
+ compatible = "qcom,pm-8x60";
+ qcom,pc-mode = <0>;
+ qcom,use-sync-timer;
+ };
diff --git a/Documentation/devicetree/bindings/gpio/qpnp-pin.txt b/Documentation/devicetree/bindings/gpio/qpnp-pin.txt
index 31c3bc2..36ac336 100644
--- a/Documentation/devicetree/bindings/gpio/qpnp-pin.txt
+++ b/Documentation/devicetree/bindings/gpio/qpnp-pin.txt
@@ -94,7 +94,7 @@
QPNP_PIN_OUT_STRENGTH_MED = 2, (GPIO)
QPNP_PIN_OUT_STRENGTH_HIGH = 3, (GPIO)
- - qcom,src-select: select a function for the pin. Certain pins
+ - qcom,src-sel: select a function for the pin. Certain pins
can be paired (shorted) with each other. Some gpio pins
can act as alternate functions.
In the context of gpio, this acts as a source select.
diff --git a/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt
index 88fca69..bcea355 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt
@@ -29,6 +29,8 @@
needed
- atmel,need-calibration : specify to indicate whether calibration is
needed during wakeup.
+ - atmel,no-force-update : flag that signifies whether force configuration
+ update is applicable or not
Example:
i2c@f9966000 {
@@ -52,7 +54,8 @@
vcc_i2c-supply = <&pm8941_lvs1>;
atmel,panel-coords = <0 0 479 799>;
atmel,display-coords = <0 0 479 799>;
- atmel,i2c-pull-up = <1>;
+ atmel,i2c-pull-up;
+ atmel,no-force-update;
atmel,dig-reg-support;
atmel,key-codes = <
102 139 0 0 0 0 0 0
diff --git a/Documentation/devicetree/bindings/pil/pil-venus.txt b/Documentation/devicetree/bindings/pil/pil-venus.txt
index 4b87f17..232c2cd 100644
--- a/Documentation/devicetree/bindings/pil/pil-venus.txt
+++ b/Documentation/devicetree/bindings/pil/pil-venus.txt
@@ -12,8 +12,6 @@
"vbif_base" are expected.
- vdd-supply: regulator to supply venus.
- qcom,firmware-name: Base name of the firmware image. Ex. "venus"
-- qcom,firmware-min-paddr: The lowest addr boundary for firmware image in DDR
-- qcom,firmware-max-paddr: The highest addr boundary for firmware image in DDR
Example:
qcom,venus@fdce0000 {
@@ -24,7 +22,4 @@
vdd-supply = <&gdsc_venus>;
qcom,firmware-name = "venus";
- qcom,firmware-min-paddr = <0xF500000>;
- qcom,firmware-max-paddr = <0xFA00000>;
-
};
diff --git a/Documentation/devicetree/bindings/tty/serial/msm_serial.txt b/Documentation/devicetree/bindings/tty/serial/msm_serial.txt
index 3b0426b..e784bfa 100644
--- a/Documentation/devicetree/bindings/tty/serial/msm_serial.txt
+++ b/Documentation/devicetree/bindings/tty/serial/msm_serial.txt
@@ -34,10 +34,15 @@
- reg : offset and length of the register set for the device.
- interrupts : should contain the uart interrupt.
+Optional properties:
+- cell-index: An integer specifying the line number of the UART device that
+ represents this HSL hardware instance.
+
Example:
serial@19c400000 {
compatible = "qcom,msm-lsuart-v14"
reg = <0x19c40000 0x1000">;
interrupts = <195>;
+ cell-index = <0>; // this device will be named ttyHSL0
};
diff --git a/arch/arm/boot/dts/msm8974-cdp.dtsi b/arch/arm/boot/dts/msm8974-cdp.dtsi
index 00f20ad..6004d15 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-cdp.dtsi
@@ -39,7 +39,8 @@
atmel,irq-gpio = <&msmgpio 61 0x00>;
atmel,panel-coords = <0 0 760 1424>;
atmel,display-coords = <0 0 720 1280>;
- atmel,i2c-pull-up = <1>;
+ atmel,i2c-pull-up;
+ atmel,no-force-update;
atmel,cfg_1 {
atmel,family-id = <0x82>;
atmel,variant-id = <0x19>;
@@ -178,21 +179,21 @@
qcom,mode = <0>;
qcom,pull = <0>;
qcom,vin-sel = <2>;
- qcom,select = <0>;
+ qcom,src-sel = <0>;
};
gpio@c300 { /* GPIO 4 */
qcom,mode = <0>;
qcom,pull = <0>;
qcom,vin-sel = <2>;
- qcom,select = <0>;
+ qcom,src-sel = <0>;
};
gpio@c400 { /* GPIO 5 */
qcom,mode = <0>;
qcom,pull = <0>;
qcom,vin-sel = <2>;
- qcom,select = <0>;
+ qcom,src-sel = <0>;
};
gpio@c500 { /* GPIO 6 */
@@ -228,7 +229,7 @@
qcom,pull = <5>;
qcom,vin-sel = <2>;
qcom,out-strength = <3>;
- qcom,src-select = <2>;
+ qcom,src-sel = <2>;
qcom,master-en = <1>;
};
@@ -247,7 +248,7 @@
qcom,pull = <5>; /* QPNP_PIN_PULL_NO */
qcom,vin-sel = <2>; /* QPNP_PIN_VIN2 */
qcom,out-strength = <2>; /* QPNP_PIN_OUT_STRENGTH_MED */
- qcom,src-select = <0>; /* QPNP_PIN_SEL_FUNC_CONSTANT */
+ qcom,src-sel = <0>; /* QPNP_PIN_SEL_FUNC_CONSTANT */
qcom,master-en = <1>;
};
@@ -325,7 +326,7 @@
qcom,mode = <1>; /* DIG_OUT */
qcom,output-type = <0>; /* CMOS */
qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
- qcom,src-select = <0>; /* CONSTANT */
+ qcom,src-sel = <0>; /* CONSTANT */
qcom,master-en = <1>; /* ENABLE MPP */
};
@@ -334,7 +335,7 @@
qcom,mode = <1>; /* DIG_OUT */
qcom,output-type = <0>; /* CMOS */
qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
- qcom,src-select = <0>; /* CONSTANT */
+ qcom,src-sel = <0>; /* CONSTANT */
qcom,master-en = <1>; /* ENABLE MPP */
};
diff --git a/arch/arm/boot/dts/msm8974-fluid.dtsi b/arch/arm/boot/dts/msm8974-fluid.dtsi
index a55e6d4..93f92c7 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-fluid.dtsi
@@ -39,7 +39,8 @@
atmel,irq-gpio = <&msmgpio 61 0x00>;
atmel,panel-coords = <0 0 760 1424>;
atmel,display-coords = <0 0 720 1280>;
- atmel,i2c-pull-up = <1>;
+ atmel,i2c-pull-up;
+ atmel,no-force-update;
atmel,cfg_1 {
atmel,family-id = <0x82>;
atmel,variant-id = <0x19>;
@@ -181,21 +182,21 @@
qcom,mode = <0>;
qcom,pull = <0>;
qcom,vin-sel = <2>;
- qcom,select = <0>;
+ qcom,src-sel = <0>;
};
gpio@c300 { /* GPIO 4 */
qcom,mode = <0>;
qcom,pull = <0>;
qcom,vin-sel = <2>;
- qcom,select = <0>;
+ qcom,src-sel = <0>;
};
gpio@c400 { /* GPIO 5 */
qcom,mode = <0>;
qcom,pull = <0>;
qcom,vin-sel = <2>;
- qcom,select = <0>;
+ qcom,src-sel = <0>;
};
gpio@c500 { /* GPIO 6 */
@@ -231,7 +232,7 @@
qcom,pull = <5>;
qcom,vin-sel = <2>;
qcom,out-strength = <3>;
- qcom,src-select = <2>;
+ qcom,src-sel = <2>;
qcom,master-en = <1>;
};
@@ -250,7 +251,7 @@
qcom,pull = <5>; /* QPNP_PIN_PULL_NO */
qcom,vin-sel = <2>; /* QPNP_PIN_VIN2 */
qcom,out-strength = <2>; /* QPNP_PIN_OUT_STRENGTH_MED */
- qcom,src-select = <0>; /* QPNP_PIN_SEL_FUNC_CONSTANT */
+ qcom,src-sel = <0>; /* QPNP_PIN_SEL_FUNC_CONSTANT */
qcom,master-en = <1>;
};
@@ -328,7 +329,7 @@
qcom,mode = <1>; /* DIG_OUT */
qcom,output-type = <0>; /* CMOS */
qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
- qcom,src-select = <0>; /* CONSTANT */
+ qcom,src-sel = <0>; /* CONSTANT */
qcom,master-en = <1>; /* ENABLE MPP */
};
@@ -337,7 +338,7 @@
qcom,mode = <1>; /* DIG_OUT */
qcom,output-type = <0>; /* CMOS */
qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
- qcom,src-select = <0>; /* CONSTANT */
+ qcom,src-sel = <0>; /* CONSTANT */
qcom,master-en = <1>; /* ENABLE MPP */
};
diff --git a/arch/arm/boot/dts/msm8974-ion.dtsi b/arch/arm/boot/dts/msm8974-ion.dtsi
index 634ac43..01e200a 100644
--- a/arch/arm/boot/dts/msm8974-ion.dtsi
+++ b/arch/arm/boot/dts/msm8974-ion.dtsi
@@ -28,23 +28,6 @@
qcom,memory-reservation-size = <0x7800000>;
};
- qcom,ion-heap@29 { /* FIRMWARE HEAP */
- compatible = "qcom,msm-ion-reserve";
- reg = <29>;
- qcom,heap-align = <0x20000>;
- qcom,heap-adjacent = <8>;
- qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
- qcom,memory-reservation-size = <0xA00000>;
- };
-
- qcom,ion-heap@12 { /* MFC HEAP */
- compatible = "qcom,msm-ion-reserve";
- reg = <12>;
- qcom,heap-align = <0x1000>;
- qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
- qcom,memory-reservation-size = <0x2000>;
- };
-
qcom,ion-heap@23 { /* PIL1 HEAP */
compatible = "qcom,msm-ion-reserve";
reg = <23>;
@@ -52,14 +35,6 @@
qcom,memory-fixed = <0xd200000 0x2800000>;
};
- qcom,ion-heap@24 { /* SF HEAP */
- compatible = "qcom,msm-ion-reserve";
- reg = <24>;
- qcom,heap-align = <0x1000>;
- qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
- qcom,memory-reservation-size = <0x2800000>;
- };
-
qcom,ion-heap@25 { /* IOMMU HEAP */
reg = <25>;
};
@@ -76,7 +51,7 @@
reg = <27>;
qcom,heap-align = <0x1000>;
qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
- qcom,memory-reservation-size = <0x600000>;
+ qcom,memory-reservation-size = <0x780000>;
};
qcom,ion-heap@28 { /* AUDIO HEAP */
diff --git a/arch/arm/boot/dts/msm8974-liquid.dtsi b/arch/arm/boot/dts/msm8974-liquid.dtsi
index 1e3d1b3..002332b 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-liquid.dtsi
@@ -24,6 +24,16 @@
compatible = "ti,bq28400-battery";
reg = <0xb>;
};
+
+ charger@2b {
+ compatible = "summit,smb350-charger";
+ reg = <0x2b>; /* 0x56/0x57 */
+ summit,stat-gpio = <&pm8941_gpios 30 0x00>;
+ summit,chg-en-n-gpio = <&pm8941_gpios 10 0x00>;
+ summit,chg-susp-n-gpio = <&pm8941_gpios 13 0x00>;
+ summit,chg-current-ma = <1600>;
+ summit,term-current-ma = <300>;
+ };
};
gpio_keys {
@@ -78,7 +88,8 @@
atmel,irq-gpio = <&msmgpio 61 0x00>;
atmel,panel-coords = <0 0 1080 1920>;
atmel,display-coords = <0 0 1080 1920>;
- atmel,i2c-pull-up = <1>;
+ atmel,i2c-pull-up;
+ atmel,no-force-update;
atmel,cfg_1 {
atmel,family-id = <0xa2>;
atmel,variant-id = <0x00>;
@@ -182,14 +193,14 @@
qcom,mode = <0>;
qcom,pull = <0>;
qcom,vin-sel = <2>;
- qcom,select = <0>;
+ qcom,src-sel = <0>;
};
gpio@c100 { /* GPIO 2 */
qcom,mode = <0>;
qcom,pull = <0>;
qcom,vin-sel = <2>;
- qcom,select = <0>;
+ qcom,src-sel = <0>;
};
gpio@c200 { /* GPIO 3 */
@@ -202,7 +213,7 @@
qcom,mode = <0>;
qcom,pull = <0>;
qcom,vin-sel = <2>;
- qcom,select = <0>;
+ qcom,src-sel = <0>;
};
gpio@c500 { /* GPIO 6 */
@@ -218,6 +229,14 @@
};
gpio@c900 { /* GPIO 10 */
+ /* SMB350-CHG-EN-N */
+ qcom,mode = <1>; /* DIG_OUT */
+ qcom,output-type = <0>; /* CMOS */
+ qcom,pull = <5>; /* PULL_NO */
+ qcom,vin-sel = <0>; /* VPH */
+ qcom,out-strength = <2>; /* STRENGTH_MED */
+ qcom,src-sel = <0>; /* CONSTANT */
+ qcom,master-en = <1>;
};
gpio@ca00 { /* GPIO 11 */
@@ -227,6 +246,14 @@
};
gpio@cc00 { /* GPIO 13 */
+ /* SMB350-CHG-SUSP-N */
+ qcom,mode = <1>; /* DIG_OUT */
+ qcom,output-type = <0>; /* CMOS */
+ qcom,pull = <5>; /* PULL_NO */
+ qcom,vin-sel = <0>; /* VPH */
+ qcom,out-strength = <2>; /* STRENGTH_MED */
+ qcom,src-sel = <0>; /* CONSTANT */
+ qcom,master-en = <1>;
};
gpio@cd00 { /* GPIO 14 */
@@ -238,7 +265,7 @@
qcom,pull = <5>;
qcom,vin-sel = <2>;
qcom,out-strength = <3>;
- qcom,src-select = <2>;
+ qcom,src-sel = <2>;
qcom,master-en = <1>;
};
@@ -257,7 +284,7 @@
qcom,pull = <5>; /* QPNP_PIN_PULL_NO */
qcom,vin-sel = <2>; /* QPNP_PIN_VIN2 */
qcom,out-strength = <2>; /* QPNP_PIN_OUT_STRENGTH_MED */
- qcom,src-select = <0>; /* QPNP_PIN_SEL_FUNC_CONSTANT */
+ qcom,src-sel = <0>; /* QPNP_PIN_SEL_FUNC_CONSTANT */
qcom,master-en = <1>;
};
@@ -295,6 +322,12 @@
};
gpio@dd00 { /* GPIO 30 */
+ /* SMB350-STAT */
+ qcom,mode = <0>; /* DIG_IN */
+ qcom,pull = <5>; /* PULL_NO */
+ qcom,vin-sel = <2>; /* S3 1.8V */
+ qcom,src-sel = <0>; /* CONSTANT */
+ qcom,master-en = <1>;
};
gpio@de00 { /* GPIO 31 */
@@ -318,7 +351,7 @@
qcom,pull = <5>; /* QPNP_PIN_PULL_NO */
qcom,vin-sel = <2>; /* QPNP_PIN_VIN2 */
qcom,out-strength = <3>; /* QPNP_PIN_OUT_STRENGTH_HIGH */
- qcom,src-select = <3>; /* QPNP_PIN_SEL_FUNC_2 */
+ qcom,src-sel = <3>; /* QPNP_PIN_SEL_FUNC_2 */
qcom,master-en = <1>;
};
};
@@ -333,7 +366,7 @@
qcom,mode = <1>; /* Digital output */
qcom,invert = <0>; /* Output low initially */
qcom,vin-sel = <2>; /* PM8941 S3 = 1.8 V */
- qcom,src-select = <0>; /* Constant */
+ qcom,src-sel = <0>; /* Constant */
qcom,master-en = <1>; /* Enable MPP */
};
@@ -348,7 +381,7 @@
qcom,mode = <1>; /* DIG_OUT */
qcom,output-type = <0>; /* CMOS */
qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
- qcom,src-select = <0>; /* CONSTANT */
+ qcom,src-sel = <0>; /* CONSTANT */
qcom,master-en = <1>; /* ENABLE MPP */
};
@@ -357,7 +390,7 @@
qcom,mode = <1>; /* DIG_OUT */
qcom,output-type = <0>; /* CMOS */
qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
- qcom,src-select = <0>; /* CONSTANT */
+ qcom,src-sel = <0>; /* CONSTANT */
qcom,master-en = <1>; /* ENABLE MPP */
};
@@ -381,7 +414,7 @@
qcom,mode = <1>; /* DIG_OUT */
qcom,output-type = <0>; /* CMOS */
qcom,vin-sel = <2>; /* PM8841_S3A 1.8V */
- qcom,src-select = <0>; /* CONSTANT */
+ qcom,src-sel = <0>; /* CONSTANT */
qcom,master-en = <1>; /* ENABLE MPP */
};
@@ -390,7 +423,7 @@
qcom,mode = <1>; /* DIG_OUT */
qcom,output-type = <0>; /* CMOS */
qcom,vin-sel = <0>; /* PM8841_VPH 3.4V */
- qcom,src-select = <0>; /* CONSTANT */
+ qcom,src-sel = <0>; /* CONSTANT */
qcom,master-en = <1>; /* ENABLE MPP */
};
-};
\ No newline at end of file
+};
diff --git a/arch/arm/boot/dts/msm8974-mtp.dtsi b/arch/arm/boot/dts/msm8974-mtp.dtsi
index f1f4286..f4be0dc 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-mtp.dtsi
@@ -39,7 +39,8 @@
atmel,irq-gpio = <&msmgpio 61 0x00>;
atmel,panel-coords = <0 0 760 1424>;
atmel,display-coords = <0 0 720 1280>;
- atmel,i2c-pull-up = <1>;
+ atmel,i2c-pull-up;
+ atmel,no-force-update;
atmel,cfg_1 {
atmel,family-id = <0x82>;
atmel,variant-id = <0x19>;
@@ -219,21 +220,21 @@
qcom,mode = <0>;
qcom,pull = <0>;
qcom,vin-sel = <2>;
- qcom,select = <0>;
+ qcom,src-sel = <0>;
};
gpio@c300 { /* GPIO 4 */
qcom,mode = <0>;
qcom,pull = <0>;
qcom,vin-sel = <2>;
- qcom,select = <0>;
+ qcom,src-sel = <0>;
};
gpio@c400 { /* GPIO 5 */
qcom,mode = <0>;
qcom,pull = <0>;
qcom,vin-sel = <2>;
- qcom,select = <0>;
+ qcom,src-sel = <0>;
};
gpio@c500 { /* GPIO 6 */
@@ -269,7 +270,7 @@
qcom,pull = <5>;
qcom,vin-sel = <2>;
qcom,out-strength = <3>;
- qcom,src-select = <2>;
+ qcom,src-sel = <2>;
qcom,master-en = <1>;
};
@@ -288,7 +289,7 @@
qcom,pull = <5>; /* QPNP_PIN_PULL_NO */
qcom,vin-sel = <2>; /* QPNP_PIN_VIN2 */
qcom,out-strength = <2>; /* QPNP_PIN_OUT_STRENGTH_MED */
- qcom,src-select = <0>; /* QPNP_PIN_SEL_FUNC_CONSTANT */
+ qcom,src-sel = <0>; /* QPNP_PIN_SEL_FUNC_CONSTANT */
qcom,master-en = <1>;
};
@@ -366,7 +367,7 @@
qcom,mode = <1>; /* DIG_OUT */
qcom,output-type = <0>; /* CMOS */
qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
- qcom,src-select = <0>; /* CONSTANT */
+ qcom,src-sel = <0>; /* CONSTANT */
qcom,master-en = <1>; /* ENABLE MPP */
};
@@ -375,7 +376,7 @@
qcom,mode = <1>; /* DIG_OUT */
qcom,output-type = <0>; /* CMOS */
qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
- qcom,src-select = <0>; /* CONSTANT */
+ qcom,src-sel = <0>; /* CONSTANT */
qcom,master-en = <1>; /* ENABLE MPP */
};
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index dcd6e11..c554a5a 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -1016,8 +1016,6 @@
vdd-supply = <&gdsc_venus>;
qcom,firmware-name = "venus";
- qcom,firmware-min-paddr = <0xF500000>;
- qcom,firmware-max-paddr = <0xFA00000>;
};
qcom,cache_erp {
@@ -1052,6 +1050,12 @@
qcom,memory-reservation-size = <0x100000>; /* 1M EBI1 buffer */
};
+ qcom,msm-contig-mem {
+ compatible = "qcom,msm-contig-mem";
+ qcom,memory-reservation-type = "EBI1";
+ qcom,memory-reservation-size = <0x280000>; /* 2.5M EBI1 buffer */
+ };
+
qcom,qcedev@fd440000 {
compatible = "qcom,qcedev";
reg = <0xfd440000 0x20000>,
diff --git a/arch/arm/boot/dts/msm9625-cdp.dts b/arch/arm/boot/dts/msm9625-cdp.dts
index 89c269e..e48572c 100644
--- a/arch/arm/boot/dts/msm9625-cdp.dts
+++ b/arch/arm/boot/dts/msm9625-cdp.dts
@@ -38,7 +38,7 @@
qcom,invert = <0>; /* Output low */
qcom,out-strength = <1>; /* Low */
qcom,vin-sel = <2>; /* PM8019 L11 - 1.8V */
- qcom,src-select = <0>; /* Constant */
+ qcom,src-sel = <0>; /* Constant */
qcom,master-en = <1>; /* Enable GPIO */
};
diff --git a/arch/arm/boot/dts/msm9625-mtp.dts b/arch/arm/boot/dts/msm9625-mtp.dts
index a5673e5..606a4bc 100644
--- a/arch/arm/boot/dts/msm9625-mtp.dts
+++ b/arch/arm/boot/dts/msm9625-mtp.dts
@@ -38,7 +38,7 @@
qcom,invert = <0>; /* Output low */
qcom,out-strength = <1>; /* Low */
qcom,vin-sel = <2>; /* PM8019 L11 - 1.8V */
- qcom,src-select = <0>; /* Constant */
+ qcom,src-sel = <0>; /* Constant */
qcom,master-en = <1>; /* Enable GPIO */
};
diff --git a/arch/arm/boot/dts/msm9625-pm.dtsi b/arch/arm/boot/dts/msm9625-pm.dtsi
new file mode 100644
index 0000000..86e0cf7
--- /dev/null
+++ b/arch/arm/boot/dts/msm9625-pm.dtsi
@@ -0,0 +1,207 @@
+/* Copyright (c) 2012, 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/ "skeleton.dtsi"
+
+/ {
+ qcom,spm@f9009000 {
+ compatible = "qcom,spm-v2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xf9009000 0x1000>;
+ qcom,core-id = <0>;
+ qcom,saw2-ver-reg = <0xfd0>;
+ qcom,saw2-cfg = <0x101>;
+ qcom,saw2-spm-dly= <0>;
+ qcom,saw2-spm-ctl = <0x1>;
+ qcom,saw2-spm-cmd-wfi = [04 03 04 0f];
+ qcom,saw2-spm-cmd-spc = [34 04 44 14 24 54 03 54 44 14 04 24
+ 3e 0f];
+ qcom,saw2-spm-cmd-pc = [34 04 44 14 24 54 07 54 44 14 04 24
+ 3e 0f];
+ };
+
+ qcom,lpm-resources {
+ compatible = "qcom,lpm-resources";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ qcom,lpm-resources@0 {
+ reg = <0x0>;
+ qcom,name = "vdd-dig";
+ qcom,resource-type = <0>;
+ qcom,type = <0x616F646C>; /* "ldoa" */
+ qcom,id = <0x0A>;
+ qcom,key = <0x6e726f63>; /* "corn" */
+ };
+
+ qcom,lpm-resources@1 {
+ reg = <0x1>;
+ qcom,name = "vdd-mem";
+ qcom,resource-type = <0>;
+ qcom,type = <0x616F646C>; /* "ldoa" */
+ qcom,id = <0x0C>;
+ qcom,key = <0x7675>; /* "uv" */
+ };
+
+ qcom,lpm-resources@2 {
+ reg = <0x2>;
+ qcom,name = "pxo";
+ qcom,resource-type = <0>;
+ qcom,type = <0x306b6c63>; /* "clk0" */
+ qcom,id = <0x00>;
+ qcom,key = <0x62616e45>; /* "Enab" */
+ };
+ };
+
+ qcom,lpm-levels {
+ compatible = "qcom,lpm-levels";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ qcom,lpm-level@0 {
+ reg = <0x0>;
+ qcom,mode = <0>; /* MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT */
+ qcom,xo = <1>; /* ON */
+ qcom,l2 = <3>; /* ACTIVE */
+ qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
+ qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
+ qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
+ qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
+ qcom,latency-us = <100>;
+ qcom,ss-power = <8000>;
+ qcom,energy-overhead = <100000>;
+ qcom,time-overhead = <1>;
+ };
+
+ qcom,lpm-level@1 {
+ reg = <0x1>;
+ qcom,mode = <2>; /* MSM_PM_SLEEP_MODE_STANDALONE_POWER_COLLAPSE */
+ qcom,xo = <1>; /* ON */
+ qcom,l2 = <3>; /* ACTIVE */
+ qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
+ qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
+ qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
+ qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
+ qcom,latency-us = <2000>;
+ qcom,ss-power = <5000>;
+ qcom,energy-overhead = <60100000>;
+ qcom,time-overhead = <3000>;
+ };
+
+ qcom,lpm-level@2 {
+ reg = <0x2>;
+ qcom,mode = <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
+ qcom,xo = <1>; /* ON */
+ qcom,l2 = <1>; /* GDHS */
+ qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
+ qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
+ qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
+ qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
+ qcom,latency-us = <3500>;
+ qcom,ss-power = <5000>;
+ qcom,energy-overhead = <60350000>;
+ qcom,time-overhead = <6300>;
+ };
+
+ qcom,lpm-level@3 {
+ reg = <0x3>;
+ qcom,mode= <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
+ qcom,xo = <0>; /* OFF */
+ qcom,l2 = <0>; /* OFF */
+ qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
+ qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
+ qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
+ qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
+ qcom,latency-us = <6800>;
+ qcom,ss-power = <2000>;
+ qcom,energy-overhead = <71850000>;
+ qcom,time-overhead = <13300>;
+ };
+
+ qcom,lpm-level@4 {
+ reg = <0x4>;
+ qcom,mode= <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
+ qcom,xo = <0>; /* OFF */
+ qcom,l2 = <0>; /* OFF */
+ qcom,vdd-mem-upper-bound = <950000>; /* SVS SOC */
+ qcom,vdd-mem-lower-bound = <675000>; /* RETENTION */
+ qcom,vdd-dig-upper-bound = <3>; /* SVS SOC */
+ qcom,vdd-dig-lower-bound = <1>; /* RETENTION */
+ qcom,latency-us = <9800>;
+ qcom,ss-power = <0>;
+ qcom,energy-overhead = <76350000>;
+ qcom,time-overhead = <28300>;
+ };
+ };
+
+ qcom,pm-boot {
+ compatible = "qcom,pm-boot";
+ qcom,mode = <0>; /* MSM_PM_BOOT_CONFIG_TZ */
+ };
+
+ qcom,mpm@fc4281d0 {
+ compatible = "qcom,mpm-v2";
+ reg = <0xfc4281d0 0x1000>, /* MSM_RPM_MPM_BASE 4K */
+ <0xf9011008 0x4>; /* MSM_APCS_GCC_BASE 4K */
+ reg-names = "vmpm", "ipc";
+ interrupts = <0 171 1>;
+
+ qcom,ipc-bit-offset = <1>;
+
+ qcom,gic-parent = <&intc>;
+ qcom,gic-map = <41 172>, /* usb2_hsic_async_wakeup_irq */
+ <0xff 208>; /* summary_irq_kpss */
+
+ qcom,gpio-parent = <&msmgpio>;
+ qcom,gpio-map = <4 1>,
+ <5 5>,
+ <6 9>,
+ <7 18>,
+ <8 20>,
+ <9 24>,
+ <10 27>,
+ <11 28>,
+ <12 34>,
+ <13 35>,
+ <14 37>,
+ <15 42>,
+ <16 44>,
+ <17 46>,
+ <18 50>,
+ <19 54>,
+ <20 59>,
+ <21 61>,
+ <22 62>,
+ <23 64>,
+ <24 65>,
+ <25 66>,
+ <26 67>,
+ <27 68>,
+ <28 71>,
+ <29 72>,
+ <30 73>,
+ <31 74>,
+ <32 75>,
+ <33 77>,
+ <34 79>,
+ <35 80>,
+ <36 82>,
+ <37 86>;
+ };
+
+ qcom,pm-8x60 {
+ compatible = "qcom,pm-8x60";
+ qcom,pc-mode = <2>; /*MSM_PC_TZ_L2_EXT */
+ qcom,use-sync-timer;
+ };
+};
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index 0ebeb9c..7b01020 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -12,6 +12,7 @@
/include/ "skeleton.dtsi"
/include/ "msm9625-ion.dtsi"
+/include/ "msm9625-pm.dtsi"
/ {
model = "Qualcomm MSM 9625";
@@ -240,6 +241,7 @@
compatible = "qcom,bam_dmux";
reg = <0xfc834000 0x7000>;
interrupts = <0 29 1>;
+ qcom,satellite-mode;
};
qcom,acpuclk@f9010000 {
diff --git a/arch/arm/configs/msm8910_defconfig b/arch/arm/configs/msm8910_defconfig
index 83a499b..7e4e7705 100644
--- a/arch/arm/configs/msm8910_defconfig
+++ b/arch/arm/configs/msm8910_defconfig
@@ -10,8 +10,6 @@
CONFIG_CGROUP_CPUACCT=y
CONFIG_RESOURCE_COUNTERS=y
CONFIG_CGROUP_SCHED=y
-CONFIG_VFP=y
-# CONFIG_FAIR_GROUP_SCHED is not set
CONFIG_RT_GROUP_SCHED=y
CONFIG_NAMESPACES=y
# CONFIG_UTS_NS is not set
@@ -22,14 +20,18 @@
CONFIG_BLK_DEV_INITRD=y
CONFIG_RD_BZIP2=y
CONFIG_RD_LZMA=y
+CONFIG_PANIC_TIMEOUT=5
CONFIG_KALLSYMS_ALL=y
+CONFIG_ASHMEM=y
CONFIG_EMBEDDED=y
CONFIG_PROFILING=y
CONFIG_OPROFILE=m
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
CONFIG_PARTITION_ADVANCED=y
+CONFIG_EFI_PARTITION=y
CONFIG_ARCH_MSM=y
CONFIG_ARCH_MSM8910=y
# CONFIG_MSM_STACKED_MEMORY is not set
@@ -40,6 +42,8 @@
CONFIG_MSM_DIRECT_SCLK_ACCESS=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
+# CONFIG_SMP_ON_UP is not set
CONFIG_ARM_ARCH_TIMER=y
CONFIG_HOTPLUG_CPU=y
CONFIG_PREEMPT=y
@@ -47,17 +51,44 @@
CONFIG_HIGHMEM=y
CONFIG_VMALLOC_RESERVE=0x19000000
CONFIG_USE_OF=y
+CONFIG_VFP=y
+CONFIG_NEON=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_SUSPEND is not set
CONFIG_NET=y
+CONFIG_PACKET=y
CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+CONFIG_IPV6=y
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
CONFIG_NETFILTER=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
-# CONFIG_ANDROID_PMEM is not set
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_CRYPT=y
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=m
CONFIG_INPUT_MISC=y
CONFIG_INPUT_UINPUT=y
CONFIG_INPUT_GPIO=m
@@ -71,6 +102,9 @@
# CONFIG_HWMON is not set
CONFIG_REGULATOR=y
CONFIG_REGULATOR_STUB=y
+CONFIG_FB=y
+CONFIG_FB_VIRTUAL=y
+# CONFIG_MSM_HW3D is not set
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_SOC=y
@@ -89,9 +123,21 @@
CONFIG_MMC_TEST=m
CONFIG_MMC_MSM=y
CONFIG_MMC_MSM_SPS_SUPPORT=y
+CONFIG_STAGING=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_LOGGER=y
+CONFIG_ANDROID_RAM_CONSOLE=y
+CONFIG_ANDROID_TIMED_GPIO=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT4_FS=y
+CONFIG_FUSE_FS=y
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
-# CONFIG_MISC_FILESYSTEMS is not set
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ASCII=y
CONFIG_NLS_ISO8859_1=y
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index 98c1ede..8bf3429 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -239,6 +239,7 @@
CONFIG_MSM_RMNET_BAM=y
CONFIG_SLIP=y
CONFIG_SLIP_COMPRESSED=y
+CONFIG_USB_USBNET=y
CONFIG_SLIP_MODE_SLIP6=y
CONFIG_WCNSS_CORE=y
CONFIG_WCNSS_CORE_PRONTO=y
@@ -275,6 +276,7 @@
CONFIG_QPNP_BMS=y
CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
CONFIG_SENSORS_QPNP_ADC_CURRENT=y
+CONFIG_SENSORS_EPM_ADC=y
CONFIG_THERMAL=y
CONFIG_THERMAL_TSENS8974=y
CONFIG_THERMAL_QPNP=y
@@ -287,6 +289,7 @@
CONFIG_VIDEO_DEV=y
CONFIG_VIDEO_V4L2_SUBDEV_API=y
CONFIG_VIDEOBUF2_MSM_MEM=y
+CONFIG_USB_VIDEO_CLASS=y
CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_MSM_CAMERA_V4L2=y
CONFIG_MT9M114=y
@@ -319,10 +322,12 @@
# CONFIG_BACKLIGHT_GENERIC is not set
CONFIG_SOUND=y
CONFIG_SND=y
+CONFIG_SND_USB_AUDIO=y
CONFIG_SND_SOC=y
CONFIG_SND_SOC_MSM8974=y
CONFIG_USB=y
CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_ACM=y
CONFIG_USB_STORAGE=y
CONFIG_USB_STORAGE_DATAFAB=y
CONFIG_USB_STORAGE_FREECOM=y
@@ -338,7 +343,7 @@
CONFIG_USB_STORAGE_ENE_UB6250=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_DEBUG_FILES=y
-CONFIG_USB_CI13XXX_MSM=y
+CONFIG_USB_DWC3_MSM=y
CONFIG_USB_G_ANDROID=y
CONFIG_MMC=y
CONFIG_MMC_PERF_PROFILING=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 328a4dc..e2524ba 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -240,6 +240,7 @@
CONFIG_MSM_RMNET_BAM=y
CONFIG_SLIP=y
CONFIG_SLIP_COMPRESSED=y
+CONFIG_USB_USBNET=y
CONFIG_SLIP_MODE_SLIP6=y
CONFIG_WCNSS_CORE=y
CONFIG_WCNSS_CORE_PRONTO=y
@@ -272,10 +273,12 @@
CONFIG_GPIO_QPNP_PIN_DEBUG=y
CONFIG_POWER_SUPPLY=y
CONFIG_BATTERY_BQ28400=y
+CONFIG_SMB350_CHARGER=y
CONFIG_QPNP_CHARGER=y
CONFIG_QPNP_BMS=y
CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
CONFIG_SENSORS_QPNP_ADC_CURRENT=y
+CONFIG_SENSORS_EPM_ADC=y
CONFIG_THERMAL=y
CONFIG_THERMAL_TSENS8974=y
CONFIG_THERMAL_QPNP=y
@@ -288,6 +291,7 @@
CONFIG_VIDEO_DEV=y
CONFIG_VIDEO_V4L2_SUBDEV_API=y
CONFIG_VIDEOBUF2_MSM_MEM=y
+CONFIG_USB_VIDEO_CLASS=y
CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_MSM_CAMERA_V4L2=y
CONFIG_MT9M114=y
@@ -320,10 +324,12 @@
# CONFIG_BACKLIGHT_GENERIC is not set
CONFIG_SOUND=y
CONFIG_SND=y
+CONFIG_SND_USB_AUDIO=y
CONFIG_SND_SOC=y
CONFIG_SND_SOC_MSM8974=y
CONFIG_USB=y
CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_ACM=y
CONFIG_USB_STORAGE=y
CONFIG_USB_STORAGE_DATAFAB=y
CONFIG_USB_STORAGE_FREECOM=y
@@ -339,7 +345,7 @@
CONFIG_USB_STORAGE_ENE_UB6250=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_DEBUG_FILES=y
-CONFIG_USB_CI13XXX_MSM=y
+CONFIG_USB_DWC3_MSM=y
CONFIG_USB_G_ANDROID=y
CONFIG_MMC=y
CONFIG_MMC_PERF_PROFILING=y
@@ -398,6 +404,7 @@
CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
# CONFIG_DEBUG_PREEMPT is not set
CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_ATOMIC_SLEEP=y
CONFIG_DEBUG_STACK_USAGE=y
CONFIG_DEBUG_INFO=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 6bd87de..fd642ee 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -384,6 +384,8 @@
select MULTI_IRQ_HANDLER
select GPIO_MSM_V3
select MSM_GPIOMUX
+ select MSM_NATIVE_RESTART
+ select MSM_RESTART_V2
endmenu
choice
diff --git a/arch/arm/mach-msm/avs.h b/arch/arm/mach-msm/avs.h
index a549e9d..e87bded 100644
--- a/arch/arm/mach-msm/avs.h
+++ b/arch/arm/mach-msm/avs.h
@@ -37,7 +37,8 @@
u32 avs_get_avsdscr(void);
u32 avs_get_tscsr(void);
void avs_set_tscsr(u32 to_tscsr);
-void avs_disable(void);
+u32 avs_disable(void);
+void avs_enable(u32 avscsr);
#else
static inline u32 avs_reset_delays(u32 avsdscr)
{ return 0; }
@@ -48,7 +49,9 @@
static inline u32 avs_get_tscsr(void)
{ return 0; }
static inline void avs_set_tscsr(u32 to_tscsr) {}
-static inline void avs_disable(void) {}
+static inline u32 avs_disable(void)
+{return 0; }
+static inline void avs_enable(u32 avscsr) {}
#endif
/*#define AVSDEBUG(x...) pr_info("AVS: " x);*/
@@ -60,9 +63,13 @@
put_cpu(); \
} while (0);
+/* AVSCSR(0x61) to enable CPU, V and L2 AVS module */
+
#define AVS_ENABLE(cpu, x) do { \
- if (get_cpu() == (cpu)) \
+ if (get_cpu() == (cpu)) { \
avs_reset_delays((x)); \
+ avs_enable(0x61); \
+ } \
put_cpu(); \
} while (0);
diff --git a/arch/arm/mach-msm/avs_hw.S b/arch/arm/mach-msm/avs_hw.S
index 1cc3ce0..efb9c47 100644
--- a/arch/arm/mach-msm/avs_hw.S
+++ b/arch/arm/mach-msm/avs_hw.S
@@ -102,23 +102,23 @@
/* Read r0=AVSDSCR */
mrc p15, 7, r0, c15, c0, 6
-
-/* AVSCSR(0x61) to enable CPU, V and L2 AVS module */
- mov r3, #0x61
- mcr p15, 7, r3, c15, c1, 7
-
bx lr
-
+ .global avs_enable
+avs_enable:
+/* Restore the avs_scr register */
+ mcr p15, 7, r0, c15, c1, 7
+ bx lr
.global avs_disable
avs_disable:
+/* Get the AVSCSR value */
+ mrc p15, 7, r0, c15, c1, 7
/* Clear AVSCSR */
- mov r0, #0
-
+ mov r1, #0
/* Write AVSCSR */
- mcr p15, 7, r0, c15, c1, 7
+ mcr p15, 7, r1, c15, c1, 7
bx lr
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index 7ba22f4..c475e2d 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -193,6 +193,7 @@
static struct sps_mem_buffer rx_desc_mem_buf;
static struct sps_register_event tx_register_event;
static struct sps_register_event rx_register_event;
+static bool satellite_mode;
static struct bam_ch_info bam_ch[BAM_DMUX_NUM_CHANNELS];
static int bam_mux_initialized;
@@ -2074,7 +2075,7 @@
a2_props.options = SPS_BAM_OPT_IRQ_WAKEUP;
a2_props.num_pipes = A2_NUM_PIPES;
a2_props.summing_threshold = A2_SUMMING_THRESHOLD;
- if (cpu_is_msm9615())
+ if (cpu_is_msm9615() || satellite_mode)
a2_props.manage = SPS_BAM_MGR_DEVICE_REMOTE;
/* need to free on tear down */
ret = sps_register_bam_device(&a2_props, &h);
@@ -2246,7 +2247,7 @@
a2_props.options = SPS_BAM_OPT_IRQ_WAKEUP;
a2_props.num_pipes = A2_NUM_PIPES;
a2_props.summing_threshold = A2_SUMMING_THRESHOLD;
- if (cpu_is_msm9615())
+ if (cpu_is_msm9615() || satellite_mode)
a2_props.manage = SPS_BAM_MGR_DEVICE_REMOTE;
ret = sps_register_bam_device(&a2_props, &h);
if (ret < 0) {
@@ -2374,10 +2375,14 @@
pr_err("%s: irq field missing\n", __func__);
return -ENODEV;
}
- DBG("%s: base:%p size:%x irq:%d\n", __func__,
+ satellite_mode = of_property_read_bool(pdev->dev.of_node,
+ "qcom,satellite-mode");
+
+ DBG("%s: base:%p size:%x irq:%d satellite:%d\n", __func__,
a2_phys_base,
a2_phys_size,
- a2_bam_irq);
+ a2_bam_irq,
+ satellite_mode);
} else { /* fallback to default init data */
a2_phys_base = (void *)(A2_PHYS_BASE);
a2_phys_size = A2_PHYS_SIZE;
diff --git a/arch/arm/mach-msm/board-8910.c b/arch/arm/mach-msm/board-8910.c
index eaf146b..b79ee0b 100644
--- a/arch/arm/mach-msm/board-8910.c
+++ b/arch/arm/mach-msm/board-8910.c
@@ -31,6 +31,7 @@
#include <mach/board.h>
#include <mach/gpiomux.h>
#include <mach/msm_iomap.h>
+#include <mach/restart.h>
#ifdef CONFIG_ION_MSM
#include <mach/ion.h>
#endif
@@ -45,12 +46,12 @@
CLK_DUMMY("iface_clk", BLSP1_UART_CLK, "f991f000.serial", OFF),
CLK_DUMMY("iface_clk", HSUSB_IFACE_CLK, "f9a55000.usb", OFF),
CLK_DUMMY("core_clk", HSUSB_CORE_CLK, "f9a55000.usb", OFF),
- CLK_DUMMY("iface_clk", NULL, "f9824000.qcom,sdcc", OFF),
- CLK_DUMMY("core_clk", NULL, "f9824000.qcom,sdcc", OFF),
- CLK_DUMMY("bus_clk", NULL, "f9824000.qcom,sdcc", OFF),
- CLK_DUMMY("iface_clk", NULL, "f98a4000.qcom,sdcc", OFF),
- CLK_DUMMY("core_clk", NULL, "f98a4000.qcom,sdcc", OFF),
- CLK_DUMMY("bus_clk", NULL, "f98a4000.qcom,sdcc", OFF),
+ CLK_DUMMY("iface_clk", NULL, "msm_sdcc.1", OFF),
+ CLK_DUMMY("core_clk", NULL, "msm_sdcc.1", OFF),
+ CLK_DUMMY("bus_clk", NULL, "msm_sdcc.1", OFF),
+ CLK_DUMMY("iface_clk", NULL, "msm_sdcc.2", OFF),
+ CLK_DUMMY("core_clk", NULL, "msm_sdcc.2", OFF),
+ CLK_DUMMY("bus_clk", NULL, "msm_sdcc.2", OFF),
};
struct clock_init_data msm_dummy_clock_init_data __initdata = {
@@ -58,14 +59,24 @@
.size = ARRAY_SIZE(msm_clocks_dummy),
};
+static struct of_dev_auxdata msm8910_auxdata_lookup[] __initdata = {
+ OF_DEV_AUXDATA("qcom,msm-sdcc", 0xF9824000, \
+ "msm_sdcc.1", NULL),
+ OF_DEV_AUXDATA("qcom,msm-sdcc", 0xF98A4000, \
+ "msm_sdcc.2", NULL),
+ {}
+};
+
void __init msm8910_init(void)
{
+ struct of_dev_auxdata *adata = msm8910_auxdata_lookup;
+
msm_clock_init(&msm_dummy_clock_init_data);
if (socinfo_init() < 0)
pr_err("%s: socinfo_init() failed\n", __func__);
- of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+ of_platform_populate(NULL, of_default_bus_match_table, adata, NULL);
}
static const char *msm8910_dt_match[] __initconst = {
@@ -80,4 +91,5 @@
.handle_irq = gic_handle_irq,
.timer = &msm_dt_timer,
.dt_compat = msm8910_dt_match,
+ .restart = msm_restart,
MACHINE_END
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 05d2fe1..1aa9c10 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -133,7 +133,7 @@
#endif
#define MSM_PMEM_ADSP_SIZE 0x7800000
-#define MSM_PMEM_AUDIO_SIZE 0x4CF000
+#define MSM_PMEM_AUDIO_SIZE 0x314000
#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
#define MSM_PMEM_SIZE 0x4000000 /* 64 Mbytes */
#else
@@ -762,7 +762,7 @@
.regulator = {
{
.name = "CDC_VDD_CP",
- .min_uV = 1800000,
+ .min_uV = 2200000,
.max_uV = 2200000,
.optimum_uA = WCD9XXX_CDC_VDDA_CP_CUR_MAX,
},
@@ -828,7 +828,7 @@
.regulator = {
{
.name = "CDC_VDD_CP",
- .min_uV = 1800000,
+ .min_uV = 2200000,
.max_uV = 2200000,
.optimum_uA = WCD9XXX_CDC_VDDA_CP_CUR_MAX,
},
@@ -2295,7 +2295,6 @@
static struct platform_device *common_devices[] __initdata = {
&msm_8960_q6_lpass,
- &msm_8960_q6_mss,
&msm_8960_riva,
&msm_pil_tzapps,
&msm_pil_vidc,
@@ -2714,11 +2713,34 @@
#endif
}
+/*Modify the WCD9xxx platform data to support supplies from PM8917 */
+static void __init msm8930_pm8917_wcd9xxx_pdata_fixup(
+ struct wcd9xxx_pdata *cdc_pdata)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(cdc_pdata->regulator); i++) {
+
+ if (cdc_pdata->regulator[i].name != NULL
+ && strncmp(cdc_pdata->regulator[i].name,
+ "CDC_VDD_CP", 10) == 0) {
+ cdc_pdata->regulator[i].min_uV =
+ cdc_pdata->regulator[i].max_uV = 1800000;
+ pr_info("%s: CDC_VDD_CP forced to 1.8 volts for PM8917\n",
+ __func__);
+ return;
+ }
+ }
+}
+
/* Modify platform data values to match requirements for PM8917. */
static void __init msm8930_pm8917_pdata_fixup(void)
{
struct acpuclk_platform_data *pdata;
+ msm8930_pm8917_wcd9xxx_pdata_fixup(&sitar_platform_data);
+ msm8930_pm8917_wcd9xxx_pdata_fixup(&sitar1p1_platform_data);
+
mhl_platform_data.gpio_mhl_power = MHL_POWER_GPIO_PM8917;
gpio_keys_8930_pdata.buttons = keys_8930_pm8917;
@@ -2825,6 +2847,10 @@
else
msm8930_pm8917_gpio_mpp_init();
#endif
+ /* Don't add modem devices on APQ targets */
+ if (socinfo_get_id() != 119 && socinfo_get_id() != 157
+ && socinfo_get_id() != 160)
+ platform_device_register(&msm_8960_q6_mss);
platform_add_devices(cdp_devices, ARRAY_SIZE(cdp_devices));
#ifdef CONFIG_MSM_CAMERA
msm8930_init_cam();
diff --git a/arch/arm/mach-msm/board-8974.c b/arch/arm/mach-msm/board-8974.c
index def9b76..98a82b1 100644
--- a/arch/arm/mach-msm/board-8974.c
+++ b/arch/arm/mach-msm/board-8974.c
@@ -49,17 +49,6 @@
#include "modem_notifier.h"
#include "lpm_resources.h"
-#define MSM_KERNEL_EBI1_MEM_SIZE 0x280000
-
-#ifdef CONFIG_KERNEL_PMEM_EBI_REGION
-static unsigned kernel_ebi1_mem_size = MSM_KERNEL_EBI1_MEM_SIZE;
-static int __init kernel_ebi1_mem_size_setup(char *p)
-{
- kernel_ebi1_mem_size = memparse(p, NULL);
- return 0;
-}
-early_param("kernel_ebi1_mem_size", kernel_ebi1_mem_size_setup);
-#endif
static struct memtype_reserve msm8974_reserve_table[] __initdata = {
[MEMTYPE_SMI] = {
@@ -77,13 +66,6 @@
return MEMTYPE_EBI1;
}
-static void __init reserve_ebi_memory(void)
-{
-#ifdef CONFIG_KERNEL_PMEM_EBI_REGION
- msm8974_reserve_table[MEMTYPE_EBI1].size += kernel_ebi1_mem_size;
-#endif
-}
-
static struct resource smd_resource[] = {
{
.name = "modem_smd_in",
@@ -246,14 +228,8 @@
}
};
-static void __init msm8974_calculate_reserve_sizes(void)
-{
- reserve_ebi_memory();
-}
-
static struct reserve_info msm8974_reserve_info __initdata = {
.memtype_reserve_table = msm8974_reserve_table,
- .calculate_reserve_sizes = msm8974_calculate_reserve_sizes,
.paddr_to_memtype = msm8974_paddr_to_memtype,
};
diff --git a/arch/arm/mach-msm/board-9615-gpiomux.c b/arch/arm/mach-msm/board-9615-gpiomux.c
index 9339638..cef967c 100644
--- a/arch/arm/mach-msm/board-9615-gpiomux.c
+++ b/arch/arm/mach-msm/board-9615-gpiomux.c
@@ -201,6 +201,23 @@
},
};
+static struct gpiomux_setting sd_card_det = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_NONE,
+ .dir = GPIOMUX_IN,
+};
+
+struct msm_gpiomux_config sd_card_det_config[] __initdata = {
+ {
+ .gpio = 80,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &sd_card_det,
+ [GPIOMUX_SUSPENDED] = &sd_card_det,
+ },
+ },
+};
+
#ifdef CONFIG_LTC4088_CHARGER
static struct msm_gpiomux_config
msm9615_ltc4088_charger_config[] __initdata = {
@@ -362,6 +379,8 @@
msm_gpiomux_install(msm9615_ps_hold_config,
ARRAY_SIZE(msm9615_ps_hold_config));
+ msm_gpiomux_install(sd_card_det_config,
+ ARRAY_SIZE(sd_card_det_config));
msm_gpiomux_install(msm9615_sdcc2_configs,
ARRAY_SIZE(msm9615_sdcc2_configs));
#ifdef CONFIG_LTC4088_CHARGER
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index b9da615..2f3ab7f 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -939,6 +939,7 @@
&msm9615_rpm_stat_device,
&msm9615_rpm_master_stat_device,
&msm_tsens_device,
+ &msm9615_pm_8x60,
};
static void __init msm9615_i2c_init(void)
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index 13c4be2..4e14ff3 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -375,7 +375,8 @@
};
/* 8625 PM platform data */
-static struct msm_pm_platform_data msm8625_pm_data[MSM_PM_SLEEP_MODE_NR * 2] = {
+static struct msm_pm_platform_data
+ msm8625_pm_data[MSM_PM_SLEEP_MODE_NR * CONFIG_NR_CPUS] = {
/* CORE0 entries */
[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
.idle_supported = 1,
@@ -433,6 +434,44 @@
.residency = 10,
},
+ /* picked latency & redisdency values from 7x30 */
+ [MSM_PM_MODE(2, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
+ .idle_supported = 1,
+ .suspend_supported = 1,
+ .idle_enabled = 0,
+ .suspend_enabled = 0,
+ .latency = 500,
+ .residency = 6000,
+ },
+
+ [MSM_PM_MODE(2, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
+ .idle_supported = 1,
+ .suspend_supported = 1,
+ .idle_enabled = 1,
+ .suspend_enabled = 1,
+ .latency = 2,
+ .residency = 10,
+ },
+
+ /* picked latency & redisdency values from 7x30 */
+ [MSM_PM_MODE(3, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
+ .idle_supported = 1,
+ .suspend_supported = 1,
+ .idle_enabled = 0,
+ .suspend_enabled = 0,
+ .latency = 500,
+ .residency = 6000,
+ },
+
+ [MSM_PM_MODE(3, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
+ .idle_supported = 1,
+ .suspend_supported = 1,
+ .idle_enabled = 1,
+ .suspend_enabled = 1,
+ .latency = 2,
+ .residency = 10,
+ },
+
};
static struct msm_pm_boot_platform_data msm_pm_8625_boot_pdata __initdata = {
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index fd322e9..023ce86 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -349,7 +349,8 @@
};
/* 8625 PM platform data */
-static struct msm_pm_platform_data msm8625_pm_data[MSM_PM_SLEEP_MODE_NR * 2] = {
+static struct msm_pm_platform_data
+ msm8625_pm_data[MSM_PM_SLEEP_MODE_NR * CONFIG_NR_CPUS] = {
/* CORE0 entries */
[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
.idle_supported = 1,
@@ -407,6 +408,44 @@
.residency = 10,
},
+ /* picked latency & redisdency values from 7x30 */
+ [MSM_PM_MODE(2, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
+ .idle_supported = 1,
+ .suspend_supported = 1,
+ .idle_enabled = 0,
+ .suspend_enabled = 0,
+ .latency = 500,
+ .residency = 6000,
+ },
+
+ [MSM_PM_MODE(2, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
+ .idle_supported = 1,
+ .suspend_supported = 1,
+ .idle_enabled = 1,
+ .suspend_enabled = 1,
+ .latency = 2,
+ .residency = 10,
+ },
+
+ /* picked latency & redisdency values from 7x30 */
+ [MSM_PM_MODE(3, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
+ .idle_supported = 1,
+ .suspend_supported = 1,
+ .idle_enabled = 0,
+ .suspend_enabled = 0,
+ .latency = 500,
+ .residency = 6000,
+ },
+
+ [MSM_PM_MODE(3, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
+ .idle_supported = 1,
+ .suspend_supported = 1,
+ .idle_enabled = 1,
+ .suspend_enabled = 1,
+ .latency = 2,
+ .residency = 10,
+ },
+
};
static struct msm_pm_boot_platform_data msm_pm_8625_boot_pdata __initdata = {
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index d080a379..777e0bf 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -2829,8 +2829,8 @@
.div_src_val = BVAL(10, 8, dsipll0_byte_mm_source_val),
};
static struct clk_freq_tbl pixel_freq = {
- .src_clk = &dsipll0_byte_clk_src,
- .div_src_val = BVAL(10, 8, dsipll0_byte_mm_source_val),
+ .src_clk = &dsipll0_pixel_clk_src,
+ .div_src_val = BVAL(10, 8, dsipll0_pixel_mm_source_val),
};
static struct clk_ops clk_ops_byte;
static struct clk_ops clk_ops_pixel;
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index 5c5b51e..5a9799a 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -607,7 +607,7 @@
},
.c = {
.dbg_name = "smi_2x_axi_clk",
- .ops = &clk_ops_branch,
+ .ops = &clk_ops_smi_2x,
CLK_INIT(smi_2x_axi_clk.c),
},
};
diff --git a/arch/arm/mach-msm/clock-local.c b/arch/arm/mach-msm/clock-local.c
index d2260cb..c43ca46 100644
--- a/arch/arm/mach-msm/clock-local.c
+++ b/arch/arm/mach-msm/clock-local.c
@@ -839,6 +839,14 @@
.set_flags = branch_clk_set_flags,
};
+struct clk_ops clk_ops_smi_2x = {
+ .prepare = branch_clk_enable,
+ .unprepare = branch_clk_disable,
+ .is_enabled = branch_clk_is_enabled,
+ .get_parent = branch_clk_get_parent,
+ .handoff = branch_clk_handoff,
+};
+
struct clk_ops clk_ops_reset = {
.reset = branch_clk_reset,
};
diff --git a/arch/arm/mach-msm/clock-local.h b/arch/arm/mach-msm/clock-local.h
index 1873343..fca6486 100644
--- a/arch/arm/mach-msm/clock-local.h
+++ b/arch/arm/mach-msm/clock-local.h
@@ -153,6 +153,7 @@
};
extern struct clk_ops clk_ops_branch;
+extern struct clk_ops clk_ops_smi_2x;
extern struct clk_ops clk_ops_reset;
int branch_reset(struct branch *b, enum clk_reset_action action);
diff --git a/arch/arm/mach-msm/clock-mdss-8974.c b/arch/arm/mach-msm/clock-mdss-8974.c
index 1603c93..e7a596d 100644
--- a/arch/arm/mach-msm/clock-mdss-8974.c
+++ b/arch/arm/mach-msm/clock-mdss-8974.c
@@ -67,7 +67,6 @@
static int pll_byte_clk_rate;
static int pll_pclk_rate;
static int pll_initialized;
-static int pll_enabled;
static struct clk *mdss_dsi_ahb_clk;
static unsigned long dsi_pll_rate;
@@ -208,15 +207,12 @@
return 0;
}
-static int mdss_dsi_pll_enable(struct clk *c)
+static int __mdss_dsi_pll_enable(struct clk *c)
{
u32 status;
u32 max_reads, timeout_us;
int i;
- if (pll_enabled)
- return 0;
-
if (!pll_initialized) {
if (dsi_pll_rate)
mdss_dsi_pll_byte_set_rate(c, dsi_pll_rate);
@@ -266,12 +262,11 @@
pr_debug("%s: **** PLL Lock success\n", __func__);
clk_disable(mdss_dsi_ahb_clk);
- pll_enabled = 1;
return 0;
}
-static void mdss_dsi_pll_disable(struct clk *c)
+static void __mdss_dsi_pll_disable(void)
{
if (!mdss_dsi_ahb_clk)
pr_err("%s: mdss_dsi_ahb_clk not initialized\n",
@@ -282,7 +277,40 @@
clk_disable(mdss_dsi_ahb_clk);
pr_debug("%s: **** disable pll Initialize\n", __func__);
pll_initialized = 0;
- pll_enabled = 0;
+}
+
+static DEFINE_SPINLOCK(dsipll_lock);
+static int dsipll_refcount;
+
+static void mdss_dsi_pll_disable(struct clk *c)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&dsipll_lock, flags);
+ if (WARN(dsipll_refcount == 0, "DSI PLL clock is unbalanced"))
+ goto out;
+ if (dsipll_refcount == 1)
+ __mdss_dsi_pll_disable();
+ dsipll_refcount--;
+out:
+ spin_unlock_irqrestore(&dsipll_lock, flags);
+}
+
+static int mdss_dsi_pll_enable(struct clk *c)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&dsipll_lock, flags);
+ if (dsipll_refcount == 0) {
+ ret = __mdss_dsi_pll_enable(c);
+ if (ret < 0)
+ goto out;
+ }
+ dsipll_refcount++;
+out:
+ spin_unlock_irqrestore(&dsipll_lock, flags);
+ return ret;
}
void hdmi_pll_disable(void)
diff --git a/arch/arm/mach-msm/clock-rpm.c b/arch/arm/mach-msm/clock-rpm.c
index daf83e2..63e67b3 100644
--- a/arch/arm/mach-msm/clock-rpm.c
+++ b/arch/arm/mach-msm/clock-rpm.c
@@ -12,37 +12,29 @@
*/
#include <linux/err.h>
+#include <linux/mutex.h>
#include <mach/clk-provider.h>
#include "rpm_resources.h"
#include "clock-rpm.h"
-#define __clk_rpmrs_set_rate(r, value, ctx, noirq) \
- ((r)->rpmrs_data->set_rate_fn((r), (value), (ctx), (noirq)))
+#define __clk_rpmrs_set_rate(r, value, ctx) \
+ ((r)->rpmrs_data->set_rate_fn((r), (value), (ctx)))
#define clk_rpmrs_set_rate_sleep(r, value) \
- __clk_rpmrs_set_rate((r), (value), (r)->rpmrs_data->ctx_sleep_id, 0)
-
-#define clk_rpmrs_set_rate_sleep_noirq(r, value) \
- __clk_rpmrs_set_rate((r), (value), (r)->rpmrs_data->ctx_sleep_id, 1)
+ __clk_rpmrs_set_rate((r), (value), (r)->rpmrs_data->ctx_sleep_id)
#define clk_rpmrs_set_rate_active(r, value) \
- __clk_rpmrs_set_rate((r), (value), (r)->rpmrs_data->ctx_active_id, 0)
-
-#define clk_rpmrs_set_rate_active_noirq(r, value) \
- __clk_rpmrs_set_rate((r), (value), (r)->rpmrs_data->ctx_active_id, 1)
+ __clk_rpmrs_set_rate((r), (value), (r)->rpmrs_data->ctx_active_id)
static int clk_rpmrs_set_rate(struct rpm_clk *r, uint32_t value,
- uint32_t context, int noirq)
+ uint32_t context)
{
struct msm_rpm_iv_pair iv = {
.id = r->rpm_clk_id,
.value = value,
};
- if (noirq)
- return msm_rpmrs_set_noirq(context, &iv, 1);
- else
- return msm_rpmrs_set(context, &iv, 1);
+ return msm_rpmrs_set(context, &iv, 1);
}
static int clk_rpmrs_get_rate(struct rpm_clk *r)
@@ -72,7 +64,7 @@
}
static int clk_rpmrs_set_rate_smd(struct rpm_clk *r, uint32_t value,
- uint32_t context, int noirq)
+ uint32_t context)
{
struct msm_rpm_kvp kvp = {
.key = r->rpm_key,
@@ -80,12 +72,8 @@
.length = sizeof(value),
};
- if (noirq)
- return msm_rpm_send_message_noirq(context,
- r->rpm_res_type, r->rpm_clk_id, &kvp, 1);
- else
- return msm_rpm_send_message(context, r->rpm_res_type,
- r->rpm_clk_id, &kvp, 1);
+ return msm_rpm_send_message(context, r->rpm_res_type, r->rpm_clk_id,
+ &kvp, 1);
}
static int clk_rpmrs_handoff_smd(struct rpm_clk *r)
@@ -94,8 +82,7 @@
}
struct clk_rpmrs_data {
- int (*set_rate_fn)(struct rpm_clk *r, uint32_t value,
- uint32_t context, int noirq);
+ int (*set_rate_fn)(struct rpm_clk *r, uint32_t value, uint32_t context);
int (*get_rate_fn)(struct rpm_clk *r);
int (*handoff_fn)(struct rpm_clk *r);
int ctx_active_id;
@@ -117,11 +104,10 @@
.ctx_sleep_id = MSM_RPM_CTX_SLEEP_SET,
};
-static DEFINE_SPINLOCK(rpm_clock_lock);
+static DEFINE_MUTEX(rpm_clock_lock);
-static int rpm_clk_enable(struct clk *clk)
+static int rpm_clk_prepare(struct clk *clk)
{
- unsigned long flags;
struct rpm_clk *r = to_rpm_clk(clk);
uint32_t value;
int rc = 0;
@@ -129,7 +115,7 @@
unsigned long peer_khz = 0, peer_sleep_khz = 0;
struct rpm_clk *peer = r->peer;
- spin_lock_irqsave(&rpm_clock_lock, flags);
+ mutex_lock(&rpm_clock_lock);
this_khz = r->last_set_khz;
/* Don't send requests to the RPM if the rate has not been set. */
@@ -148,7 +134,7 @@
if (r->branch)
value = !!value;
- rc = clk_rpmrs_set_rate_active_noirq(r, value);
+ rc = clk_rpmrs_set_rate_active(r, value);
if (rc)
goto out;
@@ -156,28 +142,27 @@
if (r->branch)
value = !!value;
- rc = clk_rpmrs_set_rate_sleep_noirq(r, value);
+ rc = clk_rpmrs_set_rate_sleep(r, value);
if (rc) {
/* Undo the active set vote and restore it to peer_khz */
value = peer_khz;
- rc = clk_rpmrs_set_rate_active_noirq(r, value);
+ rc = clk_rpmrs_set_rate_active(r, value);
}
out:
if (!rc)
r->enabled = true;
- spin_unlock_irqrestore(&rpm_clock_lock, flags);
+ mutex_unlock(&rpm_clock_lock);
return rc;
}
-static void rpm_clk_disable(struct clk *clk)
+static void rpm_clk_unprepare(struct clk *clk)
{
- unsigned long flags;
struct rpm_clk *r = to_rpm_clk(clk);
- spin_lock_irqsave(&rpm_clock_lock, flags);
+ mutex_lock(&rpm_clock_lock);
if (r->last_set_khz) {
uint32_t value;
@@ -192,30 +177,29 @@
}
value = r->branch ? !!peer_khz : peer_khz;
- rc = clk_rpmrs_set_rate_active_noirq(r, value);
+ rc = clk_rpmrs_set_rate_active(r, value);
if (rc)
goto out;
value = r->branch ? !!peer_sleep_khz : peer_sleep_khz;
- rc = clk_rpmrs_set_rate_sleep_noirq(r, value);
+ rc = clk_rpmrs_set_rate_sleep(r, value);
}
r->enabled = false;
out:
- spin_unlock_irqrestore(&rpm_clock_lock, flags);
+ mutex_unlock(&rpm_clock_lock);
return;
}
static int rpm_clk_set_rate(struct clk *clk, unsigned long rate)
{
- unsigned long flags;
struct rpm_clk *r = to_rpm_clk(clk);
unsigned long this_khz, this_sleep_khz;
int rc = 0;
this_khz = DIV_ROUND_UP(rate, r->factor);
- spin_lock_irqsave(&rpm_clock_lock, flags);
+ mutex_lock(&rpm_clock_lock);
/* Active-only clocks don't care what the rate is during sleep. So,
* they vote for zero. */
@@ -236,12 +220,12 @@
}
value = max(this_khz, peer_khz);
- rc = clk_rpmrs_set_rate_active_noirq(r, value);
+ rc = clk_rpmrs_set_rate_active(r, value);
if (rc)
goto out;
value = max(this_sleep_khz, peer_sleep_khz);
- rc = clk_rpmrs_set_rate_sleep_noirq(r, value);
+ rc = clk_rpmrs_set_rate_sleep(r, value);
}
if (!rc) {
r->last_set_khz = this_khz;
@@ -249,7 +233,7 @@
}
out:
- spin_unlock_irqrestore(&rpm_clock_lock, flags);
+ mutex_unlock(&rpm_clock_lock);
return rc;
}
@@ -319,8 +303,8 @@
}
struct clk_ops clk_ops_rpm = {
- .enable = rpm_clk_enable,
- .disable = rpm_clk_disable,
+ .prepare = rpm_clk_prepare,
+ .unprepare = rpm_clk_unprepare,
.set_rate = rpm_clk_set_rate,
.get_rate = rpm_clk_get_rate,
.is_enabled = rpm_clk_is_enabled,
@@ -330,8 +314,8 @@
};
struct clk_ops clk_ops_rpm_branch = {
- .enable = rpm_clk_enable,
- .disable = rpm_clk_disable,
+ .prepare = rpm_clk_prepare,
+ .unprepare = rpm_clk_unprepare,
.is_local = rpm_clk_is_local,
.handoff = rpm_clk_handoff,
};
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index fbfa036..3b3425f 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -1874,7 +1874,7 @@
},
{
.irq_config_id = SMD_Q6,
- .subsys_name = "q6",
+ .subsys_name = "adsp",
.edge = SMD_APPS_QDSP,
.smd_int.irq_name = "adsp_a11",
@@ -2020,6 +2020,11 @@
.flags = IORESOURCE_MEM,
},
{
+ .start = 0x00900000,
+ .end = 0x00900000 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
.start = GSS_A5_WDOG_EXPIRED,
.end = GSS_A5_WDOG_EXPIRED,
.flags = IORESOURCE_IRQ,
@@ -2396,16 +2401,28 @@
};
static struct msm_rpmstats_platform_data msm_rpm_stat_pdata = {
- .phys_addr_base = 0x0010DD04,
- .phys_size = SZ_256,
+ .version = 1,
};
+
+static struct resource msm_rpm_stat_resource[] = {
+ {
+ .start = 0x0010D204,
+ .end = 0x0010D204 + SZ_8K,
+ .flags = IORESOURCE_MEM,
+ .name = "phys_addr_base"
+ },
+};
+
+
struct platform_device apq8064_rpm_stat_device = {
.name = "msm_rpm_stat",
.id = -1,
- .dev = {
+ .resource = msm_rpm_stat_resource,
+ .num_resources = ARRAY_SIZE(msm_rpm_stat_resource),
+ .dev = {
.platform_data = &msm_rpm_stat_pdata,
- },
+ }
};
static struct resource resources_rpm_master_stats[] = {
diff --git a/arch/arm/mach-msm/devices-8930.c b/arch/arm/mach-msm/devices-8930.c
index 322347b..6e305e0 100644
--- a/arch/arm/mach-msm/devices-8930.c
+++ b/arch/arm/mach-msm/devices-8930.c
@@ -547,16 +547,28 @@
};
static struct msm_rpmstats_platform_data msm_rpm_stat_pdata = {
- .phys_addr_base = 0x0010DD04,
- .phys_size = SZ_256,
+ .version = 1,
};
+static struct resource msm_rpm_stat_resource[] = {
+ {
+ .start = 0x0010D204,
+ .end = 0x0010D204 + SZ_8K,
+ .flags = IORESOURCE_MEM,
+ .name = "phys_addr_base"
+
+ },
+};
+
+
struct platform_device msm8930_rpm_stat_device = {
.name = "msm_rpm_stat",
.id = -1,
- .dev = {
+ .resource = msm_rpm_stat_resource,
+ .num_resources = ARRAY_SIZE(msm_rpm_stat_resource),
+ .dev = {
.platform_data = &msm_rpm_stat_pdata,
- },
+ }
};
static struct resource resources_rpm_master_stats[] = {
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index f8132b4..50040a8 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -1373,6 +1373,11 @@
.flags = IORESOURCE_MEM,
},
{
+ .start = 0x00900000,
+ .end = 0x00900000 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
.start = 0x08B00000,
.end = 0x08B00000 + SZ_256 - 1,
.flags = IORESOURCE_MEM,
@@ -1412,7 +1417,6 @@
.aclk_reg = MSM_CLK_CTL_BASE + 0x2C6C,
.jtag_clk_reg = MSM_CLK_CTL_BASE + 0x2044,
.name = "modem_fw",
- .depends = "q6",
.pas_id = PAS_MODEM_FW,
.bus_port = MSM_BUS_MASTER_MSS_FW_PROC,
},
@@ -1423,7 +1427,6 @@
.aclk_reg = MSM_CLK_CTL_BASE + 0x2040,
.jtag_clk_reg = MSM_CLK_CTL_BASE + 0x2C68,
.name = "modem",
- .depends = "modem_fw",
.pas_id = PAS_MODEM_SW,
.bus_port = MSM_BUS_MASTER_MSS_SW_PROC,
}
@@ -1444,6 +1447,11 @@
.flags = IORESOURCE_MEM,
},
{
+ .start = 0x00900000,
+ .end = 0x00900000 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
.start = RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ,
.end = RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ,
.flags = IORESOURCE_IRQ,
@@ -1464,6 +1472,11 @@
static struct resource msm_pil_dsps_resources[] = {
{
+ .start = 0x00900000,
+ .end = 0x00900000 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
.start = PPSS_WDOG_TIMER_IRQ,
.end = PPSS_WDOG_TIMER_IRQ,
.flags = IORESOURCE_IRQ,
@@ -1557,7 +1570,7 @@
},
{
.irq_config_id = SMD_Q6,
- .subsys_name = "q6",
+ .subsys_name = "adsp",
.edge = SMD_APPS_QDSP,
.smd_int.irq_name = "adsp_a11",
@@ -3760,16 +3773,28 @@
};
static struct msm_rpmstats_platform_data msm_rpm_stat_pdata = {
- .phys_addr_base = 0x0010DD04,
- .phys_size = SZ_256,
+ .version = 1,
};
+static struct resource msm_rpm_stat_resource[] = {
+ {
+ .start = 0x0010D204,
+ .end = 0x0010D204 + SZ_8K,
+ .flags = IORESOURCE_MEM,
+ .name = "phys_addr_base"
+ },
+};
+
+
+
struct platform_device msm8960_rpm_stat_device = {
.name = "msm_rpm_stat",
.id = -1,
- .dev = {
+ .resource = msm_rpm_stat_resource,
+ .num_resources = ARRAY_SIZE(msm_rpm_stat_resource),
+ .dev = {
.platform_data = &msm_rpm_stat_pdata,
- },
+ }
};
static struct resource resources_rpm_master_stats[] = {
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index fe3a4d5..af8687e 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -1361,16 +1361,29 @@
};
static struct msm_rpmstats_platform_data msm_rpm_stat_pdata = {
- .phys_addr_base = 0x0010DD04,
- .phys_size = SZ_256,
+ .version = 1,
};
+
+static struct resource msm_rpm_stat_resource[] = {
+ {
+ .start = 0x0010D204,
+ .end = 0x0010D204 + SZ_8K,
+ .flags = IORESOURCE_MEM,
+ .name = "phys_addr_base"
+ },
+};
+
+
+
struct platform_device msm9615_rpm_stat_device = {
.name = "msm_rpm_stat",
.id = -1,
- .dev = {
+ .resource = msm_rpm_stat_resource,
+ .num_resources = ARRAY_SIZE(msm_rpm_stat_resource),
+ .dev = {
.platform_data = &msm_rpm_stat_pdata,
- },
+ }
};
static struct resource resources_rpm_master_stats[] = {
@@ -1421,6 +1434,19 @@
},
};
+static struct msm_pm_init_data_type msm_pm_data = {
+ .use_sync_timer = false,
+ .pc_mode = MSM_PM_PC_NOTZ_L2_EXT,
+};
+
+struct platform_device msm9615_pm_8x60 = {
+ .name = "pm-8x60",
+ .id = -1,
+ .dev = {
+ .platform_data = &msm_pm_data,
+ },
+};
+
uint32_t __init msm9615_rpm_get_swfi_latency(void)
{
int i;
diff --git a/arch/arm/mach-msm/devices-iommu.c b/arch/arm/mach-msm/devices-iommu.c
index 63c1dbd..091a8e8 100644
--- a/arch/arm/mach-msm/devices-iommu.c
+++ b/arch/arm/mach-msm/devices-iommu.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, 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
@@ -312,11 +312,6 @@
},
};
-static struct platform_device msm_root_iommu_dev = {
- .name = "msm_iommu",
- .id = -1,
-};
-
static struct msm_iommu_dev jpegd_iommu = {
.name = "jpegd",
.ncb = 2,
@@ -395,7 +390,6 @@
.name = "msm_iommu",
.id = 0,
.dev = {
- .parent = &msm_root_iommu_dev.dev,
.platform_data = &jpegd_iommu,
},
.num_resources = ARRAY_SIZE(msm_iommu_jpegd_resources),
@@ -406,7 +400,6 @@
.name = "msm_iommu",
.id = 1,
.dev = {
- .parent = &msm_root_iommu_dev.dev,
.platform_data = &vpe_iommu,
},
.num_resources = ARRAY_SIZE(msm_iommu_vpe_resources),
@@ -417,7 +410,6 @@
.name = "msm_iommu",
.id = 2,
.dev = {
- .parent = &msm_root_iommu_dev.dev,
.platform_data = &mdp0_iommu,
},
.num_resources = ARRAY_SIZE(msm_iommu_mdp0_resources),
@@ -428,7 +420,6 @@
.name = "msm_iommu",
.id = 3,
.dev = {
- .parent = &msm_root_iommu_dev.dev,
.platform_data = &mdp1_iommu,
},
.num_resources = ARRAY_SIZE(msm_iommu_mdp1_resources),
@@ -439,7 +430,6 @@
.name = "msm_iommu",
.id = 4,
.dev = {
- .parent = &msm_root_iommu_dev.dev,
.platform_data = &rot_iommu,
},
.num_resources = ARRAY_SIZE(msm_iommu_rot_resources),
@@ -450,7 +440,6 @@
.name = "msm_iommu",
.id = 5,
.dev = {
- .parent = &msm_root_iommu_dev.dev,
.platform_data = &ijpeg_iommu,
},
.num_resources = ARRAY_SIZE(msm_iommu_ijpeg_resources),
@@ -461,7 +450,6 @@
.name = "msm_iommu",
.id = 6,
.dev = {
- .parent = &msm_root_iommu_dev.dev,
.platform_data = &vfe_iommu,
},
.num_resources = ARRAY_SIZE(msm_iommu_vfe_resources),
@@ -472,7 +460,6 @@
.name = "msm_iommu",
.id = 7,
.dev = {
- .parent = &msm_root_iommu_dev.dev,
.platform_data = &vcodec_a_iommu,
},
.num_resources = ARRAY_SIZE(msm_iommu_vcodec_a_resources),
@@ -483,7 +470,6 @@
.name = "msm_iommu",
.id = 8,
.dev = {
- .parent = &msm_root_iommu_dev.dev,
.platform_data = &vcodec_b_iommu,
},
.num_resources = ARRAY_SIZE(msm_iommu_vcodec_b_resources),
@@ -494,7 +480,6 @@
.name = "msm_iommu",
.id = 9,
.dev = {
- .parent = &msm_root_iommu_dev.dev,
.platform_data = &gfx3d_iommu,
},
.num_resources = ARRAY_SIZE(msm_iommu_gfx3d_resources),
@@ -505,7 +490,6 @@
.name = "msm_iommu",
.id = 10,
.dev = {
- .parent = &msm_root_iommu_dev.dev,
.platform_data = &gfx3d1_iommu,
},
.num_resources = ARRAY_SIZE(msm_iommu_gfx3d1_resources),
@@ -516,7 +500,6 @@
.name = "msm_iommu",
.id = 10,
.dev = {
- .parent = &msm_root_iommu_dev.dev,
.platform_data = &gfx2d0_iommu,
},
.num_resources = ARRAY_SIZE(msm_iommu_gfx2d0_resources),
@@ -527,7 +510,6 @@
.name = "msm_iommu",
.id = 11,
.dev = {
- .parent = &msm_root_iommu_dev.dev,
.platform_data = &gfx2d1_iommu,
},
.num_resources = ARRAY_SIZE(msm_iommu_gfx2d1_resources),
@@ -538,7 +520,6 @@
.name = "msm_iommu",
.id = 11,
.dev = {
- .parent = &msm_root_iommu_dev.dev,
.platform_data = &vcap_iommu,
},
.num_resources = ARRAY_SIZE(msm_iommu_vcap_resources),
@@ -999,12 +980,6 @@
return -ENODEV;
}
- ret = platform_device_register(&msm_root_iommu_dev);
- if (ret != 0) {
- pr_err("Failed to register root IOMMU device!\n");
- goto failure;
- }
-
/* Initialize common devs */
platform_add_devices(msm_iommu_common_devs,
ARRAY_SIZE(msm_iommu_common_devs));
@@ -1051,9 +1026,6 @@
ARRAY_SIZE(msm_iommu_vcap_ctx_devs));
return 0;
-
-failure:
- return ret;
}
static void __exit iommu_exit(void)
@@ -1112,8 +1084,6 @@
for (i = 0; i < ARRAY_SIZE(msm_iommu_jpegd_devs); i++)
platform_device_unregister(msm_iommu_jpegd_devs[i]);
}
-
- platform_device_unregister(&msm_root_iommu_dev);
}
subsys_initcall(iommu_init);
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index b709f50..189a616 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -1667,6 +1667,7 @@
case 0x771:
case 0x77C:
case 0x780:
+ case 0x785: /* Edge-only MSM8125-0 */
case 0x8D0:
cpu = MSM8625;
break;
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index 5554eb8..c6513d9 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -213,6 +213,11 @@
.flags = IORESOURCE_MEM,
},
{
+ .start = 0x00900000,
+ .end = 0x00900000 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
.start = LPASS_Q6SS_WDOG_EXPIRED,
.end = LPASS_Q6SS_WDOG_EXPIRED,
.flags = IORESOURCE_IRQ,
@@ -241,6 +246,11 @@
.flags = IORESOURCE_MEM,
},
{
+ .start = 0x00900000,
+ .end = 0x00900000 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
.start = MARM_WDOG_EXPIRED,
.end = MARM_WDOG_EXPIRED,
.flags = IORESOURCE_IRQ,
@@ -259,9 +269,19 @@
.id = -1,
};
+static struct resource msm_pil_dsps_resources[] = {
+ {
+ .start = 0x00900000,
+ .end = 0x00900000 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
struct platform_device msm_pil_dsps = {
.name = "pil_dsps",
.id = -1,
+ .resource = msm_pil_dsps_resources,
+ .num_resources = ARRAY_SIZE(msm_pil_dsps_resources),
.dev.platform_data = "dsps",
};
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 97adb35..16b4eee 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -109,6 +109,8 @@
extern struct platform_device msm_device_sdc3;
extern struct platform_device msm_device_sdc4;
+extern struct platform_device msm9615_pm_8x60;
+
extern struct platform_device msm8960_pc_cntr;
extern struct platform_device msm8064_pc_cntr;
extern struct platform_device msm8930_pc_cntr;
diff --git a/arch/arm/mach-msm/idle-v7.S b/arch/arm/mach-msm/idle-v7.S
index 1d8f313..ccd0bf7 100644
--- a/arch/arm/mach-msm/idle-v7.S
+++ b/arch/arm/mach-msm/idle-v7.S
@@ -22,7 +22,7 @@
#include "idle.h"
#include "idle-macros.S"
-#ifdef CONFIG_ARCH_MSM_KRAIT
+#ifdef CONFIG_MSM_SCM
#define SCM_SVC_BOOT 0x1
#define SCM_CMD_TERMINATE_PC 0x2
#endif
@@ -127,7 +127,18 @@
cmp r1, #1
bne skip
bl v7_flush_dcache_all
+ ldr r1, =msm_pm_flush_l2_fn
+ ldr r1, [r1]
+ cmp r1, #0
+ blxne r1
+
skip:
+ ldr r1, =msm_pm_disable_l2_fn
+ ldr r1, [r1]
+ cmp r1, #0
+ blxne r1
+ dmb
+
mrc p15, 0, r0, c0, c0, 5 /* MPIDR */
and r0, r0, #15 /* what CPU am I */
@@ -141,7 +152,7 @@
str r2, [r1]
skip_pc_debug1:
-#ifdef CONFIG_ARCH_MSM_KRAIT
+#ifdef CONFIG_MSM_SCM
ldr r0, =SCM_SVC_BOOT
ldr r1, =SCM_CMD_TERMINATE_PC
ldr r2, =msm_pm_flush_l2_flag
@@ -182,6 +193,11 @@
str r2, [r1]
skip_pc_debug2:
+ ldr r1, =msm_pm_enable_l2_fn
+ ldr r1, [r1]
+ cmp r1, #0
+ blxne r1
+ dmb
#ifdef CONFIG_MSM_JTAG
bl msm_jtag_restore_state
@@ -286,11 +302,16 @@
SET_SMP_COHERENCY ON
#endif
-#ifdef CONFIG_MSM_JTAG
+ ldr r1, =msm_pm_enable_l2_fn
+ ldr r1, [r1]
+ cmp r1, #0
stmfd sp!, {lr}
+ blxne r1
+ dmb
+#ifdef CONFIG_MSM_JTAG
bl msm_jtag_restore_state
- ldmfd sp!, {lr}
#endif
+ ldmfd sp!, {lr}
mov r0, #1
bx lr
nop
@@ -377,6 +398,18 @@
msm_pc_debug_counters:
.long 0x0
+ .globl msm_pm_enable_l2_fn
+msm_pm_enable_l2_fn:
+ .long 0x0
+
+ .globl msm_pm_disable_l2_fn
+msm_pm_disable_l2_fn:
+ .long 0x0
+
+ .globl msm_pm_flush_l2_fn
+msm_pm_flush_l2_fn:
+ .long 0x0
+
/*
* Default the l2 flush flag to 1 so that caches are flushed during power
* collapse unless the L2 driver decides to flush them only during L2
diff --git a/arch/arm/mach-msm/idle.h b/arch/arm/mach-msm/idle.h
index 7a939ab..ee3209c 100644
--- a/arch/arm/mach-msm/idle.h
+++ b/arch/arm/mach-msm/idle.h
@@ -33,6 +33,9 @@
int msm_pm_collapse(void);
void msm_pm_collapse_exit(void);
extern void *msm_saved_state;
+extern void (*msm_pm_disable_l2_fn)(void);
+extern void (*msm_pm_enable_l2_fn)(void);
+extern void (*msm_pm_flush_l2_fn)(void);
extern unsigned long msm_saved_state_phys;
#ifdef CONFIG_CPU_V7
diff --git a/arch/arm/mach-msm/include/mach/bam_dmux.h b/arch/arm/mach-msm/include/mach/bam_dmux.h
index f02a882..f11b72c 100644
--- a/arch/arm/mach-msm/include/mach/bam_dmux.h
+++ b/arch/arm/mach-msm/include/mach/bam_dmux.h
@@ -28,6 +28,18 @@
BAM_DMUX_DATA_RMNET_6,
BAM_DMUX_DATA_RMNET_7,
BAM_DMUX_USB_RMNET_0,
+ BAM_DMUX_RESERVED_0, /* 9..11 are reserved*/
+ BAM_DMUX_RESERVED_1,
+ BAM_DMUX_RESERVED_2,
+ BAM_DMUX_DATA_REV_RMNET_0,
+ BAM_DMUX_DATA_REV_RMNET_1,
+ BAM_DMUX_DATA_REV_RMNET_2,
+ BAM_DMUX_DATA_REV_RMNET_3,
+ BAM_DMUX_DATA_REV_RMNET_4,
+ BAM_DMUX_DATA_REV_RMNET_5,
+ BAM_DMUX_DATA_REV_RMNET_6,
+ BAM_DMUX_DATA_REV_RMNET_7,
+ BAM_DMUX_DATA_REV_RMNET_8,
BAM_DMUX_NUM_CHANNELS
};
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index 69ddeb9..5d6ec96 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, 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
@@ -15,11 +15,11 @@
#include <linux/interrupt.h>
#include <linux/clk.h>
+#include <linux/list.h>
#include <linux/regulator/consumer.h>
#include <mach/socinfo.h>
extern pgprot_t pgprot_kernel;
-extern struct platform_device *msm_iommu_root_dev;
extern struct bus_type msm_iommu_sec_bus_type;
/* Domain attributes */
@@ -91,6 +91,8 @@
* @name: Human-readable name of this IOMMU device
* @gdsc: Regulator needed to power this HW block (v2 only)
* @bfb_settings: Optional BFB performance tuning parameters
+ * @dev: Struct device this hardware instance is tied to
+ * @list: List head to link all iommus together
*
* A msm_iommu_drvdata holds the global driver data about a single piece
* of an IOMMU hardware instance.
@@ -106,8 +108,13 @@
struct regulator *gdsc;
struct msm_iommu_bfb_settings *bfb_settings;
int sec_id;
+ struct device *dev;
+ struct list_head list;
};
+void msm_iommu_add_drv(struct msm_iommu_drvdata *drv);
+void msm_iommu_remove_drv(struct msm_iommu_drvdata *drv);
+
/**
* struct msm_iommu_ctx_drvdata - an IOMMU context bank instance
* @num: Hardware context number of this context
diff --git a/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h b/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h
index 2455e93..9b04141 100644
--- a/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h
+++ b/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h
@@ -29,7 +29,8 @@
HDMI_SAMPLE_RATE_88_2KHZ,
HDMI_SAMPLE_RATE_96KHZ,
HDMI_SAMPLE_RATE_176_4KHZ,
- HDMI_SAMPLE_RATE_192KHZ
+ HDMI_SAMPLE_RATE_192KHZ,
+ HDMI_SAMPLE_RATE_MAX
};
int hdmi_audio_enable(bool on , u32 fifo_water_mark);
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8910.h b/arch/arm/mach-msm/include/mach/msm_iomap-8910.h
index e4cd312..08f21b6 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8910.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8910.h
@@ -30,9 +30,12 @@
#define MSM8910_TLMM_PHYS 0xFD510000
#define MSM8910_TLMM_SIZE SZ_16K
-#define MSM8910_IMEM_PHYS 0xFC42B000
+#define MSM8910_IMEM_PHYS 0xFE805000
#define MSM8910_IMEM_SIZE SZ_4K
+#define MSM8910_MPM2_PSHOLD_PHYS 0xFC4AB000
+#define MSM8910_MPM2_PSHOLD_SIZE SZ_4K
+
#ifdef CONFIG_DEBUG_MSM8910_UART
#define MSM_DEBUG_UART_BASE IOMEM(0xFA71E000)
#define MSM_DEBUG_UART_PHYS 0xF991E000
diff --git a/arch/arm/mach-msm/include/mach/msm_tspp.h b/arch/arm/mach-msm/include/mach/msm_tspp.h
index 5395b88..a024a99 100644
--- a/arch/arm/mach-msm/include/mach/msm_tspp.h
+++ b/arch/arm/mach-msm/include/mach/msm_tspp.h
@@ -25,31 +25,34 @@
struct tspp_data_descriptor {
void *virt_base; /* logical address of the actual data */
u32 phys_base; /* physical address of the actual data */
- int size; /* size of buffer in bytes */
+ u32 size; /* size of buffer in bytes */
int id; /* unique identifier */
void *user; /* user-defined data */
};
-typedef void (tspp_notifier)(int channel, void *user);
-typedef void* (tspp_allocator)(int channel, int size,
+typedef void (tspp_notifier)(int channel_id, void *user);
+typedef void* (tspp_allocator)(int channel_id, u32 size,
u32 *phys_base, void *user);
+typedef void (tspp_memfree)(int channel_id, u32 size,
+ void *virt_base, u32 phys_base, void *user);
/* Kernel API functions */
int tspp_open_stream(u32 dev, u32 channel_id,
- struct tspp_select_source *source);
+ struct tspp_select_source *source);
int tspp_close_stream(u32 dev, u32 channel_id);
int tspp_open_channel(u32 dev, u32 channel_id);
int tspp_close_channel(u32 dev, u32 channel_id);
-int tspp_add_filter(u32 dev, u32 channel_id, struct tspp_filter *filter);
+int tspp_add_filter(u32 dev, u32 channel_id, struct tspp_filter *filter);
int tspp_remove_filter(u32 dev, u32 channel_id, struct tspp_filter *filter);
int tspp_set_key(u32 dev, u32 channel_id, struct tspp_key *key);
-int tspp_register_notification(u32 dev, u32 channel, tspp_notifier *notify,
+int tspp_register_notification(u32 dev, u32 channel_id, tspp_notifier *notify,
void *data, u32 timer_ms);
-int tspp_unregister_notification(u32 dev, u32 channel);
-const struct tspp_data_descriptor *tspp_get_buffer(u32 dev, u32 channel);
-int tspp_release_buffer(u32 dev, u32 channel, u32 descriptor_id);
+int tspp_unregister_notification(u32 dev, u32 channel_id);
+const struct tspp_data_descriptor *tspp_get_buffer(u32 dev, u32 channel_id);
+int tspp_release_buffer(u32 dev, u32 channel_id, u32 descriptor_id);
int tspp_allocate_buffers(u32 dev, u32 channel_id, u32 count,
- u32 size, u32 int_freq, tspp_allocator *alloc, void *user);
+ u32 size, u32 int_freq, tspp_allocator *alloc,
+ tspp_memfree *memfree, void *user);
#endif /* _MSM_TSPP_H_ */
diff --git a/arch/arm/mach-msm/include/mach/peripheral-loader.h b/arch/arm/mach-msm/include/mach/peripheral-loader.h
deleted file mode 100644
index 327c82f..0000000
--- a/arch/arm/mach-msm/include/mach/peripheral-loader.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-#ifndef __MACH_PERIPHERAL_LOADER_H
-#define __MACH_PERIPHERAL_LOADER_H
-
-#ifdef CONFIG_MSM_PIL
-extern void *pil_get(const char *name);
-extern void pil_put(void *peripheral_handle);
-extern void pil_force_shutdown(const char *name);
-extern int pil_force_boot(const char *name);
-#else
-static inline void *pil_get(const char *name) { return NULL; }
-static inline void pil_put(void *peripheral_handle) { }
-static inline void pil_force_shutdown(const char *name) { }
-static inline int pil_force_boot(const char *name) { return -ENOSYS; }
-#endif
-
-#endif
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index 6fa7faa..ae908e1 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -542,6 +542,7 @@
static struct map_desc msm8910_io_desc[] __initdata = {
MSM_CHIP_DEVICE(APCS_GCC, MSM8910),
MSM_CHIP_DEVICE(TLMM, MSM8910),
+ MSM_CHIP_DEVICE(MPM2_PSHOLD, MSM8910),
MSM_CHIP_DEVICE(IMEM, MSM8910),
{
.virtual = (unsigned long) MSM_SHARED_RAM_BASE,
diff --git a/arch/arm/mach-msm/ipc_router.c b/arch/arm/mach-msm/ipc_router.c
index 3a632e5..ac33836 100644
--- a/arch/arm/mach-msm/ipc_router.c
+++ b/arch/arm/mach-msm/ipc_router.c
@@ -815,7 +815,6 @@
ctl.cmd = IPC_ROUTER_CTRL_CMD_NEW_SERVER;
- mutex_lock(&server_list_lock);
for (i = 0; i < SRV_HASH_SIZE; i++) {
list_for_each_entry(server, &server_list[i], list) {
ctl.srv.service = server->name.service;
@@ -835,7 +834,6 @@
}
}
}
- mutex_unlock(&server_list_lock);
return 0;
}
@@ -1255,6 +1253,7 @@
* Send list of servers from the local node and from nodes
* outside the mesh network in which this XPRT is part of.
*/
+ mutex_lock(&server_list_lock);
mutex_lock(&routing_table_lock);
for (i = 0; i < RT_HASH_SIZE; i++) {
list_for_each_entry(rt_entry, &routing_table[i], list) {
@@ -1266,11 +1265,13 @@
xprt_info);
if (rc < 0) {
mutex_unlock(&routing_table_lock);
+ mutex_unlock(&server_list_lock);
return rc;
}
}
}
mutex_unlock(&routing_table_lock);
+ mutex_unlock(&server_list_lock);
RR("HELLO message processed\n");
return rc;
}
diff --git a/arch/arm/mach-msm/ipc_router_smd_xprt.c b/arch/arm/mach-msm/ipc_router_smd_xprt.c
index b2e6490..8c0bf4b 100644
--- a/arch/arm/mach-msm/ipc_router_smd_xprt.c
+++ b/arch/arm/mach-msm/ipc_router_smd_xprt.c
@@ -20,7 +20,7 @@
#include <linux/types.h>
#include <mach/msm_smd.h>
-#include <mach/peripheral-loader.h>
+#include <mach/subsystem_restart.h>
#include "ipc_router.h"
#include "smd_private.h"
@@ -210,7 +210,7 @@
rc = smd_close(smd_xprtp->channel);
if (smd_xprtp->pil) {
- pil_put(smd_xprtp->pil);
+ subsystem_put(smd_xprtp->pil);
smd_xprtp->pil = NULL;
}
return rc;
@@ -402,7 +402,7 @@
peripheral = smd_edge_to_subsystem(edge);
if (peripheral) {
- pil = pil_get(peripheral);
+ pil = subsystem_get(peripheral);
if (IS_ERR(pil)) {
pr_err("%s: Failed to load %s\n",
__func__, peripheral);
@@ -460,7 +460,7 @@
pr_err("%s: Channel open failed for %s\n",
__func__, smd_xprt_cfg[id].ch_name);
if (smd_remote_xprt[id].pil) {
- pil_put(smd_remote_xprt[id].pil);
+ subsystem_put(smd_remote_xprt[id].pil);
smd_remote_xprt[id].pil = NULL;
}
destroy_workqueue(smd_remote_xprt[id].smd_xprt_wq);
@@ -481,7 +481,7 @@
peripheral = smd_edge_to_subsystem(SMD_APPS_MODEM);
if (peripheral && !strncmp(peripheral, "modem", 6)) {
- pil = pil_get(peripheral);
+ pil = subsystem_get(peripheral);
if (IS_ERR(pil)) {
pr_err("%s: Failed to load %s\n",
__func__, peripheral);
@@ -495,7 +495,7 @@
void msm_ipc_unload_default_node(void *pil)
{
if (pil)
- pil_put(pil);
+ subsystem_put(pil);
}
EXPORT_SYMBOL(msm_ipc_unload_default_node);
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index 7d7380b..3fe65b8 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -464,3 +464,8 @@
return ret;
}
+
+/* Provide a string that anonymous device tree allocations (those not
+ * directly associated with any driver) can use for their "compatible"
+ * field */
+EXPORT_COMPAT("qcom,msm-contig-mem");
diff --git a/arch/arm/mach-msm/msm_dsps.c b/arch/arm/mach-msm/msm_dsps.c
index 859fc15..0551130 100644
--- a/arch/arm/mach-msm/msm_dsps.c
+++ b/arch/arm/mach-msm/msm_dsps.c
@@ -585,7 +585,7 @@
*
* If the DSPS is running, then we must reset DSPS CPU & HW before
* setting the clocks off.
- * The DSPS reset should be done as part of the pil_put().
+ * The DSPS reset should be done as part of the subsystem_put().
* The DSPS reset should be used for error recovery if the DSPS firmware
* has crashed and re-loading the firmware is required.
*/
diff --git a/arch/arm/mach-msm/peripheral-loader.c b/arch/arm/mach-msm/peripheral-loader.c
index 4ff34bf..65e05a9 100644
--- a/arch/arm/mach-msm/peripheral-loader.c
+++ b/arch/arm/mach-msm/peripheral-loader.c
@@ -12,28 +12,33 @@
#include <linux/module.h>
#include <linux/string.h>
-#include <linux/device.h>
#include <linux/firmware.h>
#include <linux/io.h>
-#include <linux/debugfs.h>
#include <linux/elf.h>
#include <linux/mutex.h>
#include <linux/memblock.h>
#include <linux/slab.h>
-#include <linux/atomic.h>
#include <linux/suspend.h>
#include <linux/rwsem.h>
#include <linux/sysfs.h>
#include <linux/workqueue.h>
#include <linux/jiffies.h>
#include <linux/wakelock.h>
+#include <linux/err.h>
+#include <linux/msm_ion.h>
+#include <linux/list.h>
+#include <linux/list_sort.h>
#include <asm/uaccess.h>
#include <asm/setup.h>
-#include <mach/peripheral-loader.h>
#include "peripheral-loader.h"
+#define pil_err(desc, fmt, ...) \
+ dev_err(desc->dev, "%s: " fmt, desc->name, ##__VA_ARGS__)
+#define pil_info(desc, fmt, ...) \
+ dev_info(desc->dev, "%s: " fmt, desc->name, ##__VA_ARGS__)
+
/**
* proxy_timeout - Override for proxy vote timeouts
* -1: Use driver-specified timeout
@@ -43,146 +48,376 @@
static int proxy_timeout_ms = -1;
module_param(proxy_timeout_ms, int, S_IRUGO | S_IWUSR);
-enum pil_state {
- PIL_OFFLINE,
- PIL_ONLINE,
+/**
+ * struct pil_mdt - Representation of <name>.mdt file in memory
+ * @hdr: ELF32 header
+ * @phdr: ELF32 program headers
+ */
+struct pil_mdt {
+ struct elf32_hdr hdr;
+ struct elf32_phdr phdr[];
};
-static const char *pil_states[] = {
- [PIL_OFFLINE] = "OFFLINE",
- [PIL_ONLINE] = "ONLINE",
+/**
+ * struct pil_seg - memory map representing one segment
+ * @next: points to next seg mentor NULL if last segment
+ * @paddr: start address of segment
+ * @sz: size of segment
+ * @filesz: size of segment on disk
+ * @num: segment number
+ * @relocated: true if segment is relocated, false otherwise
+ *
+ * Loosely based on an elf program header. Contains all necessary information
+ * to load and initialize a segment of the image in memory.
+ */
+struct pil_seg {
+ phys_addr_t paddr;
+ unsigned long sz;
+ unsigned long filesz;
+ int num;
+ struct list_head list;
+ bool relocated;
};
-struct pil_device {
- struct pil_desc *desc;
- int count;
- enum pil_state state;
- struct mutex lock;
- struct device dev;
- struct module *owner;
-#ifdef CONFIG_DEBUG_FS
- struct dentry *dentry;
-#endif
+/**
+ * struct pil_priv - Private state for a pil_desc
+ * @proxy: work item used to run the proxy unvoting routine
+ * @wlock: wakelock to prevent suspend during pil_boot
+ * @wname: name of @wlock
+ * @desc: pointer to pil_desc this is private data for
+ * @seg: list of segments sorted by physical address
+ * @entry_addr: physical address where processor starts booting at
+ * @base_addr: smallest start address among all segments that are relocatable
+ * @region_start: address where relocatable region starts or lowest address
+ * for non-relocatable images
+ * @region_end: address where relocatable region ends or highest address for
+ * non-relocatable images
+ * @region: region allocated for relocatable images
+ *
+ * This struct contains data for a pil_desc that should not be exposed outside
+ * of this file. This structure points to the descriptor and the descriptor
+ * points to this structure so that PIL drivers can't access the private
+ * data of a descriptor but this file can access both.
+ */
+struct pil_priv {
struct delayed_work proxy;
struct wake_lock wlock;
- char wake_name[32];
+ char wname[32];
+ struct pil_desc *desc;
+ struct list_head segs;
+ phys_addr_t entry_addr;
+ phys_addr_t base_addr;
+ phys_addr_t region_start;
+ phys_addr_t region_end;
+ struct ion_handle *region;
};
-#define to_pil_device(d) container_of(d, struct pil_device, dev)
+static struct ion_client *ion;
-static ssize_t name_show(struct device *dev, struct device_attribute *attr,
- char *buf)
+/**
+ * pil_get_entry_addr() - Retrieve the entry address of a peripheral image
+ * @desc: descriptor from pil_desc_init()
+ *
+ * Returns the physical address where the image boots at or 0 if unknown.
+ */
+phys_addr_t pil_get_entry_addr(struct pil_desc *desc)
{
- return snprintf(buf, PAGE_SIZE, "%s\n", to_pil_device(dev)->desc->name);
+ return desc->priv ? desc->priv->entry_addr : 0;
}
-
-static ssize_t state_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- enum pil_state state = to_pil_device(dev)->state;
- return snprintf(buf, PAGE_SIZE, "%s\n", pil_states[state]);
-}
-
-static struct device_attribute pil_attrs[] = {
- __ATTR_RO(name),
- __ATTR_RO(state),
- { },
-};
-
-struct bus_type pil_bus_type = {
- .name = "pil",
- .dev_attrs = pil_attrs,
-};
-
-static int __find_peripheral(struct device *dev, void *data)
-{
- struct pil_device *pdev = to_pil_device(dev);
- return !strncmp(pdev->desc->name, data, INT_MAX);
-}
-
-static struct pil_device *find_peripheral(const char *str)
-{
- struct device *dev;
-
- if (!str)
- return NULL;
-
- dev = bus_find_device(&pil_bus_type, NULL, (void *)str,
- __find_peripheral);
- return dev ? to_pil_device(dev) : NULL;
-}
+EXPORT_SYMBOL(pil_get_entry_addr);
static void pil_proxy_work(struct work_struct *work)
{
- struct pil_device *pil;
+ struct delayed_work *delayed = to_delayed_work(work);
+ struct pil_priv *priv = container_of(delayed, struct pil_priv, proxy);
+ struct pil_desc *desc = priv->desc;
- pil = container_of(work, struct pil_device, proxy.work);
- pil->desc->ops->proxy_unvote(pil->desc);
- wake_unlock(&pil->wlock);
+ desc->ops->proxy_unvote(desc);
+ wake_unlock(&priv->wlock);
+ module_put(desc->owner);
}
-static int pil_proxy_vote(struct pil_device *pil)
+static int pil_proxy_vote(struct pil_desc *desc)
{
int ret = 0;
+ struct pil_priv *priv = desc->priv;
- if (pil->desc->ops->proxy_vote) {
- wake_lock(&pil->wlock);
- ret = pil->desc->ops->proxy_vote(pil->desc);
+ if (desc->ops->proxy_vote) {
+ wake_lock(&priv->wlock);
+ ret = desc->ops->proxy_vote(desc);
if (ret)
- wake_unlock(&pil->wlock);
+ wake_unlock(&priv->wlock);
}
return ret;
}
-static void pil_proxy_unvote(struct pil_device *pil, unsigned long timeout)
+static void pil_proxy_unvote(struct pil_desc *desc, unsigned long timeout)
{
+ struct pil_priv *priv = desc->priv;
+
if (proxy_timeout_ms >= 0)
timeout = proxy_timeout_ms;
- if (timeout && pil->desc->ops->proxy_unvote)
- schedule_delayed_work(&pil->proxy, msecs_to_jiffies(timeout));
+ if (timeout && desc->ops->proxy_unvote) {
+ if (WARN_ON(!try_module_get(desc->owner)))
+ return;
+ schedule_delayed_work(&priv->proxy, msecs_to_jiffies(timeout));
+ }
+}
+
+static bool segment_is_relocatable(const struct elf32_phdr *p)
+{
+ return !!(p->p_flags & BIT(27));
+}
+
+static phys_addr_t pil_reloc(const struct pil_priv *priv, phys_addr_t addr)
+{
+ return addr - priv->base_addr + priv->region_start;
+}
+
+static struct pil_seg *pil_init_seg(const struct pil_desc *desc,
+ const struct elf32_phdr *phdr, int num)
+{
+ bool reloc = segment_is_relocatable(phdr);
+ const struct pil_priv *priv = desc->priv;
+ struct pil_seg *seg;
+
+ if (!reloc && memblock_overlaps_memory(phdr->p_paddr, phdr->p_memsz)) {
+ pil_err(desc, "kernel memory would be overwritten [%#08lx, %#08lx)\n",
+ (unsigned long)phdr->p_paddr,
+ (unsigned long)(phdr->p_paddr + phdr->p_memsz));
+ return ERR_PTR(-EPERM);
+ }
+
+ seg = kmalloc(sizeof(*seg), GFP_KERNEL);
+ if (!seg)
+ return ERR_PTR(-ENOMEM);
+ seg->num = num;
+ seg->paddr = reloc ? pil_reloc(priv, phdr->p_paddr) : phdr->p_paddr;
+ seg->filesz = phdr->p_filesz;
+ seg->sz = phdr->p_memsz;
+ seg->relocated = reloc;
+ INIT_LIST_HEAD(&seg->list);
+
+ return seg;
+}
+
+#define segment_is_hash(flag) (((flag) & (0x7 << 24)) == (0x2 << 24))
+
+static int segment_is_loadable(const struct elf32_phdr *p)
+{
+ return (p->p_type == PT_LOAD) && !segment_is_hash(p->p_flags) &&
+ p->p_memsz;
+}
+
+static void pil_dump_segs(const struct pil_priv *priv)
+{
+ struct pil_seg *seg;
+
+ list_for_each_entry(seg, &priv->segs, list) {
+ pil_info(priv->desc, "%d: %#08zx %#08lx\n", seg->num,
+ seg->paddr, seg->paddr + seg->sz);
+ }
+}
+
+/*
+ * Ensure the entry address lies within the image limits and if the image is
+ * relocatable ensure it lies within a relocatable segment.
+ */
+static int pil_init_entry_addr(struct pil_priv *priv, const struct pil_mdt *mdt)
+{
+ struct pil_seg *seg;
+ phys_addr_t entry = mdt->hdr.e_entry;
+ bool image_relocated = priv->region;
+
+ if (image_relocated)
+ entry = pil_reloc(priv, entry);
+ priv->entry_addr = entry;
+
+ if (priv->desc->flags & PIL_SKIP_ENTRY_CHECK)
+ return 0;
+
+ list_for_each_entry(seg, &priv->segs, list) {
+ if (entry >= seg->paddr && entry < seg->paddr + seg->sz) {
+ if (!image_relocated)
+ return 0;
+ else if (seg->relocated)
+ return 0;
+ }
+ }
+ pil_err(priv->desc, "entry address %08zx not within range\n", entry);
+ pil_dump_segs(priv);
+ return -EADDRNOTAVAIL;
+}
+
+static int pil_alloc_region(struct pil_priv *priv, phys_addr_t min_addr,
+ phys_addr_t max_addr, size_t align)
+{
+ struct ion_handle *region;
+ int ret;
+ unsigned int mask;
+ size_t size = round_up(max_addr - min_addr, align);
+
+ if (!ion) {
+ WARN_ON_ONCE("No ION client, can't support relocation\n");
+ return -ENOMEM;
+ }
+
+ /* Force alignment due to linker scripts not getting it right */
+ if (align > SZ_1M) {
+ mask = ION_HEAP(ION_PIL2_HEAP_ID);
+ align = SZ_4M;
+ } else {
+ mask = ION_HEAP(ION_PIL1_HEAP_ID);
+ align = SZ_1M;
+ }
+
+ region = ion_alloc(ion, size, align, mask, 0);
+ if (IS_ERR(region)) {
+ pil_err(priv->desc, "Failed to allocate relocatable region\n");
+ return PTR_ERR(region);
+ }
+
+ ret = ion_phys(ion, region, (ion_phys_addr_t *)&priv->region_start,
+ &size);
+ if (ret) {
+ ion_free(ion, region);
+ return ret;
+ }
+
+ priv->region = region;
+ priv->region_end = priv->region_start + size;
+ priv->base_addr = min_addr;
+
+ return 0;
+}
+
+static int pil_setup_region(struct pil_priv *priv, const struct pil_mdt *mdt)
+{
+ const struct elf32_phdr *phdr;
+ phys_addr_t min_addr_r, min_addr_n, max_addr_r, max_addr_n, start, end;
+ size_t align = 0;
+ int i, ret = 0;
+ bool relocatable = false;
+
+ min_addr_n = min_addr_r = (phys_addr_t)ULLONG_MAX;
+ max_addr_n = max_addr_r = 0;
+
+ /* Find the image limits */
+ for (i = 0; i < mdt->hdr.e_phnum; i++) {
+ phdr = &mdt->phdr[i];
+ if (!segment_is_loadable(phdr))
+ continue;
+
+ start = phdr->p_paddr;
+ end = start + phdr->p_memsz;
+
+ if (segment_is_relocatable(phdr)) {
+ min_addr_r = min(min_addr_r, start);
+ max_addr_r = max(max_addr_r, end);
+ /*
+ * Lowest relocatable segment dictates alignment of
+ * relocatable region
+ */
+ if (min_addr_r == start)
+ align = phdr->p_align;
+ relocatable = true;
+ } else {
+ min_addr_n = min(min_addr_n, start);
+ max_addr_n = max(max_addr_n, end);
+ }
+
+ }
+
+ if (relocatable) {
+ ret = pil_alloc_region(priv, min_addr_r, max_addr_r, align);
+ } else {
+ priv->region_start = min_addr_n;
+ priv->region_end = max_addr_n;
+ priv->base_addr = min_addr_n;
+ }
+
+ return ret;
+}
+
+static int pil_cmp_seg(void *priv, struct list_head *a, struct list_head *b)
+{
+ struct pil_seg *seg_a = list_entry(a, struct pil_seg, list);
+ struct pil_seg *seg_b = list_entry(b, struct pil_seg, list);
+
+ return seg_a->paddr - seg_b->paddr;
+}
+
+static int pil_init_mmap(struct pil_desc *desc, const struct pil_mdt *mdt)
+{
+ struct pil_priv *priv = desc->priv;
+ const struct elf32_phdr *phdr;
+ struct pil_seg *seg;
+ int i, ret;
+
+ ret = pil_setup_region(priv, mdt);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < mdt->hdr.e_phnum; i++) {
+ phdr = &mdt->phdr[i];
+ if (!segment_is_loadable(phdr))
+ continue;
+
+ seg = pil_init_seg(desc, phdr, i);
+ if (IS_ERR(seg))
+ return PTR_ERR(seg);
+
+ list_add_tail(&seg->list, &priv->segs);
+ }
+ list_sort(NULL, &priv->segs, pil_cmp_seg);
+
+ return pil_init_entry_addr(priv, mdt);
+}
+
+static void pil_release_mmap(struct pil_desc *desc)
+{
+ struct pil_priv *priv = desc->priv;
+ struct pil_seg *p, *tmp;
+
+ if (priv->region)
+ ion_free(ion, priv->region);
+ list_for_each_entry_safe(p, tmp, &priv->segs, list) {
+ list_del(&p->list);
+ kfree(p);
+ }
}
#define IOMAP_SIZE SZ_4M
-static int load_segment(const struct elf32_phdr *phdr, unsigned num,
- struct pil_device *pil)
+static int pil_load_seg(struct pil_desc *desc, struct pil_seg *seg)
{
int ret = 0, count, paddr;
char fw_name[30];
const struct firmware *fw = NULL;
const u8 *data;
+ int num = seg->num;
- if (memblock_overlaps_memory(phdr->p_paddr, phdr->p_memsz)) {
- dev_err(&pil->dev, "%s: kernel memory would be overwritten "
- "[%#08lx, %#08lx)\n", pil->desc->name,
- (unsigned long)phdr->p_paddr,
- (unsigned long)(phdr->p_paddr + phdr->p_memsz));
- return -EPERM;
- }
-
- if (phdr->p_filesz) {
+ if (seg->filesz) {
snprintf(fw_name, ARRAY_SIZE(fw_name), "%s.b%02d",
- pil->desc->name, num);
- ret = request_firmware(&fw, fw_name, &pil->dev);
+ desc->name, num);
+ ret = request_firmware(&fw, fw_name, desc->dev);
if (ret) {
- dev_err(&pil->dev, "%s: Failed to locate blob %s\n",
- pil->desc->name, fw_name);
+ pil_err(desc, "Failed to locate blob %s\n", fw_name);
return ret;
}
- if (fw->size != phdr->p_filesz) {
- dev_err(&pil->dev, "%s: Blob size %u doesn't match "
- "%u\n", pil->desc->name, fw->size,
- phdr->p_filesz);
+ if (fw->size != seg->filesz) {
+ pil_err(desc, "Blob size %u doesn't match %lu\n",
+ fw->size, seg->filesz);
ret = -EPERM;
goto release_fw;
}
}
/* Load the segment into memory */
- count = phdr->p_filesz;
- paddr = phdr->p_paddr;
+ count = seg->filesz;
+ paddr = seg->paddr;
data = fw ? fw->data : NULL;
while (count > 0) {
int size;
@@ -191,8 +426,7 @@
size = min_t(size_t, IOMAP_SIZE, count);
buf = ioremap(paddr, size);
if (!buf) {
- dev_err(&pil->dev, "%s: Failed to map memory\n",
- pil->desc->name);
+ pil_err(desc, "Failed to map memory\n");
ret = -ENOMEM;
goto release_fw;
}
@@ -205,7 +439,7 @@
}
/* Zero out trailing memory */
- count = phdr->p_memsz - phdr->p_filesz;
+ count = seg->sz - seg->filesz;
while (count > 0) {
int size;
u8 __iomem *buf;
@@ -213,8 +447,7 @@
size = min_t(size_t, IOMAP_SIZE, count);
buf = ioremap(paddr, size);
if (!buf) {
- dev_err(&pil->dev, "%s: Failed to map memory\n",
- pil->desc->name);
+ pil_err(desc, "Failed to map memory\n");
ret = -ENOMEM;
goto release_fw;
}
@@ -225,12 +458,10 @@
paddr += size;
}
- if (pil->desc->ops->verify_blob) {
- ret = pil->desc->ops->verify_blob(pil->desc, phdr->p_paddr,
- phdr->p_memsz);
+ if (desc->ops->verify_blob) {
+ ret = desc->ops->verify_blob(desc, seg->paddr, seg->sz);
if (ret)
- dev_err(&pil->dev, "%s: Blob%u failed verification\n",
- pil->desc->name, num);
+ pil_err(desc, "Blob%u failed verification\n", num);
}
release_fw:
@@ -238,423 +469,180 @@
return ret;
}
-#define segment_is_hash(flag) (((flag) & (0x7 << 24)) == (0x2 << 24))
-
-static int segment_is_loadable(const struct elf32_phdr *p)
-{
- return (p->p_type == PT_LOAD) && !segment_is_hash(p->p_flags);
-}
-
-/* Sychronize request_firmware() with suspend */
+/* Synchronize request_firmware() with suspend */
static DECLARE_RWSEM(pil_pm_rwsem);
-static int load_image(struct pil_device *pil)
+/**
+ * pil_boot() - Load a peripheral image into memory and boot it
+ * @desc: descriptor from pil_desc_init()
+ *
+ * Returns 0 on success or -ERROR on failure.
+ */
+int pil_boot(struct pil_desc *desc)
{
- int i, ret;
+ int ret;
char fw_name[30];
- struct elf32_hdr *ehdr;
- const struct elf32_phdr *phdr;
+ const struct pil_mdt *mdt;
+ const struct elf32_hdr *ehdr;
+ struct pil_seg *seg;
const struct firmware *fw;
- unsigned long proxy_timeout = pil->desc->proxy_timeout;
+ unsigned long proxy_timeout = desc->proxy_timeout;
+ struct pil_priv *priv = desc->priv;
+
+ /* Reinitialize for new image */
+ pil_release_mmap(desc);
down_read(&pil_pm_rwsem);
- snprintf(fw_name, sizeof(fw_name), "%s.mdt", pil->desc->name);
- ret = request_firmware(&fw, fw_name, &pil->dev);
+ snprintf(fw_name, sizeof(fw_name), "%s.mdt", desc->name);
+ ret = request_firmware(&fw, fw_name, desc->dev);
if (ret) {
- dev_err(&pil->dev, "%s: Failed to locate %s\n",
- pil->desc->name, fw_name);
+ pil_err(desc, "Failed to locate %s\n", fw_name);
goto out;
}
if (fw->size < sizeof(*ehdr)) {
- dev_err(&pil->dev, "%s: Not big enough to be an elf header\n",
- pil->desc->name);
+ pil_err(desc, "Not big enough to be an elf header\n");
ret = -EIO;
goto release_fw;
}
- ehdr = (struct elf32_hdr *)fw->data;
+ mdt = (const struct pil_mdt *)fw->data;
+ ehdr = &mdt->hdr;
+
if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
- dev_err(&pil->dev, "%s: Not an elf header\n", pil->desc->name);
+ pil_err(desc, "Not an elf header\n");
ret = -EIO;
goto release_fw;
}
if (ehdr->e_phnum == 0) {
- dev_err(&pil->dev, "%s: No loadable segments\n",
- pil->desc->name);
+ pil_err(desc, "No loadable segments\n");
ret = -EIO;
goto release_fw;
}
if (sizeof(struct elf32_phdr) * ehdr->e_phnum +
sizeof(struct elf32_hdr) > fw->size) {
- dev_err(&pil->dev, "%s: Program headers not within mdt\n",
- pil->desc->name);
+ pil_err(desc, "Program headers not within mdt\n");
ret = -EIO;
goto release_fw;
}
- ret = pil->desc->ops->init_image(pil->desc, fw->data, fw->size);
+ ret = pil_init_mmap(desc, mdt);
+ if (ret)
+ goto release_fw;
+
+ if (desc->ops->init_image)
+ ret = desc->ops->init_image(desc, fw->data, fw->size);
if (ret) {
- dev_err(&pil->dev, "%s: Invalid firmware metadata\n",
- pil->desc->name);
+ pil_err(desc, "Invalid firmware metadata\n");
goto release_fw;
}
- phdr = (const struct elf32_phdr *)(fw->data + sizeof(struct elf32_hdr));
- for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
- if (!segment_is_loadable(phdr))
- continue;
+ if (desc->ops->mem_setup)
+ ret = desc->ops->mem_setup(desc, priv->region_start,
+ priv->region_end - priv->region_start);
+ if (ret) {
+ pil_err(desc, "Memory setup error\n");
+ goto release_fw;
+ }
- ret = load_segment(phdr, i, pil);
- if (ret) {
- dev_err(&pil->dev, "%s: Failed to load segment %d\n",
- pil->desc->name, i);
+ list_for_each_entry(seg, &desc->priv->segs, list) {
+ ret = pil_load_seg(desc, seg);
+ if (ret)
goto release_fw;
- }
}
- ret = pil_proxy_vote(pil);
+ ret = pil_proxy_vote(desc);
if (ret) {
- dev_err(&pil->dev, "%s: Failed to proxy vote\n",
- pil->desc->name);
+ pil_err(desc, "Failed to proxy vote\n");
goto release_fw;
}
- ret = pil->desc->ops->auth_and_reset(pil->desc);
+ ret = desc->ops->auth_and_reset(desc);
if (ret) {
- dev_err(&pil->dev, "%s: Failed to bring out of reset\n",
- pil->desc->name);
+ pil_err(desc, "Failed to bring out of reset\n");
proxy_timeout = 0; /* Remove proxy vote immediately on error */
goto err_boot;
}
- dev_info(&pil->dev, "%s: Brought out of reset\n", pil->desc->name);
+ pil_info(desc, "Brought out of reset\n");
err_boot:
- pil_proxy_unvote(pil, proxy_timeout);
+ pil_proxy_unvote(desc, proxy_timeout);
release_fw:
release_firmware(fw);
out:
up_read(&pil_pm_rwsem);
+ if (ret)
+ pil_release_mmap(desc);
return ret;
}
-
-static void pil_set_state(struct pil_device *pil, enum pil_state state)
-{
- if (pil->state != state) {
- pil->state = state;
- sysfs_notify(&pil->dev.kobj, NULL, "state");
- }
-}
+EXPORT_SYMBOL(pil_boot);
/**
- * pil_get() - Load a peripheral into memory and take it out of reset
- * @name: pointer to a string containing the name of the peripheral to load
- *
- * This function returns a pointer if it succeeds. If an error occurs an
- * ERR_PTR is returned.
- *
- * If PIL is not enabled in the kernel, the value %NULL will be returned.
+ * pil_shutdown() - Shutdown a peripheral
+ * @desc: descriptor from pil_desc_init()
*/
-void *pil_get(const char *name)
+void pil_shutdown(struct pil_desc *desc)
{
- int ret;
- struct pil_device *pil;
- struct pil_device *pil_d;
- void *retval;
-
- if (!name)
- return NULL;
-
- pil = retval = find_peripheral(name);
- if (!pil)
- return ERR_PTR(-ENODEV);
- if (!try_module_get(pil->owner)) {
- put_device(&pil->dev);
- return ERR_PTR(-ENODEV);
- }
-
- pil_d = pil_get(pil->desc->depends_on);
- if (IS_ERR(pil_d)) {
- retval = pil_d;
- goto err_depends;
- }
-
- mutex_lock(&pil->lock);
- if (!pil->count) {
- ret = load_image(pil);
- if (ret) {
- retval = ERR_PTR(ret);
- goto err_load;
- }
- }
- pil->count++;
- pil_set_state(pil, PIL_ONLINE);
- mutex_unlock(&pil->lock);
-out:
- return retval;
-err_load:
- mutex_unlock(&pil->lock);
- pil_put(pil_d);
-err_depends:
- put_device(&pil->dev);
- module_put(pil->owner);
- goto out;
-}
-EXPORT_SYMBOL(pil_get);
-
-static void pil_shutdown(struct pil_device *pil)
-{
- pil->desc->ops->shutdown(pil->desc);
- if (proxy_timeout_ms == 0 && pil->desc->ops->proxy_unvote)
- pil->desc->ops->proxy_unvote(pil->desc);
+ struct pil_priv *priv = desc->priv;
+ desc->ops->shutdown(desc);
+ if (proxy_timeout_ms == 0 && desc->ops->proxy_unvote)
+ desc->ops->proxy_unvote(desc);
else
- flush_delayed_work(&pil->proxy);
-
- pil_set_state(pil, PIL_OFFLINE);
+ flush_delayed_work(&priv->proxy);
}
+EXPORT_SYMBOL(pil_shutdown);
/**
- * pil_put() - Inform PIL the peripheral no longer needs to be active
- * @peripheral_handle: pointer from a previous call to pil_get()
+ * pil_desc_init() - Initialize a pil descriptor
+ * @desc: descriptor to intialize
*
- * This doesn't imply that a peripheral is shutdown or in reset since another
- * driver could be using the peripheral.
+ * Initialize a pil descriptor for use by other pil functions. This function
+ * must be called before calling pil_boot() or pil_shutdown().
+ *
+ * Returns 0 for success and -ERROR on failure.
*/
-void pil_put(void *peripheral_handle)
+int pil_desc_init(struct pil_desc *desc)
{
- struct pil_device *pil_d, *pil = peripheral_handle;
-
- if (IS_ERR_OR_NULL(pil))
- return;
-
- mutex_lock(&pil->lock);
- if (WARN(!pil->count, "%s: %s: Reference count mismatch\n",
- pil->desc->name, __func__))
- goto err_out;
- if (!--pil->count)
- pil_shutdown(pil);
- mutex_unlock(&pil->lock);
-
- pil_d = find_peripheral(pil->desc->depends_on);
- module_put(pil->owner);
- if (pil_d) {
- pil_put(pil_d);
- put_device(&pil_d->dev);
- }
- put_device(&pil->dev);
- return;
-err_out:
- mutex_unlock(&pil->lock);
- return;
-}
-EXPORT_SYMBOL(pil_put);
-
-void pil_force_shutdown(const char *name)
-{
- struct pil_device *pil;
-
- pil = find_peripheral(name);
- if (!pil) {
- pr_err("%s: Couldn't find %s\n", __func__, name);
- return;
- }
-
- mutex_lock(&pil->lock);
- if (!WARN(!pil->count, "%s: %s: Reference count mismatch\n",
- pil->desc->name, __func__))
- pil_shutdown(pil);
- mutex_unlock(&pil->lock);
-
- put_device(&pil->dev);
-}
-EXPORT_SYMBOL(pil_force_shutdown);
-
-int pil_force_boot(const char *name)
-{
- int ret = -EINVAL;
- struct pil_device *pil;
-
- pil = find_peripheral(name);
- if (!pil) {
- pr_err("%s: Couldn't find %s\n", __func__, name);
- return -EINVAL;
- }
-
- mutex_lock(&pil->lock);
- if (!WARN(!pil->count, "%s: %s: Reference count mismatch\n",
- pil->desc->name, __func__))
- ret = load_image(pil);
- if (!ret)
- pil_set_state(pil, PIL_ONLINE);
- mutex_unlock(&pil->lock);
- put_device(&pil->dev);
-
- return ret;
-}
-EXPORT_SYMBOL(pil_force_boot);
-
-#ifdef CONFIG_DEBUG_FS
-static int msm_pil_debugfs_open(struct inode *inode, struct file *filp)
-{
- filp->private_data = inode->i_private;
- return 0;
-}
-
-static ssize_t msm_pil_debugfs_read(struct file *filp, char __user *ubuf,
- size_t cnt, loff_t *ppos)
-{
- int r;
- char buf[40];
- struct pil_device *pil = filp->private_data;
-
- mutex_lock(&pil->lock);
- r = snprintf(buf, sizeof(buf), "%d\n", pil->count);
- mutex_unlock(&pil->lock);
- return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
-}
-
-static ssize_t msm_pil_debugfs_write(struct file *filp,
- const char __user *ubuf, size_t cnt, loff_t *ppos)
-{
- struct pil_device *pil = filp->private_data;
- char buf[4];
-
- if (cnt > sizeof(buf))
- return -EINVAL;
-
- if (copy_from_user(&buf, ubuf, cnt))
- return -EFAULT;
-
- if (!strncmp(buf, "get", 3)) {
- if (IS_ERR(pil_get(pil->desc->name)))
- return -EIO;
- } else if (!strncmp(buf, "put", 3))
- pil_put(pil);
- else
- return -EINVAL;
-
- return cnt;
-}
-
-static const struct file_operations msm_pil_debugfs_fops = {
- .open = msm_pil_debugfs_open,
- .read = msm_pil_debugfs_read,
- .write = msm_pil_debugfs_write,
-};
-
-static struct dentry *pil_base_dir;
-
-static int __init msm_pil_debugfs_init(void)
-{
- pil_base_dir = debugfs_create_dir("pil", NULL);
- if (!pil_base_dir) {
- pil_base_dir = NULL;
- return -ENOMEM;
- }
-
- return 0;
-}
-
-static void __exit msm_pil_debugfs_exit(void)
-{
- debugfs_remove_recursive(pil_base_dir);
-}
-
-static int msm_pil_debugfs_add(struct pil_device *pil)
-{
- if (!pil_base_dir)
- return -ENOMEM;
-
- pil->dentry = debugfs_create_file(pil->desc->name, S_IRUGO | S_IWUSR,
- pil_base_dir, pil, &msm_pil_debugfs_fops);
- return !pil->dentry ? -ENOMEM : 0;
-}
-
-static void msm_pil_debugfs_remove(struct pil_device *pil)
-{
- debugfs_remove(pil->dentry);
-}
-#else
-static int __init msm_pil_debugfs_init(void) { return 0; };
-static void __exit msm_pil_debugfs_exit(void) { return 0; };
-static int msm_pil_debugfs_add(struct pil_device *pil) { return 0; }
-static void msm_pil_debugfs_remove(struct pil_device *pil) { }
-#endif
-
-static void pil_device_release(struct device *dev)
-{
- struct pil_device *pil = to_pil_device(dev);
- wake_lock_destroy(&pil->wlock);
- mutex_destroy(&pil->lock);
- kfree(pil);
-}
-
-struct pil_device *msm_pil_register(struct pil_desc *desc)
-{
- int err;
- static atomic_t pil_count = ATOMIC_INIT(-1);
- struct pil_device *pil;
+ struct pil_priv *priv;
/* Ignore users who don't make any sense */
+ WARN(desc->ops->proxy_unvote && !desc->proxy_timeout,
+ "A proxy timeout of 0 was specified.\n");
if (WARN(desc->ops->proxy_unvote && !desc->ops->proxy_vote,
- "invalid proxy voting. ignoring\n"))
+ "Invalid proxy voting. Ignoring\n"))
((struct pil_reset_ops *)desc->ops)->proxy_unvote = NULL;
- WARN(desc->ops->proxy_unvote && !desc->proxy_timeout,
- "A proxy timeout of 0 ms was specified for %s. Specify one in "
- "desc->proxy_timeout.\n", desc->name);
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+ desc->priv = priv;
+ priv->desc = desc;
- pil = kzalloc(sizeof(*pil), GFP_KERNEL);
- if (!pil)
- return ERR_PTR(-ENOMEM);
+ snprintf(priv->wname, sizeof(priv->wname), "pil-%s", desc->name);
+ wake_lock_init(&priv->wlock, WAKE_LOCK_SUSPEND, priv->wname);
+ INIT_DELAYED_WORK(&priv->proxy, pil_proxy_work);
+ INIT_LIST_HEAD(&priv->segs);
- mutex_init(&pil->lock);
- pil->desc = desc;
- pil->owner = desc->owner;
- pil->dev.parent = desc->dev;
- pil->dev.bus = &pil_bus_type;
- pil->dev.release = pil_device_release;
-
- snprintf(pil->wake_name, sizeof(pil->wake_name), "pil-%s", desc->name);
- wake_lock_init(&pil->wlock, WAKE_LOCK_SUSPEND, pil->wake_name);
- INIT_DELAYED_WORK(&pil->proxy, pil_proxy_work);
-
- dev_set_name(&pil->dev, "pil%d", atomic_inc_return(&pil_count));
- err = device_register(&pil->dev);
- if (err) {
- put_device(&pil->dev);
- wake_lock_destroy(&pil->wlock);
- mutex_destroy(&pil->lock);
- kfree(pil);
- return ERR_PTR(err);
- }
-
- err = msm_pil_debugfs_add(pil);
- if (err) {
- device_unregister(&pil->dev);
- return ERR_PTR(err);
- }
-
- return pil;
+ return 0;
}
-EXPORT_SYMBOL(msm_pil_register);
+EXPORT_SYMBOL(pil_desc_init);
-void msm_pil_unregister(struct pil_device *pil)
+/**
+ * pil_desc_release() - Release a pil descriptor
+ * @desc: descriptor to free
+ */
+void pil_desc_release(struct pil_desc *desc)
{
- if (IS_ERR_OR_NULL(pil))
- return;
+ struct pil_priv *priv = desc->priv;
- if (get_device(&pil->dev)) {
- mutex_lock(&pil->lock);
- WARN_ON(pil->count);
- flush_delayed_work_sync(&pil->proxy);
- msm_pil_debugfs_remove(pil);
- device_unregister(&pil->dev);
- mutex_unlock(&pil->lock);
- put_device(&pil->dev);
+ if (priv) {
+ flush_delayed_work(&priv->proxy);
+ wake_lock_destroy(&priv->wlock);
}
+ desc->priv = NULL;
+ kfree(priv);
}
-EXPORT_SYMBOL(msm_pil_unregister);
+EXPORT_SYMBOL(pil_desc_release);
static int pil_pm_notify(struct notifier_block *b, unsigned long event, void *p)
{
@@ -675,19 +663,18 @@
static int __init msm_pil_init(void)
{
- int ret = msm_pil_debugfs_init();
- if (ret)
- return ret;
- register_pm_notifier(&pil_pm_notifier);
- return bus_register(&pil_bus_type);
+ ion = msm_ion_client_create(UINT_MAX, "pil");
+ if (IS_ERR(ion)) /* Can't support relocatable images */
+ ion = NULL;
+ return register_pm_notifier(&pil_pm_notifier);
}
-subsys_initcall(msm_pil_init);
+device_initcall(msm_pil_init);
static void __exit msm_pil_exit(void)
{
- bus_unregister(&pil_bus_type);
unregister_pm_notifier(&pil_pm_notifier);
- msm_pil_debugfs_exit();
+ if (ion)
+ ion_client_destroy(ion);
}
module_exit(msm_pil_exit);
diff --git a/arch/arm/mach-msm/peripheral-loader.h b/arch/arm/mach-msm/peripheral-loader.h
index 405b73f..1c2faf7 100644
--- a/arch/arm/mach-msm/peripheral-loader.h
+++ b/arch/arm/mach-msm/peripheral-loader.h
@@ -14,28 +14,33 @@
struct device;
struct module;
+struct pil_priv;
/**
* struct pil_desc - PIL descriptor
* @name: string used for pil_get()
- * @depends_on: booted before this peripheral
* @dev: parent device
* @ops: callback functions
* @owner: module the descriptor belongs to
* @proxy_timeout: delay in ms until proxy vote is removed
+ * @flags: bitfield for image flags
+ * @priv: DON'T USE - internal only
*/
struct pil_desc {
const char *name;
- const char *depends_on;
struct device *dev;
const struct pil_reset_ops *ops;
struct module *owner;
unsigned long proxy_timeout;
+ unsigned long flags;
+#define PIL_SKIP_ENTRY_CHECK BIT(0)
+ struct pil_priv *priv;
};
/**
* struct pil_reset_ops - PIL operations
* @init_image: prepare an image for authentication
+ * @mem_setup: prepare the image memory region
* @verify_blob: authenticate a program segment, called once for each loadable
* program segment (optional)
* @proxy_vote: make proxy votes before auth_and_reset (optional)
@@ -46,6 +51,7 @@
struct pil_reset_ops {
int (*init_image)(struct pil_desc *pil, const u8 *metadata,
size_t size);
+ int (*mem_setup)(struct pil_desc *pil, phys_addr_t addr, size_t size);
int (*verify_blob)(struct pil_desc *pil, u32 phy_addr, size_t size);
int (*proxy_vote)(struct pil_desc *pil);
int (*auth_and_reset)(struct pil_desc *pil);
@@ -53,17 +59,21 @@
int (*shutdown)(struct pil_desc *pil);
};
-struct pil_device;
-
#ifdef CONFIG_MSM_PIL
-extern struct pil_device *msm_pil_register(struct pil_desc *desc);
-extern void msm_pil_unregister(struct pil_device *pil);
+extern int pil_desc_init(struct pil_desc *desc);
+extern int pil_boot(struct pil_desc *desc);
+extern void pil_shutdown(struct pil_desc *desc);
+extern void pil_desc_release(struct pil_desc *desc);
+extern phys_addr_t pil_get_entry_addr(struct pil_desc *desc);
#else
-static inline struct pil_device *msm_pil_register(struct pil_desc *desc)
+static inline int pil_desc_init(struct pil_desc *desc) { return 0; }
+static inline int pil_boot(struct pil_desc *desc) { return 0; }
+static inline void pil_shutdown(struct pil_desc *desc) { }
+static inline void pil_desc_release(struct pil_desc *desc) { }
+static inline phys_addr_t pil_get_entry_addr(struct pil_desc *desc)
{
- return NULL;
+ return 0;
}
-static inline void msm_pil_unregister(struct pil_device *pil) { }
#endif
#endif
diff --git a/arch/arm/mach-msm/pil-dsps.c b/arch/arm/mach-msm/pil-dsps.c
index c074086..519e1c9 100644
--- a/arch/arm/mach-msm/pil-dsps.c
+++ b/arch/arm/mach-msm/pil-dsps.c
@@ -13,34 +13,31 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <linux/elf.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/atomic.h>
#include <linux/interrupt.h>
-#include <mach/msm_iomap.h>
#include <mach/subsystem_restart.h>
#include <mach/msm_smsm.h>
-#include <mach/peripheral-loader.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
#include "ramdump.h"
-#define PPSS_RESET (MSM_CLK_CTL_BASE + 0x2594)
+#define PPSS_RESET 0x2594
#define PPSS_RESET_PROC_RESET 0x2
#define PPSS_RESET_RESET 0x1
-#define PPSS_PROC_CLK_CTL (MSM_CLK_CTL_BASE + 0x2588)
+#define PPSS_PROC_CLK_CTL 0x2588
#define CLK_BRANCH_ENA 0x10
-#define PPSS_HCLK_CTL (MSM_CLK_CTL_BASE + 0x2580)
-#define CLK_HALT_DFAB_STATE (MSM_CLK_CTL_BASE + 0x2FC8)
+#define PPSS_HCLK_CTL 0x2580
+#define CLK_HALT_DFAB_STATE 0x2FC8
#define PPSS_WDOG_UNMASKED_INT_EN 0x1808
struct dsps_data {
- struct pil_device *pil;
+ void __iomem *base;
struct pil_desc desc;
struct subsys_device *subsys;
struct subsys_desc subsys_desc;
@@ -58,33 +55,41 @@
};
#define desc_to_drv(d) container_of(d, struct dsps_data, subsys_desc)
+#define pil_to_drv(d) container_of(d, struct dsps_data, desc)
static int init_image_dsps(struct pil_desc *pil, const u8 *metadata,
size_t size)
{
+ struct dsps_data *drv = pil_to_drv(pil);
+
/* Bring memory and bus interface out of reset */
- writel_relaxed(PPSS_RESET_PROC_RESET, PPSS_RESET);
- writel_relaxed(CLK_BRANCH_ENA, PPSS_HCLK_CTL);
+ writel_relaxed(PPSS_RESET_PROC_RESET, drv->base + PPSS_RESET);
+ writel_relaxed(CLK_BRANCH_ENA, drv->base + PPSS_HCLK_CTL);
mb();
return 0;
}
static int reset_dsps(struct pil_desc *pil)
{
- writel_relaxed(CLK_BRANCH_ENA, PPSS_PROC_CLK_CTL);
- while (readl_relaxed(CLK_HALT_DFAB_STATE) & BIT(18))
+ struct dsps_data *drv = pil_to_drv(pil);
+
+ writel_relaxed(CLK_BRANCH_ENA, drv->base + PPSS_PROC_CLK_CTL);
+ while (readl_relaxed(drv->base + CLK_HALT_DFAB_STATE) & BIT(18))
cpu_relax();
/* Bring DSPS out of reset */
- writel_relaxed(0x0, PPSS_RESET);
+ writel_relaxed(0x0, drv->base + PPSS_RESET);
return 0;
}
static int shutdown_dsps(struct pil_desc *pil)
{
- writel_relaxed(PPSS_RESET_PROC_RESET | PPSS_RESET_RESET, PPSS_RESET);
+ struct dsps_data *drv = pil_to_drv(pil);
+
+ writel_relaxed(PPSS_RESET_PROC_RESET | PPSS_RESET_RESET,
+ drv->base + PPSS_RESET);
usleep_range(1000, 2000);
- writel_relaxed(PPSS_RESET_PROC_RESET, PPSS_RESET);
- writel_relaxed(0x0, PPSS_PROC_CLK_CTL);
+ writel_relaxed(PPSS_RESET_PROC_RESET, drv->base + PPSS_RESET);
+ writel_relaxed(0x0, drv->base + PPSS_PROC_CLK_CTL);
return 0;
}
@@ -165,19 +170,15 @@
static int dsps_start(const struct subsys_desc *desc)
{
- void *ret;
struct dsps_data *drv = desc_to_drv(desc);
- ret = pil_get(drv->desc.name);
- if (IS_ERR(ret))
- return PTR_ERR(ret);
- return 0;
+ return pil_boot(&drv->desc);
}
static void dsps_stop(const struct subsys_desc *desc)
{
struct dsps_data *drv = desc_to_drv(desc);
- pil_put(drv->pil);
+ pil_shutdown(&drv->desc);
}
static int dsps_shutdown(const struct subsys_desc *desc)
@@ -188,7 +189,7 @@
writel_relaxed(0, drv->ppss_base + PPSS_WDOG_UNMASKED_INT_EN);
mb(); /* Make sure wdog is disabled before shutting down */
}
- pil_force_shutdown(drv->desc.name);
+ pil_shutdown(&drv->desc);
return 0;
}
@@ -196,7 +197,7 @@
{
struct dsps_data *drv = desc_to_drv(desc);
- pil_force_boot(drv->desc.name);
+ pil_boot(&drv->desc);
atomic_set(&drv->crash_in_progress, 0);
enable_irq(drv->wdog_irq);
@@ -253,8 +254,8 @@
{
struct dsps_data *drv;
struct pil_desc *desc;
- int ret;
struct resource *res;
+ int ret;
drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
if (!drv)
@@ -262,6 +263,13 @@
platform_set_drvdata(pdev, drv);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -EINVAL;
+ drv->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ if (!drv->base)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (res) {
drv->ppss_base = devm_ioremap(&pdev->dev, res->start,
resource_size(res));
@@ -273,6 +281,7 @@
desc->name = pdev->dev.platform_data;
desc->dev = &pdev->dev;
desc->owner = THIS_MODULE;
+ desc->flags = PIL_SKIP_ENTRY_CHECK;
if (pas_supported(PAS_DSPS) > 0) {
desc->ops = &pil_dsps_ops_trusted;
dev_info(&pdev->dev, "using secure boot\n");
@@ -280,9 +289,9 @@
desc->ops = &pil_dsps_ops;
dev_info(&pdev->dev, "using non-secure boot\n");
}
- drv->pil = msm_pil_register(desc);
- if (IS_ERR(drv->pil))
- return PTR_ERR(drv->pil);
+ ret = pil_desc_init(desc);
+ if (ret)
+ return ret;
drv->fw_ramdump_segments[0].address = 0x12000000;
drv->fw_ramdump_segments[0].size = 0x28000;
@@ -292,7 +301,7 @@
drv->fw_ramdump_segments[2].size = 0x4000;
drv->fw_ramdump_segments[3].address = 0x8fe00000;
drv->fw_ramdump_segments[3].size = 0x100000;
- drv->ramdump_dev = create_ramdump_device("dsps");
+ drv->ramdump_dev = create_ramdump_device("dsps", &pdev->dev);
if (!drv->ramdump_dev) {
ret = -ENOMEM;
goto err_ramdump;
@@ -300,7 +309,7 @@
drv->smem_ramdump_segments[0].address = PHYS_OFFSET - SZ_2M;
drv->smem_ramdump_segments[0].size = SZ_2M;
- drv->smem_ramdump_dev = create_ramdump_device("smem-dsps");
+ drv->smem_ramdump_dev = create_ramdump_device("smem-dsps", &pdev->dev);
if (!drv->smem_ramdump_dev) {
ret = -ENOMEM;
goto err_smem_ramdump;
@@ -350,7 +359,7 @@
err_smem_ramdump:
destroy_ramdump_device(drv->ramdump_dev);
err_ramdump:
- msm_pil_unregister(drv->pil);
+ pil_desc_release(desc);
return ret;
}
@@ -362,7 +371,7 @@
subsys_unregister(drv->subsys);
destroy_ramdump_device(drv->smem_ramdump_dev);
destroy_ramdump_device(drv->ramdump_dev);
- msm_pil_unregister(drv->pil);
+ pil_desc_release(&drv->desc);
return 0;
}
diff --git a/arch/arm/mach-msm/pil-gss.c b/arch/arm/mach-msm/pil-gss.c
index 0c8f4e3..a6d13d0 100644
--- a/arch/arm/mach-msm/pil-gss.c
+++ b/arch/arm/mach-msm/pil-gss.c
@@ -14,7 +14,6 @@
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/io.h>
-#include <linux/elf.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -25,13 +24,11 @@
#include <linux/reboot.h>
#include <linux/interrupt.h>
-#include <mach/msm_iomap.h>
#include <mach/msm_xo.h>
#include <mach/socinfo.h>
#include <mach/msm_bus_board.h>
#include <mach/msm_bus.h>
#include <mach/subsystem_restart.h>
-#include <mach/peripheral-loader.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
@@ -46,13 +43,13 @@
#define GSS_CSR_POWER_UP_DOWN 0x18
#define GSS_CSR_CFG_HID 0x2C
-#define GSS_SLP_CLK_CTL (MSM_CLK_CTL_BASE + 0x2C60)
-#define GSS_RESET (MSM_CLK_CTL_BASE + 0x2C64)
-#define GSS_CLAMP_ENA (MSM_CLK_CTL_BASE + 0x2C68)
-#define GSS_CXO_SRC_CTL (MSM_CLK_CTL_BASE + 0x2C74)
+#define GSS_SLP_CLK_CTL 0x2C60
+#define GSS_RESET 0x2C64
+#define GSS_CLAMP_ENA 0x2C68
+#define GSS_CXO_SRC_CTL 0x2C74
-#define PLL5_STATUS (MSM_CLK_CTL_BASE + 0x30F8)
-#define PLL_ENA_GSS (MSM_CLK_CTL_BASE + 0x3480)
+#define PLL5_STATUS 0x30F8
+#define PLL_ENA_GSS 0x3480
#define PLL5_VOTE BIT(5)
#define PLL_STATUS BIT(16)
@@ -67,9 +64,9 @@
struct gss_data {
void __iomem *base;
void __iomem *qgic2_base;
- unsigned long start_addr;
+ void __iomem *cbase;
struct clk *xo;
- struct pil_device *pil;
+ struct pil_desc pil_desc;
struct miscdevice misc_dev;
struct subsys_device *subsys;
struct subsys_desc subsys_desc;
@@ -80,15 +77,6 @@
struct ramdump_device *smem_ramdump_dev;
};
-static int pil_gss_init_image(struct pil_desc *pil, const u8 *metadata,
- size_t size)
-{
- const struct elf32_hdr *ehdr = (struct elf32_hdr *)metadata;
- struct gss_data *drv = dev_get_drvdata(pil->dev);
- drv->start_addr = ehdr->e_entry;
- return 0;
-}
-
static int make_gss_proxy_votes(struct pil_desc *pil)
{
int ret;
@@ -111,14 +99,15 @@
static void gss_init(struct gss_data *drv)
{
void __iomem *base = drv->base;
+ void __iomem *cbase = drv->cbase;
/* Supply clocks to GSS. */
- writel_relaxed(XO_CLK_BRANCH_ENA, GSS_CXO_SRC_CTL);
- writel_relaxed(SLP_CLK_BRANCH_ENA, GSS_SLP_CLK_CTL);
+ writel_relaxed(XO_CLK_BRANCH_ENA, cbase + GSS_CXO_SRC_CTL);
+ writel_relaxed(SLP_CLK_BRANCH_ENA, cbase + GSS_SLP_CLK_CTL);
/* Deassert GSS reset and clamps. */
- writel_relaxed(0x0, GSS_RESET);
- writel_relaxed(0x0, GSS_CLAMP_ENA);
+ writel_relaxed(0x0, cbase + GSS_RESET);
+ writel_relaxed(0x0, cbase + GSS_CLAMP_ENA);
mb();
/*
@@ -159,6 +148,7 @@
{
struct gss_data *drv = dev_get_drvdata(pil->dev);
void __iomem *base = drv->base;
+ void __iomem *cbase = drv->cbase;
u32 regval;
int ret;
@@ -175,8 +165,8 @@
* Vote PLL on in GSS's voting register and wait for it to enable.
* The PLL must be enable to switch the GFMUX to a low-power source.
*/
- writel_relaxed(PLL5_VOTE, PLL_ENA_GSS);
- while ((readl_relaxed(PLL5_STATUS) & PLL_STATUS) == 0)
+ writel_relaxed(PLL5_VOTE, cbase + PLL_ENA_GSS);
+ while ((readl_relaxed(cbase + PLL5_STATUS) & PLL_STATUS) == 0)
cpu_relax();
/* Perform one-time GSS initialization. */
@@ -201,7 +191,7 @@
writel_relaxed(0x1F, base + GSS_CSR_CLK_ENABLE);
/* Clear GSS PLL votes. */
- writel_relaxed(0, PLL_ENA_GSS);
+ writel_relaxed(0, cbase + PLL_ENA_GSS);
mb();
clk_disable_unprepare(drv->xo);
@@ -213,7 +203,8 @@
{
struct gss_data *drv = dev_get_drvdata(pil->dev);
void __iomem *base = drv->base;
- unsigned long start_addr = drv->start_addr;
+ unsigned long start_addr = pil_get_entry_addr(pil);
+ void __iomem *cbase = drv->cbase;
int ret;
/* Unhalt bus port. */
@@ -224,8 +215,8 @@
}
/* Vote PLL on in GSS's voting register and wait for it to enable. */
- writel_relaxed(PLL5_VOTE, PLL_ENA_GSS);
- while ((readl_relaxed(PLL5_STATUS) & PLL_STATUS) == 0)
+ writel_relaxed(PLL5_VOTE, cbase + PLL_ENA_GSS);
+ while ((readl_relaxed(cbase + PLL5_STATUS) & PLL_STATUS) == 0)
cpu_relax();
/* Perform GSS initialization. */
@@ -258,7 +249,6 @@
}
static struct pil_reset_ops pil_gss_ops = {
- .init_image = pil_gss_init_image,
.auth_and_reset = pil_gss_reset,
.shutdown = pil_gss_shutdown,
.proxy_vote = make_gss_proxy_votes,
@@ -373,14 +363,10 @@
static int gss_start(const struct subsys_desc *desc)
{
- void *ret;
struct gss_data *drv;
drv = container_of(desc, struct gss_data, subsys_desc);
- ret = pil_get("gss");
- if (IS_ERR(ret))
- return PTR_ERR(ret);
- return 0;
+ return pil_boot(&drv->pil_desc);
}
static void gss_stop(const struct subsys_desc *desc)
@@ -388,14 +374,14 @@
struct gss_data *drv;
drv = container_of(desc, struct gss_data, subsys_desc);
- pil_put(drv->pil);
+ pil_shutdown(&drv->pil_desc);
}
static int gss_shutdown(const struct subsys_desc *desc)
{
struct gss_data *drv = container_of(desc, struct gss_data, subsys_desc);
- pil_force_shutdown("gss");
+ pil_shutdown(&drv->pil_desc);
disable_irq_nosync(drv->irq);
return 0;
@@ -405,7 +391,7 @@
{
struct gss_data *drv = container_of(desc, struct gss_data, subsys_desc);
- pil_force_boot("gss");
+ pil_boot(&drv->pil_desc);
enable_irq(drv->irq);
return 0;
}
@@ -467,8 +453,10 @@
struct gss_data *drv = container_of(c, struct gss_data, misc_dev);
drv->subsys_handle = subsystem_get("gss");
- if (!drv->subsys_handle)
- pr_debug("%s - subsystem_get returned NULL\n", __func__);
+ if (IS_ERR(drv->subsys_handle)) {
+ pr_debug("%s - subsystem_get returned error\n", __func__);
+ return PTR_ERR(drv->subsys_handle);
+ }
return 0;
}
@@ -497,30 +485,26 @@
struct pil_desc *desc;
int ret;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -EINVAL;
-
drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
if (!drv)
return -ENOMEM;
platform_set_drvdata(pdev, drv);
- drv->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ drv->base = devm_request_and_ioremap(&pdev->dev, res);
if (!drv->base)
return -ENOMEM;
- desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL);
- if (!desc)
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ drv->qgic2_base = devm_request_and_ioremap(&pdev->dev, res);
+ if (!drv->qgic2_base)
return -ENOMEM;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
if (!res)
return -EINVAL;
-
- drv->qgic2_base = devm_ioremap(&pdev->dev, res->start,
- resource_size(res));
- if (!drv->qgic2_base)
+ drv->cbase = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ if (!drv->cbase)
return -ENOMEM;
drv->xo = devm_clk_get(&pdev->dev, "xo");
@@ -531,6 +515,7 @@
if (drv->irq < 0)
return drv->irq;
+ desc = &drv->pil_desc;
desc->name = "gss";
desc->dev = &pdev->dev;
desc->owner = THIS_MODULE;
@@ -543,14 +528,13 @@
desc->ops = &pil_gss_ops;
dev_info(&pdev->dev, "using non-secure boot\n");
}
+ ret = pil_desc_init(desc);
+ if (ret)
+ return ret;
+
/* Force into low power mode because hardware doesn't do this */
desc->ops->shutdown(desc);
- drv->pil = msm_pil_register(desc);
- if (IS_ERR(drv->pil)) {
- return PTR_ERR(drv->pil);
- }
-
ret = smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_RESET,
smsm_state_cb, drv);
if (ret < 0)
@@ -579,13 +563,13 @@
if (ret)
goto err_misc;
- drv->ramdump_dev = create_ramdump_device("gss");
+ drv->ramdump_dev = create_ramdump_device("gss", &pdev->dev);
if (!drv->ramdump_dev) {
ret = -ENOMEM;
goto err_ramdump;
}
- drv->smem_ramdump_dev = create_ramdump_device("smem-gss");
+ drv->smem_ramdump_dev = create_ramdump_device("smem-gss", &pdev->dev);
if (!drv->smem_ramdump_dev) {
ret = -ENOMEM;
goto err_smem;
@@ -605,7 +589,7 @@
err_misc:
subsys_unregister(drv->subsys);
err_subsys:
- msm_pil_unregister(drv->pil);
+ pil_desc_release(desc);
return ret;
}
@@ -617,7 +601,7 @@
destroy_ramdump_device(drv->ramdump_dev);
misc_deregister(&drv->misc_dev);
subsys_unregister(drv->subsys);
- msm_pil_unregister(drv->pil);
+ pil_desc_release(&drv->pil_desc);
return 0;
}
diff --git a/arch/arm/mach-msm/pil-modem.c b/arch/arm/mach-msm/pil-modem.c
index ad27cd1..d3c832b 100644
--- a/arch/arm/mach-msm/pil-modem.c
+++ b/arch/arm/mach-msm/pil-modem.c
@@ -15,7 +15,6 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/ioport.h>
-#include <linux/elf.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/clk.h>
@@ -23,10 +22,8 @@
#include <linux/interrupt.h>
#include <linux/reboot.h>
-#include <mach/msm_iomap.h>
#include <mach/subsystem_restart.h>
#include <mach/msm_smsm.h>
-#include <mach/peripheral-loader.h>
#include "modem_notifier.h"
#include "peripheral-loader.h"
@@ -34,37 +31,38 @@
#include "ramdump.h"
#define MARM_BOOT_CONTROL 0x0010
-#define MARM_RESET (MSM_CLK_CTL_BASE + 0x2BD4)
-#define MAHB0_SFAB_PORT_RESET (MSM_CLK_CTL_BASE + 0x2304)
-#define MARM_CLK_BRANCH_ENA_VOTE (MSM_CLK_CTL_BASE + 0x3000)
-#define MARM_CLK_SRC0_NS (MSM_CLK_CTL_BASE + 0x2BC0)
-#define MARM_CLK_SRC1_NS (MSM_CLK_CTL_BASE + 0x2BC4)
-#define MARM_CLK_SRC_CTL (MSM_CLK_CTL_BASE + 0x2BC8)
-#define MARM_CLK_CTL (MSM_CLK_CTL_BASE + 0x2BCC)
-#define SFAB_MSS_S_HCLK_CTL (MSM_CLK_CTL_BASE + 0x2C00)
-#define MSS_MODEM_CXO_CLK_CTL (MSM_CLK_CTL_BASE + 0x2C44)
-#define MSS_SLP_CLK_CTL (MSM_CLK_CTL_BASE + 0x2C60)
-#define MSS_MARM_SYS_REF_CLK_CTL (MSM_CLK_CTL_BASE + 0x2C64)
-#define MAHB0_CLK_CTL (MSM_CLK_CTL_BASE + 0x2300)
-#define MAHB1_CLK_CTL (MSM_CLK_CTL_BASE + 0x2BE4)
-#define MAHB2_CLK_CTL (MSM_CLK_CTL_BASE + 0x2C20)
-#define MAHB1_NS (MSM_CLK_CTL_BASE + 0x2BE0)
-#define MARM_CLK_FS (MSM_CLK_CTL_BASE + 0x2BD0)
-#define MAHB2_CLK_FS (MSM_CLK_CTL_BASE + 0x2C24)
-#define PLL_ENA_MARM (MSM_CLK_CTL_BASE + 0x3500)
-#define PLL8_STATUS (MSM_CLK_CTL_BASE + 0x3158)
-#define CLK_HALT_MSS_SMPSS_MISC_STATE (MSM_CLK_CTL_BASE + 0x2FDC)
-#define MSS_MODEM_RESET (MSM_CLK_CTL_BASE + 0x2C48)
+#define MARM_RESET 0x2BD4
+#define MAHB0_SFAB_PORT_RESET 0x2304
+#define MARM_CLK_BRANCH_ENA_VOTE 0x3000
+#define MARM_CLK_SRC0_NS 0x2BC0
+#define MARM_CLK_SRC1_NS 0x2BC4
+#define MARM_CLK_SRC_CTL 0x2BC8
+#define MARM_CLK_CTL 0x2BCC
+#define SFAB_MSS_S_HCLK_CTL 0x2C00
+#define MSS_MODEM_CXO_CLK_CTL 0x2C44
+#define MSS_SLP_CLK_CTL 0x2C60
+#define MSS_MARM_SYS_REF_CLK_CTL 0x2C64
+#define MAHB0_CLK_CTL 0x2300
+#define MAHB1_CLK_CTL 0x2BE4
+#define MAHB2_CLK_CTL 0x2C20
+#define MAHB1_NS 0x2BE0
+#define MARM_CLK_FS 0x2BD0
+#define MAHB2_CLK_FS 0x2C24
+#define PLL_ENA_MARM 0x3500
+#define PLL8_STATUS 0x3158
+#define CLK_HALT_MSS_SMPSS_MISC_STATE 0x2FDC
+#define MSS_MODEM_RESET 0x2C48
struct modem_data {
void __iomem *base;
void __iomem *wdog;
- unsigned long start_addr;
+ void __iomem *cbase;
struct pil_device *pil;
struct clk *xo;
struct notifier_block notifier;
int ignore_smsm_ack;
int irq;
+ struct pil_desc pil_desc;
struct subsys_device *subsys;
struct subsys_desc subsys_desc;
struct delayed_work unlock_work;
@@ -91,90 +89,82 @@
clk_disable_unprepare(drv->xo);
}
-static int modem_init_image(struct pil_desc *pil, const u8 *metadata,
- size_t size)
-{
- const struct elf32_hdr *ehdr = (struct elf32_hdr *)metadata;
- struct modem_data *drv = dev_get_drvdata(pil->dev);
- drv->start_addr = ehdr->e_entry;
- return 0;
-}
-
static int modem_reset(struct pil_desc *pil)
{
u32 reg;
const struct modem_data *drv = dev_get_drvdata(pil->dev);
+ unsigned long start_addr = pil_get_entry_addr(pil);
/* Put modem AHB0,1,2 clocks into reset */
- writel_relaxed(BIT(0) | BIT(1), MAHB0_SFAB_PORT_RESET);
- writel_relaxed(BIT(7), MAHB1_CLK_CTL);
- writel_relaxed(BIT(7), MAHB2_CLK_CTL);
+ writel_relaxed(BIT(0) | BIT(1), drv->cbase + MAHB0_SFAB_PORT_RESET);
+ writel_relaxed(BIT(7), drv->cbase + MAHB1_CLK_CTL);
+ writel_relaxed(BIT(7), drv->cbase + MAHB2_CLK_CTL);
/* Vote for pll8 on behalf of the modem */
- reg = readl_relaxed(PLL_ENA_MARM);
+ reg = readl_relaxed(drv->cbase + PLL_ENA_MARM);
reg |= BIT(8);
- writel_relaxed(reg, PLL_ENA_MARM);
+ writel_relaxed(reg, drv->cbase + PLL_ENA_MARM);
/* Wait for PLL8 to enable */
- while (!(readl_relaxed(PLL8_STATUS) & BIT(16)))
+ while (!(readl_relaxed(drv->cbase + PLL8_STATUS) & BIT(16)))
cpu_relax();
/* Set MAHB1 divider to Div-5 to run MAHB1,2 and sfab at 79.8 Mhz*/
- writel_relaxed(0x4, MAHB1_NS);
+ writel_relaxed(0x4, drv->cbase + MAHB1_NS);
/* Vote for modem AHB1 and 2 clocks to be on on behalf of the modem */
- reg = readl_relaxed(MARM_CLK_BRANCH_ENA_VOTE);
+ reg = readl_relaxed(drv->cbase + MARM_CLK_BRANCH_ENA_VOTE);
reg |= BIT(0) | BIT(1);
- writel_relaxed(reg, MARM_CLK_BRANCH_ENA_VOTE);
+ writel_relaxed(reg, drv->cbase + MARM_CLK_BRANCH_ENA_VOTE);
/* Source marm_clk off of PLL8 */
- reg = readl_relaxed(MARM_CLK_SRC_CTL);
+ reg = readl_relaxed(drv->cbase + MARM_CLK_SRC_CTL);
if ((reg & 0x1) == 0) {
- writel_relaxed(0x3, MARM_CLK_SRC1_NS);
+ writel_relaxed(0x3, drv->cbase + MARM_CLK_SRC1_NS);
reg |= 0x1;
} else {
- writel_relaxed(0x3, MARM_CLK_SRC0_NS);
+ writel_relaxed(0x3, drv->cbase + MARM_CLK_SRC0_NS);
reg &= ~0x1;
}
- writel_relaxed(reg | 0x2, MARM_CLK_SRC_CTL);
+ writel_relaxed(reg | 0x2, drv->cbase + MARM_CLK_SRC_CTL);
/*
* Force core on and periph on signals to remain active during halt
* for marm_clk and mahb2_clk
*/
- writel_relaxed(0x6F, MARM_CLK_FS);
- writel_relaxed(0x6F, MAHB2_CLK_FS);
+ writel_relaxed(0x6F, drv->cbase + MARM_CLK_FS);
+ writel_relaxed(0x6F, drv->cbase + MAHB2_CLK_FS);
/*
* Enable all of the marm_clk branches, cxo sourced marm branches,
* and sleep clock branches
*/
- writel_relaxed(0x10, MARM_CLK_CTL);
- writel_relaxed(0x10, MAHB0_CLK_CTL);
- writel_relaxed(0x10, SFAB_MSS_S_HCLK_CTL);
- writel_relaxed(0x10, MSS_MODEM_CXO_CLK_CTL);
- writel_relaxed(0x10, MSS_SLP_CLK_CTL);
- writel_relaxed(0x10, MSS_MARM_SYS_REF_CLK_CTL);
+ writel_relaxed(0x10, drv->cbase + MARM_CLK_CTL);
+ writel_relaxed(0x10, drv->cbase + MAHB0_CLK_CTL);
+ writel_relaxed(0x10, drv->cbase + SFAB_MSS_S_HCLK_CTL);
+ writel_relaxed(0x10, drv->cbase + MSS_MODEM_CXO_CLK_CTL);
+ writel_relaxed(0x10, drv->cbase + MSS_SLP_CLK_CTL);
+ writel_relaxed(0x10, drv->cbase + MSS_MARM_SYS_REF_CLK_CTL);
/* Wait for above clocks to be turned on */
- while (readl_relaxed(CLK_HALT_MSS_SMPSS_MISC_STATE) & (BIT(7) | BIT(8) |
- BIT(9) | BIT(10) | BIT(4) | BIT(6)))
+ while (readl_relaxed(drv->cbase + CLK_HALT_MSS_SMPSS_MISC_STATE) &
+ (BIT(7) | BIT(8) | BIT(9) | BIT(10) | BIT(4) | BIT(6)))
cpu_relax();
/* Take MAHB0,1,2 clocks out of reset */
- writel_relaxed(0x0, MAHB2_CLK_CTL);
- writel_relaxed(0x0, MAHB1_CLK_CTL);
- writel_relaxed(0x0, MAHB0_SFAB_PORT_RESET);
+ writel_relaxed(0x0, drv->cbase + MAHB2_CLK_CTL);
+ writel_relaxed(0x0, drv->cbase + MAHB1_CLK_CTL);
+ writel_relaxed(0x0, drv->cbase + MAHB0_SFAB_PORT_RESET);
mb();
/* Setup exception vector table base address */
- writel_relaxed(drv->start_addr | 0x1, drv->base + MARM_BOOT_CONTROL);
+ writel_relaxed(start_addr | 0x1, drv->base + MARM_BOOT_CONTROL);
/* Wait for vector table to be setup */
mb();
/* Bring modem out of reset */
- writel_relaxed(0x0, MARM_RESET);
+ writel_relaxed(0x0, drv->cbase + MARM_RESET);
return 0;
}
@@ -182,44 +172,44 @@
static int modem_pil_shutdown(struct pil_desc *pil)
{
u32 reg;
+ const struct modem_data *drv = dev_get_drvdata(pil->dev);
/* Put modem into reset */
- writel_relaxed(0x1, MARM_RESET);
+ writel_relaxed(0x1, drv->cbase + MARM_RESET);
mb();
/* Put modem AHB0,1,2 clocks into reset */
- writel_relaxed(BIT(0) | BIT(1), MAHB0_SFAB_PORT_RESET);
- writel_relaxed(BIT(7), MAHB1_CLK_CTL);
- writel_relaxed(BIT(7), MAHB2_CLK_CTL);
+ writel_relaxed(BIT(0) | BIT(1), drv->cbase + MAHB0_SFAB_PORT_RESET);
+ writel_relaxed(BIT(7), drv->cbase + MAHB1_CLK_CTL);
+ writel_relaxed(BIT(7), drv->cbase + MAHB2_CLK_CTL);
mb();
/*
* Disable all of the marm_clk branches, cxo sourced marm branches,
* and sleep clock branches
*/
- writel_relaxed(0x0, MARM_CLK_CTL);
- writel_relaxed(0x0, MAHB0_CLK_CTL);
- writel_relaxed(0x0, SFAB_MSS_S_HCLK_CTL);
- writel_relaxed(0x0, MSS_MODEM_CXO_CLK_CTL);
- writel_relaxed(0x0, MSS_SLP_CLK_CTL);
- writel_relaxed(0x0, MSS_MARM_SYS_REF_CLK_CTL);
+ writel_relaxed(0x0, drv->cbase + MARM_CLK_CTL);
+ writel_relaxed(0x0, drv->cbase + MAHB0_CLK_CTL);
+ writel_relaxed(0x0, drv->cbase + SFAB_MSS_S_HCLK_CTL);
+ writel_relaxed(0x0, drv->cbase + MSS_MODEM_CXO_CLK_CTL);
+ writel_relaxed(0x0, drv->cbase + MSS_SLP_CLK_CTL);
+ writel_relaxed(0x0, drv->cbase + MSS_MARM_SYS_REF_CLK_CTL);
/* Disable marm_clk */
- reg = readl_relaxed(MARM_CLK_SRC_CTL);
+ reg = readl_relaxed(drv->cbase + MARM_CLK_SRC_CTL);
reg &= ~0x2;
- writel_relaxed(reg, MARM_CLK_SRC_CTL);
+ writel_relaxed(reg, drv->cbase + MARM_CLK_SRC_CTL);
/* Clear modem's votes for ahb clocks */
- writel_relaxed(0x0, MARM_CLK_BRANCH_ENA_VOTE);
+ writel_relaxed(0x0, drv->cbase + MARM_CLK_BRANCH_ENA_VOTE);
/* Clear modem's votes for PLLs */
- writel_relaxed(0x0, PLL_ENA_MARM);
+ writel_relaxed(0x0, drv->cbase + PLL_ENA_MARM);
return 0;
}
static struct pil_reset_ops pil_modem_ops = {
- .init_image = modem_init_image,
.auth_and_reset = modem_reset,
.shutdown = modem_pil_shutdown,
.proxy_vote = make_modem_proxy_votes,
@@ -284,7 +274,7 @@
drv = container_of(dwork, struct modem_data, unlock_work);
/* The unlock didn't work, clear the reset */
- writel_relaxed(0x0, MSS_MODEM_RESET);
+ writel_relaxed(0x0, drv->cbase + MSS_MODEM_RESET);
mb();
subsystem_restart_dev(drv->subsys);
@@ -316,7 +306,7 @@
pr_err("Modem AHB locked up. Trying to free up modem!\n");
- writel_relaxed(0x3, MSS_MODEM_RESET);
+ writel_relaxed(0x3, drv->cbase + MSS_MODEM_RESET);
/*
* If we are still alive (allowing for the 5 second
* delayed-panic-reboot), the modem is either still wedged or
@@ -344,14 +334,10 @@
static int modem_start(const struct subsys_desc *subsys)
{
- void *ret;
struct modem_data *drv;
drv = container_of(subsys, struct modem_data, subsys_desc);
- ret = pil_get("modem");
- if (IS_ERR(ret))
- return PTR_ERR(ret);
- return 0;
+ return pil_boot(&drv->pil_desc);
}
static void modem_stop(const struct subsys_desc *subsys)
@@ -359,7 +345,7 @@
struct modem_data *drv;
drv = container_of(subsys, struct modem_data, subsys_desc);
- pil_put(drv->pil);
+ pil_shutdown(&drv->pil_desc);
}
static int modem_shutdown(const struct subsys_desc *subsys)
@@ -389,7 +375,7 @@
/* Wait here to allow the modem to clean up caches, etc. */
msleep(20);
- pil_force_shutdown("modem");
+ pil_shutdown(&drv->pil_desc);
disable_irq_nosync(drv->irq);
return 0;
@@ -401,7 +387,7 @@
int ret;
drv = container_of(subsys, struct modem_data, subsys_desc);
- ret = pil_force_boot("modem");
+ ret = pil_boot(&drv->pil_desc);
enable_irq(drv->irq);
return ret;
@@ -431,10 +417,6 @@
struct pil_desc *desc;
int ret;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -EINVAL;
-
drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
if (!drv)
return -ENOMEM;
@@ -444,28 +426,30 @@
if (drv->irq < 0)
return drv->irq;
- drv->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
- if (!drv->base)
- return -ENOMEM;
-
drv->xo = devm_clk_get(&pdev->dev, "xo");
if (IS_ERR(drv->xo))
return PTR_ERR(drv->xo);
- desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL);
- if (!desc)
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ drv->base = devm_request_and_ioremap(&pdev->dev, res);
+ if (!drv->base)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (!res)
- return -EINVAL;
-
- drv->wdog = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ drv->wdog = devm_request_and_ioremap(&pdev->dev, res);
if (!drv->wdog)
return -ENOMEM;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+ if (!res)
+ return -EINVAL;
+
+ drv->cbase = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ if (!drv->cbase)
+ return -ENOMEM;
+
+ desc = &drv->pil_desc;
desc->name = "modem";
- desc->depends_on = "q6";
desc->dev = &pdev->dev;
desc->owner = THIS_MODULE;
desc->proxy_timeout = 10000;
@@ -477,9 +461,9 @@
desc->ops = &pil_modem_ops;
dev_info(&pdev->dev, "using non-secure boot\n");
}
- drv->pil = msm_pil_register(desc);
- if (IS_ERR(drv->pil))
- return PTR_ERR(drv->pil);
+ ret = pil_desc_init(desc);
+ if (ret)
+ return ret;
drv->notifier.notifier_call = modem_notif_handler,
ret = modem_register_notifier(&drv->notifier);
@@ -487,7 +471,7 @@
goto err_notify;
drv->subsys_desc.name = "modem";
- drv->subsys_desc.depends_on = "q6";
+ drv->subsys_desc.depends_on = "adsp";
drv->subsys_desc.dev = &pdev->dev;
drv->subsys_desc.owner = THIS_MODULE;
drv->subsys_desc.start = modem_start;
@@ -506,7 +490,7 @@
goto err_subsys;
}
- drv->ramdump_dev = create_ramdump_device("modem");
+ drv->ramdump_dev = create_ramdump_device("modem", &pdev->dev);
if (!drv->ramdump_dev) {
ret = -ENOMEM;
goto err_ramdump;
@@ -525,7 +509,7 @@
err_subsys:
modem_unregister_notifier(&drv->notifier);
err_notify:
- msm_pil_unregister(drv->pil);
+ pil_desc_release(desc);
return ret;
}
@@ -536,7 +520,7 @@
destroy_ramdump_device(drv->ramdump_dev);
subsys_unregister(drv->subsys);
modem_unregister_notifier(&drv->notifier);
- msm_pil_unregister(drv->pil);
+ pil_desc_release(&drv->pil_desc);
return 0;
}
diff --git a/arch/arm/mach-msm/pil-pronto.c b/arch/arm/mach-msm/pil-pronto.c
index 04b3a21..49fe182 100644
--- a/arch/arm/mach-msm/pil-pronto.c
+++ b/arch/arm/mach-msm/pil-pronto.c
@@ -13,7 +13,6 @@
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/io.h>
-#include <linux/elf.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -27,9 +26,7 @@
#include <linux/workqueue.h>
#include <linux/wcnss_wlan.h>
-#include <mach/peripheral-loader.h>
#include <mach/subsystem_restart.h>
-#include <mach/peripheral-loader.h>
#include <mach/msm_smsm.h>
#include "peripheral-loader.h"
@@ -74,7 +71,6 @@
void __iomem *base;
void __iomem *reset_base;
void __iomem *axi_halt_base;
- unsigned long start_addr;
struct pil_device *pil;
struct pil_desc desc;
struct subsys_device *subsys;
@@ -116,22 +112,13 @@
clk_disable_unprepare(drv->cxo);
}
-static int pil_pronto_init_image(struct pil_desc *pil, const u8 *metadata,
- size_t size)
-{
- const struct elf32_hdr *ehdr = (struct elf32_hdr *)metadata;
- struct pronto_data *drv = dev_get_drvdata(pil->dev);
- drv->start_addr = ehdr->e_entry;
- return 0;
-}
-
static int pil_pronto_reset(struct pil_desc *pil)
{
u32 reg;
int rc;
struct pronto_data *drv = dev_get_drvdata(pil->dev);
void __iomem *base = drv->base;
- unsigned long start_addr = drv->start_addr;
+ unsigned long start_addr = pil_get_entry_addr(pil);
/* Deassert reset to subsystem and wait for propagation */
reg = readl_relaxed(drv->reset_base);
@@ -234,7 +221,6 @@
}
static struct pil_reset_ops pil_pronto_ops = {
- .init_image = pil_pronto_init_image,
.auth_and_reset = pil_pronto_reset,
.shutdown = pil_pronto_shutdown,
.proxy_vote = pil_pronto_make_proxy_vote,
@@ -245,19 +231,14 @@
static int pronto_start(const struct subsys_desc *desc)
{
- void *ret;
struct pronto_data *drv = subsys_to_drv(desc);
-
- ret = pil_get(drv->desc.name);
- if (IS_ERR(ret))
- return PTR_ERR(ret);
- return 0;
+ return pil_boot(&drv->desc);
}
static void pronto_stop(const struct subsys_desc *desc)
{
struct pronto_data *drv = subsys_to_drv(desc);
- pil_put(drv->pil);
+ pil_shutdown(&drv->desc);
}
static void log_wcnss_sfr(void)
@@ -338,7 +319,7 @@
{
struct pronto_data *drv = subsys_to_drv(subsys);
- pil_force_shutdown("wcnss");
+ pil_shutdown(&drv->desc);
flush_delayed_work(&drv->cancel_vote_work);
wcnss_flush_delayed_boot_votes();
disable_irq_nosync(drv->irq);
@@ -358,7 +339,9 @@
WCNSS_WLAN_SWITCH_ON);
if (!ret) {
msleep(1000);
- pil_force_boot("wcnss");
+ ret = pil_boot(&drv->desc);
+ if (ret)
+ return ret;
}
drv->restart_inprogress = false;
enable_irq(drv->irq);
@@ -389,10 +372,6 @@
int ret;
uint32_t regval;
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pmu_base");
- if (!res)
- return -EINVAL;
-
drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
if (!drv)
return -ENOMEM;
@@ -402,23 +381,20 @@
if (drv->irq < 0)
return drv->irq;
- drv->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pmu_base");
+ drv->base = devm_request_and_ioremap(&pdev->dev, res);
if (!drv->base)
return -ENOMEM;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "clk_base");
- if (!res)
- return -EINVAL;
-
- drv->reset_base = devm_ioremap(&pdev->dev, res->start,
- resource_size(res));
+ drv->reset_base = devm_request_and_ioremap(&pdev->dev, res);
+ if (!drv->reset_base)
+ return -ENOMEM;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "halt_base");
- if (!res)
- return -EINVAL;
-
- drv->axi_halt_base = devm_ioremap(&pdev->dev, res->start,
- resource_size(res));
+ drv->axi_halt_base = devm_request_and_ioremap(&pdev->dev, res);
+ if (!drv->axi_halt_base)
+ return -ENOMEM;
desc = &drv->desc;
ret = of_property_read_string(pdev->dev.of_node, "qcom,firmware-name",
@@ -456,9 +432,9 @@
if (IS_ERR(drv->cxo))
return PTR_ERR(drv->cxo);
- drv->pil = msm_pil_register(desc);
- if (IS_ERR(drv->pil))
- return PTR_ERR(drv->pil);
+ ret = pil_desc_init(desc);
+ if (ret)
+ return ret;
ret = smsm_state_cb_register(SMSM_WCNSS_STATE, SMSM_RESET,
smsm_state_cb_hdlr, drv);
@@ -502,7 +478,7 @@
smsm_state_cb_deregister(SMSM_WCNSS_STATE, SMSM_RESET,
smsm_state_cb_hdlr, drv);
err_smsm:
- msm_pil_unregister(drv->pil);
+ pil_desc_release(desc);
return ret;
}
@@ -512,7 +488,7 @@
subsys_unregister(drv->subsys);
smsm_state_cb_deregister(SMSM_WCNSS_STATE, SMSM_RESET,
smsm_state_cb_hdlr, drv);
- msm_pil_unregister(drv->pil);
+ pil_desc_release(&drv->desc);
return 0;
}
diff --git a/arch/arm/mach-msm/pil-q6v3.c b/arch/arm/mach-msm/pil-q6v3.c
index 9de9c60..d7e712c 100644
--- a/arch/arm/mach-msm/pil-q6v3.c
+++ b/arch/arm/mach-msm/pil-q6v3.c
@@ -16,16 +16,13 @@
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/delay.h>
-#include <linux/elf.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h>
-#include <mach/msm_iomap.h>
#include <mach/subsystem_restart.h>
#include <mach/scm.h>
-#include <mach/peripheral-loader.h>
#include "ramdump.h"
#include "peripheral-loader.h"
@@ -35,7 +32,7 @@
#define QDSP6SS_STRAP_TCM 0x001C
#define QDSP6SS_STRAP_AHB 0x0020
-#define LCC_Q6_FUNC (MSM_LPASS_CLK_CTL_BASE + 0x001C)
+#define LCC_Q6_FUNC 0x001C
#define LV_EN BIT(27)
#define STOP_CORE BIT(26)
#define CLAMP_IO BIT(25)
@@ -71,9 +68,9 @@
/**
* struct q6v3_data - LPASS driver data
* @base: register base
+ * @cbase: clock base
* @wk_base: wakeup register base
* @wd_base: watchdog register base
- * @start_addr: address that processor starts running at
* @irq: watchdog irq
* @pil: peripheral handle
* @subsys: subsystem restart handle
@@ -84,11 +81,11 @@
*/
struct q6v3_data {
void __iomem *base;
+ void __iomem *cbase;
void __iomem *wk_base;
void __iomem *wd_base;
- unsigned long start_addr;
int irq;
- struct pil_device *pil;
+ struct pil_desc pil_desc;
struct subsys_device *subsys;
struct subsys_desc subsys_desc;
struct work_struct fatal_wrk;
@@ -96,15 +93,6 @@
struct ramdump_device *ramdump_dev;
};
-static int pil_q6v3_init_image(struct pil_desc *pil, const u8 *metadata,
- size_t size)
-{
- const struct elf32_hdr *ehdr = (struct elf32_hdr *)metadata;
- struct q6v3_data *drv = dev_get_drvdata(pil->dev);
- drv->start_addr = ehdr->e_entry;
- return 0;
-}
-
static void pil_q6v3_remove_proxy_votes(struct pil_desc *pil)
{
struct q6v3_data *drv = dev_get_drvdata(pil->dev);
@@ -128,13 +116,14 @@
{
u32 reg;
struct q6v3_data *drv = dev_get_drvdata(pil->dev);
+ unsigned long start_addr = pil_get_entry_addr(pil);
/* Put Q6 into reset */
- reg = readl_relaxed(LCC_Q6_FUNC);
+ reg = readl_relaxed(drv->cbase + LCC_Q6_FUNC);
reg |= Q6SS_SS_ARES | Q6SS_ISDB_ARES | Q6SS_ETM_ARES | STOP_CORE |
CORE_ARES;
reg &= ~CORE_GFM4_CLK_EN;
- writel_relaxed(reg, LCC_Q6_FUNC);
+ writel_relaxed(reg, drv->cbase + LCC_Q6_FUNC);
/* Wait 8 AHB cycles for Q6 to be fully reset (AHB = 1.5Mhz) */
usleep_range(20, 30);
@@ -142,17 +131,17 @@
/* Turn on Q6 memory */
reg |= CORE_GFM4_CLK_EN | CORE_L1_MEM_CORE_EN | CORE_TCM_MEM_CORE_EN |
CORE_TCM_MEM_PERPH_EN;
- writel_relaxed(reg, LCC_Q6_FUNC);
+ writel_relaxed(reg, drv->cbase + LCC_Q6_FUNC);
/* Turn on Q6 core clocks and take core out of reset */
reg &= ~(CLAMP_IO | Q6SS_SS_ARES | Q6SS_ISDB_ARES | Q6SS_ETM_ARES |
CORE_ARES);
- writel_relaxed(reg, LCC_Q6_FUNC);
+ writel_relaxed(reg, drv->cbase + LCC_Q6_FUNC);
/* Wait for clocks to be enabled */
mb();
/* Program boot address */
- writel_relaxed((drv->start_addr >> 12) & 0xFFFFF,
+ writel_relaxed((start_addr >> 12) & 0xFFFFF,
drv->base + QDSP6SS_RST_EVB);
writel_relaxed(Q6_STRAP_TCM_CONFIG | Q6_STRAP_TCM_BASE,
@@ -165,7 +154,7 @@
/* Start Q6 instruction execution */
reg &= ~STOP_CORE;
- writel_relaxed(reg, LCC_Q6_FUNC);
+ writel_relaxed(reg, drv->cbase + LCC_Q6_FUNC);
return 0;
}
@@ -173,13 +162,14 @@
static int pil_q6v3_shutdown(struct pil_desc *pil)
{
u32 reg;
+ struct q6v3_data *drv = dev_get_drvdata(pil->dev);
/* Put Q6 into reset */
- reg = readl_relaxed(LCC_Q6_FUNC);
+ reg = readl_relaxed(drv->cbase + LCC_Q6_FUNC);
reg |= Q6SS_SS_ARES | Q6SS_ISDB_ARES | Q6SS_ETM_ARES | STOP_CORE |
CORE_ARES;
reg &= ~CORE_GFM4_CLK_EN;
- writel_relaxed(reg, LCC_Q6_FUNC);
+ writel_relaxed(reg, drv->cbase + LCC_Q6_FUNC);
/* Wait 8 AHB cycles for Q6 to be fully reset (AHB = 1.5Mhz) */
usleep_range(20, 30);
@@ -187,16 +177,15 @@
/* Turn off Q6 memory */
reg &= ~(CORE_L1_MEM_CORE_EN | CORE_TCM_MEM_CORE_EN |
CORE_TCM_MEM_PERPH_EN);
- writel_relaxed(reg, LCC_Q6_FUNC);
+ writel_relaxed(reg, drv->cbase + LCC_Q6_FUNC);
reg |= CLAMP_IO;
- writel_relaxed(reg, LCC_Q6_FUNC);
+ writel_relaxed(reg, drv->cbase + LCC_Q6_FUNC);
return 0;
}
static struct pil_reset_ops pil_q6v3_ops = {
- .init_image = pil_q6v3_init_image,
.auth_and_reset = pil_q6v3_reset,
.shutdown = pil_q6v3_shutdown,
.proxy_vote = pil_q6v3_make_proxy_votes,
@@ -250,14 +239,10 @@
static int lpass_q6_start(const struct subsys_desc *subsys)
{
- void *ret;
struct q6v3_data *drv;
drv = container_of(subsys, struct q6v3_data, subsys_desc);
- ret = pil_get("q6");
- if (IS_ERR(ret))
- return PTR_ERR(ret);
- return 0;
+ return pil_boot(&drv->pil_desc);
}
static void lpass_q6_stop(const struct subsys_desc *subsys)
@@ -265,7 +250,7 @@
struct q6v3_data *drv;
drv = container_of(subsys, struct q6v3_data, subsys_desc);
- pil_put(drv->pil);
+ pil_shutdown(&drv->pil_desc);
}
static int lpass_q6_shutdown(const struct subsys_desc *subsys)
@@ -277,7 +262,7 @@
writel_relaxed(0x0, drv->wd_base + 0x24);
mb();
- pil_force_shutdown("q6");
+ pil_shutdown(&drv->pil_desc);
disable_irq_nosync(drv->irq);
return 0;
@@ -289,7 +274,7 @@
int ret;
drv = container_of(subsys, struct q6v3_data, subsys_desc);
- ret = pil_force_boot("q6");
+ ret = pil_boot(&drv->pil_desc);
enable_irq(drv->irq);
return ret;
}
@@ -338,33 +323,31 @@
struct pil_desc *desc;
int ret;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -EINVAL;
-
drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
if (!drv)
return -ENOMEM;
platform_set_drvdata(pdev, drv);
- drv->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ drv->base = devm_request_and_ioremap(&pdev->dev, res);
if (!drv->base)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (!res)
- return -EINVAL;
-
- drv->wk_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ drv->wk_base = devm_request_and_ioremap(&pdev->dev, res);
if (!drv->wk_base)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+ drv->wd_base = devm_request_and_ioremap(&pdev->dev, res);
+ if (!drv->wd_base)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 3);
if (!res)
return -EINVAL;
-
- drv->wd_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
- if (!drv->wd_base)
+ drv->cbase = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ if (!drv->cbase)
return -ENOMEM;
drv->irq = platform_get_irq(pdev, 0);
@@ -375,10 +358,7 @@
if (IS_ERR(drv->pll))
return PTR_ERR(drv->pll);
- desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL);
- if (!drv)
- return -ENOMEM;
-
+ desc = &drv->pil_desc;
desc->name = "q6";
desc->dev = &pdev->dev;
desc->owner = THIS_MODULE;
@@ -392,11 +372,11 @@
dev_info(&pdev->dev, "using non-secure boot\n");
}
- drv->pil = msm_pil_register(desc);
- if (IS_ERR(drv->pil))
- return PTR_ERR(drv->pil);
+ ret = pil_desc_init(desc);
+ if (ret)
+ return ret;
- drv->subsys_desc.name = "lpass";
+ drv->subsys_desc.name = "adsp";
drv->subsys_desc.dev = &pdev->dev;
drv->subsys_desc.owner = THIS_MODULE;
drv->subsys_desc.start = lpass_q6_start;
@@ -408,7 +388,7 @@
INIT_WORK(&drv->fatal_wrk, q6_fatal_fn);
- drv->ramdump_dev = create_ramdump_device("lpass");
+ drv->ramdump_dev = create_ramdump_device("lpass", &pdev->dev);
if (!drv->ramdump_dev) {
ret = -ENOMEM;
goto err_ramdump;
@@ -433,7 +413,7 @@
err_subsys:
destroy_ramdump_device(drv->ramdump_dev);
err_ramdump:
- msm_pil_unregister(drv->pil);
+ pil_desc_release(desc);
return ret;
}
@@ -442,7 +422,7 @@
struct q6v3_data *drv = platform_get_drvdata(pdev);
subsys_unregister(drv->subsys);
destroy_ramdump_device(drv->ramdump_dev);
- msm_pil_unregister(drv->pil);
+ pil_desc_release(&drv->pil_desc);
return 0;
}
diff --git a/arch/arm/mach-msm/pil-q6v4-lpass.c b/arch/arm/mach-msm/pil-q6v4-lpass.c
index c32cf5c..1e6c1f6 100644
--- a/arch/arm/mach-msm/pil-q6v4-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v4-lpass.c
@@ -22,7 +22,6 @@
#include <linux/delay.h>
#include <mach/scm.h>
-#include <mach/peripheral-loader.h>
#include <mach/subsystem_restart.h>
#include <mach/subsystem_notif.h>
@@ -43,7 +42,6 @@
void *ramdump_dev;
struct work_struct work;
int loadable;
- void *pil;
};
static int pil_q6v4_lpass_boot(struct pil_desc *pil)
@@ -71,7 +69,6 @@
}
static struct pil_reset_ops pil_q6v4_lpass_ops = {
- .init_image = pil_q6v4_init_image,
.auth_and_reset = pil_q6v4_lpass_boot,
.shutdown = pil_q6v4_lpass_shutdown,
.proxy_vote = pil_q6v4_make_proxy_votes,
@@ -197,19 +194,17 @@
{
struct lpass_q6v4 *drv = subsys_to_lpass(desc);
- if (drv->loadable) {
- drv->pil = pil_get("q6");
- if (IS_ERR(drv->pil))
- return PTR_ERR(drv->pil);
- }
+ if (drv->loadable)
+ return pil_boot(&drv->q6.desc);
return 0;
}
static void lpass_stop(const struct subsys_desc *desc)
{
struct lpass_q6v4 *drv = subsys_to_lpass(desc);
+
if (drv->loadable)
- pil_put(drv->pil);
+ pil_shutdown(&drv->q6.desc);
}
static int lpass_shutdown(const struct subsys_desc *subsys)
@@ -218,7 +213,7 @@
send_q6_nmi();
if (drv->loadable)
- pil_force_shutdown("q6");
+ pil_shutdown(&drv->q6.desc);
disable_irq_nosync(drv->q6.wdog_irq);
return 0;
@@ -230,7 +225,7 @@
int ret = 0;
if (drv->loadable)
- ret = pil_force_boot("q6");
+ ret = pil_boot(&drv->q6.desc);
enable_irq(drv->q6.wdog_irq);
return ret;
@@ -291,10 +286,7 @@
drv->loadable = !!pdata; /* No pdata = don't use PIL */
if (drv->loadable) {
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -EINVAL;
- q6->base = devm_ioremap(&pdev->dev, res->start,
- resource_size(res));
+ q6->base = devm_request_and_ioremap(&pdev->dev, res);
if (!q6->base)
return -ENOMEM;
@@ -320,12 +312,12 @@
dev_info(&pdev->dev, "using non-secure boot\n");
}
- q6->pil = msm_pil_register(desc);
- if (IS_ERR(q6->pil))
- return PTR_ERR(q6->pil);
+ ret = pil_desc_init(desc);
+ if (ret)
+ return ret;
}
- drv->subsys_desc.name = "lpass";
+ drv->subsys_desc.name = "adsp";
drv->subsys_desc.dev = &pdev->dev;
drv->subsys_desc.owner = THIS_MODULE;
drv->subsys_desc.start = lpass_start;
@@ -337,7 +329,7 @@
INIT_WORK(&drv->work, lpass_fatal_fn);
- drv->ramdump_dev = create_ramdump_device("lpass");
+ drv->ramdump_dev = create_ramdump_device("lpass", &pdev->dev);
if (!drv->ramdump_dev) {
ret = -ENOMEM;
goto err_ramdump;
@@ -385,7 +377,7 @@
destroy_ramdump_device(drv->ramdump_dev);
err_ramdump:
if (drv->loadable)
- msm_pil_unregister(q6->pil);
+ pil_desc_release(desc);
return ret;
}
@@ -399,7 +391,7 @@
subsys_unregister(drv->subsys);
destroy_ramdump_device(drv->ramdump_dev);
if (drv->loadable)
- msm_pil_unregister(drv->q6.pil);
+ pil_desc_release(&drv->q6.desc);
return 0;
}
diff --git a/arch/arm/mach-msm/pil-q6v4-mss.c b/arch/arm/mach-msm/pil-q6v4-mss.c
index aa59bbd..ee01f04 100644
--- a/arch/arm/mach-msm/pil-q6v4-mss.c
+++ b/arch/arm/mach-msm/pil-q6v4-mss.c
@@ -20,10 +20,8 @@
#include <linux/clk.h>
#include <linux/interrupt.h>
-#include <mach/msm_iomap.h>
#include <mach/subsystem_restart.h>
#include <mach/msm_smsm.h>
-#include <mach/peripheral-loader.h>
#include "smd_private.h"
#include "ramdump.h"
@@ -31,16 +29,17 @@
#include "pil-q6v4.h"
#include "scm-pas.h"
-#define MSS_S_HCLK_CTL (MSM_CLK_CTL_BASE + 0x2C70)
-#define MSS_SLP_CLK_CTL (MSM_CLK_CTL_BASE + 0x2C60)
-#define SFAB_MSS_M_ACLK_CTL (MSM_CLK_CTL_BASE + 0x2340)
-#define SFAB_MSS_S_HCLK_CTL (MSM_CLK_CTL_BASE + 0x2C00)
-#define MSS_RESET (MSM_CLK_CTL_BASE + 0x2C64)
+#define MSS_S_HCLK_CTL 0x2C70
+#define MSS_SLP_CLK_CTL 0x2C60
+#define SFAB_MSS_M_ACLK_CTL 0x2340
+#define SFAB_MSS_S_HCLK_CTL 0x2C00
+#define MSS_RESET 0x2C64
struct q6v4_modem {
struct q6v4_data q6_fw;
struct q6v4_data q6_sw;
void __iomem *modem_base;
+ void __iomem *cbase;
void *fw_ramdump_dev;
void *sw_ramdump_dev;
void *smem_ramdump_dev;
@@ -55,21 +54,22 @@
static unsigned pil_q6v4_modem_count;
/* Bring modem subsystem out of reset */
-static void pil_q6v4_init_modem(void __iomem *base, void __iomem *jtag_clk)
+static void pil_q6v4_init_modem(void __iomem *base, void __iomem *cbase,
+ void __iomem *jtag_clk)
{
mutex_lock(&pil_q6v4_modem_lock);
if (!pil_q6v4_modem_count) {
/* Enable MSS clocks */
- writel_relaxed(0x10, SFAB_MSS_M_ACLK_CTL);
- writel_relaxed(0x10, SFAB_MSS_S_HCLK_CTL);
- writel_relaxed(0x10, MSS_S_HCLK_CTL);
- writel_relaxed(0x10, MSS_SLP_CLK_CTL);
+ writel_relaxed(0x10, cbase + SFAB_MSS_M_ACLK_CTL);
+ writel_relaxed(0x10, cbase + SFAB_MSS_S_HCLK_CTL);
+ writel_relaxed(0x10, cbase + MSS_S_HCLK_CTL);
+ writel_relaxed(0x10, cbase + MSS_SLP_CLK_CTL);
/* Wait for clocks to enable */
mb();
udelay(10);
/* De-assert MSS reset */
- writel_relaxed(0x0, MSS_RESET);
+ writel_relaxed(0x0, cbase + MSS_RESET);
mb();
udelay(10);
/* Enable MSS */
@@ -85,13 +85,13 @@
}
/* Put modem subsystem back into reset */
-static void pil_q6v4_shutdown_modem(void)
+static void pil_q6v4_shutdown_modem(struct q6v4_modem *mdm)
{
mutex_lock(&pil_q6v4_modem_lock);
if (pil_q6v4_modem_count)
pil_q6v4_modem_count--;
if (pil_q6v4_modem_count == 0)
- writel_relaxed(0x1, MSS_RESET);
+ writel_relaxed(0x1, mdm->cbase + MSS_RESET);
mutex_unlock(&pil_q6v4_modem_lock);
}
@@ -105,25 +105,25 @@
if (err)
return err;
- pil_q6v4_init_modem(mdm->modem_base, drv->jtag_clk_reg);
+ pil_q6v4_init_modem(mdm->modem_base, mdm->cbase, drv->jtag_clk_reg);
return pil_q6v4_boot(pil);
}
static int pil_q6v4_modem_shutdown(struct pil_desc *pil)
{
struct q6v4_data *drv = pil_to_q6v4_data(pil);
+ struct q6v4_modem *mdm = dev_get_drvdata(pil->dev);
int ret;
ret = pil_q6v4_shutdown(pil);
if (ret)
return ret;
- pil_q6v4_shutdown_modem();
+ pil_q6v4_shutdown_modem(mdm);
pil_q6v4_power_down(drv);
return 0;
}
static struct pil_reset_ops pil_q6v4_modem_ops = {
- .init_image = pil_q6v4_init_image,
.auth_and_reset = pil_q6v4_modem_boot,
.shutdown = pil_q6v4_modem_shutdown,
.proxy_vote = pil_q6v4_make_proxy_votes,
@@ -173,20 +173,26 @@
static int modem_start(const struct subsys_desc *desc)
{
struct q6v4_modem *drv = desc_to_modem(desc);
+ int ret = 0;
if (drv->loadable) {
- drv->pil = pil_get("modem");
- if (IS_ERR(drv->pil))
- return PTR_ERR(drv->pil);
+ ret = pil_boot(&drv->q6_fw.desc);
+ if (ret)
+ return ret;
+ ret = pil_boot(&drv->q6_sw.desc);
+ if (ret)
+ pil_shutdown(&drv->q6_fw.desc);
}
- return 0;
+ return ret;
}
static void modem_stop(const struct subsys_desc *desc)
{
struct q6v4_modem *drv = desc_to_modem(desc);
- if (drv->loadable)
- pil_put(drv->pil);
+ if (drv->loadable) {
+ pil_shutdown(&drv->q6_sw.desc);
+ pil_shutdown(&drv->q6_fw.desc);
+ }
}
static int modem_shutdown(const struct subsys_desc *subsys)
@@ -199,8 +205,8 @@
mb();
if (drv->loadable) {
- pil_force_shutdown("modem");
- pil_force_shutdown("modem_fw");
+ pil_shutdown(&drv->q6_sw.desc);
+ pil_shutdown(&drv->q6_fw.desc);
}
disable_irq_nosync(drv->q6_fw.wdog_irq);
@@ -212,10 +218,17 @@
static int modem_powerup(const struct subsys_desc *subsys)
{
struct q6v4_modem *drv = desc_to_modem(subsys);
+ int ret;
if (drv->loadable) {
- pil_force_boot("modem_fw");
- pil_force_boot("modem");
+ ret = pil_boot(&drv->q6_fw.desc);
+ if (ret)
+ return ret;
+ ret = pil_boot(&drv->q6_sw.desc);
+ if (ret) {
+ pil_shutdown(&drv->q6_fw.desc);
+ return ret;
+ }
}
enable_irq(drv->q6_fw.wdog_irq);
enable_irq(drv->q6_sw.wdog_irq);
@@ -299,20 +312,13 @@
struct pil_desc *desc;
struct resource *res;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1 + (i * 2));
- if (!res)
- return -EINVAL;
-
- drv->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 2 + (i * 2));
+ drv->base = devm_request_and_ioremap(&pdev->dev, res);
if (!drv->base)
return -ENOMEM;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 2 + (i * 2));
- if (!res)
- return -EINVAL;
-
- drv->wdog_base = devm_ioremap(&pdev->dev, res->start,
- resource_size(res));
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 3 + (i * 2));
+ drv->wdog_base = devm_request_and_ioremap(&pdev->dev, res);
if (!drv->wdog_base)
return -ENOMEM;
@@ -327,7 +333,6 @@
desc = &drv->desc;
desc->name = pdata->name;
- desc->depends_on = pdata->depends;
desc->dev = &pdev->dev;
desc->owner = THIS_MODULE;
desc->proxy_timeout = 10000;
@@ -396,27 +401,29 @@
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -EINVAL;
-
- drv->modem_base = devm_ioremap(&pdev->dev, res->start,
- resource_size(res));
+ drv->modem_base = devm_request_and_ioremap(&pdev->dev, res);
if (!drv->modem_base)
return -ENOMEM;
- drv_fw->pil = msm_pil_register(&drv_fw->desc);
- if (IS_ERR(drv_fw->pil))
- return PTR_ERR(drv_fw->pil);
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!res)
+ return -EINVAL;
+ drv->cbase = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (!drv->cbase)
+ return -ENOMEM;
- drv_sw->pil = msm_pil_register(&drv_sw->desc);
- if (IS_ERR(drv_sw->pil)) {
- ret = PTR_ERR(drv_sw->pil);
+ ret = pil_desc_init(&drv_fw->desc);
+ if (ret)
+ return ret;
+
+ ret = pil_desc_init(&drv_sw->desc);
+ if (ret)
goto err_pil_sw;
- }
}
drv->subsys_desc.name = "modem";
- drv->subsys_desc.depends_on = "lpass";
+ drv->subsys_desc.depends_on = "adsp";
drv->subsys_desc.dev = &pdev->dev;
drv->subsys_desc.owner = THIS_MODULE;
drv->subsys_desc.start = modem_start;
@@ -426,19 +433,19 @@
drv->subsys_desc.ramdump = modem_ramdump;
drv->subsys_desc.crash_shutdown = modem_crash_shutdown;
- drv->fw_ramdump_dev = create_ramdump_device("modem_fw");
+ drv->fw_ramdump_dev = create_ramdump_device("modem_fw", &pdev->dev);
if (!drv->fw_ramdump_dev) {
ret = -ENOMEM;
goto err_fw_ramdump;
}
- drv->sw_ramdump_dev = create_ramdump_device("modem_sw");
+ drv->sw_ramdump_dev = create_ramdump_device("modem_sw", &pdev->dev);
if (!drv->sw_ramdump_dev) {
ret = -ENOMEM;
goto err_sw_ramdump;
}
- drv->smem_ramdump_dev = create_ramdump_device("smem-modem");
+ drv->smem_ramdump_dev = create_ramdump_device("smem-modem", &pdev->dev);
if (!drv->smem_ramdump_dev) {
ret = -ENOMEM;
goto err_smem_ramdump;
@@ -480,9 +487,9 @@
destroy_ramdump_device(drv->fw_ramdump_dev);
err_fw_ramdump:
if (drv->loadable)
- msm_pil_unregister(drv_sw->pil);
+ pil_desc_release(&drv_sw->desc);
err_pil_sw:
- msm_pil_unregister(drv_fw->pil);
+ pil_desc_release(&drv_fw->desc);
return ret;
}
@@ -497,8 +504,8 @@
destroy_ramdump_device(drv->sw_ramdump_dev);
destroy_ramdump_device(drv->fw_ramdump_dev);
if (drv->loadable) {
- msm_pil_unregister(drv->q6_sw.pil);
- msm_pil_unregister(drv->q6_fw.pil);
+ pil_desc_release(&drv->q6_sw.desc);
+ pil_desc_release(&drv->q6_fw.desc);
}
return 0;
}
diff --git a/arch/arm/mach-msm/pil-q6v4.c b/arch/arm/mach-msm/pil-q6v4.c
index 47033fc..7f04c64 100644
--- a/arch/arm/mach-msm/pil-q6v4.c
+++ b/arch/arm/mach-msm/pil-q6v4.c
@@ -16,7 +16,6 @@
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/regulator/consumer.h>
-#include <linux/elf.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/clk.h>
@@ -52,16 +51,6 @@
#define Q6SS_CLK_ENA BIT(1)
#define Q6SS_SRC_SWITCH_CLK_OVR BIT(8)
-int pil_q6v4_init_image(struct pil_desc *pil, const u8 *metadata,
- size_t size)
-{
- const struct elf32_hdr *ehdr = (struct elf32_hdr *)metadata;
- struct q6v4_data *drv = pil_to_q6v4_data(pil);
- drv->start_addr = ehdr->e_entry;
- return 0;
-}
-EXPORT_SYMBOL(pil_q6v4_init_image);
-
int pil_q6v4_make_proxy_votes(struct pil_desc *pil)
{
const struct q6v4_data *drv = pil_to_q6v4_data(pil);
@@ -141,6 +130,7 @@
{
u32 reg, err;
const struct q6v4_data *drv = pil_to_q6v4_data(pil);
+ unsigned long start_addr = pil_get_entry_addr(pil);
/* Enable Q6 ACLK */
writel_relaxed(0x10, drv->aclk_reg);
@@ -156,7 +146,7 @@
writel_relaxed(reg, drv->base + QDSP6SS_RESET);
/* Program boot address */
- writel_relaxed((drv->start_addr >> 8) & 0xFFFFFF,
+ writel_relaxed((start_addr >> 8) & 0xFFFFFF,
drv->base + QDSP6SS_RST_EVB);
/* Program TCM and AHB address ranges */
diff --git a/arch/arm/mach-msm/pil-q6v4.h b/arch/arm/mach-msm/pil-q6v4.h
index 0395bed..86e55ea 100644
--- a/arch/arm/mach-msm/pil-q6v4.h
+++ b/arch/arm/mach-msm/pil-q6v4.h
@@ -21,7 +21,6 @@
void __iomem *aclk_reg;
void __iomem *jtag_clk_reg;
const char *name;
- const char *depends;
const unsigned pas_id;
int bus_port;
};
@@ -36,7 +35,6 @@
struct q6v4_data {
void __iomem *base;
void __iomem *wdog_base;
- unsigned long start_addr;
unsigned long strap_tcm_base;
unsigned long strap_ahb_upper;
unsigned long strap_ahb_lower;
@@ -51,14 +49,11 @@
bool vreg_enabled;
struct clk *xo;
- struct pil_device *pil;
struct pil_desc desc;
};
#define pil_to_q6v4_data(p) container_of(p, struct q6v4_data, desc)
-extern int pil_q6v4_init_image(struct pil_desc *pil, const u8 *metadata,
- size_t size);
extern int pil_q6v4_make_proxy_votes(struct pil_desc *pil);
extern void pil_q6v4_remove_proxy_votes(struct pil_desc *pil);
extern int pil_q6v4_power_up(struct q6v4_data *drv);
diff --git a/arch/arm/mach-msm/pil-q6v5-lpass.c b/arch/arm/mach-msm/pil-q6v5-lpass.c
index 3c68da0..662377d 100644
--- a/arch/arm/mach-msm/pil-q6v5-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v5-lpass.c
@@ -26,7 +26,6 @@
#include <mach/subsystem_restart.h>
#include <mach/subsystem_notif.h>
#include <mach/scm.h>
-#include <mach/peripheral-loader.h>
#include "peripheral-loader.h"
#include "pil-q6v5.h"
@@ -119,6 +118,7 @@
static int pil_lpass_reset(struct pil_desc *pil)
{
struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc);
+ unsigned long start_addr = pil_get_entry_addr(pil);
int ret;
ret = pil_lpass_enable_clks(drv);
@@ -126,7 +126,7 @@
return ret;
/* Program Image Address */
- writel_relaxed(((drv->start_addr >> 4) & 0x0FFFFFF0),
+ writel_relaxed((start_addr >> 4) & 0x0FFFFFF0,
drv->reg_base + QDSP6SS_RST_EVB);
ret = pil_q6v5_reset(pil);
@@ -141,7 +141,6 @@
}
static struct pil_reset_ops pil_lpass_ops = {
- .init_image = pil_q6v5_init_image,
.proxy_vote = pil_q6v5_make_proxy_votes,
.proxy_unvote = pil_q6v5_remove_proxy_votes,
.auth_and_reset = pil_lpass_reset,
@@ -286,7 +285,7 @@
send_q6_nmi();
/* The write needs to go through before the q6 is shutdown. */
mb();
- pil_force_shutdown("adsp");
+ pil_shutdown(&drv->q6->desc);
disable_irq_nosync(drv->wdog_irq);
return 0;
@@ -302,7 +301,7 @@
msleep(10000);
}
- ret = pil_force_boot("adsp");
+ ret = pil_boot(&drv->q6->desc);
enable_irq(drv->wdog_irq);
return ret;
@@ -339,19 +338,15 @@
static int lpass_start(const struct subsys_desc *desc)
{
- void *ret;
struct lpass_data *drv = subsys_to_drv(desc);
- ret = pil_get(drv->q6->desc.name);
- if (IS_ERR(ret))
- return PTR_ERR(ret);
- return 0;
+ return pil_boot(&drv->q6->desc);
}
static void lpass_stop(const struct subsys_desc *desc)
{
struct lpass_data *drv = subsys_to_drv(desc);
- pil_put(drv->q6->pil);
+ pil_shutdown(&drv->q6->desc);
}
static int __devinit pil_lpass_driver_probe(struct platform_device *pdev)
@@ -403,9 +398,9 @@
dev_info(&pdev->dev, "using non-secure boot\n");
}
- drv->q6->pil = msm_pil_register(desc);
- if (IS_ERR(drv->q6->pil))
- return PTR_ERR(drv->q6->pil);
+ ret = pil_desc_init(desc);
+ if (ret)
+ return ret;
drv->subsys_desc.name = desc->name;
drv->subsys_desc.owner = THIS_MODULE;
@@ -419,7 +414,7 @@
INIT_WORK(&drv->work, adsp_fatal_fn);
- drv->ramdump_dev = create_ramdump_device("adsp");
+ drv->ramdump_dev = create_ramdump_device("adsp", &pdev->dev);
if (!drv->ramdump_dev) {
ret = -ENOMEM;
goto err_ramdump;
@@ -464,7 +459,7 @@
err_subsys:
destroy_ramdump_device(drv->ramdump_dev);
err_ramdump:
- msm_pil_unregister(drv->q6->pil);
+ pil_desc_release(desc);
return 0;
}
@@ -477,7 +472,7 @@
adsp_smsm_state_cb, drv);
subsys_unregister(drv->subsys);
destroy_ramdump_device(drv->ramdump_dev);
- msm_pil_unregister(drv->q6->pil);
+ pil_desc_release(&drv->q6->desc);
return 0;
}
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index 8a02251..2e25076 100644
--- a/arch/arm/mach-msm/pil-q6v5-mss.c
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -17,7 +17,6 @@
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/ioport.h>
-#include <linux/elf.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/clk.h>
@@ -26,7 +25,6 @@
#include <linux/regulator/consumer.h>
#include <linux/interrupt.h>
-#include <mach/peripheral-loader.h>
#include <mach/subsystem_restart.h>
#include <mach/clk.h>
#include <mach/msm_smsm.h>
@@ -73,7 +71,6 @@
void __iomem *rmb_base;
void __iomem *io_clamp_reg;
unsigned long metadata_phys;
- struct pil_device *pil;
struct pil_desc desc;
struct subsys_device *subsys;
struct subsys_desc subsys_desc;
@@ -209,6 +206,7 @@
struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc);
struct platform_device *pdev = to_platform_device(pil->dev);
struct mba_data *mba = platform_get_drvdata(pdev);
+ unsigned long start_addr = pil_get_entry_addr(pil);
int ret;
/* Deassert reset to subsystem and wait for propagation */
@@ -230,11 +228,11 @@
/* Program Image Address */
if (mba->self_auth) {
- writel_relaxed(drv->start_addr, mba->rmb_base + RMB_MBA_IMAGE);
+ writel_relaxed(start_addr, mba->rmb_base + RMB_MBA_IMAGE);
/* Ensure write to RMB base occurs before reset is released. */
mb();
} else {
- writel_relaxed((drv->start_addr >> 4) & 0x0FFFFFF0,
+ writel_relaxed((start_addr >> 4) & 0x0FFFFFF0,
drv->reg_base + QDSP6SS_RST_EVB);
}
@@ -264,7 +262,6 @@
}
static struct pil_reset_ops pil_mss_ops = {
- .init_image = pil_q6v5_init_image,
.proxy_vote = pil_q6v5_make_proxy_votes,
.proxy_unvote = pil_q6v5_remove_proxy_votes,
.auth_and_reset = pil_mss_reset,
@@ -365,18 +362,12 @@
return ret;
}
-static int pil_mba_shutdown(struct pil_desc *pil)
-{
- return 0;
-}
-
static struct pil_reset_ops pil_mba_ops = {
.init_image = pil_mba_init_image,
.proxy_vote = pil_mba_make_proxy_votes,
.proxy_unvote = pil_mba_remove_proxy_votes,
.verify_blob = pil_mba_verify_blob,
.auth_and_reset = pil_mba_auth,
- .shutdown = pil_mba_shutdown,
};
#define subsys_to_drv(d) container_of(d, struct mba_data, subsys_desc)
@@ -426,23 +417,30 @@
static int modem_shutdown(const struct subsys_desc *subsys)
{
- pil_force_shutdown("modem");
- pil_force_shutdown("mba");
+ struct mba_data *drv = subsys_to_drv(subsys);
+
+ /* MBA doesn't support shutdown */
+ pil_shutdown(&drv->q6->desc);
return 0;
}
static int modem_powerup(const struct subsys_desc *subsys)
{
struct mba_data *drv = subsys_to_drv(subsys);
+ int ret;
/*
* At this time, the modem is shutdown. Therefore this function cannot
* run concurrently with either the watchdog bite error handler or the
* SMSM callback, making it safe to unset the flag below.
*/
drv->ignore_errors = false;
- pil_force_boot("mba");
- pil_force_boot("modem");
- return 0;
+ ret = pil_boot(&drv->q6->desc);
+ if (ret)
+ return ret;
+ ret = pil_boot(&drv->desc);
+ if (ret)
+ pil_shutdown(&drv->q6->desc);
+ return ret;
}
static void modem_crash_shutdown(const struct subsys_desc *subsys)
@@ -468,7 +466,9 @@
if (!enable)
return 0;
- pil_force_boot("mba");
+ ret = pil_boot(&drv->q6->desc);
+ if (ret)
+ return ret;
ret = do_ramdump(drv->ramdump_dev, modem_segments,
ARRAY_SIZE(modem_segments));
@@ -485,7 +485,7 @@
}
out:
- pil_force_shutdown("mba");
+ pil_shutdown(&drv->q6->desc);
return ret;
}
@@ -501,19 +501,23 @@
static int mss_start(const struct subsys_desc *desc)
{
- void *ret;
+ int ret;
struct mba_data *drv = subsys_to_drv(desc);
- ret = pil_get(drv->desc.name);
- if (IS_ERR(ret))
- return PTR_ERR(ret);
- return 0;
+ ret = pil_boot(&drv->q6->desc);
+ if (ret)
+ return ret;
+ ret = pil_boot(&drv->desc);
+ if (ret)
+ pil_shutdown(&drv->q6->desc);
+ return ret;
}
static void mss_stop(const struct subsys_desc *desc)
{
struct mba_data *drv = subsys_to_drv(desc);
- pil_put(drv->pil);
+ /* MBA doesn't support shutdown */
+ pil_shutdown(&drv->q6->desc);
}
static int __devinit pil_mss_driver_probe(struct platform_device *pdev)
@@ -548,8 +552,7 @@
if (drv->self_auth) {
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"rmb_base");
- drv->rmb_base = devm_ioremap(&pdev->dev, res->start,
- resource_size(res));
+ drv->rmb_base = devm_request_and_ioremap(&pdev->dev, res);
if (!drv->rmb_base)
return -ENOMEM;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
@@ -564,8 +567,7 @@
}
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "restart_reg");
- q6->restart_reg = devm_ioremap(&pdev->dev, res->start,
- resource_size(res));
+ q6->restart_reg = devm_request_and_ioremap(&pdev->dev, res);
if (!q6->restart_reg)
return -ENOMEM;
@@ -595,23 +597,20 @@
if (IS_ERR(q6->rom_clk))
return PTR_ERR(q6->rom_clk);
- q6->pil = msm_pil_register(q6_desc);
- if (IS_ERR(q6->pil))
- return PTR_ERR(q6->pil);
+ ret = pil_desc_init(q6_desc);
+ if (ret)
+ return ret;
mba_desc = &drv->desc;
mba_desc->name = "modem";
- mba_desc->depends_on = "mba";
mba_desc->dev = &pdev->dev;
mba_desc->ops = &pil_mba_ops;
mba_desc->owner = THIS_MODULE;
mba_desc->proxy_timeout = PROXY_TIMEOUT_MS;
- drv->pil = msm_pil_register(mba_desc);
- if (IS_ERR(drv->pil)) {
- ret = PTR_ERR(drv->pil);
+ ret = pil_desc_init(mba_desc);
+ if (ret)
goto err_mba_desc;
- }
drv->subsys_desc.name = "modem";
drv->subsys_desc.dev = &pdev->dev;
@@ -623,7 +622,7 @@
drv->subsys_desc.start = mss_start;
drv->subsys_desc.stop = mss_stop;
- drv->ramdump_dev = create_ramdump_device("modem");
+ drv->ramdump_dev = create_ramdump_device("modem", &pdev->dev);
if (!drv->ramdump_dev) {
pr_err("%s: Unable to create a modem ramdump device.\n",
__func__);
@@ -631,7 +630,7 @@
goto err_ramdump;
}
- drv->smem_ramdump_dev = create_ramdump_device("smem-modem");
+ drv->smem_ramdump_dev = create_ramdump_device("smem-modem", &pdev->dev);
if (!drv->smem_ramdump_dev) {
pr_err("%s: Unable to create an smem ramdump device.\n",
__func__);
@@ -668,9 +667,9 @@
err_ramdump_smem:
destroy_ramdump_device(drv->ramdump_dev);
err_ramdump:
- msm_pil_unregister(drv->pil);
+ pil_desc_release(mba_desc);
err_mba_desc:
- msm_pil_unregister(q6->pil);
+ pil_desc_release(q6_desc);
return ret;
}
@@ -682,8 +681,8 @@
subsys_unregister(drv->subsys);
destroy_ramdump_device(drv->smem_ramdump_dev);
destroy_ramdump_device(drv->ramdump_dev);
- msm_pil_unregister(drv->pil);
- msm_pil_unregister(drv->q6->pil);
+ pil_desc_release(&drv->desc);
+ pil_desc_release(&drv->q6->desc);
return 0;
}
diff --git a/arch/arm/mach-msm/pil-q6v5.c b/arch/arm/mach-msm/pil-q6v5.c
index 70a12de..ab88749 100644
--- a/arch/arm/mach-msm/pil-q6v5.c
+++ b/arch/arm/mach-msm/pil-q6v5.c
@@ -16,7 +16,6 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/iopoll.h>
-#include <linux/elf.h>
#include <linux/err.h>
#include <linux/of.h>
#include <linux/clk.h>
@@ -100,16 +99,6 @@
}
EXPORT_SYMBOL(pil_q6v5_halt_axi_port);
-int pil_q6v5_init_image(struct pil_desc *pil, const u8 *metadata,
- size_t size)
-{
- const struct elf32_hdr *ehdr = (struct elf32_hdr *)metadata;
- struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc);
- drv->start_addr = ehdr->e_entry;
- return 0;
-}
-EXPORT_SYMBOL(pil_q6v5_init_image);
-
void pil_q6v5_shutdown(struct pil_desc *pil)
{
u32 val;
@@ -205,12 +194,10 @@
return ERR_PTR(-ENOMEM);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qdsp6_base");
- if (!res)
- return ERR_PTR(-EINVAL);
- drv->reg_base = devm_ioremap(&pdev->dev, res->start,
- resource_size(res));
+ drv->reg_base = devm_request_and_ioremap(&pdev->dev, res);
if (!drv->reg_base)
return ERR_PTR(-ENOMEM);
+
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "halt_base");
drv->axi_halt_base = devm_ioremap(&pdev->dev, res->start,
resource_size(res));
diff --git a/arch/arm/mach-msm/pil-q6v5.h b/arch/arm/mach-msm/pil-q6v5.h
index 340b5e3..ecdaf9b 100644
--- a/arch/arm/mach-msm/pil-q6v5.h
+++ b/arch/arm/mach-msm/pil-q6v5.h
@@ -30,18 +30,14 @@
struct clk *rom_clk; /* Boot ROM */
void __iomem *axi_halt_base;
void __iomem *restart_reg;
- unsigned long start_addr;
struct regulator *vreg;
bool is_booted;
- struct pil_device *pil;
struct pil_desc desc;
};
int pil_q6v5_make_proxy_votes(struct pil_desc *pil);
void pil_q6v5_remove_proxy_votes(struct pil_desc *pil);
void pil_q6v5_halt_axi_port(struct pil_desc *pil, void __iomem *halt_base);
-int pil_q6v5_init_image(struct pil_desc *pil, const u8 *metadata,
- size_t size);
void pil_q6v5_shutdown(struct pil_desc *pil);
int pil_q6v5_reset(struct pil_desc *pil);
struct q6v5_data *pil_q6v5_init(struct platform_device *pdev);
diff --git a/arch/arm/mach-msm/pil-riva.c b/arch/arm/mach-msm/pil-riva.c
index a0e39ea..7993090 100644
--- a/arch/arm/mach-msm/pil-riva.c
+++ b/arch/arm/mach-msm/pil-riva.c
@@ -13,7 +13,6 @@
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/io.h>
-#include <linux/elf.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -23,9 +22,7 @@
#include <linux/interrupt.h>
#include <linux/wcnss_wlan.h>
-#include <mach/msm_iomap.h>
#include <mach/subsystem_restart.h>
-#include <mach/peripheral-loader.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
@@ -54,19 +51,18 @@
#define RIVA_PMU_CCPU_BOOT_REMAP_ADDR 0xA0
-#define RIVA_PLL_MODE (MSM_CLK_CTL_BASE + 0x31A0)
+#define RIVA_PLL_MODE 0x31A0
#define PLL_MODE_OUTCTRL BIT(0)
#define PLL_MODE_BYPASSNL BIT(1)
#define PLL_MODE_RESET_N BIT(2)
#define PLL_MODE_REF_XO_SEL 0x30
#define PLL_MODE_REF_XO_SEL_CXO (2 << 4)
#define PLL_MODE_REF_XO_SEL_RF (3 << 4)
-#define RIVA_PLL_L_VAL (MSM_CLK_CTL_BASE + 0x31A4)
-#define RIVA_PLL_M_VAL (MSM_CLK_CTL_BASE + 0x31A8)
-#define RIVA_PLL_N_VAL (MSM_CLK_CTL_BASE + 0x31Ac)
-#define RIVA_PLL_CONFIG (MSM_CLK_CTL_BASE + 0x31B4)
-#define RIVA_PLL_STATUS (MSM_CLK_CTL_BASE + 0x31B8)
-#define RIVA_RESET (MSM_CLK_CTL_BASE + 0x35E0)
+#define RIVA_PLL_L_VAL 0x31A4
+#define RIVA_PLL_M_VAL 0x31A8
+#define RIVA_PLL_N_VAL 0x31Ac
+#define RIVA_PLL_CONFIG 0x31B4
+#define RIVA_RESET 0x35E0
#define RIVA_PMU_ROOT_CLK_SEL 0xC8
#define RIVA_PMU_ROOT_CLK_SEL_3 BIT(2)
@@ -84,10 +80,10 @@
struct riva_data {
void __iomem *base;
- unsigned long start_addr;
+ void __iomem *cbase;
struct clk *xo;
struct regulator *pll_supply;
- struct pil_device *pil;
+ struct pil_desc pil_desc;
int irq;
int crash;
int rst_in_progress;
@@ -133,21 +129,13 @@
clk_disable_unprepare(drv->xo);
}
-static int pil_riva_init_image(struct pil_desc *pil, const u8 *metadata,
- size_t size)
-{
- const struct elf32_hdr *ehdr = (struct elf32_hdr *)metadata;
- struct riva_data *drv = dev_get_drvdata(pil->dev);
- drv->start_addr = ehdr->e_entry;
- return 0;
-}
-
static int pil_riva_reset(struct pil_desc *pil)
{
u32 reg, sel;
struct riva_data *drv = dev_get_drvdata(pil->dev);
void __iomem *base = drv->base;
- unsigned long start_addr = drv->start_addr;
+ unsigned long start_addr = pil_get_entry_addr(pil);
+ void __iomem *cbase = drv->cbase;
bool use_cxo = cxo_is_needed(drv);
/* Enable A2XB bridge */
@@ -156,26 +144,26 @@
writel_relaxed(reg, base + RIVA_PMU_A2XB_CFG);
/* Program PLL 13 to 960 MHz */
- reg = readl_relaxed(RIVA_PLL_MODE);
+ reg = readl_relaxed(cbase + RIVA_PLL_MODE);
reg &= ~(PLL_MODE_BYPASSNL | PLL_MODE_OUTCTRL | PLL_MODE_RESET_N);
- writel_relaxed(reg, RIVA_PLL_MODE);
+ writel_relaxed(reg, cbase + RIVA_PLL_MODE);
if (use_cxo)
- writel_relaxed(0x40000C00 | 50, RIVA_PLL_L_VAL);
+ writel_relaxed(0x40000C00 | 50, cbase + RIVA_PLL_L_VAL);
else
- writel_relaxed(0x40000C00 | 40, RIVA_PLL_L_VAL);
- writel_relaxed(0, RIVA_PLL_M_VAL);
- writel_relaxed(1, RIVA_PLL_N_VAL);
- writel_relaxed(0x01495227, RIVA_PLL_CONFIG);
+ writel_relaxed(0x40000C00 | 40, cbase + RIVA_PLL_L_VAL);
+ writel_relaxed(0, cbase + RIVA_PLL_M_VAL);
+ writel_relaxed(1, cbase + RIVA_PLL_N_VAL);
+ writel_relaxed(0x01495227, cbase + RIVA_PLL_CONFIG);
- reg = readl_relaxed(RIVA_PLL_MODE);
+ reg = readl_relaxed(cbase + RIVA_PLL_MODE);
reg &= ~(PLL_MODE_REF_XO_SEL);
reg |= use_cxo ? PLL_MODE_REF_XO_SEL_CXO : PLL_MODE_REF_XO_SEL_RF;
- writel_relaxed(reg, RIVA_PLL_MODE);
+ writel_relaxed(reg, cbase + RIVA_PLL_MODE);
/* Enable PLL 13 */
reg |= PLL_MODE_BYPASSNL;
- writel_relaxed(reg, RIVA_PLL_MODE);
+ writel_relaxed(reg, cbase + RIVA_PLL_MODE);
/*
* H/W requires a 5us delay between disabling the bypass and
@@ -185,9 +173,9 @@
usleep_range(10, 20);
reg |= PLL_MODE_RESET_N;
- writel_relaxed(reg, RIVA_PLL_MODE);
+ writel_relaxed(reg, cbase + RIVA_PLL_MODE);
reg |= PLL_MODE_OUTCTRL;
- writel_relaxed(reg, RIVA_PLL_MODE);
+ writel_relaxed(reg, cbase + RIVA_PLL_MODE);
/* Wait for PLL to settle */
mb();
@@ -241,20 +229,22 @@
static int pil_riva_shutdown(struct pil_desc *pil)
{
+ struct riva_data *drv = dev_get_drvdata(pil->dev);
+ void __iomem *cbase = drv->cbase;
+
/* Assert reset to Riva */
- writel_relaxed(1, RIVA_RESET);
+ writel_relaxed(1, cbase + RIVA_RESET);
mb();
usleep_range(1000, 2000);
/* Deassert reset to Riva */
- writel_relaxed(0, RIVA_RESET);
+ writel_relaxed(0, cbase + RIVA_RESET);
mb();
return 0;
}
static struct pil_reset_ops pil_riva_ops = {
- .init_image = pil_riva_init_image,
.auth_and_reset = pil_riva_reset,
.shutdown = pil_riva_shutdown,
.proxy_vote = pil_riva_make_proxy_vote,
@@ -374,15 +364,10 @@
static int riva_start(const struct subsys_desc *desc)
{
- void *ret;
struct riva_data *drv;
drv = container_of(desc, struct riva_data, subsys_desc);
-
- ret = pil_get("wcnss");
- if (IS_ERR(ret))
- return PTR_ERR(ret);
- return 0;
+ return pil_boot(&drv->pil_desc);
}
static void riva_stop(const struct subsys_desc *desc)
@@ -390,7 +375,7 @@
struct riva_data *drv;
drv = container_of(desc, struct riva_data, subsys_desc);
- pil_put(drv->pil);
+ pil_shutdown(&drv->pil_desc);
}
static int riva_shutdown(const struct subsys_desc *desc)
@@ -398,7 +383,7 @@
struct riva_data *drv;
drv = container_of(desc, struct riva_data, subsys_desc);
- pil_force_shutdown("wcnss");
+ pil_shutdown(&drv->pil_desc);
flush_delayed_work(&drv->cancel_work);
wcnss_flush_delayed_boot_votes();
disable_irq_nosync(drv->irq);
@@ -418,7 +403,7 @@
ret = wcnss_wlan_power(&pdev->dev, pwlanconfig,
WCNSS_WLAN_SWITCH_ON);
if (!ret)
- pil_force_boot("wcnss");
+ pil_boot(&drv->pil_desc);
}
drv->rst_in_progress = 0;
enable_irq(drv->irq);
@@ -467,21 +452,20 @@
struct pil_desc *desc;
int ret;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -EINVAL;
-
drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
if (!drv)
return -ENOMEM;
platform_set_drvdata(pdev, drv);
- drv->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ drv->base = devm_request_and_ioremap(&pdev->dev, res);
if (!drv->base)
return -ENOMEM;
- desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL);
- if (!desc)
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ drv->cbase = devm_request_and_ioremap(&pdev->dev, res);
+ if (!drv->cbase)
return -ENOMEM;
drv->pll_supply = devm_regulator_get(&pdev->dev, "pll_vdd");
@@ -509,6 +493,11 @@
if (drv->irq < 0)
return drv->irq;
+ drv->xo = devm_clk_get(&pdev->dev, "cxo");
+ if (IS_ERR(drv->xo))
+ return PTR_ERR(drv->xo);
+
+ desc = &drv->pil_desc;
desc->name = "wcnss";
desc->dev = &pdev->dev;
desc->owner = THIS_MODULE;
@@ -521,14 +510,7 @@
desc->ops = &pil_riva_ops;
dev_info(&pdev->dev, "using non-secure boot\n");
}
-
- drv->xo = devm_clk_get(&pdev->dev, "cxo");
- if (IS_ERR(drv->xo))
- return PTR_ERR(drv->xo);
-
- drv->pil = msm_pil_register(desc);
- if (IS_ERR(drv->pil))
- return PTR_ERR(drv->pil);
+ ret = pil_desc_init(desc);
ret = smsm_state_cb_register(SMSM_WCNSS_STATE, SMSM_RESET,
smsm_state_cb_hdlr, drv);
@@ -547,7 +529,7 @@
INIT_DELAYED_WORK(&drv->cancel_work, riva_post_bootup);
- drv->ramdump_dev = create_ramdump_device("riva");
+ drv->ramdump_dev = create_ramdump_device("riva", &pdev->dev);
if (!drv->ramdump_dev) {
ret = -ENOMEM;
goto err_ramdump;
@@ -573,7 +555,7 @@
smsm_state_cb_deregister(SMSM_WCNSS_STATE, SMSM_RESET,
smsm_state_cb_hdlr, drv);
err_smsm:
- msm_pil_unregister(drv->pil);
+ pil_desc_release(desc);
return ret;
}
@@ -585,7 +567,7 @@
destroy_ramdump_device(drv->ramdump_dev);
smsm_state_cb_deregister(SMSM_WCNSS_STATE, SMSM_RESET,
smsm_state_cb_hdlr, drv);
- msm_pil_unregister(drv->pil);
+ pil_desc_release(&drv->pil_desc);
return 0;
}
diff --git a/arch/arm/mach-msm/pil-tzapps.c b/arch/arm/mach-msm/pil-tzapps.c
index be78fab..8658e6e 100644
--- a/arch/arm/mach-msm/pil-tzapps.c
+++ b/arch/arm/mach-msm/pil-tzapps.c
@@ -13,17 +13,15 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <linux/elf.h>
#include <linux/err.h>
-#include <mach/peripheral-loader.h>
#include <mach/subsystem_restart.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
struct tzapps_data {
- struct pil_device *pil;
+ struct pil_desc pil_desc;
struct subsys_device *subsys;
struct subsys_desc subsys_desc;
};
@@ -54,44 +52,39 @@
static int tzapps_start(const struct subsys_desc *desc)
{
- void *ret;
+ struct tzapps_data *drv = subsys_to_drv(desc);
- ret = pil_get("tzapps");
- if (IS_ERR(ret))
- return PTR_ERR(ret);
- return 0;
+ return pil_boot(&drv->pil_desc);
}
static void tzapps_stop(const struct subsys_desc *desc)
{
struct tzapps_data *drv = subsys_to_drv(desc);
- pil_put(drv->pil);
+ pil_shutdown(&drv->pil_desc);
}
static int __devinit pil_tzapps_driver_probe(struct platform_device *pdev)
{
struct pil_desc *desc;
struct tzapps_data *drv;
+ int ret;
if (pas_supported(PAS_TZAPPS) < 0)
return -ENOSYS;
- desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL);
- if (!desc)
- return -ENOMEM;
-
drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
if (!drv)
return -ENOMEM;
platform_set_drvdata(pdev, drv);
+ desc = &drv->pil_desc;
desc->name = "tzapps";
desc->dev = &pdev->dev;
desc->ops = &pil_tzapps_ops;
desc->owner = THIS_MODULE;
- drv->pil = msm_pil_register(desc);
- if (IS_ERR(drv->pil))
- return PTR_ERR(drv->pil);
+ ret = pil_desc_init(desc);
+ if (ret)
+ return ret;
drv->subsys_desc.name = "tzapps";
drv->subsys_desc.dev = &pdev->dev;
@@ -101,7 +94,7 @@
drv->subsys = subsys_register(&drv->subsys_desc);
if (IS_ERR(drv->subsys)) {
- msm_pil_unregister(drv->pil);
+ pil_desc_release(desc);
return PTR_ERR(drv->subsys);
}
return 0;
@@ -111,7 +104,7 @@
{
struct tzapps_data *drv = platform_get_drvdata(pdev);
subsys_unregister(drv->subsys);
- msm_pil_unregister(drv->pil);
+ pil_desc_release(&drv->pil_desc);
return 0;
}
diff --git a/arch/arm/mach-msm/pil-venus.c b/arch/arm/mach-msm/pil-venus.c
index e3125cf..47799cc 100644
--- a/arch/arm/mach-msm/pil-venus.c
+++ b/arch/arm/mach-msm/pil-venus.c
@@ -13,7 +13,6 @@
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/io.h>
-#include <linux/elf.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -29,7 +28,6 @@
#include <mach/iommu.h>
#include <mach/iommu_domains.h>
#include <mach/subsystem_restart.h>
-#include <mach/peripheral-loader.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
@@ -67,11 +65,10 @@
struct venus_data {
void __iomem *venus_wrapper_base;
void __iomem *venus_vbif_base;
- struct pil_device *pil;
+ struct pil_desc desc;
struct subsys_device *subsys;
struct subsys_desc subsys_desc;
struct regulator *gdsc;
- phys_addr_t start_addr;
struct clk *clks[ARRAY_SIZE(clk_names)];
struct device *iommu_fw_ctx;
struct iommu_domain *iommu_fw_domain;
@@ -184,22 +181,29 @@
regulator_disable(drv->gdsc);
}
-static int pil_venus_init_image(struct pil_desc *pil, const u8 *metadata,
- size_t size)
+static int pil_venus_mem_setup(struct pil_desc *pil, phys_addr_t addr,
+ size_t size)
{
- const struct elf32_hdr *ehdr = (struct elf32_hdr *)metadata;
+ int domain;
struct venus_data *drv = dev_get_drvdata(pil->dev);
- drv->start_addr = ehdr->e_entry;
-
- if (drv->start_addr < drv->fw_min_paddr ||
- drv->start_addr >= drv->fw_max_paddr) {
- dev_err(pil->dev, "fw start addr is not within valid range\n");
- return -EINVAL;
+ /* TODO: unregister? */
+ if (!drv->venus_domain_num) {
+ size = round_up(size, SZ_4K);
+ domain = venus_register_domain(size);
+ if (domain < 0) {
+ dev_err(pil->dev, "Venus fw iommu domain register failed\n");
+ return -ENODEV;
+ }
+ drv->iommu_fw_domain = msm_get_iommu_domain(domain);
+ if (!drv->iommu_fw_domain) {
+ dev_err(pil->dev, "No iommu fw domain found\n");
+ return -ENODEV;
+ }
+ drv->venus_domain_num = domain;
+ drv->fw_sz = size;
}
- drv->fw_sz = drv->fw_max_paddr - drv->start_addr;
-
return 0;
}
@@ -208,7 +212,7 @@
int rc;
struct venus_data *drv = dev_get_drvdata(pil->dev);
void __iomem *wrapper_base = drv->venus_wrapper_base;
- phys_addr_t pa = drv->start_addr;
+ phys_addr_t pa = pil_get_entry_addr(pil);
unsigned long iova;
/*
@@ -327,7 +331,7 @@
}
static struct pil_reset_ops pil_venus_ops = {
- .init_image = pil_venus_init_image,
+ .mem_setup = pil_venus_mem_setup,
.auth_and_reset = pil_venus_reset,
.shutdown = pil_venus_shutdown,
.proxy_vote = pil_venus_make_proxy_vote,
@@ -389,19 +393,15 @@
static int venus_start(const struct subsys_desc *desc)
{
- void *ret;
struct venus_data *drv = subsys_to_drv(desc);
- ret = pil_get(drv->subsys_desc.name);
- if (IS_ERR(ret))
- return PTR_ERR(ret);
- return 0;
+ return pil_boot(&drv->desc);
}
static void venus_stop(const struct subsys_desc *desc)
{
struct venus_data *drv = subsys_to_drv(desc);
- pil_put(drv->pil);
+ pil_shutdown(&drv->desc);
}
static int __devinit pil_venus_probe(struct platform_device *pdev)
@@ -411,27 +411,20 @@
struct pil_desc *desc;
int rc;
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- "wrapper_base");
- if (!res)
- return -EINVAL;
-
drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
if (!drv)
return -ENOMEM;
platform_set_drvdata(pdev, drv);
- drv->venus_wrapper_base = devm_ioremap(&pdev->dev, res->start,
- resource_size(res));
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "wrapper_base");
+ drv->venus_wrapper_base = devm_request_and_ioremap(&pdev->dev, res);
if (!drv->venus_wrapper_base)
return -ENOMEM;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vbif_base");
- if (!res)
- return -EINVAL;
-
- drv->venus_vbif_base = devm_ioremap(&pdev->dev, res->start,
- resource_size(res));
+ drv->venus_vbif_base = devm_request_and_ioremap(&pdev->dev, res);
if (!drv->venus_vbif_base)
return -ENOMEM;
@@ -451,45 +444,7 @@
return -ENODEV;
}
- /* Get fw address boundaries */
- rc = of_property_read_u32(pdev->dev.of_node,
- "qcom,firmware-max-paddr",
- &drv->fw_max_paddr);
- if (rc) {
- dev_err(&pdev->dev, "Failed to get fw max paddr\n");
- return rc;
- }
-
- rc = of_property_read_u32(pdev->dev.of_node,
- "qcom,firmware-min-paddr",
- &drv->fw_min_paddr);
- if (rc) {
- dev_err(&pdev->dev, "Failed to get fw min paddr\n");
- return rc;
- }
-
- if (drv->fw_max_paddr <= drv->fw_min_paddr) {
- dev_err(&pdev->dev, "Invalid fw max paddr or min paddr\n");
- return -EINVAL;
- }
-
- drv->venus_domain_num =
- venus_register_domain(drv->fw_max_paddr - drv->fw_min_paddr);
- if (drv->venus_domain_num < 0) {
- dev_err(&pdev->dev, "Venus fw iommu domain register failed\n");
- return -ENODEV;
- }
-
- drv->iommu_fw_domain = msm_get_iommu_domain(drv->venus_domain_num);
- if (!drv->iommu_fw_domain) {
- dev_err(&pdev->dev, "No iommu fw domain found\n");
- return -ENODEV;
- }
-
- desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL);
- if (!desc)
- return -ENOMEM;
-
+ desc = &drv->desc;
rc = of_property_read_string(pdev->dev.of_node, "qcom,firmware-name",
&desc->name);
if (rc)
@@ -507,9 +462,9 @@
dev_info(&pdev->dev, "using non-secure boot\n");
}
- drv->pil = msm_pil_register(desc);
- if (IS_ERR(drv->pil))
- return PTR_ERR(drv->pil);
+ rc = pil_desc_init(desc);
+ if (rc)
+ return rc;
drv->subsys_desc.name = desc->name;
drv->subsys_desc.owner = THIS_MODULE;
@@ -519,7 +474,7 @@
drv->subsys = subsys_register(&drv->subsys_desc);
if (IS_ERR(drv->subsys)) {
- msm_pil_unregister(drv->pil);
+ pil_desc_release(desc);
return PTR_ERR(drv->subsys);
}
@@ -530,7 +485,7 @@
{
struct venus_data *drv = platform_get_drvdata(pdev);
subsys_unregister(drv->subsys);
- msm_pil_unregister(drv->pil);
+ pil_desc_release(&drv->desc);
return 0;
}
diff --git a/arch/arm/mach-msm/pil-vidc.c b/arch/arm/mach-msm/pil-vidc.c
index b2609b1..42bb51c 100644
--- a/arch/arm/mach-msm/pil-vidc.c
+++ b/arch/arm/mach-msm/pil-vidc.c
@@ -13,11 +13,9 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <linux/elf.h>
#include <linux/err.h>
#include <linux/clk.h>
-#include <mach/peripheral-loader.h>
#include <mach/subsystem_restart.h>
#include "peripheral-loader.h"
@@ -26,7 +24,7 @@
struct vidc_data {
struct clk *smmu_iface;
struct clk *core;
- struct pil_device *pil;
+ struct pil_desc pil_desc;
struct subsys_device *subsys;
struct subsys_desc subsys_desc;
};
@@ -72,32 +70,25 @@
static int vidc_start(const struct subsys_desc *desc)
{
- void *ret;
-
- ret = pil_get("vidc");
- if (IS_ERR(ret))
- return PTR_ERR(ret);
- return 0;
+ struct vidc_data *drv = subsys_to_drv(desc);
+ return pil_boot(&drv->pil_desc);
}
static void vidc_stop(const struct subsys_desc *desc)
{
struct vidc_data *drv = subsys_to_drv(desc);
- pil_put(drv->pil);
+ pil_shutdown(&drv->pil_desc);
}
static int __devinit pil_vidc_driver_probe(struct platform_device *pdev)
{
struct pil_desc *desc;
struct vidc_data *drv;
+ int ret;
if (pas_supported(PAS_VIDC) < 0)
return -ENOSYS;
- desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL);
- if (!desc)
- return -ENOMEM;
-
drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
if (!drv)
return -ENOMEM;
@@ -111,13 +102,14 @@
if (IS_ERR(drv->core))
return PTR_ERR(drv->core);
+ desc = &drv->pil_desc;
desc->name = "vidc";
desc->dev = &pdev->dev;
desc->ops = &pil_vidc_ops;
desc->owner = THIS_MODULE;
- drv->pil = msm_pil_register(desc);
- if (IS_ERR(drv->pil))
- return PTR_ERR(drv->pil);
+ ret = pil_desc_init(desc);
+ if (ret)
+ return ret;
drv->subsys_desc.name = "vidc";
drv->subsys_desc.dev = &pdev->dev;
@@ -127,7 +119,7 @@
drv->subsys = subsys_register(&drv->subsys_desc);
if (IS_ERR(drv->subsys)) {
- msm_pil_unregister(drv->pil);
+ pil_desc_release(desc);
return PTR_ERR(drv->subsys);
}
return 0;
@@ -137,7 +129,7 @@
{
struct vidc_data *drv = platform_get_drvdata(pdev);
subsys_unregister(drv->subsys);
- msm_pil_unregister(drv->pil);
+ pil_desc_release(&drv->pil_desc);
return 0;
}
diff --git a/arch/arm/mach-msm/platsmp-8910.c b/arch/arm/mach-msm/platsmp-8910.c
index 5d055bd..af2f496 100644
--- a/arch/arm/mach-msm/platsmp-8910.c
+++ b/arch/arm/mach-msm/platsmp-8910.c
@@ -32,7 +32,7 @@
* control for which core is the next to come out of the secondary
* boot "holding pen"
*/
-volatile int __cpuinitdata pen_release = -1;
+volatile int pen_release = -1;
/*
* Write pen_release in a way that is guaranteed to be visible to all
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index f55d509..2eac6b7 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -35,7 +35,7 @@
#include <asm/hardware/gic.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
-#include <asm/hardware/cache-l2x0.h>
+#include <asm/outercache.h>
#ifdef CONFIG_VFP
#include <asm/vfp.h>
#endif
@@ -114,6 +114,7 @@
"standalone_power_collapse",
};
+static struct msm_pm_init_data_type msm_pm_init_data;
static struct hrtimer pm_hrtimer;
static struct msm_pm_sleep_ops pm_sleep_ops;
/*
@@ -473,7 +474,6 @@
}
static void *msm_pm_idle_rs_limits;
-static bool msm_pm_use_qtimer;
static void msm_pm_swfi(void)
{
@@ -499,24 +499,6 @@
msm_pm_config_hw_after_retention();
}
-#ifdef CONFIG_CACHE_L2X0
-static inline bool msm_pm_l2x0_power_collapse(void)
-{
- bool collapsed = 0;
-
- l2cc_suspend();
- collapsed = msm_pm_collapse();
- l2cc_resume();
-
- return collapsed;
-}
-#else
-static inline bool msm_pm_l2x0_power_collapse(void)
-{
- return msm_pm_collapse();
-}
-#endif
-
static bool __ref msm_pm_spm_power_collapse(
unsigned int cpu, bool from_idle, bool notify_rpm)
{
@@ -547,7 +529,7 @@
#ifdef CONFIG_VFP
vfp_pm_suspend();
#endif
- collapsed = msm_pm_l2x0_power_collapse();
+ collapsed = msm_pm_collapse();
msm_pm_boot_config_after_pc(cpu);
@@ -576,11 +558,13 @@
{
unsigned int cpu = smp_processor_id();
unsigned int avsdscr_setting;
+ unsigned int avscsr_enable;
bool collapsed;
avsdscr_setting = avs_get_avsdscr();
- avs_disable();
+ avscsr_enable = avs_disable();
collapsed = msm_pm_spm_power_collapse(cpu, from_idle, false);
+ avs_enable(avscsr_enable);
avs_reset_delays(avsdscr_setting);
return collapsed;
}
@@ -590,6 +574,7 @@
unsigned int cpu = smp_processor_id();
unsigned long saved_acpuclk_rate;
unsigned int avsdscr_setting;
+ unsigned int avscsr_enable;
bool collapsed;
if (MSM_PM_DEBUG_POWER_COLLAPSE & msm_pm_debug_mask)
@@ -601,7 +586,7 @@
pr_info("CPU%u: %s: pre power down\n", cpu, __func__);
avsdscr_setting = avs_get_avsdscr();
- avs_disable();
+ avscsr_enable = avs_disable();
if (cpu_online(cpu))
saved_acpuclk_rate = acpuclk_power_collapse();
@@ -643,6 +628,7 @@
}
+ avs_enable(avscsr_enable);
avs_reset_delays(avsdscr_setting);
msm_pm_config_hw_after_power_up();
if (MSM_PM_DEBUG_POWER_COLLAPSE & msm_pm_debug_mask)
@@ -657,14 +643,11 @@
{
if (cpu_is_apq8064())
msm_pm_save_cp15 = true;
-
- if (cpu_is_msm8974())
- msm_pm_use_qtimer = true;
}
static int64_t msm_pm_timer_enter_idle(void)
{
- if (msm_pm_use_qtimer)
+ if (msm_pm_init_data.use_sync_timer)
return ktime_to_ns(tick_nohz_get_sleep_length());
return msm_timer_enter_idle();
@@ -672,7 +655,7 @@
static void msm_pm_timer_exit_idle(bool timer_halted)
{
- if (msm_pm_use_qtimer)
+ if (msm_pm_init_data.use_sync_timer)
return;
msm_timer_exit_idle((int) timer_halted);
@@ -682,7 +665,7 @@
{
int64_t time = 0;
- if (msm_pm_use_qtimer)
+ if (msm_pm_init_data.use_sync_timer)
return sched_clock();
time = msm_timer_get_sclk_time(period);
@@ -694,7 +677,7 @@
static int64_t msm_pm_timer_exit_suspend(int64_t time, int64_t period)
{
- if (msm_pm_use_qtimer)
+ if (msm_pm_init_data.use_sync_timer)
return sched_clock() - time;
if (time != 0) {
@@ -1165,3 +1148,73 @@
}
late_initcall(msm_pm_init);
+
+static void __devinit msm_pm_set_flush_fn(uint32_t pc_mode)
+{
+ msm_pm_disable_l2_fn = NULL;
+ msm_pm_enable_l2_fn = NULL;
+ msm_pm_flush_l2_fn = outer_flush_all;
+
+ if (pc_mode == MSM_PM_PC_NOTZ_L2_EXT) {
+ msm_pm_disable_l2_fn = outer_disable;
+ msm_pm_enable_l2_fn = outer_resume;
+ }
+}
+
+static int __devinit msm_pm_8x60_probe(struct platform_device *pdev)
+{
+ char *key = NULL;
+ uint32_t val = 0;
+ int ret = 0;
+
+ if (!pdev->dev.of_node) {
+ struct msm_pm_init_data_type *d = pdev->dev.platform_data;
+
+ if (!d)
+ goto pm_8x60_probe_done;
+
+ msm_pm_init_data.pc_mode = d->pc_mode;
+ msm_pm_set_flush_fn(msm_pm_init_data.pc_mode);
+ msm_pm_init_data.use_sync_timer = d->use_sync_timer;
+ } else {
+ key = "qcom,pc-mode";
+ ret = of_property_read_u32(pdev->dev.of_node, key, &val);
+
+ if (ret) {
+ pr_debug("%s: Cannot read %s,defaulting to 0",
+ __func__, key);
+ val = MSM_PM_PC_TZ_L2_INT;
+ ret = 0;
+ }
+
+ msm_pm_init_data.pc_mode = val;
+ msm_pm_set_flush_fn(msm_pm_init_data.pc_mode);
+
+ key = "qcom,use-sync-timer";
+ msm_pm_init_data.use_sync_timer =
+ of_property_read_bool(pdev->dev.of_node, key);
+ }
+
+pm_8x60_probe_done:
+ return ret;
+}
+
+static struct of_device_id msm_pm_8x60_table[] = {
+ {.compatible = "qcom,pm-8x60"},
+ {},
+};
+
+static struct platform_driver msm_pm_8x60_driver = {
+ .probe = msm_pm_8x60_probe,
+ .driver = {
+ .name = "pm-8x60",
+ .owner = THIS_MODULE,
+ .of_match_table = msm_pm_8x60_table,
+ },
+};
+
+static int __init msm_pm_8x60_init(void)
+{
+ return platform_driver_register(&msm_pm_8x60_driver);
+}
+module_init(msm_pm_8x60_init);
diff --git a/arch/arm/mach-msm/pm.h b/arch/arm/mach-msm/pm.h
index 51256ca..faefe34 100644
--- a/arch/arm/mach-msm/pm.h
+++ b/arch/arm/mach-msm/pm.h
@@ -87,6 +87,20 @@
bool notify_rpm, bool collapsed);
};
+enum msm_pm_pc_mode_type {
+ MSM_PM_PC_TZ_L2_INT = 0, /*Power collapse terminates in TZ;
+ integrated L2 cache controller */
+ MSM_PM_PC_NOTZ_L2_EXT = 1, /* Power collapse doesn't terminate in
+ TZ; external L2 cache controller */
+ MSM_PM_PC_TZ_L2_EXT = 2, /* Power collapse terminates in TZ;
+ external L2 cache controller */
+};
+
+struct msm_pm_init_data_type {
+ enum msm_pm_pc_mode_type pc_mode;
+ bool use_sync_timer;
+};
+
struct msm_pm_cpr_ops {
void (*cpr_suspend)(void);
void (*cpr_resume)(void);
diff --git a/arch/arm/mach-msm/qdsp6v2/Makefile b/arch/arm/mach-msm/qdsp6v2/Makefile
index 0f17a0b..66d6bda 100644
--- a/arch/arm/mach-msm/qdsp6v2/Makefile
+++ b/arch/arm/mach-msm/qdsp6v2/Makefile
@@ -27,4 +27,3 @@
obj-$(CONFIG_MSM_QDSP6V2_CODECS) += audio_mp3.o audio_amrnb.o audio_amrwb.o audio_evrc.o audio_qcelp.o amrwb_in.o
obj-$(CONFIG_MSM_ADSP_LOADER) += adsp-loader.o
obj-$(CONFIG_MSM_ULTRASOUND_A) += ultrasound/version_a/
-obj-m += adsprpc.o
diff --git a/arch/arm/mach-msm/qdsp6v2/adsp-loader.c b/arch/arm/mach-msm/qdsp6v2/adsp-loader.c
index 9924b52..c28e403 100644
--- a/arch/arm/mach-msm/qdsp6v2/adsp-loader.c
+++ b/arch/arm/mach-msm/qdsp6v2/adsp-loader.c
@@ -17,7 +17,7 @@
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
-#include <mach/peripheral-loader.h>
+#include <mach/subsystem_restart.h>
#include <mach/qdsp6v2/apr.h>
#define Q6_PIL_GET_DELAY_MS 100
@@ -37,7 +37,7 @@
platform_set_drvdata(pdev, priv);
- priv->pil_h = pil_get("adsp");
+ priv->pil_h = subsystem_get("adsp");
if (IS_ERR(priv->pil_h)) {
pr_err("%s: pil get adsp failed, error:%d\n", __func__, rc);
devm_kfree(&pdev->dev, priv);
@@ -62,7 +62,7 @@
struct adsp_loader_private *priv;
priv = platform_get_drvdata(pdev);
- pil_put(priv->pil_h);
+ subsystem_put(priv->pil_h);
pr_info("%s: Q6/ADSP image is unloaded\n", __func__);
return 0;
diff --git a/arch/arm/mach-msm/qdsp6v2/apr.c b/arch/arm/mach-msm/qdsp6v2/apr.c
index d494069..39bec8e 100644
--- a/arch/arm/mach-msm/qdsp6v2/apr.c
+++ b/arch/arm/mach-msm/qdsp6v2/apr.c
@@ -27,7 +27,7 @@
#include <linux/device.h>
#include <linux/slab.h>
#include <asm/mach-types.h>
-#include <mach/peripheral-loader.h>
+#include <mach/subsystem_restart.h>
#include <mach/msm_smd.h>
#include <mach/qdsp6v2/apr.h>
#include <mach/qdsp6v2/apr_tal.h>
@@ -223,7 +223,7 @@
int rc = 0;
mutex_lock(&q6.lock);
if (apr_get_q6_state() == APR_SUBSYS_UP) {
- q6.pil = pil_get("q6");
+ q6.pil = subsystem_get("adsp");
if (IS_ERR(q6.pil)) {
rc = PTR_ERR(q6.pil);
pr_err("APR: Unable to load q6 image, error:%d\n", rc);
diff --git a/arch/arm/mach-msm/qdsp6v2/apr_v1.c b/arch/arm/mach-msm/qdsp6v2/apr_v1.c
index 011a73b..870bbb4 100644
--- a/arch/arm/mach-msm/qdsp6v2/apr_v1.c
+++ b/arch/arm/mach-msm/qdsp6v2/apr_v1.c
@@ -19,7 +19,6 @@
#include <mach/qdsp6v2/apr.h>
#include <mach/qdsp6v2/apr_tal.h>
#include <mach/qdsp6v2/dsp_debug.h>
-#include <mach/peripheral-loader.h>
static const char *lpass_subsys_name = "lpass";
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
index d6abdda..fb0ace7 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
@@ -779,6 +779,8 @@
__func__, audio, buf_node, buf_node->paddr,
buf_node->buf.data_len,
audio->buf_cfg.meta_info_enable);
+ pr_debug("%s[%p]: flags = 0x%x\n", __func__, audio,
+ buf_node->meta_info.meta_in.nflags);
ac = audio->ac;
/* Offset with appropriate meta */
@@ -798,6 +800,11 @@
param.flags = 0;
else
param.flags = 0xFF00;
+
+ if ((buf_node != NULL) &&
+ (buf_node->meta_info.meta_in.nflags & AUDIO_DEC_EOF_SET))
+ param.flags |= AUDIO_DEC_EOF_SET;
+
param.uid = param.paddr;
/* Read command will populate paddr as token */
buf_node->token = param.paddr;
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.h b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.h
index b2829c3..dedf991 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.h
+++ b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.h
@@ -36,6 +36,7 @@
#define ADRV_STATUS_FSYNC 0x00000008
#define ADRV_STATUS_PAUSE 0x00000010
#define AUDIO_DEC_EOS_SET 0x00000001
+#define AUDIO_DEC_EOF_SET 0x00000010
#define AUDIO_EVENT_NUM 10
#define __CONTAINS(r, v, l) ({ \
diff --git a/arch/arm/mach-msm/ramdump.c b/arch/arm/mach-msm/ramdump.c
index 21e81dd..e33ec48 100644
--- a/arch/arm/mach-msm/ramdump.c
+++ b/arch/arm/mach-msm/ramdump.c
@@ -181,7 +181,7 @@
.poll = ramdump_poll
};
-void *create_ramdump_device(const char *dev_name)
+void *create_ramdump_device(const char *dev_name, struct device *parent)
{
int ret;
struct ramdump_device *rd_dev;
@@ -207,6 +207,7 @@
rd_dev->device.minor = MISC_DYNAMIC_MINOR;
rd_dev->device.name = rd_dev->name;
rd_dev->device.fops = &ramdump_file_ops;
+ rd_dev->device.parent = parent;
init_waitqueue_head(&rd_dev->dump_wait_q);
diff --git a/arch/arm/mach-msm/ramdump.h b/arch/arm/mach-msm/ramdump.h
index 9006010..3e5bfaf 100644
--- a/arch/arm/mach-msm/ramdump.h
+++ b/arch/arm/mach-msm/ramdump.h
@@ -13,12 +13,14 @@
#ifndef _RAMDUMP_HEADER
#define _RAMDUMP_HEADER
+struct device;
+
struct ramdump_segment {
unsigned long address;
unsigned long size;
};
-void *create_ramdump_device(const char *dev_name);
+void *create_ramdump_device(const char *dev_name, struct device *parent);
void destroy_ramdump_device(void *dev);
int do_ramdump(void *handle, struct ramdump_segment *segments,
int nsegments);
diff --git a/arch/arm/mach-msm/rpm_stats.c b/arch/arm/mach-msm/rpm_stats.c
index a831bd5..032633c 100644
--- a/arch/arm/mach-msm/rpm_stats.c
+++ b/arch/arm/mach-msm/rpm_stats.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, 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
@@ -22,6 +22,7 @@
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/mm.h>
+#include <linux/types.h>
#include <asm/uaccess.h>
#include <mach/msm_iomap.h>
@@ -44,7 +45,6 @@
uint32_t id;
uint32_t val;
};
-
struct msm_rpmstats_private_data{
void __iomem *reg_base;
u32 num_records;
@@ -53,7 +53,6 @@
char buf[128];
struct msm_rpmstats_platform_data *platform_data;
};
-
static inline unsigned long msm_rpmstats_read_register(void __iomem *regbase,
int index, int offset)
{
@@ -120,7 +119,6 @@
msm_rpmstats_id_labels[record.id],
usec);
}
-
static int msm_rpmstats_file_read(struct file *file, char __user *bufu,
size_t count, loff_t *ppos)
{
@@ -133,13 +131,16 @@
if (!bufu || count < 0)
return -EINVAL;
- if (!prvdata->num_records)
- prvdata->num_records = readl_relaxed(prvdata->reg_base);
+ if (prvdata->platform_data->version == 1) {
+ if (!prvdata->num_records)
+ prvdata->num_records = readl_relaxed(prvdata->reg_base);
+ }
if ((*ppos >= prvdata->len)
- && (prvdata->read_idx < prvdata->num_records)) {
- prvdata->len = msm_rpmstats_copy_stats(prvdata);
- *ppos = 0;
+ && (prvdata->read_idx < prvdata->num_records)) {
+ if (prvdata->platform_data->version == 1)
+ prvdata->len = msm_rpmstats_copy_stats(prvdata);
+ *ppos = 0;
}
return simple_read_from_buffer(bufu, count, ppos,
@@ -198,15 +199,37 @@
{
struct dentry *dent;
struct msm_rpmstats_platform_data *pdata;
+ struct msm_rpmstats_platform_data *pd;
+ struct resource *res = NULL;
- pdata = pdev->dev.platform_data;
- if (!pdata)
+ if (!pdev)
return -EINVAL;
+
+ pdata = kzalloc(sizeof(struct msm_rpmstats_platform_data), GFP_KERNEL);
+
+ if (!pdata)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ if (!res)
+ return -EINVAL;
+
+ pdata->phys_addr_base = res->start;
+
+ pdata->phys_size = resource_size(res);
+
+ if (pdev->dev.platform_data) {
+ pd = pdev->dev.platform_data;
+ pdata->version = pd->version ;
+ }
+
dent = debugfs_create_file("rpm_stats", S_IRUGO, NULL,
- pdev->dev.platform_data, &msm_rpmstats_fops);
+ pdata, &msm_rpmstats_fops);
if (!dent) {
pr_err("%s: ERROR debugfs_create_file failed\n", __func__);
+ kfree(pdata);
return -ENOMEM;
}
platform_set_drvdata(pdev, dent);
diff --git a/arch/arm/mach-msm/rpm_stats.h b/arch/arm/mach-msm/rpm_stats.h
index a3beaa4..c1dfe34 100644
--- a/arch/arm/mach-msm/rpm_stats.h
+++ b/arch/arm/mach-msm/rpm_stats.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -19,6 +19,7 @@
struct msm_rpmstats_platform_data {
phys_addr_t phys_addr_base;
u32 phys_size;
+ u32 version;
};
struct msm_rpm_master_stats_platform_data {
diff --git a/arch/arm/mach-msm/scm-pas.c b/arch/arm/mach-msm/scm-pas.c
index 55ae2f8..e248917 100644
--- a/arch/arm/mach-msm/scm-pas.c
+++ b/arch/arm/mach-msm/scm-pas.c
@@ -24,6 +24,7 @@
#include "scm-pas.h"
#define PAS_INIT_IMAGE_CMD 1
+#define PAS_MEM_SETUP_CMD 2
#define PAS_AUTH_AND_RESET_CMD 5
#define PAS_SHUTDOWN_CMD 6
#define PAS_IS_SUPPORTED_CMD 7
@@ -55,6 +56,28 @@
}
EXPORT_SYMBOL(pas_init_image);
+int pas_mem_setup(enum pas_id id, u32 start_addr, u32 len)
+{
+ int ret;
+ struct pas_init_image_req {
+ u32 proc;
+ u32 start_addr;
+ u32 len;
+ } request;
+ u32 scm_ret = 0;
+
+ request.proc = id;
+ request.start_addr = start_addr;
+ request.len = len;
+
+ ret = scm_call(SCM_SVC_PIL, PAS_MEM_SETUP_CMD, &request,
+ sizeof(request), &scm_ret, sizeof(scm_ret));
+ if (ret)
+ return ret;
+ return scm_ret;
+}
+EXPORT_SYMBOL(pas_mem_setup);
+
static struct msm_bus_paths scm_pas_bw_tbl[] = {
{
.vectors = (struct msm_bus_vectors[]){
diff --git a/arch/arm/mach-msm/scm-pas.h b/arch/arm/mach-msm/scm-pas.h
index 8da1d75..6441a18 100644
--- a/arch/arm/mach-msm/scm-pas.h
+++ b/arch/arm/mach-msm/scm-pas.h
@@ -27,6 +27,7 @@
#ifdef CONFIG_MSM_PIL
extern int pas_init_image(enum pas_id id, const u8 *metadata, size_t size);
+extern int pas_mem_setup(enum pas_id id, u32 start_addr, u32 len);
extern int pas_auth_and_reset(enum pas_id id);
extern int pas_shutdown(enum pas_id id);
extern int pas_supported(enum pas_id id);
@@ -36,6 +37,10 @@
{
return 0;
}
+static inline int pas_mem_setup(enum pas_id id, u32 start_addr, u32 len)
+{
+ return 0;
+}
static inline int pas_auth_and_reset(enum pas_id id)
{
return 0;
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index c6da910..3c0cbf7 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -706,7 +706,7 @@
*/
static struct edge_to_pid edge_to_pids[] = {
[SMD_APPS_MODEM] = {SMD_APPS, SMD_MODEM, "modem"},
- [SMD_APPS_QDSP] = {SMD_APPS, SMD_Q6, "q6"},
+ [SMD_APPS_QDSP] = {SMD_APPS, SMD_Q6, "adsp"},
[SMD_MODEM_QDSP] = {SMD_MODEM, SMD_Q6},
[SMD_APPS_DSPS] = {SMD_APPS, SMD_DSPS, "dsps"},
[SMD_MODEM_DSPS] = {SMD_MODEM, SMD_DSPS},
diff --git a/arch/arm/mach-msm/smd_pkt.c b/arch/arm/mach-msm/smd_pkt.c
index 928e59b..73ebdf6 100644
--- a/arch/arm/mach-msm/smd_pkt.c
+++ b/arch/arm/mach-msm/smd_pkt.c
@@ -34,14 +34,14 @@
#include <linux/wakelock.h>
#include <mach/msm_smd.h>
-#include <mach/peripheral-loader.h>
+#include <mach/subsystem_restart.h>
#include <mach/msm_ipc_logging.h>
#include "smd_private.h"
#ifdef CONFIG_ARCH_FSM9XXX
#define NUM_SMD_PKT_PORTS 4
#else
-#define NUM_SMD_PKT_PORTS 15
+#define NUM_SMD_PKT_PORTS 24
#endif
#define PDRIVER_NAME_MAX_SIZE 32
@@ -711,6 +711,15 @@
"smdcntl6",
"smdcntl7",
"smd22",
+ "smdcnt_rev0",
+ "smdcnt_rev1",
+ "smdcnt_rev2",
+ "smdcnt_rev3",
+ "smdcnt_rev4",
+ "smdcnt_rev5",
+ "smdcnt_rev6",
+ "smdcnt_rev7",
+ "smdcnt_rev8",
"smd_sns_dsps",
"apr_apps2",
"smdcntl8",
@@ -729,6 +738,15 @@
"DATA13_CNTL",
"DATA14_CNTL",
"DATA22",
+ "DATA23_CNTL",
+ "DATA24_CNTL",
+ "DATA25_CNTL",
+ "DATA26_CNTL",
+ "DATA27_CNTL",
+ "DATA28_CNTL",
+ "DATA29_CNTL",
+ "DATA30_CNTL",
+ "DATA31_CNTL",
"SENSOR",
"apr_apps2",
"DATA40_CNTL",
@@ -747,6 +765,15 @@
SMD_APPS_MODEM,
SMD_APPS_MODEM,
SMD_APPS_MODEM,
+ SMD_APPS_MODEM,
+ SMD_APPS_MODEM,
+ SMD_APPS_MODEM,
+ SMD_APPS_MODEM,
+ SMD_APPS_MODEM,
+ SMD_APPS_MODEM,
+ SMD_APPS_MODEM,
+ SMD_APPS_MODEM,
+ SMD_APPS_MODEM,
SMD_APPS_DSPS,
SMD_APPS_QDSP,
SMD_APPS_MODEM,
@@ -823,12 +850,11 @@
peripheral = smd_edge_to_subsystem(
smd_ch_edge[smd_pkt_devp->i]);
if (peripheral) {
- smd_pkt_devp->pil = pil_get(peripheral);
+ smd_pkt_devp->pil = subsystem_get(peripheral);
if (IS_ERR(smd_pkt_devp->pil)) {
r = PTR_ERR(smd_pkt_devp->pil);
- pr_err("%s failed on smd_pkt_dev id:%d -"
- " pil_get failed for %s\n", __func__,
- smd_pkt_devp->i, peripheral);
+ pr_err("%s failed on smd_pkt_dev id:%d - subsystem_get failed for %s\n",
+ __func__, smd_pkt_devp->i, peripheral);
goto release_pd;
}
@@ -908,7 +934,7 @@
}
release_pil:
if (peripheral && (r < 0))
- pil_put(smd_pkt_devp->pil);
+ subsystem_put(smd_pkt_devp->pil);
release_pd:
if (r < 0) {
@@ -952,7 +978,7 @@
platform_driver_unregister(&smd_pkt_devp->driver);
smd_pkt_devp->driver.probe = NULL;
if (smd_pkt_devp->pil)
- pil_put(smd_pkt_devp->pil);
+ subsystem_put(smd_pkt_devp->pil);
smd_pkt_devp->has_reset = 0;
smd_pkt_devp->do_reset_notification = 0;
smd_pkt_devp->wakelock_locked = 0;
diff --git a/arch/arm/mach-msm/smd_rpcrouter_device.c b/arch/arm/mach-msm/smd_rpcrouter_device.c
index e84d213..7b51beb 100644
--- a/arch/arm/mach-msm/smd_rpcrouter_device.c
+++ b/arch/arm/mach-msm/smd_rpcrouter_device.c
@@ -1,7 +1,7 @@
/* arch/arm/mach-msm/smd_rpcrouter_device.c
*
* Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2007-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2007-2012, Code Aurora Forum. All rights reserved.
* Author: San Mehat <san@android.com>
*
* This software is licensed under the terms of the GNU General Public
@@ -34,7 +34,7 @@
#include <asm/uaccess.h>
#include <asm/byteorder.h>
-#include <mach/peripheral-loader.h>
+#include <mach/subsystem_restart.h>
#include "smd_rpcrouter.h"
/* Support 64KB of data plus some space for headers */
@@ -61,7 +61,7 @@
static void msm_rpcrouter_unload_modem(void *pil)
{
if (pil)
- pil_put(pil);
+ subsystem_put(pil);
}
static void *msm_rpcrouter_load_modem(void)
@@ -69,7 +69,7 @@
void *pil;
int rc;
- pil = pil_get("modem");
+ pil = subsystem_get("modem");
if (IS_ERR(pil))
pr_err("%s: modem load failed\n", __func__);
else {
diff --git a/arch/arm/mach-msm/smd_tty.c b/arch/arm/mach-msm/smd_tty.c
index 44ef822..881da18 100644
--- a/arch/arm/mach-msm/smd_tty.c
+++ b/arch/arm/mach-msm/smd_tty.c
@@ -30,7 +30,7 @@
#include <linux/tty_flip.h>
#include <mach/msm_smd.h>
-#include <mach/peripheral-loader.h>
+#include <mach/subsystem_restart.h>
#include <mach/socinfo.h>
#include "smd_private.h"
@@ -245,7 +245,7 @@
if (info->open_count++ == 0) {
peripheral = smd_edge_to_subsystem(smd_tty[n].smd->edge);
if (peripheral) {
- info->pil = pil_get(peripheral);
+ info->pil = subsystem_get(peripheral);
if (IS_ERR(info->pil)) {
res = PTR_ERR(info->pil);
goto out;
@@ -325,7 +325,7 @@
release_pil:
if (res < 0)
- pil_put(info->pil);
+ subsystem_put(info->pil);
else
smd_disable_read_intr(info->ch);
out:
@@ -357,7 +357,7 @@
if (info->ch) {
smd_close(info->ch);
info->ch = 0;
- pil_put(info->pil);
+ subsystem_put(info->pil);
}
}
mutex_unlock(&smd_tty_lock);
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 62085f6..6cb9339 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -260,6 +260,7 @@
[128] = MSM_CPU_8625,
[129] = MSM_CPU_8625,
[137] = MSM_CPU_8625,
+ [167] = MSM_CPU_8625,
/* 8064 MPQ ID */
[130] = MSM_CPU_8064,
diff --git a/arch/arm/mach-msm/spm.c b/arch/arm/mach-msm/spm.c
index 8337fd1..ea0b56c 100644
--- a/arch/arm/mach-msm/spm.c
+++ b/arch/arm/mach-msm/spm.c
@@ -132,6 +132,11 @@
/******************************************************************************
* Public functions
*****************************************************************************/
+/**
+ * msm_spm_set_low_power_mode() - Configure SPM start address for low power mode
+ * @mode: SPM LPM mode to enter
+ * @notify_rpm: Notify RPM in this mode
+ */
int msm_spm_set_low_power_mode(unsigned int mode, bool notify_rpm)
{
struct msm_spm_device *dev = &__get_cpu_var(msm_spm_devices);
@@ -185,6 +190,11 @@
return 0;
}
+/**
+ * msm_spm_set_vdd(): Set core voltage
+ * @cpu: core id
+ * @vlevel: Encoded PMIC data.
+ */
int msm_spm_set_vdd(unsigned int cpu, unsigned int vlevel)
{
struct msm_spm_device *dev;
@@ -235,6 +245,11 @@
return -EIO;
}
+/**
+ * msm_spm_get_vdd(): Get core voltage
+ * @cpu: core id
+ * @return: Returns encoded PMIC data.
+ */
unsigned int msm_spm_get_vdd(unsigned int cpu)
{
struct msm_spm_device *dev = &per_cpu(msm_spm_devices, cpu);
@@ -253,6 +268,11 @@
mb();
}
+/**
+ * msm_spm_init(): Board initalization function
+ * @data: platform specific SPM register configuration data
+ * @nr_devs: Number of SPM devices being initialized
+ */
int __init msm_spm_init(struct msm_spm_platform_data *data, int nr_devs)
{
unsigned int cpu;
diff --git a/arch/arm/mach-msm/spm.h b/arch/arm/mach-msm/spm.h
index 4cdfcf8..a353ce0 100644
--- a/arch/arm/mach-msm/spm.h
+++ b/arch/arm/mach-msm/spm.h
@@ -127,93 +127,29 @@
/* Public functions */
-/**
- * msm_spm_set_low_power_mode() - Configure SPM start address for low power mode
- * @mode: SPM LPM mode to enter
- * @notify_rpm: Notify RPM in this mode
- */
int msm_spm_set_low_power_mode(unsigned int mode, bool notify_rpm);
-
-/**
- * msm_spm_set_vdd(): Set core voltage
- * @cpu: core id
- * @vlevel: Encoded PMIC data.
- */
int msm_spm_set_vdd(unsigned int cpu, unsigned int vlevel);
-
-/**
- * msm_spm_get_vdd(): Get core voltage
- * @cpu: core id
- * @return: Returns encoded PMIC data.
- */
unsigned int msm_spm_get_vdd(unsigned int cpu);
-
-/**
- * msm_spm_turn_on_cpu_rail(): Power on cpu rail before turning on core
- * @cpu: core id
- */
int msm_spm_turn_on_cpu_rail(unsigned int cpu);
/* Internal low power management specific functions */
-/**
- * msm_spm_reinit(): Reinitialize SPM registers
- */
void msm_spm_reinit(void);
-
-/**
- * msm_spm_init(): Board initalization function
- * @data: platform specific SPM register configuration data
- * @nr_devs: Number of SPM devices being initialized
- */
int msm_spm_init(struct msm_spm_platform_data *data, int nr_devs);
-
-/**
- * msm_spm_device_init(): Device tree initialization function
- */
int msm_spm_device_init(void);
#if defined(CONFIG_MSM_L2_SPM)
/* Public functions */
-/**
- * msm_spm_l2_set_low_power_mode(): Configure L2 SPM start address
- * for low power mode
- * @mode: SPM LPM mode to enter
- * @notify_rpm: Notify RPM in this mode
- */
int msm_spm_l2_set_low_power_mode(unsigned int mode, bool notify_rpm);
-
-/**
- * msm_spm_apcs_set_vdd(): Set Apps processor core sub-system voltage
- * @vlevel: Encoded PMIC data.
- */
int msm_spm_apcs_set_vdd(unsigned int vlevel);
-
-/**
- * msm_spm_apcs_set_phase(): Set number of SMPS phases.
- * phase_cnt: Number of phases to be set active
- */
int msm_spm_apcs_set_phase(unsigned int phase_cnt);
-
-/** msm_spm_enable_fts_lpm() : Enable FTS to switch to low power
- * when the cores are in low power modes
- * @mode: The mode configuration for FTS
- */
int msm_spm_enable_fts_lpm(uint32_t mode);
/* Internal low power management specific functions */
-/**
- * msm_spm_l2_init(): Board initialization function
- * @data: SPM target specific register configuration
- */
int msm_spm_l2_init(struct msm_spm_platform_data *data);
-
-/**
- * msm_spm_l2_reinit(): Reinitialize L2 SPM registers
- */
void msm_spm_l2_reinit(void);
#else
diff --git a/arch/arm/mach-msm/spm_devices.c b/arch/arm/mach-msm/spm_devices.c
index 3fe3bd7..b378d3b 100644
--- a/arch/arm/mach-msm/spm_devices.c
+++ b/arch/arm/mach-msm/spm_devices.c
@@ -57,6 +57,11 @@
info->err = msm_spm_drv_set_vdd(&dev->reg_data, info->vlevel);
}
+/**
+ * msm_spm_set_vdd(): Set core voltage
+ * @cpu: core id
+ * @vlevel: Encoded PMIC data.
+ */
int msm_spm_set_vdd(unsigned int cpu, unsigned int vlevel)
{
struct msm_spm_vdd_info info;
@@ -91,6 +96,11 @@
}
EXPORT_SYMBOL(msm_spm_set_vdd);
+/**
+ * msm_spm_get_vdd(): Get core voltage
+ * @cpu: core id
+ * @return: Returns encoded PMIC data.
+ */
unsigned int msm_spm_get_vdd(unsigned int cpu)
{
struct msm_spm_device *dev;
@@ -166,6 +176,10 @@
return ret;
}
+/**
+ * msm_spm_turn_on_cpu_rail(): Power on cpu rail before turning on core
+ * @cpu: core id
+ */
int msm_spm_turn_on_cpu_rail(unsigned int cpu)
{
uint32_t val = 0;
@@ -208,6 +222,11 @@
}
EXPORT_SYMBOL(msm_spm_reinit);
+/**
+ * msm_spm_set_low_power_mode() - Configure SPM start address for low power mode
+ * @mode: SPM LPM mode to enter
+ * @notify_rpm: Notify RPM in this mode
+ */
int msm_spm_set_low_power_mode(unsigned int mode, bool notify_rpm)
{
struct msm_spm_device *dev = &__get_cpu_var(msm_cpu_spm_device);
@@ -215,7 +234,11 @@
}
EXPORT_SYMBOL(msm_spm_set_low_power_mode);
-/* Board file init function */
+/**
+ * msm_spm_init(): Board initalization function
+ * @data: platform specific SPM register configuration data
+ * @nr_devs: Number of SPM devices being initialized
+ */
int __init msm_spm_init(struct msm_spm_platform_data *data, int nr_devs)
{
unsigned int cpu;
@@ -238,6 +261,12 @@
#ifdef CONFIG_MSM_L2_SPM
+/**
+ * msm_spm_l2_set_low_power_mode(): Configure L2 SPM start address
+ * for low power mode
+ * @mode: SPM LPM mode to enter
+ * @notify_rpm: Notify RPM in this mode
+ */
int msm_spm_l2_set_low_power_mode(unsigned int mode, bool notify_rpm)
{
return msm_spm_dev_set_low_power_mode(
@@ -251,12 +280,20 @@
}
EXPORT_SYMBOL(msm_spm_l2_reinit);
+/**
+ * msm_spm_apcs_set_vdd(): Set Apps processor core sub-system voltage
+ * @vlevel: Encoded PMIC data.
+ */
int msm_spm_apcs_set_vdd(unsigned int vlevel)
{
return msm_spm_drv_set_vdd(&msm_spm_l2_device.reg_data, vlevel);
}
EXPORT_SYMBOL(msm_spm_apcs_set_vdd);
+/**
+ * msm_spm_apcs_set_phase(): Set number of SMPS phases.
+ * phase_cnt: Number of phases to be set active
+ */
int msm_spm_apcs_set_phase(unsigned int phase_cnt)
{
return msm_spm_drv_set_pmic_data(&msm_spm_l2_device.reg_data,
@@ -264,6 +301,10 @@
}
EXPORT_SYMBOL(msm_spm_apcs_set_phase);
+/** msm_spm_enable_fts_lpm() : Enable FTS to switch to low power
+ * when the cores are in low power modes
+ * @mode: The mode configuration for FTS
+ */
int msm_spm_enable_fts_lpm(uint32_t mode)
{
return msm_spm_drv_set_pmic_data(&msm_spm_l2_device.reg_data,
@@ -271,7 +312,10 @@
}
EXPORT_SYMBOL(msm_spm_enable_fts_lpm);
-/* Board file init function */
+/**
+ * msm_spm_l2_init(): Board initialization function
+ * @data: SPM target specific register configuration
+ */
int __init msm_spm_l2_init(struct msm_spm_platform_data *data)
{
return msm_spm_dev_init(&msm_spm_l2_device, data);
@@ -453,6 +497,9 @@
},
};
+/**
+ * msm_spm_device_init(): Device tree initialization function
+ */
int __init msm_spm_device_init(void)
{
return platform_driver_register(&msm_spm_device_driver);
diff --git a/arch/arm/mach-msm/subsystem_restart.c b/arch/arm/mach-msm/subsystem_restart.c
index 8951cfe..ea9337d 100644
--- a/arch/arm/mach-msm/subsystem_restart.c
+++ b/arch/arm/mach-msm/subsystem_restart.c
@@ -33,7 +33,6 @@
#include <asm/current.h>
-#include <mach/peripheral-loader.h>
#include <mach/socinfo.h>
#include <mach/subsystem_notif.h>
#include <mach/subsystem_restart.h>
@@ -228,7 +227,7 @@
/* MSM 8x60 restart ordering info */
static const char * const _order_8x60_all[] = {
- "external_modem", "modem", "lpass"
+ "external_modem", "modem", "adsp"
};
DEFINE_SINGLE_RESTART_ORDER(orders_8x60_all, _order_8x60_all);
@@ -839,7 +838,6 @@
subsys->dev.parent = desc->dev;
subsys->dev.bus = &subsys_bus_type;
subsys->dev.release = subsys_device_release;
- subsys->track.state = SUBSYS_ONLINE; /* Until proper refcounting */
subsys->notify = subsys_notif_add_subsys(desc->name);
subsys->restart_order = update_restart_order(subsys);
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 00a07a0..0b3ffef 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -649,6 +649,16 @@
block. Or some systems may want the iMem to be dedicated to a
different function.
+config MSM_ADSPRPC
+ tristate "Qualcomm ADSP RPC driver"
+ depends on MSM_AUDIO_QDSP6 || MSM_AUDIO_QDSP6V2
+ default m
+ help
+ Provides a communication mechanism that allows for clients to
+ make remote method invocations across processor boundary to
+ applications DSP processor. Say M if you want to enable this
+ module.
+
config MMC_GENERIC_CSDIO
tristate "Generic sdio driver"
default n
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index c38c26c..8032f0b 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -66,4 +66,5 @@
obj-$(CONFIG_TILE_SROM) += tile-srom.o
obj-$(CONFIG_MSM_ROTATOR) += msm_rotator.o
obj-$(CONFIG_MMC_GENERIC_CSDIO) += csdio.o
-obj-$(CONFIG_DIAG_CHAR) += diag/
\ No newline at end of file
+obj-$(CONFIG_DIAG_CHAR) += diag/
+obj-$(CONFIG_MSM_ADSPRPC) += adsprpc.o
diff --git a/arch/arm/mach-msm/qdsp6v2/adsprpc.c b/drivers/char/adsprpc.c
similarity index 100%
rename from arch/arm/mach-msm/qdsp6v2/adsprpc.c
rename to drivers/char/adsprpc.c
diff --git a/arch/arm/mach-msm/qdsp6v2/adsprpc.h b/drivers/char/adsprpc.h
similarity index 100%
rename from arch/arm/mach-msm/qdsp6v2/adsprpc.h
rename to drivers/char/adsprpc.h
diff --git a/arch/arm/mach-msm/qdsp6v2/adsprpc_shared.h b/drivers/char/adsprpc_shared.h
similarity index 100%
rename from arch/arm/mach-msm/qdsp6v2/adsprpc_shared.h
rename to drivers/char/adsprpc_shared.h
diff --git a/drivers/coresight/coresight-csr.c b/drivers/coresight/coresight-csr.c
index e9ac904..1f6bd1d 100644
--- a/drivers/coresight/coresight-csr.c
+++ b/drivers/coresight/coresight-csr.c
@@ -86,7 +86,7 @@
CSR_UNLOCK(drvdata);
usbbamctrl = csr_readl(drvdata, CSR_USBBAMCTRL);
- usbbamctrl = (usbbamctrl & ~0x3) | BLKSIZE_256;
+ usbbamctrl = (usbbamctrl & ~0x3) | BLKSIZE_2048;
csr_writel(drvdata, usbbamctrl, CSR_USBBAMCTRL);
usbflshctrl = csr_readl(drvdata, CSR_USBFLSHCTRL);
diff --git a/drivers/coresight/coresight-etm.c b/drivers/coresight/coresight-etm.c
index 50bae55..e2a16ad 100644
--- a/drivers/coresight/coresight-etm.c
+++ b/drivers/coresight/coresight-etm.c
@@ -25,8 +25,9 @@
#include <linux/wakelock.h>
#include <linux/sysfs.h>
#include <linux/stat.h>
-#include <linux/mutex.h>
+#include <linux/spinlock.h>
#include <linux/clk.h>
+#include <linux/cpu.h>
#include <linux/of_coresight.h>
#include <linux/coresight.h>
#include <asm/sections.h>
@@ -191,10 +192,12 @@
struct device *dev;
struct coresight_device *csdev;
struct clk *clk;
- struct mutex mutex;
+ spinlock_t spinlock;
struct wake_lock wake_lock;
int cpu;
uint8_t arch;
+ bool enable;
+ bool os_unlock;
uint8_t nr_addr_cmp;
uint8_t nr_cntr;
uint8_t nr_ext_inp;
@@ -203,7 +206,6 @@
uint8_t reset;
uint32_t mode;
uint32_t ctrl;
- uint8_t ctrl_pwrdwn;
uint32_t trigger_event;
uint32_t startstop_ctrl;
uint32_t enable_event;
@@ -230,12 +232,22 @@
uint32_t ctxid_mask;
uint32_t sync_freq;
uint32_t timestamp_event;
- uint8_t pdcr_pwrup;
bool pcsave_impl;
bool pcsave_enable;
};
-static struct etm_drvdata *etm0drvdata;
+static struct etm_drvdata *etmdrvdata[NR_CPUS];
+
+/*
+ * Memory mapped writes to clear os lock are not supported on Krait v1, v2
+ * and OS lock must be unlocked before any memory mapped access, otherwise
+ * memory mapped reads/writes will be invalid.
+ */
+static void etm_os_unlock(void *info)
+{
+ etm_writel_cp14(0x0, ETMOSLAR);
+ isb();
+}
/*
* ETM clock is derived from the processor clock and gets enabled on a
@@ -339,48 +351,18 @@
etm_readl(drvdata, ETMSR));
}
-static void etm_save_pwrdwn(struct etm_drvdata *drvdata)
-{
- drvdata->ctrl_pwrdwn = BVAL(etm_readl(drvdata, ETMCR), 0);
-}
-
-static void etm_restore_pwrdwn(struct etm_drvdata *drvdata)
-{
- uint32_t etmcr;
-
- etmcr = etm_readl(drvdata, ETMCR);
- etmcr = (etmcr & ~BIT(0)) | drvdata->ctrl_pwrdwn;
- etm_writel(drvdata, etmcr, ETMCR);
-}
-
-static void etm_save_pwrup(struct etm_drvdata *drvdata)
-{
- drvdata->pdcr_pwrup = BVAL(etm_readl_mm(drvdata, ETMPDCR), 3);
-}
-
-static void etm_restore_pwrup(struct etm_drvdata *drvdata)
-{
- uint32_t etmpdcr;
-
- etmpdcr = etm_readl_mm(drvdata, ETMPDCR);
- etmpdcr = (etmpdcr & ~BIT(3)) | (drvdata->pdcr_pwrup << 3);
- etm_writel_mm(drvdata, etmpdcr, ETMPDCR);
-}
-
static void etm_enable_pcsave(void *info)
{
struct etm_drvdata *drvdata = info;
ETM_UNLOCK(drvdata);
- etm_save_pwrup(drvdata);
/*
* ETMPDCR is only accessible via memory mapped interface and so use
* it first to enable power/clock to allow subsequent cp14 accesses.
*/
etm_set_pwrup(drvdata);
etm_clr_pwrdwn(drvdata);
- etm_restore_pwrup(drvdata);
ETM_LOCK(drvdata);
}
@@ -391,14 +373,10 @@
ETM_UNLOCK(drvdata);
- etm_save_pwrup(drvdata);
- /*
- * ETMPDCR is only accessible via memory mapped interface and so use
- * it first to enable power/clock to allow subsequent cp14 accesses.
- */
- etm_set_pwrup(drvdata);
- etm_set_pwrdwn(drvdata);
- etm_restore_pwrup(drvdata);
+ if (!drvdata->enable) {
+ etm_set_pwrdwn(drvdata);
+ etm_clr_pwrup(drvdata);
+ }
ETM_LOCK(drvdata);
}
@@ -416,10 +394,10 @@
* to allow subsequent cp14 accesses.
*/
etm_set_pwrup(drvdata);
- etm_save_pwrdwn(drvdata);
/*
* Clear power down bit since when this bit is set writes to
- * certain registers might be ignored.
+ * certain registers might be ignored. This is also a pre-requisite
+ * for trace enable.
*/
etm_clr_pwrdwn(drvdata);
etm_set_prog(drvdata);
@@ -463,7 +441,6 @@
etm_writel(drvdata, 0x00000000, ETMVMIDCVR);
etm_clr_prog(drvdata);
- etm_restore_pwrdwn(drvdata);
ETM_LOCK(drvdata);
dev_dbg(drvdata->dev, "cpu: %d enable smp call done\n", drvdata->cpu);
@@ -480,17 +457,29 @@
if (ret)
goto err_clk;
- mutex_lock(&drvdata->mutex);
- /* executing __etm_enable on the cpu whose ETM is being enabled
+ get_online_cpus();
+ spin_lock(&drvdata->spinlock);
+
+ /*
+ * Executing __etm_enable on the cpu whose ETM is being enabled
* ensures that register writes occur when cpu is powered.
*/
- smp_call_function_single(drvdata->cpu, __etm_enable, drvdata, 1);
- mutex_unlock(&drvdata->mutex);
+ ret = smp_call_function_single(drvdata->cpu, __etm_enable, drvdata, 1);
+ if (ret)
+ goto err;
+ drvdata->enable = true;
+
+ spin_unlock(&drvdata->spinlock);
+ put_online_cpus();
wake_unlock(&drvdata->wake_lock);
dev_info(drvdata->dev, "ETM tracing enabled\n");
return 0;
+err:
+ spin_unlock(&drvdata->spinlock);
+ put_online_cpus();
+ clk_disable_unprepare(drvdata->clk);
err_clk:
wake_unlock(&drvdata->wake_lock);
return ret;
@@ -501,20 +490,15 @@
struct etm_drvdata *drvdata = info;
ETM_UNLOCK(drvdata);
- etm_save_pwrdwn(drvdata);
- /*
- * Clear power down bit since when this bit is set writes to
- * certain registers might be ignored.
- */
- etm_clr_pwrdwn(drvdata);
etm_set_prog(drvdata);
/* program trace enable to low by using always false event */
etm_writel(drvdata, 0x6F | BIT(14), ETMTEEVR);
- etm_restore_pwrdwn(drvdata);
- /* Vote for ETM power/clock disable */
- etm_clr_pwrup(drvdata);
+ if (!drvdata->pcsave_enable) {
+ etm_set_pwrdwn(drvdata);
+ etm_clr_pwrup(drvdata);
+ }
ETM_LOCK(drvdata);
dev_dbg(drvdata->dev, "cpu: %d disable smp call done\n", drvdata->cpu);
@@ -526,12 +510,18 @@
wake_lock(&drvdata->wake_lock);
- mutex_lock(&drvdata->mutex);
- /* executing __etm_disable on the cpu whose ETM is being disabled
+ get_online_cpus();
+ spin_lock(&drvdata->spinlock);
+
+ /*
+ * Executing __etm_disable on the cpu whose ETM is being disabled
* ensures that register writes occur when cpu is powered.
*/
smp_call_function_single(drvdata->cpu, __etm_disable, drvdata, 1);
- mutex_unlock(&drvdata->mutex);
+ drvdata->enable = false;
+
+ spin_unlock(&drvdata->spinlock);
+ put_online_cpus();
clk_disable_unprepare(drvdata->clk);
@@ -600,7 +590,7 @@
if (sscanf(buf, "%lx", &val) != 1)
return -EINVAL;
- mutex_lock(&drvdata->mutex);
+ spin_lock(&drvdata->spinlock);
if (val) {
drvdata->mode = ETM_MODE_EXCLUDE;
drvdata->ctrl = 0x0;
@@ -644,7 +634,7 @@
drvdata->sync_freq = 0x80;
drvdata->timestamp_event = 0x406F;
}
- mutex_unlock(&drvdata->mutex);
+ spin_unlock(&drvdata->spinlock);
return size;
}
static DEVICE_ATTR(reset, S_IRUGO | S_IWUSR, etm_show_reset, etm_store_reset);
@@ -667,7 +657,7 @@
if (sscanf(buf, "%lx", &val) != 1)
return -EINVAL;
- mutex_lock(&drvdata->mutex);
+ spin_lock(&drvdata->spinlock);
drvdata->mode = val & ETM_MODE_ALL;
if (drvdata->mode & ETM_MODE_EXCLUDE)
@@ -694,7 +684,7 @@
drvdata->ctrl |= (BIT(14) | BIT(15));
else
drvdata->ctrl &= ~(BIT(14) | BIT(15));
- mutex_unlock(&drvdata->mutex);
+ spin_unlock(&drvdata->spinlock);
return size;
}
@@ -796,12 +786,13 @@
if (val >= drvdata->nr_addr_cmp)
return -EINVAL;
- /* Use mutex to ensure index doesn't change while it gets dereferenced
- * multiple times within a mutex block elsewhere.
+ /*
+ * Use spinlock to ensure index doesn't change while it gets
+ * dereferenced multiple times within a spinlock block elsewhere.
*/
- mutex_lock(&drvdata->mutex);
+ spin_lock(&drvdata->spinlock);
drvdata->addr_idx = val;
- mutex_unlock(&drvdata->mutex);
+ spin_unlock(&drvdata->spinlock);
return size;
}
static DEVICE_ATTR(addr_idx, S_IRUGO | S_IWUSR, etm_show_addr_idx,
@@ -814,16 +805,16 @@
unsigned long val;
uint8_t idx;
- mutex_lock(&drvdata->mutex);
+ spin_lock(&drvdata->spinlock);
idx = drvdata->addr_idx;
if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
- mutex_unlock(&drvdata->mutex);
+ spin_unlock(&drvdata->spinlock);
return -EPERM;
}
val = drvdata->addr_val[idx];
- mutex_unlock(&drvdata->mutex);
+ spin_unlock(&drvdata->spinlock);
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -838,17 +829,17 @@
if (sscanf(buf, "%lx", &val) != 1)
return -EINVAL;
- mutex_lock(&drvdata->mutex);
+ spin_lock(&drvdata->spinlock);
idx = drvdata->addr_idx;
if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
- mutex_unlock(&drvdata->mutex);
+ spin_unlock(&drvdata->spinlock);
return -EPERM;
}
drvdata->addr_val[idx] = val;
drvdata->addr_type[idx] = ETM_ADDR_TYPE_SINGLE;
- mutex_unlock(&drvdata->mutex);
+ spin_unlock(&drvdata->spinlock);
return size;
}
static DEVICE_ATTR(addr_single, S_IRUGO | S_IWUSR, etm_show_addr_single,
@@ -861,23 +852,23 @@
unsigned long val1, val2;
uint8_t idx;
- mutex_lock(&drvdata->mutex);
+ spin_lock(&drvdata->spinlock);
idx = drvdata->addr_idx;
if (idx % 2 != 0) {
- mutex_unlock(&drvdata->mutex);
+ spin_unlock(&drvdata->spinlock);
return -EPERM;
}
if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
(drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
- mutex_unlock(&drvdata->mutex);
+ spin_unlock(&drvdata->spinlock);
return -EPERM;
}
val1 = drvdata->addr_val[idx];
val2 = drvdata->addr_val[idx + 1];
- mutex_unlock(&drvdata->mutex);
+ spin_unlock(&drvdata->spinlock);
return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
}
@@ -895,17 +886,17 @@
if (val1 > val2)
return -EINVAL;
- mutex_lock(&drvdata->mutex);
+ spin_lock(&drvdata->spinlock);
idx = drvdata->addr_idx;
if (idx % 2 != 0) {
- mutex_unlock(&drvdata->mutex);
+ spin_unlock(&drvdata->spinlock);
return -EPERM;
}
if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
(drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
- mutex_unlock(&drvdata->mutex);
+ spin_unlock(&drvdata->spinlock);
return -EPERM;
}
@@ -914,7 +905,7 @@
drvdata->addr_val[idx + 1] = val2;
drvdata->addr_type[idx + 1] = ETM_ADDR_TYPE_RANGE;
drvdata->enable_ctrl1 |= (1 << (idx/2));
- mutex_unlock(&drvdata->mutex);
+ spin_unlock(&drvdata->spinlock);
return size;
}
static DEVICE_ATTR(addr_range, S_IRUGO | S_IWUSR, etm_show_addr_range,
@@ -927,16 +918,16 @@
unsigned long val;
uint8_t idx;
- mutex_lock(&drvdata->mutex);
+ spin_lock(&drvdata->spinlock);
idx = drvdata->addr_idx;
if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
- mutex_unlock(&drvdata->mutex);
+ spin_unlock(&drvdata->spinlock);
return -EPERM;
}
val = drvdata->addr_val[idx];
- mutex_unlock(&drvdata->mutex);
+ spin_unlock(&drvdata->spinlock);
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -951,11 +942,11 @@
if (sscanf(buf, "%lx", &val) != 1)
return -EINVAL;
- mutex_lock(&drvdata->mutex);
+ spin_lock(&drvdata->spinlock);
idx = drvdata->addr_idx;
if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
- mutex_unlock(&drvdata->mutex);
+ spin_unlock(&drvdata->spinlock);
return -EPERM;
}
@@ -963,7 +954,7 @@
drvdata->addr_type[idx] = ETM_ADDR_TYPE_START;
drvdata->startstop_ctrl |= (1 << idx);
drvdata->enable_ctrl1 |= BIT(25);
- mutex_unlock(&drvdata->mutex);
+ spin_unlock(&drvdata->spinlock);
return size;
}
static DEVICE_ATTR(addr_start, S_IRUGO | S_IWUSR, etm_show_addr_start,
@@ -976,16 +967,16 @@
unsigned long val;
uint8_t idx;
- mutex_lock(&drvdata->mutex);
+ spin_lock(&drvdata->spinlock);
idx = drvdata->addr_idx;
if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
- mutex_unlock(&drvdata->mutex);
+ spin_unlock(&drvdata->spinlock);
return -EPERM;
}
val = drvdata->addr_val[idx];
- mutex_unlock(&drvdata->mutex);
+ spin_unlock(&drvdata->spinlock);
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -1000,11 +991,11 @@
if (sscanf(buf, "%lx", &val) != 1)
return -EINVAL;
- mutex_lock(&drvdata->mutex);
+ spin_lock(&drvdata->spinlock);
idx = drvdata->addr_idx;
if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
- mutex_unlock(&drvdata->mutex);
+ spin_unlock(&drvdata->spinlock);
return -EPERM;
}
@@ -1012,7 +1003,7 @@
drvdata->addr_type[idx] = ETM_ADDR_TYPE_STOP;
drvdata->startstop_ctrl |= (1 << (idx + 16));
drvdata->enable_ctrl1 |= BIT(25);
- mutex_unlock(&drvdata->mutex);
+ spin_unlock(&drvdata->spinlock);
return size;
}
static DEVICE_ATTR(addr_stop, S_IRUGO | S_IWUSR, etm_show_addr_stop,
@@ -1024,9 +1015,9 @@
struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
- mutex_lock(&drvdata->mutex);
+ spin_lock(&drvdata->spinlock);
val = drvdata->addr_acctype[drvdata->addr_idx];
- mutex_unlock(&drvdata->mutex);
+ spin_unlock(&drvdata->spinlock);
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -1040,9 +1031,9 @@
if (sscanf(buf, "%lx", &val) != 1)
return -EINVAL;
- mutex_lock(&drvdata->mutex);
+ spin_lock(&drvdata->spinlock);
drvdata->addr_acctype[drvdata->addr_idx] = val;
- mutex_unlock(&drvdata->mutex);
+ spin_unlock(&drvdata->spinlock);
return size;
}
static DEVICE_ATTR(addr_acctype, S_IRUGO | S_IWUSR, etm_show_addr_acctype,
@@ -1069,12 +1060,13 @@
if (val >= drvdata->nr_cntr)
return -EINVAL;
- /* Use mutex to ensure index doesn't change while it gets dereferenced
- * multiple times within a mutex block elsewhere.
+ /*
+ * Use spinlock to ensure index doesn't change while it gets
+ * dereferenced multiple times within a spinlock block elsewhere.
*/
- mutex_lock(&drvdata->mutex);
+ spin_lock(&drvdata->spinlock);
drvdata->cntr_idx = val;
- mutex_unlock(&drvdata->mutex);
+ spin_unlock(&drvdata->spinlock);
return size;
}
static DEVICE_ATTR(cntr_idx, S_IRUGO | S_IWUSR, etm_show_cntr_idx,
@@ -1086,9 +1078,9 @@
struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
- mutex_lock(&drvdata->mutex);
+ spin_lock(&drvdata->spinlock);
val = drvdata->cntr_rld_val[drvdata->cntr_idx];
- mutex_unlock(&drvdata->mutex);
+ spin_unlock(&drvdata->spinlock);
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -1102,9 +1094,9 @@
if (sscanf(buf, "%lx", &val) != 1)
return -EINVAL;
- mutex_lock(&drvdata->mutex);
+ spin_lock(&drvdata->spinlock);
drvdata->cntr_rld_val[drvdata->cntr_idx] = val;
- mutex_unlock(&drvdata->mutex);
+ spin_unlock(&drvdata->spinlock);
return size;
}
static DEVICE_ATTR(cntr_rld_val, S_IRUGO | S_IWUSR, etm_show_cntr_rld_val,
@@ -1116,9 +1108,9 @@
struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
- mutex_lock(&drvdata->mutex);
+ spin_lock(&drvdata->spinlock);
val = drvdata->cntr_event[drvdata->cntr_idx];
- mutex_unlock(&drvdata->mutex);
+ spin_unlock(&drvdata->spinlock);
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -1132,9 +1124,9 @@
if (sscanf(buf, "%lx", &val) != 1)
return -EINVAL;
- mutex_lock(&drvdata->mutex);
+ spin_lock(&drvdata->spinlock);
drvdata->cntr_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK;
- mutex_unlock(&drvdata->mutex);
+ spin_unlock(&drvdata->spinlock);
return size;
}
static DEVICE_ATTR(cntr_event, S_IRUGO | S_IWUSR, etm_show_cntr_event,
@@ -1146,9 +1138,9 @@
struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
- mutex_lock(&drvdata->mutex);
+ spin_lock(&drvdata->spinlock);
val = drvdata->cntr_rld_event[drvdata->cntr_idx];
- mutex_unlock(&drvdata->mutex);
+ spin_unlock(&drvdata->spinlock);
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -1162,9 +1154,9 @@
if (sscanf(buf, "%lx", &val) != 1)
return -EINVAL;
- mutex_lock(&drvdata->mutex);
+ spin_lock(&drvdata->spinlock);
drvdata->cntr_rld_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK;
- mutex_unlock(&drvdata->mutex);
+ spin_unlock(&drvdata->spinlock);
return size;
}
static DEVICE_ATTR(cntr_rld_event, S_IRUGO | S_IWUSR, etm_show_cntr_rld_event,
@@ -1176,9 +1168,9 @@
struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
- mutex_lock(&drvdata->mutex);
+ spin_lock(&drvdata->spinlock);
val = drvdata->cntr_val[drvdata->cntr_idx];
- mutex_unlock(&drvdata->mutex);
+ spin_unlock(&drvdata->spinlock);
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -1192,9 +1184,9 @@
if (sscanf(buf, "%lx", &val) != 1)
return -EINVAL;
- mutex_lock(&drvdata->mutex);
+ spin_lock(&drvdata->spinlock);
drvdata->cntr_val[drvdata->cntr_idx] = val;
- mutex_unlock(&drvdata->mutex);
+ spin_unlock(&drvdata->spinlock);
return size;
}
static DEVICE_ATTR(cntr_val, S_IRUGO | S_IWUSR, etm_show_cntr_val,
@@ -1398,12 +1390,13 @@
if (val >= drvdata->nr_ctxid_cmp)
return -EINVAL;
- /* Use mutex to ensure index doesn't change while it gets dereferenced
- * multiple times within a mutex block elsewhere.
+ /*
+ * Use spinlock to ensure index doesn't change while it gets
+ * dereferenced multiple times within a spinlock block elsewhere.
*/
- mutex_lock(&drvdata->mutex);
+ spin_lock(&drvdata->spinlock);
drvdata->ctxid_idx = val;
- mutex_unlock(&drvdata->mutex);
+ spin_unlock(&drvdata->spinlock);
return size;
}
static DEVICE_ATTR(ctxid_idx, S_IRUGO | S_IWUSR, etm_show_ctxid_idx,
@@ -1415,9 +1408,9 @@
struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
- mutex_lock(&drvdata->mutex);
+ spin_lock(&drvdata->spinlock);
val = drvdata->ctxid_val[drvdata->ctxid_idx];
- mutex_unlock(&drvdata->mutex);
+ spin_unlock(&drvdata->spinlock);
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -1431,9 +1424,9 @@
if (sscanf(buf, "%lx", &val) != 1)
return -EINVAL;
- mutex_lock(&drvdata->mutex);
+ spin_lock(&drvdata->spinlock);
drvdata->ctxid_val[drvdata->ctxid_idx] = val;
- mutex_unlock(&drvdata->mutex);
+ spin_unlock(&drvdata->spinlock);
return size;
}
static DEVICE_ATTR(ctxid_val, S_IRUGO | S_IWUSR, etm_show_ctxid_val,
@@ -1527,26 +1520,43 @@
static int __etm_store_pcsave(struct etm_drvdata *drvdata, unsigned long val)
{
- int ret;
+ int ret = 0;
ret = clk_prepare_enable(drvdata->clk);
if (ret)
return ret;
- mutex_lock(&drvdata->mutex);
+ get_online_cpus();
+ spin_lock(&drvdata->spinlock);
if (val) {
- smp_call_function_single(drvdata->cpu, etm_enable_pcsave,
- drvdata, 1);
+ if (drvdata->pcsave_enable)
+ goto out;
+
+ ret = smp_call_function_single(drvdata->cpu, etm_enable_pcsave,
+ drvdata, 1);
+ if (ret)
+ goto out;
drvdata->pcsave_enable = true;
+
+ dev_info(drvdata->dev, "PC save enabled\n");
} else {
- smp_call_function_single(drvdata->cpu, etm_disable_pcsave,
- drvdata, 1);
+ if (!drvdata->pcsave_enable)
+ goto out;
+
+ ret = smp_call_function_single(drvdata->cpu, etm_disable_pcsave,
+ drvdata, 1);
+ if (ret)
+ goto out;
drvdata->pcsave_enable = false;
+
+ dev_info(drvdata->dev, "PC save disabled\n");
}
- mutex_unlock(&drvdata->mutex);
+out:
+ spin_unlock(&drvdata->spinlock);
+ put_online_cpus();
clk_disable_unprepare(drvdata->clk);
- return 0;
+ return ret;
}
static ssize_t etm_store_pcsave(struct device *dev,
@@ -1613,15 +1623,42 @@
NULL,
};
-/* Memory mapped writes to clear os lock not supported */
-static void etm_os_unlock(void *unused)
+static int etm_cpu_callback(struct notifier_block *nfb, unsigned long action,
+ void *hcpu)
{
- unsigned long value = 0x0;
+ unsigned int cpu = (unsigned long)hcpu;
- asm("mcr p14, 1, %0, c1, c0, 4\n\t" : : "r" (value));
- asm("isb\n\t");
+ switch (action & (~CPU_TASKS_FROZEN)) {
+ case CPU_STARTING:
+ if (etmdrvdata[cpu] && !etmdrvdata[cpu]->os_unlock) {
+ spin_lock(&etmdrvdata[cpu]->spinlock);
+ etm_os_unlock(etmdrvdata[cpu]);
+ etmdrvdata[cpu]->os_unlock = true;
+ spin_unlock(&etmdrvdata[cpu]->spinlock);
+ }
+
+ if (etmdrvdata[cpu] && etmdrvdata[cpu]->enable) {
+ spin_lock(&etmdrvdata[cpu]->spinlock);
+ __etm_enable(etmdrvdata[cpu]);
+ spin_unlock(&etmdrvdata[cpu]->spinlock);
+ }
+ break;
+
+ case CPU_DYING:
+ if (etmdrvdata[cpu] && etmdrvdata[cpu]->enable) {
+ spin_lock(&etmdrvdata[cpu]->spinlock);
+ __etm_disable(etmdrvdata[cpu]);
+ spin_unlock(&etmdrvdata[cpu]->spinlock);
+ }
+ break;
+ }
+ return NOTIFY_OK;
}
+static struct notifier_block etm_cpu_notifier = {
+ .notifier_call = etm_cpu_callback,
+};
+
static bool __devinit etm_arch_supported(uint8_t arch)
{
switch (arch) {
@@ -1633,15 +1670,6 @@
return true;
}
-static void __devinit etm_prepare_arch(struct etm_drvdata *drvdata)
-{
- /* Unlock OS lock first to allow memory mapped reads and writes. This
- * is required for Krait pass1
- * */
- etm_os_unlock(NULL);
- smp_call_function(etm_os_unlock, NULL, 1);
-}
-
static void __devinit etm_init_arch_data(void *info)
{
uint32_t etmidr;
@@ -1677,19 +1705,18 @@
drvdata->nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
etm_set_pwrdwn(drvdata);
- /* Vote for ETM power/clock disable */
etm_clr_pwrup(drvdata);
ETM_LOCK(drvdata);
}
static void __devinit etm_copy_arch_data(struct etm_drvdata *drvdata)
{
- drvdata->arch = etm0drvdata->arch;
- drvdata->nr_addr_cmp = etm0drvdata->nr_addr_cmp;
- drvdata->nr_cntr = etm0drvdata->nr_cntr;
- drvdata->nr_ext_inp = etm0drvdata->nr_ext_inp;
- drvdata->nr_ext_out = etm0drvdata->nr_ext_out;
- drvdata->nr_ctxid_cmp = etm0drvdata->nr_ctxid_cmp;
+ drvdata->arch = etmdrvdata[0]->arch;
+ drvdata->nr_addr_cmp = etmdrvdata[0]->nr_addr_cmp;
+ drvdata->nr_cntr = etmdrvdata[0]->nr_cntr;
+ drvdata->nr_ext_inp = etmdrvdata[0]->nr_ext_inp;
+ drvdata->nr_ext_out = etmdrvdata[0]->nr_ext_out;
+ drvdata->nr_ctxid_cmp = etmdrvdata[0]->nr_ctxid_cmp;
}
static void __devinit etm_init_default_data(struct etm_drvdata *drvdata)
@@ -1774,7 +1801,7 @@
if (!drvdata->base)
return -ENOMEM;
- mutex_init(&drvdata->mutex);
+ spin_lock_init(&drvdata->spinlock);
wake_lock_init(&drvdata->wake_lock, WAKE_LOCK_SUSPEND, "coresight-etm");
drvdata->clk = devm_clk_get(dev, "core_clk");
@@ -1787,23 +1814,32 @@
if (ret)
goto err0;
- drvdata->cpu = count++;
-
ret = clk_prepare_enable(drvdata->clk);
if (ret)
goto err0;
- /* Use CPU0 to populate read-only configuration data for ETM0. For other
- * ETMs copy it over from ETM0.
+ drvdata->cpu = count++;
+
+ get_online_cpus();
+ etmdrvdata[drvdata->cpu] = drvdata;
+
+ if (!smp_call_function_single(drvdata->cpu, etm_os_unlock, NULL, 1))
+ drvdata->os_unlock = true;
+ /*
+ * Use CPU0 to populate read-only configuration data for ETM0. For
+ * other ETMs copy it over from ETM0.
*/
if (drvdata->cpu == 0) {
- etm_prepare_arch(drvdata);
- smp_call_function_single(drvdata->cpu, etm_init_arch_data,
- drvdata, 1);
- etm0drvdata = drvdata;
+ register_hotcpu_notifier(&etm_cpu_notifier);
+ if (smp_call_function_single(drvdata->cpu, etm_init_arch_data,
+ drvdata, 1))
+ dev_err(dev, "ETM arch init failed\n");
} else {
etm_copy_arch_data(drvdata);
}
+
+ put_online_cpus();
+
if (etm_arch_supported(drvdata->arch) == false) {
ret = -EINVAL;
goto err1;
@@ -1821,7 +1857,7 @@
ret = msm_dump_table_register(&dump);
if (ret) {
devm_kfree(dev, baddr);
- dev_err(dev, "ETM REG dump setup failed\n");
+ dev_err(dev, "ETM REG dump setup failed/unsupported\n");
}
} else {
dev_err(dev, "ETM REG dump space allocation failed\n");
@@ -1830,7 +1866,7 @@
desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
if (!desc) {
ret = -ENOMEM;
- goto err0;
+ goto err2;
}
desc->type = CORESIGHT_DEV_TYPE_SOURCE;
desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
@@ -1842,7 +1878,7 @@
drvdata->csdev = coresight_register(desc);
if (IS_ERR(drvdata->csdev)) {
ret = PTR_ERR(drvdata->csdev);
- goto err0;
+ goto err2;
}
if (pdev->dev.of_node)
@@ -1864,11 +1900,17 @@
__etm_store_pcsave(drvdata, true);
return 0;
+err2:
+ if (drvdata->cpu == 0)
+ unregister_hotcpu_notifier(&etm_cpu_notifier);
+ wake_lock_destroy(&drvdata->wake_lock);
+ return ret;
err1:
+ if (drvdata->cpu == 0)
+ unregister_hotcpu_notifier(&etm_cpu_notifier);
clk_disable_unprepare(drvdata->clk);
err0:
wake_lock_destroy(&drvdata->wake_lock);
- mutex_destroy(&drvdata->mutex);
return ret;
}
@@ -1878,8 +1920,9 @@
device_remove_file(&drvdata->csdev->dev, &dev_attr_pcsave);
coresight_unregister(drvdata->csdev);
+ if (drvdata->cpu == 0)
+ unregister_hotcpu_notifier(&etm_cpu_notifier);
wake_lock_destroy(&drvdata->wake_lock);
- mutex_destroy(&drvdata->mutex);
return 0;
}
diff --git a/drivers/coresight/coresight-stm.c b/drivers/coresight/coresight-stm.c
index f6a948b..1379c55 100644
--- a/drivers/coresight/coresight-stm.c
+++ b/drivers/coresight/coresight-stm.c
@@ -24,6 +24,7 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/clk.h>
+#include <linux/bitmap.h>
#include <linux/of_coresight.h>
#include <linux/coresight.h>
#include <linux/coresight-stm.h>
@@ -45,44 +46,47 @@
mb(); \
} while (0)
-#define STMDMASTARTR (0xC04)
-#define STMDMASTOPR (0xC08)
-#define STMDMASTATR (0xC0C)
-#define STMDMACTLR (0xC10)
-#define STMDMAIDR (0xCFC)
-#define STMHEER (0xD00)
-#define STMHETER (0xD20)
-#define STMHEMCR (0xD64)
-#define STMHEMASTR (0xDF4)
-#define STMHEFEAT1R (0xDF8)
-#define STMHEIDR (0xDFC)
-#define STMSPER (0xE00)
-#define STMSPTER (0xE20)
-#define STMSPSCR (0xE60)
-#define STMSPMSCR (0xE64)
-#define STMSPOVERRIDER (0xE68)
-#define STMSPMOVERRIDER (0xE6C)
-#define STMSPTRIGCSR (0xE70)
-#define STMTCSR (0xE80)
-#define STMTSSTIMR (0xE84)
-#define STMTSFREQR (0xE8C)
-#define STMSYNCR (0xE90)
-#define STMAUXCR (0xE94)
-#define STMSPFEAT1R (0xEA0)
-#define STMSPFEAT2R (0xEA4)
-#define STMSPFEAT3R (0xEA8)
-#define STMITTRIGGER (0xEE8)
-#define STMITATBDATA0 (0xEEC)
-#define STMITATBCTR2 (0xEF0)
-#define STMITATBID (0xEF4)
-#define STMITATBCTR0 (0xEF8)
+#define STMDMASTARTR (0xC04)
+#define STMDMASTOPR (0xC08)
+#define STMDMASTATR (0xC0C)
+#define STMDMACTLR (0xC10)
+#define STMDMAIDR (0xCFC)
+#define STMHEER (0xD00)
+#define STMHETER (0xD20)
+#define STMHEMCR (0xD64)
+#define STMHEMASTR (0xDF4)
+#define STMHEFEAT1R (0xDF8)
+#define STMHEIDR (0xDFC)
+#define STMSPER (0xE00)
+#define STMSPTER (0xE20)
+#define STMSPSCR (0xE60)
+#define STMSPMSCR (0xE64)
+#define STMSPOVERRIDER (0xE68)
+#define STMSPMOVERRIDER (0xE6C)
+#define STMSPTRIGCSR (0xE70)
+#define STMTCSR (0xE80)
+#define STMTSSTIMR (0xE84)
+#define STMTSFREQR (0xE8C)
+#define STMSYNCR (0xE90)
+#define STMAUXCR (0xE94)
+#define STMSPFEAT1R (0xEA0)
+#define STMSPFEAT2R (0xEA4)
+#define STMSPFEAT3R (0xEA8)
+#define STMITTRIGGER (0xEE8)
+#define STMITATBDATA0 (0xEEC)
+#define STMITATBCTR2 (0xEF0)
+#define STMITATBID (0xEF4)
+#define STMITATBCTR0 (0xEF8)
-#define NR_STM_CHANNEL (32)
-#define BYTES_PER_CHANNEL (256)
-#define STM_TRACE_BUF_SIZE (1024)
+#define NR_STM_CHANNEL (32)
+#define BYTES_PER_CHANNEL (256)
+#define STM_TRACE_BUF_SIZE (4096)
+#define STM_USERSPACE_HEADER_SIZE (8)
+#define STM_USERSPACE_MAGIC1_VAL (0xf0)
+#define STM_USERSPACE_MAGIC2_VAL (0xf1)
-#define OST_START_TOKEN (0x30)
-#define OST_VERSION (0x1)
+#define OST_START_TOKEN (0x30)
+#define OST_VERSION (0x1)
enum stm_pkt_type {
STM_PKT_TYPE_DATA = 0x98,
@@ -128,7 +132,7 @@
spinlock_t spinlock;
struct channel_space chs;
bool enable;
- uint32_t entity;
+ DECLARE_BITMAP(entities, OST_ENTITY_MAX);
};
static struct stm_drvdata *stmdrvdata;
@@ -482,7 +486,8 @@
struct stm_drvdata *drvdata = stmdrvdata;
/* we don't support sizes more than 24bits (0 to 23) */
- if (!(drvdata && drvdata->enable && (drvdata->entity & entity_id) &&
+ if (!(drvdata && drvdata->enable &&
+ test_bit(entity_id, drvdata->entities) && size &&
(size < 0x1000000)))
return 0;
@@ -496,13 +501,12 @@
struct stm_drvdata *drvdata = container_of(file->private_data,
struct stm_drvdata, miscdev);
char *buf;
+ uint8_t entity_id, proto_id;
+ uint32_t options;
- if (!drvdata->enable)
+ if (!drvdata->enable || !size)
return -EINVAL;
- if (!(drvdata->entity & OST_ENTITY_DEV_NODE))
- return size;
-
if (size > STM_TRACE_BUF_SIZE)
size = STM_TRACE_BUF_SIZE;
@@ -516,7 +520,32 @@
return -EFAULT;
}
- __stm_trace(STM_OPTION_TIMESTAMPED, OST_ENTITY_DEV_NODE, 0, buf, size);
+ if (size >= STM_USERSPACE_HEADER_SIZE &&
+ buf[0] == STM_USERSPACE_MAGIC1_VAL &&
+ buf[1] == STM_USERSPACE_MAGIC2_VAL) {
+
+ entity_id = buf[2];
+ proto_id = buf[3];
+ options = *(uint32_t *)(buf + 4);
+
+ if (!test_bit(entity_id, drvdata->entities) ||
+ !(size - STM_USERSPACE_HEADER_SIZE)) {
+ kfree(buf);
+ return size;
+ }
+
+ __stm_trace(options, entity_id, proto_id,
+ buf + STM_USERSPACE_HEADER_SIZE,
+ size - STM_USERSPACE_HEADER_SIZE);
+ } else {
+ if (!test_bit(OST_ENTITY_DEV_NODE, drvdata->entities)) {
+ kfree(buf);
+ return size;
+ }
+
+ __stm_trace(STM_OPTION_TIMESTAMPED, OST_ENTITY_DEV_NODE, 0,
+ buf, size);
+ }
kfree(buf);
@@ -594,35 +623,50 @@
static DEVICE_ATTR(port_enable, S_IRUGO | S_IWUSR, stm_show_port_enable,
stm_store_port_enable);
-static ssize_t stm_show_entity(struct device *dev,
+static ssize_t stm_show_entities(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- unsigned long val = drvdata->entity;
+ ssize_t len;
- return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+ len = bitmap_scnprintf(buf, PAGE_SIZE, drvdata->entities,
+ OST_ENTITY_MAX);
+
+ if (PAGE_SIZE - len < 2)
+ len = -EINVAL;
+ else
+ len += scnprintf(buf + len, 2, "\n");
+
+ return len;
}
-static ssize_t stm_store_entity(struct device *dev,
+static ssize_t stm_store_entities(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- unsigned long val;
+ unsigned long val1, val2;
- if (sscanf(buf, "%lx", &val) != 1)
+ if (sscanf(buf, "%lx %lx", &val1, &val2) != 2)
return -EINVAL;
- drvdata->entity = val;
+ if (val1 >= OST_ENTITY_MAX)
+ return -EINVAL;
+
+ if (val2)
+ __set_bit(val1, drvdata->entities);
+ else
+ __clear_bit(val1, drvdata->entities);
+
return size;
}
-static DEVICE_ATTR(entity, S_IRUGO | S_IWUSR, stm_show_entity,
- stm_store_entity);
+static DEVICE_ATTR(entities, S_IRUGO | S_IWUSR, stm_show_entities,
+ stm_store_entities);
static struct attribute *stm_attrs[] = {
&dev_attr_hwevent_enable.attr,
&dev_attr_port_enable.attr,
- &dev_attr_entity.attr,
+ &dev_attr_entities.attr,
NULL,
};
@@ -698,7 +742,7 @@
if (ret)
return ret;
- drvdata->entity = OST_ENTITY_ALL;
+ bitmap_fill(drvdata->entities, OST_ENTITY_MAX);
desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
if (!desc)
diff --git a/drivers/coresight/coresight-tmc.c b/drivers/coresight/coresight-tmc.c
index 13f69cd..3bb9ec7 100644
--- a/drivers/coresight/coresight-tmc.c
+++ b/drivers/coresight/coresight-tmc.c
@@ -1043,8 +1043,7 @@
if (drvdata->config_type == TMC_CONFIG_TYPE_ETR)
drvdata->size = SZ_1M;
else
- drvdata->size = (tmc_readl(drvdata, TMC_RSZ) * BYTES_PER_WORD)
- + PAGE_SIZE;
+ drvdata->size = tmc_readl(drvdata, TMC_RSZ) * BYTES_PER_WORD;
clk_disable_unprepare(drvdata->clk);
@@ -1067,7 +1066,8 @@
if (ret)
goto err0;
} else {
- baddr = devm_kzalloc(dev, drvdata->size, GFP_KERNEL);
+ baddr = devm_kzalloc(dev, PAGE_SIZE + drvdata->size,
+ GFP_KERNEL);
if (!baddr)
return -ENOMEM;
drvdata->buf = baddr + PAGE_SIZE;
@@ -1075,7 +1075,7 @@
TMC_ETFETB_DUMP_VER;
dump.id = MSM_TMC_ETFETB + etfetb_count;
dump.start_addr = virt_to_phys(baddr);
- dump.end_addr = dump.start_addr + drvdata->size;
+ dump.end_addr = dump.start_addr + PAGE_SIZE + drvdata->size;
ret = msm_dump_table_register(&dump);
/* Don't free the buffer in case of error since it can still
* be used to provide dump collection via the device node
diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c
index f834ea8..63cdc68 100644
--- a/drivers/cpufreq/cpufreq_interactive.c
+++ b/drivers/cpufreq/cpufreq_interactive.c
@@ -972,6 +972,9 @@
spin_lock_init(&down_cpumask_lock);
mutex_init(&set_speed_lock);
+ /* Kick the kthread to idle */
+ wake_up_process(up_task);
+
idle_notifier_register(&cpufreq_interactive_idle_nb);
INIT_WORK(&inputopen.inputopen_work, cpufreq_interactive_input_open);
return cpufreq_register_governor(&cpufreq_gov_interactive);
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 785ba6c..4b03cfd 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -115,7 +115,12 @@
static struct workqueue_struct *input_wq;
-static DEFINE_PER_CPU(struct work_struct, dbs_refresh_work);
+struct dbs_work_struct {
+ struct work_struct work;
+ unsigned int cpu;
+};
+
+static DEFINE_PER_CPU(struct dbs_work_struct, dbs_refresh_work);
static struct dbs_tuners {
unsigned int sampling_rate;
@@ -831,11 +836,15 @@
return 0;
}
-static void dbs_refresh_callback(struct work_struct *unused)
+static void dbs_refresh_callback(struct work_struct *work)
{
struct cpufreq_policy *policy;
struct cpu_dbs_info_s *this_dbs_info;
- unsigned int cpu = smp_processor_id();
+ struct dbs_work_struct *dbs_work;
+ unsigned int cpu;
+
+ dbs_work = container_of(work, struct dbs_work_struct, work);
+ cpu = dbs_work->cpu;
get_online_cpus();
@@ -877,9 +886,8 @@
return;
}
- for_each_online_cpu(i) {
- queue_work_on(i, input_wq, &per_cpu(dbs_refresh_work, i));
- }
+ for_each_online_cpu(i)
+ queue_work_on(i, input_wq, &per_cpu(dbs_refresh_work, i).work);
}
static int dbs_input_connect(struct input_handler *handler,
@@ -1072,8 +1080,12 @@
for_each_possible_cpu(i) {
struct cpu_dbs_info_s *this_dbs_info =
&per_cpu(od_cpu_dbs_info, i);
+ struct dbs_work_struct *dbs_work =
+ &per_cpu(dbs_refresh_work, i);
+
mutex_init(&this_dbs_info->timer_mutex);
- INIT_WORK(&per_cpu(dbs_refresh_work, i), dbs_refresh_callback);
+ INIT_WORK(&dbs_work->work, dbs_refresh_callback);
+ dbs_work->cpu = i;
}
return cpufreq_register_governor(&cpufreq_gov_ondemand);
diff --git a/drivers/gpio/qpnp-pin.c b/drivers/gpio/qpnp-pin.c
index 67a2e6b..527fd1b 100644
--- a/drivers/gpio/qpnp-pin.c
+++ b/drivers/gpio/qpnp-pin.c
@@ -128,7 +128,7 @@
Q_PIN_CFG_PULL,
Q_PIN_CFG_VIN_SEL,
Q_PIN_CFG_OUT_STRENGTH,
- Q_PIN_CFG_SELECT,
+ Q_PIN_CFG_SRC_SEL,
Q_PIN_CFG_MASTER_EN,
Q_PIN_CFG_AOUT_REF,
Q_PIN_CFG_AIN_ROUTE,
@@ -289,7 +289,7 @@
val == 0)
return -EINVAL;
break;
- case Q_PIN_CFG_SELECT:
+ case Q_PIN_CFG_SRC_SEL:
if (q_spec->type == Q_MPP_TYPE &&
(val == QPNP_PIN_SEL_FUNC_1 ||
val == QPNP_PIN_SEL_FUNC_2))
@@ -348,9 +348,9 @@
else if (Q_CHK_INVALID(Q_PIN_CFG_INVERT, q_spec, param->invert))
pr_err("invalid invert polarity value %d for %s %d\n",
param->invert, name, pin);
- else if (Q_CHK_INVALID(Q_PIN_CFG_SELECT, q_spec, param->select))
+ else if (Q_CHK_INVALID(Q_PIN_CFG_SRC_SEL, q_spec, param->src_sel))
pr_err("invalid source select value %d for %s %d\n",
- param->select, name, pin);
+ param->src_sel, name, pin);
else if (Q_CHK_INVALID(Q_PIN_CFG_OUT_STRENGTH,
q_spec, param->out_strength))
pr_err("invalid out strength value %d for %s %d\n",
@@ -506,10 +506,10 @@
q_reg_clr_set(&q_spec->regs[Q_REG_I_MODE_CTL],
Q_REG_OUT_INVERT_SHIFT, Q_REG_OUT_INVERT_MASK,
param->invert);
- if (Q_HAVE_HW_SP(Q_PIN_CFG_SELECT, q_spec, param->select))
+ if (Q_HAVE_HW_SP(Q_PIN_CFG_SRC_SEL, q_spec, param->src_sel))
q_reg_clr_set(&q_spec->regs[Q_REG_I_MODE_CTL],
Q_REG_SRC_SEL_SHIFT, Q_REG_SRC_SEL_MASK,
- param->select);
+ param->src_sel);
if (Q_HAVE_HW_SP(Q_PIN_CFG_OUT_STRENGTH, q_spec, param->out_strength))
q_reg_clr_set(&q_spec->regs[Q_REG_I_DIG_OUT_CTL],
Q_REG_OUT_STRENGTH_SHIFT, Q_REG_OUT_STRENGTH_MASK,
@@ -828,7 +828,7 @@
param.out_strength = q_reg_get(&q_spec->regs[Q_REG_I_DIG_OUT_CTL],
Q_REG_OUT_STRENGTH_SHIFT,
Q_REG_OUT_STRENGTH_MASK);
- param.select = q_reg_get(&q_spec->regs[Q_REG_I_MODE_CTL],
+ param.src_sel = q_reg_get(&q_spec->regs[Q_REG_I_MODE_CTL],
Q_REG_SRC_SEL_SHIFT, Q_REG_SRC_SEL_MASK);
param.master_en = q_reg_get(&q_spec->regs[Q_REG_I_EN_CTL],
Q_REG_MASTER_EN_SHIFT,
@@ -855,8 +855,8 @@
¶m.vin_sel);
of_property_read_u32(node, "qcom,out-strength",
¶m.out_strength);
- of_property_read_u32(node, "qcom,src-select",
- ¶m.select);
+ of_property_read_u32(node, "qcom,src-sel",
+ ¶m.src_sel);
of_property_read_u32(node, "qcom,master-en",
¶m.master_en);
of_property_read_u32(node, "qcom,aout-ref",
@@ -942,7 +942,7 @@
cfg->shift = Q_REG_OUT_STRENGTH_SHIFT;
cfg->mask = Q_REG_OUT_STRENGTH_MASK;
break;
- case Q_PIN_CFG_SELECT:
+ case Q_PIN_CFG_SRC_SEL:
cfg->addr = Q_REG_MODE_CTL;
cfg->idx = Q_REG_I_MODE_CTL;
cfg->shift = Q_REG_SRC_SEL_SHIFT;
@@ -1036,7 +1036,7 @@
{ Q_PIN_CFG_PULL, "pull" },
{ Q_PIN_CFG_VIN_SEL, "vin_sel" },
{ Q_PIN_CFG_OUT_STRENGTH, "out_strength" },
- { Q_PIN_CFG_SELECT, "select" },
+ { Q_PIN_CFG_SRC_SEL, "src_sel" },
{ Q_PIN_CFG_MASTER_EN, "master_en" },
{ Q_PIN_CFG_AOUT_REF, "aout_ref" },
{ Q_PIN_CFG_AIN_ROUTE, "ain_route" },
diff --git a/drivers/gpu/ion/ion_cp_heap.c b/drivers/gpu/ion/ion_cp_heap.c
index f9a9212..aa3469c 100644
--- a/drivers/gpu/ion/ion_cp_heap.c
+++ b/drivers/gpu/ion/ion_cp_heap.c
@@ -399,14 +399,16 @@
return ION_CP_ALLOCATE_FAIL;
}
- if (secure_allocation &&
- (cp_heap->umap_count > 0 || cp_heap->kmap_cached_count > 0)) {
- mutex_unlock(&cp_heap->lock);
- pr_err("ION cannot allocate secure memory from heap with "
- "outstanding mappings: User space: %lu, kernel space "
- "(cached): %lu\n", cp_heap->umap_count,
- cp_heap->kmap_cached_count);
- return ION_CP_ALLOCATE_FAIL;
+ /*
+ * The check above already checked for non-secure allocations when the
+ * heap is protected. HEAP_PROTECTED implies that this must be a secure
+ * allocation. If the heap is protected and there are userspace or
+ * cached kernel mappings, something has gone wrong in the security
+ * model.
+ */
+ if (cp_heap->heap_protected == HEAP_PROTECTED) {
+ BUG_ON(cp_heap->umap_count != 0);
+ BUG_ON(cp_heap->kmap_cached_count != 0);
}
/*
@@ -569,18 +571,11 @@
if (!table)
return ERR_PTR(-ENOMEM);
- if (buf->is_secure) {
+ if (buf->is_secure && IS_ALIGNED(buffer->size, SZ_1M)) {
int n_chunks;
int i;
struct scatterlist *sg;
- if (!IS_ALIGNED(buffer->size, SZ_1M)) {
- pr_err("%s: buffer is marked as secure but buffer size %x is not aligned to 1MB\n",
- __func__, buffer->size);
-
- return ERR_PTR(-EINVAL);
- }
-
/* Count number of 1MB chunks. Alignment is already checked. */
n_chunks = buffer->size >> 20;
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index bec19e2..f9d0316 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -38,6 +38,7 @@
/* Command identifiers */
#define KGSL_CONTEXT_TO_MEM_IDENTIFIER 0x2EADBEEF
#define KGSL_CMD_IDENTIFIER 0x2EEDFACE
+#define KGSL_CMD_INTERNAL_IDENTIFIER 0x2EEDD00D
#define KGSL_START_OF_IB_IDENTIFIER 0x2EADEABE
#define KGSL_END_OF_IB_IDENTIFIER 0x2ABEDEAD
diff --git a/drivers/gpu/msm/adreno_postmortem.c b/drivers/gpu/msm/adreno_postmortem.c
index daa78ed..e069fa5 100644
--- a/drivers/gpu/msm/adreno_postmortem.c
+++ b/drivers/gpu/msm/adreno_postmortem.c
@@ -70,6 +70,14 @@
{CP_WAIT_FOR_IDLE, "WAIT4IDL"},
};
+static const struct pm_id_name pm3_nop_values[] = {
+ {KGSL_CONTEXT_TO_MEM_IDENTIFIER, "CTX_SWCH"},
+ {KGSL_CMD_IDENTIFIER, "CMD__EXT"},
+ {KGSL_CMD_INTERNAL_IDENTIFIER, "CMD__INT"},
+ {KGSL_START_OF_IB_IDENTIFIER, "IB_START"},
+ {KGSL_END_OF_IB_IDENTIFIER, "IB___END"},
+};
+
static uint32_t adreno_is_pm4_len(uint32_t word)
{
if (word == INVALID_RB_CMD)
@@ -129,6 +137,28 @@
return "????????";
}
+static bool adreno_is_pm3_nop_value(uint32_t word)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(pm3_nop_values); ++i) {
+ if (word == pm3_nop_values[i].id)
+ return 1;
+ }
+ return 0;
+}
+
+static const char *adreno_pm3_nop_name(uint32_t word)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(pm3_nop_values); ++i) {
+ if (word == pm3_nop_values[i].id)
+ return pm3_nop_values[i].name;
+ }
+ return "????????";
+}
+
static void adreno_dump_regs(struct kgsl_device *device,
const int *registers, int size)
{
@@ -245,8 +275,13 @@
"%s", adreno_pm4_name(ptr4[j]));
*argp = -(adreno_is_pm4_len(ptr4[j])+1);
} else {
- lx += scnprintf(linebuf + lx, linebuflen - lx,
- "%8.8X", ptr4[j]);
+ if (adreno_is_pm3_nop_value(ptr4[j]))
+ lx += scnprintf(linebuf + lx, linebuflen - lx,
+ "%s", adreno_pm3_nop_name(ptr4[j]));
+ else
+ lx += scnprintf(linebuf + lx, linebuflen - lx,
+ "%8.8X", ptr4[j]);
+
if (*argp > 1)
--*argp;
else if (*argp == 1) {
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index da9daf7..e5a790f 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -524,6 +524,9 @@
total_sizedwords += flags & KGSL_CMD_FLAGS_PMODE ? 4 : 0;
/* 2 dwords to store the start of command sequence */
total_sizedwords += 2;
+ /* internal ib command identifier for the ringbuffer */
+ total_sizedwords += (flags & KGSL_CMD_FLAGS_INTERNAL_ISSUE) ? 2 : 0;
+
/*
* Add CP_COND_EXEC commands to generate CP_INTERRUPT only
* for submissions from userspace.
@@ -560,6 +563,11 @@
GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_nop_packet(1));
GSL_RB_WRITE(ringcmds, rcmd_gpu, KGSL_CMD_IDENTIFIER);
+ if (flags & KGSL_CMD_FLAGS_INTERNAL_ISSUE) {
+ GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_nop_packet(1));
+ GSL_RB_WRITE(ringcmds, rcmd_gpu, KGSL_CMD_INTERNAL_IDENTIFIER);
+ }
+
if (flags & KGSL_CMD_FLAGS_PMODE) {
/* disable protected mode error checking */
GSL_RB_WRITE(ringcmds, rcmd_gpu,
diff --git a/drivers/gpu/msm/kgsl_drm.c b/drivers/gpu/msm/kgsl_drm.c
index 2003098..119e25d 100644
--- a/drivers/gpu/msm/kgsl_drm.c
+++ b/drivers/gpu/msm/kgsl_drm.c
@@ -17,6 +17,7 @@
#include "drmP.h"
#include "drm.h"
#include <linux/android_pmem.h>
+#include <linux/msm_ion.h>
#include "kgsl.h"
#include "kgsl_device.h"
@@ -106,6 +107,7 @@
uint32_t type;
struct kgsl_memdesc memdesc;
struct kgsl_pagetable *pagetable;
+ struct ion_handle *ion_handle;
uint64_t mmap_offset;
int bufcount;
int flags;
@@ -129,6 +131,8 @@
struct list_head wait_list;
};
+static struct ion_client *kgsl_drm_ion_phys_client;
+
static int kgsl_drm_inited = DRM_KGSL_NOT_INITED;
/* This is a global list of all the memory currently mapped in the MMU */
@@ -243,15 +247,50 @@
if (TYPE_IS_PMEM(priv->type)) {
if (priv->type == DRM_KGSL_GEM_TYPE_EBI ||
priv->type & DRM_KGSL_GEM_PMEM_EBI) {
- result = kgsl_sharedmem_ebimem_user(
- &priv->memdesc,
- priv->pagetable,
- obj->size * priv->bufcount);
- if (result) {
- DRM_ERROR(
- "Unable to allocate PMEM memory\n");
- return result;
- }
+ priv->ion_handle = ion_alloc(kgsl_drm_ion_phys_client,
+ obj->size * priv->bufcount, PAGE_SIZE,
+ ION_HEAP(ION_SF_HEAP_ID), 0);
+ if (IS_ERR_OR_NULL(priv->ion_handle)) {
+ DRM_ERROR(
+ "Unable to allocate ION Phys memory handle\n");
+ return -ENOMEM;
+ }
+
+ priv->memdesc.pagetable = priv->pagetable;
+
+ result = ion_phys(kgsl_drm_ion_phys_client,
+ priv->ion_handle, (ion_phys_addr_t *)
+ &priv->memdesc.physaddr, &priv->memdesc.size);
+ if (result) {
+ DRM_ERROR(
+ "Unable to get ION Physical memory address\n");
+ ion_free(kgsl_drm_ion_phys_client,
+ priv->ion_handle);
+ priv->ion_handle = NULL;
+ return result;
+ }
+
+ result = memdesc_sg_phys(&priv->memdesc,
+ priv->memdesc.physaddr, priv->memdesc.size);
+ if (result) {
+ DRM_ERROR(
+ "Unable to get sg list\n");
+ ion_free(kgsl_drm_ion_phys_client,
+ priv->ion_handle);
+ priv->ion_handle = NULL;
+ return result;
+ }
+
+ result = kgsl_mmu_map(priv->pagetable, &priv->memdesc,
+ GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
+ if (result) {
+ DRM_ERROR(
+ "Unable to map GPU\n");
+ ion_free(kgsl_drm_ion_phys_client,
+ priv->ion_handle);
+ priv->ion_handle = NULL;
+ return result;
+ }
}
else
return -EINVAL;
@@ -296,7 +335,16 @@
kgsl_gem_mem_flush(&priv->memdesc, priv->type,
DRM_KGSL_GEM_CACHE_OP_FROM_DEV);
- kgsl_sharedmem_free(&priv->memdesc);
+ if (priv->memdesc.gpuaddr)
+ kgsl_mmu_unmap(priv->memdesc.pagetable, &priv->memdesc);
+
+ kgsl_sg_free(priv->memdesc.sg, priv->memdesc.sglen);
+
+ if (priv->ion_handle)
+ ion_free(kgsl_drm_ion_phys_client, priv->ion_handle);
+ priv->ion_handle = NULL;
+
+ memset(&priv->memdesc, 0, sizeof(priv->memdesc));
kgsl_mmu_putpagetable(priv->pagetable);
priv->pagetable = NULL;
@@ -1447,6 +1495,16 @@
DRM_MASTER),
};
+static const struct file_operations kgsl_drm_driver_fops = {
+ .owner = THIS_MODULE,
+ .open = drm_open,
+ .release = drm_release,
+ .unlocked_ioctl = drm_ioctl,
+ .mmap = msm_drm_gem_mmap,
+ .poll = drm_poll,
+ .fasync = drm_fasync,
+};
+
static struct drm_driver driver = {
.driver_features = DRIVER_GEM,
.load = kgsl_drm_load,
@@ -1458,17 +1516,7 @@
.gem_init_object = kgsl_gem_init_object,
.gem_free_object = kgsl_gem_free_object,
.ioctls = kgsl_drm_ioctls,
-
- .fops = {
- .owner = THIS_MODULE,
- .open = drm_open,
- .release = drm_release,
- .unlocked_ioctl = drm_ioctl,
- .mmap = msm_drm_gem_mmap,
- .poll = drm_poll,
- .fasync = drm_fasync,
- },
-
+ .fops = &kgsl_drm_driver_fops,
.name = DRIVER_NAME,
.desc = DRIVER_DESC,
.date = DRIVER_DATE,
@@ -1497,6 +1545,14 @@
gem_buf_fence[i].fence_id = ENTRY_EMPTY;
}
+ /* Create ION Client */
+ kgsl_drm_ion_phys_client = msm_ion_client_create(
+ ION_HEAP_CARVEOUT_MASK, ION_SF_HEAP_NAME);
+ if (!kgsl_drm_ion_phys_client) {
+ DRM_ERROR("Unable to create ION client\n");
+ return -ENOMEM;
+ }
+
return drm_platform_init(&driver, dev);
}
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index a70647a..be51c11 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.c
@@ -541,27 +541,8 @@
struct page **pages = NULL;
pgprot_t page_prot = pgprot_writecombine(PAGE_KERNEL);
void *ptr;
- struct sysinfo si;
unsigned int align;
- /*
- * Get the current memory information to be used in deciding if we
- * should go ahead with this allocation
- */
-
- si_meminfo(&si);
-
- /*
- * Limit the size of the allocation to the amount of free memory minus
- * 32MB. Why 32MB? Because thats the buffer that page_alloc uses and
- * it just seems like a reasonable limit that won't make the OOM killer
- * go all serial on us. Of course, if we are down this low all bets
- * are off but above all do no harm.
- */
-
- if (size >= ((si.freeram << PAGE_SHIFT) - SZ_32M))
- return -ENOMEM;
-
align = (memdesc->flags & KGSL_MEMALIGN_MASK) >> KGSL_MEMALIGN_SHIFT;
page_size = (align >= ilog2(SZ_64K) && size >= SZ_64K)
@@ -623,7 +604,7 @@
while (len > 0) {
struct page *page;
unsigned int gfp_mask = GFP_KERNEL | __GFP_HIGHMEM |
- __GFP_NOWARN;
+ __GFP_NOWARN | __GFP_NORETRY;
int j;
/* don't waste space at the end of the allocation*/
@@ -640,6 +621,13 @@
page_size = PAGE_SIZE;
continue;
}
+
+ KGSL_CORE_ERR(
+ "Out of memory: only allocated %dKB of %dKB requested\n",
+ (size - len) >> 10, size >> 10);
+
+ ret = -ENOMEM;
+ goto done;
}
for (j = 0; j < page_size >> PAGE_SHIFT; j++)
diff --git a/drivers/hwmon/qpnp-adc-current.c b/drivers/hwmon/qpnp-adc-current.c
index 0a85b93..10c5a17 100644
--- a/drivers/hwmon/qpnp-adc-current.c
+++ b/drivers/hwmon/qpnp-adc-current.c
@@ -672,9 +672,9 @@
qpnp_adc_attr.index = iadc->adc->adc_channels[i].channel_num;
qpnp_adc_attr.dev_attr.attr.name =
iadc->adc->adc_channels[i].name;
- sysfs_attr_init(&iadc->sens_attr[i].dev_attr.attr);
memcpy(&iadc->sens_attr[i], &qpnp_adc_attr,
sizeof(qpnp_adc_attr));
+ sysfs_attr_init(&iadc->sens_attr[i].dev_attr.attr);
rc = device_create_file(&spmi->dev,
&iadc->sens_attr[i].dev_attr);
if (rc) {
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index 5690c88..5eef34f 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -714,9 +714,9 @@
qpnp_adc_attr.index = vadc->adc->adc_channels[i].channel_num;
qpnp_adc_attr.dev_attr.attr.name =
vadc->adc->adc_channels[i].name;
- sysfs_attr_init(&vadc->sens_attr[i].dev_attr.attr);
memcpy(&vadc->sens_attr[i], &qpnp_adc_attr,
sizeof(qpnp_adc_attr));
+ sysfs_attr_init(&vadc->sens_attr[i].dev_attr.attr);
rc = device_create_file(&spmi->dev,
&vadc->sens_attr[i].dev_attr);
if (rc) {
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index f671806..b3bd8a0 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -363,6 +363,7 @@
int t38_start_addr;
bool update_cfg;
const char *fw_name;
+ bool no_force_update;
};
static struct dentry *debug_base;
@@ -984,9 +985,9 @@
continue;
}
- /* check whether report id is part of T9 or T15 */
id = reportid - data->t9_min_reportid;
+ /* check whether report id is part of T9,T15 or T42*/
if (reportid >= data->t9_min_reportid &&
reportid <= data->t9_max_reportid)
mxt_input_touchevent(data, &message, id);
@@ -1273,25 +1274,18 @@
data->cfg_version[0], data->cfg_version[1],
data->cfg_version[2]);
- /* It is possible that the config data on the controller is not
- * versioned and the version number returns 0. In this case,
- * find a match without the config version checking.
- */
- error = mxt_search_config_array(data,
- data->cfg_version[0] != 0 ? true : false);
+ /* configuration update requires major match */
+ error = mxt_search_config_array(data, true);
+
+ /* if no_force_update is false , try again with false
+ as the second parameter to mxt_search_config_array */
+ if (error && (data->no_force_update == false))
+ error = mxt_search_config_array(data, false);
+
if (error) {
- /* If a match wasn't found for a non-zero config version,
- * it means the controller has the wrong config data. Search
- * for a best match based on controller and firmware version,
- * but not config version.
- */
- if (data->cfg_version[0])
- error = mxt_search_config_array(data, false);
- if (error) {
- dev_err(dev,
- "Unable to find matching config in pdata\n");
- return error;
- }
+ dev_err(dev,
+ "Unable to find matching config in pdata\n");
+ return error;
}
return 0;
@@ -1418,13 +1412,62 @@
return 0;
}
+static int mxt_update_cfg(struct mxt_data *data)
+{
+ int error;
+ const u8 *cfg_ver;
+
+ /* Get config data from platform data */
+ error = mxt_get_config(data);
+ if (error)
+ dev_dbg(&data->client->dev, "Config info not found.\n");
+
+ /* Check register init values */
+ if (data->config_info && data->config_info->config) {
+ if (data->update_cfg) {
+ error = mxt_check_reg_init(data);
+ if (error) {
+ dev_err(&data->client->dev,
+ "Failed to check reg init value\n");
+ return error;
+ }
+
+ error = mxt_backup_nv(data);
+ if (error) {
+ dev_err(&data->client->dev, "Failed to back up NV\n");
+ return error;
+ }
+
+ cfg_ver = data->config_info->config +
+ data->cfg_version_idx;
+ dev_info(&data->client->dev,
+ "Config updated from %d.%d.%d to %d.%d.%d\n",
+ data->cfg_version[0], data->cfg_version[1],
+ data->cfg_version[2],
+ cfg_ver[0], cfg_ver[1], cfg_ver[2]);
+
+ memcpy(data->cfg_version, cfg_ver, MXT_CFG_VERSION_LEN);
+ }
+ } else {
+ dev_info(&data->client->dev,
+ "No cfg data defined, skipping check reg init\n");
+ }
+
+ error = mxt_save_objects(data);
+ if (error)
+ return error;
+
+ return 0;
+}
+
+
+
static int mxt_initialize(struct mxt_data *data)
{
struct i2c_client *client = data->client;
struct mxt_info *info = &data->info;
int error;
u8 val;
- const u8 *cfg_ver;
error = mxt_get_info(data);
if (error) {
@@ -1465,46 +1508,9 @@
if (error)
goto free_object_table;
- /* Get config data from platform data */
- error = mxt_get_config(data);
- if (error)
- dev_dbg(&client->dev, "Config info not found.\n");
-
- /* Check register init values */
- if (data->config_info && data->config_info->config) {
- if (data->update_cfg) {
- error = mxt_check_reg_init(data);
- if (error) {
- dev_err(&client->dev,
- "Failed to check reg init value\n");
- goto free_object_table;
- }
-
- error = mxt_backup_nv(data);
- if (error) {
- dev_err(&client->dev, "Failed to back up NV\n");
- goto free_object_table;
- }
-
- cfg_ver = data->config_info->config +
- data->cfg_version_idx;
- dev_info(&client->dev,
- "Config updated from %d.%d.%d to %d.%d.%d\n",
- data->cfg_version[0], data->cfg_version[1],
- data->cfg_version[2],
- cfg_ver[0], cfg_ver[1], cfg_ver[2]);
-
- memcpy(data->cfg_version, cfg_ver, MXT_CFG_VERSION_LEN);
- }
- } else {
- dev_info(&client->dev,
- "No cfg data defined, skipping check reg init\n");
- }
-
- error = mxt_save_objects(data);
+ error = mxt_update_cfg(data);
if (error)
goto free_object_table;
-
/* Update matrix size at info struct */
error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val);
if (error)
@@ -1732,6 +1738,30 @@
return fw_name;
}
+static ssize_t mxt_force_cfg_update_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct mxt_data *data = dev_get_drvdata(dev);
+ int flag = buf[0]-'0';
+ int error;
+ data->no_force_update = !flag;
+
+ if (data->state == APPMODE) {
+ disable_irq(data->irq);
+ error = mxt_update_cfg(data);
+ enable_irq(data->irq);
+ if (error)
+ return error;
+ } else {
+ dev_err(dev,
+ "Not in APPMODE, Unable to force cfg update\n");
+ return -EINVAL;
+ }
+
+ return count;
+}
+
static ssize_t mxt_update_fw_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
@@ -1742,7 +1772,7 @@
u8 bootldr_id;
u8 cfg_version[MXT_CFG_VERSION_LEN] = {0};
-
+ data->no_force_update = false;
/* If fw_name is set, then the existing firmware has an upgrade */
if (!data->fw_name) {
/*
@@ -1824,10 +1854,12 @@
static DEVICE_ATTR(object, 0444, mxt_object_show, NULL);
static DEVICE_ATTR(update_fw, 0664, NULL, mxt_update_fw_store);
+static DEVICE_ATTR(force_cfg_update, 0664, NULL, mxt_force_cfg_update_store);
static struct attribute *mxt_attrs[] = {
&dev_attr_object.attr,
&dev_attr_update_fw.attr,
+ &dev_attr_force_cfg_update.attr,
NULL
};
@@ -2433,6 +2465,10 @@
pdata->i2c_pull_up = of_property_read_bool(np, "atmel,i2c-pull-up");
pdata->digital_pwr_regulator = of_property_read_bool(np,
"atmel,dig-reg-support");
+
+ pdata->no_force_update = of_property_read_bool(np,
+ "atmel,no-force-update");
+
/* reset, irq gpio info */
pdata->reset_gpio = of_get_named_gpio_flags(np, "atmel,reset-gpio",
0, &pdata->reset_gpio_flags);
@@ -2583,6 +2619,7 @@
data->client = client;
data->input_dev = input_dev;
data->pdata = pdata;
+ data->no_force_update = pdata->no_force_update;
__set_bit(EV_ABS, input_dev->evbit);
__set_bit(EV_KEY, input_dev->evbit);
diff --git a/drivers/iommu/msm_iommu_dev-v2.c b/drivers/iommu/msm_iommu_dev-v2.c
index ea6c87c..5a0b593 100644
--- a/drivers/iommu/msm_iommu_dev-v2.c
+++ b/drivers/iommu/msm_iommu_dev-v2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012 Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -21,7 +21,6 @@
#include <linux/interrupt.h>
#include <linux/err.h>
#include <linux/slab.h>
-#include <linux/atomic.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
@@ -95,9 +94,8 @@
struct device_node *child;
int ret = 0;
- ret = device_move(&pdev->dev, &msm_iommu_root_dev->dev, DPM_ORDER_NONE);
- if (ret)
- goto fail;
+ drvdata->dev = &pdev->dev;
+ msm_iommu_add_drv(drvdata);
ret = msm_iommu_parse_bfb_settings(pdev, drvdata);
if (ret)
@@ -118,20 +116,12 @@
return ret;
}
-static atomic_t msm_iommu_next_id = ATOMIC_INIT(-1);
-
static int __devinit msm_iommu_probe(struct platform_device *pdev)
{
struct msm_iommu_drvdata *drvdata;
struct resource *r;
int ret, needs_alt_core_clk;
- if (msm_iommu_root_dev == pdev)
- return 0;
-
- if (pdev->id == -1)
- pdev->id = atomic_inc_return(&msm_iommu_next_id) - 1;
-
drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
if (!drvdata)
return -ENOMEM;
@@ -192,6 +182,7 @@
drv = platform_get_drvdata(pdev);
if (drv) {
+ msm_iommu_remove_drv(drv);
if (drv->clk)
clk_put(drv->clk);
clk_put(drv->pclk);
@@ -315,25 +306,8 @@
static int __init msm_iommu_driver_init(void)
{
- struct device_node *node;
int ret;
- node = of_find_compatible_node(NULL, NULL, "qcom,msm-smmu-v2");
- if (!node)
- return -ENODEV;
-
- of_node_put(node);
-
- msm_iommu_root_dev = platform_device_register_simple(
- "msm_iommu", -1, 0, 0);
- if (!msm_iommu_root_dev) {
- pr_err("Failed to create root IOMMU device\n");
- ret = -ENODEV;
- goto error;
- }
-
- atomic_inc(&msm_iommu_next_id);
-
ret = platform_driver_register(&msm_iommu_driver);
if (ret != 0) {
pr_err("Failed to register IOMMU driver\n");
@@ -354,7 +328,6 @@
{
platform_driver_unregister(&msm_iommu_ctx_driver);
platform_driver_unregister(&msm_iommu_driver);
- platform_device_unregister(msm_iommu_root_dev);
}
subsys_initcall(msm_iommu_driver_init);
diff --git a/drivers/iommu/msm_iommu_dev.c b/drivers/iommu/msm_iommu_dev.c
index 967283d..d9eddcd 100644
--- a/drivers/iommu/msm_iommu_dev.c
+++ b/drivers/iommu/msm_iommu_dev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -21,62 +21,63 @@
#include <linux/interrupt.h>
#include <linux/err.h>
#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
#include <mach/iommu_hw-8xxx.h>
#include <mach/iommu.h>
-struct iommu_ctx_iter_data {
- /* input */
- const char *name;
+static DEFINE_MUTEX(iommu_list_lock);
+static LIST_HEAD(iommu_list);
- /* output */
- struct device *dev;
-};
-
-struct platform_device *msm_iommu_root_dev;
-
-static int each_iommu_ctx(struct device *dev, void *data)
+void msm_iommu_add_drv(struct msm_iommu_drvdata *drv)
{
- struct iommu_ctx_iter_data *res = data;
+ mutex_lock(&iommu_list_lock);
+ list_add(&drv->list, &iommu_list);
+ mutex_unlock(&iommu_list_lock);
+}
+
+void msm_iommu_remove_drv(struct msm_iommu_drvdata *drv)
+{
+ mutex_lock(&iommu_list_lock);
+ list_del(&drv->list);
+ mutex_unlock(&iommu_list_lock);
+}
+
+static int find_iommu_ctx(struct device *dev, void *data)
+{
struct msm_iommu_ctx_drvdata *c;
c = dev_get_drvdata(dev);
- if (!res || !c || !c->name || !res->name)
- return -EINVAL;
+ if (!c || !c->name)
+ return 0;
- if (!strcmp(res->name, c->name)) {
- res->dev = dev;
- return 1;
- }
- return 0;
+ return !strcmp(data, c->name);
}
-static int each_iommu(struct device *dev, void *data)
+static struct device *find_context(struct device *dev, const char *name)
{
- return device_for_each_child(dev, data, each_iommu_ctx);
+ return device_find_child(dev, (void *)name, find_iommu_ctx);
}
struct device *msm_iommu_get_ctx(const char *ctx_name)
{
- struct iommu_ctx_iter_data r;
- int found;
+ struct msm_iommu_drvdata *drv;
+ struct device *dev = NULL;
- if (!msm_iommu_root_dev) {
- pr_err("No root IOMMU device.\n");
- goto fail;
+ mutex_lock(&iommu_list_lock);
+ list_for_each_entry(drv, &iommu_list, list) {
+ dev = find_context(drv->dev, ctx_name);
+ if (dev)
+ break;
}
+ mutex_unlock(&iommu_list_lock);
- r.name = ctx_name;
- found = device_for_each_child(&msm_iommu_root_dev->dev, &r, each_iommu);
-
- if (found <= 0 || !dev_get_drvdata(r.dev)) {
+ if (!dev || !dev_get_drvdata(dev))
pr_err("Could not find context <%s>\n", ctx_name);
- goto fail;
- }
+ put_device(dev);
- return r.dev;
-fail:
- return NULL;
+ return dev;
}
EXPORT_SYMBOL(msm_iommu_get_ctx);
@@ -134,11 +135,6 @@
resource_size_t len;
int ret, par;
- if (pdev->id == -1) {
- msm_iommu_root_dev = pdev;
- return 0;
- }
-
drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
if (!drvdata) {
@@ -227,6 +223,9 @@
drvdata->ncb = iommu_dev->ncb;
drvdata->ttbr_split = iommu_dev->ttbr_split;
drvdata->name = iommu_dev->name;
+ drvdata->dev = &pdev->dev;
+
+ msm_iommu_add_drv(drvdata);
pr_info("device %s mapped at %p, with %d ctx banks\n",
iommu_dev->name, regs_base, iommu_dev->ncb);
@@ -263,6 +262,7 @@
drv = platform_get_drvdata(pdev);
if (drv) {
+ msm_iommu_remove_drv(drv);
if (drv->clk)
clk_put(drv->clk);
clk_put(drv->pclk);
diff --git a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tspp_v1.c b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tspp_v1.c
index 191a0c4..9fb6004 100644
--- a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tspp_v1.c
+++ b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tspp_v1.c
@@ -18,15 +18,15 @@
#include "mpq_dmx_plugin_common.h"
-#define TSIF_COUNT 2
+#define TSIF_COUNT 2
#define TSPP_MAX_PID_FILTER_NUM 16
/* Max number of section filters */
-#define TSPP_MAX_SECTION_FILTER_NUM 64
+#define TSPP_MAX_SECTION_FILTER_NUM 64
/* For each TSIF we allocate two pipes, one for PES and one for sections */
-#define TSPP_PES_CHANNEL 0
+#define TSPP_PES_CHANNEL 0
#define TSPP_SECTION_CHANNEL 1
/* the channel_id set to TSPP driver based on TSIF number and channel type */
@@ -35,7 +35,7 @@
#define TSPP_GET_TSIF_NUM(ch_id) (ch_id >> 1)
/* mask that set to care for all bits in pid filter */
-#define TSPP_PID_MASK 0x1FFF
+#define TSPP_PID_MASK 0x1FFF
/* dvb-demux defines pid 0x2000 as full capture pid */
#define TSPP_PASS_THROUGH_PID 0x2000
@@ -53,6 +53,7 @@
* Meanning about 82 notifications per second.
*/
#define MAX_BAM_DESCRIPTOR_SIZE (32*1024 - 1)
+
#define TSPP_BUFFER_SIZE \
((MAX_BAM_DESCRIPTOR_SIZE / TSPP_RAW_TTS_SIZE) * TSPP_RAW_TTS_SIZE)
@@ -65,11 +66,18 @@
/* Channel timeout in msec */
#define TSPP_CHANNEL_TIMEOUT 16
+enum mem_buffer_allocation_mode {
+ MPQ_DMX_TSPP_INTERNAL_ALLOC = 0,
+ MPQ_DMX_TSPP_CONTIGUOUS_PHYS_ALLOC = 1
+};
+
/* module parameters for load time configuration */
static int clock_inv;
static int tsif_mode = 2;
+static int allocation_mode = MPQ_DMX_TSPP_INTERNAL_ALLOC;
module_param(tsif_mode, int, S_IRUGO);
module_param(clock_inv, int, S_IRUGO);
+module_param(allocation_mode, int, S_IRUGO);
/*
* Work scheduled each time TSPP notifies dmx
@@ -97,6 +105,15 @@
/* work used to submit to workqueue to process pes channel */
struct tspp_work pes_work;
+ /* ION handle used for TSPP data buffer allocation */
+ struct ion_handle *pes_mem_heap_handle;
+ /* TSPP data buffer heap virtual base address */
+ void *pes_mem_heap_virt_base;
+ /* TSPP data buffer heap physical base address */
+ ion_phys_addr_t pes_mem_heap_phys_base;
+ /* buffer allocation index */
+ int pes_index;
+
/*
* TSPP pipe holding all TS packets with section data.
* The following is reference count for number of feeds
@@ -107,6 +124,15 @@
/* work used to submit to workqueue to process pes channel */
struct tspp_work section_work;
+ /* ION handle used for TSPP data buffer allocation */
+ struct ion_handle *section_mem_heap_handle;
+ /* TSPP data buffer heap virtual base address */
+ void *section_mem_heap_virt_base;
+ /* TSPP data buffer heap physical base address */
+ ion_phys_addr_t section_mem_heap_phys_base;
+ /* buffer allocation index */
+ int section_index;
+
/*
* Holds PIDs of allocated TSPP filters along with
* how many feeds are opened on same PID.
@@ -128,8 +154,65 @@
/* mutex protecting the data-structure */
struct mutex mutex;
} tsif[TSIF_COUNT];
+
+ /* ION client used for TSPP data buffer allocation */
+ struct ion_client *ion_client;
} mpq_dmx_tspp_info;
+static void *tspp_mem_allocator(int channel_id, u32 size,
+ u32 *phys_base, void *user)
+{
+ void *virt_addr = NULL;
+ int i = TSPP_GET_TSIF_NUM(channel_id);
+
+ if (TSPP_IS_PES_CHANNEL(channel_id)) {
+ if (mpq_dmx_tspp_info.tsif[i].pes_index == TSPP_BUFFER_COUNT)
+ return NULL;
+ virt_addr =
+ (mpq_dmx_tspp_info.tsif[i].pes_mem_heap_virt_base +
+ (mpq_dmx_tspp_info.tsif[i].pes_index * size));
+ *phys_base =
+ (mpq_dmx_tspp_info.tsif[i].pes_mem_heap_phys_base +
+ (mpq_dmx_tspp_info.tsif[i].pes_index * size));
+ mpq_dmx_tspp_info.tsif[i].pes_index++;
+ } else {
+ if (mpq_dmx_tspp_info.tsif[i].section_index ==
+ TSPP_BUFFER_COUNT)
+ return NULL;
+ virt_addr =
+ (mpq_dmx_tspp_info.tsif[i].section_mem_heap_virt_base +
+ (mpq_dmx_tspp_info.tsif[i].section_index * size));
+ *phys_base =
+ (mpq_dmx_tspp_info.tsif[i].section_mem_heap_phys_base +
+ (mpq_dmx_tspp_info.tsif[i].section_index * size));
+ mpq_dmx_tspp_info.tsif[i].section_index++;
+ }
+
+ return virt_addr;
+}
+
+static void tspp_mem_free(int channel_id, u32 size,
+ void *virt_base, u32 phys_base, void *user)
+{
+ int i = TSPP_GET_TSIF_NUM(channel_id);
+
+ /*
+ * actual buffer heap free is done in mpq_dmx_tspp_plugin_exit().
+ * we update index here, so if this function is called repetitively
+ * for all the buffers, then afterwards tspp_mem_allocator()
+ * can be called again.
+ * Note: it would be incorrect to call tspp_mem_allocator()
+ * a few times, then call tspp_mem_free(), then call
+ * tspp_mem_allocator() again.
+ */
+ if (TSPP_IS_PES_CHANNEL(channel_id)) {
+ if (mpq_dmx_tspp_info.tsif[i].pes_index > 0)
+ mpq_dmx_tspp_info.tsif[i].pes_index--;
+ } else {
+ if (mpq_dmx_tspp_info.tsif[i].section_index > 0)
+ mpq_dmx_tspp_info.tsif[i].section_index--;
+ }
+}
/**
* Returns a free filter slot that can be used.
@@ -374,20 +457,34 @@
(void *)tsif,
TSPP_CHANNEL_TIMEOUT);
- /* TODO: register allocater and provide allocation function
- * that allocate from continous memory so that we can have
+ /* register allocater and provide allocation function
+ * that allocates from continous memory so that we can have
* big notification size, smallest descriptor, and still provide
* TZ with single big buffer based on notification size.
*/
- /* set buffer/descriptor size and count */
- ret = tspp_allocate_buffers(0,
- channel_id,
- TSPP_BUFFER_COUNT,
- TSPP_BUFFER_SIZE,
- TSPP_NOTIFICATION_SIZE,
- NULL,
- NULL);
+ /* set buffer/descriptor size and count,
+ * allocate TSPP data buffers
+ */
+ if (allocation_mode == MPQ_DMX_TSPP_CONTIGUOUS_PHYS_ALLOC) {
+ ret = tspp_allocate_buffers(0,
+ channel_id,
+ TSPP_BUFFER_COUNT,
+ TSPP_BUFFER_SIZE,
+ TSPP_NOTIFICATION_SIZE,
+ tspp_mem_allocator,
+ tspp_mem_free,
+ NULL);
+ } else {
+ ret = tspp_allocate_buffers(0,
+ channel_id,
+ TSPP_BUFFER_COUNT,
+ TSPP_BUFFER_SIZE,
+ TSPP_NOTIFICATION_SIZE,
+ NULL,
+ NULL,
+ NULL);
+ }
if (ret < 0) {
MPQ_DVB_ERR_PRINT(
"%s: tspp_allocate_buffers(%d) failed (%d)\n",
@@ -745,20 +842,152 @@
return 0;
}
+static void mpq_dmx_tsif_ion_cleanup(int i)
+{
+ mpq_dmx_tspp_info.tsif[i].pes_mem_heap_phys_base = 0;
+ mpq_dmx_tspp_info.tsif[i].section_mem_heap_phys_base = 0;
+
+ if (!IS_ERR_OR_NULL(mpq_dmx_tspp_info.tsif[i].pes_mem_heap_handle)) {
+ if (!IS_ERR_OR_NULL(mpq_dmx_tspp_info.tsif[i].
+ pes_mem_heap_virt_base))
+ ion_unmap_kernel(mpq_dmx_tspp_info.ion_client,
+ mpq_dmx_tspp_info.tsif[i].pes_mem_heap_handle);
+
+ ion_free(mpq_dmx_tspp_info.ion_client,
+ mpq_dmx_tspp_info.tsif[i].pes_mem_heap_handle);
+ }
+
+ if (!IS_ERR_OR_NULL(mpq_dmx_tspp_info.tsif[i].
+ section_mem_heap_handle)) {
+ if (!IS_ERR_OR_NULL(mpq_dmx_tspp_info.tsif[i].
+ section_mem_heap_virt_base))
+ ion_unmap_kernel(mpq_dmx_tspp_info.ion_client,
+ mpq_dmx_tspp_info.tsif[i].
+ section_mem_heap_handle);
+
+ ion_free(mpq_dmx_tspp_info.ion_client,
+ mpq_dmx_tspp_info.tsif[i].section_mem_heap_handle);
+ }
+
+ mpq_dmx_tspp_info.tsif[i].pes_mem_heap_virt_base = NULL;
+ mpq_dmx_tspp_info.tsif[i].section_mem_heap_virt_base = NULL;
+ mpq_dmx_tspp_info.tsif[i].pes_mem_heap_handle = NULL;
+ mpq_dmx_tspp_info.tsif[i].section_mem_heap_handle = NULL;
+}
+
+static void mpq_dmx_tspp_ion_cleanup(void)
+{
+ int i;
+
+ for (i = 0; i < TSIF_COUNT; i++)
+ mpq_dmx_tsif_ion_cleanup(i);
+}
+
static int mpq_tspp_dmx_init(
struct dvb_adapter *mpq_adapter,
struct mpq_demux *mpq_demux)
{
- int result;
+ int i, result;
+ size_t len;
MPQ_DVB_DBG_PRINT("%s executed\n", __func__);
+ if (allocation_mode == MPQ_DMX_TSPP_CONTIGUOUS_PHYS_ALLOC) {
+ /*
+ * Save ION client, used to allocate memory
+ * for TSPP's buffers.
+ */
+ mpq_dmx_tspp_info.ion_client = mpq_demux->ion_client;
+
+ if (IS_ERR_OR_NULL(mpq_dmx_tspp_info.ion_client))
+ return -EINVAL;
+
+ for (i = 0; i < TSIF_COUNT; i++) {
+ mpq_dmx_tspp_info.tsif[i].pes_mem_heap_handle =
+ ion_alloc(mpq_dmx_tspp_info.ion_client,
+ (TSPP_BUFFER_COUNT * TSPP_BUFFER_SIZE),
+ TSPP_RAW_TTS_SIZE,
+ ION_HEAP(ION_CP_MM_HEAP_ID),
+ 0); /* non-cached */
+ if (IS_ERR_OR_NULL(mpq_dmx_tspp_info.tsif[i].
+ pes_mem_heap_handle)) {
+ MPQ_DVB_ERR_PRINT("%s: ion_alloc() failed\n",
+ __func__);
+ mpq_dmx_tspp_ion_cleanup();
+ return -ENOMEM;
+ }
+ /* save virtual base address of heap */
+ mpq_dmx_tspp_info.tsif[i].pes_mem_heap_virt_base =
+ ion_map_kernel(mpq_dmx_tspp_info.ion_client,
+ mpq_dmx_tspp_info.tsif[i].
+ pes_mem_heap_handle);
+ if (IS_ERR_OR_NULL(mpq_dmx_tspp_info.tsif[i].
+ pes_mem_heap_virt_base)) {
+ MPQ_DVB_ERR_PRINT(
+ "%s: ion_map_kernel() failed\n",
+ __func__);
+ mpq_dmx_tspp_ion_cleanup();
+ return -ENOMEM;
+ }
+ /* save physical base address of heap */
+ result = ion_phys(mpq_dmx_tspp_info.ion_client,
+ mpq_dmx_tspp_info.tsif[i].pes_mem_heap_handle,
+ &(mpq_dmx_tspp_info.tsif[i].
+ pes_mem_heap_phys_base), &len);
+ if (result < 0) {
+ MPQ_DVB_ERR_PRINT("%s: ion_phys() failed\n",
+ __func__);
+ mpq_dmx_tspp_ion_cleanup();
+ return -ENOMEM;
+ }
+
+ mpq_dmx_tspp_info.tsif[i].section_mem_heap_handle =
+ ion_alloc(mpq_dmx_tspp_info.ion_client,
+ (TSPP_BUFFER_COUNT * TSPP_BUFFER_SIZE),
+ TSPP_RAW_TTS_SIZE,
+ ION_HEAP(ION_CP_MM_HEAP_ID),
+ 0); /* non-cached */
+ if (IS_ERR_OR_NULL(mpq_dmx_tspp_info.tsif[i].
+ section_mem_heap_handle)) {
+ MPQ_DVB_ERR_PRINT("%s: ion_alloc() failed\n",
+ __func__);
+ mpq_dmx_tspp_ion_cleanup();
+ return -ENOMEM;
+ }
+ /* save virtual base address of heap */
+ mpq_dmx_tspp_info.tsif[i].section_mem_heap_virt_base =
+ ion_map_kernel(mpq_dmx_tspp_info.ion_client,
+ mpq_dmx_tspp_info.tsif[i].
+ section_mem_heap_handle);
+ if (IS_ERR_OR_NULL(mpq_dmx_tspp_info.tsif[i].
+ section_mem_heap_virt_base)) {
+ MPQ_DVB_ERR_PRINT(
+ "%s: ion_map_kernel() failed\n",
+ __func__);
+ mpq_dmx_tspp_ion_cleanup();
+ return -ENOMEM;
+ }
+ /* save physical base address of heap */
+ result = ion_phys(mpq_dmx_tspp_info.ion_client,
+ mpq_dmx_tspp_info.tsif[i].
+ section_mem_heap_handle,
+ &(mpq_dmx_tspp_info.tsif[i].
+ section_mem_heap_phys_base), &len);
+ if (result < 0) {
+ MPQ_DVB_ERR_PRINT("%s: ion_phys() failed\n",
+ __func__);
+ mpq_dmx_tspp_ion_cleanup();
+ return -ENOMEM;
+ }
+ }
+ }
+
/* Set the kernel-demux object capabilities */
mpq_demux->demux.dmx.capabilities =
DMX_TS_FILTERING |
DMX_PES_FILTERING |
- DMX_SECTION_FILTERING |
- DMX_MEMORY_BASED_FILTERING |
+ DMX_SECTION_FILTERING |
+ DMX_MEMORY_BASED_FILTERING |
DMX_CRC_CHECKING |
DMX_TS_DESCRAMBLING;
@@ -818,6 +1047,7 @@
init_failed_dmx_release:
dvb_dmx_release(&mpq_demux->demux);
init_failed:
+ mpq_dmx_tspp_ion_cleanup();
return result;
}
@@ -831,6 +1061,10 @@
for (i = 0; i < TSIF_COUNT; i++) {
mpq_dmx_tspp_info.tsif[i].pes_channel_ref = 0;
+ mpq_dmx_tspp_info.tsif[i].pes_index = 0;
+ mpq_dmx_tspp_info.tsif[i].pes_mem_heap_handle = NULL;
+ mpq_dmx_tspp_info.tsif[i].pes_mem_heap_virt_base = NULL;
+ mpq_dmx_tspp_info.tsif[i].pes_mem_heap_phys_base = 0;
mpq_dmx_tspp_info.tsif[i].pes_work.channel_id =
TSPP_CHANNEL_ID(i, TSPP_PES_CHANNEL);
@@ -839,6 +1073,10 @@
mpq_dmx_tspp_work);
mpq_dmx_tspp_info.tsif[i].section_channel_ref = 0;
+ mpq_dmx_tspp_info.tsif[i].section_index = 0;
+ mpq_dmx_tspp_info.tsif[i].section_mem_heap_handle = NULL;
+ mpq_dmx_tspp_info.tsif[i].section_mem_heap_virt_base = NULL;
+ mpq_dmx_tspp_info.tsif[i].section_mem_heap_phys_base = 0;
mpq_dmx_tspp_info.tsif[i].section_work.channel_id =
TSPP_CHANNEL_ID(i, TSPP_SECTION_CHANNEL);
@@ -861,14 +1099,12 @@
mpq_dmx_tspp_info.tsif[i].name);
if (mpq_dmx_tspp_info.tsif[i].workqueue == NULL) {
-
for (j = 0; j < i; j++) {
destroy_workqueue(
mpq_dmx_tspp_info.tsif[j].workqueue);
mutex_destroy(&mpq_dmx_tspp_info.tsif[j].mutex);
}
-
MPQ_DVB_ERR_PRINT(
"%s: create_singlethread_workqueue failed\n",
__func__);
@@ -905,6 +1141,11 @@
for (i = 0; i < TSIF_COUNT; i++) {
mutex_lock(&mpq_dmx_tspp_info.tsif[i].mutex);
+ /*
+ * Note: tspp_close_channel will also free the TSPP buffers
+ * even if we allocated them ourselves,
+ * using our free function.
+ */
if (mpq_dmx_tspp_info.tsif[i].pes_channel_ref) {
tspp_unregister_notification(0, TSPP_PES_CHANNEL);
tspp_close_channel(0,
@@ -917,9 +1158,11 @@
TSPP_CHANNEL_ID(i, TSPP_SECTION_CHANNEL));
}
- /* TODO: if we allocate buffer
- * to TSPP ourself, need to free those as well
+ /* if we allocated buffer pools
+ * to TSPP, need to free those as well
*/
+ if (allocation_mode == MPQ_DMX_TSPP_CONTIGUOUS_PHYS_ALLOC)
+ mpq_dmx_tsif_ion_cleanup(i);
mutex_unlock(&mpq_dmx_tspp_info.tsif[i].mutex);
flush_workqueue(mpq_dmx_tspp_info.tsif[i].workqueue);
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index ac143b1..fde7cb7 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -39,6 +39,17 @@
#include <asm/unaligned.h>
static unsigned int rds_buf = 100;
+static int oda_agt;
+static int grp_mask;
+static int rt_plus_carrier = -1;
+static int ert_carrier = -1;
+static unsigned char ert_buf[256];
+static unsigned char ert_len;
+static unsigned char c_byt_pair_index;
+static char utf_8_flag;
+static char rt_ert_flag;
+static char formatting_dir;
+
module_param(rds_buf, uint, 0);
MODULE_PARM_DESC(rds_buf, "RDS buffer entries: *100*");
@@ -108,7 +119,11 @@
static struct video_device *priv_videodev;
static int iris_do_calibration(struct iris_device *radio);
-
+static void hci_buff_ert(struct iris_device *radio,
+ struct rds_grp_data *rds_buf);
+static void hci_ev_rt_plus(struct iris_device *radio,
+ struct rds_grp_data rds_buf);
+static void hci_ev_ert(struct iris_device *radio);
static int update_spur_table(struct iris_device *radio);
static struct v4l2_queryctrl iris_v4l2_queryctrl[] = {
{
@@ -921,6 +936,20 @@
return radio_hci_send_cmd(hdev, opcode, 0, NULL);
}
+static int hci_fm_rds_grp_mask_req(struct radio_hci_dev *hdev,
+ unsigned long param)
+{
+ __u16 opcode = 0;
+
+ struct hci_fm_rds_grp_req *fm_grp_mask =
+ (struct hci_fm_rds_grp_req *)param;
+
+ opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
+ HCI_OCF_FM_RDS_GRP);
+ return radio_hci_send_cmd(hdev, opcode, sizeof(*fm_grp_mask),
+ fm_grp_mask);
+}
+
static int hci_fm_rds_grp_process_req(struct radio_hci_dev *hdev,
unsigned long param)
{
@@ -1313,7 +1342,13 @@
static int hci_fm_rds_grp(struct hci_fm_rds_grp_req *arg,
struct radio_hci_dev *hdev)
{
- return 0;
+ int ret = 0;
+ struct hci_fm_rds_grp_req *fm_grp_mask = arg;
+
+ ret = radio_hci_request(hdev, hci_fm_rds_grp_mask_req, (unsigned
+ long)fm_grp_mask, RADIO_HCI_TIMEOUT);
+
+ return ret;
}
static int hci_fm_rds_grps_process(__u32 *arg, struct radio_hci_dev *hdev)
@@ -2078,6 +2113,234 @@
iris_q_event(radio, IRIS_EVT_MONO);
}
+static void hci_ev_raw_rds_group_data(struct radio_hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ struct iris_device *radio;
+ unsigned char blocknum, index;
+ struct rds_grp_data temp;
+ unsigned int mask_bit;
+ unsigned short int aid, agt, gtc;
+ unsigned short int carrier;
+
+ radio = video_get_drvdata(video_get_dev());
+ index = RDSGRP_DATA_OFFSET;
+
+ for (blocknum = 0; blocknum < RDS_BLOCKS_NUM; blocknum++) {
+ temp.rdsBlk[blocknum].rdsLsb =
+ (skb->data[index]);
+ temp.rdsBlk[blocknum].rdsMsb =
+ (skb->data[index+1]);
+ index = index + 2;
+ }
+
+ aid = AID(temp.rdsBlk[3].rdsLsb, temp.rdsBlk[3].rdsMsb);
+ gtc = GTC(temp.rdsBlk[1].rdsMsb);
+ agt = AGT(temp.rdsBlk[1].rdsLsb);
+
+ if (gtc == GRP_3A) {
+ switch (aid) {
+ case ERT_AID:
+ /* calculate the grp mask for RDS grp
+ * which will contain actual eRT text
+ *
+ * Bit Pos 0 1 2 3 4 5 6 7
+ * Grp Type 0A 0B 1A 1B 2A 2B 3A 3B
+ *
+ * similary for rest grps
+ */
+ mask_bit = (((agt >> 1) << 1) + (agt & 1));
+ oda_agt = (1 << mask_bit);
+ utf_8_flag = (temp.rdsBlk[2].rdsLsb & 1);
+ formatting_dir = EXTRACT_BIT(temp.rdsBlk[2].rdsLsb,
+ ERT_FORMAT_DIR_BIT);
+ if (ert_carrier != agt)
+ iris_q_event(radio, IRIS_EVT_NEW_ODA);
+ ert_carrier = agt;
+ break;
+ case RT_PLUS_AID:
+ /* calculate the grp mask for RDS grp
+ * which will contain actual eRT text
+ *
+ * Bit Pos 0 1 2 3 4 5 6 7
+ * Grp Type 0A 0B 1A 1B 2A 2B 3A 3B
+ *
+ * similary for rest grps
+ */
+ mask_bit = (((agt >> 1) << 1) + (agt & 1));
+ oda_agt = (1 << mask_bit);
+ /*Extract 5th bit of MSB (b7b6b5b4b3b2b1b0)*/
+ rt_ert_flag = EXTRACT_BIT(temp.rdsBlk[2].rdsMsb,
+ RT_ERT_FLAG_BIT);
+ if (rt_plus_carrier != agt)
+ iris_q_event(radio, IRIS_EVT_NEW_ODA);
+ rt_plus_carrier = agt;
+ break;
+ default:
+ oda_agt = 0;
+ break;
+ }
+ } else {
+ carrier = gtc;
+ if ((carrier == rt_plus_carrier))
+ hci_ev_rt_plus(radio, temp);
+ else if (carrier == ert_carrier)
+ hci_buff_ert(radio, &temp);
+ }
+}
+
+static void hci_buff_ert(struct iris_device *radio,
+ struct rds_grp_data *rds_buf)
+{
+ int i;
+ unsigned short int info_byte = 0;
+ unsigned short int byte_pair_index;
+
+ byte_pair_index = AGT(rds_buf->rdsBlk[1].rdsLsb);
+ if (byte_pair_index == 0) {
+ c_byt_pair_index = 0;
+ ert_len = 0;
+ }
+ if (c_byt_pair_index == byte_pair_index) {
+ c_byt_pair_index++;
+ for (i = 2; i <= 3; i++) {
+ info_byte = rds_buf->rdsBlk[i].rdsLsb;
+ info_byte |= (rds_buf->rdsBlk[i].rdsMsb << 8);
+ ert_buf[ert_len++] = rds_buf->rdsBlk[i].rdsMsb;
+ ert_buf[ert_len++] = rds_buf->rdsBlk[i].rdsLsb;
+ if ((utf_8_flag == 0)
+ && (info_byte == CARRIAGE_RETURN)) {
+ ert_len -= 2;
+ break;
+ } else if ((utf_8_flag == 1)
+ &&
+ (rds_buf->rdsBlk[i].rdsMsb
+ == CARRIAGE_RETURN)) {
+ info_byte = CARRIAGE_RETURN;
+ ert_len -= 2;
+ break;
+ } else if ((utf_8_flag == 1)
+ &&
+ (rds_buf->rdsBlk[i].rdsLsb
+ == CARRIAGE_RETURN)) {
+ info_byte = CARRIAGE_RETURN;
+ ert_len--;
+ break;
+ }
+ }
+ if ((byte_pair_index == MAX_ERT_SEGMENT) ||
+ (info_byte == CARRIAGE_RETURN)) {
+ hci_ev_ert(radio);
+ c_byt_pair_index = 0;
+ ert_len = 0;
+ }
+ } else {
+ ert_len = 0;
+ c_byt_pair_index = 0;
+ }
+}
+static void hci_ev_ert(struct iris_device *radio)
+
+{
+ char *data = NULL;
+
+ if (ert_len <= 0)
+ return;
+ data = kmalloc((ert_len + 3), GFP_ATOMIC);
+ if (data != NULL) {
+ data[0] = ert_len;
+ data[1] = utf_8_flag;
+ data[2] = formatting_dir;
+ memcpy((data + 3), ert_buf, ert_len);
+ iris_q_evt_data(radio, data, (ert_len + 3), IRIS_BUF_ERT);
+ iris_q_event(radio, IRIS_EVT_NEW_ERT);
+ kfree(data);
+ }
+}
+
+static void hci_ev_rt_plus(struct iris_device *radio,
+ struct rds_grp_data rds_buf)
+{
+ char tag_type1, tag_type2;
+ char *data = NULL;
+ int len = 0;
+ unsigned short int agt;
+
+ agt = AGT(rds_buf.rdsBlk[1].rdsLsb);
+ /*right most 3 bits of Lsb of block 2
+ * and left most 3 bits of Msb of block 3
+ */
+ tag_type1 = (((agt & TAG1_MSB_MASK) << TAG1_MSB_OFFSET) |
+ (rds_buf.rdsBlk[2].rdsMsb >> TAG1_LSB_OFFSET));
+
+ /*right most 1 bit of lsb of 3rd block
+ * and left most 5 bits of Msb of 4th block
+ */
+ tag_type2 = (((rds_buf.rdsBlk[2].rdsLsb & TAG2_MSB_MASK)
+ << TAG2_MSB_OFFSET) |
+ (rds_buf.rdsBlk[3].rdsMsb >> TAG2_LSB_OFFSET));
+
+ if (tag_type1 != DUMMY_CLASS)
+ len += RT_PLUS_LEN_1_TAG;
+ if (tag_type2 != DUMMY_CLASS)
+ len += RT_PLUS_LEN_1_TAG;
+
+ if (len != 0) {
+ len += 2;
+ data = kmalloc(len, GFP_ATOMIC);
+ } else {
+ FMDERR("Len is zero\n");
+ return ;
+ }
+ if (data != NULL) {
+ data[0] = len;
+ len = 1;
+ data[len++] = rt_ert_flag;
+ if (tag_type1 != DUMMY_CLASS) {
+ data[len++] = tag_type1;
+ /*start position of tag1
+ *right most 5 bits of msb of 3rd block
+ *and left most bit of lsb of 3rd block
+ */
+ data[len++] = (((rds_buf.rdsBlk[2].rdsMsb &
+ TAG1_POS_MSB_MASK)
+ << TAG1_POS_MSB_OFFSET)
+ |
+ (rds_buf.rdsBlk[2].rdsLsb >>
+ TAG1_POS_LSB_OFFSET));
+ /*length of tag1
+ *left most 6 bits of lsb of 3rd block
+ */
+ data[len++] = ((rds_buf.rdsBlk[2].rdsLsb
+ >> TAG1_LEN_OFFSET)
+ &
+ TAG1_LEN_MASK) + 1;
+ }
+ if (tag_type2 != DUMMY_CLASS) {
+ data[len++] = tag_type2;
+ /*start position of tag2
+ *right most 3 bit of msb of 4th block
+ *and left most 3 bits of lsb of 4th block
+ */
+ data[len++] = (((rds_buf.rdsBlk[3].rdsMsb
+ & TAG2_POS_MSB_MASK)
+ << TAG2_POS_MSB_OFFSET)
+ |
+ (rds_buf.rdsBlk[3].rdsLsb
+ >> TAG2_POS_LSB_OFFSET));
+ /*length of tag2
+ *right most 5 bits of lsb of 4th block
+ */
+ data[len++] = (rds_buf.rdsBlk[3].rdsLsb
+ & TAG2_LEN_MASK) + 1;
+ }
+ iris_q_evt_data(radio, data, len, IRIS_BUF_RT_PLUS);
+ iris_q_event(radio, IRIS_EVT_NEW_RT_PLUS);
+ kfree(data);
+ } else {
+ FMDERR("memory allocation failed\n");
+ }
+}
static inline void hci_ev_program_service(struct radio_hci_dev *hdev,
struct sk_buff *skb)
@@ -2217,6 +2480,7 @@
hci_ev_service_available(hdev, skb);
break;
case HCI_EV_RDS_RX_DATA:
+ hci_ev_raw_rds_group_data(hdev, skb);
break;
case HCI_EV_PROGRAM_SERVICE:
hci_ev_program_service(hdev, skb);
@@ -2984,8 +3248,13 @@
}
break;
case V4L2_CID_PRIVATE_IRIS_RDSGROUP_MASK:
- radio->rds_grp.rds_grp_enable_mask = ctrl->value;
+ grp_mask = (grp_mask | oda_agt | ctrl->value);
+ radio->rds_grp.rds_grp_enable_mask = grp_mask;
+ radio->rds_grp.rds_buf_size = 1;
+ radio->rds_grp.en_rds_change_filter = 0;
retval = hci_fm_rds_grp(&radio->rds_grp, radio->fm_hdev);
+ if (retval < 0)
+ FMDERR("error in setting group mask\n");
break;
case V4L2_CID_PRIVATE_IRIS_RDSGROUP_PROC:
rds_grps_proc = radio->g_rds_grp_proc_ps | ctrl->value;
diff --git a/drivers/media/video/msm_vidc/msm_vdec.c b/drivers/media/video/msm_vidc/msm_vdec.c
index b476e39..22063d4 100644
--- a/drivers/media/video/msm_vidc/msm_vdec.c
+++ b/drivers/media/video/msm_vidc/msm_vdec.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, 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
@@ -167,23 +167,7 @@
static u32 get_frame_size_nv12(int plane,
u32 height, u32 width)
{
- int size;
- int luma_h, luma_w, luma_stride, luma_scanl, luma_size;
- int chroma_h, chroma_w, chroma_stride, chroma_scanl, chroma_size;
-
- luma_w = width;
- luma_h = height;
-
- chroma_w = luma_w;
- chroma_h = luma_h/2;
- NV12_IL_CALC_Y_STRIDE(luma_stride, luma_w, 32);
- NV12_IL_CALC_Y_BUFHEIGHT(luma_scanl, luma_h, 32);
- NV12_IL_CALC_UV_STRIDE(chroma_stride, chroma_w, 32);
- NV12_IL_CALC_UV_BUFHEIGHT(chroma_scanl, luma_h, 32);
- NV12_IL_CALC_BUF_SIZE(size, luma_size, luma_stride,
- luma_scanl, chroma_size, chroma_stride, chroma_scanl, 32);
- size = ALIGN(size, SZ_4K);
- return size;
+ return VENUS_BUFFER_SIZE(COLOR_FMT_NV12, width, height);
}
static u32 get_frame_size_compressed(int plane,
diff --git a/drivers/media/video/msm_vidc/msm_venc.c b/drivers/media/video/msm_vidc/msm_venc.c
index 3f892b1..fdadb36 100644
--- a/drivers/media/video/msm_vidc/msm_venc.c
+++ b/drivers/media/video/msm_vidc/msm_venc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, 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
@@ -461,23 +461,7 @@
static u32 get_frame_size_nv12(int plane, u32 height, u32 width)
{
- int size;
- int luma_h, luma_w, luma_stride, luma_scanl, luma_size;
- int chroma_h, chroma_w, chroma_stride, chroma_scanl, chroma_size;
-
- luma_w = width;
- luma_h = height;
-
- chroma_w = luma_w;
- chroma_h = luma_h/2;
- NV12_IL_CALC_Y_STRIDE(luma_stride, luma_w, 32);
- NV12_IL_CALC_Y_BUFHEIGHT(luma_scanl, luma_h, 32);
- NV12_IL_CALC_UV_STRIDE(chroma_stride, chroma_w, 32);
- NV12_IL_CALC_UV_BUFHEIGHT(chroma_scanl, luma_h, 32);
- NV12_IL_CALC_BUF_SIZE(size, luma_size, luma_stride,
- luma_scanl, chroma_size, chroma_stride, chroma_scanl, 32);
- size = ALIGN(size, SZ_4K);
- return size;
+ return VENUS_BUFFER_SIZE(COLOR_FMT_NV12, width, height);
}
static u32 get_frame_size_nv21(int plane, u32 height, u32 width)
diff --git a/drivers/media/video/msm_vidc/msm_vidc_common.c b/drivers/media/video/msm_vidc/msm_vidc_common.c
index 56bcf65..772f0de 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_common.c
+++ b/drivers/media/video/msm_vidc/msm_vidc_common.c
@@ -17,7 +17,7 @@
#include <asm/div64.h>
#include <mach/iommu.h>
#include <mach/iommu_domains.h>
-#include <mach/peripheral-loader.h>
+#include <mach/subsystem_restart.h>
#include "msm_vidc_common.h"
#include "vidc_hal_api.h"
@@ -388,7 +388,9 @@
struct msm_vidc_cb_cmd_done *response = data;
struct msm_vidc_inst *inst;
struct v4l2_event dqevent;
+ struct v4l2_control control = {0};
struct msm_vidc_cb_event *event_notify;
+ int rc = 0;
if (response) {
inst = (struct msm_vidc_inst *)response->session_id;
dqevent.id = 0;
@@ -396,7 +398,16 @@
switch (event_notify->hal_event_type) {
case HAL_EVENT_SEQ_CHANGED_SUFFICIENT_RESOURCES:
dqevent.type =
- V4L2_EVENT_SEQ_CHANGED_SUFFICIENT;
+ V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT;
+ control.id =
+ V4L2_CID_MPEG_VIDC_VIDEO_CONTINUE_DATA_TRANSFER;
+ rc = v4l2_g_ctrl(&inst->ctrl_handler, &control);
+ if (rc)
+ dprintk(VIDC_WARN,
+ "Failed to get Smooth streamng flag\n");
+ if (!rc && control.value == true)
+ dqevent.type =
+ V4L2_EVENT_SEQ_CHANGED_SUFFICIENT;
break;
case HAL_EVENT_SEQ_CHANGED_INSUFFICIENT_RESOURCES:
dqevent.type =
@@ -509,6 +520,71 @@
}
}
+static void handle_session_error(enum command_response cmd, void *data)
+{
+ struct msm_vidc_cb_cmd_done *response = data;
+ struct msm_vidc_inst *inst = NULL;
+ struct v4l2_event dqevent;
+ if (response) {
+ inst = (struct msm_vidc_inst *)response->session_id;
+ if (inst) {
+ dprintk(VIDC_WARN,
+ "Session error receivd for session %p\n", inst);
+ mutex_lock(&inst->sync_lock);
+ inst->state = MSM_VIDC_CORE_INVALID;
+ mutex_unlock(&inst->sync_lock);
+ dqevent.type = V4L2_EVENT_MSM_VIDC_SYS_ERROR;
+ dqevent.id = 0;
+ v4l2_event_queue_fh(&inst->event_handler, &dqevent);
+ wake_up(&inst->kernel_event_queue);
+ }
+ } else {
+ dprintk(VIDC_ERR,
+ "Failed to get valid response for session error\n");
+ }
+}
+static void handle_sys_error(enum command_response cmd, void *data)
+{
+ struct msm_vidc_cb_cmd_done *response = data;
+ struct msm_vidc_inst *inst = NULL ;
+ struct msm_vidc_core *core = NULL;
+ struct v4l2_event dqevent;
+ unsigned long flags;
+ if (response) {
+ inst = (struct msm_vidc_inst *)response->session_id;
+ dprintk(VIDC_WARN,
+ "Sys error received for session %p\n", inst);
+ if (inst) {
+ core = inst->core;
+ if (core) {
+ spin_lock_irqsave(&core->lock, flags);
+ core->state = VIDC_CORE_INVALID;
+ spin_unlock_irqrestore(&core->lock, flags);
+ dqevent.type = V4L2_EVENT_MSM_VIDC_SYS_ERROR;
+ dqevent.id = 0;
+ list_for_each_entry(inst, &core->instances,
+ list) {
+ if (inst) {
+ v4l2_event_queue_fh(
+ &inst->event_handler,
+ &dqevent);
+ spin_lock_irqsave(&inst->lock,
+ flags);
+ inst->state =
+ MSM_VIDC_CORE_INVALID;
+ spin_unlock_irqrestore(
+ &inst->lock, flags);
+ }
+ }
+ wake_up(&inst->kernel_event_queue);
+ }
+ }
+ } else {
+ dprintk(VIDC_ERR,
+ "Failed to get valid response for sys error\n");
+ }
+}
+
static void handle_sys_watchdog_timeout(enum command_response cmd, void *data)
{
subsystem_restart("msm_vidc");
@@ -755,6 +831,12 @@
case SYS_WATCHDOG_TIMEOUT:
handle_sys_watchdog_timeout(cmd, data);
break;
+ case SYS_ERROR:
+ handle_sys_error(cmd, data);
+ break;
+ case SESSION_ERROR:
+ handle_session_error(cmd, data);
+ break;
default:
dprintk(VIDC_ERR, "response unhandled\n");
break;
@@ -837,12 +919,12 @@
}
if (!core->resources.fw.cookie)
- core->resources.fw.cookie = pil_get("venus");
+ core->resources.fw.cookie = subsystem_get("venus");
if (IS_ERR_OR_NULL(core->resources.fw.cookie)) {
dprintk(VIDC_ERR, "Failed to download firmware\n");
rc = -ENOMEM;
- goto fail_pil_get;
+ goto fail_subsystem_get;
}
rc = msm_comm_enable_clks(core);
@@ -860,9 +942,9 @@
fail_iommu_attach:
msm_comm_disable_clks(core);
fail_enable_clks:
- pil_put(core->resources.fw.cookie);
+ subsystem_put(core->resources.fw.cookie);
core->resources.fw.cookie = NULL;
-fail_pil_get:
+fail_subsystem_get:
return rc;
}
@@ -873,7 +955,7 @@
return;
}
if (core->resources.fw.cookie) {
- pil_put(core->resources.fw.cookie);
+ subsystem_put(core->resources.fw.cookie);
core->resources.fw.cookie = NULL;
msm_comm_iommu_detach(core);
msm_comm_disable_clks(core);
diff --git a/drivers/media/video/msm_vidc/msm_vidc_internal.h b/drivers/media/video/msm_vidc/msm_vidc_internal.h
index f288cc6..8e1a99e 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_internal.h
+++ b/drivers/media/video/msm_vidc/msm_vidc_internal.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -30,6 +30,7 @@
#include <media/v4l2-ctrls.h>
#include <media/videobuf2-core.h>
#include <media/msm_vidc.h>
+#include <media/msm_media_info.h>
#include "vidc_hal_api.h"
@@ -49,33 +50,7 @@
#define MAX_NAME_LENGTH 64
-#define NV12_IL_CALC_Y_STRIDE(stride, frame_width, stride_multiple) \
- { stride = (frame_width + stride_multiple - 1) & \
- (0xffffffff - (stride_multiple - 1)); }
-
-#define NV12_IL_CALC_Y_BUFHEIGHT(buf_height, frame_height,\
- min_buf_height_multiple) \
- { buf_height = (frame_height + min_buf_height_multiple - 1) & \
- (0xffffffff - (min_buf_height_multiple - 1)); }
-
-#define NV12_IL_CALC_UV_STRIDE(stride, frame_width, stride_multiple) \
- { stride = ((((frame_width + 1) >> 1) + stride_multiple - 1) & \
- (0xffffffff - (stride_multiple - 1))) << 1; }
-
-#define NV12_IL_CALC_UV_BUFHEIGHT(buf_height, frame_height,\
- min_buf_height_multiple) \
- { buf_height = ((((frame_height + 1) >> 1) + \
- min_buf_height_multiple - 1) & (0xffffffff - \
- (min_buf_height_multiple - 1))); }
-
-#define NV12_IL_CALC_BUF_SIZE(buf_size, y_buf_size, y_stride, \
- y_buf_height, uv_buf_size, uv_stride, uv_buf_height, uv_alignment) \
- { y_buf_size = (y_stride * y_buf_height); \
- uv_buf_size = (uv_stride * uv_buf_height) + uv_alignment; \
- buf_size = y_buf_size + uv_buf_size; }
-
#define EXTRADATA_IDX(__num_planes) (__num_planes - 1)
-
enum vidc_ports {
OUTPUT_PORT,
CAPTURE_PORT,
diff --git a/drivers/media/video/msm_vidc/msm_vidc_ssr.c b/drivers/media/video/msm_vidc/msm_vidc_ssr.c
index e8a6745..33464c6f 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_ssr.c
+++ b/drivers/media/video/msm_vidc/msm_vidc_ssr.c
@@ -157,7 +157,8 @@
dprintk(VIDC_ERR, "msm_vidc Sub System registration failed\n");
rc = -ENODEV;
}
- core->ssr_info.msm_vidc_ramdump_dev = create_ramdump_device("msm_vidc");
+ core->ssr_info.msm_vidc_ramdump_dev = create_ramdump_device("msm_vidc",
+ msm_vidc_subsystem.dev);
if (!core->ssr_info.msm_vidc_ramdump_dev) {
dprintk(VIDC_ERR, "Unable to create msm_vidc ramdump device\n");
rc = -ENODEV;
diff --git a/drivers/media/video/msm_vidc/vidc_hal.c b/drivers/media/video/msm_vidc/vidc_hal.c
index 190e132..55f9a07 100644
--- a/drivers/media/video/msm_vidc/vidc_hal.c
+++ b/drivers/media/video/msm_vidc/vidc_hal.c
@@ -613,11 +613,9 @@
write_register(device->hal_data->register_base_addr,
VIDC_VENUS_VBIF_CLK_ON, 1, 0);
write_register(device->hal_data->register_base_addr,
- VIDC_VBIF_OUT_AXI_AOOO_EN, 0x00000FFF, 0);
+ VIDC_VBIF_OUT_AXI_AOOO_EN, 0x00001FFF, 0);
write_register(device->hal_data->register_base_addr,
- VIDC_VBIF_OUT_AXI_AOOO, 0x0FFF0FFF, 0);
- write_register(device->hal_data->register_base_addr,
- VIDC_VENUS_VBIF_CLK_ON, 1, 0);
+ VIDC_VBIF_OUT_AXI_AOOO, 0x1FFF1FFF, 0);
write_register(device->hal_data->register_base_addr,
VIDC_VBIF_IN_RD_LIM_CONF0, 0x10101001, 0);
write_register(device->hal_data->register_base_addr,
@@ -641,7 +639,15 @@
write_register(device->hal_data->register_base_addr,
VIDC_VBIF_ARB_CTL, 0x00000030, 0);
write_register(device->hal_data->register_base_addr,
+ VIDC_VENUS_VBIF_DDR_OUT_MAX_BURST, 0x00000707, 0);
+ write_register(device->hal_data->register_base_addr,
+ VIDC_VENUS_VBIF_OCMEM_OUT_MAX_BURST, 0x00000707, 0);
+ write_register(device->hal_data->register_base_addr,
+ VIDC_VENUS_VBIF_ROUND_ROBIN_QOS_ARB, 0x00000001, 0);
+ write_register(device->hal_data->register_base_addr,
VIDC_VENUS0_WRAPPER_VBIF_REQ_PRIORITY, 0x5555556, 0);
+ write_register(device->hal_data->register_base_addr,
+ VIDC_VENUS0_WRAPPER_VBIF_PRIORITY_LEVEL, 0, 0);
}
static int vidc_hal_sys_set_debug(struct hal_device *device, int debug)
diff --git a/drivers/media/video/msm_vidc/vidc_hal_api.h b/drivers/media/video/msm_vidc/vidc_hal_api.h
index d3fa1d0..8aff5af 100644
--- a/drivers/media/video/msm_vidc/vidc_hal_api.h
+++ b/drivers/media/video/msm_vidc/vidc_hal_api.h
@@ -814,6 +814,7 @@
SYS_IDLE,
SYS_DEBUG,
SYS_WATCHDOG_TIMEOUT,
+ SYS_ERROR,
/* SESSION COMMANDS_DONE */
SESSION_LOAD_RESOURCE_DONE,
SESSION_INIT_DONE,
@@ -833,6 +834,7 @@
SESSION_RELEASE_BUFFER_DONE,
SESSION_RELEASE_RESOURCE_DONE,
SESSION_PROPERTY_INFO,
+ SESSION_ERROR,
RESPONSE_UNUSED = 0x10000000,
};
diff --git a/drivers/media/video/msm_vidc/vidc_hal_interrupt_handler.c b/drivers/media/video/msm_vidc/vidc_hal_interrupt_handler.c
index 7eb0ae1..ba599ec 100644
--- a/drivers/media/video/msm_vidc/vidc_hal_interrupt_handler.c
+++ b/drivers/media/video/msm_vidc/vidc_hal_interrupt_handler.c
@@ -146,6 +146,21 @@
cmd_done.device_id = device->device_id;
device->callback(SYS_WATCHDOG_TIMEOUT, &cmd_done);
}
+static void hal_process_sys_error(struct hal_device *device)
+{
+ struct msm_vidc_cb_cmd_done cmd_done;
+ disable_irq_nosync(device->hal_data->irq);
+ memset(&cmd_done, 0, sizeof(struct msm_vidc_cb_cmd_done));
+ cmd_done.device_id = device->device_id;
+ device->callback(SYS_ERROR, &cmd_done);
+}
+static void hal_process_session_error(struct hal_device *device)
+{
+ struct msm_vidc_cb_cmd_done cmd_done;
+ memset(&cmd_done, 0, sizeof(struct msm_vidc_cb_cmd_done));
+ cmd_done.device_id = device->device_id;
+ device->callback(SESSION_ERROR, &cmd_done);
+}
static void hal_process_event_notify(struct hal_device *device,
struct hfi_msg_event_notify_packet *pkt)
{
@@ -160,10 +175,11 @@
switch (pkt->event_id) {
case HFI_EVENT_SYS_ERROR:
dprintk(VIDC_INFO, "HFI_EVENT_SYS_ERROR");
- hal_process_sys_watchdog_timeout(device);
+ hal_process_sys_error(device);
break;
case HFI_EVENT_SESSION_ERROR:
dprintk(VIDC_INFO, "HFI_EVENT_SESSION_ERROR");
+ hal_process_session_error(device);
break;
case HFI_EVENT_SESSION_SEQUENCE_CHANGED:
dprintk(VIDC_INFO, "HFI_EVENT_SESSION_SEQUENCE_CHANGED");
diff --git a/drivers/media/video/msm_vidc/vidc_hal_io.h b/drivers/media/video/msm_vidc/vidc_hal_io.h
index b85e015..6845ac5 100644
--- a/drivers/media/video/msm_vidc/vidc_hal_io.h
+++ b/drivers/media/video/msm_vidc/vidc_hal_io.h
@@ -22,6 +22,12 @@
#define VIDC_VBIF_BASE_OFFS 0x00080000
#define VIDC_VBIF_VERSION (VIDC_VBIF_BASE_OFFS + 0x00)
+#define VIDC_VENUS_VBIF_DDR_OUT_MAX_BURST \
+ (VIDC_VBIF_BASE_OFFS + 0xD8)
+#define VIDC_VENUS_VBIF_OCMEM_OUT_MAX_BURST \
+ (VIDC_VBIF_BASE_OFFS + 0xDC)
+#define VIDC_VENUS_VBIF_ROUND_ROBIN_QOS_ARB \
+ (VIDC_VBIF_BASE_OFFS + 0x124)
#define VIDC_CPU_BASE_OFFS 0x000C0000
#define VIDC_CPU_CS_BASE_OFFS (VIDC_CPU_BASE_OFFS + 0x00012000)
@@ -128,7 +134,5 @@
(VIDC_WRAPPER_BASE_OFFS + 0x20)
#define VIDC_VENUS0_WRAPPER_VBIF_PRIORITY_LEVEL \
(VIDC_WRAPPER_BASE_OFFS + 0x24)
-#define VIDC_VENUS_VBIF_REQ_PRIORITY (VIDC_WRAPPER_BASE_OFFS + 0x20)
-#define VIDC_VENUS_VBIF_PRIORITY_LEVEL (VIDC_WRAPPER_BASE_OFFS + 0x24)
#endif
diff --git a/drivers/media/video/msm_wfd/enc-mfc-subdev.c b/drivers/media/video/msm_wfd/enc-mfc-subdev.c
index 09a5e32..6db2ad1 100644
--- a/drivers/media/video/msm_wfd/enc-mfc-subdev.c
+++ b/drivers/media/video/msm_wfd/enc-mfc-subdev.c
@@ -1975,6 +1975,7 @@
unsigned long phy_addr;
int i = 0;
int heap_mask = 0;
+ u32 ion_flags = 0;
u32 len;
control.width = inst->width;
control.height = inst->height;
@@ -1988,7 +1989,8 @@
goto err;
}
heap_mask = ION_HEAP(ION_CP_MM_HEAP_ID);
- heap_mask |= inst->secure ? ION_SECURE : ION_HEAP(ION_IOMMU_HEAP_ID);
+ heap_mask |= inst->secure ? 0 : ION_HEAP(ION_IOMMU_HEAP_ID);
+ ion_flags |= inst->secure ? ION_SECURE : 0;
if (vcd_get_ion_status()) {
for (i = 0; i < 4; ++i) {
@@ -1999,7 +2001,7 @@
ctrl->user_virtual_addr = (void *)i;
client_ctx->recon_buffer_ion_handle[i]
= ion_alloc(client_ctx->user_ion_client,
- control.size, SZ_8K, heap_mask, 0);
+ control.size, SZ_8K, heap_mask, ion_flags);
ctrl->kernel_virtual_addr = ion_map_kernel(
client_ctx->user_ion_client,
diff --git a/drivers/media/video/msm_wfd/wfd-ioctl.c b/drivers/media/video/msm_wfd/wfd-ioctl.c
index d8080dd..371ae3c 100644
--- a/drivers/media/video/msm_wfd/wfd-ioctl.c
+++ b/drivers/media/video/msm_wfd/wfd-ioctl.c
@@ -155,13 +155,15 @@
struct ion_handle *handle = NULL;
void *kvaddr = NULL;
unsigned int alloc_regions = 0;
+ unsigned int ion_flags = 0;
int rc = 0;
alloc_regions = ION_HEAP(ION_CP_MM_HEAP_ID);
- alloc_regions |= secure ? ION_SECURE :
+ alloc_regions |= secure ? 0 :
ION_HEAP(ION_IOMMU_HEAP_ID);
+ ion_flags |= secure ? ION_SECURE : 0;
handle = ion_alloc(client,
- mregion->size, SZ_4K, alloc_regions, 0);
+ mregion->size, SZ_4K, alloc_regions, ion_flags);
if (IS_ERR_OR_NULL(handle)) {
WFD_MSG_ERR("Failed to allocate input buffer\n");
diff --git a/drivers/media/video/msm_wfd/wfd-util.c b/drivers/media/video/msm_wfd/wfd-util.c
index 233668b0..5c00e5c 100644
--- a/drivers/media/video/msm_wfd/wfd-util.c
+++ b/drivers/media/video/msm_wfd/wfd-util.c
@@ -159,10 +159,10 @@
}
case WFD_STAT_EVENT_MDP_QUEUE:
stats->mdp_buf_count++;
- stats->mdp_updates++;
break;
case WFD_STAT_EVENT_MDP_DEQUEUE:
stats->mdp_buf_count--;
+ stats->mdp_updates++;
break;
case WFD_STAT_EVENT_ENC_QUEUE: {
struct wfd_stats_encode_sample *sample = NULL;
diff --git a/drivers/media/video/vcap_v4l2.c b/drivers/media/video/vcap_v4l2.c
index 51a798f..2b73b11 100644
--- a/drivers/media/video/vcap_v4l2.c
+++ b/drivers/media/video/vcap_v4l2.c
@@ -2267,7 +2267,7 @@
ret = request_irq(dev->vcirq->start, vcap_vc_handler,
- IRQF_TRIGGER_RISING, "vc_irq", 0);
+ IRQF_TRIGGER_HIGH, "vc_irq", 0);
if (ret < 0) {
pr_err("%s: vc irq request fail\n", __func__);
ret = -EBUSY;
diff --git a/drivers/media/video/vcap_vc.c b/drivers/media/video/vcap_vc.c
index f3c9362..08dcdf3 100644
--- a/drivers/media/video/vcap_vc.c
+++ b/drivers/media/video/vcap_vc.c
@@ -126,28 +126,9 @@
return tv;
}
-irqreturn_t vc_handler(struct vcap_dev *dev)
+inline void vc_isr_error_checking(struct vcap_dev *dev,
+ struct v4l2_event v4l2_evt, uint32_t irq)
{
- uint32_t irq, timestamp;
- struct vcap_buffer *buf;
- struct vb2_buffer *vb = NULL;
- struct vcap_client_data *c_data;
- struct v4l2_event v4l2_evt;
- uint8_t i, idx, buf_num, tot, done_count = 0;
- bool work_todo = false;
-
- irq = readl_relaxed(VCAP_VC_INT_STATUS);
-
- pr_debug("%s: irq=0x%08x\n", __func__, irq);
-
- c_data = dev->vc_client;
- if (!c_data->streaming) {
- writel_iowmb(irq, VCAP_VC_INT_CLEAR);
- pr_err("VC no longer streaming\n");
- return IRQ_HANDLED;
- }
-
- v4l2_evt.id = 0;
if (irq & 0x8000200) {
writel_iowmb(0x00000102, VCAP_VC_NPL_CTRL);
v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
@@ -166,6 +147,12 @@
VCAP_VC_VSYNC_ERR_EVENT;
v4l2_event_queue(dev->vfd, &v4l2_evt);
}
+ if (irq & 0x00001000) {
+ writel_iowmb(0x00000102, VCAP_VC_NPL_CTRL);
+ v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
+ VCAP_VC_VSYNC_SEQ_ERR;
+ v4l2_event_queue(dev->vfd, &v4l2_evt);
+ }
if (irq & 0x00000800) {
writel_iowmb(0x00000102, VCAP_VC_NPL_CTRL);
v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
@@ -178,33 +165,26 @@
VCAP_VC_LBUF_OFLOW_ERR_EVENT;
v4l2_event_queue(dev->vfd, &v4l2_evt);
}
+}
- if (!(irq & VC_BUFFER_MASK)) {
- writel_relaxed(irq, VCAP_VC_INT_CLEAR);
- pr_err("VC IRQ shows some error\n");
- return IRQ_HANDLED;
- }
-
- if (dev->vc_client == NULL) {
- /* This should never happen */
- writel_relaxed(irq, VCAP_VC_INT_CLEAR);
- pr_err("VC: There is no active vc client\n");
- return IRQ_HANDLED;
- }
- c_data = dev->vc_client;
-
+inline uint8_t vc_isr_buffer_done_count(struct vcap_dev *dev,
+ struct vcap_client_data *c_data, uint32_t irq)
+{
+ int i;
+ uint8_t done_count = 0;
for (i = 0; i < VCAP_VC_MAX_BUF; i++) {
if (0x2 & (irq >> i))
done_count++;
}
+ return done_count;
+}
- /* Assign field value in case somehow got out of sync */
- if (c_data->vc_format.mode == HAL_VCAP_MODE_INT && done_count == 1)
- c_data->vc_action.top_field = !(irq & 0x1);
-
+inline bool vc_isr_verify_expect_buf_rdy(struct vcap_dev *dev,
+ struct vcap_client_data *c_data, struct v4l2_event v4l2_evt,
+ uint32_t irq, uint8_t done_count, uint8_t tot, uint8_t buf_num)
+{
+ int i;
/* Double check expected buffers are done */
- buf_num = c_data->vc_action.buf_num;
- tot = c_data->vc_action.tot_buf;
for (i = 0; i < done_count; i++) {
if (!(irq & (0x1 << (((buf_num + i) % tot) + 1)))) {
v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
@@ -213,12 +193,17 @@
pr_debug("Unexpected buffer done\n");
c_data->vc_action.buf_num =
correct_buf_num(irq) % tot;
- writel_relaxed(irq, VCAP_VC_INT_CLEAR);
- return IRQ_HANDLED;
+ return true;
}
}
+ return false;
+}
- /* If here we know which buffers are done */
+inline void vc_isr_update_timestamp(struct vcap_dev *dev,
+ struct vcap_client_data *c_data)
+{
+ uint32_t timestamp;
+
timestamp = readl_relaxed(VCAP_VC_TIMESTAMP);
if (timestamp < c_data->vc_action.last_ts) {
c_data->vc_action.vc_ts.tv_usec +=
@@ -234,65 +219,142 @@
c_data->vc_action.vc_ts.tv_usec =
c_data->vc_action.vc_ts.tv_usec % VCAP_USEC;
c_data->vc_action.last_ts = timestamp;
+}
- c_data->vc_action.buf_num = (buf_num + done_count) % tot;
+inline void vc_isr_no_new_buffer(struct vcap_dev *dev,
+ struct vcap_client_data *c_data, struct v4l2_event v4l2_evt)
+{
+ v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
+ VCAP_VC_BUF_OVERWRITE_EVENT;
+ v4l2_event_queue(dev->vfd, &v4l2_evt);
+
+ c_data->vc_action.field_dropped =
+ !c_data->vc_action.field_dropped;
+
+ c_data->vc_action.field1 =
+ !c_data->vc_action.field1;
+ atomic_inc(&dev->dbg_p.vc_drop_count);
+}
+
+inline void vc_isr_switch_buffers(struct vcap_dev *dev,
+ struct vcap_client_data *c_data, struct vcap_buffer *buf,
+ struct vb2_buffer *vb, uint8_t idx, int done_count, int i)
+{
+ /* Config vc with this new buffer */
+ config_buffer(c_data, buf, VCAP_VC_Y_ADDR_1 + 0x8 * idx,
+ VCAP_VC_C_ADDR_1 + 0x8 * idx);
+ vb->v4l2_buf.timestamp = interpolate_ts(
+ c_data->vc_action.vc_ts,
+ 1000000 / c_data->vc_format.frame_rate *
+ (done_count - 1 - i));
+ if (c_data->vc_format.mode == HAL_VCAP_MODE_INT) {
+ if (c_data->vc_action.field1)
+ vb->v4l2_buf.field = V4L2_FIELD_TOP;
+ else
+ vb->v4l2_buf.field = V4L2_FIELD_BOTTOM;
+
+ c_data->vc_action.field1 =
+ !c_data->vc_action.field1;
+ }
+ vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
+ c_data->vc_action.buf[idx] = buf;
+}
+
+inline bool vc_isr_change_buffers(struct vcap_dev *dev,
+ struct vcap_client_data *c_data, struct v4l2_event v4l2_evt,
+ int done_count, uint8_t tot, uint8_t buf_num)
+{
+ struct vb2_buffer *vb = NULL;
+ struct vcap_buffer *buf;
+ bool schedule_work = false;
+ uint8_t idx;
+ int i;
+
for (i = 0; i < done_count; i++) {
idx = (buf_num + i) % tot;
vb = &c_data->vc_action.buf[idx]->vb;
spin_lock(&c_data->cap_slock);
if (list_empty(&c_data->vc_action.active)) {
spin_unlock(&c_data->cap_slock);
- v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
- VCAP_VC_BUF_OVERWRITE_EVENT;
- v4l2_event_queue(dev->vfd, &v4l2_evt);
- c_data->vc_action.top_field =
- !c_data->vc_action.top_field;
-
- if (c_data->vc_format.mode == HAL_VCAP_MODE_INT)
- c_data->vc_action.field_dropped =
- !c_data->vc_action.field_dropped;
-
- atomic_inc(&dev->dbg_p.vc_drop_count);
+ vc_isr_no_new_buffer(dev, c_data, v4l2_evt);
continue;
}
if (c_data->vc_format.mode == HAL_VCAP_MODE_INT &&
c_data->vc_action.field_dropped) {
spin_unlock(&c_data->cap_slock);
- c_data->vc_action.field_dropped =
- !c_data->vc_action.field_dropped;
- c_data->vc_action.top_field =
- !c_data->vc_action.top_field;
- atomic_inc(&dev->dbg_p.vc_drop_count);
+ vc_isr_no_new_buffer(dev, c_data, v4l2_evt);
continue;
}
buf = list_entry(c_data->vc_action.active.next,
struct vcap_buffer, list);
list_del(&buf->list);
spin_unlock(&c_data->cap_slock);
- /* Config vc with this new buffer */
- config_buffer(c_data, buf, VCAP_VC_Y_ADDR_1 + 0x8 * idx,
- VCAP_VC_C_ADDR_1 + 0x8 * idx);
- vb->v4l2_buf.timestamp = interpolate_ts(
- c_data->vc_action.vc_ts,
- 1000000 / c_data->vc_format.frame_rate *
- (done_count - 1 - i));
- if (c_data->vc_format.mode == HAL_VCAP_MODE_INT) {
- if (c_data->vc_action.top_field)
- vb->v4l2_buf.field = V4L2_FIELD_TOP;
- else
- vb->v4l2_buf.field = V4L2_FIELD_BOTTOM;
- c_data->vc_action.top_field =
- !c_data->vc_action.top_field;
- }
- vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
- work_todo = true;
- c_data->vc_action.buf[idx] = buf;
+ vc_isr_switch_buffers(dev, c_data, buf, vb, idx, done_count, i);
+ schedule_work = true;
+ }
+ return schedule_work;
+}
+
+irqreturn_t vc_handler(struct vcap_dev *dev)
+{
+ uint32_t irq;
+ struct vcap_client_data *c_data;
+ struct v4l2_event v4l2_evt;
+ uint8_t done_count = 0, buf_num, tot;
+ bool schedule_work = false;
+
+ v4l2_evt.id = 0;
+ irq = readl_relaxed(VCAP_VC_INT_STATUS);
+ writel_relaxed(irq, VCAP_VC_INT_CLEAR);
+
+ pr_debug("%s: irq=0x%08x\n", __func__, irq);
+
+ if (dev->vc_client == NULL) {
+ /* This should never happen */
+ pr_err("VC: There is no active vc client\n");
+ return IRQ_HANDLED;
}
- if (work_todo && c_data->op_mode == VC_AND_VP_VCAP_OP)
+ c_data = dev->vc_client;
+ if (!c_data->streaming) {
+ pr_err("VC no longer streaming\n");
+ return IRQ_HANDLED;
+ }
+
+ if (irq == VC_VSYNC_MASK) {
+ if (c_data->vc_format.mode == HAL_VCAP_MODE_INT)
+ c_data->vc_action.field1 = irq & 0x1;
+ return IRQ_HANDLED;
+ }
+
+ if (irq & VC_ERR_MASK) {
+ vc_isr_error_checking(dev, v4l2_evt, irq);
+ return IRQ_HANDLED;
+ }
+
+ if (!(irq & VC_BUFFER_MASK)) {
+ pr_debug("No frames done\n");
+ return IRQ_HANDLED;
+ }
+
+ done_count = vc_isr_buffer_done_count(dev, c_data, irq);
+ buf_num = c_data->vc_action.buf_num;
+ tot = c_data->vc_action.tot_buf;
+
+ if (vc_isr_verify_expect_buf_rdy(dev, c_data,
+ v4l2_evt, irq, done_count, tot, buf_num))
+ return IRQ_HANDLED;
+
+ vc_isr_update_timestamp(dev, c_data);
+
+ c_data->vc_action.buf_num = (buf_num + done_count) % tot;
+
+ schedule_work = vc_isr_change_buffers(dev, c_data, v4l2_evt,
+ done_count, tot, buf_num);
+
+ if (schedule_work && c_data->op_mode == VC_AND_VP_VCAP_OP)
queue_work(dev->vcap_wq, &dev->vc_to_vp_work.work);
- writel_relaxed(irq, VCAP_VC_INT_CLEAR);
return IRQ_HANDLED;
}
@@ -362,6 +424,8 @@
rc = 0;
for (i = 0; i < c_data->vc_action.tot_buf; i++)
rc = rc << 1 | 0x2;
+ rc |= VC_ERR_MASK;
+ rc |= VC_VSYNC_MASK;
writel_relaxed(rc, VCAP_VC_INT_MASK);
enable_irq(dev->vcirq->start);
diff --git a/drivers/media/video/vcap_vc.h b/drivers/media/video/vcap_vc.h
index 7f42c7f..9c3f5a7 100644
--- a/drivers/media/video/vcap_vc.h
+++ b/drivers/media/video/vcap_vc.h
@@ -63,6 +63,8 @@
#define VC_BUFFER_WRITTEN (0x3 << 1)
#define VC_BUFFER_MASK 0x7E
+#define VC_ERR_MASK 0xE0001E00
+#define VC_VSYNC_MASK 0x1
int vc_start_capture(struct vcap_client_data *c_data);
int vc_hw_kick_off(struct vcap_client_data *c_data);
diff --git a/drivers/media/video/vcap_vp.c b/drivers/media/video/vcap_vp.c
index 57813f5..82f9e58 100644
--- a/drivers/media/video/vcap_vp.c
+++ b/drivers/media/video/vcap_vp.c
@@ -267,7 +267,7 @@
}
/* Config VP */
- if (vp_act->bufT2->vb.v4l2_buf.field == V4L2_FIELD_TOP)
+ if (vp_act->bufT2->vb.v4l2_buf.field == V4L2_FIELD_BOTTOM)
top_field = 1;
writel_iowmb(0x00000000 | top_field, VCAP_VP_CTRL);
@@ -832,7 +832,7 @@
chroma_fmt << 11 | 0x1 << 4, VCAP_VP_OUT_CONFIG);
/* Enable Interrupt */
- if (vp_act->bufT2->vb.v4l2_buf.field == V4L2_FIELD_TOP)
+ if (vp_act->bufT2->vb.v4l2_buf.field == V4L2_FIELD_BOTTOM)
top_field = 1;
vp_act->vp_state = VP_FRAME2;
writel_relaxed(0x01100001, VCAP_VP_INTERRUPT_ENABLE);
@@ -875,7 +875,7 @@
if (rc < 0)
return rc;
- if (vp_act->bufT2->vb.v4l2_buf.field == V4L2_FIELD_TOP)
+ if (vp_act->bufT2->vb.v4l2_buf.field == V4L2_FIELD_BOTTOM)
top_field = 1;
/* Config VP & Enable Interrupt */
diff --git a/drivers/mfd/marimba-core.c b/drivers/mfd/marimba-core.c
index d84bb7b..26f3ece 100644
--- a/drivers/mfd/marimba-core.c
+++ b/drivers/mfd/marimba-core.c
@@ -857,8 +857,7 @@
ssbi_adap = NULL;
if (!marimba->client) {
- dev_err(&marimba->client->dev,
- "can't attach client %d\n", i);
+ pr_err("can't attach client %d\n", i);
status = -ENOMEM;
goto fail;
}
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 8cb903a..e71c95d 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -39,7 +39,7 @@
#include <mach/msm_bus.h>
#include <mach/msm_bus_board.h>
#include <mach/scm.h>
-#include <mach/peripheral-loader.h>
+#include <mach/subsystem_restart.h>
#include <mach/socinfo.h>
#include "qseecom_legacy.h"
#include "qseecom_kernel.h"
@@ -47,7 +47,9 @@
#define QSEECOM_DEV "qseecom"
#define QSEOS_VERSION_13 0x13
#define QSEOS_VERSION_14 0x14
-#define QSEOS_CHECK_VERSION_CMD 0x00001803;
+#define QSEEE_VERSION_00 0x400000
+
+#define QSEOS_CHECK_VERSION_CMD 0x00001803
enum qseecom_command_scm_resp_type {
QSEOS_APP_ID = 0xEE01,
@@ -64,6 +66,9 @@
QSEOS_LISTENER_DATA_RSP_COMMAND,
QSEOS_LOAD_EXTERNAL_ELF_COMMAND,
QSEOS_UNLOAD_EXTERNAL_ELF_COMMAND,
+ QSEOS_GET_APP_STATE_COMMAND,
+ QSEOS_LOAD_SERV_IMAGE_COMMAND,
+ QSEOS_UNLOAD_SERV_IMAGE_COMMAND,
QSEOS_CMD_MAX = 0xEFFFFFFF
};
@@ -96,6 +101,17 @@
uint32_t app_id;
};
+__packed struct qseecom_load_lib_image_ireq {
+ uint32_t qsee_cmd_id;
+ uint32_t mdt_len;
+ uint32_t img_len;
+ uint32_t phy_addr;
+};
+
+__packed struct qseecom_unload_lib_image_ireq {
+ uint32_t qsee_cmd_id;
+};
+
__packed struct qseecom_register_listener_ireq {
uint32_t qsee_cmd_id;
uint32_t listener_id;
@@ -191,7 +207,9 @@
int send_resp_flag;
uint32_t qseos_version;
+ uint32_t qsee_version;
struct device *pdev;
+ bool commonlib_loaded;
};
struct qseecom_client_handle {
@@ -1352,10 +1370,92 @@
return ret;
}
+static int qseecom_load_commonlib_image(void)
+{
+ int32_t ret = 0;
+ uint32_t fw_size = 0;
+ struct qseecom_load_app_ireq load_req = {0, 0, 0, 0};
+ struct qseecom_command_scm_resp resp;
+ u8 *img_data = NULL;
+
+ if (__qseecom_get_fw_size("commonlib", &fw_size))
+ return -EIO;
+
+ img_data = kzalloc(fw_size, GFP_KERNEL);
+ if (!img_data) {
+ pr_err("Mem allocation for lib image data failed\n");
+ return -ENOMEM;
+ }
+ ret = __qseecom_get_fw_data("commonlib", img_data, &load_req);
+ if (ret) {
+ kzfree(img_data);
+ return -EIO;
+ }
+ /* Populate the remaining parameters */
+ load_req.qsee_cmd_id = QSEOS_LOAD_SERV_IMAGE_COMMAND;
+ /* SCM_CALL to load the image */
+ ret = scm_call(SCM_SVC_TZSCHEDULER, 1, &load_req,
+ sizeof(struct qseecom_load_lib_image_ireq),
+ &resp, sizeof(resp));
+ kzfree(img_data);
+ if (ret) {
+ pr_err("scm_call to load failed : ret %d\n", ret);
+ ret = -EIO;
+ } else {
+ switch (resp.result) {
+ case QSEOS_RESULT_SUCCESS:
+ break;
+ case QSEOS_RESULT_FAILURE:
+ pr_err("scm call failed w/response result%d\n",
+ resp.result);
+ ret = -EINVAL;
+ break;
+ default:
+ pr_err("scm call return unknown response %d\n",
+ resp.result);
+ ret = -EINVAL;
+ break;
+ }
+ }
+ return ret;
+}
+
+static int qseecom_unload_commonlib_image(void)
+{
+ int ret = -EINVAL;
+ struct qseecom_unload_lib_image_ireq unload_req = {0};
+ struct qseecom_command_scm_resp resp;
+
+ /* Populate the remaining parameters */
+ unload_req.qsee_cmd_id = QSEOS_UNLOAD_SERV_IMAGE_COMMAND;
+ /* SCM_CALL to load the image */
+ ret = scm_call(SCM_SVC_TZSCHEDULER, 1, &unload_req,
+ sizeof(struct qseecom_unload_lib_image_ireq),
+ &resp, sizeof(resp));
+ if (ret) {
+ pr_err("scm_call to unload lib failed : ret %d\n", ret);
+ ret = -EIO;
+ } else {
+ switch (resp.result) {
+ case QSEOS_RESULT_SUCCESS:
+ break;
+ case QSEOS_RESULT_FAILURE:
+ pr_err("scm fail resp.result QSEOS_RESULT FAILURE\n");
+ break;
+ default:
+ pr_err("scm call return unknown response %d\n",
+ resp.result);
+ ret = -EINVAL;
+ break;
+ }
+ }
+ return ret;
+}
+
int qseecom_start_app(struct qseecom_handle **handle,
char *app_name, uint32_t size)
{
- int32_t ret;
+ int32_t ret = 0;
unsigned long flags = 0;
struct qseecom_dev_handle *data = NULL;
struct qseecom_check_app_ireq app_ireq;
@@ -1370,6 +1470,19 @@
return -EINVAL;
}
+ if (qseecom.qsee_version > QSEEE_VERSION_00) {
+ mutex_lock(&app_access_lock);
+ if (qseecom.commonlib_loaded == false) {
+ ret = qseecom_load_commonlib_image();
+ if (ret == 0)
+ qseecom.commonlib_loaded = true;
+ }
+ mutex_unlock(&app_access_lock);
+ }
+
+ if (ret)
+ return -EIO;
+
*handle = kzalloc(sizeof(struct qseecom_handle), GFP_KERNEL);
if (!(*handle)) {
pr_err("failed to allocate memory for kernel client handle\n");
@@ -1984,7 +2097,15 @@
case QSEECOM_IOCTL_LOAD_APP_REQ: {
mutex_lock(&app_access_lock);
atomic_inc(&data->ioctl_count);
- ret = qseecom_load_app(data, argp);
+ if (qseecom.qsee_version > QSEEE_VERSION_00) {
+ if (qseecom.commonlib_loaded == false) {
+ ret = qseecom_load_commonlib_image();
+ if (ret == 0)
+ qseecom.commonlib_loaded = true;
+ }
+ }
+ if (ret == 0)
+ ret = qseecom_load_app(data, argp);
atomic_dec(&data->ioctl_count);
mutex_unlock(&app_access_lock);
if (ret)
@@ -2089,7 +2210,7 @@
int pil_error;
mutex_lock(&pil_access_lock);
if (pil_ref_cnt == 0) {
- pil = pil_get("tzapps");
+ pil = subsystem_get("tzapps");
if (IS_ERR(pil)) {
pr_err("Playready PIL image load failed\n");
pil_error = PTR_ERR(pil);
@@ -2124,7 +2245,7 @@
if (qseecom.qseos_version == QSEOS_VERSION_13) {
mutex_lock(&pil_access_lock);
if (pil_ref_cnt == 1)
- pil_put(pil);
+ subsystem_put(pil);
pil_ref_cnt--;
mutex_unlock(&pil_access_lock);
}
@@ -2315,17 +2436,27 @@
rc = scm_call(6, 1, &system_call_id, sizeof(system_call_id),
&qsee_not_legacy, sizeof(qsee_not_legacy));
if (rc) {
- pr_err("Failed to retrieve QSEE version information %d\n", rc);
+ pr_err("Failed to retrieve QSEOS version information %d\n", rc);
goto err;
}
- if (qsee_not_legacy)
+ if (qsee_not_legacy) {
+ uint32_t feature = 10;
+
+ qseecom.qsee_version = QSEEE_VERSION_00;
+ rc = scm_call(6, 3, &feature, sizeof(feature),
+ &qseecom.qsee_version, sizeof(qseecom.qsee_version));
+ if (rc) {
+ pr_err("Failed to get QSEE version info %d\n", rc);
+ goto err;
+ }
qseecom.qseos_version = QSEOS_VERSION_14;
- else {
+ } else {
qseecom.qseos_version = QSEOS_VERSION_13;
+ qseecom.qsee_version = 0;
pil = NULL;
pil_ref_cnt = 0;
}
-
+ qseecom.commonlib_loaded = false;
qseecom.pdev = class_dev;
/* Create ION msm client */
qseecom.ion_clnt = msm_ion_client_create(-1, "qseecom-kernel");
@@ -2417,6 +2548,8 @@
break;
}
}
+ if (qseecom.qseos_version > QSEEE_VERSION_00)
+ qseecom_unload_commonlib_image();
return ret;
};
diff --git a/drivers/misc/tspp.c b/drivers/misc/tspp.c
index 8a1e0da..3b678c5 100644
--- a/drivers/misc/tspp.c
+++ b/drivers/misc/tspp.c
@@ -103,29 +103,29 @@
/*
* TSPP register offsets
*/
-#define TSPP_RST 0x00
+#define TSPP_RST 0x00
#define TSPP_CLK_CONTROL 0x04
-#define TSPP_CONFIG 0x08
-#define TSPP_CONTROL 0x0C
+#define TSPP_CONFIG 0x08
+#define TSPP_CONTROL 0x0C
#define TSPP_PS_DISABLE 0x10
-#define TSPP_MSG_IRQ_STATUS 0x14
+#define TSPP_MSG_IRQ_STATUS 0x14
#define TSPP_MSG_IRQ_MASK 0x18
#define TSPP_IRQ_STATUS 0x1C
#define TSPP_IRQ_MASK 0x20
#define TSPP_IRQ_CLEAR 0x24
#define TSPP_PIPE_ERROR_STATUS(_n) (0x28 + (_n << 2))
-#define TSPP_STATUS 0x68
-#define TSPP_CURR_TSP_HEADER 0x6C
-#define TSPP_CURR_PID_FILTER 0x70
-#define TSPP_SYSTEM_KEY(_n) (0x74 + (_n << 2))
-#define TSPP_CBC_INIT_VAL(_n) (0x94 + (_n << 2))
-#define TSPP_DATA_KEY_RESET 0x9C
+#define TSPP_STATUS 0x68
+#define TSPP_CURR_TSP_HEADER 0x6C
+#define TSPP_CURR_PID_FILTER 0x70
+#define TSPP_SYSTEM_KEY(_n) (0x74 + (_n << 2))
+#define TSPP_CBC_INIT_VAL(_n) (0x94 + (_n << 2))
+#define TSPP_DATA_KEY_RESET 0x9C
#define TSPP_KEY_VALID 0xA0
#define TSPP_KEY_ERROR 0xA4
#define TSPP_TEST_CTRL 0xA8
-#define TSPP_VERSION 0xAC
+#define TSPP_VERSION 0xAC
#define TSPP_GENERICS 0xB0
-#define TSPP_NOP 0xB4
+#define TSPP_NOP 0xB4
/*
* Register bit definitions
@@ -172,30 +172,30 @@
#define TSPP_MSG_TSIF_0_IRQ BIT(0)
/* TSPP_IRQ_STATUS + TSPP_IRQ_MASK + TSPP_IRQ_CLEAR */
-#define TSPP_IRQ_STATUS_TSP_RD_CMPL BIT(19)
-#define TSPP_IRQ_STATUS_KEY_ERROR BIT(18)
+#define TSPP_IRQ_STATUS_TSP_RD_CMPL BIT(19)
+#define TSPP_IRQ_STATUS_KEY_ERROR BIT(18)
#define TSPP_IRQ_STATUS_KEY_SWITCHED_BAD BIT(17)
#define TSPP_IRQ_STATUS_KEY_SWITCHED BIT(16)
#define TSPP_IRQ_STATUS_PS_BROKEN(_n) BIT((_n))
/* TSPP_PIPE_ERROR_STATUS */
-#define TSPP_PIPE_PES_SYNC_ERROR BIT(3)
-#define TSPP_PIPE_PS_LENGTH_ERROR BIT(2)
+#define TSPP_PIPE_PES_SYNC_ERROR BIT(3)
+#define TSPP_PIPE_PS_LENGTH_ERROR BIT(2)
#define TSPP_PIPE_PS_CONTINUITY_ERROR BIT(1)
-#define TSPP_PIP_PS_LOST_START BIT(0)
+#define TSPP_PIP_PS_LOST_START BIT(0)
/* TSPP_STATUS */
-#define TSPP_STATUS_TSP_PKT_AVAIL BIT(10)
-#define TSPP_STATUS_TSIF1_DM_REQ BIT(6)
-#define TSPP_STATUS_TSIF0_DM_REQ BIT(2)
-#define TSPP_CURR_FILTER_TABLE BIT(0)
+#define TSPP_STATUS_TSP_PKT_AVAIL BIT(10)
+#define TSPP_STATUS_TSIF1_DM_REQ BIT(6)
+#define TSPP_STATUS_TSIF0_DM_REQ BIT(2)
+#define TSPP_CURR_FILTER_TABLE BIT(0)
/* TSPP_GENERICS */
-#define TSPP_GENERICS_CRYPTO_GEN BIT(12)
+#define TSPP_GENERICS_CRYPTO_GEN BIT(12)
#define TSPP_GENERICS_MAX_CONS_PIPES BIT(7)
-#define TSPP_GENERICS_MAX_PIPES BIT(2)
-#define TSPP_GENERICS_TSIF_1_GEN BIT(1)
-#define TSPP_GENERICS_TSIF_0_GEN BIT(0)
+#define TSPP_GENERICS_MAX_PIPES BIT(2)
+#define TSPP_GENERICS_TSIF_1_GEN BIT(1)
+#define TSPP_GENERICS_TSIF_0_GEN BIT(0)
/*
* TSPP memory regions
@@ -375,6 +375,8 @@
tspp_notifier *notifier; /* used only with kernel api */
void *notify_data; /* data to be passed with the notifier */
u32 notify_timer; /* notification for partially filled buffers */
+ tspp_memfree *memfree; /* user defined memory free function */
+ void *user_info; /* user cookie passed to memory alloc/free function */
};
struct tspp_pid_filter_table {
@@ -584,8 +586,7 @@
g = table + i;
tmp = gpio_tlmm_config(g->gpio_cfg, GPIO_CFG_DISABLE);
if (tmp) {
- pr_err("tspp_gpios_disable(0x%08x, GPIO_CFG_DISABLE)"
- " <%s> failed: %d\n",
+ pr_err("tspp_gpios_disable(0x%08x, GPIO_CFG_DISABLE) <%s> failed: %d\n",
g->gpio_cfg, g->label ?: "?", rc);
pr_err("tspp: pin %d func %d dir %d pull %d drvstr %d\n",
GPIO_PIN(g->gpio_cfg), GPIO_FUNC(g->gpio_cfg),
@@ -608,8 +609,7 @@
g = table + i;
rc = gpio_tlmm_config(g->gpio_cfg, GPIO_CFG_ENABLE);
if (rc) {
- pr_err("tspp: gpio_tlmm_config(0x%08x, GPIO_CFG_ENABLE)"
- " <%s> failed: %d\n",
+ pr_err("tspp: gpio_tlmm_config(0x%08x, GPIO_CFG_ENABLE) <%s> failed: %d\n",
g->gpio_cfg, g->label ?: "?", rc);
pr_err("tspp: pin %d func %d dir %d pull %d drvstr %d\n",
GPIO_PIN(g->gpio_cfg), GPIO_FUNC(g->gpio_cfg),
@@ -820,12 +820,12 @@
desc->virt_base = alloc(channel_id, size,
&desc->phys_base, user);
} else {
- desc->virt_base = dma_alloc_coherent(NULL, size,
- &desc->phys_base, GFP_KERNEL);
- if (desc->virt_base == 0) {
- pr_err("tspp dma alloc coherent failed %i", size);
- return -ENOMEM;
- }
+ desc->virt_base = dma_alloc_coherent(NULL, size,
+ &desc->phys_base, GFP_KERNEL);
+ if (desc->virt_base == 0) {
+ pr_err("tspp dma alloc coherent failed %i", size);
+ return -ENOMEM;
+ }
}
desc->size = size;
@@ -977,9 +977,13 @@
channel->buffer_count = 0;
channel->filter_count = 0;
channel->int_freq = 1;
+ channel->src = TSPP_SOURCE_NONE;
+ channel->mode = TSPP_MODE_DISABLED;
channel->notifier = NULL;
channel->notify_data = NULL;
channel->notify_timer = 0;
+ channel->memfree = NULL;
+ channel->user_info = NULL;
init_waitqueue_head(&channel->in_queue);
if (cdev_add(&channel->cdev, tspp_minor++, 1) != 0) {
@@ -1002,6 +1006,11 @@
static int tspp_set_buffer_size(struct tspp_channel *channel,
struct tspp_buffer *buf)
{
+ if (channel->buffer_count > 0) {
+ pr_err("tspp: cannot set buffer size - buffers already allocated\n");
+ return -EPERM;
+ }
+
if (buf->size < TSPP_MIN_BUFFER_SIZE)
channel->buffer_size = TSPP_MIN_BUFFER_SIZE;
else if (buf->size > TSPP_MAX_BUFFER_SIZE)
@@ -1033,8 +1042,8 @@
}
static void tspp_set_signal_inversion(struct tspp_channel *channel,
- int clock_inverse, int data_inverse,
- int sync_inverse, int enable_inverse)
+ int clock_inverse, int data_inverse,
+ int sync_inverse, int enable_inverse)
{
int index;
@@ -1054,8 +1063,106 @@
channel->pdev->tsif[index].enable_inverse = enable_inverse;
}
+static int tspp_is_buffer_size_aligned(u32 size, enum tspp_mode mode)
+{
+ u32 alignment;
+
+ switch (mode) {
+ case TSPP_MODE_RAW:
+ /* must be a multiple of 192 */
+ alignment = (TSPP_PACKET_LENGTH + 4);
+ if (size % alignment)
+ return 0;
+ return 1;
+
+ case TSPP_MODE_RAW_NO_SUFFIX:
+ /* must be a multiple of 188 */
+ alignment = TSPP_PACKET_LENGTH;
+ if (size % alignment)
+ return 0;
+ return 1;
+
+ case TSPP_MODE_DISABLED:
+ case TSPP_MODE_PES:
+ default:
+ /* no alignment requirement */
+ return 1;
+ }
+
+}
+
+static u32 tspp_align_buffer_size_by_mode(u32 size, enum tspp_mode mode)
+{
+ u32 new_size;
+ u32 alignment;
+
+ switch (mode) {
+ case TSPP_MODE_RAW:
+ /* must be a multiple of 192 */
+ alignment = (TSPP_PACKET_LENGTH + 4);
+ break;
+
+ case TSPP_MODE_RAW_NO_SUFFIX:
+ /* must be a multiple of 188 */
+ alignment = TSPP_PACKET_LENGTH;
+ break;
+
+ case TSPP_MODE_DISABLED:
+ case TSPP_MODE_PES:
+ default:
+ /* no alignment requirement - give the user what he asks for */
+ alignment = 1;
+ break;
+ }
+ /* align up */
+ new_size = (((size + alignment - 1) / alignment) * alignment);
+ return new_size;
+}
+
+static void tspp_destroy_buffers(u32 channel_id, struct tspp_channel *channel)
+{
+ int i;
+ struct tspp_mem_buffer *pbuf, *temp;
+
+ pbuf = channel->data;
+ for (i = 0; i < channel->buffer_count; i++) {
+ if (pbuf->desc.phys_base) {
+ if (channel->memfree) {
+ channel->memfree(channel_id,
+ pbuf->desc.size,
+ pbuf->desc.virt_base,
+ pbuf->desc.phys_base,
+ channel->user_info);
+ } else {
+ dma_free_coherent(NULL,
+ pbuf->desc.size,
+ pbuf->desc.virt_base,
+ pbuf->desc.phys_base);
+ }
+ pbuf->desc.phys_base = 0;
+ }
+ pbuf->desc.virt_base = 0;
+ pbuf->state = TSPP_BUF_STATE_EMPTY;
+ temp = pbuf;
+ pbuf = pbuf->next;
+ kfree(temp);
+ }
+}
+
/*** TSPP API functions ***/
-int tspp_open_stream(u32 dev, u32 channel_id, struct tspp_select_source *source)
+
+/**
+ * tspp_open_stream - open a TSPP stream for use.
+ *
+ * @dev: TSPP device (up to TSPP_MAX_DEVICES)
+ * @channel_id: Channel ID number (up to TSPP_NUM_CHANNELS)
+ * @source: stream source parameters.
+ *
+ * Return error status
+ *
+ */
+int tspp_open_stream(u32 dev, u32 channel_id,
+ struct tspp_select_source *source)
{
u32 val;
struct tspp_device *pdev;
@@ -1063,6 +1170,7 @@
TSPP_DEBUG("tspp_open_stream %i %i %i %i",
dev, channel_id, source->source, source->mode);
+
if (dev >= TSPP_MAX_DEVICES) {
pr_err("tspp: device id out of range");
return -ENODEV;
@@ -1082,8 +1190,8 @@
channel->src = source->source;
tspp_set_tsif_mode(channel, source->mode);
tspp_set_signal_inversion(channel, source->clk_inverse,
- source->data_inverse, source->sync_inverse,
- source->enable_inverse);
+ source->data_inverse, source->sync_inverse,
+ source->enable_inverse);
switch (source->source) {
case TSPP_SOURCE_TSIF0:
@@ -1120,6 +1228,15 @@
}
EXPORT_SYMBOL(tspp_open_stream);
+/**
+ * tspp_close_stream - close a TSPP stream.
+ *
+ * @dev: TSPP device (up to TSPP_MAX_DEVICES)
+ * @channel_id: Channel ID number (up to TSPP_NUM_CHANNELS)
+ *
+ * Return error status
+ *
+ */
int tspp_close_stream(u32 dev, u32 channel_id)
{
u32 val;
@@ -1162,6 +1279,15 @@
}
EXPORT_SYMBOL(tspp_close_stream);
+/**
+ * tspp_open_channel - open a TSPP channel.
+ *
+ * @dev: TSPP device (up to TSPP_MAX_DEVICES)
+ * @channel_id: Channel ID number (up to TSPP_NUM_CHANNELS)
+ *
+ * Return error status
+ *
+ */
int tspp_open_channel(u32 dev, u32 channel_id)
{
int rc = 0;
@@ -1269,6 +1395,15 @@
}
EXPORT_SYMBOL(tspp_open_channel);
+/**
+ * tspp_close_channel - close a TSPP channel.
+ *
+ * @dev: TSPP device (up to TSPP_MAX_DEVICES)
+ * @channel_id: Channel ID number (up to TSPP_NUM_CHANNELS)
+ *
+ * Return error status
+ *
+ */
int tspp_close_channel(u32 dev, u32 channel_id)
{
int i;
@@ -1278,7 +1413,6 @@
struct sps_connect *config;
struct tspp_device *pdev;
struct tspp_channel *channel;
- struct tspp_mem_buffer *pbuf, *temp;
if (channel_id >= TSPP_NUM_CHANNELS) {
pr_err("tspp: channel id out of range");
@@ -1333,21 +1467,12 @@
dma_free_coherent(NULL, config->desc.size, config->desc.base,
config->desc.phys_base);
- pbuf = channel->data;
- for (i = 0; i < channel->buffer_count; i++) {
- if (pbuf->desc.phys_base) {
- dma_free_coherent(NULL,
- pbuf->desc.size,
- pbuf->desc.virt_base,
- pbuf->desc.phys_base);
- pbuf->desc.phys_base = 0;
- }
- pbuf->desc.virt_base = 0;
- pbuf->state = TSPP_BUF_STATE_EMPTY;
- temp = pbuf;
- pbuf = pbuf->next;
- kfree(temp);
- }
+ tspp_destroy_buffers(channel_id, channel);
+
+ channel->src = TSPP_SOURCE_NONE;
+ channel->mode = TSPP_MODE_DISABLED;
+ channel->memfree = NULL;
+ channel->user_info = NULL;
channel->buffer_count = 0;
channel->data = NULL;
channel->read = NULL;
@@ -1363,10 +1488,20 @@
}
EXPORT_SYMBOL(tspp_close_channel);
+/**
+ * tspp_add_filter - add a TSPP filter to a channel.
+ *
+ * @dev: TSPP device (up to TSPP_MAX_DEVICES)
+ * @channel_id: Channel ID number (up to TSPP_NUM_CHANNELS)
+ * @filter: TSPP filter parameters
+ *
+ * Return error status
+ *
+ */
int tspp_add_filter(u32 dev, u32 channel_id,
struct tspp_filter *filter)
{
- int i;
+ int i, rc;
int other_channel;
int entry;
u32 val, pid, enabled;
@@ -1397,19 +1532,14 @@
return -ENOSR;
}
- /* make sure this filter mode matches the channel mode */
- switch (channel->mode) {
- case TSPP_MODE_DISABLED:
- channel->mode = filter->mode;
- break;
- case TSPP_MODE_RAW:
- case TSPP_MODE_PES:
- case TSPP_MODE_RAW_NO_SUFFIX:
- if (filter->mode != channel->mode) {
- pr_err("tspp: wrong filter mode");
- return -EBADSLT;
- }
- }
+ channel->mode = filter->mode;
+ /*
+ * if buffers are already allocated, verify they fulfil
+ * the alignment requirements.
+ */
+ if ((channel->buffer_count > 0) &&
+ (!tspp_is_buffer_size_aligned(channel->buffer_size, channel->mode)))
+ pr_warn("tspp: buffers allocated with incorrect alignment\n");
if (filter->mode == TSPP_MODE_PES) {
for (i = 0; i < TSPP_NUM_PRIORITIES; i++) {
@@ -1468,13 +1598,22 @@
pdev->filters[channel->src]->
filter[filter->priority].filter = p.filter;
- /* allocate buffers if needed */
- tspp_allocate_buffers(dev, channel->id, channel->max_buffers,
- channel->buffer_size, channel->int_freq, 0, 0);
- if (channel->buffer_count < MIN_ACCEPTABLE_BUFFER_COUNT) {
- pr_err("tspp: failed to allocate at least %i buffers",
- MIN_ACCEPTABLE_BUFFER_COUNT);
- return -ENOMEM;
+ /*
+ * allocate buffers if needed (i.e. if user did has not already called
+ * tspp_allocate_buffers() explicitly).
+ */
+ if (channel->buffer_count == 0) {
+ channel->buffer_size =
+ tspp_align_buffer_size_by_mode(channel->buffer_size,
+ channel->mode);
+ rc = tspp_allocate_buffers(dev, channel->id,
+ channel->max_buffers,
+ channel->buffer_size,
+ channel->int_freq, NULL, NULL, NULL);
+ if (rc != 0) {
+ pr_err("tspp: tspp_allocate_buffers failed\n");
+ return rc;
+ }
}
/* reenable pipe */
@@ -1489,6 +1628,16 @@
}
EXPORT_SYMBOL(tspp_add_filter);
+/**
+ * tspp_remove_filter - remove a TSPP filter from a channel.
+ *
+ * @dev: TSPP device (up to TSPP_MAX_DEVICES)
+ * @channel_id: Channel ID number (up to TSPP_NUM_CHANNELS)
+ * @filter: TSPP filter parameters
+ *
+ * Return error status
+ *
+ */
int tspp_remove_filter(u32 dev, u32 channel_id,
struct tspp_filter *filter)
{
@@ -1541,6 +1690,16 @@
}
EXPORT_SYMBOL(tspp_remove_filter);
+/**
+ * tspp_set_key - set TSPP key in key table.
+ *
+ * @dev: TSPP device (up to TSPP_MAX_DEVICES)
+ * @channel_id: Channel ID number (up to TSPP_NUM_CHANNELS)
+ * @key: TSPP key parameters
+ *
+ * Return error status
+ *
+ */
int tspp_set_key(u32 dev, u32 channel_id, struct tspp_key *key)
{
int i;
@@ -1591,6 +1750,18 @@
}
EXPORT_SYMBOL(tspp_set_key);
+/**
+ * tspp_register_notification - register TSPP channel notification function.
+ *
+ * @dev: TSPP device (up to TSPP_MAX_DEVICES)
+ * @channel_id: Channel ID number (up to TSPP_NUM_CHANNELS)
+ * @pNotify: notification function
+ * @userdata: user data to pass to notification function
+ * @timer_ms: notification for partially filled buffers
+ *
+ * Return error status
+ *
+ */
int tspp_register_notification(u32 dev, u32 channel_id,
tspp_notifier *pNotify, void *userdata, u32 timer_ms)
{
@@ -1614,6 +1785,15 @@
}
EXPORT_SYMBOL(tspp_register_notification);
+/**
+ * tspp_unregister_notification - unregister TSPP channel notification function.
+ *
+ * @dev: TSPP device (up to TSPP_MAX_DEVICES)
+ * @channel_id: Channel ID number (up to TSPP_NUM_CHANNELS)
+ *
+ * Return error status
+ *
+ */
int tspp_unregister_notification(u32 dev, u32 channel_id)
{
struct tspp_channel *channel;
@@ -1635,6 +1815,15 @@
}
EXPORT_SYMBOL(tspp_unregister_notification);
+/**
+ * tspp_get_buffer - get TSPP data buffer.
+ *
+ * @dev: TSPP device (up to TSPP_MAX_DEVICES)
+ * @channel_id: Channel ID number (up to TSPP_NUM_CHANNELS)
+ *
+ * Return error status
+ *
+ */
const struct tspp_data_descriptor *tspp_get_buffer(u32 dev, u32 channel_id)
{
struct tspp_mem_buffer *buffer;
@@ -1675,6 +1864,16 @@
}
EXPORT_SYMBOL(tspp_get_buffer);
+/**
+ * tspp_release_buffer - release TSPP data buffer back to TSPP.
+ *
+ * @dev: TSPP device (up to TSPP_MAX_DEVICES)
+ * @channel_id: Channel ID number (up to TSPP_NUM_CHANNELS)
+ * @descriptor_id: buffer descriptor ID
+ *
+ * Return error status
+ *
+ */
int tspp_release_buffer(u32 dev, u32 channel_id, u32 descriptor_id)
{
int i, found = 0;
@@ -1726,8 +1925,27 @@
}
EXPORT_SYMBOL(tspp_release_buffer);
-int tspp_allocate_buffers(u32 dev, u32 channel_id, u32 count,
- u32 size, u32 int_freq, tspp_allocator *alloc, void *user)
+/**
+ * tspp_allocate_buffers - allocate TSPP data buffers.
+ *
+ * @dev: TSPP device (up to TSPP_MAX_DEVICES)
+ * @channel_id: Channel ID number (up to TSPP_NUM_CHANNELS)
+ * @count: number of buffers to allocate
+ * @size: size of each buffer to allocate
+ * @int_freq: interrupt frequency
+ * @alloc: user defined memory allocator function. Pass NULL for default.
+ * @memfree: user defined memory free function. Pass NULL for default.
+ * @user: user data to pass to the memory allocator/free function
+ *
+ * Return error status
+ *
+ * The user can optionally call this function explicitly to allocate the TSPP
+ * data buffers. Alternatively, if the user did not call this function, it
+ * is called implicitly by tspp_add_filter().
+ */
+int tspp_allocate_buffers(u32 dev, u32 channel_id, u32 count, u32 size,
+ u32 int_freq, tspp_allocator *alloc,
+ tspp_memfree *memfree, void *user)
{
struct tspp_channel *channel;
struct tspp_device *pdev;
@@ -1736,56 +1954,62 @@
TSPP_DEBUG("tspp_allocate_buffers");
if (channel_id >= TSPP_NUM_CHANNELS) {
- pr_err("tspp: channel id out of range");
+ pr_err("%s: channel id out of range", __func__);
return -ECHRNG;
}
+
pdev = tspp_find_by_id(dev);
if (!pdev) {
- pr_err("tspp_alloc: can't find device %i", dev);
+ pr_err("%s: can't find device %i", __func__, dev);
return -ENODEV;
}
+
+ if (count < MIN_ACCEPTABLE_BUFFER_COUNT) {
+ pr_err("%s: tspp requires a minimum of %i buffers\n",
+ __func__, MIN_ACCEPTABLE_BUFFER_COUNT);
+ return -EINVAL;
+ }
+
channel = &pdev->channels[channel_id];
+ /* allow buffer allocation only if there was no previous buffer
+ * allocation for this channel.
+ */
+ if (channel->buffer_count > 0) {
+ pr_err("%s: buffers already allocated for channel %u",
+ __func__, channel_id);
+ return -EINVAL;
+ }
channel->max_buffers = count;
/* set up interrupt frequency */
- if (int_freq > channel->max_buffers)
+ if (int_freq > channel->max_buffers) {
int_freq = channel->max_buffers;
- channel->int_freq = int_freq;
-
- switch (channel->mode) {
- case TSPP_MODE_DISABLED:
- case TSPP_MODE_PES:
- /* give the user what he asks for */
- channel->buffer_size = size;
- break;
-
- case TSPP_MODE_RAW:
- /* must be a multiple of 192 */
- if (size < (TSPP_PACKET_LENGTH+4))
- channel->buffer_size = (TSPP_PACKET_LENGTH+4);
- else
- channel->buffer_size = (size /
- (TSPP_PACKET_LENGTH+4)) *
- (TSPP_PACKET_LENGTH+4);
- break;
-
- case TSPP_MODE_RAW_NO_SUFFIX:
- /* must be a multiple of 188 */
- channel->buffer_size = (size / TSPP_PACKET_LENGTH) *
- TSPP_PACKET_LENGTH;
- break;
+ pr_warn("%s: setting interrupt frequency to %u\n",
+ __func__, int_freq);
}
+ channel->int_freq = int_freq;
+ /*
+ * it is the responsibility of the caller to tspp_allocate_buffers(),
+ * whether it's the user or the driver, to make sure the size parameter
+ * is compatible to the channel mode.
+ */
+ channel->buffer_size = size;
- for (; channel->buffer_count < channel->max_buffers;
+ /* save user defined memory free function for later use */
+ channel->memfree = memfree;
+ channel->user_info = user;
+
+ for (channel->buffer_count = 0;
+ channel->buffer_count < channel->max_buffers;
channel->buffer_count++) {
/* allocate the descriptor */
struct tspp_mem_buffer *desc = (struct tspp_mem_buffer *)
kmalloc(sizeof(struct tspp_mem_buffer), GFP_KERNEL);
if (!desc) {
- pr_warn("tspp: Can't allocate desc %i",
- channel->buffer_count);
+ pr_warn("%s: Can't allocate desc %i",
+ __func__, channel->buffer_count);
break;
}
@@ -1794,8 +2018,8 @@
if (tspp_alloc_buffer(channel_id, &desc->desc,
channel->buffer_size, alloc, user) != 0) {
kfree(desc);
- pr_warn("tspp: Can't allocate buffer %i",
- channel->buffer_count);
+ pr_warn("%s: Can't allocate buffer %i",
+ __func__, channel->buffer_count);
break;
}
@@ -1818,12 +2042,24 @@
/* start the transfer */
if (tspp_queue_buffer(channel, desc))
- pr_err("tspp: can't queue buffer %i", desc->desc.id);
+ pr_err("%s: can't queue buffer %i",
+ __func__, desc->desc.id);
+ }
+
+ if (channel->buffer_count < channel->max_buffers) {
+ /*
+ * we failed to allocate the requested number of buffers.
+ * we don't allow a partial success, so need to clean up here.
+ */
+ tspp_destroy_buffers(channel_id, channel);
+ channel->buffer_count = 0;
+ return -ENOMEM;
}
channel->waiting = channel->data;
channel->read = channel->data;
channel->locked = channel->data;
+
return 0;
}
EXPORT_SYMBOL(tspp_allocate_buffers);
@@ -1942,8 +2178,10 @@
transferred += size;
buffer->read_index += size;
- /* after reading the end of the buffer, requeue it,
- and set up for reading the next one */
+ /*
+ * after reading the end of the buffer, requeue it,
+ * and set up for reading the next one
+ */
if (buffer->read_index == buffer->filled) {
buffer->state = TSPP_BUF_STATE_WAITING;
if (tspp_queue_buffer(channel, buffer))
@@ -2042,8 +2280,10 @@
pr_err("tspp: Unknown ioctl %i", param0);
}
- /* normalize the return code in case one of the subfunctions does
- something weird */
+ /*
+ * normalize the return code in case one of the subfunctions does
+ * something weird
+ */
if (rc != 0)
rc = -ENOIOCTLCMD;
@@ -2136,13 +2376,14 @@
{
int rc = -ENODEV;
u32 version;
- u32 i;
+ u32 i, j;
struct msm_tspp_platform_data *data;
struct tspp_device *device;
struct resource *mem_tsif0;
struct resource *mem_tsif1;
struct resource *mem_tspp;
struct resource *mem_bam;
+ struct tspp_channel *channel;
/* must have platform data */
data = pdev->dev.platform_data;
@@ -2338,6 +2579,12 @@
return 0;
err_channel:
+ /* uninitialize channels */
+ for (j = 0; j < i; j++) {
+ channel = &(device->channels[i]);
+ device_destroy(tspp_class, channel->cdev.dev);
+ cdev_del(&channel->cdev);
+ }
err_clock:
sps_deregister_bam_device(device->bam_handle);
err_bam:
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index fe41cdd..ade2b97 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -1472,64 +1472,6 @@
}
EXPORT_SYMBOL(mmc_blk_init_packed_statistics);
-void print_mmc_packing_stats(struct mmc_card *card)
-{
- int i;
- int max_num_of_packed_reqs = 0;
-
- if ((!card) || (!card->wr_pack_stats.packing_events))
- return;
-
- max_num_of_packed_reqs = card->ext_csd.max_packed_writes;
-
- spin_lock(&card->wr_pack_stats.lock);
-
- pr_info("%s: write packing statistics:\n",
- mmc_hostname(card->host));
-
- for (i = 1 ; i <= max_num_of_packed_reqs ; ++i) {
- if (card->wr_pack_stats.packing_events[i] != 0)
- pr_info("%s: Packed %d reqs - %d times\n",
- mmc_hostname(card->host), i,
- card->wr_pack_stats.packing_events[i]);
- }
-
- pr_info("%s: stopped packing due to the following reasons:\n",
- mmc_hostname(card->host));
-
- if (card->wr_pack_stats.pack_stop_reason[EXCEEDS_SEGMENTS])
- pr_info("%s: %d times: exceedmax num of segments\n",
- mmc_hostname(card->host),
- card->wr_pack_stats.pack_stop_reason[EXCEEDS_SEGMENTS]);
- if (card->wr_pack_stats.pack_stop_reason[EXCEEDS_SECTORS])
- pr_info("%s: %d times: exceeding the max num of sectors\n",
- mmc_hostname(card->host),
- card->wr_pack_stats.pack_stop_reason[EXCEEDS_SECTORS]);
- if (card->wr_pack_stats.pack_stop_reason[WRONG_DATA_DIR])
- pr_info("%s: %d times: wrong data direction\n",
- mmc_hostname(card->host),
- card->wr_pack_stats.pack_stop_reason[WRONG_DATA_DIR]);
- if (card->wr_pack_stats.pack_stop_reason[FLUSH_OR_DISCARD])
- pr_info("%s: %d times: flush or discard\n",
- mmc_hostname(card->host),
- card->wr_pack_stats.pack_stop_reason[FLUSH_OR_DISCARD]);
- if (card->wr_pack_stats.pack_stop_reason[EMPTY_QUEUE])
- pr_info("%s: %d times: empty queue\n",
- mmc_hostname(card->host),
- card->wr_pack_stats.pack_stop_reason[EMPTY_QUEUE]);
- if (card->wr_pack_stats.pack_stop_reason[REL_WRITE])
- pr_info("%s: %d times: rel write\n",
- mmc_hostname(card->host),
- card->wr_pack_stats.pack_stop_reason[REL_WRITE]);
- if (card->wr_pack_stats.pack_stop_reason[THRESHOLD])
- pr_info("%s: %d times: Threshold\n",
- mmc_hostname(card->host),
- card->wr_pack_stats.pack_stop_reason[THRESHOLD]);
-
- spin_unlock(&card->wr_pack_stats.lock);
-}
-EXPORT_SYMBOL(print_mmc_packing_stats);
-
static u8 mmc_blk_prep_packed_list(struct mmc_queue *mq, struct request *req)
{
struct request_queue *q = mq->queue;
diff --git a/drivers/mmc/card/mmc_block_test.c b/drivers/mmc/card/mmc_block_test.c
index 2307d7a..c5551b8 100644
--- a/drivers/mmc/card/mmc_block_test.c
+++ b/drivers/mmc/card/mmc_block_test.c
@@ -221,6 +221,63 @@
static struct mmc_block_test_data *mbtd;
+void print_mmc_packing_stats(struct mmc_card *card)
+{
+ int i;
+ int max_num_of_packed_reqs = 0;
+
+ if ((!card) || (!card->wr_pack_stats.packing_events))
+ return;
+
+ max_num_of_packed_reqs = card->ext_csd.max_packed_writes;
+
+ spin_lock(&card->wr_pack_stats.lock);
+
+ pr_info("%s: write packing statistics:\n",
+ mmc_hostname(card->host));
+
+ for (i = 1 ; i <= max_num_of_packed_reqs ; ++i) {
+ if (card->wr_pack_stats.packing_events[i] != 0)
+ pr_info("%s: Packed %d reqs - %d times\n",
+ mmc_hostname(card->host), i,
+ card->wr_pack_stats.packing_events[i]);
+ }
+
+ pr_info("%s: stopped packing due to the following reasons:\n",
+ mmc_hostname(card->host));
+
+ if (card->wr_pack_stats.pack_stop_reason[EXCEEDS_SEGMENTS])
+ pr_info("%s: %d times: exceedmax num of segments\n",
+ mmc_hostname(card->host),
+ card->wr_pack_stats.pack_stop_reason[EXCEEDS_SEGMENTS]);
+ if (card->wr_pack_stats.pack_stop_reason[EXCEEDS_SECTORS])
+ pr_info("%s: %d times: exceeding the max num of sectors\n",
+ mmc_hostname(card->host),
+ card->wr_pack_stats.pack_stop_reason[EXCEEDS_SECTORS]);
+ if (card->wr_pack_stats.pack_stop_reason[WRONG_DATA_DIR])
+ pr_info("%s: %d times: wrong data direction\n",
+ mmc_hostname(card->host),
+ card->wr_pack_stats.pack_stop_reason[WRONG_DATA_DIR]);
+ if (card->wr_pack_stats.pack_stop_reason[FLUSH_OR_DISCARD])
+ pr_info("%s: %d times: flush or discard\n",
+ mmc_hostname(card->host),
+ card->wr_pack_stats.pack_stop_reason[FLUSH_OR_DISCARD]);
+ if (card->wr_pack_stats.pack_stop_reason[EMPTY_QUEUE])
+ pr_info("%s: %d times: empty queue\n",
+ mmc_hostname(card->host),
+ card->wr_pack_stats.pack_stop_reason[EMPTY_QUEUE]);
+ if (card->wr_pack_stats.pack_stop_reason[REL_WRITE])
+ pr_info("%s: %d times: rel write\n",
+ mmc_hostname(card->host),
+ card->wr_pack_stats.pack_stop_reason[REL_WRITE]);
+ if (card->wr_pack_stats.pack_stop_reason[THRESHOLD])
+ pr_info("%s: %d times: Threshold\n",
+ mmc_hostname(card->host),
+ card->wr_pack_stats.pack_stop_reason[THRESHOLD]);
+
+ spin_unlock(&card->wr_pack_stats.lock);
+}
+
/*
* A callback assigned to the packed_test_fn field.
* Called from block layer in mmc_blk_packed_hdr_wrq_prep.
@@ -499,11 +556,11 @@
switch (td->test_info.testcase) {
case TEST_STOP_DUE_TO_FLUSH:
- return "Test stop due to flush";
+ return " stop due to flush";
case TEST_STOP_DUE_TO_FLUSH_AFTER_MAX_REQS:
- return "Test stop due to flush after max-1 reqs";
+ return " stop due to flush after max-1 reqs";
case TEST_STOP_DUE_TO_READ:
- return "Test stop due to read";
+ return " stop due to read";
case TEST_STOP_DUE_TO_READ_AFTER_MAX_REQS:
return "Test stop due to read after max-1 reqs";
case TEST_STOP_DUE_TO_EMPTY_QUEUE:
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 49bbe09..95e7753 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -2215,7 +2215,9 @@
}
if ((mrq->cmd->opcode == MMC_WRITE_BLOCK) ||
- (mrq->cmd->opcode == MMC_WRITE_MULTIPLE_BLOCK))
+ (mrq->cmd->opcode == MMC_WRITE_MULTIPLE_BLOCK) ||
+ ((mrq->cmd->opcode == SD_IO_RW_EXTENDED) &&
+ is_data_pend_for_cmd53(host)))
host->curr.use_wr_data_pend = true;
}
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index af5498e..9fa2027 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -446,6 +446,7 @@
#define MSMSDCC_AUTO_CMD19 (1 << 9)
#define MSMSDCC_AUTO_CMD21 (1 << 10)
#define MSMSDCC_SW_RST_CFG_BROKEN (1 << 11)
+#define MSMSDCC_DATA_PEND_FOR_CMD53 (1 << 12)
#define set_hw_caps(h, val) ((h)->hw_caps |= val)
#define is_sps_mode(h) ((h)->hw_caps & MSMSDCC_SPS_BAM_SUP)
@@ -461,6 +462,7 @@
#define is_auto_cmd21(h) ((h)->hw_caps & MSMSDCC_AUTO_CMD21)
#define is_sw_reset_save_config_broken(h) \
((h)->hw_caps & MSMSDCC_SW_RST_CFG_BROKEN)
+#define is_data_pend_for_cmd53(h) ((h)->hw_caps & MSMSDCC_DATA_PEND_FOR_CMD53)
/* Set controller capabilities based on version */
static inline void set_default_hw_caps(struct msmsdcc_host *host)
@@ -493,7 +495,8 @@
if (step >= 0x2b) /* SDCC v4 2.1.0 and greater */
host->hw_caps |= MSMSDCC_SW_RST | MSMSDCC_SW_RST_CFG |
- MSMSDCC_AUTO_CMD21;
+ MSMSDCC_AUTO_CMD21 |
+ MSMSDCC_DATA_PEND_FOR_CMD53;
if (step == 0x2b)
host->hw_caps |= MSMSDCC_SW_RST_CFG_BROKEN;
diff --git a/drivers/net/ethernet/msm/msm_rmnet.c b/drivers/net/ethernet/msm/msm_rmnet.c
index 41ad8af..4af2d8c 100644
--- a/drivers/net/ethernet/msm/msm_rmnet.c
+++ b/drivers/net/ethernet/msm/msm_rmnet.c
@@ -3,7 +3,7 @@
* Virtual Ethernet Interface for MSM7K Networking
*
* Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
* Author: Brian Swetland <swetland@google.com>
*
* This software is licensed under the terms of the GNU General Public
@@ -37,7 +37,7 @@
#endif
#include <mach/msm_smd.h>
-#include <mach/peripheral-loader.h>
+#include <mach/subsystem_restart.h>
/* Debug message support */
static int msm_rmnet_debug_mask;
@@ -403,7 +403,7 @@
static void msm_rmnet_unload_modem(void *pil)
{
if (pil)
- pil_put(pil);
+ subsystem_put(pil);
}
static void *msm_rmnet_load_modem(struct net_device *dev)
@@ -412,7 +412,7 @@
int rc;
struct rmnet_private *p = netdev_priv(dev);
- pil = pil_get("modem");
+ pil = subsystem_get("modem");
if (IS_ERR(pil))
pr_err("[%s] %s: modem load failed\n",
dev->name, __func__);
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index 2bf857c..b9459dd 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -25,9 +25,11 @@
#include <linux/delay.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
-#include <mach/peripheral-loader.h>
+
#include <mach/msm_smd.h>
#include <mach/msm_iomap.h>
+#include <mach/subsystem_restart.h>
+
#ifdef CONFIG_WCNSS_MEM_PRE_ALLOC
#include "wcnss_prealloc.h"
#endif
@@ -664,7 +666,7 @@
}
/* trigger initialization of the WCNSS */
- penv->pil = pil_get(WCNSS_PIL_DEVICE);
+ penv->pil = subsystem_get(WCNSS_PIL_DEVICE);
if (IS_ERR(penv->pil)) {
dev_err(&pdev->dev, "Peripheral Loader failed on WCNSS.\n");
ret = PTR_ERR(penv->pil);
@@ -694,7 +696,7 @@
fail_res:
if (penv->pil)
- pil_put(penv->pil);
+ subsystem_put(penv->pil);
fail_pil:
wcnss_wlan_power(&pdev->dev, &penv->wlan_config,
WCNSS_WLAN_SWITCH_OFF);
@@ -840,7 +842,7 @@
{
if (penv) {
if (penv->pil)
- pil_put(penv->pil);
+ subsystem_put(penv->pil);
kfree(penv);
diff --git a/drivers/power/bq28400_battery.c b/drivers/power/bq28400_battery.c
index 47fced1..39eac60 100644
--- a/drivers/power/bq28400_battery.c
+++ b/drivers/power/bq28400_battery.c
@@ -509,13 +509,15 @@
return POWER_SUPPLY_STATUS_FULL;
}
+ /* Enable charging when battery is not full */
+ bq28400_enable_charging(bq28400_dev, true);
+
/*
* Positive current indicates charging
* Negative current indicates discharging.
* Charging is stopped at termination-current.
*/
if (current_ma < 0) {
- bq28400_enable_charging(bq28400_dev, true);
pr_debug("Discharging.\n");
status = POWER_SUPPLY_STATUS_DISCHARGING;
} else if (current_ma > BQ_TERMINATION_CURRENT_MA) {
@@ -755,6 +757,12 @@
static void bq28400_external_power_changed(struct power_supply *psy)
{
pr_debug("Notify power_supply_changed.\n");
+
+ /* The battery gauge monitors the current and voltage every 1 second.
+ * Therefore a delay from the time that the charger start/stop charging
+ * until the battery gauge detects it.
+ */
+ msleep(1000);
/* Update LEDs and notify uevents */
power_supply_changed(&bq28400_dev->batt_psy);
}
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index eaf0fcb..8a36d6c 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -4357,6 +4357,11 @@
vin_collapse_check_worker);
INIT_DELAYED_WORK(&chip->unplug_check_work, unplug_check_worker);
+ INIT_WORK(&chip->bms_notify.work, bms_notify);
+ INIT_WORK(&chip->battery_id_valid_work, battery_id_valid);
+
+ INIT_DELAYED_WORK(&chip->update_heartbeat_work, update_heartbeat);
+
rc = request_irqs(chip, pdev);
if (rc) {
pr_err("couldn't register interrupts rc=%d\n", rc);
@@ -4393,19 +4398,13 @@
}
create_debugfs_entries(chip);
- INIT_WORK(&chip->bms_notify.work, bms_notify);
- INIT_WORK(&chip->battery_id_valid_work, battery_id_valid);
-
/* determine what state the charger is in */
determine_initial_state(chip);
- if (chip->update_time) {
- INIT_DELAYED_WORK(&chip->update_heartbeat_work,
- update_heartbeat);
+ if (chip->update_time)
schedule_delayed_work(&chip->update_heartbeat_work,
round_jiffies_relative(msecs_to_jiffies
(chip->update_time)));
- }
return 0;
free_irq:
diff --git a/drivers/power/smb350_charger.c b/drivers/power/smb350_charger.c
index 93e208c..319caba 100644
--- a/drivers/power/smb350_charger.c
+++ b/drivers/power/smb350_charger.c
@@ -753,13 +753,22 @@
i2c_set_clientdata(client, dev);
- pr_debug("set charge-enable + not suspend.\n");
- gpio_set_value_cansleep(dev->chg_en_n_gpio, 1); /* Disable */
+ /* Disable battery charging by default on power up.
+ * Battery charging is enabled by BMS or Battery-Gauge
+ * by using the set_property callback.
+ */
+ smb350_enable_charging(dev, false);
msleep(100);
gpio_set_value_cansleep(dev->chg_susp_n_gpio, 1); /* Normal */
msleep(100); /* Allow the device to exist shutdown */
- smb350_read_reg(client, I2C_SLAVE_ADDR_REG);
+ /* I2C transaction allowed only after device exit suspend */
+ ret = smb350_read_reg(client, I2C_SLAVE_ADDR_REG);
+ if ((ret>>1) != client->addr) {
+ pr_err("No device.\n");
+ ret = -ENODEV;
+ goto err_no_dev;
+ }
ret = smb350_set_volatile_params(dev);
if (ret)
@@ -784,14 +793,13 @@
goto err_irq;
}
- smb350_enable_charging(dev, true);
-
return 0;
err_irq:
err_debugfs:
if (dev->dent)
debugfs_remove_recursive(dev->dent);
+err_no_dev:
err_set_params:
gpio_free(dev->chg_en_n_gpio);
err_en_gpio:
diff --git a/drivers/slimbus/slim-msm-ctrl.c b/drivers/slimbus/slim-msm-ctrl.c
index 58a1d66..7efe40d 100644
--- a/drivers/slimbus/slim-msm-ctrl.c
+++ b/drivers/slimbus/slim-msm-ctrl.c
@@ -111,15 +111,16 @@
static int msm_sat_enqueue(struct msm_slim_sat *sat, u32 *buf, u8 len)
{
struct msm_slim_ctrl *dev = sat->dev;
- spin_lock(&sat->lock);
+ unsigned long flags;
+ spin_lock_irqsave(&sat->lock, flags);
if ((sat->stail + 1) % SAT_CONCUR_MSG == sat->shead) {
- spin_unlock(&sat->lock);
+ spin_unlock_irqrestore(&sat->lock, flags);
dev_err(dev->dev, "SAT QUEUE full!");
return -EXFULL;
}
memcpy(sat->sat_msgs[sat->stail], (u8 *)buf, len);
sat->stail = (sat->stail + 1) % SAT_CONCUR_MSG;
- spin_unlock(&sat->lock);
+ spin_unlock_irqrestore(&sat->lock, flags);
return 0;
}
diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c
index e73caf1..432abe5 100644
--- a/drivers/staging/android/lowmemorykiller.c
+++ b/drivers/staging/android/lowmemorykiller.c
@@ -62,6 +62,81 @@
printk(x); \
} while (0)
+static int nr_free_zone_mtype_pages(struct zone *zone, int mtype)
+{
+ int order;
+ int sum = 0;
+
+ for (order = 0; order < MAX_ORDER; ++order) {
+ unsigned long freecount = 0;
+ struct free_area *area;
+ struct list_head *curr;
+
+ area = &(zone->free_area[order]);
+
+ list_for_each(curr, &area->free_list[mtype])
+ freecount++;
+
+ sum += freecount << order;
+ }
+ return sum;
+}
+
+static int nr_free_zone_pages(struct zone *zone, gfp_t gfp_mask)
+{
+ int sum = 0;
+ int mtype = allocflags_to_migratetype(gfp_mask);
+ int i = 0;
+ int *mtype_fallbacks = get_migratetype_fallbacks(mtype);
+
+ sum = nr_free_zone_mtype_pages(zone, mtype);
+
+ /*
+ * Also count the fallback pages
+ */
+ for (i = 0;; i++) {
+ int fallbacktype = mtype_fallbacks[i];
+ sum += nr_free_zone_mtype_pages(zone, fallbacktype);
+
+ if (fallbacktype == MIGRATE_RESERVE)
+ break;
+ }
+
+ return sum;
+}
+
+static int nr_free_pages(gfp_t gfp_mask)
+{
+ struct zoneref *z;
+ struct zone *zone;
+ int sum = 0;
+
+ struct zonelist *zonelist = node_zonelist(numa_node_id(), gfp_mask);
+
+ for_each_zone_zonelist(zone, z, zonelist, gfp_zone(gfp_mask)) {
+ sum += nr_free_zone_pages(zone, gfp_mask);
+ }
+
+ return sum;
+}
+
+
+static int test_task_flag(struct task_struct *p, int flag)
+{
+ struct task_struct *t = p;
+
+ do {
+ task_lock(t);
+ if (test_tsk_thread_flag(t, flag)) {
+ task_unlock(t);
+ return 1;
+ }
+ task_unlock(t);
+ } while_each_thread(p, t);
+
+ return 0;
+}
+
static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
{
struct task_struct *tsk;
@@ -77,6 +152,15 @@
int other_file = global_page_state(NR_FILE_PAGES) -
global_page_state(NR_SHMEM);
+ if (sc->nr_to_scan > 0 && other_free > other_file) {
+ /*
+ * If the number of free pages is going to affect the decision
+ * of which process is selected then ensure only free pages
+ * which can satisfy the request are considered.
+ */
+ other_free = nr_free_pages(sc->gfp_mask);
+ }
+
if (lowmem_adj_size < array_size)
array_size = lowmem_adj_size;
if (lowmem_minfree_size < array_size)
@@ -111,16 +195,17 @@
if (tsk->flags & PF_KTHREAD)
continue;
+ if (time_before_eq(jiffies, lowmem_deathpending_timeout)) {
+ if (test_task_flag(tsk, TIF_MEMDIE)) {
+ rcu_read_unlock();
+ return 0;
+ }
+ }
+
p = find_lock_task_mm(tsk);
if (!p)
continue;
- if (test_tsk_thread_flag(p, TIF_MEMDIE) &&
- time_before_eq(jiffies, lowmem_deathpending_timeout)) {
- task_unlock(p);
- rcu_read_unlock();
- return 0;
- }
oom_score_adj = p->signal->oom_score_adj;
if (oom_score_adj < min_score_adj) {
task_unlock(p);
diff --git a/drivers/tty/serial/msm_serial_hs_lite.c b/drivers/tty/serial/msm_serial_hs_lite.c
index f065eaa..2f3f83d 100644
--- a/drivers/tty/serial/msm_serial_hs_lite.c
+++ b/drivers/tty/serial/msm_serial_hs_lite.c
@@ -149,12 +149,9 @@
static int get_line(struct platform_device *pdev)
{
- const struct msm_serial_hslite_platform_data *pdata =
- pdev->dev.platform_data;
- if (pdata)
- return pdata->line;
+ struct msm_hsl_port *msm_hsl_port = platform_get_drvdata(pdev);
- return pdev->id;
+ return msm_hsl_port->uart.line;
}
static int clk_en(struct uart_port *port, int enable)
@@ -1357,18 +1354,32 @@
struct resource *uart_resource;
struct resource *gsbi_resource;
struct uart_port *port;
+ const struct msm_serial_hslite_platform_data *pdata;
const struct of_device_id *match;
+ u32 line;
int ret;
if (pdev->id == -1)
pdev->id = atomic_inc_return(&msm_serial_hsl_next_id) - 1;
- if (unlikely(get_line(pdev) < 0 || get_line(pdev) >= UART_NR))
+ /* Use line (ttyHSLx) number from pdata or device tree if specified */
+ pdata = pdev->dev.platform_data;
+ if (pdata)
+ line = pdata->line;
+ else
+ line = pdev->id;
+
+ /* Use line number from device tree if present */
+ if (pdev->dev.of_node)
+ of_property_read_u32(pdev->dev.of_node, "cell-index", &line);
+
+ if (unlikely(line < 0 || line >= UART_NR))
return -ENXIO;
- printk(KERN_INFO "msm_serial_hsl: detected port #%d\n", pdev->id);
+ printk(KERN_INFO "msm_serial_hsl: detected port #%d (ttyHSL%d)\n",
+ pdev->id, line);
- port = get_port_from_line(get_line(pdev));
+ port = get_port_from_line(line);
port->dev = &pdev->dev;
msm_hsl_port = UART_TO_MSM(port);
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 0531f83..98eb0a0 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -1290,6 +1290,8 @@
if (mdwc->otg_xceiv && mdwc->ext_xceiv.otg_capability)
dwc3_hsusb_ldo_enable(0);
+ dwc3_ssusb_ldo_enable(0);
+ dwc3_ssusb_config_vddcx(0);
dwc3_hsusb_config_vddcx(0);
wake_unlock(&mdwc->wlock);
atomic_set(&mdwc->in_lpm, 1);
@@ -1328,6 +1330,8 @@
if (mdwc->otg_xceiv && mdwc->ext_xceiv.otg_capability)
dwc3_hsusb_ldo_enable(1);
+ dwc3_ssusb_ldo_enable(1);
+ dwc3_ssusb_config_vddcx(1);
dwc3_hsusb_config_vddcx(1);
clk_prepare_enable(mdwc->ref_clk);
usleep_range(1000, 1200);
diff --git a/drivers/usb/gadget/f_accessory.c b/drivers/usb/gadget/f_accessory.c
index 42a6c43..5659c79 100644
--- a/drivers/usb/gadget/f_accessory.c
+++ b/drivers/usb/gadget/f_accessory.c
@@ -132,6 +132,41 @@
.bInterfaceProtocol = 0,
};
+static struct usb_endpoint_descriptor acc_superspeed_in_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = __constant_cpu_to_le16(1024),
+};
+
+static struct usb_ss_ep_comp_descriptor acc_superspeed_in_comp_desc = {
+ .bLength = sizeof acc_superspeed_in_comp_desc,
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+
+ /* the following 2 values can be tweaked if necessary */
+ /* .bMaxBurst = 0, */
+ /* .bmAttributes = 0, */
+};
+
+static struct usb_endpoint_descriptor acc_superspeed_out_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = __constant_cpu_to_le16(1024),
+};
+
+static struct usb_ss_ep_comp_descriptor acc_superspeed_out_comp_desc = {
+ .bLength = sizeof acc_superspeed_out_comp_desc,
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+
+ /* the following 2 values can be tweaked if necessary */
+ /* .bMaxBurst = 0, */
+ /* .bmAttributes = 0, */
+};
+
+
static struct usb_endpoint_descriptor acc_highspeed_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@@ -176,6 +211,15 @@
NULL,
};
+static struct usb_descriptor_header *ss_acc_descs[] = {
+ (struct usb_descriptor_header *) &acc_interface_desc,
+ (struct usb_descriptor_header *) &acc_superspeed_in_desc,
+ (struct usb_descriptor_header *) &acc_superspeed_in_comp_desc,
+ (struct usb_descriptor_header *) &acc_superspeed_out_desc,
+ (struct usb_descriptor_header *) &acc_superspeed_out_comp_desc,
+ NULL,
+};
+
static struct usb_string acc_string_defs[] = {
[INTERFACE_STRING_INDEX].s = "Android Accessory Interface",
{ }, /* end of list */
@@ -907,6 +951,14 @@
acc_fullspeed_out_desc.bEndpointAddress;
}
+ /* support super speed hardware */
+ if (gadget_is_superspeed(c->cdev->gadget)) {
+ acc_superspeed_in_desc.bEndpointAddress =
+ acc_fullspeed_in_desc.bEndpointAddress;
+ acc_superspeed_out_desc.bEndpointAddress =
+ acc_fullspeed_out_desc.bEndpointAddress;
+ }
+
DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n",
gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
f->name, dev->ep_in->name, dev->ep_out->name);
@@ -1135,6 +1187,8 @@
dev->function.strings = acc_strings,
dev->function.descriptors = fs_acc_descs;
dev->function.hs_descriptors = hs_acc_descs;
+ if (gadget_is_superspeed(c->cdev->gadget))
+ dev->function.ss_descriptors = ss_acc_descs;
dev->function.bind = acc_function_bind;
dev->function.unbind = acc_function_unbind;
dev->function.set_alt = acc_function_set_alt;
diff --git a/drivers/usb/gadget/f_adb.c b/drivers/usb/gadget/f_adb.c
index 14e5b60..68c99a3 100644
--- a/drivers/usb/gadget/f_adb.c
+++ b/drivers/usb/gadget/f_adb.c
@@ -69,6 +69,40 @@
.bInterfaceProtocol = 1,
};
+static struct usb_endpoint_descriptor adb_superspeed_in_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = __constant_cpu_to_le16(1024),
+};
+
+static struct usb_ss_ep_comp_descriptor adb_superspeed_in_comp_desc = {
+ .bLength = sizeof adb_superspeed_in_comp_desc,
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+
+ /* the following 2 values can be tweaked if necessary */
+ /* .bMaxBurst = 0, */
+ /* .bmAttributes = 0, */
+};
+
+static struct usb_endpoint_descriptor adb_superspeed_out_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = __constant_cpu_to_le16(1024),
+};
+
+static struct usb_ss_ep_comp_descriptor adb_superspeed_out_comp_desc = {
+ .bLength = sizeof adb_superspeed_out_comp_desc,
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+
+ /* the following 2 values can be tweaked if necessary */
+ /* .bMaxBurst = 0, */
+ /* .bmAttributes = 0, */
+};
+
static struct usb_endpoint_descriptor adb_highspeed_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@@ -113,6 +147,15 @@
NULL,
};
+static struct usb_descriptor_header *ss_adb_descs[] = {
+ (struct usb_descriptor_header *) &adb_interface_desc,
+ (struct usb_descriptor_header *) &adb_superspeed_in_desc,
+ (struct usb_descriptor_header *) &adb_superspeed_in_comp_desc,
+ (struct usb_descriptor_header *) &adb_superspeed_out_desc,
+ (struct usb_descriptor_header *) &adb_superspeed_out_comp_desc,
+ NULL,
+};
+
static void adb_ready_callback(void);
static void adb_closed_callback(void);
@@ -503,6 +546,13 @@
adb_highspeed_out_desc.bEndpointAddress =
adb_fullspeed_out_desc.bEndpointAddress;
}
+ /* support super speed hardware */
+ if (gadget_is_superspeed(c->cdev->gadget)) {
+ adb_superspeed_in_desc.bEndpointAddress =
+ adb_fullspeed_in_desc.bEndpointAddress;
+ adb_superspeed_out_desc.bEndpointAddress =
+ adb_fullspeed_out_desc.bEndpointAddress;
+ }
DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n",
gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
@@ -605,6 +655,8 @@
dev->function.name = "adb";
dev->function.descriptors = fs_adb_descs;
dev->function.hs_descriptors = hs_adb_descs;
+ if (gadget_is_superspeed(c->cdev->gadget))
+ dev->function.ss_descriptors = ss_adb_descs;
dev->function.bind = adb_function_bind;
dev->function.unbind = adb_function_unbind;
dev->function.set_alt = adb_function_set_alt;
diff --git a/drivers/usb/gadget/f_diag.c b/drivers/usb/gadget/f_diag.c
index 87597d5..8f68234 100644
--- a/drivers/usb/gadget/f_diag.c
+++ b/drivers/usb/gadget/f_diag.c
@@ -73,6 +73,40 @@
.bInterval = 0,
};
+static struct usb_endpoint_descriptor ss_bulk_in_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = __constant_cpu_to_le16(1024),
+};
+
+static struct usb_ss_ep_comp_descriptor ss_bulk_in_comp_desc = {
+ .bLength = sizeof ss_bulk_in_comp_desc,
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+
+ /* the following 2 values can be tweaked if necessary */
+ /* .bMaxBurst = 0, */
+ /* .bmAttributes = 0, */
+};
+
+static struct usb_endpoint_descriptor ss_bulk_out_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = __constant_cpu_to_le16(1024),
+};
+
+static struct usb_ss_ep_comp_descriptor ss_bulk_out_comp_desc = {
+ .bLength = sizeof ss_bulk_out_comp_desc,
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+
+ /* the following 2 values can be tweaked if necessary */
+ /* .bMaxBurst = 0, */
+ /* .bmAttributes = 0, */
+};
+
static struct usb_descriptor_header *fs_diag_desc[] = {
(struct usb_descriptor_header *) &intf_desc,
(struct usb_descriptor_header *) &fs_bulk_in_desc,
@@ -86,6 +120,15 @@
NULL,
};
+static struct usb_descriptor_header *ss_diag_desc[] = {
+ (struct usb_descriptor_header *) &intf_desc,
+ (struct usb_descriptor_header *) &ss_bulk_in_desc,
+ (struct usb_descriptor_header *) &ss_bulk_in_comp_desc,
+ (struct usb_descriptor_header *) &ss_bulk_out_desc,
+ (struct usb_descriptor_header *) &ss_bulk_out_comp_desc,
+ NULL,
+};
+
/**
* struct diag_context - USB diag function driver private structure
* @function: function structure for USB interface
@@ -551,6 +594,8 @@
{
struct diag_context *ctxt = func_to_diag(f);
+ if (gadget_is_superspeed(c->cdev->gadget))
+ usb_free_descriptors(f->ss_descriptors);
if (gadget_is_dualspeed(c->cdev->gadget))
usb_free_descriptors(f->hs_descriptors);
@@ -580,6 +625,7 @@
ctxt->out = ep;
ep->driver_data = ctxt;
+ status = -ENOMEM;
/* copy descriptors, and track endpoint copies */
f->descriptors = usb_copy_descriptors(fs_diag_desc);
if (!f->descriptors)
@@ -593,9 +639,29 @@
/* copy descriptors, and track endpoint copies */
f->hs_descriptors = usb_copy_descriptors(hs_diag_desc);
+ if (!f->hs_descriptors)
+ goto fail;
+ }
+
+ if (gadget_is_superspeed(c->cdev->gadget)) {
+ ss_bulk_in_desc.bEndpointAddress =
+ fs_bulk_in_desc.bEndpointAddress;
+ ss_bulk_out_desc.bEndpointAddress =
+ fs_bulk_out_desc.bEndpointAddress;
+
+ /* copy descriptors, and track endpoint copies */
+ f->ss_descriptors = usb_copy_descriptors(ss_diag_desc);
+ if (!f->ss_descriptors)
+ goto fail;
}
return 0;
fail:
+ if (f->ss_descriptors)
+ usb_free_descriptors(f->ss_descriptors);
+ if (f->hs_descriptors)
+ usb_free_descriptors(f->hs_descriptors);
+ if (f->descriptors)
+ usb_free_descriptors(f->descriptors);
if (ctxt->out)
ctxt->out->driver_data = NULL;
if (ctxt->in)
diff --git a/drivers/usb/gadget/f_mtp.c b/drivers/usb/gadget/f_mtp.c
index ccbc330..82ffbba 100644
--- a/drivers/usb/gadget/f_mtp.c
+++ b/drivers/usb/gadget/f_mtp.c
@@ -129,6 +129,40 @@
.bInterfaceProtocol = 1,
};
+static struct usb_endpoint_descriptor mtp_superspeed_in_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = __constant_cpu_to_le16(1024),
+};
+
+static struct usb_ss_ep_comp_descriptor mtp_superspeed_in_comp_desc = {
+ .bLength = sizeof mtp_superspeed_in_comp_desc,
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+
+ /* the following 2 values can be tweaked if necessary */
+ /* .bMaxBurst = 0, */
+ /* .bmAttributes = 0, */
+};
+
+static struct usb_endpoint_descriptor mtp_superspeed_out_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = __constant_cpu_to_le16(1024),
+};
+
+static struct usb_ss_ep_comp_descriptor mtp_superspeed_out_comp_desc = {
+ .bLength = sizeof mtp_superspeed_out_comp_desc,
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+
+ /* the following 2 values can be tweaked if necessary */
+ /* .bMaxBurst = 0, */
+ /* .bmAttributes = 0, */
+};
+
static struct usb_endpoint_descriptor mtp_highspeed_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@@ -168,6 +202,16 @@
.bInterval = 6,
};
+static struct usb_ss_ep_comp_descriptor mtp_superspeed_intr_comp_desc = {
+ .bLength = sizeof mtp_superspeed_intr_comp_desc,
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+
+ /* the following 3 values can be tweaked if necessary */
+ /* .bMaxBurst = 0, */
+ /* .bmAttributes = 0, */
+ .wBytesPerInterval = cpu_to_le16(INTR_BUFFER_SIZE),
+};
+
static struct usb_descriptor_header *fs_mtp_descs[] = {
(struct usb_descriptor_header *) &mtp_interface_desc,
(struct usb_descriptor_header *) &mtp_fullspeed_in_desc,
@@ -184,6 +228,17 @@
NULL,
};
+static struct usb_descriptor_header *ss_mtp_descs[] = {
+ (struct usb_descriptor_header *) &mtp_interface_desc,
+ (struct usb_descriptor_header *) &mtp_superspeed_in_desc,
+ (struct usb_descriptor_header *) &mtp_superspeed_in_comp_desc,
+ (struct usb_descriptor_header *) &mtp_superspeed_out_desc,
+ (struct usb_descriptor_header *) &mtp_superspeed_out_comp_desc,
+ (struct usb_descriptor_header *) &mtp_intr_desc,
+ (struct usb_descriptor_header *) &mtp_superspeed_intr_comp_desc,
+ NULL,
+};
+
static struct usb_descriptor_header *fs_ptp_descs[] = {
(struct usb_descriptor_header *) &ptp_interface_desc,
(struct usb_descriptor_header *) &mtp_fullspeed_in_desc,
@@ -200,6 +255,17 @@
NULL,
};
+static struct usb_descriptor_header *ss_ptp_descs[] = {
+ (struct usb_descriptor_header *) &ptp_interface_desc,
+ (struct usb_descriptor_header *) &mtp_superspeed_in_desc,
+ (struct usb_descriptor_header *) &mtp_superspeed_in_comp_desc,
+ (struct usb_descriptor_header *) &mtp_superspeed_out_desc,
+ (struct usb_descriptor_header *) &mtp_superspeed_out_comp_desc,
+ (struct usb_descriptor_header *) &mtp_intr_desc,
+ (struct usb_descriptor_header *) &mtp_superspeed_intr_comp_desc,
+ NULL,
+};
+
static struct usb_string mtp_string_defs[] = {
/* Naming interface "MTP" so libmtp will recognize us */
[INTERFACE_STRING_INDEX].s = "MTP",
@@ -1126,6 +1192,14 @@
mtp_fullspeed_out_desc.bEndpointAddress;
}
+ /* support super speed hardware */
+ if (gadget_is_superspeed(c->cdev->gadget)) {
+ mtp_superspeed_in_desc.bEndpointAddress =
+ mtp_fullspeed_in_desc.bEndpointAddress;
+ mtp_superspeed_out_desc.bEndpointAddress =
+ mtp_fullspeed_out_desc.bEndpointAddress;
+ }
+
DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n",
gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
f->name, dev->ep_in->name, dev->ep_out->name);
@@ -1239,9 +1313,13 @@
if (ptp_config) {
dev->function.descriptors = fs_ptp_descs;
dev->function.hs_descriptors = hs_ptp_descs;
+ if (gadget_is_superspeed(c->cdev->gadget))
+ dev->function.ss_descriptors = ss_ptp_descs;
} else {
dev->function.descriptors = fs_mtp_descs;
dev->function.hs_descriptors = hs_mtp_descs;
+ if (gadget_is_superspeed(c->cdev->gadget))
+ dev->function.ss_descriptors = ss_mtp_descs;
}
dev->function.bind = mtp_function_bind;
dev->function.unbind = mtp_function_unbind;
diff --git a/drivers/usb/gadget/f_rmnet.c b/drivers/usb/gadget/f_rmnet.c
index aa9daf3..4357e0d 100644
--- a/drivers/usb/gadget/f_rmnet.c
+++ b/drivers/usb/gadget/f_rmnet.c
@@ -147,6 +147,71 @@
NULL,
};
+/* Super speed support */
+static struct usb_endpoint_descriptor rmnet_ss_notify_desc = {
+ .bLength = sizeof rmnet_ss_notify_desc,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = __constant_cpu_to_le16(RMNET_MAX_NOTIFY_SIZE),
+ .bInterval = RMNET_NOTIFY_INTERVAL + 4,
+};
+
+static struct usb_ss_ep_comp_descriptor rmnet_ss_notify_comp_desc = {
+ .bLength = sizeof rmnet_ss_notify_comp_desc,
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+
+ /* the following 3 values can be tweaked if necessary */
+ /* .bMaxBurst = 0, */
+ /* .bmAttributes = 0, */
+ .wBytesPerInterval = cpu_to_le16(RMNET_MAX_NOTIFY_SIZE),
+};
+
+static struct usb_endpoint_descriptor rmnet_ss_in_desc = {
+ .bLength = sizeof rmnet_ss_in_desc,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = __constant_cpu_to_le16(1024),
+};
+
+static struct usb_ss_ep_comp_descriptor rmnet_ss_in_comp_desc = {
+ .bLength = sizeof rmnet_ss_in_comp_desc,
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+
+ /* the following 2 values can be tweaked if necessary */
+ /* .bMaxBurst = 0, */
+ /* .bmAttributes = 0, */
+};
+
+static struct usb_endpoint_descriptor rmnet_ss_out_desc = {
+ .bLength = sizeof rmnet_ss_out_desc,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = __constant_cpu_to_le16(1024),
+};
+
+static struct usb_ss_ep_comp_descriptor rmnet_ss_out_comp_desc = {
+ .bLength = sizeof rmnet_ss_out_comp_desc,
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+
+ /* the following 2 values can be tweaked if necessary */
+ /* .bMaxBurst = 0, */
+ /* .bmAttributes = 0, */
+};
+
+static struct usb_descriptor_header *rmnet_ss_function[] = {
+ (struct usb_descriptor_header *) &rmnet_interface_desc,
+ (struct usb_descriptor_header *) &rmnet_ss_notify_desc,
+ (struct usb_descriptor_header *) &rmnet_ss_notify_comp_desc,
+ (struct usb_descriptor_header *) &rmnet_ss_in_desc,
+ (struct usb_descriptor_header *) &rmnet_ss_in_comp_desc,
+ (struct usb_descriptor_header *) &rmnet_ss_out_desc,
+ (struct usb_descriptor_header *) &rmnet_ss_out_comp_desc,
+ NULL,
+};
+
/* String descriptors */
static struct usb_string rmnet_string_defs[] = {
@@ -460,6 +525,8 @@
pr_debug("%s: portno:%d\n", __func__, dev->port_num);
+ if (gadget_is_superspeed(c->cdev->gadget))
+ usb_free_descriptors(f->ss_descriptors);
if (gadget_is_dualspeed(c->cdev->gadget))
usb_free_descriptors(f->hs_descriptors);
usb_free_descriptors(f->descriptors);
@@ -964,6 +1031,7 @@
dev->notify_req->complete = frmnet_notify_complete;
dev->notify_req->context = dev;
+ ret = -ENOMEM;
f->descriptors = usb_copy_descriptors(rmnet_fs_function);
if (!f->descriptors)
@@ -984,6 +1052,21 @@
goto fail;
}
+ if (gadget_is_superspeed(cdev->gadget)) {
+ rmnet_ss_in_desc.bEndpointAddress =
+ rmnet_fs_in_desc.bEndpointAddress;
+ rmnet_ss_out_desc.bEndpointAddress =
+ rmnet_fs_out_desc.bEndpointAddress;
+ rmnet_ss_notify_desc.bEndpointAddress =
+ rmnet_fs_notify_desc.bEndpointAddress;
+
+ /* copy descriptors, and track endpoint copies */
+ f->ss_descriptors = usb_copy_descriptors(rmnet_ss_function);
+
+ if (!f->ss_descriptors)
+ goto fail;
+ }
+
pr_info("%s: RmNet(%d) %s Speed, IN:%s OUT:%s\n",
__func__, dev->port_num,
gadget_is_dualspeed(cdev->gadget) ? "dual" : "full",
@@ -992,8 +1075,14 @@
return 0;
fail:
+ if (f->ss_descriptors)
+ usb_free_descriptors(f->ss_descriptors);
+ if (f->hs_descriptors)
+ usb_free_descriptors(f->hs_descriptors);
if (f->descriptors)
usb_free_descriptors(f->descriptors);
+ if (dev->notify_req)
+ frmnet_free_req(dev->notify, dev->notify_req);
ep_notify_alloc_fail:
dev->notify->driver_data = NULL;
dev->notify = NULL;
diff --git a/drivers/usb/gadget/f_rmnet_smd.c b/drivers/usb/gadget/f_rmnet_smd.c
index 5e2c6ed..e8c1f2a 100644
--- a/drivers/usb/gadget/f_rmnet_smd.c
+++ b/drivers/usb/gadget/f_rmnet_smd.c
@@ -874,9 +874,6 @@
struct rmnet_smd_dev *dev = container_of(f, struct rmnet_smd_dev,
function);
- if (!atomic_read(&dev->online))
- return;
-
atomic_set(&dev->online, 0);
usb_ep_fifo_flush(dev->epnotify);
diff --git a/drivers/usb/gadget/f_serial.c b/drivers/usb/gadget/f_serial.c
index 649fe14..43347b3 100644
--- a/drivers/usb/gadget/f_serial.c
+++ b/drivers/usb/gadget/f_serial.c
@@ -244,8 +244,37 @@
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
};
+#ifdef CONFIG_MODEM_SUPPORT
+static struct usb_endpoint_descriptor gser_ss_notify_desc = {
+ .bLength = sizeof gser_ss_notify_desc,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = __constant_cpu_to_le16(GS_NOTIFY_MAXPACKET),
+ .bInterval = GS_LOG2_NOTIFY_INTERVAL+4,
+};
+
+static struct usb_ss_ep_comp_descriptor gser_ss_notify_comp_desc = {
+ .bLength = sizeof gser_ss_notify_comp_desc,
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+
+ /* the following 2 values can be tweaked if necessary */
+ /* .bMaxBurst = 0, */
+ /* .bmAttributes = 0, */
+ .wBytesPerInterval = cpu_to_le16(GS_NOTIFY_MAXPACKET),
+};
+#endif
+
static struct usb_descriptor_header *gser_ss_function[] = {
(struct usb_descriptor_header *) &gser_interface_desc,
+#ifdef CONFIG_MODEM_SUPPORT
+ (struct usb_descriptor_header *) &gser_header_desc,
+ (struct usb_descriptor_header *) &gser_call_mgmt_descriptor,
+ (struct usb_descriptor_header *) &gser_descriptor,
+ (struct usb_descriptor_header *) &gser_union_desc,
+ (struct usb_descriptor_header *) &gser_ss_notify_desc,
+ (struct usb_descriptor_header *) &gser_ss_notify_comp_desc,
+#endif
(struct usb_descriptor_header *) &gser_ss_in_desc,
(struct usb_descriptor_header *) &gser_ss_bulk_comp_desc,
(struct usb_descriptor_header *) &gser_ss_out_desc,
@@ -304,7 +333,6 @@
ret = ghsic_ctrl_setup(no_hsic_sports, USB_GADGET_SERIAL);
if (ret < 0)
return ret;
- return 0;
}
if (no_hsuart_sports) {
port_idx = ghsuart_data_setup(no_hsuart_sports,
@@ -319,8 +347,6 @@
port_idx++;
}
}
-
- return 0;
}
return ret;
}
@@ -824,6 +850,10 @@
gser_fs_in_desc.bEndpointAddress;
gser_ss_out_desc.bEndpointAddress =
gser_fs_out_desc.bEndpointAddress;
+#ifdef CONFIG_MODEM_SUPPORT
+ gser_ss_notify_desc.bEndpointAddress =
+ gser_fs_notify_desc.bEndpointAddress;
+#endif
/* copy descriptors, and track endpoint copies */
f->ss_descriptors = usb_copy_descriptors(gser_ss_function);
@@ -839,6 +869,10 @@
return 0;
fail:
+ if (f->ss_descriptors)
+ usb_free_descriptors(f->ss_descriptors);
+ if (f->hs_descriptors)
+ usb_free_descriptors(f->hs_descriptors);
if (f->descriptors)
usb_free_descriptors(f->descriptors);
#ifdef CONFIG_MODEM_SUPPORT
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index c2d5f28..d53240f 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -18,6 +18,7 @@
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <linux/types.h>
+#include <mach/msm_hdmi_audio.h>
#define REG_DUMP 0
@@ -40,6 +41,17 @@
((d & 0xff) + ((d >> 8) & 0xff) + \
((d >> 16) & 0xff) + ((d >> 24) & 0xff))
+/* parameters for clock regeneration */
+struct hdmi_tx_audio_acr {
+ u32 n;
+ u32 cts;
+};
+
+struct hdmi_tx_audio_acr_arry {
+ u32 pclk;
+ struct hdmi_tx_audio_acr lut[HDMI_SAMPLE_RATE_MAX];
+};
+
static int hdmi_tx_sysfs_enable_hpd(struct hdmi_tx_ctrl *hdmi_ctrl, int on);
static irqreturn_t hdmi_tx_isr(int irq, void *data);
@@ -90,6 +102,27 @@
0x07, 0x07, 0x07, 0x07, 0x02, 0x02, 0x02} /*12*/
};
+/* Audio constants lookup table for hdmi_tx_audio_acr_setup */
+/* Valid Pixel-Clock rates: 25.2MHz, 27MHz, 27.03MHz, 74.25MHz, 148.5MHz */
+static const struct hdmi_tx_audio_acr_arry hdmi_tx_audio_acr_lut[] = {
+ /* 25.200MHz */
+ {25200, {{4096, 25200}, {6272, 28000}, {6144, 25200}, {12544, 28000},
+ {12288, 25200}, {25088, 28000}, {24576, 25200} } },
+ /* 27.000MHz */
+ {27000, {{4096, 27000}, {6272, 30000}, {6144, 27000}, {12544, 30000},
+ {12288, 27000}, {25088, 30000}, {24576, 27000} } },
+ /* 27.027MHz */
+ {27030, {{4096, 27027}, {6272, 30030}, {6144, 27027}, {12544, 30030},
+ {12288, 27027}, {25088, 30030}, {24576, 27027} } },
+ /* 74.250MHz */
+ {74250, {{4096, 74250}, {6272, 82500}, {6144, 74250}, {12544, 82500},
+ {12288, 74250}, {25088, 82500}, {24576, 74250} } },
+ /* 148.500MHz */
+ {148500, {{4096, 148500}, {6272, 165000}, {6144, 148500},
+ {12544, 165000}, {12288, 148500}, {25088, 165000},
+ {24576, 148500} } },
+};
+
const char *hdmi_tx_pm_name(enum hdmi_tx_power_module_type module)
{
switch (module) {
@@ -335,8 +368,8 @@
static inline u32 hdmi_tx_is_dvi_mode(struct hdmi_tx_ctrl *hdmi_ctrl)
{
- struct dss_io_data *io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
- return !(DSS_REG_R_ND(io, HDMI_CTRL) & BIT(1));
+ return hdmi_edid_get_sink_mode(
+ hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID]) ? 0 : 1;
} /* hdmi_tx_is_dvi_mode */
static int hdmi_tx_init_panel_info(uint32_t resolution,
@@ -1275,6 +1308,335 @@
DSS_REG_W_ND(io, HDMI_PHY_PD_CTRL0, 0x7F);
} /* hdmi_tx_powerdown_phy */
+static int hdmi_tx_audio_acr_setup(struct hdmi_tx_ctrl *hdmi_ctrl,
+ bool enabled, int num_of_channels)
+{
+ /* Read first before writing */
+ u32 acr_pck_ctrl_reg;
+ struct dss_io_data *io = NULL;
+
+ if (!hdmi_ctrl) {
+ DEV_ERR("%s: Invalid input\n", __func__);
+ return -EINVAL;
+ }
+
+ io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+ if (!io->base) {
+ DEV_ERR("%s: core io not inititalized\n", __func__);
+ return -EINVAL;
+ }
+
+ acr_pck_ctrl_reg = DSS_REG_R(io, HDMI_ACR_PKT_CTRL);
+
+ if (enabled) {
+ const struct hdmi_disp_mode_timing_type *timing =
+ hdmi_get_supported_mode(hdmi_ctrl->video_resolution);
+ const struct hdmi_tx_audio_acr_arry *audio_acr =
+ &hdmi_tx_audio_acr_lut[0];
+ const int lut_size = sizeof(hdmi_tx_audio_acr_lut)
+ / sizeof(*hdmi_tx_audio_acr_lut);
+ u32 i, n, cts, layout, multiplier, aud_pck_ctrl_2_reg;
+
+ if (timing == NULL) {
+ DEV_WARN("%s: video format %d not supported\n",
+ __func__, hdmi_ctrl->video_resolution);
+ return -EPERM;
+ }
+
+ for (i = 0; i < lut_size;
+ audio_acr = &hdmi_tx_audio_acr_lut[++i]) {
+ if (audio_acr->pclk == timing->pixel_freq)
+ break;
+ }
+ if (i >= lut_size) {
+ DEV_WARN("%s: pixel clk %d not supported\n", __func__,
+ timing->pixel_freq);
+ return -EPERM;
+ }
+
+ n = audio_acr->lut[hdmi_ctrl->audio_sample_rate].n;
+ cts = audio_acr->lut[hdmi_ctrl->audio_sample_rate].cts;
+ layout = (MSM_HDMI_AUDIO_CHANNEL_2 == num_of_channels) ? 0 : 1;
+
+ if (
+ (HDMI_SAMPLE_RATE_192KHZ == hdmi_ctrl->audio_sample_rate) ||
+ (HDMI_SAMPLE_RATE_176_4KHZ == hdmi_ctrl->audio_sample_rate)) {
+ multiplier = 4;
+ n >>= 2; /* divide N by 4 and use multiplier */
+ } else if (
+ (HDMI_SAMPLE_RATE_96KHZ == hdmi_ctrl->audio_sample_rate) ||
+ (HDMI_SAMPLE_RATE_88_2KHZ == hdmi_ctrl->audio_sample_rate)) {
+ multiplier = 2;
+ n >>= 1; /* divide N by 2 and use multiplier */
+ } else {
+ multiplier = 1;
+ }
+ DEV_DBG("%s: n=%u, cts=%u, layout=%u\n", __func__, n, cts,
+ layout);
+
+ /* AUDIO_PRIORITY | SOURCE */
+ acr_pck_ctrl_reg |= 0x80000100;
+ /* N_MULTIPLE(multiplier) */
+ acr_pck_ctrl_reg |= (multiplier & 7) << 16;
+
+ if ((HDMI_SAMPLE_RATE_48KHZ == hdmi_ctrl->audio_sample_rate) ||
+ (HDMI_SAMPLE_RATE_96KHZ == hdmi_ctrl->audio_sample_rate) ||
+ (HDMI_SAMPLE_RATE_192KHZ == hdmi_ctrl->audio_sample_rate)) {
+ /* SELECT(3) */
+ acr_pck_ctrl_reg |= 3 << 4;
+ /* CTS_48 */
+ cts <<= 12;
+
+ /* CTS: need to determine how many fractional bits */
+ DSS_REG_W(io, HDMI_ACR_48_0, cts);
+ /* N */
+ DSS_REG_W(io, HDMI_ACR_48_1, n);
+ } else if (
+ (HDMI_SAMPLE_RATE_44_1KHZ == hdmi_ctrl->audio_sample_rate) ||
+ (HDMI_SAMPLE_RATE_88_2KHZ == hdmi_ctrl->audio_sample_rate) ||
+ (HDMI_SAMPLE_RATE_176_4KHZ == hdmi_ctrl->audio_sample_rate)) {
+ /* SELECT(2) */
+ acr_pck_ctrl_reg |= 2 << 4;
+ /* CTS_44 */
+ cts <<= 12;
+
+ /* CTS: need to determine how many fractional bits */
+ DSS_REG_W(io, HDMI_ACR_44_0, cts);
+ /* N */
+ DSS_REG_W(io, HDMI_ACR_44_1, n);
+ } else { /* default to 32k */
+ /* SELECT(1) */
+ acr_pck_ctrl_reg |= 1 << 4;
+ /* CTS_32 */
+ cts <<= 12;
+
+ /* CTS: need to determine how many fractional bits */
+ DSS_REG_W(io, HDMI_ACR_32_0, cts);
+ /* N */
+ DSS_REG_W(io, HDMI_ACR_32_1, n);
+ }
+ /* Payload layout depends on number of audio channels */
+ /* LAYOUT_SEL(layout) */
+ aud_pck_ctrl_2_reg = 1 | (layout << 1);
+ /* override | layout */
+ DSS_REG_W(io, HDMI_AUDIO_PKT_CTRL2, aud_pck_ctrl_2_reg);
+
+ /* SEND | CONT */
+ acr_pck_ctrl_reg |= 0x00000003;
+ } else {
+ /* ~(SEND | CONT) */
+ acr_pck_ctrl_reg &= ~0x00000003;
+ }
+ DSS_REG_W(io, HDMI_ACR_PKT_CTRL, acr_pck_ctrl_reg);
+
+ return 0;
+} /* hdmi_tx_audio_acr_setup */
+
+static int hdmi_tx_audio_info_setup(void *priv_d, bool enabled,
+ u32 num_of_channels, u32 channel_allocation, u32 level_shift,
+ bool down_mix)
+{
+ struct hdmi_tx_ctrl *hdmi_ctrl = (struct hdmi_tx_ctrl *)priv_d;
+ struct dss_io_data *io = NULL;
+
+ u32 channel_count = 1; /* Def to 2 channels -> Table 17 in CEA-D */
+ u32 check_sum, audio_info_0_reg, audio_info_1_reg;
+ u32 audio_info_ctrl_reg;
+ u32 aud_pck_ctrl_2_reg;
+ u32 layout;
+
+ if (!hdmi_ctrl) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return -EINVAL;
+ }
+
+ io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+ if (!io->base) {
+ DEV_ERR("%s: core io not inititalized\n", __func__);
+ return -EINVAL;
+ }
+
+ layout = (MSM_HDMI_AUDIO_CHANNEL_2 == num_of_channels) ? 0 : 1;
+ aud_pck_ctrl_2_reg = 1 | (layout << 1);
+ DSS_REG_W(io, HDMI_AUDIO_PKT_CTRL2, aud_pck_ctrl_2_reg);
+
+ /*
+ * Please see table 20 Audio InfoFrame in HDMI spec
+ * FL = front left
+ * FC = front Center
+ * FR = front right
+ * FLC = front left center
+ * FRC = front right center
+ * RL = rear left
+ * RC = rear center
+ * RR = rear right
+ * RLC = rear left center
+ * RRC = rear right center
+ * LFE = low frequency effect
+ */
+
+ /* Read first then write because it is bundled with other controls */
+ audio_info_ctrl_reg = DSS_REG_R(io, HDMI_INFOFRAME_CTRL0);
+
+ if (enabled) {
+ switch (num_of_channels) {
+ case MSM_HDMI_AUDIO_CHANNEL_2:
+ channel_allocation = 0; /* Default to FR, FL */
+ break;
+ case MSM_HDMI_AUDIO_CHANNEL_4:
+ channel_count = 3;
+ /* FC, LFE, FR, FL */
+ channel_allocation = 0x3;
+ break;
+ case MSM_HDMI_AUDIO_CHANNEL_6:
+ channel_count = 5;
+ /* RR, RL, FC, LFE, FR, FL */
+ channel_allocation = 0xB;
+ break;
+ case MSM_HDMI_AUDIO_CHANNEL_8:
+ channel_count = 7;
+ /* FRC, FLC, RR, RL, FC, LFE, FR, FL */
+ channel_allocation = 0x1f;
+ break;
+ default:
+ DEV_ERR("%s: Unsupported num_of_channels = %u\n",
+ __func__, num_of_channels);
+ return -EINVAL;
+ }
+
+ /* Program the Channel-Speaker allocation */
+ audio_info_1_reg = 0;
+ /* CA(channel_allocation) */
+ audio_info_1_reg |= channel_allocation & 0xff;
+ /* Program the Level shifter */
+ audio_info_1_reg |= (level_shift << 11) & 0x00007800;
+ /* Program the Down-mix Inhibit Flag */
+ audio_info_1_reg |= (down_mix << 15) & 0x00008000;
+
+ DSS_REG_W(io, HDMI_AUDIO_INFO1, audio_info_1_reg);
+
+ /*
+ * Calculate CheckSum: Sum of all the bytes in the
+ * Audio Info Packet (See table 8.4 in HDMI spec)
+ */
+ check_sum = 0;
+ /* HDMI_AUDIO_INFO_FRAME_PACKET_HEADER_TYPE[0x84] */
+ check_sum += 0x84;
+ /* HDMI_AUDIO_INFO_FRAME_PACKET_HEADER_VERSION[0x01] */
+ check_sum += 1;
+ /* HDMI_AUDIO_INFO_FRAME_PACKET_LENGTH[0x0A] */
+ check_sum += 0x0A;
+ check_sum += channel_count;
+ check_sum += channel_allocation;
+ /* See Table 8.5 in HDMI spec */
+ check_sum += (level_shift & 0xF) << 3 | (down_mix & 0x1) << 7;
+ check_sum &= 0xFF;
+ check_sum = (u8) (256 - check_sum);
+
+ audio_info_0_reg = 0;
+ /* CHECKSUM(check_sum) */
+ audio_info_0_reg |= check_sum & 0xff;
+ /* CC(channel_count) */
+ audio_info_0_reg |= (channel_count << 8) & 0x00000700;
+
+ DSS_REG_W(io, HDMI_AUDIO_INFO0, audio_info_0_reg);
+
+ /*
+ * Set these flags
+ * AUDIO_INFO_UPDATE |
+ * AUDIO_INFO_SOURCE |
+ * AUDIO_INFO_CONT |
+ * AUDIO_INFO_SEND
+ */
+ audio_info_ctrl_reg |= 0x000000F0;
+ } else {
+ /*Clear these flags
+ * ~(AUDIO_INFO_UPDATE |
+ * AUDIO_INFO_SOURCE |
+ * AUDIO_INFO_CONT |
+ * AUDIO_INFO_SEND)
+ */
+ audio_info_ctrl_reg &= ~0x000000F0;
+ }
+ DSS_REG_W(io, HDMI_INFOFRAME_CTRL0, audio_info_ctrl_reg);
+
+ dss_reg_dump(io->base, io->len, "HDMI-AUDIO-ON: ", REG_DUMP);
+
+ return 0;
+} /* hdmi_tx_audio_info_setup */
+
+static int hdmi_tx_audio_setup(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+ int rc = 0;
+ const int channels = MSM_HDMI_AUDIO_CHANNEL_2;
+ struct dss_io_data *io = NULL;
+
+ if (!hdmi_ctrl) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return -EINVAL;
+ }
+
+ io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+ if (!io->base) {
+ DEV_ERR("%s: core io not inititalized\n", __func__);
+ return -EINVAL;
+ }
+
+ rc = hdmi_tx_audio_acr_setup(hdmi_ctrl, true, channels);
+ if (rc) {
+ DEV_ERR("%s: hdmi_tx_audio_acr_setup failed. rc=%d\n",
+ __func__, rc);
+ return rc;
+ }
+
+ rc = hdmi_tx_audio_info_setup(hdmi_ctrl, true, channels, 0, 0, false);
+ if (rc) {
+ DEV_ERR("%s: hdmi_tx_audio_info_setup failed. rc=%d\n",
+ __func__, rc);
+ return rc;
+ }
+
+ DEV_INFO("HDMI Audio: Enabled\n");
+
+ return 0;
+} /* hdmi_tx_audio_setup */
+
+static void hdmi_tx_audio_off(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+ int i;
+ u32 audio_pkt_ctrl, audio_cfg;
+ struct dss_io_data *io = NULL;
+
+ if (!hdmi_ctrl) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return;
+ }
+
+ io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+ if (!io->base) {
+ DEV_ERR("%s: core io not inititalized\n", __func__);
+ return;
+ }
+
+ /* Number of wait iterations */
+ i = 10;
+ do {
+ audio_pkt_ctrl = DSS_REG_R_ND(io, HDMI_AUDIO_PKT_CTRL);
+ audio_cfg = DSS_REG_R_ND(io, HDMI_AUDIO_CFG);
+ DEV_DBG("%s: i=%d, AUDIO PACKET=%08x, AUDIO CFG=%08x",
+ __func__, i, audio_pkt_ctrl, audio_cfg);
+ msleep(20);
+ } while (((audio_pkt_ctrl & BIT(0)) || (audio_cfg & BIT(0))) && i--);
+
+ if (hdmi_tx_audio_info_setup(hdmi_ctrl, false, 0, 0, 0, false))
+ DEV_ERR("%s: hdmi_tx_audio_info_setup failed.\n", __func__);
+
+ if (hdmi_tx_audio_acr_setup(hdmi_ctrl, false, 0))
+ DEV_ERR("%s: hdmi_tx_audio_acr_setup failed.\n", __func__);
+
+ DEV_INFO("HDMI Audio: Disabled\n");
+} /* hdmi_tx_audio_off */
+
static int hdmi_tx_start(struct hdmi_tx_ctrl *hdmi_ctrl)
{
int rc = 0;
@@ -1290,8 +1652,6 @@
return -EINVAL;
}
- /* todo: Audio */
-
hdmi_tx_set_mode(hdmi_ctrl, false);
hdmi_tx_init_phy(hdmi_ctrl);
DSS_REG_W(io, HDMI_USEC_REFTIMER, 0x0001001B);
@@ -1299,7 +1659,21 @@
hdmi_tx_set_mode(hdmi_ctrl, true);
hdmi_tx_video_setup(hdmi_ctrl, hdmi_ctrl->video_resolution);
- /* todo: Audio */
+
+ if (!hdmi_tx_is_dvi_mode(hdmi_ctrl)) {
+ rc = hdmi_tx_audio_setup(hdmi_ctrl);
+ if (rc) {
+ DEV_ERR("%s: hdmi_msm_audio_setup failed. rc=%d\n",
+ __func__, rc);
+ hdmi_tx_set_mode(hdmi_ctrl, false);
+ return rc;
+ }
+
+ switch_set_state(&hdmi_ctrl->audio_sdev, 1);
+ DEV_INFO("%s: hdmi_audio state switch to %d\n", __func__,
+ hdmi_ctrl->audio_sdev.state);
+ }
+
hdmi_tx_set_avi_infoframe(hdmi_ctrl);
/* todo: CONFIG_FB_MSM_HDMI_3D */
hdmi_tx_set_spd_infoframe(hdmi_ctrl);
@@ -1324,8 +1698,16 @@
return -EINVAL;
}
- DEV_INFO("%s: power: OFF (audio off, Reset Core)\n", __func__);
- /* todo: Audio */
+ DEV_INFO("%s: HDMI Core: OFF\n", __func__);
+
+ if (!hdmi_tx_is_dvi_mode(hdmi_ctrl)) {
+ switch_set_state(&hdmi_ctrl->audio_sdev, 0);
+ DEV_INFO("%s: hdmi_audio state switch to %d\n", __func__,
+ hdmi_ctrl->audio_sdev.state);
+
+ hdmi_tx_audio_off(hdmi_ctrl);
+ }
+
hdmi_tx_powerdown_phy(hdmi_ctrl);
hdmi_ctrl->panel_power_on = false;
hdmi_tx_core_off(hdmi_ctrl);
@@ -1546,6 +1928,7 @@
if (hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID])
hdmi_edid_deinit(hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID]);
+ switch_dev_unregister(&hdmi_ctrl->audio_sdev);
switch_dev_unregister(&hdmi_ctrl->sdev);
del_timer_sync(&hdmi_ctrl->hpd_state_timer);
if (hdmi_ctrl->workq)
@@ -1581,6 +1964,7 @@
hdmi_ctrl->workq = create_workqueue("hdmi_tx_workq");
if (!hdmi_ctrl->workq) {
DEV_ERR("%s: hdmi_tx_workq creation failed.\n", __func__);
+ rc = -EPERM;
goto fail_create_workq;
}
@@ -1594,14 +1978,27 @@
hdmi_ctrl->hpd_state_timer.data = (u32)hdmi_ctrl;
hdmi_ctrl->hpd_state_timer.expires = 0xffffffffL;
+ hdmi_ctrl->audio_sample_rate = HDMI_SAMPLE_RATE_48KHZ;
+
hdmi_ctrl->sdev.name = "hdmi";
if (switch_dev_register(&hdmi_ctrl->sdev) < 0) {
DEV_ERR("%s: Hdmi switch registration failed\n", __func__);
+ rc = -ENODEV;
goto fail_switch_dev;
}
+ hdmi_ctrl->audio_sdev.name = "hdmi_audio";
+ if (switch_dev_register(&hdmi_ctrl->audio_sdev) < 0) {
+ DEV_ERR("%s: hdmi_audio switch registration failed\n",
+ __func__);
+ rc = -ENODEV;
+ goto fail_audio_switch_dev;
+ }
+
return 0;
+fail_audio_switch_dev:
+ switch_dev_unregister(&hdmi_ctrl->sdev);
fail_switch_dev:
del_timer_sync(&hdmi_ctrl->hpd_state_timer);
fail_create_workq:
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.h b/drivers/video/msm/mdss/mdss_hdmi_tx.h
index 94e0fda..437f681 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.h
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.h
@@ -41,9 +41,12 @@
struct hdmi_tx_platform_data pdata;
struct mdss_panel_data panel_data;
+ int audio_sample_rate;
+
struct mutex mutex;
struct kobject *kobj;
struct switch_dev sdev;
+ struct switch_dev audio_sdev;
struct workqueue_struct *workq;
uint32_t video_resolution;
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 1994b1b..527b02f 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -3279,7 +3279,9 @@
ret = wait_for_completion_interruptible_timeout(
&mfd->msmfb_no_update_notify, 4*HZ);
}
- return (ret > 0) ? 0 : -1;
+ if (ret == 0)
+ ret = -ETIMEDOUT;
+ return (ret > 0) ? 0 : ret;
}
static int msmfb_handle_pp_ioctl(struct msm_fb_data_type *mfd,
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
index 8cfa95b..2c41ab4 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
@@ -493,6 +493,7 @@
ddl_get_state_string(ddl->client_state));
ddl_calc_core_proc_time(__func__, DEC_OP_TIME, ddl);
ddl_reset_core_time_variables(DEC_OP_TIME);
+ ddl_vidc_decode_reset_avg_time(ddl);
ddl->client_state = DDL_CLIENT_WAIT_FOR_FRAME;
ddl_vidc_decode_frame_run(ddl);
ret_status = false;
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
index 31f60e5..4b5fbf5 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
@@ -13,7 +13,7 @@
#include <linux/memory_alloc.h>
#include <linux/delay.h>
#include <mach/msm_subsystem_map.h>
-#include <mach/peripheral-loader.h>
+#include <mach/subsystem_restart.h>
#include "vcd_ddl_utils.h"
#include "vcd_ddl.h"
#include "vcd_res_tracker_api.h"
@@ -70,7 +70,7 @@
alloc_size = (alloc_size+4095) & ~4095;
addr->alloc_handle = ion_alloc(
ddl_context->video_ion_client, alloc_size, SZ_4K,
- res_trk_get_mem_type(), 0);
+ res_trk_get_mem_type(), res_trk_get_ion_flags());
if (IS_ERR_OR_NULL(addr->alloc_handle)) {
DDL_MSG_ERROR("%s() :DDL ION alloc failed\n",
__func__);
@@ -361,12 +361,12 @@
pr_err("Failed to enable iommu clocks\n");
return false;
}
- dram_base->pil_cookie = pil_get("vidc");
+ dram_base->pil_cookie = subsystem_get("vidc");
if (res_trk_disable_iommu_clocks())
pr_err("Failed to disable iommu clocks\n");
if (IS_ERR_OR_NULL(dram_base->pil_cookie)) {
res_trk_disable_footswitch();
- pr_err("pil_get failed\n");
+ pr_err("subsystem_get failed\n");
return false;
}
} else {
@@ -398,7 +398,7 @@
pr_err("Failed to enable iommu clocks\n");
return;
}
- pil_put(cookie);
+ subsystem_put(cookie);
if (res_trk_disable_iommu_clocks())
pr_err("Failed to disable iommu clocks\n");
if (res_trk_disable_footswitch())
diff --git a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
index 0bc2228..d9cadef 100644
--- a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
+++ b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
@@ -209,7 +209,8 @@
addr->alloc_handle = ion_alloc(
ddl_context->video_ion_client,
alloc_size, SZ_4K,
- res_trk_get_mem_type(), 0);
+ res_trk_get_mem_type(),
+ res_trk_get_ion_flags());
if (IS_ERR_OR_NULL(addr->alloc_handle)) {
DDL_MSG_ERROR("%s() :DDL ION alloc failed\n",
__func__);
@@ -452,6 +453,10 @@
static struct ion_client *res_trk_create_ion_client(void){
struct ion_client *video_client;
video_client = msm_ion_client_create(-1, "video_client");
+ if (IS_ERR_OR_NULL(video_client)) {
+ VCDRES_MSG_ERROR("%s: Unable to create ION client\n", __func__);
+ video_client = NULL;
+ }
return video_client;
}
@@ -826,17 +831,31 @@
if (resource_context.vidc_platform_data->enable_ion) {
if (res_trk_check_for_sec_session()) {
mem_type = ION_HEAP(mem_type);
- if (resource_context.res_mem_type != DDL_FW_MEM)
- mem_type |= ION_SECURE;
- else if (res_trk_is_cp_enabled())
- mem_type |= ION_SECURE;
} else
mem_type = (ION_HEAP(mem_type) |
ION_HEAP(ION_IOMMU_HEAP_ID));
}
+
return mem_type;
}
+unsigned int res_trk_get_ion_flags(void)
+{
+ unsigned int flags = 0;
+ if (resource_context.res_mem_type == DDL_FW_MEM)
+ return flags;
+
+ if (resource_context.vidc_platform_data->enable_ion) {
+ if (res_trk_check_for_sec_session()) {
+ if (resource_context.res_mem_type != DDL_FW_MEM)
+ flags |= ION_SECURE;
+ else if (res_trk_is_cp_enabled())
+ flags |= ION_SECURE;
+ }
+ }
+ return flags;
+}
+
u32 res_trk_is_cp_enabled(void)
{
if (resource_context.vidc_platform_data->cp_enabled)
diff --git a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker_api.h b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker_api.h
index 2ae2512..ee876f4 100644
--- a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker_api.h
+++ b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker_api.h
@@ -30,6 +30,7 @@
u32 res_trk_get_core_type(void);
u32 res_trk_get_firmware_addr(struct ddl_buf_addr *firm_addr);
int res_trk_get_mem_type(void);
+unsigned int res_trk_get_ion_flags(void);
u32 res_trk_get_enable_ion(void);
u32 res_trk_is_cp_enabled(void);
u32 res_trk_get_disable_fullhd(void);
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c
index 3b40640..9fb8162 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c
@@ -125,9 +125,8 @@
alloc_size,
SZ_4K,
buff_addr->mem_type, 0);
- if (!buff_addr->alloc_handle) {
- ERR("\n%s(): DDL ION alloc failed\n",
- __func__);
+ if (IS_ERR_OR_NULL(buff_addr->alloc_handle)) {
+ ERR("\n%s(): DDL ION alloc failed\n", __func__);
goto bailout;
}
ret = ion_phys(ddl_context->video_ion_client,
diff --git a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c
index aee9dfe..c83faa6 100644
--- a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c
+++ b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c
@@ -681,6 +681,10 @@
struct ion_client *video_client;
VCDRES_MSG_LOW("%s", __func__);
video_client = msm_ion_client_create(-1, "video_client");
+ if (IS_ERR_OR_NULL(video_client)) {
+ VCDRES_MSG_ERROR("%s: Unable to create ION client\n", __func__);
+ video_client = NULL;
+ }
return video_client;
}
@@ -760,6 +764,11 @@
return 0;
}
+u32 res_trk_get_ion_flags(void)
+{
+ return 0;
+}
+
int res_trk_check_for_sec_session()
{
return 0;
diff --git a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker_api.h b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker_api.h
index 75fdb3e..a20d9f2 100644
--- a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker_api.h
+++ b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker_api.h
@@ -29,6 +29,7 @@
u32 res_trk_get_core_type(void);
u32 res_trk_get_mem_type(void);
u32 res_trk_get_disable_fullhd(void);
+u32 res_trk_get_ion_flags(void);
u32 res_trk_get_enable_ion(void);
u32 res_trk_is_cp_enabled(void);
struct ion_client *res_trk_get_ion_client(void);
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_sub.c b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
index 5fdee02..a9709fb 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_sub.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
@@ -92,8 +92,8 @@
} else {
map_buffer->alloc_handle = ion_alloc(
cctxt->vcd_ion_client, sz, SZ_4K,
- memtype, 0);
- if (!map_buffer->alloc_handle) {
+ memtype, res_trk_get_ion_flags());
+ if (IS_ERR_OR_NULL(map_buffer->alloc_handle)) {
pr_err("%s() ION alloc failed", __func__);
goto bailout;
}
diff --git a/include/linux/coresight-stm.h b/include/linux/coresight-stm.h
index bb3ebca..427fae0 100644
--- a/include/linux/coresight-stm.h
+++ b/include/linux/coresight-stm.h
@@ -1,5 +1,5 @@
-#ifndef __MACH_STM_H
-#define __MACH_STM_H
+#ifndef _LINUX_CORESIGHT_STM_H
+#define _LINUX_CORESIGHT_STM_H
enum {
OST_ENTITY_NONE = 0x00,
@@ -7,7 +7,7 @@
OST_ENTITY_TRACE_PRINTK = 0x02,
OST_ENTITY_TRACE_MARKER = 0x04,
OST_ENTITY_DEV_NODE = 0x08,
- OST_ENTITY_ALL = 0x1F,
+ OST_ENTITY_MAX = 0xFF,
};
enum {
diff --git a/include/linux/i2c/atmel_mxt_ts.h b/include/linux/i2c/atmel_mxt_ts.h
index 348a231..fe23993 100644
--- a/include/linux/i2c/atmel_mxt_ts.h
+++ b/include/linux/i2c/atmel_mxt_ts.h
@@ -74,6 +74,7 @@
u32 irq_gpio_flags;
int *key_codes;
bool need_calibration;
+ bool no_force_update;
u8(*read_chg) (void);
int (*init_hw) (bool);
diff --git a/include/linux/ion.h b/include/linux/ion.h
index 85e5002..73fb995 100644
--- a/include/linux/ion.h
+++ b/include/linux/ion.h
@@ -418,7 +418,7 @@
}
static inline void *ion_map_kernel(struct ion_client *client,
- struct ion_handle *handle, unsigned long flags)
+ struct ion_handle *handle)
{
return ERR_PTR(-ENODEV);
}
@@ -453,6 +453,12 @@
return -ENODEV;
}
+static inline int ion_handle_get_size(struct ion_client *client,
+ struct ion_handle *handle, unsigned long *size)
+{
+ return -ENODEV;
+}
+
static inline void ion_unmap_iommu(struct ion_client *client,
struct ion_handle *handle, int domain_num,
int partition_num)
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index f8a3a10..08f74e6 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -61,6 +61,14 @@
MIGRATE_TYPES
};
+/*
+ * Returns a list which contains the migrate types on to which
+ * an allocation falls back when the free list for the migrate
+ * type mtype is depleted.
+ * The end of the list is delimited by the type MIGRATE_RESERVE.
+ */
+extern int *get_migratetype_fallbacks(int mtype);
+
#ifdef CONFIG_CMA
# define is_migrate_cma(migratetype) unlikely((migratetype) == MIGRATE_CMA)
# define cma_wmark_pages(zone) zone->min_cma_pages
diff --git a/include/linux/qpnp/pin.h b/include/linux/qpnp/pin.h
index fa9c30f..fff29ab 100644
--- a/include/linux/qpnp/pin.h
+++ b/include/linux/qpnp/pin.h
@@ -131,7 +131,7 @@
* the input is interpreted as a logical 1.
* @out_strength: the amount of current supplied for an output gpio,
* should be of the type QPNP_PIN_STRENGTH_*.
- * @select: select alternate function for the pin. Certain pins
+ * @src_sel: select alternate function for the pin. Certain pins
* can be paired (shorted) with each other. Some pins
* can act as alternate functions. In the context of
* gpio, this acts as a source select. For mpps,
@@ -159,7 +159,7 @@
int pull;
int vin_sel;
int out_strength;
- int select;
+ int src_sel;
int master_en;
int aout_ref;
int ain_route;
diff --git a/include/media/Kbuild b/include/media/Kbuild
index 4b6e6a9..70f6334 100644
--- a/include/media/Kbuild
+++ b/include/media/Kbuild
@@ -7,3 +7,4 @@
header-y += msm_gestures.h
header-y += msm_mercury.h
header-y += msm_jpeg.h
+header-y += msm_media_info.h
diff --git a/include/media/msm_media_info.h b/include/media/msm_media_info.h
new file mode 100644
index 0000000..3098bfe
--- /dev/null
+++ b/include/media/msm_media_info.h
@@ -0,0 +1,113 @@
+#ifndef __MEDIA_INFO_H__
+#define __MEDIA_INFO_H__
+
+#ifndef ALIGN
+#define ALIGN(__sz, __align) (((__sz) + (__align-1)) & (~(__align-1)))
+#endif
+
+enum color_fmts {
+ COLOR_FMT_NV12,
+};
+
+static inline unsigned int VENUS_Y_STRIDE(int color_fmt, int width)
+{
+ unsigned int alignment, stride = 0;
+ if (!width)
+ goto invalid_input;
+
+ switch (color_fmt) {
+ case COLOR_FMT_NV12:
+ alignment = 32;
+ stride = ALIGN(width, alignment);
+ break;
+ default:
+ break;
+ }
+invalid_input:
+ return stride;
+}
+
+static inline unsigned int VENUS_UV_STRIDE(int color_fmt, int width)
+{
+ unsigned int alignment, stride = 0;
+ if (!width)
+ goto invalid_input;
+
+ switch (color_fmt) {
+ case COLOR_FMT_NV12:
+ alignment = 32;
+ stride = ALIGN(((width + 1) >> 1), alignment) << 1;
+ break;
+ default:
+ break;
+ }
+invalid_input:
+ return stride;
+}
+
+static inline unsigned int VENUS_Y_SCANLINES(int color_fmt, int height)
+{
+ unsigned int alignment, sclines = 0;
+ if (!height)
+ goto invalid_input;
+
+ switch (color_fmt) {
+ case COLOR_FMT_NV12:
+ alignment = 32;
+ sclines = ALIGN(height, alignment);
+ break;
+ default:
+ break;
+ }
+invalid_input:
+ return sclines;
+}
+
+static inline unsigned int VENUS_UV_SCANLINES(int color_fmt, int height)
+{
+ unsigned int alignment, sclines = 0;
+ if (!height)
+ goto invalid_input;
+
+ switch (color_fmt) {
+ case COLOR_FMT_NV12:
+ alignment = 32;
+ sclines = ALIGN(((height + 1) >> 1), alignment);
+ break;
+ default:
+ break;
+ }
+invalid_input:
+ return sclines;
+}
+
+static inline unsigned int VENUS_BUFFER_SIZE(
+ int color_fmt, int width, int height)
+{
+ unsigned int uv_alignment;
+ unsigned int size = 0;
+ unsigned int y_plane, uv_plane, y_stride,
+ uv_stride, y_sclines, uv_sclines;
+ if (!width || !height)
+ goto invalid_input;
+
+ y_stride = VENUS_Y_STRIDE(color_fmt, width);
+ uv_stride = VENUS_UV_STRIDE(color_fmt, width);
+ y_sclines = VENUS_Y_SCANLINES(color_fmt, height);
+ uv_sclines = VENUS_UV_SCANLINES(color_fmt, height);
+ switch (color_fmt) {
+ case COLOR_FMT_NV12:
+ uv_alignment = 32;
+ y_plane = y_stride * y_sclines;
+ uv_plane = uv_stride * uv_sclines + uv_alignment;
+ size = y_plane + uv_plane;
+ size = ALIGN(size, 4096);
+ break;
+ default:
+ break;
+ }
+invalid_input:
+ return size;
+}
+
+#endif
diff --git a/include/media/radio-iris.h b/include/media/radio-iris.h
index db69518..0efeff4 100644
--- a/include/media/radio-iris.h
+++ b/include/media/radio-iris.h
@@ -363,6 +363,53 @@
#define HCI_REQ_CANCELED 2
#define HCI_REQ_STATUS 3
+#define MAX_RAW_RDS_GRPS 21
+
+#define RDSGRP_DATA_OFFSET 0x1
+
+/*RT PLUS*/
+#define DUMMY_CLASS 0
+#define RT_PLUS_LEN_1_TAG 3
+#define RT_ERT_FLAG_BIT 5
+
+/*TAG1*/
+#define TAG1_MSB_OFFSET 3
+#define TAG1_MSB_MASK 7
+#define TAG1_LSB_OFFSET 5
+#define TAG1_POS_MSB_MASK 31
+#define TAG1_POS_MSB_OFFSET 1
+#define TAG1_POS_LSB_OFFSET 7
+#define TAG1_LEN_OFFSET 1
+#define TAG1_LEN_MASK 63
+
+/*TAG2*/
+#define TAG2_MSB_OFFSET 5
+#define TAG2_MSB_MASK 1
+#define TAG2_LSB_OFFSET 3
+#define TAG2_POS_MSB_MASK 7
+#define TAG2_POS_MSB_OFFSET 3
+#define TAG2_POS_LSB_OFFSET 5
+#define TAG2_LEN_MASK 31
+
+#define AGT_MASK 31
+/*Extract 5 left most bits of lsb of 2nd block*/
+#define AGT(x) (x & AGT_MASK)
+/*16 bits of 4th block*/
+#define AID(lsb, msb) ((msb << 8) | (lsb))
+/*Extract 5 right most bits of msb of 2nd block*/
+#define GTC(blk2msb) (blk2msb >> 3)
+
+#define GRP_3A 0x6
+#define RT_PLUS_AID 0x4bd7
+
+/*ERT*/
+#define ERT_AID 0x6552
+#define CARRIAGE_RETURN 0x000D
+#define MAX_ERT_SEGMENT 31
+#define ERT_FORMAT_DIR_BIT 1
+
+#define EXTRACT_BIT(data, bit_pos) ((data & (1 << bit_pos)) >> bit_pos)
+
struct hci_ev_tune_status {
__u8 sub_event;
__le32 station_freq;
@@ -375,9 +422,19 @@
__u8 intf_det_th;
} __packed;
+struct rds_blk_data {
+ __u8 rdsMsb;
+ __u8 rdsLsb;
+ __u8 blockStatus;
+} __packed;
+
+struct rds_grp_data {
+ struct rds_blk_data rdsBlk[4];
+} __packed;
+
struct hci_ev_rds_rx_data {
__u8 num_rds_grps;
- __u8 rds_grp_data[12];
+ struct rds_grp_data rds_grp_data[MAX_RAW_RDS_GRPS];
} __packed;
struct hci_ev_prg_service {
@@ -628,7 +685,10 @@
IRIS_EVT_NEW_AF_LIST,
IRIS_EVT_TXRDSDAT,
IRIS_EVT_TXRDSDONE,
- IRIS_EVT_RADIO_DISABLED
+ IRIS_EVT_RADIO_DISABLED,
+ IRIS_EVT_NEW_ODA,
+ IRIS_EVT_NEW_RT_PLUS,
+ IRIS_EVT_NEW_ERT,
};
enum emphasis_type {
FM_RX_EMP75 = 0x0,
@@ -660,7 +720,7 @@
IRIS_REGION_OTHER
};
-#define STD_BUF_SIZE (128)
+#define STD_BUF_SIZE (256)
enum iris_buf_t {
IRIS_BUF_SRCH_LIST,
@@ -674,7 +734,9 @@
IRIS_BUF_RDS_CNTRS,
IRIS_BUF_RD_DEFAULT,
IRIS_BUF_CAL_DATA,
- IRIS_BUF_MAX
+ IRIS_BUF_RT_PLUS,
+ IRIS_BUF_ERT,
+ IRIS_BUF_MAX,
};
enum iris_xfr_t {
diff --git a/include/media/tavarua.h b/include/media/tavarua.h
index 1cccb2b..881b851 100644
--- a/include/media/tavarua.h
+++ b/include/media/tavarua.h
@@ -52,7 +52,7 @@
#define SRCH_MASK (1 << SRCH200KHZ_OFFSET)
/* Standard buffer size */
-#define STD_BUF_SIZE (128)
+#define STD_BUF_SIZE (256)
/* Search direction */
#define SRCH_DIR_UP (0)
#define SRCH_DIR_DOWN (1)
diff --git a/include/media/vcap_fmt.h b/include/media/vcap_fmt.h
index 3b1bd7c2..13b3f05 100644
--- a/include/media/vcap_fmt.h
+++ b/include/media/vcap_fmt.h
@@ -24,12 +24,13 @@
#define VCAP_VC_NPL_OFLOW_ERR_EVENT 4
#define VCAP_VC_LBUF_OFLOW_ERR_EVENT 5
#define VCAP_VC_BUF_OVERWRITE_EVENT 6
-#define VCAP_VP_REG_R_ERR_EVENT 7
-#define VCAP_VP_REG_W_ERR_EVENT 8
-#define VCAP_VP_IN_HEIGHT_ERR_EVENT 9
-#define VCAP_VP_IN_WIDTH_ERR_EVENT 10
-#define VCAP_VC_UNEXPECT_BUF_DONE 11
-#define VCAP_MAX_NOTIFY_EVENT 12
+#define VCAP_VC_VSYNC_SEQ_ERR 7
+#define VCAP_VP_REG_R_ERR_EVENT 8
+#define VCAP_VP_REG_W_ERR_EVENT 9
+#define VCAP_VP_IN_HEIGHT_ERR_EVENT 10
+#define VCAP_VP_IN_WIDTH_ERR_EVENT 11
+#define VCAP_VC_UNEXPECT_BUF_DONE 12
+#define VCAP_MAX_NOTIFY_EVENT 13
enum hal_vcap_mode {
HAL_VCAP_MODE_PRO = 0,
diff --git a/include/media/vcap_v4l2.h b/include/media/vcap_v4l2.h
index 3db949c..55d67bf 100644
--- a/include/media/vcap_v4l2.h
+++ b/include/media/vcap_v4l2.h
@@ -109,7 +109,7 @@
uint8_t tot_buf;
uint8_t buf_num;
- bool top_field;
+ bool field1;
bool field_dropped;
struct timeval vc_ts;
diff --git a/include/sound/apr_audio.h b/include/sound/apr_audio.h
index 8c35ada..23c1d51 100644
--- a/include/sound/apr_audio.h
+++ b/include/sound/apr_audio.h
@@ -61,7 +61,7 @@
#define RT_PROXY_PORT_001_TX 0x2001 /* index = 31 */
#define SECONDARY_PCM_RX 12 /* index = 32 */
#define SECONDARY_PCM_TX 13 /* index = 33 */
-
+#define PSEUDOPORT_01 0x8001 /* index =34 */
#define AFE_PORT_INVALID 0xFFFF
#define SLIMBUS_EXTPROC_RX AFE_PORT_INVALID
@@ -299,6 +299,14 @@
int num_ch; /* 1 to 8 */
} __packed;
+struct afe_port_pseudo_cfg {
+ u16 bit_width;
+ u16 num_channels;
+ u16 data_format;
+ u16 timing_mode;
+ u16 reserved;
+} __packed;
+
#define AFE_PORT_AUDIO_IF_CONFIG 0x000100d3
#define AFE_PORT_AUDIO_SLIM_SCH_CONFIG 0x000100e4
#define AFE_PORT_MULTI_CHAN_HDMI_AUDIO_IF_CONFIG 0x000100D9
@@ -312,6 +320,7 @@
struct afe_port_slimbus_cfg slimbus;
struct afe_port_slimbus_sch_cfg slim_sch;
struct afe_port_rtproxy_cfg rtproxy;
+ struct afe_port_pseudo_cfg pseudo;
} __attribute__((packed));
struct afe_audioif_config_command {
@@ -574,6 +583,19 @@
u32 rate;
u8 dev_channel_mapping[8];
} __packed;
+
+struct adm_multi_channel_copp_open_v3 {
+ struct apr_hdr hdr;
+ u16 flags;
+ u16 mode;
+ u16 endpoint_id1;
+ u16 endpoint_id2;
+ u32 topology_id;
+ u16 channel_config;
+ u16 bit_width;
+ u32 rate;
+ u8 dev_channel_mapping[8];
+};
#define ADM_CMD_MEMORY_MAP 0x00010C30
struct adm_cmd_memory_map{
struct apr_hdr hdr;
@@ -914,7 +936,38 @@
* An unused channel is set to zero.
*/
};
+struct asm_dts_enc_cfg {
+ uint32_t sample_rate;
+ /*
+ * Samples at which input is to be encoded.
+ * Supported values:
+ * 44100 -- encode at 44.1 Khz
+ * 48000 -- encode at 48 Khz
+ */
+ uint32_t num_channels;
+ /*
+ * Number of channels for multi-channel encoding.
+ * Supported values: 1 to 6
+ */
+
+ uint8_t channel_mapping[6];
+ /*
+ * Channel array of size 16. Channel[i] mapping describes channel I.
+ * Each element i of the array describes channel I inside the buffer
+ * where num_channels. An unused channel is set to zero. Only first
+ * num_channels elements are valid
+
+ * Supported values:
+ * - # PCM_CHANNEL_L
+ * - # PCM_CHANNEL_R
+ * - # PCM_CHANNEL_C
+ * - # PCM_CHANNEL_LS
+ * - # PCM_CHANNEL_RS
+ * - # PCM_CHANNEL_LFE
+ */
+
+};
struct asm_adpcm_cfg {
u16 ch_cfg;
u16 bits_per_sample;
@@ -1107,6 +1160,7 @@
struct asm_sbc_read_cfg sbc;
struct asm_amrwb_read_cfg amrwb;
struct asm_multi_channel_pcm_fmt_blk mpcm;
+ struct asm_dts_enc_cfg dts;
} __attribute__((packed)) cfg;
};
@@ -1209,6 +1263,148 @@
u32 flags;
u32 format;
} __packed;
+#define ASM_STREAM_CMD_OPEN_TRANSCODE_LOOPBACK 0x00010DBA
+struct asm_stream_cmd_open_transcode_loopback {
+ struct apr_hdr hdr;
+ uint32_t mode_flags;
+ /*
+ * All bits are reserved. Clients must set them to zero.
+ */
+
+ uint32_t src_format_id;
+ /*
+ * Specifies the media format of the input audio stream.
+
+ * Supported values:
+ * - #ASM_MEDIA_FMT_LINEAR_PCM
+ * - #ASM_MEDIA_FMT_MULTI_CHANNEL_PCM
+ */
+
+ uint32_t sink_format_id;
+ /*
+ * Specifies the media format of the output stream.
+
+ * Supported values:
+ * - #ASM_MEDIA_FMT_LINEAR_PCM
+ * - #ASM_MEDIA_FMT_MULTI_CHANNEL_PCM
+ * - #ASM_MEDIA_FMT_DTS
+ */
+
+ uint32_t audproc_topo_id;
+ /*
+ * Postprocessing topology ID, which specifies the topology (order of
+ * processing) of postprocessing algorithms.
+
+ * Supported values:
+ * - #ASM_STREAM_POSTPROC_TOPO_ID_DEFAULT
+ * - #ASM_STREAM_POSTPROC_TOPO_ID_PEAKMETER
+ * - #ASM_STREAM_POSTPROC_TOPO_ID_NONE
+ * - #ASM_STREAM_POSTPROC_TOPO_ID_MCH_PEAK_VOL
+ */
+
+ uint16_t src_endpoint_type;
+ /*
+ * Specifies the source endpoint that provides the input samples.
+
+ * Supported values:
+ * - 0 -- Tx device matrix or stream router
+ * (gateway to the hardware ports)
+ * - All other values are reserved
+
+ * Clients must set this field to zero. Otherwise, an error is returned.
+ */
+
+ uint16_t sink_endpoint_type;
+ /*
+ * Specifies the sink endpoint type.
+
+ * Supported values:
+ * - 0 -- Rx device matrix or stream router
+ * (gateway to the hardware ports)
+ * - All other values are reserved
+
+ * Clients must set this field to zero. Otherwise, an error is returned.
+ */
+
+ uint16_t bits_per_sample;
+ /*
+ * Number of bits per sample processed by the ASM modules.
+ * Supported values: 16, 24
+ */
+
+ uint16_t reserved;
+ /*
+ * This field must be set to zero.
+ */
+} __packed;
+
+/*
+* ID of the DTS mix LFE channel to front channels parameter in the
+* #ASM_STREAM_CMD_SET_ENCDEC_PARAM command.
+* asm_dts_generic_param_t
+* ASM_PARAM_ID_DTS_MIX_LFE_TO_FRONT
+*/
+#define ASM_PARAM_ID_DTS_MIX_LFE_TO_FRONT 0x00010DB6
+
+/*
+* ID of the DTS DRC ratio parameter in the
+* #ASM_STREAM_CMD_SET_ENCDEC_PARAM command.
+* asm_dts_generic_param_t
+* ASM_PARAM_ID_DTS_DRC_RATIO
+*/
+#define ASM_PARAM_ID_DTS_DRC_RATIO 0x00010DB7
+
+/*
+* ID of the DTS enable dialog normalization parameter in the
+* #ASM_STREAM_CMD_SET_ENCDEC_PARAM command.
+
+* asm_dts_generic_param_t
+* ASM_PARAM_ID_DTS_ENABLE_DIALNORM
+*/
+#define ASM_PARAM_ID_DTS_ENABLE_DIALNORM 0x00010DB8
+
+/*
+* ID of the DTS enable parse REV2AUX parameter in the
+* #ASM_STREAM_CMD_SET_ENCDEC_PARAM command.
+* asm_dts_generic_param_t
+* ASM_PARAM_ID_DTS_ENABLE_PARSE_REV2AUX
+*/
+#define ASM_PARAM_ID_DTS_ENABLE_PARSE_REV2AUX 0x00010DB9
+
+struct asm_dts_generic_param {
+ int32_t generic_parameter;
+ /*
+ * #ASM_PARAM_ID_DTS_MIX_LFE_TO_FRONT:
+ * - if enabled, mixes LFE channel to front
+ * while downmixing (if necessary)
+ * - Supported values: 1-> enable, 0-> disable
+ * - Default: disabled
+
+ * #ASM_PARAM_ID_DTS_DRC_RATIO:
+ * - percentage of DRC ratio.
+ * - Supported values: 0-100
+ * - Default: 0, DRC is disabled.
+
+ * #ASM_PARAM_ID_DTS_ENABLE_DIALNORM:
+ * - flag to enable dialog normalization post processing.
+ * - Supported values: 1-> enable, 0-> disable.
+ * - Default: enabled.
+
+ * #ASM_PARAM_ID_DTS_ENABLE_PARSE_REV2AUX:
+ * - flag to enable parsing of rev2aux chunk in the bitstream.
+ * This chunk contains broadcast metadata.
+ * - Supported values: 1-> enable, 0-> disable.
+ * - Default: disabled.
+ */
+};
+
+struct asm_stream_cmd_dts_dec_param {
+ struct apr_hdr hdr;
+ u32 param_id;
+ u32 param_size;
+ struct asm_dts_generic_param generic_param;
+} __packed;
+
#define ASM_STREAM_CMD_OPEN_READWRITE 0x00010BCC
@@ -1238,7 +1434,7 @@
u8 session_id; /*ASM session ID*/
u16 afe_port_id;
u32 num_channels;
- u32 sampleing_rate;
+ u32 sampling_rate;
} __packed;
#define ASM_STREAM_CMD_SET_ENCDEC_PARAM 0x00010C10
diff --git a/include/sound/compress_params.h b/include/sound/compress_params.h
index f5c2d13..b95fa3c 100644
--- a/include/sound/compress_params.h
+++ b/include/sound/compress_params.h
@@ -418,6 +418,8 @@
__u32 ch_mode;
__u32 format;
__u32 align;
+ __u32 transcode_dts;
+ struct snd_dec_dts dts;
union snd_codec_options options;
__u32 reserved[3];
};
diff --git a/include/sound/q6adm.h b/include/sound/q6adm.h
index 676c4cb..70c68a8 100644
--- a/include/sound/q6adm.h
+++ b/include/sound/q6adm.h
@@ -37,6 +37,8 @@
int adm_close(int port);
+int adm_pseudo_close(int port);
+
int adm_matrix_map(int session_id, int path, int num_copps,
unsigned int *port_id, int copp_id);
@@ -45,6 +47,12 @@
void adm_ec_ref_rx_id(int port_id);
+int adm_connect_afe_port_v2(int mode, int session_id, int port_id,
+ int sample_rate, int channels);
+
+int adm_multi_ch_copp_pseudo_open_v3(int port_id, int path, int rate,
+ int channel_mode, int topology);
+
#ifdef CONFIG_RTAC
int adm_get_copp_id(int port_id);
#endif
diff --git a/include/sound/q6afe.h b/include/sound/q6afe.h
index a7264e8..8451ac6 100644
--- a/include/sound/q6afe.h
+++ b/include/sound/q6afe.h
@@ -70,6 +70,7 @@
IDX_RT_PROXY_PORT_001_TX = 31,
IDX_SECONDARY_PCM_RX = 32,
IDX_SECONDARY_PCM_TX = 33,
+ IDX_PSEUDOPORT_01 = 34,
AFE_MAX_PORTS
};
diff --git a/include/sound/q6asm.h b/include/sound/q6asm.h
index b0d74ba..6b4c17b 100644
--- a/include/sound/q6asm.h
+++ b/include/sound/q6asm.h
@@ -55,6 +55,7 @@
#define ENCDEC_SBCBITRATE 0x0001
#define ENCDEC_IMMEDIATE_DECODE 0x0002
#define ENCDEC_CFG_BLK 0x0003
+#define DTS_ENC_SAMPLE_RATE48k 48000
#define CMD_PAUSE 0x0001
#define CMD_FLUSH 0x0002
@@ -194,6 +195,11 @@
int q6asm_open_write_compressed(struct audio_client *ac, uint32_t format);
+int q6asm_open_transcode_loopback(struct audio_client *ac, uint32_t channels);
+
+int q6asm_enc_cfg_blk_dts(struct audio_client *ac,
+ uint32_t sample_rate, uint32_t channels);
+
int q6asm_open_read_write(struct audio_client *ac,
uint32_t rd_format,
uint32_t wr_format);
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index b9d1a73..1076be8 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -3825,10 +3825,11 @@
if (entry->buf[cnt - 1] != '\n') {
entry->buf[cnt] = '\n';
entry->buf[cnt + 1] = '\0';
- } else
+ stm_log(OST_ENTITY_TRACE_MARKER, entry->buf, cnt + 2);
+ } else {
entry->buf[cnt] = '\0';
-
- stm_log(OST_ENTITY_TRACE_MARKER, event, size);
+ stm_log(OST_ENTITY_TRACE_MARKER, entry->buf, cnt + 1);
+ }
ring_buffer_unlock_commit(buffer, event);
written = cnt;
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 831509c..c3142e8 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -913,6 +913,11 @@
[MIGRATE_ISOLATE] = { MIGRATE_RESERVE }, /* Never used */
};
+int *get_migratetype_fallbacks(int mtype)
+{
+ return fallbacks[mtype];
+}
+
/*
* Move the free pages in a range to the free lists of the requested type.
* Note that start_page and end_pages are not aligned on a pageblock
diff --git a/sound/soc/codecs/wcd9304.c b/sound/soc/codecs/wcd9304.c
index 5dcfefd..412090f 100644
--- a/sound/soc/codecs/wcd9304.c
+++ b/sound/soc/codecs/wcd9304.c
@@ -1238,9 +1238,9 @@
snd_soc_update_bits(codec, lineout_gain_reg, 0x10, 0x10);
break;
case SND_SOC_DAPM_POST_PMU:
- pr_debug("%s: sleeping 16 ms after %s PA turn on\n",
+ pr_debug("%s: sleeping 32 ms after %s PA turn on\n",
__func__, w->name);
- usleep_range(16000, 16000);
+ usleep_range(32000, 32000);
break;
case SND_SOC_DAPM_POST_PMD:
snd_soc_update_bits(codec, lineout_gain_reg, 0x10, 0x00);
@@ -2056,6 +2056,24 @@
return 0;
}
+static int sitar_ear_pa_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ pr_debug("%s: Sleeping 20ms after enabling EAR PA\n",
+ __func__);
+ msleep(20);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ pr_debug("%s: Sleeping 20ms after disabling EAR PA\n",
+ __func__);
+ msleep(20);
+ break;
+ }
+ return 0;
+}
+
static const struct snd_soc_dapm_widget sitar_dapm_i2s_widgets[] = {
SND_SOC_DAPM_SUPPLY("RX_I2S_CLK", SITAR_A_CDC_CLK_RX_I2S_CTL,
4, 0, NULL, 0),
@@ -2067,7 +2085,9 @@
/*RX stuff */
SND_SOC_DAPM_OUTPUT("EAR"),
- SND_SOC_DAPM_PGA("EAR PA", SITAR_A_RX_EAR_EN, 4, 0, NULL, 0),
+ SND_SOC_DAPM_PGA_E("EAR PA", SITAR_A_RX_EAR_EN, 4, 0, NULL, 0,
+ sitar_ear_pa_event, SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MIXER("DAC1", SITAR_A_RX_EAR_EN, 6, 0, dac1_switch,
ARRAY_SIZE(dac1_switch)),
SND_SOC_DAPM_SUPPLY("EAR DRIVER", SITAR_A_RX_EAR_EN, 3, 0, NULL, 0),
@@ -5137,6 +5157,8 @@
SITAR_REG_VAL(SITAR_A_RX_EAR_GAIN, 0x02),
SITAR_REG_VAL(SITAR_A_RX_EAR_VCM, 0x03),
+ SITAR_REG_VAL(SITAR_A_RX_LINE_BIAS_PA, 0xA7),
+
SITAR_REG_VAL(SITAR_A_CDC_RX1_B5_CTL, 0x78),
SITAR_REG_VAL(SITAR_A_CDC_RX2_B5_CTL, 0x78),
SITAR_REG_VAL(SITAR_A_CDC_RX3_B5_CTL, 0x78),
diff --git a/sound/soc/msm/mpq8064.c b/sound/soc/msm/mpq8064.c
index 016ef94..90c96b4 100644
--- a/sound/soc/msm/mpq8064.c
+++ b/sound/soc/msm/mpq8064.c
@@ -1486,6 +1486,20 @@
.ignore_pmdown_time = 1, /* dainlink has playback support */
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
+
+ },
+ {
+ .name = "MSM8960 Pseudo",
+ .stream_name = "Pseudo",
+ .cpu_dai_name = "Pseudo",
+ .dynamic = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ .be_id = MSM_FRONTEND_DAI_PSEUDO,
},
/* Backend DAI Links */
{
@@ -1624,6 +1638,18 @@
.be_id = MSM_BACKEND_DAI_AUXPCM_TX,
.be_hw_params_fixup = mpq8064_auxpcm_be_params_fixup,
},
+ {
+ .name = LPASS_BE_PSEUDO,
+ .stream_name = "PSEUDO Playback",
+ .cpu_dai_name = "msm-dai-q6.32769",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "snd-soc-dummy",
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_PSEUDO_PORT,
+ .be_hw_params_fixup = msm_be_hw_params_fixup,
+ .ignore_pmdown_time = 1,
+ },
};
diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
index eeabb78..5b0eb9c 100644
--- a/sound/soc/msm/msm-compr-q6.c
+++ b/sound/soc/msm/msm-compr-q6.c
@@ -474,7 +474,23 @@
default:
return -EINVAL;
}
-
+ if (compr->info.codec_param.codec.transcode_dts) {
+ msm_pcm_routing_reg_pseudo_stream(
+ MSM_FRONTEND_DAI_PSEUDO,
+ prtd->enc_audio_client->perf_mode,
+ prtd->enc_audio_client->session,
+ SNDRV_PCM_STREAM_CAPTURE,
+ 48000, runtime->channels > 6 ?
+ 6 : runtime->channels);
+ pr_debug("%s: cmd: DTS ENCDEC CFG BLK\n", __func__);
+ ret = q6asm_enc_cfg_blk_dts(prtd->enc_audio_client,
+ DTS_ENC_SAMPLE_RATE48k,
+ runtime->channels > 6 ?
+ 6 : runtime->channels);
+ if (ret < 0)
+ pr_err("%s: CMD: DTS ENCDEC CFG BLK failed\n",
+ __func__);
+ }
prtd->enabled = 1;
prtd->cmd_ack = 0;
@@ -650,6 +666,8 @@
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
pr_debug("%s: Trigger start\n", __func__);
q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
+ if (prtd->enc_audio_client)
+ q6asm_run_nowait(prtd->enc_audio_client, 0, 0, 0);
atomic_set(&prtd->start, 1);
break;
case SNDRV_PCM_TRIGGER_STOP:
@@ -660,6 +678,8 @@
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
pr_debug("SNDRV_PCM_TRIGGER_PAUSE\n");
q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE);
+ if (prtd->enc_audio_client)
+ q6asm_cmd_nowait(prtd->enc_audio_client, CMD_PAUSE);
atomic_set(&prtd->start, 0);
runtime->render_flag &= ~SNDRV_RENDER_STOPPED;
break;
@@ -811,6 +831,8 @@
atomic_set(&prtd->pending_buffer, 0);
prtd->pcm_irq_pos = 0;
q6asm_cmd(prtd->audio_client, CMD_CLOSE);
+ if (prtd->enc_audio_client)
+ q6asm_cmd(prtd->enc_audio_client, CMD_CLOSE);
compressed_audio.prtd = NULL;
q6asm_audio_client_buf_free_contiguous(dir,
prtd->audio_client);
@@ -827,6 +849,12 @@
soc_prtd->dai_link->be_id,
SNDRV_PCM_STREAM_PLAYBACK);
}
+ if (compr->info.codec_param.codec.transcode_dts) {
+ msm_pcm_routing_dereg_pseudo_stream(MSM_FRONTEND_DAI_PSEUDO,
+ prtd->enc_audio_client->session);
+ }
+ if (prtd->enc_audio_client)
+ q6asm_audio_client_free(prtd->enc_audio_client);
q6asm_audio_client_free(prtd->audio_client);
kfree(prtd);
return 0;
@@ -968,6 +996,29 @@
prtd->session_id,
substream->stream);
+ if (compr->info.codec_param.codec.transcode_dts) {
+ prtd->enc_audio_client =
+ q6asm_audio_client_alloc(
+ (app_cb)compr_event_handler, compr);
+ if (!prtd->enc_audio_client) {
+ pr_err("%s: Could not allocate " \
+ "memory\n", __func__);
+ return -ENOMEM;
+ }
+ prtd->enc_audio_client->perf_mode = false;
+ pr_debug("%s Setting up loopback path\n",
+ __func__);
+ ret = q6asm_open_transcode_loopback(
+ prtd->enc_audio_client,
+ params_channels(params));
+ if (ret < 0) {
+ pr_err("%s: Session transcode " \
+ "loopback open failed\n",
+ __func__);
+ return -ENODEV;
+ }
+ }
+
break;
}
} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
@@ -1117,6 +1168,22 @@
pr_err("%s: ERROR: copy from user\n", __func__);
return rc;
}
+ /*
+ * DTS Security needed for the transcode path
+ */
+ if (compr->info.codec_param.codec.transcode_dts) {
+ char modelId[128];
+ struct snd_dec_dts opt_dts =
+ compr->info.codec_param.codec.dts;
+ int modelIdLength = opt_dts.modelIdLength;
+ if (copy_from_user(modelId, (void *)opt_dts.modelId,
+ modelIdLength))
+ pr_err("%s: ERROR: copy modelId\n", __func__);
+ modelId[modelIdLength] = '\0';
+ pr_debug("%s: Received modelId =%s,length=%d\n",
+ __func__, modelId, modelIdLength);
+ core_set_dts_model_id(modelIdLength, modelId);
+ }
switch (compr->info.codec_param.codec.id) {
case SND_AUDIOCODEC_MP3:
/* For MP3 we dont need any other parameter */
@@ -1150,7 +1217,7 @@
case SND_AUDIOCODEC_DTS: {
char modelId[128];
struct snd_dec_dts opt_dts =
- compr->info.codec_param.codec.options.dts;
+ compr->info.codec_param.codec.dts;
int modelIdLength = opt_dts.modelIdLength;
pr_debug("SND_AUDIOCODEC_DTS\n");
if (copy_from_user(modelId, (void *)opt_dts.modelId,
@@ -1166,7 +1233,7 @@
case SND_AUDIOCODEC_DTS_LBR:{
char modelId[128];
struct snd_dec_dts opt_dts =
- compr->info.codec_param.codec.options.dts;
+ compr->info.codec_param.codec.dts;
int modelIdLength = opt_dts.modelIdLength;
pr_debug("SND_AUDIOCODEC_DTS_LBR\n");
if (copy_from_user(modelId, (void *)opt_dts.modelId,
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index dc8d9e6..e91ed86 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -477,6 +477,32 @@
.ops = &msm_fe_dai_ops,
.name = "SGLTE",
},
+ {
+ .playback = {
+ .stream_name = "Pseudo Playback",
+ .aif_name = "MM_DL9",
+ .rates = (SNDRV_PCM_RATE_8000_48000 |
+ SNDRV_PCM_RATE_KNOT),
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels_min = 1,
+ .channels_max = 8,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .capture = {
+ .stream_name = "Pseudo Capture",
+ .aif_name = "MM_UL9",
+ .rates = (SNDRV_PCM_RATE_8000_48000|
+ SNDRV_PCM_RATE_KNOT),
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels_min = 1,
+ .channels_max = 8,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .ops = &msm_fe_Multimedia_dai_ops,
+ .name = "Pseudo",
+ },
};
static __devinit int msm_fe_dai_dev_probe(struct platform_device *pdev)
diff --git a/sound/soc/msm/msm-dai-q6.c b/sound/soc/msm/msm-dai-q6.c
index 18c2329..8cc0eaa 100644
--- a/sound/soc/msm/msm-dai-q6.c
+++ b/sound/soc/msm/msm-dai-q6.c
@@ -660,6 +660,24 @@
return 0;
}
+static int msm_dai_q6_pseudo_hw_params(struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
+
+ dai_data->rate = params_rate(params);
+ dai_data->channels = params_channels(params) > 6 ?
+ params_channels(params) : 6;
+
+ dai_data->port_config.pseudo.bit_width = 16;
+ dai_data->port_config.pseudo.num_channels =
+ dai_data->channels;
+ dai_data->port_config.pseudo.data_format = 0;
+ dai_data->port_config.pseudo.timing_mode = 1;
+ dai_data->port_config.pseudo.reserved = 16;
+ return 0;
+}
+
/* Current implementation assumes hw_param is called once
* This may not be the case but what to do when ADM and AFE
* port are already opened and parameter changes
@@ -703,6 +721,9 @@
case RT_PROXY_DAI_002_RX:
rc = msm_dai_q6_afe_rtproxy_hw_params(params, dai);
break;
+ case PSEUDOPORT_01:
+ rc = msm_dai_q6_pseudo_hw_params(params, dai);
+ break;
case VOICE_PLAYBACK_TX:
case VOICE_RECORD_RX:
case VOICE_RECORD_TX:
@@ -1819,6 +1840,20 @@
.probe = msm_dai_q6_dai_probe,
.remove = msm_dai_q6_dai_remove,
};
+static struct snd_soc_dai_driver msm_dai_q6_pseudo_dai = {
+ .playback = {
+ .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
+ SNDRV_PCM_RATE_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels_min = 1,
+ .channels_max = 6,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .ops = &msm_dai_q6_ops,
+ .probe = msm_dai_q6_dai_probe,
+ .remove = msm_dai_q6_dai_remove,
+};
/* To do: change to register DAIs as batch */
static __devinit int msm_dai_q6_dev_probe(struct platform_device *pdev)
@@ -1915,6 +1950,10 @@
rc = snd_soc_register_dai(&pdev->dev,
&msm_dai_q6_incall_record_dai);
break;
+ case PSEUDOPORT_01:
+ rc = snd_soc_register_dai(&pdev->dev,
+ &msm_dai_q6_pseudo_dai);
+ break;
default:
rc = -ENODEV;
break;
diff --git a/sound/soc/msm/msm-pcm-q6.h b/sound/soc/msm/msm-pcm-q6.h
index 2678498..86e5c54 100644
--- a/sound/soc/msm/msm-pcm-q6.h
+++ b/sound/soc/msm/msm-pcm-q6.h
@@ -59,6 +59,7 @@
uint16_t source; /* Encoding source bit mask */
struct audio_client *audio_client;
+ struct audio_client *enc_audio_client;
uint16_t session_id;
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 800bea8..378baf1 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -194,6 +194,7 @@
{ SLIMBUS_EXTPROC_RX, 0, 0, 0, 0, 0},
{ SECONDARY_PCM_RX, 0, 0, 0, 0, 0},
{ SECONDARY_PCM_TX, 0, 0, 0, 0, 0},
+ { PSEUDOPORT_01, 0, 0, 0, 0, 0},
};
@@ -215,7 +216,8 @@
{INVALID_SESSION, INVALID_SESSION},
/* MULTIMEDIA8 */
{INVALID_SESSION, INVALID_SESSION},
-
+ /* PSEUDO */
+ {INVALID_SESSION, INVALID_SESSION},
};
static uint8_t is_be_dai_extproc(int be_dai)
@@ -298,6 +300,59 @@
mutex_unlock(&routing_lock);
}
+void msm_pcm_routing_reg_pseudo_stream(int fedai_id, bool perf_mode,
+ int dspst_id, int stream_type,
+ int sample_rate, int channels)
+{
+ int i, session_type, path_type, port_type, mode, ret;
+ struct route_payload payload;
+ pr_debug("%s:fedai_id = %d dspst_id = %d stream_type %d",
+ __func__, fedai_id, dspst_id, stream_type);
+
+ if (stream_type == SNDRV_PCM_STREAM_PLAYBACK) {
+ session_type = SESSION_TYPE_RX;
+ path_type = ADM_PATH_PLAYBACK;
+ port_type = MSM_AFE_PORT_TYPE_RX;
+ } else {
+ session_type = SESSION_TYPE_TX;
+ path_type = ADM_PATH_LIVE_REC;
+ port_type = MSM_AFE_PORT_TYPE_TX;
+ }
+
+ mutex_lock(&routing_lock);
+
+ payload.num_copps = 0;
+ adm_multi_ch_copp_pseudo_open_v3(PSEUDOPORT_01,
+ path_type, sample_rate, channels,
+ DEFAULT_COPP_TOPOLOGY);
+
+ payload.copp_ids[payload.num_copps++] = PSEUDOPORT_01;
+
+ for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
+ if (test_bit(fedai_id, &msm_bedais[i].fe_sessions))
+ msm_bedais[i].perf_mode = perf_mode;
+ if (!is_be_dai_extproc(i) &&
+ (msm_bedais[i].active) &&
+ (test_bit(fedai_id, &msm_bedais[i].fe_sessions))) {
+
+ mode = afe_get_port_type(msm_bedais[i].port_id);
+ ret = adm_connect_afe_port_v2(mode, dspst_id,
+ msm_bedais[i].port_id,
+ msm_bedais[i].sample_rate,
+ msm_bedais[i].channel);
+
+ if (ret < 0)
+ pr_err("%s: adm_connect_afe_port_v2 failed\n",
+ __func__);
+ }
+ }
+ if (payload.num_copps)
+ adm_matrix_map(dspst_id, path_type,
+ payload.num_copps, payload.copp_ids, 0);
+
+ mutex_unlock(&routing_lock);
+}
+
void msm_pcm_routing_reg_phy_stream(int fedai_id, bool perf_mode, int dspst_id,
int stream_type)
{
@@ -375,6 +430,32 @@
mutex_unlock(&routing_lock);
}
+void msm_pcm_routing_dereg_pseudo_stream(int fedai_id, int dspst_id)
+{
+ int i, mode, ret;
+ pr_debug("%s:fedai_id = %d dspst_id = %d",
+ __func__, fedai_id, dspst_id);
+
+ mutex_lock(&routing_lock);
+
+ adm_pseudo_close(PSEUDOPORT_01);
+ for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
+ if (!is_be_dai_extproc(i) &&
+ (msm_bedais[i].active) &&
+ (test_bit(fedai_id, &msm_bedais[i].fe_sessions))) {
+
+ mode = afe_get_port_type(msm_bedais[i].port_id);
+ ret = adm_disconnect_afe_port(mode, dspst_id,
+ msm_bedais[i].port_id);
+ if (ret < 0)
+ pr_err("%s: adm_connect_afe_port_v2 failed\n",
+ __func__);
+ }
+ }
+
+ mutex_unlock(&routing_lock);
+
+}
void msm_pcm_routing_dereg_phy_stream(int fedai_id, int stream_type)
{
int i, port_type, session_type;
@@ -1210,6 +1291,9 @@
SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_SEC_I2S_RX,
MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("Pseudo", MSM_BACKEND_DAI_SEC_I2S_RX,
+ MSM_FRONTEND_DAI_PSEUDO, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new slimbus_rx_mixer_controls[] = {
@@ -1291,6 +1375,17 @@
SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_HDMI_RX,
MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("Pseudo", MSM_BACKEND_DAI_HDMI_RX,
+ MSM_FRONTEND_DAI_PSEUDO, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+};
+static const struct snd_kcontrol_new pseudo_mixer_controls[] = {
+ SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_PSEUDO_PORT,
+ MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_PSEUDO_PORT,
+ MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
/* incall music delivery mixer */
static const struct snd_kcontrol_new incall_music_delivery_mixer_controls[] = {
@@ -2163,6 +2258,7 @@
SND_SOC_DAPM_AIF_IN("MM_DL6", "MultiMedia6 Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("MM_DL7", "MultiMedia7 Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("MM_DL8", "MultiMedia8 Playback", 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_IN("MM_DL9", "Pseudo Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("VOIP_DL", "VoIP Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("MM_UL1", "MultiMedia1 Capture", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("MM_UL2", "MultiMedia2 Capture", 0, 0, 0, 0),
@@ -2201,6 +2297,7 @@
0, 0, 0 , 0),
SND_SOC_DAPM_AIF_OUT("SLIMBUS_0_RX", "Slimbus Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("HDMI", "HDMI Playback", 0, 0, 0 , 0),
+ SND_SOC_DAPM_AIF_OUT("PSEUDO", "PSEUDO Playback", 0, 0, 0 , 0),
SND_SOC_DAPM_AIF_OUT("MI2S_RX", "MI2S Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("PRI_I2S_TX", "Primary I2S Capture", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("SEC_I2S_TX", "Secondary I2S Capture", 0, 0, 0, 0),
@@ -2260,6 +2357,8 @@
slimbus_rx_mixer_controls, ARRAY_SIZE(slimbus_rx_mixer_controls)),
SND_SOC_DAPM_MIXER("HDMI Mixer", SND_SOC_NOPM, 0, 0,
hdmi_mixer_controls, ARRAY_SIZE(hdmi_mixer_controls)),
+ SND_SOC_DAPM_MIXER("PSEUDO Mixer", SND_SOC_NOPM, 0, 0,
+ pseudo_mixer_controls, ARRAY_SIZE(pseudo_mixer_controls)),
SND_SOC_DAPM_MIXER("MI2S_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
mi2s_rx_mixer_controls, ARRAY_SIZE(mi2s_rx_mixer_controls)),
SND_SOC_DAPM_MIXER("MultiMedia1 Mixer", SND_SOC_NOPM, 0, 0,
@@ -2398,6 +2497,7 @@
{"SEC_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
{"SEC_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
{"SEC_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
+ {"SEC_RX Audio Mixer", "Pseudo", "MM_DL9"},
{"SEC_I2S_RX", NULL, "SEC_RX Audio Mixer"},
{"SLIMBUS_0_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
@@ -2418,8 +2518,12 @@
{"HDMI Mixer", "MultiMedia6", "MM_DL6"},
{"HDMI Mixer", "MultiMedia7", "MM_DL7"},
{"HDMI Mixer", "MultiMedia8", "MM_DL8"},
+ {"HDMI Mixer", "Pseudo", "MM_DL9"},
{"HDMI", NULL, "HDMI Mixer"},
+ {"PSEUDO Mixer", "MultiMedia4", "MM_DL4"},
+ {"PSEUDO", NULL, "PSEUDO Mixer"},
+
/* incall */
{"Incall_Music Audio Mixer", "MultiMedia1", "MM_DL1"},
{"Incall_Music Audio Mixer", "MultiMedia2", "MM_DL2"},
@@ -2665,6 +2769,7 @@
{"BE_OUT", NULL, "SLIMBUS_3_RX"},
{"BE_OUT", NULL, "SLIMBUS_4_RX"},
{"BE_OUT", NULL, "HDMI"},
+ {"BE_OUT", NULL, "PSEUDO"},
{"BE_OUT", NULL, "MI2S_RX"},
{"PRI_I2S_TX", NULL, "BE_IN"},
{"SEC_I2S_TX", NULL, "BE_IN"},
@@ -2784,7 +2889,14 @@
for_each_set_bit(i, &bedai->fe_sessions, MSM_FRONTEND_DAI_MM_SIZE) {
if (fe_dai_map[i][session_type] != INVALID_SESSION) {
channels = bedai->channel;
- if ((playback || capture)
+ if (bedai->port_id == PSEUDOPORT_01) {
+ adm_multi_ch_copp_pseudo_open_v3(bedai->port_id,
+ path_type,
+ bedai->sample_rate,
+ channels > 6 ? 6 :
+ channels,
+ DEFAULT_COPP_TOPOLOGY);
+ } else if ((playback || capture)
&& ((channels == 2) || (channels == 1)) &&
bedai->perf_mode) {
adm_multi_ch_copp_open(bedai->port_id,
diff --git a/sound/soc/msm/msm-pcm-routing.h b/sound/soc/msm/msm-pcm-routing.h
index e11133e..32ab063 100644
--- a/sound/soc/msm/msm-pcm-routing.h
+++ b/sound/soc/msm/msm-pcm-routing.h
@@ -18,6 +18,7 @@
#define LPASS_BE_SLIMBUS_0_RX "SLIMBUS_0_RX"
#define LPASS_BE_SLIMBUS_0_TX "SLIMBUS_0_TX"
#define LPASS_BE_HDMI "HDMI"
+#define LPASS_BE_PSEUDO "PSEUDO"
#define LPASS_BE_INT_BT_SCO_RX "INT_BT_SCO_RX"
#define LPASS_BE_INT_BT_SCO_TX "INT_BT_SCO_TX"
#define LPASS_BE_INT_FM_RX "INT_FM_RX"
@@ -61,6 +62,7 @@
MSM_FRONTEND_DAI_MULTIMEDIA6,
MSM_FRONTEND_DAI_MULTIMEDIA7,
MSM_FRONTEND_DAI_MULTIMEDIA8,
+ MSM_FRONTEND_DAI_PSEUDO,
MSM_FRONTEND_DAI_CS_VOICE,
MSM_FRONTEND_DAI_VOIP,
MSM_FRONTEND_DAI_AFE_RX,
@@ -71,8 +73,8 @@
MSM_FRONTEND_DAI_MAX,
};
-#define MSM_FRONTEND_DAI_MM_SIZE (MSM_FRONTEND_DAI_MULTIMEDIA8 + 1)
-#define MSM_FRONTEND_DAI_MM_MAX_ID MSM_FRONTEND_DAI_MULTIMEDIA8
+#define MSM_FRONTEND_DAI_MM_SIZE (MSM_FRONTEND_DAI_PSEUDO + 1)
+#define MSM_FRONTEND_DAI_MM_MAX_ID MSM_FRONTEND_DAI_PSEUDO
enum {
MSM_BACKEND_DAI_PRI_I2S_RX = 0,
@@ -106,6 +108,7 @@
MSM_BACKEND_DAI_EXTPROC_EC_TX,
MSM_BACKEND_DAI_SEC_AUXPCM_RX,
MSM_BACKEND_DAI_SEC_AUXPCM_TX,
+ MSM_BACKEND_DAI_PSEUDO_PORT,
MSM_BACKEND_DAI_MAX,
};
@@ -118,6 +121,12 @@
void msm_pcm_routing_reg_psthr_stream(int fedai_id, int dspst_id,
int stream_type, int enable);
+void msm_pcm_routing_reg_pseudo_stream(int fedai_id, bool perf_mode,
+ int dspst_id, int stream_type, int sample_rate,
+ int channels);
+
+void msm_pcm_routing_dereg_pseudo_stream(int fedai_id, int dspst_id);
+
void msm_pcm_routing_dereg_phy_stream(int fedai_id, int stream_type);
int lpa_set_volume(unsigned volume);
diff --git a/sound/soc/msm/msm8930.c b/sound/soc/msm/msm8930.c
index b3db9e1..42699c9 100644
--- a/sound/soc/msm/msm8930.c
+++ b/sound/soc/msm/msm8930.c
@@ -183,9 +183,9 @@
pm8xxx_spk_enable(MSM8930_SPK_ON);
}
- pr_debug("%s: slepping 4 ms after turning on external "
+ pr_debug("%s: sleeping 10 ms after turning on external "
" Left Speaker Ampl\n", __func__);
- usleep_range(4000, 4000);
+ usleep_range(10000, 10000);
}
} else {
@@ -218,9 +218,9 @@
pm8xxx_spk_enable(MSM8930_SPK_OFF);
msm8930_ext_spk_pamp = 0;
- pr_debug("%s: slepping 4 ms after turning on external "
+ pr_debug("%s: slepping 10 ms after turning on external "
" Left Speaker Ampl\n", __func__);
- usleep_range(4000, 4000);
+ usleep_range(10000, 10000);
} else {
@@ -788,6 +788,18 @@
return 0;
}
+static int msm8930_proxy_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_interval *rate = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_RATE);
+
+ pr_debug("%s()\n", __func__);
+ rate->min = rate->max = 48000;
+
+ return 0;
+}
+
static int msm8930_aux_pcm_get_gpios(void)
{
int ret = 0;
@@ -1195,6 +1207,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
+ .be_hw_params_fixup = msm8930_proxy_be_hw_params_fixup,
.ignore_pmdown_time = 1, /* this dainlink has playback support */
},
{
@@ -1206,6 +1219,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
+ .be_hw_params_fixup = msm8930_proxy_be_hw_params_fixup,
},
/* AUX PCM Backend DAI Links */
{
diff --git a/sound/soc/msm/qdsp6/q6adm.c b/sound/soc/msm/qdsp6/q6adm.c
index c6970f1..00394aa 100644
--- a/sound/soc/msm/qdsp6/q6adm.c
+++ b/sound/soc/msm/qdsp6/q6adm.c
@@ -45,7 +45,7 @@
static struct acdb_cal_block mem_addr_audvol[MAX_AUDPROC_TYPES];
static struct adm_ctl this_adm;
-
+static int pseudo_copp[2];
int srs_trumedia_open(int port_id, int srs_tech_id, void *srs_params)
{
@@ -293,6 +293,8 @@
case ADM_CMD_MATRIX_MAP_ROUTINGS:
case ADM_CMD_CONNECT_AFE_PORT:
case ADM_CMD_DISCONNECT_AFE_PORT:
+ case ADM_CMD_CONNECT_AFE_PORT_V2:
+ case ADM_CMD_MULTI_CHANNEL_COPP_OPEN_V3:
atomic_set(&this_adm.copp_stat[index], 1);
wake_up(&this_adm.wait);
break;
@@ -305,9 +307,10 @@
}
switch (data->opcode) {
+
+ case ADM_CMDRSP_MULTI_CHANNEL_COPP_OPEN_V3:
case ADM_CMDRSP_COPP_OPEN:
- case ADM_CMDRSP_MULTI_CHANNEL_COPP_OPEN:
- case ADM_CMDRSP_MULTI_CHANNEL_COPP_OPEN_V3: {
+ case ADM_CMDRSP_MULTI_CHANNEL_COPP_OPEN: {
struct adm_copp_open_respond *open = data->payload;
if (open->copp_id == INVALID_COPP_ID) {
pr_err("%s: invalid coppid rxed %d\n",
@@ -316,6 +319,10 @@
wake_up(&this_adm.wait);
break;
}
+ if (index == IDX_PSEUDOPORT_01)
+ pseudo_copp[
+ atomic_read(&this_adm.copp_cnt[index])] =
+ open->copp_id;
atomic_set(&this_adm.copp_id[index], open->copp_id);
atomic_set(&this_adm.copp_stat[index], 1);
pr_debug("%s: coppid rxed=%d\n", __func__,
@@ -337,6 +344,79 @@
return 0;
}
+int adm_connect_afe_port_v2(int mode, int session_id, int port_id,
+ int sample_rate, int channels)
+{
+ struct adm_cmd_connect_afe_port_v2 cmd;
+ int ret = 0;
+ int index;
+
+ pr_debug("%s: port %d session id:%d\n", __func__,
+ port_id, session_id);
+
+ port_id = afe_convert_virtual_to_portid(port_id);
+
+ if (afe_validate_port(port_id) < 0) {
+ pr_err("%s port idi[%d] is invalid\n", __func__, port_id);
+ return -ENODEV;
+ }
+ if (this_adm.apr == NULL) {
+ this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
+ 0xFFFFFFFF, &this_adm);
+ if (this_adm.apr == NULL) {
+ pr_err("%s: Unable to register ADM\n", __func__);
+ ret = -ENODEV;
+ return ret;
+ }
+ rtac_set_adm_handle(this_adm.apr);
+ }
+ index = afe_get_port_index(port_id);
+ pr_debug("%s: Port ID %d, index %d\n", __func__, port_id, index);
+
+ cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+ cmd.hdr.pkt_size = sizeof(cmd);
+ cmd.hdr.src_svc = APR_SVC_ADM;
+ cmd.hdr.src_domain = APR_DOMAIN_APPS;
+ cmd.hdr.src_port = port_id;
+ cmd.hdr.dest_svc = APR_SVC_ADM;
+ cmd.hdr.dest_domain = APR_DOMAIN_ADSP;
+ cmd.hdr.dest_port = port_id;
+ cmd.hdr.token = port_id;
+ cmd.hdr.opcode = ADM_CMD_CONNECT_AFE_PORT_V2;
+
+ cmd.mode = mode;
+ cmd.session_id = session_id;
+ cmd.afe_port_id = port_id;
+ cmd.num_channels = channels;
+ cmd.sampling_rate = sample_rate;
+
+ atomic_set(&this_adm.copp_stat[index], 0);
+ ret = apr_send_pkt(this_adm.apr, (uint32_t *)&cmd);
+ if (ret < 0) {
+ pr_err("%s:ADM enable for port %d failed\n",
+ __func__, port_id);
+ ret = -EINVAL;
+ goto fail_cmd;
+ }
+ ret = wait_event_timeout(this_adm.wait,
+ atomic_read(&this_adm.copp_stat[index]),
+ msecs_to_jiffies(TIMEOUT_MS));
+ if (!ret) {
+ pr_err("%s ADM connect AFE failed for port %d\n", __func__,
+ port_id);
+ ret = -EINVAL;
+ goto fail_cmd;
+ }
+ atomic_inc(&this_adm.copp_cnt[index]);
+ return 0;
+
+fail_cmd:
+
+ return ret;
+
+}
+
static int send_adm_cal_block(int port_id, struct acdb_cal_block *aud_cal)
{
s32 result = 0;
@@ -718,6 +798,138 @@
return ret;
}
+int adm_multi_ch_copp_pseudo_open_v3(int port_id, int path,
+ int rate, int channel_mode,
+ int topology)
+{
+ struct adm_multi_channel_copp_open_v3 open;
+ int ret = 0;
+ int index;
+
+ pr_debug("%s: port %d path:%d rate:%d mode:%d\n", __func__,
+ port_id, path, rate, channel_mode);
+
+ port_id = afe_convert_virtual_to_portid(port_id);
+
+ if (afe_validate_port(port_id) < 0) {
+ pr_err("%s port idi[%d] is invalid\n", __func__, port_id);
+ return -ENODEV;
+ }
+
+ index = afe_get_port_index(port_id);
+ pr_debug("%s: Port ID %d, index %d\n", __func__, port_id, index);
+
+ if (this_adm.apr == NULL) {
+ this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
+ 0xFFFFFFFF, &this_adm);
+ if (this_adm.apr == NULL) {
+ pr_err("%s: Unable to register ADM\n", __func__);
+ ret = -ENODEV;
+ return ret;
+ }
+ rtac_set_adm_handle(this_adm.apr);
+ }
+
+
+ {
+ open.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+ open.hdr.pkt_size = sizeof(open);
+ open.hdr.src_svc = APR_SVC_ADM;
+ open.hdr.src_domain = APR_DOMAIN_APPS;
+ open.hdr.src_port = port_id;
+ open.hdr.dest_svc = APR_SVC_ADM;
+ open.hdr.dest_domain = APR_DOMAIN_ADSP;
+ open.hdr.dest_port = port_id;
+ open.hdr.token = port_id;
+ open.hdr.opcode = ADM_CMD_MULTI_CHANNEL_COPP_OPEN_V3;
+ memset(open.dev_channel_mapping, 0, 8);
+
+ if (channel_mode == 1) {
+ open.dev_channel_mapping[0] = PCM_CHANNEL_FC;
+ } else if (channel_mode == 2) {
+ open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
+ open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
+ } else if (channel_mode == 4) {
+ open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
+ open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
+ open.dev_channel_mapping[2] = PCM_CHANNEL_RB;
+ open.dev_channel_mapping[3] = PCM_CHANNEL_LB;
+ } else if (channel_mode == 6) {
+ open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
+ open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
+ open.dev_channel_mapping[2] = PCM_CHANNEL_LFE;
+ open.dev_channel_mapping[3] = PCM_CHANNEL_FC;
+ open.dev_channel_mapping[4] = PCM_CHANNEL_LB;
+ open.dev_channel_mapping[5] = PCM_CHANNEL_RB;
+ } else if (channel_mode == 8) {
+ open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
+ open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
+ open.dev_channel_mapping[2] = PCM_CHANNEL_LFE;
+ open.dev_channel_mapping[3] = PCM_CHANNEL_FC;
+ open.dev_channel_mapping[4] = PCM_CHANNEL_LB;
+ open.dev_channel_mapping[5] = PCM_CHANNEL_RB;
+ open.dev_channel_mapping[6] = PCM_CHANNEL_FLC;
+ open.dev_channel_mapping[7] = PCM_CHANNEL_FRC;
+ } else {
+ pr_err("%s invalid num_chan %d\n", __func__,
+ channel_mode);
+ return -EINVAL;
+ }
+
+ open.mode = path;
+ open.endpoint_id1 = port_id;
+ open.endpoint_id2 = 0xFFFF;
+ open.bit_width = 16;
+
+ if (path == ADM_PATH_PLAYBACK)
+ open.topology_id = get_adm_rx_topology();
+ else {
+ open.topology_id = get_adm_tx_topology();
+ if ((open.topology_id ==
+ VPM_TX_SM_ECNS_COPP_TOPOLOGY) ||
+ (open.topology_id ==
+ VPM_TX_DM_FLUENCE_COPP_TOPOLOGY))
+ rate = 16000;
+ }
+
+ if (open.topology_id == 0)
+ open.topology_id = topology;
+
+ open.channel_config = channel_mode & 0x00FF;
+ open.rate = rate;
+ open.flags = 0;
+
+ pr_debug("%s: channel_config=%d port_id=%d rate=%d" \
+ "topology_id=0x%X\n", __func__, open.channel_config,\
+ open.endpoint_id1, open.rate,\
+ open.topology_id);
+
+ atomic_set(&this_adm.copp_stat[index], 0);
+ ret = apr_send_pkt(this_adm.apr, (uint32_t *)&open);
+ if (ret < 0) {
+ pr_err("%s:ADM enable for port %d failed\n",
+ __func__, port_id);
+ ret = -EINVAL;
+ goto fail_cmd;
+ }
+ ret = wait_event_timeout(this_adm.wait,
+ atomic_read(&this_adm.copp_stat[index]),
+ msecs_to_jiffies(TIMEOUT_MS));
+ if (!ret) {
+ pr_err("%s ADM open failed for port %d\n", __func__,
+ port_id);
+ ret = -EINVAL;
+ goto fail_cmd;
+ }
+ }
+ atomic_inc(&this_adm.copp_cnt[index]);
+ return 0;
+
+fail_cmd:
+ return ret;
+
+}
int adm_multi_ch_copp_open(int port_id, int path, int rate, int channel_mode,
int topology, int perfmode)
@@ -1127,6 +1339,56 @@
pr_debug("%s ec_ref_rx:%d", __func__, this_adm.ec_ref_rx);
}
+int adm_pseudo_close(int port_id)
+{
+ struct apr_hdr close;
+
+ int ret = 0, i = 0;
+ int index = 0;
+ int pseudo_copp_cnt;
+ index = afe_get_port_index(port_id);
+ if (afe_validate_port(port_id) < 0)
+ return -EINVAL;
+
+ pseudo_copp_cnt = atomic_read(&this_adm.copp_cnt[index]);
+ pr_debug("%s port_id=%d index %d copp_cnt %d\n", __func__, port_id,
+ index, pseudo_copp_cnt);
+
+ for (i = 0; i < pseudo_copp_cnt; i++) {
+ close.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+ close.pkt_size = sizeof(close);
+ close.src_svc = APR_SVC_ADM;
+ close.src_domain = APR_DOMAIN_APPS;
+ close.src_port = port_id;
+ close.dest_svc = APR_SVC_ADM;
+ close.dest_domain = APR_DOMAIN_ADSP;
+ close.dest_port = pseudo_copp[i];
+ close.token = port_id;
+ close.opcode = ADM_CMD_COPP_CLOSE;
+
+ atomic_set(&this_adm.copp_id[index], RESET_COPP_ID);
+ atomic_set(&this_adm.copp_stat[index], 0);
+
+
+ pr_debug("%s:coppid %d portid=%d index=%d coppcnt=%d\n",
+ __func__,
+ atomic_read(&this_adm.copp_id[index]),
+ port_id, index,
+ atomic_read(&this_adm.copp_cnt[index]));
+
+ ret = apr_send_pkt(this_adm.apr, (uint32_t *)&close);
+
+ ret = wait_event_timeout(this_adm.wait,
+ atomic_read(&this_adm.copp_stat[index]),
+ msecs_to_jiffies(TIMEOUT_MS));
+ }
+
+ atomic_set(&this_adm.copp_cnt[index], 0);
+ return ret;
+
+}
+
int adm_close(int port_id)
{
struct apr_hdr close;
diff --git a/sound/soc/msm/qdsp6/q6afe.c b/sound/soc/msm/qdsp6/q6afe.c
index a4f4b60..9c62a2e 100644
--- a/sound/soc/msm/qdsp6/q6afe.c
+++ b/sound/soc/msm/qdsp6/q6afe.c
@@ -156,6 +156,7 @@
case VOICE_PLAYBACK_TX:
case RT_PROXY_PORT_001_RX:
case SLIMBUS_4_RX:
+ case PSEUDOPORT_01:
ret = MSM_AFE_PORT_TYPE_RX;
break;
@@ -225,6 +226,7 @@
case RT_PROXY_PORT_001_TX:
case SLIMBUS_4_RX:
case SLIMBUS_4_TX:
+ case PSEUDOPORT_01:
{
ret = 0;
break;
@@ -295,6 +297,7 @@
case RT_PROXY_PORT_001_TX: return IDX_RT_PROXY_PORT_001_TX;
case SLIMBUS_4_RX: return IDX_SLIMBUS_4_RX;
case SLIMBUS_4_TX: return IDX_SLIMBUS_4_TX;
+ case PSEUDOPORT_01: return IDX_PSEUDOPORT_01;
default: return -EINVAL;
}
@@ -331,6 +334,9 @@
case RT_PROXY_PORT_001_TX:
ret_size = SIZEOF_CFG_CMD(afe_port_rtproxy_cfg);
break;
+ case PSEUDOPORT_01:
+ ret_size = SIZEOF_CFG_CMD(afe_port_pseudo_cfg);
+ break;
case PCM_RX:
case PCM_TX:
case SECONDARY_PCM_RX:
@@ -506,6 +512,11 @@
else
config.hdr.opcode = AFE_PORT_CMD_I2S_CONFIG;
break;
+ case PSEUDOPORT_01:
+ config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
+ pr_debug("%s, config, opcode=%x\n", __func__,
+ config.hdr.opcode);
+ break;
default:
config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
break;
diff --git a/sound/soc/msm/qdsp6/q6asm.c b/sound/soc/msm/qdsp6/q6asm.c
index b7d5d33..7b52956 100644
--- a/sound/soc/msm/qdsp6/q6asm.c
+++ b/sound/soc/msm/qdsp6/q6asm.c
@@ -35,7 +35,6 @@
#include <mach/memory.h>
#include <mach/debug_mm.h>
-#include <mach/peripheral-loader.h>
#include <mach/qdsp6v2/audio_acdb.h>
#include <mach/qdsp6v2/rtac.h>
@@ -894,6 +893,7 @@
case ASM_STREAM_CMD_SET_ENCDEC_PARAM:
case ASM_STREAM_CMD_OPEN_WRITE_COMPRESSED:
case ASM_STREAM_CMD_OPEN_READ_COMPRESSED:
+ case ASM_STREAM_CMD_OPEN_TRANSCODE_LOOPBACK:
if (atomic_read(&ac->cmd_state) && wakeup_flag) {
atomic_set(&ac->cmd_state, 0);
pr_debug("response payload[1]:%d",
@@ -1066,6 +1066,114 @@
return 0;
}
+int q6asm_open_transcode_loopback(struct audio_client *ac, uint32_t channels)
+{
+ int rc = 0x00;
+ struct asm_stream_cmd_open_transcode_loopback open;
+
+ if ((ac == NULL) || (ac->apr == NULL)) {
+ pr_err("%s: APR handle NULL\n", __func__);
+ return -EINVAL;
+ }
+ pr_debug("%s: session[%d] channels = %d", __func__, ac->session,
+ channels);
+
+ q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
+
+ open.hdr.opcode = ASM_STREAM_CMD_OPEN_TRANSCODE_LOOPBACK;
+
+ open.mode_flags = 0;
+
+ if (channels > 2)
+ open.src_format_id = MULTI_CHANNEL_PCM;
+ else
+ open.src_format_id = LINEAR_PCM;
+
+
+ open.sink_format_id = DTS;
+ open.audproc_topo_id = DEFAULT_POPP_TOPOLOGY;
+ open.src_endpoint_type = 0;
+ open.sink_endpoint_type = 0;
+ open.bits_per_sample = 16;
+ open.reserved = 0;
+
+ rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
+ if (rc < 0) {
+ pr_err("%s: open failed op[0x%x]rc[%d]\n", \
+ __func__, open.hdr.opcode, rc);
+ goto fail_cmd;
+ }
+ rc = wait_event_timeout(ac->cmd_wait,
+ (atomic_read(&ac->cmd_state) == 0), 5*HZ);
+ if (!rc) {
+ pr_err("%s: timeout. waited for OPEN_WRITE rc[%d]\n", __func__,
+ rc);
+ goto fail_cmd;
+ }
+ return 0;
+fail_cmd:
+ return -EINVAL;
+}
+
+int q6asm_enc_cfg_blk_dts(struct audio_client *ac,
+ uint32_t sample_rate,
+ uint32_t channels)
+{
+ struct asm_stream_cmd_encdec_cfg_blk enc_cfg;
+ int rc = 0;
+
+ pr_debug("%s: sample_rate=%d,channels=%d\n", __func__,
+ sample_rate, channels);
+
+ q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
+
+ enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
+ enc_cfg.param_id = ASM_ENCDEC_CFG_BLK_ID;
+ enc_cfg.param_size = sizeof(struct asm_encode_cfg_blk);
+ enc_cfg.enc_blk.frames_per_buf = 0;
+ enc_cfg.enc_blk.format_id = DTS;
+ enc_cfg.enc_blk.cfg_size = sizeof(struct asm_dts_enc_cfg);
+ enc_cfg.enc_blk.cfg.dts.sample_rate = sample_rate;
+ enc_cfg.enc_blk.cfg.dts.num_channels = channels;
+ if (channels == 2) {
+ enc_cfg.enc_blk.cfg.dts.channel_mapping[0] = PCM_CHANNEL_FL;
+ enc_cfg.enc_blk.cfg.dts.channel_mapping[1] = PCM_CHANNEL_FR;
+ enc_cfg.enc_blk.cfg.dts.channel_mapping[2] = 0;
+ enc_cfg.enc_blk.cfg.dts.channel_mapping[3] = 0;
+ enc_cfg.enc_blk.cfg.dts.channel_mapping[4] = 0;
+ enc_cfg.enc_blk.cfg.dts.channel_mapping[5] = 0;
+ } else if (channels == 4) {
+ enc_cfg.enc_blk.cfg.dts.channel_mapping[0] = PCM_CHANNEL_FL;
+ enc_cfg.enc_blk.cfg.dts.channel_mapping[1] = PCM_CHANNEL_FR;
+ enc_cfg.enc_blk.cfg.dts.channel_mapping[2] = PCM_CHANNEL_LS;
+ enc_cfg.enc_blk.cfg.dts.channel_mapping[3] = PCM_CHANNEL_RS;
+ enc_cfg.enc_blk.cfg.dts.channel_mapping[4] = 0;
+ enc_cfg.enc_blk.cfg.dts.channel_mapping[5] = 0;
+ } else if (channels == 6) {
+ enc_cfg.enc_blk.cfg.dts.channel_mapping[0] = PCM_CHANNEL_FL;
+ enc_cfg.enc_blk.cfg.dts.channel_mapping[1] = PCM_CHANNEL_FR;
+ enc_cfg.enc_blk.cfg.dts.channel_mapping[2] = PCM_CHANNEL_LFE;
+ enc_cfg.enc_blk.cfg.dts.channel_mapping[3] = PCM_CHANNEL_LS;
+ enc_cfg.enc_blk.cfg.dts.channel_mapping[4] = PCM_CHANNEL_RS;
+ enc_cfg.enc_blk.cfg.dts.channel_mapping[5] = PCM_CHANNEL_FC;
+ }
+ rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
+ if (rc < 0) {
+ pr_err("Comamnd %d failed\n", ASM_STREAM_CMD_SET_ENCDEC_PARAM);
+ rc = -EINVAL;
+ goto fail_cmd;
+ }
+ rc = wait_event_timeout(ac->cmd_wait,
+ (atomic_read(&ac->cmd_state) == 0), 5*HZ);
+ if (!rc) {
+ pr_err("timeout. waited for FORMAT_UPDATE\n");
+ goto fail_cmd;
+ }
+ return 0;
+fail_cmd:
+ return -EINVAL;
+}
+
void *q6asm_is_cpu_buf_avail(int dir, struct audio_client *ac, uint32_t *size,
uint32_t *index)
{
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 875bf47..2d52c43 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -34,7 +34,6 @@
#include <mach/memory.h>
#include <mach/debug_mm.h>
-#include <mach/peripheral-loader.h>
#include <mach/qdsp6v2/audio_acdb.h>
#include <mach/qdsp6v2/rtac.h>
#include <mach/msm_subsystem_map.h>
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index 4e41c80..338cfe3 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -83,6 +83,10 @@
static int32_t qdsp_cvs_callback(struct apr_client_data *data, void *priv);
static int32_t qdsp_cvp_callback(struct apr_client_data *data, void *priv);
+static int voice_send_set_widevoice_enable_cmd(struct voice_data *v);
+static int voice_send_set_pp_enable_cmd(struct voice_data *v,
+ uint32_t module_id, int enable);
+
static u16 voice_get_mvm_handle(struct voice_data *v)
{
if (v == NULL) {
@@ -764,6 +768,114 @@
return -EINVAL;
}
+static int voice_send_set_widevoice_enable_cmd(struct voice_data *v)
+{
+ struct mvm_set_widevoice_enable_cmd mvm_set_wv_cmd;
+ int ret = 0;
+ void *apr_mvm;
+ u16 mvm_handle;
+
+ if (v == NULL) {
+ pr_err("%s: v is NULL\n", __func__);
+ return -EINVAL;
+ }
+ apr_mvm = common.apr_q6_mvm;
+
+ if (!apr_mvm) {
+ pr_err("%s: apr_mvm is NULL.\n", __func__);
+ return -EINVAL;
+ }
+ mvm_handle = voice_get_mvm_handle(v);
+
+ mvm_set_wv_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE),
+ APR_PKT_VER);
+ mvm_set_wv_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
+ sizeof(mvm_set_wv_cmd) -
+ APR_HDR_SIZE);
+ mvm_set_wv_cmd.hdr.src_port = v->session_id;
+ mvm_set_wv_cmd.hdr.dest_port = mvm_handle;
+ mvm_set_wv_cmd.hdr.token = 0;
+ mvm_set_wv_cmd.hdr.opcode = VSS_IWIDEVOICE_CMD_SET_WIDEVOICE;
+
+ mvm_set_wv_cmd.vss_set_wv.enable = v->wv_enable;
+
+ v->mvm_state = CMD_STATUS_FAIL;
+ ret = apr_send_pkt(apr_mvm, (uint32_t *) &mvm_set_wv_cmd);
+ if (ret < 0) {
+ pr_err("Fail: sending mvm set widevoice enable,\n");
+ goto fail;
+ }
+ ret = wait_event_timeout(v->mvm_wait,
+ (v->mvm_state == CMD_STATUS_SUCCESS),
+ msecs_to_jiffies(TIMEOUT_MS));
+ if (!ret) {
+ pr_err("%s: wait_event timeout\n", __func__);
+ goto fail;
+ }
+ return 0;
+fail:
+ return -EINVAL;
+}
+
+static int voice_send_set_pp_enable_cmd(struct voice_data *v,
+ uint32_t module_id, int enable)
+{
+ struct cvs_set_pp_enable_cmd cvs_set_pp_cmd;
+ int ret = 0;
+ void *apr_cvs;
+ u16 cvs_handle;
+
+ if (v == NULL) {
+ pr_err("%s: v is NULL\n", __func__);
+ return -EINVAL;
+ }
+ apr_cvs = common.apr_q6_cvs;
+
+ if (!apr_cvs) {
+ pr_err("%s: apr_cvs is NULL.\n", __func__);
+ return -EINVAL;
+ }
+ cvs_handle = voice_get_cvs_handle(v);
+
+ cvs_set_pp_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE),
+ APR_PKT_VER);
+ cvs_set_pp_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
+ sizeof(cvs_set_pp_cmd) -
+ APR_HDR_SIZE);
+ cvs_set_pp_cmd.hdr.src_port = v->session_id;
+ cvs_set_pp_cmd.hdr.dest_port = cvs_handle;
+ cvs_set_pp_cmd.hdr.token = 0;
+ cvs_set_pp_cmd.hdr.opcode = VSS_ICOMMON_CMD_SET_UI_PROPERTY;
+
+ cvs_set_pp_cmd.vss_set_pp.module_id = module_id;
+ cvs_set_pp_cmd.vss_set_pp.param_id = VOICE_PARAM_MOD_ENABLE;
+ cvs_set_pp_cmd.vss_set_pp.param_size = MOD_ENABLE_PARAM_LEN;
+ cvs_set_pp_cmd.vss_set_pp.reserved = 0;
+ cvs_set_pp_cmd.vss_set_pp.enable = enable;
+ cvs_set_pp_cmd.vss_set_pp.reserved_field = 0;
+ pr_debug("voice_send_set_pp_enable_cmd, module_id=%d, enable=%d\n",
+ module_id, enable);
+
+ v->cvs_state = CMD_STATUS_FAIL;
+ ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_set_pp_cmd);
+ if (ret < 0) {
+ pr_err("Fail: sending cvs set pp enable,\n");
+ goto fail;
+ }
+ ret = wait_event_timeout(v->cvs_wait,
+ (v->cvs_state == CMD_STATUS_SUCCESS),
+ msecs_to_jiffies(TIMEOUT_MS));
+ if (!ret) {
+ pr_err("%s: wait_event timeout\n", __func__);
+ goto fail;
+ }
+ return 0;
+fail:
+ return -EINVAL;
+}
+
static int voice_set_dtx(struct voice_data *v)
{
int ret = 0;
@@ -2042,6 +2154,20 @@
voice_send_netid_timing_cmd(v);
}
+ /* enable widevoice if wv_enable is set */
+ if (v->wv_enable)
+ voice_send_set_widevoice_enable_cmd(v);
+
+ /* enable slowtalk if st_enable is set */
+ if (v->st_enable)
+ voice_send_set_pp_enable_cmd(v,
+ MODULE_ID_VOICE_MODULE_ST,
+ v->st_enable);
+
+ voice_send_set_pp_enable_cmd(v,
+ MODULE_ID_VOICE_MODULE_FENS,
+ v->fens_enable);
+
/* Start in-call music delivery if this feature is enabled */
if (v->music_info.play_enable)
voice_cvs_start_playback(v);
@@ -3207,6 +3333,22 @@
/* Send tty mode if tty device is used */
voice_send_tty_mode_cmd(v);
+ /* enable widevoice if wv_enable is set */
+ if (v->wv_enable)
+ voice_send_set_widevoice_enable_cmd(v);
+
+ /* enable slowtalk */
+ if (v->st_enable)
+ voice_send_set_pp_enable_cmd(v,
+ MODULE_ID_VOICE_MODULE_ST,
+ v->st_enable);
+
+ /* enable FENS */
+ if (v->fens_enable)
+ voice_send_set_pp_enable_cmd(v,
+ MODULE_ID_VOICE_MODULE_FENS,
+ v->fens_enable);
+
v->voc_state = VOC_RUN;
}
@@ -3370,7 +3512,8 @@
v->wv_enable = wv_enable;
mvm_handle = voice_get_mvm_handle(v);
-
+ if (mvm_handle != 0)
+ voice_send_set_widevoice_enable_cmd(v);
mutex_unlock(&v->lock);
@@ -3414,6 +3557,17 @@
else if (module_id == MODULE_ID_VOICE_MODULE_FENS)
v->fens_enable = enable;
+ if (v->voc_state == VOC_RUN) {
+ if (module_id == MODULE_ID_VOICE_MODULE_ST)
+ ret = voice_send_set_pp_enable_cmd(v,
+ MODULE_ID_VOICE_MODULE_ST,
+ enable);
+ else if (module_id == MODULE_ID_VOICE_MODULE_FENS)
+ ret = voice_send_set_pp_enable_cmd(v,
+ MODULE_ID_VOICE_MODULE_FENS,
+ enable);
+ }
+
mutex_unlock(&v->lock);
return ret;