Merge "arm/dt: msm8974: Disable Q6 MSS PIL device node for RUMI" into msm-3.4
diff --git a/Documentation/devicetree/bindings/crypto/msm/qcedev.txt b/Documentation/devicetree/bindings/crypto/msm/qcedev.txt
new file mode 100644
index 0000000..c50a6c3
--- /dev/null
+++ b/Documentation/devicetree/bindings/crypto/msm/qcedev.txt
@@ -0,0 +1,18 @@
+* QCEDEV (Qualcomm Crypto Engine Device)
+
+Required properties:
+ - compatible : should be "qcom,qcedev"
+ - reg : should contain crypto, BAM register map.
+ - interrupts : should contain crypto BAM interrupt.
+ - qcom,bam-pipe-pair : should contain crypto BAM pipe pair index.
+
+Example:
+
+ qcom,qcedev@fd440000 {
+ compatible = "qcom,qcedev";
+ reg = <0xfd440000 0x20000>,
+ <0xfd444000 0x8000>;
+ reg-names = "crypto-base","crypto-bam-base";
+ interrupts = <0 235 0>;
+ qcom,bam-pipe-pair = <0>;
+ };
diff --git a/Documentation/devicetree/bindings/crypto/msm/qcrypto.txt b/Documentation/devicetree/bindings/crypto/msm/qcrypto.txt
new file mode 100644
index 0000000..1b0f703
--- /dev/null
+++ b/Documentation/devicetree/bindings/crypto/msm/qcrypto.txt
@@ -0,0 +1,18 @@
+* QCRYPTO (Qualcomm Crypto)
+
+Required properties:
+ - compatible : should be "qcom,qcrypto"
+ - reg : should contain crypto, BAM register map.
+ - interrupts : should contain crypto BAM interrupt.
+ - qcom,bam-pipe-pair : should contain crypto BAM pipe pair.
+
+Example:
+
+ qcom,qcrypto@fd444000 {
+ compatible = "qcom,qcrypto";
+ reg = <0xfd440000 0x20000>,
+ <0xfd444000 0x8000>;
+ reg-names = "crypto-base","crypto-bam-base";
+ interrupts = <0 235 0>;
+ qcom,bam-pipe-pair = <1>;
+ };
diff --git a/Documentation/devicetree/bindings/iommu/msm_iommu.txt b/Documentation/devicetree/bindings/iommu/msm_iommu.txt
index 67933e7..c198fe9 100644
--- a/Documentation/devicetree/bindings/iommu/msm_iommu.txt
+++ b/Documentation/devicetree/bindings/iommu/msm_iommu.txt
@@ -13,12 +13,15 @@
- qcom,iommu-ctx-sids : List of stream identifiers associated with this
translation context.
- qcom,iommu-ctx-name : Name of the context bank
+ - qcom,iommu-smt-size : Number of SMR entries in the SMT of this HW block
+ - vdd-supply : vdd-supply: phandle to GDSC regulator controlling this IOMMU.
Example:
qcom,iommu@fda64000 {
compatible = "qcom,msm-smmu-v2";
reg = <0xfda64000 0x10000>;
+ vdd-supply = <&gdsc_iommu>;
qcom,iommu-ctx@fda6c000 {
reg = <0xfda6c000 0x1000>;
diff --git a/Documentation/devicetree/bindings/rtc/qpnp-rtc.txt b/Documentation/devicetree/bindings/rtc/qpnp-rtc.txt
new file mode 100644
index 0000000..156141f
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/qpnp-rtc.txt
@@ -0,0 +1,64 @@
+* msm-qpnp-rtc
+
+msm-qpnp-rtc is a RTC driver that supports 32 bit RTC housed inside PMIC.
+Driver utilizes MSM SPMI interface to communicate with the RTC module.
+RTC device is divided into two sub-peripherals one which controls basic RTC
+and other for controlling alarm.
+
+[PMIC RTC Device Declarations]
+
+-Root Node-
+
+Required properties :
+ - compatible: Must be "qcom,qpnp-rtc"
+ - #address-cells: The number of cells dedicated to represent an address
+ This must be set to '1'.
+ - #size-cells: The number of cells dedicated to represent address
+ space range of a peripheral. This must be set to '1'.
+ - spmi-dev-container: This specifies that all the device nodes specified
+ within this node should have their resources
+ coalesced into a single spmi_device.
+
+Optional properties:
+ - qcom,qpnp-rtc-write: This property enables/disables rtc write
+ operation. If not mentioned rtc driver keeps
+ rtc writes disabled.
+ 0 = Disable rtc writes.
+ 1 = Enable rtc writes.
+ - qcom,qpnp-rtc-alarm-pwrup: This property enables/disables feature of
+ powering up phone (from power down state)
+ through alarm interrupt.
+ If not mentioned rtc driver will disable
+ feature of powring-up phone through alarm.
+ 0 = Disable powering up of phone through
+ alarm interrupt.
+ 1 = Enable powering up of phone through
+ alarm interrupt.
+
+-Child Nodes-
+
+Required properties :
+ - reg : Specify the spmi offset and size for device.
+ - interrupts: Specifies alarm interrupt, only for rtc_alarm
+ sub-peripheral.
+
+Example:
+ qcom,pm8941_rtc {
+ spmi-dev-container;
+ compatible = "qcom,qpnp-rtc";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ qcom,qpnp-rtc-write = <0>;
+ qcom,qpnp-rtc-alarm-pwrup = <0>;
+
+ qcom,pm8941_rtc_rw@6000 {
+ reg = <0x6000 0x100>;
+ };
+
+ qcom,pm8941_rtc_alarm@6100 {
+ reg = <0x6100 0x100>;
+ interrupts = <0x0 0x61 0x1>;
+ };
+ };
+
+
diff --git a/Documentation/devicetree/bindings/thermal/tsens.txt b/Documentation/devicetree/bindings/thermal/tsens.txt
new file mode 100644
index 0000000..c683f58
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/tsens.txt
@@ -0,0 +1,42 @@
+Qualcomm's TSENS driver
+
+The TSENS driver supports reading temperature from sensors across
+the MSM. The driver defaults to support a 10 bit ADC.
+
+The driver uses the Thermal sysfs framework to provide thermal
+clients the ability to enable/disable the sensors, read trip zones,
+read cool/warm temperature thresholds, set temperature thresholds
+for cool/warm notification and receive notification on temperature
+threshold events.
+
+TSENS node
+
+Required properties:
+- compatible : should be "qcom,msm-tsens" for MSM8974 TSENS driver.
+- reg : offset and length of the TSENS registers.
+- reg : offset and length of the QFPROM registers used for storing
+ the calibration data for the individual sensors.
+- reg-names : resource names used for the physical address of the TSENS
+ registers and the QFPROM efuse calibration address.
+ Should be "tsens_physical" for physical address of the TSENS
+ and "tsens_eeprom_physical" for physical address where calibration
+ data is stored.
+- interrupts : TSENS interrupt for cool/warm temperature threshold.
+- qcom,sensors : Total number of available Temperature sensors for TSENS.
+- qcom,slope : One point calibration characterized slope data for each
+ sensor used to compute the offset. Slope is represented
+ as ADC code/DegC and the value is multipled by a factor
+ of 1000.
+
+Example:
+
+tsens@fc4a8000 {
+ compatible = "qcom,msm-tsens";
+ reg = <0xfc4a8000 0x2000>,
+ <0xfc4b80d0 0x5>;
+ reg-names = "tsens_physical", "tsens_eeprom_physical";
+ interrupts = <0 184 0>;
+ qcom,sensors = <11>;
+ qcom,slope = <1134 1122 1142 1123 1176 1176 1176 1186 1176
+ 1176>;
+};
diff --git a/arch/arm/boot/dts/msm-pm8841.dtsi b/arch/arm/boot/dts/msm-pm8841.dtsi
index a586a90..d84c8e0 100644
--- a/arch/arm/boot/dts/msm-pm8841.dtsi
+++ b/arch/arm/boot/dts/msm-pm8841.dtsi
@@ -10,218 +10,216 @@
* GNU General Public License for more details.
*/
-/ {
- qcom,spmi@fc4c0000 {
- #address-cells = <1>;
- #size-cells = <0>;
- interrupt-controller;
- #interrupt-cells = <3>;
+&spmi_bus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
- qcom,pm8841@4 {
- spmi-slave-container;
- reg = <0x4>;
+ qcom,pm8841@4 {
+ spmi-slave-container;
+ reg = <0x4>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ pm8841_mpps {
+ spmi-dev-container;
+ compatible = "qcom,qpnp-pin";
+ gpio-controller;
+ #gpio-cells = <2>;
#address-cells = <1>;
#size-cells = <1>;
+ label = "pm8841-mpp";
- pm8841_mpps {
- spmi-dev-container;
- compatible = "qcom,qpnp-pin";
- gpio-controller;
- #gpio-cells = <2>;
- #address-cells = <1>;
- #size-cells = <1>;
- label = "pm8841-mpp";
+ mpp@a000 {
+ reg = <0xa000 0x100>;
+ qcom,pin-num = <1>;
+ status = "disabled";
+ };
- mpp@a000 {
- reg = <0xa000 0x100>;
- qcom,pin-num = <1>;
- status = "disabled";
- };
+ mpp@a100 {
+ reg = <0xa100 0x100>;
+ qcom,pin-num = <2>;
+ status = "disabled";
+ };
- mpp@a100 {
- reg = <0xa100 0x100>;
- qcom,pin-num = <2>;
- status = "disabled";
- };
+ mpp@a200 {
+ reg = <0xa200 0x100>;
+ qcom,pin-num = <3>;
+ status = "disabled";
+ };
- mpp@a200 {
- reg = <0xa200 0x100>;
- qcom,pin-num = <3>;
- status = "disabled";
- };
+ mpp@a300 {
+ reg = <0xa300 0x100>;
+ qcom,pin-num = <4>;
+ status = "disabled";
+ };
+ };
+ };
- mpp@a300 {
- reg = <0xa300 0x100>;
- qcom,pin-num = <4>;
- status = "disabled";
- };
+ qcom,pm8841@5 {
+ spmi-slave-container;
+ reg = <0x5>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ regulator@1400 {
+ regulator-name = "8841_s1";
+ spmi-dev-container;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "qcom,qpnp-regulator";
+ reg = <0x1400 0x300>;
+ status = "disabled";
+
+ qcom,ctl@1400 {
+ reg = <0x1400 0x100>;
+ };
+ qcom,ps@1500 {
+ reg = <0x1500 0x100>;
+ };
+ qcom,freq@1600 {
+ reg = <0x1600 0x100>;
};
};
- qcom,pm8841@5 {
- spmi-slave-container;
- reg = <0x5>;
+ regulator@1700 {
+ regulator-name = "8841_s2";
+ spmi-dev-container;
#address-cells = <1>;
#size-cells = <1>;
+ compatible = "qcom,qpnp-regulator";
+ reg = <0x1700 0x300>;
+ status = "disabled";
- regulator@1400 {
- regulator-name = "8841_s1";
- spmi-dev-container;
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "qcom,qpnp-regulator";
- reg = <0x1400 0x300>;
- status = "disabled";
-
- qcom,ctl@1400 {
- reg = <0x1400 0x100>;
- };
- qcom,ps@1500 {
- reg = <0x1500 0x100>;
- };
- qcom,freq@1600 {
- reg = <0x1600 0x100>;
- };
+ qcom,ctl@1700 {
+ reg = <0x1700 0x100>;
};
-
- regulator@1700 {
- regulator-name = "8841_s2";
- spmi-dev-container;
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "qcom,qpnp-regulator";
- reg = <0x1700 0x300>;
- status = "disabled";
-
- qcom,ctl@1700 {
- reg = <0x1700 0x100>;
- };
- qcom,ps@1800 {
- reg = <0x1800 0x100>;
- };
- qcom,freq@1900 {
- reg = <0x1900 0x100>;
- };
+ qcom,ps@1800 {
+ reg = <0x1800 0x100>;
};
-
- regulator@1a00 {
- regulator-name = "8841_s3";
- spmi-dev-container;
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "qcom,qpnp-regulator";
- reg = <0x1a00 0x300>;
- status = "disabled";
-
- qcom,ctl@1a00 {
- reg = <0x1a00 0x100>;
- };
- qcom,ps@1b00 {
- reg = <0x1b00 0x100>;
- };
- qcom,freq@1c00 {
- reg = <0x1c00 0x100>;
- };
+ qcom,freq@1900 {
+ reg = <0x1900 0x100>;
};
+ };
- regulator@1d00 {
- regulator-name = "8841_s4";
- spmi-dev-container;
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "qcom,qpnp-regulator";
- reg = <0x1d00 0x300>;
- status = "disabled";
+ regulator@1a00 {
+ regulator-name = "8841_s3";
+ spmi-dev-container;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "qcom,qpnp-regulator";
+ reg = <0x1a00 0x300>;
+ status = "disabled";
- qcom,ctl@1d00 {
- reg = <0x1d00 0x100>;
- };
- qcom,ps@1e00 {
- reg = <0x1e00 0x100>;
- };
- qcom,freq@1f00 {
- reg = <0x1f00 0x100>;
- };
+ qcom,ctl@1a00 {
+ reg = <0x1a00 0x100>;
};
-
- regulator@2000 {
- regulator-name = "8841_s5";
- spmi-dev-container;
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "qcom,qpnp-regulator";
- reg = <0x2000 0x300>;
- status = "disabled";
-
- qcom,ctl@0 {
- reg = <0x2000 0x100>;
- };
- qcom,ps@100 {
- reg = <0x2100 0x100>;
- };
- qcom,freq@200 {
- reg = <0x2200 0x100>;
- };
+ qcom,ps@1b00 {
+ reg = <0x1b00 0x100>;
};
-
- regulator@2300 {
- regulator-name = "8841_s6";
- spmi-dev-container;
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "qcom,qpnp-regulator";
- reg = <0x2300 0x300>;
- status = "disabled";
-
- qcom,ctl@2300 {
- reg = <0x2300 0x100>;
- };
- qcom,ps@2400 {
- reg = <0x2400 0x100>;
- };
- qcom,freq@2500 {
- reg = <0x2500 0x100>;
- };
+ qcom,freq@1c00 {
+ reg = <0x1c00 0x100>;
};
+ };
- regulator@2600 {
- regulator-name = "8841_s7";
- spmi-dev-container;
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "qcom,qpnp-regulator";
- reg = <0x2600 0x300>;
- status = "disabled";
+ regulator@1d00 {
+ regulator-name = "8841_s4";
+ spmi-dev-container;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "qcom,qpnp-regulator";
+ reg = <0x1d00 0x300>;
+ status = "disabled";
- qcom,ctl@2600 {
- reg = <0x2600 0x100>;
- };
- qcom,ps@2700 {
- reg = <0x2700 0x100>;
- };
- qcom,freq@2800 {
- reg = <0x2800 0x100>;
- };
+ qcom,ctl@1d00 {
+ reg = <0x1d00 0x100>;
};
+ qcom,ps@1e00 {
+ reg = <0x1e00 0x100>;
+ };
+ qcom,freq@1f00 {
+ reg = <0x1f00 0x100>;
+ };
+ };
- regulator@2900 {
- regulator-name = "8841_s8";
- spmi-dev-container;
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "qcom,qpnp-regulator";
- reg = <0x2900 0x300>;
- status = "disabled";
+ regulator@2000 {
+ regulator-name = "8841_s5";
+ spmi-dev-container;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "qcom,qpnp-regulator";
+ reg = <0x2000 0x300>;
+ status = "disabled";
- qcom,ctl@2900 {
- reg = <0x2900 0x100>;
- };
- qcom,ps@2a000 {
- reg = <0x2a00 0x100>;
- };
- qcom,freq@2b00 {
- reg = <0x2b00 0x100>;
- };
+ qcom,ctl@0 {
+ reg = <0x2000 0x100>;
+ };
+ qcom,ps@100 {
+ reg = <0x2100 0x100>;
+ };
+ qcom,freq@200 {
+ reg = <0x2200 0x100>;
+ };
+ };
+
+ regulator@2300 {
+ regulator-name = "8841_s6";
+ spmi-dev-container;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "qcom,qpnp-regulator";
+ reg = <0x2300 0x300>;
+ status = "disabled";
+
+ qcom,ctl@2300 {
+ reg = <0x2300 0x100>;
+ };
+ qcom,ps@2400 {
+ reg = <0x2400 0x100>;
+ };
+ qcom,freq@2500 {
+ reg = <0x2500 0x100>;
+ };
+ };
+
+ regulator@2600 {
+ regulator-name = "8841_s7";
+ spmi-dev-container;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "qcom,qpnp-regulator";
+ reg = <0x2600 0x300>;
+ status = "disabled";
+
+ qcom,ctl@2600 {
+ reg = <0x2600 0x100>;
+ };
+ qcom,ps@2700 {
+ reg = <0x2700 0x100>;
+ };
+ qcom,freq@2800 {
+ reg = <0x2800 0x100>;
+ };
+ };
+
+ regulator@2900 {
+ regulator-name = "8841_s8";
+ spmi-dev-container;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "qcom,qpnp-regulator";
+ reg = <0x2900 0x300>;
+ status = "disabled";
+
+ qcom,ctl@2900 {
+ reg = <0x2900 0x100>;
+ };
+ qcom,ps@2a000 {
+ reg = <0x2a00 0x100>;
+ };
+ qcom,freq@2b00 {
+ reg = <0x2b00 0x100>;
};
};
};
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 2714d9e..87864fd 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -10,579 +10,577 @@
* GNU General Public License for more details.
*/
-/ {
- qcom,spmi@fc4c0000 {
- #address-cells = <1>;
- #size-cells = <0>;
- interrupt-controller;
- #interrupt-cells = <3>;
+&spmi_bus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
- qcom,pm8941@0 {
- spmi-slave-container;
- reg = <0x0>;
+ qcom,pm8941@0 {
+ spmi-slave-container;
+ reg = <0x0>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ pm8941_gpios {
+ spmi-dev-container;
+ compatible = "qcom,qpnp-pin";
+ gpio-controller;
+ #gpio-cells = <2>;
#address-cells = <1>;
#size-cells = <1>;
+ label = "pm8941-gpio";
- pm8941_gpios {
- spmi-dev-container;
- compatible = "qcom,qpnp-pin";
- gpio-controller;
- #gpio-cells = <2>;
- #address-cells = <1>;
- #size-cells = <1>;
- label = "pm8941-gpio";
-
- gpio@c000 {
- reg = <0xc000 0x100>;
- qcom,pin-num = <1>;
- status = "disabled";
- };
-
- gpio@c100 {
- reg = <0xc100 0x100>;
- qcom,pin-num = <2>;
- status = "disabled";
- };
-
- gpio@c200 {
- reg = <0xc200 0x100>;
- qcom,pin-num = <3>;
- status = "disabled";
- };
-
- gpio@c300 {
- reg = <0xc300 0x100>;
- qcom,pin-num = <4>;
- status = "disabled";
- };
-
- gpio@c400 {
- reg = <0xc400 0x100>;
- qcom,pin-num = <5>;
- status = "disabled";
- };
-
- gpio@c500 {
- reg = <0xc500 0x100>;
- qcom,pin-num = <6>;
- status = "disabled";
- };
-
- gpio@c600 {
- reg = <0xc600 0x100>;
- qcom,pin-num = <7>;
- status = "disabled";
- };
-
- gpio@c700 {
- reg = <0xc700 0x100>;
- qcom,pin-num = <8>;
- status = "disabled";
- };
-
- gpio@c800 {
- reg = <0xc800 0x100>;
- qcom,pin-num = <9>;
- status = "disabled";
- };
-
- gpio@c900 {
- reg = <0xc900 0x100>;
- qcom,pin-num = <10>;
- status = "disabled";
- };
-
- gpio@ca00 {
- reg = <0xca00 0x100>;
- qcom,pin-num = <11>;
- status = "disabled";
- };
-
- gpio@cb00 {
- reg = <0xcb00 0x100>;
- qcom,pin-num = <12>;
- status = "disabled";
- };
-
- gpio@cc00 {
- reg = <0xcc00 0x100>;
- qcom,pin-num = <13>;
- status = "disabled";
- };
-
- gpio@cd00 {
- reg = <0xcd00 0x100>;
- qcom,pin-num = <14>;
- status = "disabled";
- };
-
- gpio@ce00 {
- reg = <0xce00 0x100>;
- qcom,pin-num = <15>;
- status = "disabled";
- };
-
- gpio@cf00 {
- reg = <0xcf00 0x100>;
- qcom,pin-num = <16>;
- status = "disabled";
- };
-
- gpio@d000 {
- reg = <0xd000 0x100>;
- qcom,pin-num = <17>;
- status = "disabled";
- };
-
- gpio@d100 {
- reg = <0xd100 0x100>;
- qcom,pin-num = <18>;
- status = "disabled";
- };
-
- gpio@d200 {
- reg = <0xd200 0x100>;
- qcom,pin-num = <19>;
- status = "disabled";
- };
-
- gpio@d300 {
- reg = <0xd300 0x100>;
- qcom,pin-num = <20>;
- status = "disabled";
- };
-
- gpio@d400 {
- reg = <0xd400 0x100>;
- qcom,pin-num = <21>;
- status = "disabled";
- };
-
- gpio@d500 {
- reg = <0xd500 0x100>;
- qcom,pin-num = <22>;
- status = "disabled";
- };
-
- gpio@d600 {
- reg = <0xd600 0x100>;
- qcom,pin-num = <23>;
- status = "disabled";
- };
-
- gpio@d700 {
- reg = <0xd700 0x100>;
- qcom,pin-num = <24>;
- status = "disabled";
- };
-
- gpio@d800 {
- reg = <0xd800 0x100>;
- qcom,pin-num = <25>;
- status = "disabled";
- };
-
- gpio@d900 {
- reg = <0xd900 0x100>;
- qcom,pin-num = <26>;
- status = "disabled";
- };
-
- gpio@da00 {
- reg = <0xda00 0x100>;
- qcom,pin-num = <27>;
- status = "disabled";
- };
-
- gpio@db00 {
- reg = <0xdb00 0x100>;
- qcom,pin-num = <28>;
- status = "disabled";
- };
-
- gpio@dc00 {
- reg = <0xdc00 0x100>;
- qcom,pin-num = <29>;
- status = "disabled";
- };
-
- gpio@dd00 {
- reg = <0xdd00 0x100>;
- qcom,pin-num = <30>;
- status = "disabled";
- };
-
- gpio@de00 {
- reg = <0xde00 0x100>;
- qcom,pin-num = <31>;
- status = "disabled";
- };
-
- gpio@df00 {
- reg = <0xdf00 0x100>;
- qcom,pin-num = <32>;
- status = "disabled";
- };
-
- gpio@e000 {
- reg = <0xe000 0x100>;
- qcom,pin-num = <33>;
- status = "disabled";
- };
-
- gpio@e100 {
- reg = <0xe100 0x100>;
- qcom,pin-num = <34>;
- status = "disabled";
- };
-
- gpio@e200 {
- reg = <0xe200 0x100>;
- qcom,pin-num = <35>;
- status = "disabled";
- };
-
- gpio@e300 {
- reg = <0xe300 0x100>;
- qcom,pin-num = <36>;
- status = "disabled";
- };
+ gpio@c000 {
+ reg = <0xc000 0x100>;
+ qcom,pin-num = <1>;
+ status = "disabled";
};
- pm8941_mpps {
- spmi-dev-container;
- compatible = "qcom,qpnp-pin";
- gpio-controller;
- #gpio-cells = <2>;
- #address-cells = <1>;
- #size-cells = <1>;
- label = "pm8941-mpp";
+ gpio@c100 {
+ reg = <0xc100 0x100>;
+ qcom,pin-num = <2>;
+ status = "disabled";
+ };
- mpp@a000 {
- reg = <0xa000 0x100>;
- qcom,pin-num = <1>;
- status = "disabled";
- };
+ gpio@c200 {
+ reg = <0xc200 0x100>;
+ qcom,pin-num = <3>;
+ status = "disabled";
+ };
- mpp@a100 {
- reg = <0xa100 0x100>;
- qcom,pin-num = <2>;
- status = "disabled";
- };
+ gpio@c300 {
+ reg = <0xc300 0x100>;
+ qcom,pin-num = <4>;
+ status = "disabled";
+ };
- mpp@a200 {
- reg = <0xa200 0x100>;
- qcom,pin-num = <3>;
- status = "disabled";
- };
+ gpio@c400 {
+ reg = <0xc400 0x100>;
+ qcom,pin-num = <5>;
+ status = "disabled";
+ };
- mpp@a300 {
- reg = <0xa300 0x100>;
- qcom,pin-num = <4>;
- status = "disabled";
- };
+ gpio@c500 {
+ reg = <0xc500 0x100>;
+ qcom,pin-num = <6>;
+ status = "disabled";
+ };
- mpp@a400 {
- reg = <0xa400 0x100>;
- qcom,pin-num = <5>;
- status = "disabled";
- };
+ gpio@c600 {
+ reg = <0xc600 0x100>;
+ qcom,pin-num = <7>;
+ status = "disabled";
+ };
- mpp@a500 {
- reg = <0xa500 0x100>;
- qcom,pin-num = <6>;
- status = "disabled";
- };
+ gpio@c700 {
+ reg = <0xc700 0x100>;
+ qcom,pin-num = <8>;
+ status = "disabled";
+ };
- mpp@a600 {
- reg = <0xa600 0x100>;
- qcom,pin-num = <7>;
- status = "disabled";
- };
+ gpio@c800 {
+ reg = <0xc800 0x100>;
+ qcom,pin-num = <9>;
+ status = "disabled";
+ };
- mpp@a700 {
- reg = <0xa700 0x100>;
- qcom,pin-num = <8>;
- status = "disabled";
- };
+ gpio@c900 {
+ reg = <0xc900 0x100>;
+ qcom,pin-num = <10>;
+ status = "disabled";
+ };
+
+ gpio@ca00 {
+ reg = <0xca00 0x100>;
+ qcom,pin-num = <11>;
+ status = "disabled";
+ };
+
+ gpio@cb00 {
+ reg = <0xcb00 0x100>;
+ qcom,pin-num = <12>;
+ status = "disabled";
+ };
+
+ gpio@cc00 {
+ reg = <0xcc00 0x100>;
+ qcom,pin-num = <13>;
+ status = "disabled";
+ };
+
+ gpio@cd00 {
+ reg = <0xcd00 0x100>;
+ qcom,pin-num = <14>;
+ status = "disabled";
+ };
+
+ gpio@ce00 {
+ reg = <0xce00 0x100>;
+ qcom,pin-num = <15>;
+ status = "disabled";
+ };
+
+ gpio@cf00 {
+ reg = <0xcf00 0x100>;
+ qcom,pin-num = <16>;
+ status = "disabled";
+ };
+
+ gpio@d000 {
+ reg = <0xd000 0x100>;
+ qcom,pin-num = <17>;
+ status = "disabled";
+ };
+
+ gpio@d100 {
+ reg = <0xd100 0x100>;
+ qcom,pin-num = <18>;
+ status = "disabled";
+ };
+
+ gpio@d200 {
+ reg = <0xd200 0x100>;
+ qcom,pin-num = <19>;
+ status = "disabled";
+ };
+
+ gpio@d300 {
+ reg = <0xd300 0x100>;
+ qcom,pin-num = <20>;
+ status = "disabled";
+ };
+
+ gpio@d400 {
+ reg = <0xd400 0x100>;
+ qcom,pin-num = <21>;
+ status = "disabled";
+ };
+
+ gpio@d500 {
+ reg = <0xd500 0x100>;
+ qcom,pin-num = <22>;
+ status = "disabled";
+ };
+
+ gpio@d600 {
+ reg = <0xd600 0x100>;
+ qcom,pin-num = <23>;
+ status = "disabled";
+ };
+
+ gpio@d700 {
+ reg = <0xd700 0x100>;
+ qcom,pin-num = <24>;
+ status = "disabled";
+ };
+
+ gpio@d800 {
+ reg = <0xd800 0x100>;
+ qcom,pin-num = <25>;
+ status = "disabled";
+ };
+
+ gpio@d900 {
+ reg = <0xd900 0x100>;
+ qcom,pin-num = <26>;
+ status = "disabled";
+ };
+
+ gpio@da00 {
+ reg = <0xda00 0x100>;
+ qcom,pin-num = <27>;
+ status = "disabled";
+ };
+
+ gpio@db00 {
+ reg = <0xdb00 0x100>;
+ qcom,pin-num = <28>;
+ status = "disabled";
+ };
+
+ gpio@dc00 {
+ reg = <0xdc00 0x100>;
+ qcom,pin-num = <29>;
+ status = "disabled";
+ };
+
+ gpio@dd00 {
+ reg = <0xdd00 0x100>;
+ qcom,pin-num = <30>;
+ status = "disabled";
+ };
+
+ gpio@de00 {
+ reg = <0xde00 0x100>;
+ qcom,pin-num = <31>;
+ status = "disabled";
+ };
+
+ gpio@df00 {
+ reg = <0xdf00 0x100>;
+ qcom,pin-num = <32>;
+ status = "disabled";
+ };
+
+ gpio@e000 {
+ reg = <0xe000 0x100>;
+ qcom,pin-num = <33>;
+ status = "disabled";
+ };
+
+ gpio@e100 {
+ reg = <0xe100 0x100>;
+ qcom,pin-num = <34>;
+ status = "disabled";
+ };
+
+ gpio@e200 {
+ reg = <0xe200 0x100>;
+ qcom,pin-num = <35>;
+ status = "disabled";
+ };
+
+ gpio@e300 {
+ reg = <0xe300 0x100>;
+ qcom,pin-num = <36>;
+ status = "disabled";
};
};
- qcom,pm8941@1 {
- spmi-slave-container;
- reg = <0x1>;
+ pm8941_mpps {
+ spmi-dev-container;
+ compatible = "qcom,qpnp-pin";
+ gpio-controller;
+ #gpio-cells = <2>;
#address-cells = <1>;
#size-cells = <1>;
+ label = "pm8941-mpp";
- regulator@1400 {
- regulator-name = "8941_s1";
- spmi-dev-container;
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "qcom,qpnp-regulator";
- reg = <0x1400 0x300>;
- status = "disabled";
-
- qcom,ctl@1400 {
- reg = <0x1400 0x100>;
- };
- qcom,ps@1500 {
- reg = <0x1500 0x100>;
- };
- qcom,freq@1600 {
- reg = <0x1600 0x100>;
- };
- };
-
- regulator@1700 {
- regulator-name = "8941_s2";
- spmi-dev-container;
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "qcom,qpnp-regulator";
- reg = <0x1700 0x300>;
- status = "disabled";
-
- qcom,ctl@1700 {
- reg = <0x1700 0x100>;
- };
- qcom,ps@1800 {
- reg = <0x1800 0x100>;
- };
- qcom,freq@1900 {
- reg = <0x1900 0x100>;
- };
- };
-
- regulator@1a00 {
- regulator-name = "8941_s3";
- spmi-dev-container;
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "qcom,qpnp-regulator";
- reg = <0x1400 0x300>;
- status = "disabled";
-
- qcom,ctl@1a00 {
- reg = <0x1a00 0x100>;
- };
- qcom,ps@1b00 {
- reg = <0x1b00 0x100>;
- };
- qcom,freq@1c00 {
- reg = <0x1c00 0x100>;
- };
- };
-
- regulator@a000 {
- regulator-name = "8941_boost";
+ mpp@a000 {
reg = <0xa000 0x100>;
- compatible = "qcom,qpnp-regulator";
+ qcom,pin-num = <1>;
status = "disabled";
};
- regulator@4000 {
- regulator-name = "8941_l1";
- reg = <0x4000 0x100>;
- compatible = "qcom,qpnp-regulator";
+ mpp@a100 {
+ reg = <0xa100 0x100>;
+ qcom,pin-num = <2>;
status = "disabled";
};
- regulator@4100 {
- regulator-name = "8941_l2";
- reg = <0x4100 0x100>;
- compatible = "qcom,qpnp-regulator";
+ mpp@a200 {
+ reg = <0xa200 0x100>;
+ qcom,pin-num = <3>;
status = "disabled";
};
- regulator@4200 {
- regulator-name = "8941_l3";
- reg = <0x4200 0x100>;
- compatible = "qcom,qpnp-regulator";
+ mpp@a300 {
+ reg = <0xa300 0x100>;
+ qcom,pin-num = <4>;
status = "disabled";
};
- regulator@4300 {
- regulator-name = "8941_l4";
- reg = <0x4300 0x100>;
- compatible = "qcom,qpnp-regulator";
+ mpp@a400 {
+ reg = <0xa400 0x100>;
+ qcom,pin-num = <5>;
status = "disabled";
};
- regulator@4400 {
- regulator-name = "8941_l5";
- reg = <0x4400 0x100>;
- compatible = "qcom,qpnp-regulator";
+ mpp@a500 {
+ reg = <0xa500 0x100>;
+ qcom,pin-num = <6>;
status = "disabled";
};
- regulator@4500 {
- regulator-name = "8941_l6";
- reg = <0x4500 0x100>;
- compatible = "qcom,qpnp-regulator";
+ mpp@a600 {
+ reg = <0xa600 0x100>;
+ qcom,pin-num = <7>;
status = "disabled";
};
- regulator@4600 {
- regulator-name = "8941_l7";
- reg = <0x4600 0x100>;
- compatible = "qcom,qpnp-regulator";
+ mpp@a700 {
+ reg = <0xa700 0x100>;
+ qcom,pin-num = <8>;
status = "disabled";
};
+ };
+ };
- regulator@4700 {
- regulator-name = "8941_l8";
- reg = <0x4700 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
+ qcom,pm8941@1 {
+ spmi-slave-container;
+ reg = <0x1>;
+ #address-cells = <1>;
+ #size-cells = <1>;
- regulator@4800 {
- regulator-name = "8941_l9";
- reg = <0x4800 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
+ regulator@1400 {
+ regulator-name = "8941_s1";
+ spmi-dev-container;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "qcom,qpnp-regulator";
+ reg = <0x1400 0x300>;
+ status = "disabled";
- regulator@4900 {
- regulator-name = "8941_l10";
- reg = <0x4900 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
+ qcom,ctl@1400 {
+ reg = <0x1400 0x100>;
};
+ qcom,ps@1500 {
+ reg = <0x1500 0x100>;
+ };
+ qcom,freq@1600 {
+ reg = <0x1600 0x100>;
+ };
+ };
- regulator@4a00 {
- regulator-name = "8941_l11";
- reg = <0x4a00 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
+ regulator@1700 {
+ regulator-name = "8941_s2";
+ spmi-dev-container;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "qcom,qpnp-regulator";
+ reg = <0x1700 0x300>;
+ status = "disabled";
- regulator@4b00 {
- regulator-name = "8941_l12";
- reg = <0x4b00 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
+ qcom,ctl@1700 {
+ reg = <0x1700 0x100>;
};
+ qcom,ps@1800 {
+ reg = <0x1800 0x100>;
+ };
+ qcom,freq@1900 {
+ reg = <0x1900 0x100>;
+ };
+ };
- regulator@4c00 {
- regulator-name = "8941_l13";
- reg = <0x4c00 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
+ regulator@1a00 {
+ regulator-name = "8941_s3";
+ spmi-dev-container;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "qcom,qpnp-regulator";
+ reg = <0x1400 0x300>;
+ status = "disabled";
- regulator@4d00 {
- regulator-name = "8941_l14";
- reg = <0x4d00 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
+ qcom,ctl@1a00 {
+ reg = <0x1a00 0x100>;
};
+ qcom,ps@1b00 {
+ reg = <0x1b00 0x100>;
+ };
+ qcom,freq@1c00 {
+ reg = <0x1c00 0x100>;
+ };
+ };
- regulator@4e00 {
- regulator-name = "8941_l15";
- reg = <0x4e00 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
+ regulator@a000 {
+ regulator-name = "8941_boost";
+ reg = <0xa000 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
- regulator@4f00 {
- regulator-name = "8941_l16";
- reg = <0x4f00 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
+ regulator@4000 {
+ regulator-name = "8941_l1";
+ reg = <0x4000 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
- regulator@5000 {
- regulator-name = "8941_l17";
- reg = <0x5000 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
+ regulator@4100 {
+ regulator-name = "8941_l2";
+ reg = <0x4100 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
- regulator@5100 {
- regulator-name = "8941_l18";
- reg = <0x5100 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
+ regulator@4200 {
+ regulator-name = "8941_l3";
+ reg = <0x4200 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
- regulator@5200 {
- regulator-name = "8941_l19";
- reg = <0x5200 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
+ regulator@4300 {
+ regulator-name = "8941_l4";
+ reg = <0x4300 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
- regulator@5300 {
- regulator-name = "8941_l20";
- reg = <0x5300 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
+ regulator@4400 {
+ regulator-name = "8941_l5";
+ reg = <0x4400 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
- regulator@5400 {
- regulator-name = "8941_l21";
- reg = <0x5400 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
+ regulator@4500 {
+ regulator-name = "8941_l6";
+ reg = <0x4500 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
- regulator@5500 {
- regulator-name = "8941_l22";
- reg = <0x5500 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
+ regulator@4600 {
+ regulator-name = "8941_l7";
+ reg = <0x4600 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
- regulator@5600 {
- regulator-name = "8941_l23";
- reg = <0x5600 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
+ regulator@4700 {
+ regulator-name = "8941_l8";
+ reg = <0x4700 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
- regulator@5700 {
- regulator-name = "8941_l24";
- reg = <0x5700 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
+ regulator@4800 {
+ regulator-name = "8941_l9";
+ reg = <0x4800 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
- regulator@8000 {
- regulator-name = "8941_lvs1";
- reg = <0x8000 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
+ regulator@4900 {
+ regulator-name = "8941_l10";
+ reg = <0x4900 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
- regulator@8100 {
- regulator-name = "8941_lvs2";
- reg = <0x8100 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
+ regulator@4a00 {
+ regulator-name = "8941_l11";
+ reg = <0x4a00 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
- regulator@8200 {
- regulator-name = "8941_lvs3";
- reg = <0x8200 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
+ regulator@4b00 {
+ regulator-name = "8941_l12";
+ reg = <0x4b00 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
- regulator@8300 {
- regulator-name = "8941_mvs1";
- reg = <0x8300 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
+ regulator@4c00 {
+ regulator-name = "8941_l13";
+ reg = <0x4c00 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
- regulator@8400 {
- regulator-name = "8941_mvs2";
- reg = <0x8400 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
+ regulator@4d00 {
+ regulator-name = "8941_l14";
+ reg = <0x4d00 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@4e00 {
+ regulator-name = "8941_l15";
+ reg = <0x4e00 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@4f00 {
+ regulator-name = "8941_l16";
+ reg = <0x4f00 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@5000 {
+ regulator-name = "8941_l17";
+ reg = <0x5000 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@5100 {
+ regulator-name = "8941_l18";
+ reg = <0x5100 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@5200 {
+ regulator-name = "8941_l19";
+ reg = <0x5200 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@5300 {
+ regulator-name = "8941_l20";
+ reg = <0x5300 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@5400 {
+ regulator-name = "8941_l21";
+ reg = <0x5400 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@5500 {
+ regulator-name = "8941_l22";
+ reg = <0x5500 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@5600 {
+ regulator-name = "8941_l23";
+ reg = <0x5600 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@5700 {
+ regulator-name = "8941_l24";
+ reg = <0x5700 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@8000 {
+ regulator-name = "8941_lvs1";
+ reg = <0x8000 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@8100 {
+ regulator-name = "8941_lvs2";
+ reg = <0x8100 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@8200 {
+ regulator-name = "8941_lvs3";
+ reg = <0x8200 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@8300 {
+ regulator-name = "8941_mvs1";
+ reg = <0x8300 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@8400 {
+ regulator-name = "8941_mvs2";
+ reg = <0x8400 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
};
};
};
diff --git a/arch/arm/boot/dts/msm-pm8x41-rpm-regulator.dtsi b/arch/arm/boot/dts/msm-pm8x41-rpm-regulator.dtsi
index 019112a..aced482 100644
--- a/arch/arm/boot/dts/msm-pm8x41-rpm-regulator.dtsi
+++ b/arch/arm/boot/dts/msm-pm8x41-rpm-regulator.dtsi
@@ -10,578 +10,576 @@
* GNU General Public License for more details.
*/
-/ {
- qcom,rpm-smd {
- rpm-regulator-smpb1 {
- qcom,resource-name = "smpb";
- qcom,resource-id = <1>;
- qcom,regulator-type = <1>;
- qcom,hpm-min-load = <100000>;
- compatible = "qcom,rpm-regulator-smd-resource";
- status = "disabled";
+&rpm_bus {
+ rpm-regulator-smpb1 {
+ qcom,resource-name = "smpb";
+ qcom,resource-id = <1>;
+ qcom,regulator-type = <1>;
+ qcom,hpm-min-load = <100000>;
+ compatible = "qcom,rpm-regulator-smd-resource";
+ status = "disabled";
- regulator-s1 {
- regulator-name = "8841_s1";
- qcom,set = <3>;
- status = "disabled";
- compatible = "qcom,rpm-regulator-smd";
- };
+ regulator-s1 {
+ regulator-name = "8841_s1";
+ qcom,set = <3>;
+ status = "disabled";
+ compatible = "qcom,rpm-regulator-smd";
};
+ };
- rpm-regulator-smpb2 {
- qcom,resource-name = "smpb";
- qcom,resource-id = <2>;
- qcom,regulator-type = <1>;
- qcom,hpm-min-load = <100000>;
- compatible = "qcom,rpm-regulator-smd-resource";
+ rpm-regulator-smpb2 {
+ qcom,resource-name = "smpb";
+ qcom,resource-id = <2>;
+ qcom,regulator-type = <1>;
+ qcom,hpm-min-load = <100000>;
+ compatible = "qcom,rpm-regulator-smd-resource";
+ status = "disabled";
+
+ regulator-s2 {
+ regulator-name = "8841_s2";
+ qcom,set = <3>;
status = "disabled";
-
- regulator-s2 {
- regulator-name = "8841_s2";
- qcom,set = <3>;
- status = "disabled";
- compatible = "qcom,rpm-regulator-smd";
- };
+ compatible = "qcom,rpm-regulator-smd";
};
+ };
- rpm-regulator-smpb3 {
- qcom,resource-name = "smpb";
- qcom,resource-id = <3>;
- qcom,regulator-type = <1>;
- qcom,hpm-min-load = <100000>;
- compatible = "qcom,rpm-regulator-smd-resource";
+ rpm-regulator-smpb3 {
+ qcom,resource-name = "smpb";
+ qcom,resource-id = <3>;
+ qcom,regulator-type = <1>;
+ qcom,hpm-min-load = <100000>;
+ compatible = "qcom,rpm-regulator-smd-resource";
+ status = "disabled";
+
+ regulator-s3 {
+ regulator-name = "8841_s3";
+ qcom,set = <3>;
status = "disabled";
-
- regulator-s3 {
- regulator-name = "8841_s3";
- qcom,set = <3>;
- status = "disabled";
- compatible = "qcom,rpm-regulator-smd";
- };
+ compatible = "qcom,rpm-regulator-smd";
};
+ };
- rpm-regulator-smpb4 {
- qcom,resource-name = "smpb";
- qcom,resource-id = <4>;
- qcom,regulator-type = <1>;
- qcom,hpm-min-load = <100000>;
- compatible = "qcom,rpm-regulator-smd-resource";
+ rpm-regulator-smpb4 {
+ qcom,resource-name = "smpb";
+ qcom,resource-id = <4>;
+ qcom,regulator-type = <1>;
+ qcom,hpm-min-load = <100000>;
+ compatible = "qcom,rpm-regulator-smd-resource";
+ status = "disabled";
+
+ regulator-s4 {
+ regulator-name = "8841_s4";
+ qcom,set = <3>;
status = "disabled";
-
- regulator-s4 {
- regulator-name = "8841_s4";
- qcom,set = <3>;
- status = "disabled";
- compatible = "qcom,rpm-regulator-smd";
- };
+ compatible = "qcom,rpm-regulator-smd";
};
+ };
- rpm-regulator-smpa1 {
- qcom,resource-name = "smpa";
- qcom,resource-id = <1>;
- qcom,regulator-type = <1>;
- qcom,hpm-min-load = <100000>;
- compatible = "qcom,rpm-regulator-smd-resource";
+ rpm-regulator-smpa1 {
+ qcom,resource-name = "smpa";
+ qcom,resource-id = <1>;
+ qcom,regulator-type = <1>;
+ qcom,hpm-min-load = <100000>;
+ compatible = "qcom,rpm-regulator-smd-resource";
+ status = "disabled";
+
+ regulator-s1 {
+ regulator-name = "8941_s1";
+ qcom,set = <3>;
status = "disabled";
-
- regulator-s1 {
- regulator-name = "8941_s1";
- qcom,set = <3>;
- status = "disabled";
- compatible = "qcom,rpm-regulator-smd";
- };
+ compatible = "qcom,rpm-regulator-smd";
};
+ };
- rpm-regulator-smpa2 {
- qcom,resource-name = "smpa";
- qcom,resource-id = <2>;
- qcom,regulator-type = <1>;
- qcom,hpm-min-load = <100000>;
- compatible = "qcom,rpm-regulator-smd-resource";
+ rpm-regulator-smpa2 {
+ qcom,resource-name = "smpa";
+ qcom,resource-id = <2>;
+ qcom,regulator-type = <1>;
+ qcom,hpm-min-load = <100000>;
+ compatible = "qcom,rpm-regulator-smd-resource";
+ status = "disabled";
+
+ regulator-s2 {
+ regulator-name = "8941_s2";
+ qcom,set = <3>;
status = "disabled";
-
- regulator-s2 {
- regulator-name = "8941_s2";
- qcom,set = <3>;
- status = "disabled";
- compatible = "qcom,rpm-regulator-smd";
- };
+ compatible = "qcom,rpm-regulator-smd";
};
+ };
- rpm-regulator-smpa3 {
- qcom,resource-name = "smpa";
- qcom,resource-id = <3>;
- qcom,regulator-type = <1>;
- qcom,hpm-min-load = <100000>;
- compatible = "qcom,rpm-regulator-smd-resource";
+ rpm-regulator-smpa3 {
+ qcom,resource-name = "smpa";
+ qcom,resource-id = <3>;
+ qcom,regulator-type = <1>;
+ qcom,hpm-min-load = <100000>;
+ compatible = "qcom,rpm-regulator-smd-resource";
+ status = "disabled";
+
+ regulator-s3 {
+ regulator-name = "8941_s3";
+ qcom,set = <3>;
status = "disabled";
-
- regulator-s3 {
- regulator-name = "8941_s3";
- qcom,set = <3>;
- status = "disabled";
- compatible = "qcom,rpm-regulator-smd";
- };
+ compatible = "qcom,rpm-regulator-smd";
};
+ };
- rpm-regulator-ldoa1 {
- qcom,resource-name = "ldoa";
- qcom,resource-id = <1>;
- qcom,regulator-type = <0>;
- qcom,hpm-min-load = <10000>;
- compatible = "qcom,rpm-regulator-smd-resource";
+ rpm-regulator-ldoa1 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <1>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ compatible = "qcom,rpm-regulator-smd-resource";
+ status = "disabled";
+
+ regulator-l1 {
+ regulator-name = "8941_l1";
+ qcom,set = <3>;
status = "disabled";
-
- regulator-l1 {
- regulator-name = "8941_l1";
- qcom,set = <3>;
- status = "disabled";
- compatible = "qcom,rpm-regulator-smd";
- };
+ compatible = "qcom,rpm-regulator-smd";
};
+ };
- rpm-regulator-ldoa2 {
- qcom,resource-name = "ldoa";
- qcom,resource-id = <2>;
- qcom,regulator-type = <0>;
- qcom,hpm-min-load = <10000>;
- compatible = "qcom,rpm-regulator-smd-resource";
+ rpm-regulator-ldoa2 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <2>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ compatible = "qcom,rpm-regulator-smd-resource";
+ status = "disabled";
+
+ regulator-l2 {
+ regulator-name = "8941_l2";
+ qcom,set = <3>;
status = "disabled";
-
- regulator-l2 {
- regulator-name = "8941_l2";
- qcom,set = <3>;
- status = "disabled";
- compatible = "qcom,rpm-regulator-smd";
- };
+ compatible = "qcom,rpm-regulator-smd";
};
+ };
- rpm-regulator-ldoa3 {
- qcom,resource-name = "ldoa";
- qcom,resource-id = <3>;
- qcom,regulator-type = <0>;
- qcom,hpm-min-load = <10000>;
- compatible = "qcom,rpm-regulator-smd-resource";
+ rpm-regulator-ldoa3 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <3>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ compatible = "qcom,rpm-regulator-smd-resource";
+ status = "disabled";
+
+ regulator-l3 {
+ regulator-name = "8941_l3";
+ qcom,set = <3>;
status = "disabled";
-
- regulator-l3 {
- regulator-name = "8941_l3";
- qcom,set = <3>;
- status = "disabled";
- compatible = "qcom,rpm-regulator-smd";
- };
+ compatible = "qcom,rpm-regulator-smd";
};
+ };
- rpm-regulator-ldoa4 {
- qcom,resource-name = "ldoa";
- qcom,resource-id = <4>;
- qcom,regulator-type = <0>;
- qcom,hpm-min-load = <10000>;
- compatible = "qcom,rpm-regulator-smd-resource";
+ rpm-regulator-ldoa4 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <4>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ compatible = "qcom,rpm-regulator-smd-resource";
+ status = "disabled";
+
+ regulator-l4 {
+ regulator-name = "8941_l4";
+ qcom,set = <3>;
status = "disabled";
-
- regulator-l4 {
- regulator-name = "8941_l4";
- qcom,set = <3>;
- status = "disabled";
- compatible = "qcom,rpm-regulator-smd";
- };
+ compatible = "qcom,rpm-regulator-smd";
};
+ };
- rpm-regulator-ldoa5 {
- qcom,resource-name = "ldoa";
- qcom,resource-id = <5>;
- qcom,regulator-type = <0>;
- qcom,hpm-min-load = <10000>;
- compatible = "qcom,rpm-regulator-smd-resource";
+ rpm-regulator-ldoa5 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <5>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ compatible = "qcom,rpm-regulator-smd-resource";
+ status = "disabled";
+
+ regulator-l5 {
+ regulator-name = "8941_l5";
+ qcom,set = <3>;
status = "disabled";
-
- regulator-l5 {
- regulator-name = "8941_l5";
- qcom,set = <3>;
- status = "disabled";
- compatible = "qcom,rpm-regulator-smd";
- };
+ compatible = "qcom,rpm-regulator-smd";
};
+ };
- rpm-regulator-ldoa6 {
- qcom,resource-name = "ldoa";
- qcom,resource-id = <6>;
- qcom,regulator-type = <0>;
- qcom,hpm-min-load = <10000>;
- compatible = "qcom,rpm-regulator-smd-resource";
+ rpm-regulator-ldoa6 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <6>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ compatible = "qcom,rpm-regulator-smd-resource";
+ status = "disabled";
+
+ regulator-l6 {
+ regulator-name = "8941_l6";
+ qcom,set = <3>;
status = "disabled";
-
- regulator-l6 {
- regulator-name = "8941_l6";
- qcom,set = <3>;
- status = "disabled";
- compatible = "qcom,rpm-regulator-smd";
- };
+ compatible = "qcom,rpm-regulator-smd";
};
+ };
- rpm-regulator-ldoa7 {
- qcom,resource-name = "ldoa";
- qcom,resource-id = <7>;
- qcom,regulator-type = <0>;
- qcom,hpm-min-load = <10000>;
- compatible = "qcom,rpm-regulator-smd-resource";
+ rpm-regulator-ldoa7 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <7>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ compatible = "qcom,rpm-regulator-smd-resource";
+ status = "disabled";
+
+ regulator-l7 {
+ regulator-name = "8941_l7";
+ qcom,set = <3>;
status = "disabled";
-
- regulator-l7 {
- regulator-name = "8941_l7";
- qcom,set = <3>;
- status = "disabled";
- compatible = "qcom,rpm-regulator-smd";
- };
+ compatible = "qcom,rpm-regulator-smd";
};
+ };
- rpm-regulator-ldoa8 {
- qcom,resource-name = "ldoa";
- qcom,resource-id = <8>;
- qcom,regulator-type = <0>;
- qcom,hpm-min-load = <10000>;
- compatible = "qcom,rpm-regulator-smd-resource";
+ rpm-regulator-ldoa8 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <8>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ compatible = "qcom,rpm-regulator-smd-resource";
+ status = "disabled";
+
+ regulator-l8 {
+ regulator-name = "8941_l8";
+ qcom,set = <3>;
status = "disabled";
-
- regulator-l8 {
- regulator-name = "8941_l8";
- qcom,set = <3>;
- status = "disabled";
- compatible = "qcom,rpm-regulator-smd";
- };
+ compatible = "qcom,rpm-regulator-smd";
};
+ };
- rpm-regulator-ldoa9 {
- qcom,resource-name = "ldoa";
- qcom,resource-id = <9>;
- qcom,regulator-type = <0>;
- qcom,hpm-min-load = <10000>;
- compatible = "qcom,rpm-regulator-smd-resource";
+ rpm-regulator-ldoa9 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <9>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ compatible = "qcom,rpm-regulator-smd-resource";
+ status = "disabled";
+
+ regulator-l9 {
+ regulator-name = "8941_l9";
+ qcom,set = <3>;
status = "disabled";
-
- regulator-l9 {
- regulator-name = "8941_l9";
- qcom,set = <3>;
- status = "disabled";
- compatible = "qcom,rpm-regulator-smd";
- };
+ compatible = "qcom,rpm-regulator-smd";
};
+ };
- rpm-regulator-ldoa10 {
- qcom,resource-name = "ldoa";
- qcom,resource-id = <10>;
- qcom,regulator-type = <0>;
- qcom,hpm-min-load = <10000>;
- compatible = "qcom,rpm-regulator-smd-resource";
+ rpm-regulator-ldoa10 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <10>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ compatible = "qcom,rpm-regulator-smd-resource";
+ status = "disabled";
+
+ regulator-l10 {
+ regulator-name = "8941_l10";
+ qcom,set = <3>;
status = "disabled";
-
- regulator-l10 {
- regulator-name = "8941_l10";
- qcom,set = <3>;
- status = "disabled";
- compatible = "qcom,rpm-regulator-smd";
- };
+ compatible = "qcom,rpm-regulator-smd";
};
+ };
- rpm-regulator-ldoa11 {
- qcom,resource-name = "ldoa";
- qcom,resource-id = <11>;
- qcom,regulator-type = <0>;
- qcom,hpm-min-load = <10000>;
- compatible = "qcom,rpm-regulator-smd-resource";
+ rpm-regulator-ldoa11 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <11>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ compatible = "qcom,rpm-regulator-smd-resource";
+ status = "disabled";
+
+ regulator-l11 {
+ regulator-name = "8941_l11";
+ qcom,set = <3>;
status = "disabled";
-
- regulator-l11 {
- regulator-name = "8941_l11";
- qcom,set = <3>;
- status = "disabled";
- compatible = "qcom,rpm-regulator-smd";
- };
+ compatible = "qcom,rpm-regulator-smd";
};
+ };
- rpm-regulator-ldoa12 {
- qcom,resource-name = "ldoa";
- qcom,resource-id = <12>;
- qcom,regulator-type = <0>;
- qcom,hpm-min-load = <10000>;
- compatible = "qcom,rpm-regulator-smd-resource";
+ rpm-regulator-ldoa12 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <12>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ compatible = "qcom,rpm-regulator-smd-resource";
+ status = "disabled";
+
+ regulator-l12 {
+ regulator-name = "8941_l12";
+ qcom,set = <3>;
status = "disabled";
-
- regulator-l12 {
- regulator-name = "8941_l12";
- qcom,set = <3>;
- status = "disabled";
- compatible = "qcom,rpm-regulator-smd";
- };
+ compatible = "qcom,rpm-regulator-smd";
};
+ };
- rpm-regulator-ldoa13 {
- qcom,resource-name = "ldoa";
- qcom,resource-id = <13>;
- qcom,regulator-type = <0>;
- qcom,hpm-min-load = <10000>;
- compatible = "qcom,rpm-regulator-smd-resource";
+ rpm-regulator-ldoa13 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <13>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ compatible = "qcom,rpm-regulator-smd-resource";
+ status = "disabled";
+
+ regulator-l13 {
+ regulator-name = "8941_l13";
+ qcom,set = <3>;
status = "disabled";
-
- regulator-l13 {
- regulator-name = "8941_l13";
- qcom,set = <3>;
- status = "disabled";
- compatible = "qcom,rpm-regulator-smd";
- };
+ compatible = "qcom,rpm-regulator-smd";
};
+ };
- rpm-regulator-ldoa14 {
- qcom,resource-name = "ldoa";
- qcom,resource-id = <14>;
- qcom,regulator-type = <0>;
- qcom,hpm-min-load = <10000>;
- compatible = "qcom,rpm-regulator-smd-resource";
+ rpm-regulator-ldoa14 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <14>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ compatible = "qcom,rpm-regulator-smd-resource";
+ status = "disabled";
+
+ regulator-l14 {
+ regulator-name = "8941_l14";
+ qcom,set = <3>;
status = "disabled";
-
- regulator-l14 {
- regulator-name = "8941_l14";
- qcom,set = <3>;
- status = "disabled";
- compatible = "qcom,rpm-regulator-smd";
- };
+ compatible = "qcom,rpm-regulator-smd";
};
+ };
- rpm-regulator-ldoa15 {
- qcom,resource-name = "ldoa";
- qcom,resource-id = <15>;
- qcom,regulator-type = <0>;
- qcom,hpm-min-load = <10000>;
- compatible = "qcom,rpm-regulator-smd-resource";
+ rpm-regulator-ldoa15 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <15>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ compatible = "qcom,rpm-regulator-smd-resource";
+ status = "disabled";
+
+ regulator-l15 {
+ regulator-name = "8941_l15";
+ qcom,set = <3>;
status = "disabled";
-
- regulator-l15 {
- regulator-name = "8941_l15";
- qcom,set = <3>;
- status = "disabled";
- compatible = "qcom,rpm-regulator-smd";
- };
+ compatible = "qcom,rpm-regulator-smd";
};
+ };
- rpm-regulator-ldoa16 {
- qcom,resource-name = "ldoa";
- qcom,resource-id = <16>;
- qcom,regulator-type = <0>;
- qcom,hpm-min-load = <10000>;
- compatible = "qcom,rpm-regulator-smd-resource";
+ rpm-regulator-ldoa16 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <16>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ compatible = "qcom,rpm-regulator-smd-resource";
+ status = "disabled";
+
+ regulator-l16 {
+ regulator-name = "8941_l16";
+ qcom,set = <3>;
status = "disabled";
-
- regulator-l16 {
- regulator-name = "8941_l16";
- qcom,set = <3>;
- status = "disabled";
- compatible = "qcom,rpm-regulator-smd";
- };
+ compatible = "qcom,rpm-regulator-smd";
};
+ };
- rpm-regulator-ldoa17 {
- qcom,resource-name = "ldoa";
- qcom,resource-id = <17>;
- qcom,regulator-type = <0>;
- qcom,hpm-min-load = <10000>;
- compatible = "qcom,rpm-regulator-smd-resource";
+ rpm-regulator-ldoa17 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <17>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ compatible = "qcom,rpm-regulator-smd-resource";
+ status = "disabled";
+
+ regulator-l17 {
+ regulator-name = "8941_l17";
+ qcom,set = <3>;
status = "disabled";
-
- regulator-l17 {
- regulator-name = "8941_l17";
- qcom,set = <3>;
- status = "disabled";
- compatible = "qcom,rpm-regulator-smd";
- };
+ compatible = "qcom,rpm-regulator-smd";
};
+ };
- rpm-regulator-ldoa18 {
- qcom,resource-name = "ldoa";
- qcom,resource-id = <18>;
- qcom,regulator-type = <0>;
- qcom,hpm-min-load = <10000>;
- compatible = "qcom,rpm-regulator-smd-resource";
+ rpm-regulator-ldoa18 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <18>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ compatible = "qcom,rpm-regulator-smd-resource";
+ status = "disabled";
+
+ regulator-l18 {
+ regulator-name = "8941_l18";
+ qcom,set = <3>;
status = "disabled";
-
- regulator-l18 {
- regulator-name = "8941_l18";
- qcom,set = <3>;
- status = "disabled";
- compatible = "qcom,rpm-regulator-smd";
- };
+ compatible = "qcom,rpm-regulator-smd";
};
+ };
- rpm-regulator-ldoa19 {
- qcom,resource-name = "ldoa";
- qcom,resource-id = <19>;
- qcom,regulator-type = <0>;
- qcom,hpm-min-load = <10000>;
- compatible = "qcom,rpm-regulator-smd-resource";
+ rpm-regulator-ldoa19 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <19>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ compatible = "qcom,rpm-regulator-smd-resource";
+ status = "disabled";
+
+ regulator-l19 {
+ regulator-name = "8941_l19";
+ qcom,set = <3>;
status = "disabled";
-
- regulator-l19 {
- regulator-name = "8941_l19";
- qcom,set = <3>;
- status = "disabled";
- compatible = "qcom,rpm-regulator-smd";
- };
+ compatible = "qcom,rpm-regulator-smd";
};
+ };
- rpm-regulator-ldoa20 {
- qcom,resource-name = "ldoa";
- qcom,resource-id = <20>;
- qcom,regulator-type = <0>;
- qcom,hpm-min-load = <10000>;
- compatible = "qcom,rpm-regulator-smd-resource";
+ rpm-regulator-ldoa20 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <20>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ compatible = "qcom,rpm-regulator-smd-resource";
+ status = "disabled";
+
+ regulator-l20 {
+ regulator-name = "8941_l20";
+ qcom,set = <3>;
status = "disabled";
-
- regulator-l20 {
- regulator-name = "8941_l20";
- qcom,set = <3>;
- status = "disabled";
- compatible = "qcom,rpm-regulator-smd";
- };
+ compatible = "qcom,rpm-regulator-smd";
};
+ };
- rpm-regulator-ldoa21 {
- qcom,resource-name = "ldoa";
- qcom,resource-id = <21>;
- qcom,regulator-type = <0>;
- qcom,hpm-min-load = <10000>;
- compatible = "qcom,rpm-regulator-smd-resource";
+ rpm-regulator-ldoa21 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <21>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ compatible = "qcom,rpm-regulator-smd-resource";
+ status = "disabled";
+
+ regulator-l21 {
+ regulator-name = "8941_l21";
+ qcom,set = <3>;
status = "disabled";
-
- regulator-l21 {
- regulator-name = "8941_l21";
- qcom,set = <3>;
- status = "disabled";
- compatible = "qcom,rpm-regulator-smd";
- };
+ compatible = "qcom,rpm-regulator-smd";
};
+ };
- rpm-regulator-ldoa22 {
- qcom,resource-name = "ldoa";
- qcom,resource-id = <22>;
- qcom,regulator-type = <0>;
- qcom,hpm-min-load = <10000>;
- compatible = "qcom,rpm-regulator-smd-resource";
+ rpm-regulator-ldoa22 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <22>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ compatible = "qcom,rpm-regulator-smd-resource";
+ status = "disabled";
+
+ regulator-l22 {
+ regulator-name = "8941_l22";
+ qcom,set = <3>;
status = "disabled";
-
- regulator-l22 {
- regulator-name = "8941_l22";
- qcom,set = <3>;
- status = "disabled";
- compatible = "qcom,rpm-regulator-smd";
- };
+ compatible = "qcom,rpm-regulator-smd";
};
+ };
- rpm-regulator-ldoa23 {
- qcom,resource-name = "ldoa";
- qcom,resource-id = <23>;
- qcom,regulator-type = <0>;
- qcom,hpm-min-load = <10000>;
- compatible = "qcom,rpm-regulator-smd-resource";
+ rpm-regulator-ldoa23 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <23>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ compatible = "qcom,rpm-regulator-smd-resource";
+ status = "disabled";
+
+ regulator-l23 {
+ regulator-name = "8941_l23";
+ qcom,set = <3>;
status = "disabled";
-
- regulator-l23 {
- regulator-name = "8941_l23";
- qcom,set = <3>;
- status = "disabled";
- compatible = "qcom,rpm-regulator-smd";
- };
+ compatible = "qcom,rpm-regulator-smd";
};
+ };
- rpm-regulator-ldoa24 {
- qcom,resource-name = "ldoa";
- qcom,resource-id = <24>;
- qcom,regulator-type = <0>;
- qcom,hpm-min-load = <10000>;
- compatible = "qcom,rpm-regulator-smd-resource";
+ rpm-regulator-ldoa24 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <24>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ compatible = "qcom,rpm-regulator-smd-resource";
+ status = "disabled";
+
+ regulator-l24 {
+ regulator-name = "8941_l24";
+ qcom,set = <3>;
status = "disabled";
-
- regulator-l24 {
- regulator-name = "8941_l24";
- qcom,set = <3>;
- status = "disabled";
- compatible = "qcom,rpm-regulator-smd";
- };
+ compatible = "qcom,rpm-regulator-smd";
};
+ };
- /* TODO: find out correct resource names for LVS vs MVS */
- rpm-regulator-vsa1 {
- qcom,resource-name = "vsa";
- qcom,resource-id = <1>;
- qcom,regulator-type = <2>;
- compatible = "qcom,rpm-regulator-smd-resource";
+ /* TODO: find out correct resource names for LVS vs MVS */
+ rpm-regulator-vsa1 {
+ qcom,resource-name = "vsa";
+ qcom,resource-id = <1>;
+ qcom,regulator-type = <2>;
+ compatible = "qcom,rpm-regulator-smd-resource";
+ status = "disabled";
+
+ regulator-lvs1 {
+ regulator-name = "8941_lvs1";
+ qcom,set = <3>;
status = "disabled";
-
- regulator-lvs1 {
- regulator-name = "8941_lvs1";
- qcom,set = <3>;
- status = "disabled";
- compatible = "qcom,rpm-regulator-smd";
- };
+ compatible = "qcom,rpm-regulator-smd";
};
+ };
- rpm-regulator-vsa2 {
- qcom,resource-name = "vsa";
- qcom,resource-id = <2>;
- qcom,regulator-type = <2>;
- compatible = "qcom,rpm-regulator-smd-resource";
+ rpm-regulator-vsa2 {
+ qcom,resource-name = "vsa";
+ qcom,resource-id = <2>;
+ qcom,regulator-type = <2>;
+ compatible = "qcom,rpm-regulator-smd-resource";
+ status = "disabled";
+
+ regulator-lvs2 {
+ regulator-name = "8941_lvs2";
+ qcom,set = <3>;
status = "disabled";
-
- regulator-lvs2 {
- regulator-name = "8941_lvs2";
- qcom,set = <3>;
- status = "disabled";
- compatible = "qcom,rpm-regulator-smd";
- };
+ compatible = "qcom,rpm-regulator-smd";
};
+ };
- rpm-regulator-vsa3 {
- qcom,resource-name = "vsa";
- qcom,resource-id = <3>;
- qcom,regulator-type = <2>;
- compatible = "qcom,rpm-regulator-smd-resource";
+ rpm-regulator-vsa3 {
+ qcom,resource-name = "vsa";
+ qcom,resource-id = <3>;
+ qcom,regulator-type = <2>;
+ compatible = "qcom,rpm-regulator-smd-resource";
+ status = "disabled";
+
+ regulator-lvs3 {
+ regulator-name = "8941_lvs3";
+ qcom,set = <3>;
status = "disabled";
-
- regulator-lvs3 {
- regulator-name = "8941_lvs3";
- qcom,set = <3>;
- status = "disabled";
- compatible = "qcom,rpm-regulator-smd";
- };
+ compatible = "qcom,rpm-regulator-smd";
};
+ };
- rpm-regulator-vsa4 {
- qcom,resource-name = "vsa";
- qcom,resource-id = <4>;
- qcom,regulator-type = <2>;
- compatible = "qcom,rpm-regulator-smd-resource";
+ rpm-regulator-vsa4 {
+ qcom,resource-name = "vsa";
+ qcom,resource-id = <4>;
+ qcom,regulator-type = <2>;
+ compatible = "qcom,rpm-regulator-smd-resource";
+ status = "disabled";
+
+ regulator-mvs1 {
+ regulator-name = "8941_mvs1";
+ qcom,set = <3>;
status = "disabled";
-
- regulator-mvs1 {
- regulator-name = "8941_mvs1";
- qcom,set = <3>;
- status = "disabled";
- compatible = "qcom,rpm-regulator-smd";
- };
+ compatible = "qcom,rpm-regulator-smd";
};
+ };
- rpm-regulator-vsa5 {
- qcom,resource-name = "vsa";
- qcom,resource-id = <5>;
- qcom,regulator-type = <2>;
- compatible = "qcom,rpm-regulator-smd-resource";
+ rpm-regulator-vsa5 {
+ qcom,resource-name = "vsa";
+ qcom,resource-id = <5>;
+ qcom,regulator-type = <2>;
+ compatible = "qcom,rpm-regulator-smd-resource";
+ status = "disabled";
+
+ regulator-mvs2 {
+ regulator-name = "8941_mvs2";
+ qcom,set = <3>;
status = "disabled";
-
- regulator-mvs2 {
- regulator-name = "8941_mvs2";
- qcom,set = <3>;
- status = "disabled";
- compatible = "qcom,rpm-regulator-smd";
- };
+ compatible = "qcom,rpm-regulator-smd";
};
};
};
diff --git a/arch/arm/boot/dts/msm8974-gpio.dtsi b/arch/arm/boot/dts/msm8974-gpio.dtsi
index 59ad8db..323fac4 100644
--- a/arch/arm/boot/dts/msm8974-gpio.dtsi
+++ b/arch/arm/boot/dts/msm8974-gpio.dtsi
@@ -10,225 +10,223 @@
* GNU General Public License for more details.
*/
-/ {
- qcom,spmi@fc4c0000 {
+&spmi_bus {
- qcom,pm8941@0 {
+ qcom,pm8941@0 {
- pm8941_gpios: pm8941_gpios {
+ pm8941_gpios: pm8941_gpios {
- gpio@c000 {
- status = "ok";
- };
-
- gpio@c100 {
- status = "ok";
- };
-
- gpio@c200 {
- status = "ok";
- };
-
- gpio@c300 {
- status = "ok";
- };
-
- gpio@c400 {
- status = "ok";
- };
-
- gpio@c500 {
- status = "ok";
- };
-
- gpio@c600 {
- status = "ok";
- };
-
- gpio@c700 {
- status = "ok";
- };
-
- gpio@c800 {
- status = "ok";
- };
-
- gpio@c900 {
- status = "ok";
- };
-
- gpio@ca00 {
- status = "ok";
- };
-
- gpio@cb00 {
- status = "ok";
- };
-
- gpio@cc00 {
- status = "ok";
- };
-
- gpio@cd00 {
- status = "ok";
- };
-
- gpio@ce00 {
- status = "ok";
- };
-
- gpio@cf00 {
- status = "ok";
- };
-
- gpio@d000 {
- status = "ok";
- };
-
- gpio@d100 {
- status = "ok";
- };
-
- gpio@d200 {
- status = "ok";
- };
-
- gpio@d300 {
- status = "ok";
- };
-
- gpio@d400 {
- status = "ok";
- };
-
- gpio@d500 {
- status = "ok";
- };
-
- gpio@d600 {
- status = "ok";
- };
-
- gpio@d700 {
- status = "ok";
- };
-
- gpio@d800 {
- qcom,out-strength = <1>;
- status = "ok";
- };
-
- gpio@d900 {
- qcom,out-strength = <1>;
- status = "ok";
- };
-
- gpio@da00 {
- qcom,out-strength = <1>;
- status = "ok";
- };
-
- gpio@db00 {
- qcom,out-strength = <1>;
- status = "ok";
- };
-
- gpio@dc00 {
- qcom,out-strength = <1>;
- status = "ok";
- };
-
- gpio@dd00 {
- qcom,out-strength = <1>;
- status = "ok";
- };
-
- gpio@de00 {
- qcom,out-strength = <1>;
- status = "ok";
- };
-
- gpio@df00 {
- qcom,out-strength = <1>;
- status = "ok";
- };
-
- gpio@e000 {
- qcom,out-strength = <1>;
- status = "ok";
- };
-
- gpio@e100 {
- qcom,out-strength = <1>;
- status = "ok";
- };
-
- gpio@e200 {
- qcom,out-strength = <1>;
- status = "ok";
- };
-
- gpio@e300 {
- qcom,out-strength = <1>;
- status = "ok";
- };
+ gpio@c000 {
+ status = "ok";
};
- pm8941_mpps: pm8941_mpps {
+ gpio@c100 {
+ status = "ok";
+ };
- mpp@a000 {
- status = "ok";
- };
+ gpio@c200 {
+ status = "ok";
+ };
- mpp@a100 {
- status = "ok";
- };
+ gpio@c300 {
+ status = "ok";
+ };
- mpp@a200 {
- status = "ok";
- };
+ gpio@c400 {
+ status = "ok";
+ };
- mpp@a300 {
- status = "ok";
- };
+ gpio@c500 {
+ status = "ok";
+ };
- mpp@a400 {
- status = "ok";
- };
+ gpio@c600 {
+ status = "ok";
+ };
- mpp@a500 {
- status = "ok";
- };
+ gpio@c700 {
+ status = "ok";
+ };
- mpp@a600 {
- status = "ok";
- };
+ gpio@c800 {
+ status = "ok";
+ };
- mpp@a700 {
- status = "ok";
- };
+ gpio@c900 {
+ status = "ok";
+ };
+
+ gpio@ca00 {
+ status = "ok";
+ };
+
+ gpio@cb00 {
+ status = "ok";
+ };
+
+ gpio@cc00 {
+ status = "ok";
+ };
+
+ gpio@cd00 {
+ status = "ok";
+ };
+
+ gpio@ce00 {
+ status = "ok";
+ };
+
+ gpio@cf00 {
+ status = "ok";
+ };
+
+ gpio@d000 {
+ status = "ok";
+ };
+
+ gpio@d100 {
+ status = "ok";
+ };
+
+ gpio@d200 {
+ status = "ok";
+ };
+
+ gpio@d300 {
+ status = "ok";
+ };
+
+ gpio@d400 {
+ status = "ok";
+ };
+
+ gpio@d500 {
+ status = "ok";
+ };
+
+ gpio@d600 {
+ status = "ok";
+ };
+
+ gpio@d700 {
+ status = "ok";
+ };
+
+ gpio@d800 {
+ qcom,out-strength = <1>;
+ status = "ok";
+ };
+
+ gpio@d900 {
+ qcom,out-strength = <1>;
+ status = "ok";
+ };
+
+ gpio@da00 {
+ qcom,out-strength = <1>;
+ status = "ok";
+ };
+
+ gpio@db00 {
+ qcom,out-strength = <1>;
+ status = "ok";
+ };
+
+ gpio@dc00 {
+ qcom,out-strength = <1>;
+ status = "ok";
+ };
+
+ gpio@dd00 {
+ qcom,out-strength = <1>;
+ status = "ok";
+ };
+
+ gpio@de00 {
+ qcom,out-strength = <1>;
+ status = "ok";
+ };
+
+ gpio@df00 {
+ qcom,out-strength = <1>;
+ status = "ok";
+ };
+
+ gpio@e000 {
+ qcom,out-strength = <1>;
+ status = "ok";
+ };
+
+ gpio@e100 {
+ qcom,out-strength = <1>;
+ status = "ok";
+ };
+
+ gpio@e200 {
+ qcom,out-strength = <1>;
+ status = "ok";
+ };
+
+ gpio@e300 {
+ qcom,out-strength = <1>;
+ status = "ok";
};
};
- qcom,pm8841@4 {
+ pm8941_mpps: pm8941_mpps {
- pm8841_mpps: pm8841_mpps {
+ mpp@a000 {
+ status = "ok";
+ };
- mpp@a000 {
- status = "ok";
- };
+ mpp@a100 {
+ status = "ok";
+ };
- mpp@a100 {
- status = "ok";
- };
+ mpp@a200 {
+ status = "ok";
+ };
- mpp@a200 {
- status = "ok";
- };
+ mpp@a300 {
+ status = "ok";
+ };
- mpp@a300 {
- status = "ok";
- };
+ mpp@a400 {
+ status = "ok";
+ };
+
+ mpp@a500 {
+ status = "ok";
+ };
+
+ mpp@a600 {
+ status = "ok";
+ };
+
+ mpp@a700 {
+ status = "ok";
+ };
+ };
+ };
+
+ qcom,pm8841@4 {
+
+ pm8841_mpps: pm8841_mpps {
+
+ mpp@a000 {
+ status = "ok";
+ };
+
+ mpp@a100 {
+ status = "ok";
+ };
+
+ mpp@a200 {
+ status = "ok";
+ };
+
+ mpp@a300 {
+ status = "ok";
};
};
};
diff --git a/arch/arm/boot/dts/msm8974-iommu.dtsi b/arch/arm/boot/dts/msm8974-iommu.dtsi
index e1a0a9b..a115fd8 100755
--- a/arch/arm/boot/dts/msm8974-iommu.dtsi
+++ b/arch/arm/boot/dts/msm8974-iommu.dtsi
@@ -18,6 +18,7 @@
ranges;
reg = <0xfda64000 0x10000>;
vdd-supply = <&gdsc_jpeg>;
+ qcom,iommu-smt-size = <16>;
qcom,iommu-ctx@fda6c000 {
reg = <0xfda6c000 0x1000>;
@@ -46,6 +47,7 @@
ranges;
reg = <0xfd928000 0x10000>;
vdd-supply = <&gdsc_mdss>;
+ qcom,iommu-smt-size = <16>;
qcom,iommu-ctx@fd930000 {
reg = <0xfd930000 0x1000>;
@@ -68,6 +70,7 @@
ranges;
reg = <0xfdc84000 0x10000>;
vdd-supply = <&gdsc_venus>;
+ qcom,iommu-smt-size = <16>;
qcom,iommu-ctx@fdc8c000 {
reg = <0xfdc8c000 0x1000>;
diff --git a/arch/arm/boot/dts/msm8974-regulator.dtsi b/arch/arm/boot/dts/msm8974-regulator.dtsi
index 7b3893e..f0c635e 100644
--- a/arch/arm/boot/dts/msm8974-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974-regulator.dtsi
@@ -10,474 +10,474 @@
* GNU General Public License for more details.
*/
-/ {
/* QPNP controlled regulators: */
- qcom,spmi@fc4c0000 {
+&spmi_bus {
- qcom,pm8941@1 {
+ qcom,pm8941@1 {
- pm8941_boost: regulator@a000 {
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- qcom,enable-time = <500>;
- status = "okay";
- };
-
- pm8941_mvs1: regulator@8300 {
- parent-supply = <&pm8941_boost>;
- qcom,enable-time = <200>;
- qcom,pull-down-enable = <1>;
- status = "okay";
- };
-
- pm8941_mvs2: regulator@8400 {
- parent-supply = <&pm8941_boost>;
- qcom,enable-time = <200>;
- qcom,pull-down-enable = <1>;
- status = "okay";
- };
+ pm8941_boost: regulator@a000 {
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ qcom,enable-time = <500>;
+ status = "okay";
};
- qcom,pm8841@5 {
+ pm8941_mvs1: regulator@8300 {
+ parent-supply = <&pm8941_boost>;
+ qcom,enable-time = <200>;
+ qcom,pull-down-enable = <1>;
+ status = "okay";
+ };
- pm8841_s5: regulator@2000 {
- regulator-min-microvolt = <850000>;
- regulator-max-microvolt = <1100000>;
- qcom,enable-time = <500>;
- qcom,pull-down-enable = <1>;
- regulator-always-on;
- status = "okay";
- };
-
- pm8841_s6: regulator@2300 {
- regulator-min-microvolt = <850000>;
- regulator-max-microvolt = <1100000>;
- qcom,enable-time = <500>;
- qcom,pull-down-enable = <1>;
- status = "okay";
- };
-
- pm8841_s7: regulator@2600 {
- regulator-min-microvolt = <850000>;
- regulator-max-microvolt = <1100000>;
- qcom,enable-time = <500>;
- qcom,pull-down-enable = <1>;
- status = "okay";
- };
-
- pm8841_s8: regulator@2900 {
- regulator-min-microvolt = <850000>;
- regulator-max-microvolt = <1100000>;
- qcom,enable-time = <500>;
- qcom,pull-down-enable = <1>;
- status = "okay";
- };
+ pm8941_mvs2: regulator@8400 {
+ parent-supply = <&pm8941_boost>;
+ qcom,enable-time = <200>;
+ qcom,pull-down-enable = <1>;
+ status = "okay";
};
};
+ qcom,pm8841@5 {
+
+ pm8841_s5: regulator@2000 {
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <1100000>;
+ qcom,enable-time = <500>;
+ qcom,pull-down-enable = <1>;
+ regulator-always-on;
+ status = "okay";
+ };
+
+ pm8841_s6: regulator@2300 {
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <1100000>;
+ qcom,enable-time = <500>;
+ qcom,pull-down-enable = <1>;
+ status = "okay";
+ };
+
+ pm8841_s7: regulator@2600 {
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <1100000>;
+ qcom,enable-time = <500>;
+ qcom,pull-down-enable = <1>;
+ status = "okay";
+ };
+
+ pm8841_s8: regulator@2900 {
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <1100000>;
+ qcom,enable-time = <500>;
+ qcom,pull-down-enable = <1>;
+ status = "okay";
+ };
+ };
+};
+
/* RPM controlled regulators: */
- qcom,rpm-smd {
- rpm-regulator-smpb1 {
+&rpm_bus {
+ rpm-regulator-smpb1 {
+ status = "okay";
+ pm8841_s1: regulator-s1 {
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <1050000>;
status = "okay";
- pm8841_s1: regulator-s1 {
- regulator-min-microvolt = <675000>;
- regulator-max-microvolt = <1050000>;
- status = "okay";
- };
- pm8841_s1_ao: regulator-s1-ao {
- regulator-name = "8841_s1_ao";
- qcom,set = <1>;
- regulator-min-microvolt = <675000>;
- regulator-max-microvolt = <1050000>;
- status = "okay";
- compatible = "qcom,rpm-regulator-smd";
- };
};
-
- rpm-regulator-smpb2 {
+ pm8841_s1_ao: regulator-s1-ao {
+ regulator-name = "8841_s1_ao";
+ qcom,set = <1>;
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <1050000>;
status = "okay";
- qcom,allow-atomic = <1>;
- pm8841_s2: regulator-s2 {
- regulator-min-microvolt = <500000>;
- regulator-max-microvolt = <1050000>;
- status = "okay";
- };
- pm8841_s2_corner: regulator-s2-corner {
- regulator-name = "8841_s2_corner";
- qcom,set = <3>;
- regulator-min-microvolt = <1>;
- regulator-max-microvolt = <6>;
- qcom,use-voltage-corner;
- compatible = "qcom,rpm-regulator-smd";
- qcom,consumer-supplies = "vdd_dig", "";
- };
- pm8841_s2_corner_ao: regulator-s2-corner-ao {
- regulator-name = "8841_s2_corner_ao";
- qcom,set = <1>;
- regulator-min-microvolt = <1>;
- regulator-max-microvolt = <6>;
- qcom,use-voltage-corner;
- compatible = "qcom,rpm-regulator-smd";
- };
- };
-
- rpm-regulator-smpb3 {
- status = "okay";
- pm8841_s3: regulator-s3 {
- regulator-min-microvolt = <1150000>;
- regulator-max-microvolt = <1150000>;
- qcom,init-voltage = <1150000>;
- status = "okay";
- };
- };
-
- rpm-regulator-smpb4 {
- status = "okay";
- pm8841_s4: regulator-s4 {
- regulator-min-microvolt = <900000>;
- regulator-max-microvolt = <900000>;
- qcom,init-voltage = <900000>;
- status = "okay";
- };
- };
-
- rpm-regulator-smpa1 {
- status = "okay";
- pm8941_s1: regulator-s1 {
- regulator-min-microvolt = <1300000>;
- regulator-max-microvolt = <1300000>;
- qcom,init-voltage = <1300000>;
- qcom,init-current = <100>;
- qcom,system-load = <100000>;
- regulator-always-on;
- status = "okay";
- };
- };
-
- rpm-regulator-smpa2 {
- status = "okay";
- qcom,allow-atomic = <1>;
- pm8941_s2: regulator-s2 {
- regulator-min-microvolt = <2150000>;
- regulator-max-microvolt = <2150000>;
- qcom,init-voltage = <2150000>;
- status = "okay";
- };
- pm8941_s2_ao: regulator-s2-ao {
- regulator-name = "8941_s2_ao";
- qcom,set = <1>;
- regulator-min-microvolt = <2150000>;
- regulator-max-microvolt = <2150000>;
- status = "okay";
- compatible = "qcom,rpm-regulator-smd";
- };
- };
-
- rpm-regulator-smpa3 {
- status = "okay";
- pm8941_s3: regulator-s3 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- qcom,init-voltage = <1800000>;
- qcom,init-current = <100>;
- qcom,system-load = <100000>;
- regulator-always-on;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa1 {
- status = "okay";
- pm8941_l1: regulator-l1 {
- parent-supply = <&pm8941_s1>;
- regulator-min-microvolt = <1225000>;
- regulator-max-microvolt = <1225000>;
- qcom,init-voltage = <1225000>;
- qcom,init-current = <10>;
- qcom,system-load = <10000>;
- regulator-always-on;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa2 {
- status = "okay";
- pm8941_l2: regulator-l2 {
- parent-supply = <&pm8941_s3>;
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
- qcom,init-voltage = <1200000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa3 {
- status = "okay";
- pm8941_l3: regulator-l3 {
- parent-supply = <&pm8941_s1>;
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
- qcom,init-voltage = <1200000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa4 {
- status = "okay";
- pm8941_l4: regulator-l4 {
- parent-supply = <&pm8941_s1>;
- regulator-min-microvolt = <1150000>;
- regulator-max-microvolt = <1150000>;
- qcom,init-voltage = <1150000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa5 {
- status = "okay";
- pm8941_l5: regulator-l5 {
- parent-supply = <&pm8941_s2>;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- qcom,init-voltage = <1800000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa6 {
- status = "okay";
- pm8941_l6: regulator-l6 {
- parent-supply = <&pm8941_s2>;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- qcom,init-voltage = <1800000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa7 {
- status = "okay";
- pm8941_l7: regulator-l7 {
- parent-supply = <&pm8941_s2>;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- qcom,init-voltage = <1800000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa8 {
- status = "okay";
- pm8941_l8: regulator-l8 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- qcom,init-voltage = <1800000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa9 {
- status = "okay";
- pm8941_l9: regulator-l9 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <2950000>;
- qcom,init-voltage = <2950000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa10 {
- status = "okay";
- pm8941_l10: regulator-l10 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <2950000>;
- qcom,init-voltage = <2950000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa11 {
- status = "okay";
- pm8941_l11: regulator-l11 {
- parent-supply = <&pm8941_s1>;
- regulator-min-microvolt = <1250000>;
- regulator-max-microvolt = <1250000>;
- qcom,init-voltage = <1250000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa12 {
- status = "okay";
- qcom,allow-atomic = <1>;
- pm8941_l12: regulator-l12 {
- parent-supply = <&pm8941_s2>;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- status = "okay";
- };
- pm8941_l12_ao: regulator-l12-ao {
- regulator-name = "8941_l12_ao";
- parent-supply = <&pm8941_s2_ao>;
- qcom,set = <1>;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- status = "okay";
- compatible = "qcom,rpm-regulator-smd";
- };
- };
-
- rpm-regulator-ldoa13 {
- status = "okay";
- pm8941_l13: regulator-l13 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <2950000>;
- qcom,init-voltage = <2950000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa14 {
- status = "okay";
- pm8941_l14: regulator-l14 {
- parent-supply = <&pm8941_s2>;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- qcom,init-voltage = <1800000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa15 {
- status = "okay";
- pm8941_l15: regulator-l15 {
- parent-supply = <&pm8941_s2>;
- regulator-min-microvolt = <2050000>;
- regulator-max-microvolt = <2050000>;
- qcom,init-voltage = <2050000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa16 {
- status = "okay";
- pm8941_l16: regulator-l16 {
- regulator-min-microvolt = <2700000>;
- regulator-max-microvolt = <2700000>;
- qcom,init-voltage = <2700000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa17 {
- status = "okay";
- pm8941_l17: regulator-l17 {
- regulator-min-microvolt = <2850000>;
- regulator-max-microvolt = <2850000>;
- qcom,init-voltage = <2850000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa18 {
- status = "okay";
- pm8941_l18: regulator-l18 {
- regulator-min-microvolt = <2850000>;
- regulator-max-microvolt = <2850000>;
- qcom,init-voltage = <2850000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa19 {
- status = "okay";
- pm8941_l19: regulator-l19 {
- regulator-min-microvolt = <2900000>;
- regulator-max-microvolt = <2900000>;
- qcom,init-voltage = <2900000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa20 {
- status = "okay";
- pm8941_l20: regulator-l20 {
- regulator-min-microvolt = <2950000>;
- regulator-max-microvolt = <2950000>;
- qcom,init-voltage = <2950000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa21 {
- status = "okay";
- pm8941_l21: regulator-l21 {
- regulator-min-microvolt = <2950000>;
- regulator-max-microvolt = <2950000>;
- qcom,init-voltage = <2950000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa22 {
- status = "okay";
- pm8941_l22: regulator-l22 {
- regulator-min-microvolt = <3000000>;
- regulator-max-microvolt = <3000000>;
- qcom,init-voltage = <3000000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa23 {
- status = "okay";
- pm8941_l23: regulator-l23 {
- regulator-min-microvolt = <3000000>;
- regulator-max-microvolt = <3000000>;
- qcom,init-voltage = <3000000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa24 {
- status = "okay";
- pm8941_l24: regulator-l24 {
- regulator-min-microvolt = <3075000>;
- regulator-max-microvolt = <3075000>;
- qcom,init-voltage = <3075000>;
- status = "okay";
- };
- };
-
- rpm-regulator-vsa1 {
- status = "okay";
- pm8941_lvs1: regulator-lvs1 {
- parent-supply = <&pm8941_s3>;
- status = "okay";
- };
- };
-
- rpm-regulator-vsa2 {
- status = "okay";
- pm8941_lvs2: regulator-lvs2 {
- parent-supply = <&pm8941_s3>;
- status = "okay";
- };
- };
-
- rpm-regulator-vsa3 {
- status = "okay";
- pm8941_lvs3: regulator-lvs3 {
- parent-supply = <&pm8941_s3>;
- status = "okay";
- };
+ compatible = "qcom,rpm-regulator-smd";
};
};
+ rpm-regulator-smpb2 {
+ status = "okay";
+ qcom,allow-atomic = <1>;
+ pm8841_s2: regulator-s2 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1050000>;
+ status = "okay";
+ };
+ pm8841_s2_corner: regulator-s2-corner {
+ regulator-name = "8841_s2_corner";
+ qcom,set = <3>;
+ regulator-min-microvolt = <1>;
+ regulator-max-microvolt = <6>;
+ qcom,use-voltage-corner;
+ compatible = "qcom,rpm-regulator-smd";
+ qcom,consumer-supplies = "vdd_dig", "";
+ };
+ pm8841_s2_corner_ao: regulator-s2-corner-ao {
+ regulator-name = "8841_s2_corner_ao";
+ qcom,set = <1>;
+ regulator-min-microvolt = <1>;
+ regulator-max-microvolt = <6>;
+ qcom,use-voltage-corner;
+ compatible = "qcom,rpm-regulator-smd";
+ };
+ };
+
+ rpm-regulator-smpb3 {
+ status = "okay";
+ pm8841_s3: regulator-s3 {
+ regulator-min-microvolt = <1150000>;
+ regulator-max-microvolt = <1150000>;
+ qcom,init-voltage = <1150000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-smpb4 {
+ status = "okay";
+ pm8841_s4: regulator-s4 {
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <900000>;
+ qcom,init-voltage = <900000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-smpa1 {
+ status = "okay";
+ pm8941_s1: regulator-s1 {
+ regulator-min-microvolt = <1300000>;
+ regulator-max-microvolt = <1300000>;
+ qcom,init-voltage = <1300000>;
+ qcom,init-current = <100>;
+ qcom,system-load = <100000>;
+ regulator-always-on;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-smpa2 {
+ status = "okay";
+ qcom,allow-atomic = <1>;
+ pm8941_s2: regulator-s2 {
+ regulator-min-microvolt = <2150000>;
+ regulator-max-microvolt = <2150000>;
+ qcom,init-voltage = <2150000>;
+ status = "okay";
+ };
+ pm8941_s2_ao: regulator-s2-ao {
+ regulator-name = "8941_s2_ao";
+ qcom,set = <1>;
+ regulator-min-microvolt = <2150000>;
+ regulator-max-microvolt = <2150000>;
+ status = "okay";
+ compatible = "qcom,rpm-regulator-smd";
+ };
+ };
+
+ rpm-regulator-smpa3 {
+ status = "okay";
+ pm8941_s3: regulator-s3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ qcom,init-current = <100>;
+ qcom,system-load = <100000>;
+ regulator-always-on;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa1 {
+ status = "okay";
+ pm8941_l1: regulator-l1 {
+ parent-supply = <&pm8941_s1>;
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ qcom,init-voltage = <1225000>;
+ qcom,init-current = <10>;
+ qcom,system-load = <10000>;
+ regulator-always-on;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa2 {
+ status = "okay";
+ pm8941_l2: regulator-l2 {
+ parent-supply = <&pm8941_s3>;
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ qcom,init-voltage = <1200000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa3 {
+ status = "okay";
+ pm8941_l3: regulator-l3 {
+ parent-supply = <&pm8941_s1>;
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ qcom,init-voltage = <1200000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa4 {
+ status = "okay";
+ pm8941_l4: regulator-l4 {
+ parent-supply = <&pm8941_s1>;
+ regulator-min-microvolt = <1150000>;
+ regulator-max-microvolt = <1150000>;
+ qcom,init-voltage = <1150000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa5 {
+ status = "okay";
+ pm8941_l5: regulator-l5 {
+ parent-supply = <&pm8941_s2>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa6 {
+ status = "okay";
+ pm8941_l6: regulator-l6 {
+ parent-supply = <&pm8941_s2>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa7 {
+ status = "okay";
+ pm8941_l7: regulator-l7 {
+ parent-supply = <&pm8941_s2>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa8 {
+ status = "okay";
+ pm8941_l8: regulator-l8 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa9 {
+ status = "okay";
+ pm8941_l9: regulator-l9 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ qcom,init-voltage = <2950000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa10 {
+ status = "okay";
+ pm8941_l10: regulator-l10 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ qcom,init-voltage = <2950000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa11 {
+ status = "okay";
+ pm8941_l11: regulator-l11 {
+ parent-supply = <&pm8941_s1>;
+ regulator-min-microvolt = <1250000>;
+ regulator-max-microvolt = <1250000>;
+ qcom,init-voltage = <1250000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa12 {
+ status = "okay";
+ qcom,allow-atomic = <1>;
+ pm8941_l12: regulator-l12 {
+ parent-supply = <&pm8941_s2>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ status = "okay";
+ };
+ pm8941_l12_ao: regulator-l12-ao {
+ regulator-name = "8941_l12_ao";
+ parent-supply = <&pm8941_s2_ao>;
+ qcom,set = <1>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ status = "okay";
+ compatible = "qcom,rpm-regulator-smd";
+ };
+ };
+
+ rpm-regulator-ldoa13 {
+ status = "okay";
+ pm8941_l13: regulator-l13 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ qcom,init-voltage = <2950000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa14 {
+ status = "okay";
+ pm8941_l14: regulator-l14 {
+ parent-supply = <&pm8941_s2>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa15 {
+ status = "okay";
+ pm8941_l15: regulator-l15 {
+ parent-supply = <&pm8941_s2>;
+ regulator-min-microvolt = <2050000>;
+ regulator-max-microvolt = <2050000>;
+ qcom,init-voltage = <2050000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa16 {
+ status = "okay";
+ pm8941_l16: regulator-l16 {
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <2700000>;
+ qcom,init-voltage = <2700000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa17 {
+ status = "okay";
+ pm8941_l17: regulator-l17 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2850000>;
+ qcom,init-voltage = <2850000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa18 {
+ status = "okay";
+ pm8941_l18: regulator-l18 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2850000>;
+ qcom,init-voltage = <2850000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa19 {
+ status = "okay";
+ pm8941_l19: regulator-l19 {
+ regulator-min-microvolt = <2900000>;
+ regulator-max-microvolt = <2900000>;
+ qcom,init-voltage = <2900000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa20 {
+ status = "okay";
+ pm8941_l20: regulator-l20 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+ qcom,init-voltage = <2950000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa21 {
+ status = "okay";
+ pm8941_l21: regulator-l21 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+ qcom,init-voltage = <2950000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa22 {
+ status = "okay";
+ pm8941_l22: regulator-l22 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ qcom,init-voltage = <3000000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa23 {
+ status = "okay";
+ pm8941_l23: regulator-l23 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ qcom,init-voltage = <3000000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa24 {
+ status = "okay";
+ pm8941_l24: regulator-l24 {
+ regulator-min-microvolt = <3075000>;
+ regulator-max-microvolt = <3075000>;
+ qcom,init-voltage = <3075000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-vsa1 {
+ status = "okay";
+ pm8941_lvs1: regulator-lvs1 {
+ parent-supply = <&pm8941_s3>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-vsa2 {
+ status = "okay";
+ pm8941_lvs2: regulator-lvs2 {
+ parent-supply = <&pm8941_s3>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-vsa3 {
+ status = "okay";
+ pm8941_lvs3: regulator-lvs3 {
+ parent-supply = <&pm8941_s3>;
+ status = "okay";
+ };
+ };
+};
+
+/ {
krait0_vreg: regulator@f9088000 {
compatible = "qcom,krait-regulator";
regulator-name = "krait0";
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 8f8deac..1531a95 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -12,11 +12,6 @@
/include/ "skeleton.dtsi"
/include/ "msm8974_pm.dtsi"
-/include/ "msm-pm8x41-rpm-regulator.dtsi"
-/include/ "msm-pm8841.dtsi"
-/include/ "msm-pm8941.dtsi"
-/include/ "msm8974-regulator.dtsi"
-/include/ "msm8974-gpio.dtsi"
/include/ "msm8974-iommu.dtsi"
/include/ "msm-gdsc.dtsi"
@@ -178,7 +173,7 @@
qcom,min-clk-gear = <10>;
};
- qcom,spmi@fc4c0000 {
+ spmi_bus: qcom,spmi@fc4c0000 {
cell-index = <0>;
compatible = "qcom,spmi-pmic-arb";
reg = <0xfc4cf000 0x1000>,
@@ -428,7 +423,7 @@
compatible = "qcom,msm_ocmem";
};
- qcom,rpm-smd {
+ rpm_bus: qcom,rpm-smd {
compatible = "qcom,rpm-smd";
rpm-channel-name = "rpm_requests";
rpm-channel-type = <15>; /* SMD_APPS_RPM */
@@ -482,4 +477,21 @@
qcom,firmware-min-paddr = <0xF500000>;
qcom,firmware-max-paddr = <0xFA00000>;
};
+
+ tsens@fc4a8000 {
+ compatible = "qcom,msm-tsens";
+ reg = <0xfc4a8000 0x2000>,
+ <0xfc4b80d0 0x5>;
+ reg-names = "tsens_physical", "tsens_eeprom_physical";
+ interrupts = <0 184 0>;
+ qcom,sensors = <11>;
+ qcom,slope = <1134 1122 1142 1123 1176 1176 1176 1186 1176
+ 1176 1176>;
+ };
};
+
+/include/ "msm-pm8x41-rpm-regulator.dtsi"
+/include/ "msm-pm8841.dtsi"
+/include/ "msm-pm8941.dtsi"
+/include/ "msm8974-regulator.dtsi"
+/include/ "msm8974-gpio.dtsi"
diff --git a/arch/arm/configs/msm7627a-perf_defconfig b/arch/arm/configs/msm7627a-perf_defconfig
index 3cd06a2..c40d4d0 100644
--- a/arch/arm/configs/msm7627a-perf_defconfig
+++ b/arch/arm/configs/msm7627a-perf_defconfig
@@ -17,7 +17,6 @@
CONFIG_KALLSYMS_ALL=y
CONFIG_ASHMEM=y
CONFIG_EMBEDDED=y
-CONFIG_SLAB=y
CONFIG_PROFILING=y
CONFIG_OPROFILE=y
CONFIG_KPROBES=y
@@ -62,6 +61,7 @@
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
CONFIG_VMALLOC_RESERVE=0xC800000
+CONFIG_COMPACTION=y
CONFIG_CP_ACCESS=y
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index 058349a..838933c 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -17,7 +17,6 @@
CONFIG_KALLSYMS_ALL=y
CONFIG_ASHMEM=y
CONFIG_EMBEDDED=y
-CONFIG_SLAB=y
CONFIG_PROFILING=y
CONFIG_OPROFILE=y
CONFIG_KPROBES=y
@@ -62,6 +61,7 @@
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
CONFIG_VMALLOC_RESERVE=0xC800000
+CONFIG_COMPACTION=y
CONFIG_CP_ACCESS=y
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
@@ -339,8 +339,6 @@
CONFIG_LOCKUP_DETECTOR=y
# CONFIG_SCHED_DEBUG is not set
CONFIG_TIMER_STATS=y
-CONFIG_DEBUG_SLAB=y
-CONFIG_DEBUG_SLAB_LEAK=y
CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_ATOMIC_SLEEP=y
diff --git a/arch/arm/configs/msm7630-perf_defconfig b/arch/arm/configs/msm7630-perf_defconfig
index 262c983..1bf888b 100644
--- a/arch/arm/configs/msm7630-perf_defconfig
+++ b/arch/arm/configs/msm7630-perf_defconfig
@@ -43,6 +43,7 @@
CONFIG_MSM_MEMORY_LOW_POWER_MODE_SUSPEND_DEEP_POWER_DOWN=y
CONFIG_MSM_IDLE_WAIT_ON_MODEM=2000
CONFIG_MSM_STANDALONE_POWER_COLLAPSE=y
+CONFIG_MSM_MULTIMEDIA_USE_ION=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_PREEMPT=y
@@ -263,6 +264,8 @@
CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_RADIO_TAVARUA=y
+CONFIG_ION=y
+CONFIG_ION_MSM=y
CONFIG_MSM_KGSL=y
CONFIG_VIDEO_OUTPUT_CONTROL=y
CONFIG_FB=y
diff --git a/arch/arm/configs/msm7630_defconfig b/arch/arm/configs/msm7630_defconfig
index 7eaaf35..aad13b8 100644
--- a/arch/arm/configs/msm7630_defconfig
+++ b/arch/arm/configs/msm7630_defconfig
@@ -43,6 +43,7 @@
CONFIG_MSM_MEMORY_LOW_POWER_MODE_SUSPEND_DEEP_POWER_DOWN=y
CONFIG_MSM_IDLE_WAIT_ON_MODEM=2000
CONFIG_MSM_STANDALONE_POWER_COLLAPSE=y
+CONFIG_MSM_MULTIMEDIA_USE_ION=y
CONFIG_STRICT_MEMORY_RWX=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
@@ -264,6 +265,8 @@
CONFIG_VIDEOBUF2_MSM_MEM=y
CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
CONFIG_RADIO_TAVARUA=y
+CONFIG_ION=y
+CONFIG_ION_MSM=y
CONFIG_MSM_KGSL=y
CONFIG_VIDEO_OUTPUT_CONTROL=y
CONFIG_FB=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 9eea6f6..3da628f 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -341,6 +341,7 @@
# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
CONFIG_VIDEOBUF2_MSM_MEM=y
CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+CONFIG_USB_VIDEO_CLASS=y
CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_MSM_CAMERA_V4L2=y
CONFIG_IMX074=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 07bd8e6..4087f24 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -51,6 +51,7 @@
CONFIG_MSM_TZ_LOG=y
CONFIG_MSM_DIRECT_SCLK_ACCESS=y
CONFIG_MSM_OCMEM=y
+CONFIG_MSM_WATCHDOG_V2=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_SMP=y
@@ -250,3 +251,7 @@
CONFIG_SND=y
CONFIG_SND_SOC=y
CONFIG_SND_SOC_MSM8974=y
+CONFIG_CRYPTO_DEV_QCRYPTO=m
+CONFIG_CRYPTO_DEV_QCE=m
+CONFIG_CRYPTO_DEV_QCEDEV=m
+
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 313ff0b..63917d6 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -462,9 +462,11 @@
instr_sync
mov r3, r3
#ifdef CONFIG_ARCH_MSM_KRAIT
- ldr r3, =0xff00fc00
+ movw r3, 0xfc00
+ movt r3, 0xff00
and r3, r9, r3
- ldr r4, =0x51000400
+ movw r4, 0x0400
+ movt r4, 0x5100
cmp r3, r4
mrceq p15, 7, r3, c15, c0, 2
biceq r3, r3, #0x400
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 4738d71..28d6e60 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -208,7 +208,7 @@
mb();
/* Tell __cpu_die() that this CPU is now safe to dispose of */
- complete(&cpu_died);
+ RCU_NONIDLE(complete(&cpu_died));
/*
* actual CPU shutdown procedure is at least platform (if not
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 2acf3ce..c23bc10 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -64,6 +64,7 @@
select MSM_PROC_COMM_REGULATOR
select MULTI_IRQ_HANDLER
select MSM_PM2 if PM
+ select HOLES_IN_ZONE if SPARSEMEM
config ARCH_QSD8X50
bool "QSD8X50"
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 702667b..7ccdd0f 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -27,6 +27,7 @@
obj-$(CONFIG_ARCH_MSM_SCORPION) += pmu.o
obj-$(CONFIG_ARCH_MSM_SCORPIONMP) += perf_event_msm_l2.o
obj-$(CONFIG_ARCH_MSM_KRAIT) += msm-krait-l2-accessors.o pmu.o perf_event_msm_krait_l2.o
+obj-$(CONFIG_ARCH_MSM_KRAIT) += krait-scm.o
obj-$(CONFIG_ARCH_MSM7X27A) += pmu.o
ifndef CONFIG_MSM_SMP
diff --git a/arch/arm/mach-msm/acpuclock-8960.c b/arch/arm/mach-msm/acpuclock-8960.c
index c9d3817..7f198d2 100644
--- a/arch/arm/mach-msm/acpuclock-8960.c
+++ b/arch/arm/mach-msm/acpuclock-8960.c
@@ -1235,10 +1235,8 @@
unsigned long flags;
int rc = 0;
- if (cpu > num_possible_cpus()) {
- rc = -EINVAL;
- goto out;
- }
+ if (cpu > num_possible_cpus())
+ return -EINVAL;
if (reason == SETRATE_CPUFREQ || reason == SETRATE_HOTPLUG)
mutex_lock(&driver_lock);
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index c67109e..8cf9c2b 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -123,8 +123,8 @@
#define L2(x) (&l2_freq_tbl[(x)])
static struct l2_level l2_freq_tbl[] = {
- [0] = { {STBY_KHZ, QSB, 0, 0, 0 }, LVL_NOM, 1050000, 0 },
- [1] = { { 300000, PLL_0, 0, 2, 0 }, LVL_NOM, 1050000, 2 },
+ [0] = { {STBY_KHZ, QSB, 0, 0, 0 }, LVL_LOW, 1050000, 0 },
+ [1] = { { 300000, PLL_0, 0, 2, 0 }, LVL_LOW, 1050000, 2 },
[2] = { { 384000, HFPLL, 2, 0, 40 }, LVL_NOM, 1050000, 2 },
[3] = { { 460800, HFPLL, 2, 0, 48 }, LVL_NOM, 1050000, 2 },
[4] = { { 537600, HFPLL, 1, 0, 28 }, LVL_NOM, 1050000, 2 },
diff --git a/arch/arm/mach-msm/acpuclock-8x60.c b/arch/arm/mach-msm/acpuclock-8x60.c
index ef34b3c..f94f0b2 100644
--- a/arch/arm/mach-msm/acpuclock-8x60.c
+++ b/arch/arm/mach-msm/acpuclock-8x60.c
@@ -712,10 +712,8 @@
unsigned long flags;
int rc = 0;
- if (cpu > num_possible_cpus()) {
- rc = -EINVAL;
- goto out;
- }
+ if (cpu > num_possible_cpus())
+ return -EINVAL;
if (reason == SETRATE_CPUFREQ || reason == SETRATE_HOTPLUG)
mutex_lock(&drv_state.lock);
diff --git a/arch/arm/mach-msm/acpuclock-krait.c b/arch/arm/mach-msm/acpuclock-krait.c
index 84253b8..8bd54e3 100644
--- a/arch/arm/mach-msm/acpuclock-krait.c
+++ b/arch/arm/mach-msm/acpuclock-krait.c
@@ -385,10 +385,8 @@
unsigned long flags;
int rc = 0;
- if (cpu > num_possible_cpus()) {
- rc = -EINVAL;
- goto out;
- }
+ if (cpu > num_possible_cpus())
+ return -EINVAL;
if (reason == SETRATE_CPUFREQ || reason == SETRATE_HOTPLUG)
mutex_lock(&driver_lock);
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index 3df566c..813824e 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -183,6 +183,7 @@
static int bam_rx_pool_len;
static LIST_HEAD(bam_tx_pool);
static DEFINE_SPINLOCK(bam_tx_pool_spinlock);
+static DEFINE_MUTEX(bam_pdev_mutexlock);
struct bam_mux_hdr {
uint16_t magic_num;
@@ -433,30 +434,26 @@
mutex_lock(&bam_rx_pool_mutexlock);
list_add_tail(&info->list_node, &bam_rx_pool);
rx_len_cached = ++bam_rx_pool_len;
- mutex_unlock(&bam_rx_pool_mutexlock);
-
ret = sps_transfer_one(bam_rx_pipe, info->dma_address,
BUFFER_SIZE, info,
SPS_IOVEC_FLAG_INT | SPS_IOVEC_FLAG_EOT);
-
if (ret) {
+ list_del(&info->list_node);
+ rx_len_cached = --bam_rx_pool_len;
+ mutex_unlock(&bam_rx_pool_mutexlock);
DMUX_LOG_KERR("%s: sps_transfer_one failed %d\n",
__func__, ret);
- goto fail_transfer;
+
+ dma_unmap_single(NULL, info->dma_address, BUFFER_SIZE,
+ DMA_FROM_DEVICE);
+
+ goto fail_skb;
}
+ mutex_unlock(&bam_rx_pool_mutexlock);
+
}
return;
-fail_transfer:
- mutex_lock(&bam_rx_pool_mutexlock);
- list_del(&info->list_node);
- --bam_rx_pool_len;
- rx_len_cached = bam_rx_pool_len;
- mutex_unlock(&bam_rx_pool_mutexlock);
-
- dma_unmap_single(NULL, info->dma_address, BUFFER_SIZE,
- DMA_FROM_DEVICE);
-
fail_skb:
dev_kfree_skb_any(info->skb);
@@ -502,15 +499,24 @@
unsigned long flags;
int ret;
+ mutex_lock(&bam_pdev_mutexlock);
+ if (in_global_reset) {
+ bam_dmux_log("%s: open cid %d aborted due to ssr\n",
+ __func__, rx_hdr->ch_id);
+ mutex_unlock(&bam_pdev_mutexlock);
+ queue_rx();
+ return;
+ }
spin_lock_irqsave(&bam_ch[rx_hdr->ch_id].lock, flags);
bam_ch[rx_hdr->ch_id].status |= BAM_CH_REMOTE_OPEN;
bam_ch[rx_hdr->ch_id].num_tx_pkts = 0;
spin_unlock_irqrestore(&bam_ch[rx_hdr->ch_id].lock, flags);
- queue_rx();
ret = platform_device_add(bam_ch[rx_hdr->ch_id].pdev);
if (ret)
pr_err("%s: platform_device_add() error: %d\n",
__func__, ret);
+ mutex_unlock(&bam_pdev_mutexlock);
+ queue_rx();
}
static void handle_bam_mux_cmd(struct work_struct *work)
@@ -584,16 +590,24 @@
/* probably should drop pending write */
bam_dmux_log("%s: closing cid %d\n", __func__,
rx_hdr->ch_id);
+ mutex_lock(&bam_pdev_mutexlock);
+ if (in_global_reset) {
+ bam_dmux_log("%s: close cid %d aborted due to ssr\n",
+ __func__, rx_hdr->ch_id);
+ mutex_unlock(&bam_pdev_mutexlock);
+ break;
+ }
spin_lock_irqsave(&bam_ch[rx_hdr->ch_id].lock, flags);
bam_ch[rx_hdr->ch_id].status &= ~BAM_CH_REMOTE_OPEN;
spin_unlock_irqrestore(&bam_ch[rx_hdr->ch_id].lock, flags);
- queue_rx();
platform_device_unregister(bam_ch[rx_hdr->ch_id].pdev);
bam_ch[rx_hdr->ch_id].pdev =
platform_device_alloc(bam_ch[rx_hdr->ch_id].name, 2);
if (!bam_ch[rx_hdr->ch_id].pdev)
pr_err("%s: platform_device_alloc failed\n", __func__);
+ mutex_unlock(&bam_pdev_mutexlock);
dev_kfree_skb_any(rx_skb);
+ queue_rx();
break;
default:
DMUX_LOG_KERR("%s: dropping invalid hdr. magic %x"
@@ -1060,18 +1074,29 @@
mutex_lock(&bam_rx_pool_mutexlock);
if (unlikely(list_empty(&bam_rx_pool))) {
+ DMUX_LOG_KERR("%s: have iovec %p but rx pool empty\n",
+ __func__, (void *)iov.addr);
mutex_unlock(&bam_rx_pool_mutexlock);
continue;
}
info = list_first_entry(&bam_rx_pool, struct rx_pkt_info,
list_node);
+ if (info->dma_address != iov.addr) {
+ DMUX_LOG_KERR("%s: iovec %p != dma %p\n",
+ __func__,
+ (void *)iov.addr,
+ (void *)info->dma_address);
+ list_for_each_entry(info, &bam_rx_pool, list_node) {
+ DMUX_LOG_KERR("%s: dma %p\n", __func__,
+ (void *)info->dma_address);
+ if (iov.addr == info->dma_address)
+ break;
+ }
+ }
+ BUG_ON(info->dma_address != iov.addr);
list_del(&info->list_node);
--bam_rx_pool_len;
mutex_unlock(&bam_rx_pool_mutexlock);
- if (info->dma_address != iov.addr)
- DMUX_LOG_KERR("%s: iovec %p != dma %p\n",
- __func__,
- (void *)info->dma_address, (void *)iov.addr);
handle_bam_mux_cmd(&info->work);
}
return;
@@ -1105,13 +1130,30 @@
inactive_cycles = 0;
mutex_lock(&bam_rx_pool_mutexlock);
if (unlikely(list_empty(&bam_rx_pool))) {
+ DMUX_LOG_KERR(
+ "%s: have iovec %p but rx pool empty\n",
+ __func__, (void *)iov.addr);
mutex_unlock(&bam_rx_pool_mutexlock);
continue;
}
info = list_first_entry(&bam_rx_pool,
struct rx_pkt_info, list_node);
- --bam_rx_pool_len;
+ if (info->dma_address != iov.addr) {
+ DMUX_LOG_KERR("%s: iovec %p != dma %p\n",
+ __func__,
+ (void *)iov.addr,
+ (void *)info->dma_address);
+ list_for_each_entry(info, &bam_rx_pool,
+ list_node) {
+ DMUX_LOG_KERR("%s: dma %p\n", __func__,
+ (void *)info->dma_address);
+ if (iov.addr == info->dma_address)
+ break;
+ }
+ }
+ BUG_ON(info->dma_address != iov.addr);
list_del(&info->list_node);
+ --bam_rx_pool_len;
mutex_unlock(&bam_rx_pool_mutexlock);
handle_bam_mux_cmd(&info->work);
}
@@ -1873,6 +1915,7 @@
disconnect_ack = 0;
/* Cleanup Channel States */
+ mutex_lock(&bam_pdev_mutexlock);
for (i = 0; i < BAM_DMUX_NUM_CHANNELS; ++i) {
temp_remote_status = bam_ch_is_remote_open(i);
bam_ch[i].status &= ~BAM_CH_REMOTE_OPEN;
@@ -1885,6 +1928,7 @@
bam_ch[i].name, 2);
}
}
+ mutex_unlock(&bam_pdev_mutexlock);
/* Cleanup pending UL data */
spin_lock_irqsave(&bam_tx_pool_spinlock, flags);
diff --git a/arch/arm/mach-msm/board-8064-gpu.c b/arch/arm/mach-msm/board-8064-gpu.c
index 0f9c939..eb36a81e 100644
--- a/arch/arm/mach-msm/board-8064-gpu.c
+++ b/arch/arm/mach-msm/board-8064-gpu.c
@@ -13,10 +13,11 @@
#include <linux/init.h>
#include <linux/platform_device.h>
-#include <linux/msm_kgsl.h>
+#include <mach/kgsl.h>
#include <mach/msm_bus_board.h>
#include <mach/board.h>
#include <mach/msm_dcvs.h>
+#include <mach/socinfo.h>
#include "devices.h"
#include "board-8064.h"
@@ -247,5 +248,13 @@
void __init apq8064_init_gpu(void)
{
+ unsigned int version = socinfo_get_version();
+
+ if ((SOCINFO_VERSION_MAJOR(version) == 1) &&
+ (SOCINFO_VERSION_MINOR(version) == 1))
+ kgsl_3d0_pdata.chipid = ADRENO_CHIPID(3, 2, 0, 1);
+ else
+ kgsl_3d0_pdata.chipid = ADRENO_CHIPID(3, 2, 0, 0);
+
platform_device_register(&device_kgsl_3d0);
}
diff --git a/arch/arm/mach-msm/board-8930-gpu.c b/arch/arm/mach-msm/board-8930-gpu.c
index 632fc9a..105a5aa 100644
--- a/arch/arm/mach-msm/board-8930-gpu.c
+++ b/arch/arm/mach-msm/board-8930-gpu.c
@@ -13,7 +13,7 @@
#include <linux/init.h>
#include <linux/platform_device.h>
-#include <linux/msm_kgsl.h>
+#include <mach/kgsl.h>
#include <mach/msm_bus_board.h>
#include <mach/board.h>
#include <mach/socinfo.h>
@@ -135,7 +135,7 @@
.bus_freq = 0,
},
},
- .init_level = 0,
+ .init_level = 1,
.num_levels = 4,
.set_grp_async = NULL,
.idle_timeout = HZ/12,
@@ -160,8 +160,16 @@
void __init msm8930_init_gpu(void)
{
+ unsigned int version = socinfo_get_version();
+
if (cpu_is_msm8627())
kgsl_3d0_pdata.pwrlevel[0].gpu_freq = 400000000;
+ if ((SOCINFO_VERSION_MAJOR(version) == 1) &&
+ (SOCINFO_VERSION_MINOR(version) == 2))
+ kgsl_3d0_pdata.chipid = ADRENO_CHIPID(3, 0, 5, 2);
+ else
+ kgsl_3d0_pdata.chipid = ADRENO_CHIPID(3, 0, 5, 0);
+
platform_device_register(&device_kgsl_3d0);
}
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index f63b490..ec218ac 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -26,7 +26,6 @@
#include <linux/spi/spi.h>
#include <linux/slimbus/slimbus.h>
#include <linux/bootmem.h>
-#include <linux/msm_kgsl.h>
#ifdef CONFIG_ANDROID_PMEM
#include <linux/android_pmem.h>
#endif
@@ -80,6 +79,7 @@
#include <linux/fmem.h>
#include <mach/msm_cache_dump.h>
+#include <mach/kgsl.h>
#ifdef CONFIG_INPUT_MPU3050
#include <linux/input/mpu3050.h>
#endif
@@ -1741,7 +1741,7 @@
#define MXT_TS_GPIO_IRQ 11
#define MXT_TS_RESET_GPIO 52
-static const u8 mxt_config_data_8930[] = {
+static const u8 mxt_config_data_8930_v1[] = {
/* T6 Object */
0, 0, 0, 0, 0, 0,
/* T38 Object */
@@ -1786,6 +1786,43 @@
0, 0, 0, 0,
};
+static const u8 mxt_config_data_8930_v2[] = {
+ /* T6 Object */
+ 0, 0, 0, 0, 0, 0,
+ /* T38 Object */
+ 15, 4, 0, 9, 7, 12, 0, 0,
+ /* T7 Object */
+ 32, 16, 50,
+ /* T8 Object */
+ 30, 0, 5, 10, 0, 0, 10, 10, 0, 0,
+ /* T9 Object */
+ 131, 0, 0, 19, 11, 0, 16, 50, 1, 3,
+ 12, 7, 2, 0, 4, 5, 2, 10, 43, 4,
+ 54, 2, -25, 29, 38, 18, 143, 40, 207, 80,
+ 17, 5, 50, 50, 0,
+ /* T18 Object */
+ 0, 0,
+ /* T19 Object */
+ 0, 0, 0, 0, 0, 0,
+ /* T25 Object */
+ 0, 0, 0, 0, 0, 0,
+ /* T42 Object */
+ 3, 60, 20, 20, 150, 0, 0, 0,
+ /* T46 Object */
+ 0, 3, 28, 28, 0, 0, 1, 0, 0,
+ /* T47 Object */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* T48 Object */
+ 1, 3, 82, 0, 0, 0, 0, 0, 0, 0,
+ 16, 30, 0, 6, 6, 0, 0, 124, 4, 100,
+ 0, 0, 0, 5, 0, 42, 0, 1, 0, 40,
+ 52, 20, 0, 0, 0, 50, 1, 5, 2, 1,
+ 4, 5, 3, -25, 29, 38, 18, 143, 40, 207,
+ 80, 10, 5, 2,
+ /* T55 Object */
+ 0, 0, 0, 0,
+};
+
static ssize_t mxt224e_vkeys_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
@@ -1833,12 +1870,33 @@
static struct mxt_config_info mxt_config_array[] = {
{
- .config = mxt_config_data_8930,
- .config_length = ARRAY_SIZE(mxt_config_data_8930),
+ .config = mxt_config_data_8930_v1,
+ .config_length = ARRAY_SIZE(mxt_config_data_8930_v1),
.family_id = 0x81,
.variant_id = 0x01,
.version = 0x10,
.build = 0xAA,
+ .bootldr_id = MXT_BOOTLOADER_ID_224E,
+ .fw_name = "atmel_8930_fluid_v2_0_AB.hex",
+ },
+ {
+ .config = mxt_config_data_8930_v2,
+ .config_length = ARRAY_SIZE(mxt_config_data_8930_v2),
+ .family_id = 0x81,
+ .variant_id = 0x15,
+ .version = 0x11,
+ .build = 0xAA,
+ .bootldr_id = MXT_BOOTLOADER_ID_224E,
+ .fw_name = "atmel_8930_fluid_v2_0_AB.hex",
+ },
+ {
+ .config = mxt_config_data_8930_v2,
+ .config_length = ARRAY_SIZE(mxt_config_data_8930_v2),
+ .family_id = 0x81,
+ .variant_id = 0x01,
+ .version = 0x20,
+ .build = 0xAB,
+ .bootldr_id = MXT_BOOTLOADER_ID_224E,
},
};
diff --git a/arch/arm/mach-msm/board-8960-display.c b/arch/arm/mach-msm/board-8960-display.c
index 20e9d2b..88827ab 100644
--- a/arch/arm/mach-msm/board-8960-display.c
+++ b/arch/arm/mach-msm/board-8960-display.c
@@ -1005,6 +1005,9 @@
void __init msm8960_init_fb(void)
{
+ if (cpu_is_msm8960ab())
+ mdp_pdata.mdp_rev = MDP_REV_44;
+
platform_device_register(&msm_fb_device);
#ifdef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 4721c94..bb20d04 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -26,7 +26,6 @@
#include <linux/spi/spi.h>
#include <linux/slimbus/slimbus.h>
#include <linux/bootmem.h>
-#include <linux/msm_kgsl.h>
#ifdef CONFIG_ANDROID_PMEM
#include <linux/android_pmem.h>
#endif
@@ -87,6 +86,7 @@
#include <mach/scm.h>
#include <mach/iommu_domains.h>
+#include <mach/kgsl.h>
#include <linux/fmem.h>
#include "timer.h"
@@ -1911,18 +1911,9 @@
.gest_set = CY_GEST_GRP1 | CY_GEST_GRP2 |
CY_GEST_GRP3 | CY_GEST_GRP4 |
CY_ACT_DIST,
- /* change act_intrvl to customize the Active power state
- * scanning/processing refresh interval for Operating mode
- */
- .act_intrvl = CY_ACT_INTRVL_DFLT,
- /* change tch_tmout to customize the touch timeout for the
- * Active power state for Operating mode
- */
- .tch_tmout = CY_TCH_TMOUT_DFLT,
- /* change lp_intrvl to customize the Low Power power state
- * scanning/processing refresh interval for Operating mode
- */
- .lp_intrvl = CY_LP_INTRVL_DFLT,
+ .act_intrvl = 10,
+ .tch_tmout = 200,
+ .lp_intrvl = 30,
.sleep_gpio = CYTTSP_TS_SLEEP_GPIO,
.resout_gpio = CYTTSP_TS_RESOUT_N_GPIO,
.irq_gpio = CYTTSP_TS_GPIO_IRQ,
@@ -2049,7 +2040,7 @@
/* T6 Object */
0, 0, 0, 0, 0, 0,
/* T38 Object */
- 12, 3, 0, 24, 5, 12, 0, 0, 0, 0,
+ 12, 4, 0, 5, 7, 12, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -2062,7 +2053,7 @@
25, 0, 20, 20, 0, 0, 20, 50, 0, 0,
/* T9 Object */
139, 0, 0, 26, 42, 0, 32, 80, 2, 5,
- 0, 5, 5, 0, 10, 30, 10, 10, 255, 2,
+ 0, 5, 5, 79, 10, 30, 10, 10, 255, 2,
85, 5, 10, 10, 10, 10, 135, 55, 70, 40,
10, 5, 0, 0, 0,
/* T18 Object */
@@ -2082,7 +2073,7 @@
0, 0, 0, 0, 0, 0, 0, 64, 0, 8,
16,
/* T46 Object */
- 64, 0, 20, 20, 0, 0, 0, 0, 0,
+ 64, 0, 16, 16, 0, 0, 0, 0, 0,
/* T47 Object */
0, 0, 0, 0, 0, 0, 3, 64, 66, 0,
/* T48 Object */
@@ -2476,7 +2467,6 @@
&msm8960_device_dmov,
&msm_device_smd,
&msm_device_uart_dm6,
- &msm_device_uart_dm9,
&msm_device_saw_core0,
&msm_device_saw_core1,
&msm8960_device_ext_5v_vreg,
@@ -2696,13 +2686,26 @@
static void __init msm8960_gfx_init(void)
{
+ struct kgsl_device_platform_data *kgsl_3d0_pdata =
+ msm_kgsl_3d0.dev.platform_data;
uint32_t soc_platform_version = socinfo_get_version();
+
if (SOCINFO_VERSION_MAJOR(soc_platform_version) == 1) {
- struct kgsl_device_platform_data *kgsl_3d0_pdata =
- msm_kgsl_3d0.dev.platform_data;
kgsl_3d0_pdata->pwrlevel[0].gpu_freq = 320000000;
kgsl_3d0_pdata->pwrlevel[1].gpu_freq = 266667000;
}
+ if (cpu_is_msm8960ab()) {
+ kgsl_3d0_pdata->chipid = ADRENO_CHIPID(3, 2, 1, 0);
+ } else {
+
+ /* 8960v3 GPU registers returns 5 for patch release
+ * but it should be 6, so dummy up the chipid here
+ * based the platform type
+ */
+
+ if (SOCINFO_VERSION_MAJOR(soc_platform_version) >= 3)
+ kgsl_3d0_pdata->chipid = ADRENO_CHIPID(2, 2, 0, 6);
+ }
}
static struct msm_rpmrs_level msm_rpmrs_levels[] = {
@@ -3133,6 +3136,7 @@
if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE) {
msm_uart_dm9_pdata.wakeup_irq = gpio_to_irq(94); /* GSBI9(2) */
msm_device_uart_dm9.dev.platform_data = &msm_uart_dm9_pdata;
+ platform_device_register(&msm_device_uart_dm9);
}
platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
diff --git a/arch/arm/mach-msm/board-8974.c b/arch/arm/mach-msm/board-8974.c
index 557331a..8cbde5f 100644
--- a/arch/arm/mach-msm/board-8974.c
+++ b/arch/arm/mach-msm/board-8974.c
@@ -640,6 +640,8 @@
OF_DEV_AUXDATA("qcom,qseecom", 0xFE806000, \
"qseecom", NULL),
OF_DEV_AUXDATA("qcom,mdss_mdp", 0xFD900000, "mdp.0", NULL),
+ OF_DEV_AUXDATA("qcom,msm-tsens", 0xFC4A8000, \
+ "msm-tsens", NULL),
{}
};
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index bb94474..ea12570 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -125,6 +125,13 @@
#define PMEM_KERNEL_EBI0_SIZE 0x600000
#define MSM_PMEM_AUDIO_SIZE 0x200000
+#ifdef CONFIG_ION_MSM
+static struct platform_device ion_dev;
+#define MSM_ION_AUDIO_SIZE (MSM_PMEM_AUDIO_SIZE + PMEM_KERNEL_EBI0_SIZE)
+#define MSM_ION_SF_SIZE MSM_PMEM_SF_SIZE
+#define MSM_ION_HEAP_NUM 4
+#endif
+
#define PMIC_GPIO_INT 27
#define PMIC_VREG_WLAN_LEVEL 2900
#define PMIC_GPIO_SD_DET 36
@@ -5481,7 +5488,10 @@
&msm_adc_device,
&msm_ebi0_thermal,
&msm_ebi1_thermal,
- &msm_adsp_device
+ &msm_adsp_device,
+#ifdef CONFIG_ION_MSM
+ &ion_dev,
+#endif
};
static struct msm_gpio msm_i2c_gpios_hw[] = {
@@ -7145,6 +7155,65 @@
}
early_param("pmem_kernel_ebi0_size", pmem_kernel_ebi0_size_setup);
+#ifdef CONFIG_ION_MSM
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+static struct ion_co_heap_pdata co_ion_pdata = {
+ .adjacent_mem_id = INVALID_HEAP_ID,
+ .align = PAGE_SIZE,
+};
+#endif
+
+/**
+ * These heaps are listed in the order they will be allocated.
+ * Don't swap the order unless you know what you are doing!
+ */
+static struct ion_platform_data ion_pdata = {
+ .nr = MSM_ION_HEAP_NUM,
+ .heaps = {
+ {
+ .id = ION_SYSTEM_HEAP_ID,
+ .type = ION_HEAP_TYPE_SYSTEM,
+ .name = ION_VMALLOC_HEAP_NAME,
+ },
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ /* PMEM_ADSP = CAMERA */
+ {
+ .id = ION_CAMERA_HEAP_ID,
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .name = ION_CAMERA_HEAP_NAME,
+ .memory_type = ION_EBI_TYPE,
+ .has_outer_cache = 1,
+ .extra_data = (void *)&co_ion_pdata,
+ },
+ /* PMEM_AUDIO */
+ {
+ .id = ION_AUDIO_HEAP_ID,
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .name = ION_AUDIO_HEAP_NAME,
+ .memory_type = ION_EBI_TYPE,
+ .has_outer_cache = 1,
+ .extra_data = (void *)&co_ion_pdata,
+ },
+ /* PMEM_MDP = SF */
+ {
+ .id = ION_SF_HEAP_ID,
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .name = ION_SF_HEAP_NAME,
+ .memory_type = ION_EBI_TYPE,
+ .has_outer_cache = 1,
+ .extra_data = (void *)&co_ion_pdata,
+ },
+#endif
+ }
+};
+
+static struct platform_device ion_dev = {
+ .name = "ion-msm",
+ .id = 1,
+ .dev = { .platform_data = &ion_pdata },
+};
+#endif
+
static struct memtype_reserve msm7x30_reserve_table[] __initdata = {
[MEMTYPE_SMI] = {
},
@@ -7156,34 +7225,52 @@
},
};
-static void __init size_pmem_devices(void)
-{
-#ifdef CONFIG_ANDROID_PMEM
- unsigned long size;
+unsigned long size;
+unsigned long msm_ion_camera_size;
+static void fix_sizes(void)
+{
if machine_is_msm7x30_fluid()
size = fluid_pmem_adsp_size;
else
size = pmem_adsp_size;
+
+#ifdef CONFIG_ION_MSM
+ msm_ion_camera_size = size;
+#endif
+}
+
+static void __init size_pmem_devices(void)
+{
+#ifdef CONFIG_ANDROID_PMEM
+#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
+
android_pmem_adsp_pdata.size = size;
android_pmem_audio_pdata.size = pmem_audio_size;
android_pmem_pdata.size = pmem_sf_size;
#endif
+#endif
}
+#ifdef CONFIG_ANDROID_PMEM
+#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
static void __init reserve_memory_for(struct android_pmem_platform_data *p)
{
msm7x30_reserve_table[p->memory_type].size += p->size;
}
+#endif
+#endif
static void __init reserve_pmem_memory(void)
{
#ifdef CONFIG_ANDROID_PMEM
+#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
reserve_memory_for(&android_pmem_adsp_pdata);
reserve_memory_for(&android_pmem_audio_pdata);
reserve_memory_for(&android_pmem_pdata);
msm7x30_reserve_table[MEMTYPE_EBI0].size += pmem_kernel_ebi0_size;
#endif
+#endif
}
static void __init reserve_mdp_memory(void)
@@ -7192,11 +7279,32 @@
msm7x30_reserve_table[mdp_pdata.mem_hid].size += mdp_pdata.ov0_wb_size;
}
+static void __init size_ion_devices(void)
+{
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ ion_pdata.heaps[1].size = msm_ion_camera_size;
+ ion_pdata.heaps[2].size = MSM_ION_AUDIO_SIZE;
+ ion_pdata.heaps[3].size = MSM_ION_SF_SIZE;
+#endif
+}
+
+static void __init reserve_ion_memory(void)
+{
+#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
+ msm7x30_reserve_table[MEMTYPE_EBI0].size += msm_ion_camera_size;
+ msm7x30_reserve_table[MEMTYPE_EBI0].size += MSM_ION_AUDIO_SIZE;
+ msm7x30_reserve_table[MEMTYPE_EBI0].size += MSM_ION_SF_SIZE;
+#endif
+}
+
static void __init msm7x30_calculate_reserve_sizes(void)
{
+ fix_sizes();
size_pmem_devices();
reserve_pmem_memory();
reserve_mdp_memory();
+ size_ion_devices();
+ reserve_ion_memory();
}
static int msm7x30_paddr_to_memtype(unsigned int paddr)
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index 5b9ea36..8182fc4 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -144,6 +144,7 @@
static struct android_usb_platform_data android_usb_pdata = {
.update_pid_and_serial_num = usb_diag_update_pid_and_serial_num,
+ .cdrom = 1,
};
static struct platform_device android_usb_device = {
diff --git a/arch/arm/mach-msm/board-swordfish.c b/arch/arm/mach-msm/board-swordfish.c
index 45d5bb0..7262277 100644
--- a/arch/arm/mach-msm/board-swordfish.c
+++ b/arch/arm/mach-msm/board-swordfish.c
@@ -21,7 +21,7 @@
#include <linux/delay.h>
#include <linux/fs.h>
#include <linux/android_pmem.h>
-#include <linux/msm_kgsl.h>
+#include <mach/kgsl.h>
#include <mach/hardware.h>
#include <asm/mach-types.h>
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index f99e5de8..2a4566e 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -5109,7 +5109,10 @@
CLK_LOOKUP("core_clk", sdc2_clk.c, "msm_sdcc.2"),
CLK_LOOKUP("core_clk", sdc3_clk.c, "msm_sdcc.3"),
CLK_LOOKUP("core_clk", sdc4_clk.c, "msm_sdcc.4"),
- CLK_LOOKUP("ref_clk", tsif_ref_clk.c, ""),
+ CLK_LOOKUP("ref_clk", tsif_ref_clk.c, "msm_tsif.0"),
+ CLK_LOOKUP("iface_clk", tsif_p_clk.c, "msm_tsif.0"),
+ CLK_LOOKUP("ref_clk", tsif_ref_clk.c, "msm_tsif.1"),
+ CLK_LOOKUP("iface_clk", tsif_p_clk.c, "msm_tsif.1"),
CLK_LOOKUP("core_clk", tssc_clk.c, ""),
CLK_LOOKUP("alt_core_clk", usb_hs1_xcvr_clk.c, "msm_otg"),
CLK_LOOKUP("alt_core_clk", usb_hs3_xcvr_clk.c, "msm_ehci_host.0"),
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 6c9a566..930de81 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -593,10 +593,12 @@
#define RPM_MEM_CLK_TYPE 0x326b6c63
#define CXO_ID 0x0
+#define QDSS_ID 0x1
#define PNOC_ID 0x0
#define SNOC_ID 0x1
#define CNOC_ID 0x2
+#define MMSSNOC_AHB_ID 0x4
#define BIMC_ID 0x0
#define OCMEM_ID 0x1
@@ -604,6 +606,8 @@
DEFINE_CLK_RPM_SMD(pnoc_clk, pnoc_a_clk, RPM_BUS_CLK_TYPE, PNOC_ID, NULL);
DEFINE_CLK_RPM_SMD(snoc_clk, snoc_a_clk, RPM_BUS_CLK_TYPE, SNOC_ID, NULL);
DEFINE_CLK_RPM_SMD(cnoc_clk, cnoc_a_clk, RPM_BUS_CLK_TYPE, CNOC_ID, NULL);
+DEFINE_CLK_RPM_SMD(mmssnoc_ahb_clk, mmssnoc_ahb_a_clk, RPM_BUS_CLK_TYPE,
+ MMSSNOC_AHB_ID, NULL);
DEFINE_CLK_RPM_SMD(bimc_clk, bimc_a_clk, RPM_MEM_CLK_TYPE, BIMC_ID, NULL);
DEFINE_CLK_RPM_SMD(ocmemgx_clk, ocmemgx_a_clk, RPM_MEM_CLK_TYPE, OCMEM_ID,
@@ -611,6 +615,7 @@
DEFINE_CLK_RPM_SMD_BRANCH(cxo_clk_src, cxo_a_clk_src,
RPM_MISC_CLK_TYPE, CXO_ID, 19200000);
+DEFINE_CLK_RPM_SMD_QDSS(qdss_clk, qdss_a_clk, RPM_MISC_CLK_TYPE, QDSS_ID);
static struct pll_vote_clk gpll0_clk_src = {
.en_reg = (void __iomem *)APCS_GPLL_ENA_VOTE_REG,
@@ -4830,6 +4835,36 @@
CLK_LOOKUP("bus_a_clk", ocmemnoc_clk.c, "msm_ocmem_noc"),
CLK_LOOKUP("bus_clk", mmss_mmssnoc_axi_clk.c, "msm_mmss_noc"),
CLK_LOOKUP("bus_a_clk", mmss_mmssnoc_axi_clk.c, "msm_mmss_noc"),
+
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-tmc-etr"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-tpiu"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-replicator"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-tmc-etf"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-funnel-merg"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-funnel-in0"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-funnel-in1"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-funnel-kpss"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-funnel-mmss"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-stm"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm0"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm1"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm2"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm3"),
+
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-tmc-etr"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-tpiu"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-replicator"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-tmc-etf"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-funnel-merg"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-funnel-in0"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-funnel-in1"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-funnel-kpss"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-funnel-mmss"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-stm"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-etm0"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-etm1"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-etm2"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-etm3"),
};
static struct pll_config_regs gpll0_regs __initdata = {
@@ -5028,6 +5063,13 @@
clk_set_rate(&ocmemnoc_clk_src.c, 333330000);
/*
+ * Hold an active set vote at a rate of 40MHz for the MMSS NOC AHB
+ * source. Sleep set vote is 0.
+ */
+ clk_set_rate(&mmssnoc_ahb_a_clk.c, 40000000);
+ clk_prepare_enable(&mmssnoc_ahb_a_clk.c);
+
+ /*
* Hold an active set vote for CXO; this is because CXO is expected
* to remain on whenever CPUs aren't power collapsed.
*/
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index 4493ddc..1769f07 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -3522,6 +3522,7 @@
CLK_LOOKUP("mem_a_clk", ebi1_msmbus_a_clk.c, "msm_bus"),
CLK_LOOKUP("smi_clk", smi_clk.c, "msm_bus"),
CLK_LOOKUP("smi_a_clk", smi_a_clk.c, "msm_bus"),
+ CLK_LOOKUP("mmfpb_a_clk", mmfpb_a_clk.c, "clock-8x60"),
CLK_LOOKUP("core_clk", gp0_clk.c, ""),
CLK_LOOKUP("core_clk", gp1_clk.c, ""),
@@ -3873,7 +3874,7 @@
int rc;
/* Vote for MMFPB to be at least 64MHz when an Apps CPU is active. */
- struct clk *mmfpb_a_clk = clk_get(NULL, "mmfpb_a_clk");
+ struct clk *mmfpb_a_clk = clk_get_sys("clock-8x60", "mmfpb_a_clk");
if (WARN(IS_ERR(mmfpb_a_clk), "mmfpb_a_clk not found (%ld)\n",
PTR_ERR(mmfpb_a_clk)))
return PTR_ERR(mmfpb_a_clk);
diff --git a/arch/arm/mach-msm/clock-dss-8960.c b/arch/arm/mach-msm/clock-dss-8960.c
index d9ad103..4e17b29 100644
--- a/arch/arm/mach-msm/clock-dss-8960.c
+++ b/arch/arm/mach-msm/clock-dss-8960.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2012, 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
@@ -166,6 +166,13 @@
*/
udelay(10);
writel_relaxed(0x0D, HDMI_PHY_PLL_LOCKDET_CFG2);
+
+ /*
+ * Wait for a short duration for the PLL calibration
+ * before checking if the PLL gets locked
+ */
+ udelay(350);
+
timeout_count = 1000;
pll_lock_retry--;
}
@@ -176,6 +183,7 @@
if (!pll_lock_retry) {
pr_err("%s: HDMI PLL not locked\n", __func__);
+ hdmi_pll_disable();
return -EAGAIN;
}
diff --git a/arch/arm/mach-msm/clock-rpm.c b/arch/arm/mach-msm/clock-rpm.c
index 8096c10..207dbef 100644
--- a/arch/arm/mach-msm/clock-rpm.c
+++ b/arch/arm/mach-msm/clock-rpm.c
@@ -54,15 +54,11 @@
return (rc < 0) ? rc : iv.value * r->factor;
}
-#define RPM_SMD_KEY_RATE 0x007A484B
-#define RPM_SMD_KEY_ENABLE 0x62616E45
-
static int clk_rpmrs_set_rate_smd(struct rpm_clk *r, uint32_t value,
uint32_t context, int noirq)
{
- u32 rpm_key = r->branch ? RPM_SMD_KEY_ENABLE : RPM_SMD_KEY_RATE;
struct msm_rpm_kvp kvp = {
- .key = rpm_key,
+ .key = r->rpm_key,
.data = (void *)&value,
.length = sizeof(value),
};
diff --git a/arch/arm/mach-msm/clock-rpm.h b/arch/arm/mach-msm/clock-rpm.h
index ce878ce..22691c5 100644
--- a/arch/arm/mach-msm/clock-rpm.h
+++ b/arch/arm/mach-msm/clock-rpm.h
@@ -17,6 +17,10 @@
#include <mach/rpm.h>
#include <mach/rpm-smd.h>
+#define RPM_SMD_KEY_RATE 0x007A484B
+#define RPM_SMD_KEY_ENABLE 0x62616E45
+#define RPM_SMD_KEY_STATE 0x54415453
+
struct clk_ops;
struct clk_rpmrs_data;
extern struct clk_ops clk_ops_rpm;
@@ -24,6 +28,7 @@
struct rpm_clk {
const int rpm_res_type;
+ const int rpm_key;
const int rpm_clk_id;
const int rpm_status_id;
const bool active_only;
@@ -47,12 +52,14 @@
extern struct clk_rpmrs_data clk_rpmrs_data;
extern struct clk_rpmrs_data clk_rpmrs_data_smd;
-#define __DEFINE_CLK_RPM(name, active, type, r_id, stat_id, dep, rpmrsdata) \
+#define __DEFINE_CLK_RPM(name, active, type, r_id, stat_id, dep, key, \
+ rpmrsdata) \
static struct rpm_clk active; \
static struct rpm_clk name = { \
.rpm_res_type = (type), \
.rpm_clk_id = (r_id), \
.rpm_status_id = (stat_id), \
+ .rpm_key = (key), \
.peer = &active, \
.factor = 1000, \
.rpmrs_data = (rpmrsdata),\
@@ -67,6 +74,7 @@
.rpm_res_type = (type), \
.rpm_clk_id = (r_id), \
.rpm_status_id = (stat_id), \
+ .rpm_key = (key), \
.peer = &name, \
.active_only = true, \
.factor = 1000, \
@@ -80,12 +88,13 @@
};
#define __DEFINE_CLK_RPM_BRANCH(name, active, type, r_id, stat_id, r, \
- rpmrsdata) \
+ key, rpmrsdata) \
static struct rpm_clk active; \
static struct rpm_clk name = { \
.rpm_res_type = (type), \
.rpm_clk_id = (r_id), \
.rpm_status_id = (stat_id), \
+ .rpm_key = (key), \
.peer = &active, \
.last_set_khz = ((r) / 1000), \
.last_set_sleep_khz = ((r) / 1000), \
@@ -104,6 +113,7 @@
.rpm_res_type = (type), \
.rpm_clk_id = (r_id), \
.rpm_status_id = (stat_id), \
+ .rpm_key = (key), \
.peer = &name, \
.last_set_khz = ((r) / 1000), \
.active_only = true, \
@@ -119,12 +129,14 @@
}, \
};
-#define __DEFINE_CLK_RPM_QDSS(name, active, type, r_id, stat_id, rpmrsdata) \
+#define __DEFINE_CLK_RPM_QDSS(name, active, type, r_id, stat_id, \
+ key, rpmrsdata) \
static struct rpm_clk active; \
static struct rpm_clk name = { \
.rpm_res_type = (type), \
.rpm_clk_id = (r_id), \
.rpm_status_id = (stat_id), \
+ .rpm_key = (key), \
.peer = &active, \
.factor = 1, \
.rpmrs_data = (rpmrsdata),\
@@ -139,6 +151,7 @@
.rpm_res_type = (type), \
.rpm_clk_id = (r_id), \
.rpm_status_id = (stat_id), \
+ .rpm_key = (key), \
.peer = &name, \
.active_only = true, \
.factor = 1, \
@@ -153,21 +166,26 @@
#define DEFINE_CLK_RPM(name, active, r_id, dep) \
__DEFINE_CLK_RPM(name, active, 0, MSM_RPM_ID_##r_id##_CLK, \
- MSM_RPM_STATUS_ID_##r_id##_CLK, dep, &clk_rpmrs_data)
+ MSM_RPM_STATUS_ID_##r_id##_CLK, dep, 0, &clk_rpmrs_data)
#define DEFINE_CLK_RPM_QDSS(name, active) \
__DEFINE_CLK_RPM_QDSS(name, active, 0, MSM_RPM_ID_QDSS_CLK, \
- MSM_RPM_STATUS_ID_QDSS_CLK, &clk_rpmrs_data)
+ MSM_RPM_STATUS_ID_QDSS_CLK, 0, &clk_rpmrs_data)
#define DEFINE_CLK_RPM_BRANCH(name, active, r_id, r) \
__DEFINE_CLK_RPM_BRANCH(name, active, 0, MSM_RPM_ID_##r_id##_CLK, \
- MSM_RPM_STATUS_ID_##r_id##_CLK, r, &clk_rpmrs_data)
+ MSM_RPM_STATUS_ID_##r_id##_CLK, r, 0, &clk_rpmrs_data)
#define DEFINE_CLK_RPM_SMD(name, active, type, r_id, dep) \
- __DEFINE_CLK_RPM(name, active, type, r_id, 0, dep, &clk_rpmrs_data_smd)
+ __DEFINE_CLK_RPM(name, active, type, r_id, 0, dep, \
+ RPM_SMD_KEY_RATE, &clk_rpmrs_data_smd)
-#define DEFINE_CLK_RPM_SMD_BRANCH(name, active, type, r_id, dep) \
- __DEFINE_CLK_RPM_BRANCH(name, active, type, r_id, 0, dep, \
- &clk_rpmrs_data_smd)
+#define DEFINE_CLK_RPM_SMD_BRANCH(name, active, type, r_id, r) \
+ __DEFINE_CLK_RPM_BRANCH(name, active, type, r_id, 0, r, \
+ RPM_SMD_KEY_ENABLE, &clk_rpmrs_data_smd)
+
+#define DEFINE_CLK_RPM_SMD_QDSS(name, active, type, r_id) \
+ __DEFINE_CLK_RPM_QDSS(name, active, type, r_id, \
+ 0, RPM_SMD_KEY_STATE, &clk_rpmrs_data_smd)
#endif
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index 56d3c6f..df2aa4e 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -181,7 +181,7 @@
int clock_debug_add(struct clk *clock);
void clock_debug_print_enabled(void);
#else
-static inline int clock_debug_init(struct clk_init_data *data) { return 0; }
+static inline int clock_debug_init(struct clock_init_data *data) { return 0; }
static inline int clock_debug_add(struct clk *clock) { return 0; }
static inline void clock_debug_print_enabled(void) { return; }
#endif
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 7d93fe7..79f8c88 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -19,7 +19,7 @@
#include <linux/gpio.h>
#include <linux/coresight.h>
#include <asm/clkdev.h>
-#include <linux/msm_kgsl.h>
+#include <mach/kgsl.h>
#include <linux/android_pmem.h>
#include <mach/irqs-8960.h>
#include <mach/dma.h>
diff --git a/arch/arm/mach-msm/devices-iommu.c b/arch/arm/mach-msm/devices-iommu.c
index 1432902..ae8a8fe 100644
--- a/arch/arm/mach-msm/devices-iommu.c
+++ b/arch/arm/mach-msm/devices-iommu.c
@@ -1011,7 +1011,7 @@
ARRAY_SIZE(msm_iommu_gfx2d_devs));
}
- if (cpu_is_apq8064()) {
+ if (cpu_is_apq8064() || cpu_is_msm8960ab()) {
platform_add_devices(msm_iommu_jpegd_devs,
ARRAY_SIZE(msm_iommu_jpegd_devs));
platform_add_devices(msm_iommu_8064_devs,
@@ -1030,7 +1030,7 @@
ARRAY_SIZE(msm_iommu_gfx2d_ctx_devs));
}
- if (cpu_is_apq8064()) {
+ if (cpu_is_apq8064() || cpu_is_msm8960ab()) {
platform_add_devices(msm_iommu_jpegd_ctx_devs,
ARRAY_SIZE(msm_iommu_jpegd_ctx_devs));
platform_add_devices(msm_iommu_8064_ctx_devs,
@@ -1069,7 +1069,7 @@
platform_device_unregister(msm_iommu_jpegd_devs[i]);
}
- if (cpu_is_apq8064()) {
+ if (cpu_is_apq8064() || cpu_is_msm8960ab()) {
for (i = 0; i < ARRAY_SIZE(msm_iommu_8064_ctx_devs); i++)
platform_device_unregister(msm_iommu_8064_ctx_devs[i]);
diff --git a/arch/arm/mach-msm/devices-msm7x27.c b/arch/arm/mach-msm/devices-msm7x27.c
index 4619cca..69d7430 100644
--- a/arch/arm/mach-msm/devices-msm7x27.c
+++ b/arch/arm/mach-msm/devices-msm7x27.c
@@ -15,7 +15,7 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
-#include <linux/msm_kgsl.h>
+#include <mach/kgsl.h>
#include <linux/regulator/machine.h>
#include <linux/dma-mapping.h>
#include <linux/init.h>
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index c159926..8912e96 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -13,7 +13,7 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
-#include <linux/msm_kgsl.h>
+#include <mach/kgsl.h>
#include <linux/regulator/machine.h>
#include <linux/init.h>
#include <linux/irq.h>
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index 4b02f7a..f04ef9d 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -17,7 +17,7 @@
#include <linux/platform_device.h>
#include <linux/msm_rotator.h>
#include <linux/dma-mapping.h>
-#include <linux/msm_kgsl.h>
+#include <mach/kgsl.h>
#include <linux/android_pmem.h>
#include <linux/regulator/machine.h>
#include <linux/init.h>
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index 2ced412..3920abe 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -20,7 +20,7 @@
#include <mach/dma.h>
#include <asm/mach/mmc.h>
#include <asm/clkdev.h>
-#include <linux/msm_kgsl.h>
+#include <mach/kgsl.h>
#include <linux/msm_rotator.h>
#include <mach/msm_hsusb.h>
#include "footswitch.h"
diff --git a/arch/arm/mach-msm/devices-qsd8x50.c b/arch/arm/mach-msm/devices-qsd8x50.c
index 2ecc852..ec4a14f 100644
--- a/arch/arm/mach-msm/devices-qsd8x50.c
+++ b/arch/arm/mach-msm/devices-qsd8x50.c
@@ -15,7 +15,7 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
-#include <linux/msm_kgsl.h>
+#include <mach/kgsl.h>
#include <linux/dma-mapping.h>
#include <asm/clkdev.h>
diff --git a/arch/arm/mach-msm/dma.c b/arch/arm/mach-msm/dma.c
index e5dca00..12f5aa9 100644
--- a/arch/arm/mach-msm/dma.c
+++ b/arch/arm/mach-msm/dma.c
@@ -356,7 +356,7 @@
}
if (!dmov_conf[adm].channel_active) {
dmov_conf[adm].clk_ctl = CLK_TO_BE_DIS;
- schedule_delayed_work(&dmov_conf[adm].work, HZ);
+ schedule_delayed_work(&dmov_conf[adm].work, (HZ/10));
}
spin_unlock_irqrestore(&dmov_conf[adm].list_lock, flags);
error:
@@ -573,7 +573,7 @@
if (!dmov_conf[adm].channel_active && valid) {
disable_irq_nosync(dmov_conf[adm].irq);
dmov_conf[adm].clk_ctl = CLK_TO_BE_DIS;
- schedule_delayed_work(&dmov_conf[adm].work, HZ);
+ schedule_delayed_work(&dmov_conf[adm].work, (HZ/10));
}
mutex_unlock(&dmov_conf[adm].lock);
diff --git a/arch/arm/mach-msm/gss-8064.c b/arch/arm/mach-msm/gss-8064.c
index b9b877a..e528650 100644
--- a/arch/arm/mach-msm/gss-8064.c
+++ b/arch/arm/mach-msm/gss-8064.c
@@ -43,6 +43,8 @@
static int crash_shutdown;
+static struct subsys_device *gss_8064_dev;
+
#define MAX_SSR_REASON_LEN 81U
static void log_gss_sfr(void)
@@ -72,7 +74,7 @@
static void restart_gss(void)
{
log_gss_sfr();
- subsystem_restart("gss");
+ subsystem_restart_dev(gss_8064_dev);
}
static void smsm_state_cb(void *data, uint32_t old_state, uint32_t new_state)
@@ -91,7 +93,7 @@
#define Q6_FW_WDOG_ENABLE 0x08882024
#define Q6_SW_WDOG_ENABLE 0x08982024
-static int gss_shutdown(const struct subsys_data *subsys)
+static int gss_shutdown(const struct subsys_desc *desc)
{
pil_force_shutdown("gss");
disable_irq_nosync(GSS_A5_WDOG_EXPIRED);
@@ -99,14 +101,14 @@
return 0;
}
-static int gss_powerup(const struct subsys_data *subsys)
+static int gss_powerup(const struct subsys_desc *desc)
{
pil_force_boot("gss");
enable_irq(GSS_A5_WDOG_EXPIRED);
return 0;
}
-void gss_crash_shutdown(const struct subsys_data *subsys)
+void gss_crash_shutdown(const struct subsys_desc *desc)
{
crash_shutdown = 1;
smsm_reset_modem(SMSM_RESET);
@@ -122,7 +124,7 @@
};
static int gss_ramdump(int enable,
- const struct subsys_data *crashed_subsys)
+ const struct subsys_desc *crashed_subsys)
{
int ret = 0;
@@ -157,7 +159,7 @@
return IRQ_HANDLED;
}
-static struct subsys_data gss_8064 = {
+static struct subsys_desc gss_8064 = {
.name = "gss",
.shutdown = gss_shutdown,
.powerup = gss_powerup,
@@ -167,7 +169,10 @@
static int gss_subsystem_restart_init(void)
{
- return ssr_register_subsystem(&gss_8064);
+ gss_8064_dev = subsys_register(&gss_8064);
+ if (IS_ERR(gss_8064_dev))
+ return PTR_ERR(gss_8064_dev);
+ return 0;
}
static int gss_open(struct inode *inode, struct file *filep)
diff --git a/arch/arm/mach-msm/idle-v7.S b/arch/arm/mach-msm/idle-v7.S
index b75f76f..ff7af32 100644
--- a/arch/arm/mach-msm/idle-v7.S
+++ b/arch/arm/mach-msm/idle-v7.S
@@ -28,6 +28,35 @@
#endif
ENTRY(msm_arch_idle)
+#ifdef CONFIG_ARCH_MSM_KRAIT
+ mrc p15, 0, r0, c0, c0, 0
+ bic r1, r0, #0xff
+ movw r2, #0x0400
+ movt r2, #0x511F
+ movw r3, #0x0600
+ movt r3, #0x510F
+ cmp r2, r1
+ cmpne r3, r1
+ bne go_wfi
+
+ mrs r0, cpsr
+ cpsid if
+
+ mrc p15, 7, r1, c15, c0, 5
+ bic r2, r1, #0x20000
+ mcr p15, 7, r2, c15, c0, 5
+ isb
+
+go_wfi:
+ wfi
+ bne wfi_done
+ mcr p15, 7, r1, c15, c0, 5
+ isb
+ msr cpsr_c, r0
+
+wfi_done:
+ bx lr
+#else
wfi
#ifdef CONFIG_ARCH_MSM8X60
mrc p14, 1, r1, c1, c5, 4 /* read ETM PDSR to clear sticky bit */
@@ -35,6 +64,7 @@
isb
#endif
bx lr
+#endif
ENTRY(msm_pm_collapse)
#if defined(CONFIG_MSM_FIQ_SUPPORT)
diff --git a/arch/arm/mach-msm/include/mach/dma.h b/arch/arm/mach-msm/include/mach/dma.h
index ba621e6..381ea12 100644
--- a/arch/arm/mach-msm/include/mach/dma.h
+++ b/arch/arm/mach-msm/include/mach/dma.h
@@ -263,6 +263,9 @@
#define DMOV8064_CE_OUT_CHAN 1
#define DMOV8064_CE_OUT_CRCI 15
+#define DMOV8064_TSIF_CHAN 2
+#define DMOV8064_TSIF_CRCI 1
+
/* no client rate control ifc (eg, ram) */
#define DMOV_NONE_CRCI 0
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index 4bfbe61..28c53db 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -35,6 +35,9 @@
*/
#define MAX_NUM_MIDS 32
+/* Maximum number of SMT entries allowed by the system */
+#define MAX_NUM_SMR 128
+
/**
* struct msm_iommu_dev - a single IOMMU hardware instance
* name Human-readable name given to this IOMMU HW instance
@@ -69,6 +72,9 @@
* @irq: Interrupt number
* @clk: The bus clock for this IOMMU hardware instance
* @pclk: The clock for the IOMMU bus interconnect
+ * @name: Human-readable name of this IOMMU device
+ * @gdsc: Regulator needed to power this HW block (v2 only)
+ * @nsmr: Size of the SMT on this HW block (v2 only)
*
* A msm_iommu_drvdata holds the global driver data about a single piece
* of an IOMMU hardware instance.
@@ -81,6 +87,7 @@
struct clk *pclk;
const char *name;
struct regulator *gdsc;
+ unsigned int nsmr;
};
/**
@@ -89,6 +96,10 @@
* @pdev: Platform device associated wit this HW instance
* @attached_elm: List element for domains to track which devices are
* attached to them
+ * @attached_domain Domain currently attached to this context (if any)
+ * @name Human-readable name of this context device
+ * @sids List of Stream IDs mapped to this context (v2 only)
+ * @nsid Number of Stream IDs mapped to this context (v2 only)
*
* A msm_iommu_ctx_drvdata holds the driver data for a single context bank
* within each IOMMU hardware instance
@@ -99,6 +110,8 @@
struct list_head attached_elm;
struct iommu_domain *attached_domain;
const char *name;
+ u32 sids[MAX_NUM_SMR];
+ unsigned int nsid;
};
/*
diff --git a/arch/arm/mach-msm/include/mach/iommu_hw-v2.h b/arch/arm/mach-msm/include/mach/iommu_hw-v2.h
index fac13b3..b01dbd8 100644
--- a/arch/arm/mach-msm/include/mach/iommu_hw-v2.h
+++ b/arch/arm/mach-msm/include/mach/iommu_hw-v2.h
@@ -16,8 +16,6 @@
#define CTX_SHIFT 12
#define CTX_OFFSET 0x8000
-#define MAX_NUM_SMR 128
-
#define GET_GLOBAL_REG(reg, base) (readl_relaxed((base) + (reg)))
#define GET_CTX_REG(reg, base, ctx) \
(readl_relaxed((base) + CTX_OFFSET + (reg) + ((ctx) << CTX_SHIFT)))
diff --git a/arch/arm/mach-msm/include/mach/kgsl.h b/arch/arm/mach-msm/include/mach/kgsl.h
new file mode 100644
index 0000000..a51cc46
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/kgsl.h
@@ -0,0 +1,82 @@
+/* Copyright (c) 2012, 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 _ARCH_ARM_MACH_KGSL_H
+#define _ARCH_ARM_MACH_KGSL_H
+
+/* Clock flags to show which clocks should be controled by a given platform */
+#define KGSL_CLK_SRC 0x00000001
+#define KGSL_CLK_CORE 0x00000002
+#define KGSL_CLK_IFACE 0x00000004
+#define KGSL_CLK_MEM 0x00000008
+#define KGSL_CLK_MEM_IFACE 0x00000010
+#define KGSL_CLK_AXI 0x00000020
+
+#define KGSL_MAX_PWRLEVELS 5
+
+#define KGSL_CONVERT_TO_MBPS(val) \
+ (val*1000*1000U)
+
+#define KGSL_3D0_REG_MEMORY "kgsl_3d0_reg_memory"
+#define KGSL_3D0_IRQ "kgsl_3d0_irq"
+#define KGSL_2D0_REG_MEMORY "kgsl_2d0_reg_memory"
+#define KGSL_2D0_IRQ "kgsl_2d0_irq"
+#define KGSL_2D1_REG_MEMORY "kgsl_2d1_reg_memory"
+#define KGSL_2D1_IRQ "kgsl_2d1_irq"
+
+#define ADRENO_CHIPID(_co, _ma, _mi, _pa) \
+ ((((_co) & 0xFF) << 24) | \
+ (((_ma) & 0xFF) << 16) | \
+ (((_mi) & 0xFF) << 8) | \
+ ((_pa) & 0xFF))
+
+enum kgsl_iommu_context_id {
+ KGSL_IOMMU_CONTEXT_USER = 0,
+ KGSL_IOMMU_CONTEXT_PRIV = 1,
+};
+
+struct kgsl_iommu_ctx {
+ const char *iommu_ctx_name;
+ enum kgsl_iommu_context_id ctx_id;
+};
+
+struct kgsl_device_iommu_data {
+ const struct kgsl_iommu_ctx *iommu_ctxs;
+ int iommu_ctx_count;
+ unsigned int physstart;
+ unsigned int physend;
+};
+
+struct kgsl_pwrlevel {
+ unsigned int gpu_freq;
+ unsigned int bus_freq;
+ unsigned int io_fraction;
+};
+
+struct kgsl_device_platform_data {
+ struct kgsl_pwrlevel pwrlevel[KGSL_MAX_PWRLEVELS];
+ int init_level;
+ int num_levels;
+ int (*set_grp_async)(void);
+ unsigned int idle_timeout;
+ bool strtstp_sleepwake;
+ unsigned int nap_allowed;
+ unsigned int clk_map;
+ unsigned int idle_needed;
+ struct msm_bus_scale_pdata *bus_scale_table;
+ struct kgsl_device_iommu_data *iommu_data;
+ int iommu_count;
+ struct msm_dcvs_core_info *core_info;
+ unsigned int chipid;
+};
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8960.h b/arch/arm/mach-msm/include/mach/msm_iomap-8960.h
index 54c901f..2cea3c3 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8960.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8960.h
@@ -106,11 +106,6 @@
#define MSM8960_QFPROM_PHYS 0x00700000
#define MSM8960_QFPROM_SIZE SZ_4K
-#ifdef CONFIG_DEBUG_MSM8960_UART
-#define MSM_DEBUG_UART_BASE 0xE1040000
-#define MSM_DEBUG_UART_PHYS 0x16440000
-#endif
-
#ifndef __ASSEMBLY__
extern void msm_map_msm8960_io(void);
#endif
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audppcmdi.h b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audppcmdi.h
index 86216d4..98f20a2 100644
--- a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audppcmdi.h
+++ b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audppcmdi.h
@@ -73,6 +73,7 @@
#define AUDPP_CMD_ENA_DEC_V 0x4000
#define AUDPP_CMD_DIS_DEC_V 0x0000
#define AUDPP_CMD_DEC_STATE_M 0x4000
+#define AUDPP_CMD_LPA_MODE 0x2000
#define AUDPP_CMD_UPDATDE_CFG_DEC 0x8000
#define AUDPP_CMD_DONT_UPDATE_CFG_DEC 0x0000
diff --git a/arch/arm/mach-msm/include/mach/rpm-regulator-smd.h b/arch/arm/mach-msm/include/mach/rpm-regulator-smd.h
index 319c2d8..12bf2b7 100644
--- a/arch/arm/mach-msm/include/mach/rpm-regulator-smd.h
+++ b/arch/arm/mach-msm/include/mach/rpm-regulator-smd.h
@@ -30,6 +30,7 @@
*/
enum rpm_regulator_voltage_corner {
RPM_REGULATOR_CORNER_RETENTION = 1,
+ RPM_REGULATOR_CORNER_NONE = RPM_REGULATOR_CORNER_RETENTION,
RPM_REGULATOR_CORNER_SVS_KRAIT,
RPM_REGULATOR_CORNER_SVS_SOC,
RPM_REGULATOR_CORNER_NORMAL,
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index 15aebcd..9110632 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -66,6 +66,7 @@
MSM_CPU_8X55,
MSM_CPU_8X60,
MSM_CPU_8960,
+ MSM_CPU_8960AB,
MSM_CPU_7X27A,
FSM_CPU_9XXX,
MSM_CPU_7X25A,
@@ -245,6 +246,15 @@
#endif
}
+static inline int cpu_is_msm8960ab(void)
+{
+#ifdef CONFIG_ARCH_MSM8960
+ return read_msm_cpu_type() == MSM_CPU_8960AB;
+#else
+ return 0;
+#endif
+}
+
static inline int cpu_is_apq8064(void)
{
#ifdef CONFIG_ARCH_APQ8064
diff --git a/arch/arm/mach-msm/include/mach/subsystem_restart.h b/arch/arm/mach-msm/include/mach/subsystem_restart.h
index 51ace96..6d15f47 100644
--- a/arch/arm/mach-msm/include/mach/subsystem_restart.h
+++ b/arch/arm/mach-msm/include/mach/subsystem_restart.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, 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
@@ -18,6 +18,8 @@
#define SUBSYS_NAME_MAX_LENGTH 40
+struct subsys_device;
+
enum {
RESET_SOC = 1,
RESET_SUBSYS_COUPLED,
@@ -25,29 +27,23 @@
RESET_LEVEL_MAX
};
-struct subsys_data {
+struct subsys_desc {
const char *name;
- int (*shutdown) (const struct subsys_data *);
- int (*powerup) (const struct subsys_data *);
- void (*crash_shutdown) (const struct subsys_data *);
- int (*ramdump) (int, const struct subsys_data *);
- /* Internal use only */
- struct list_head list;
- void *notif_handle;
-
- struct mutex shutdown_lock;
- struct mutex powerup_lock;
-
- void *restart_order;
- struct subsys_data *single_restart_list[1];
+ int (*shutdown)(const struct subsys_desc *desc);
+ int (*powerup)(const struct subsys_desc *desc);
+ void (*crash_shutdown)(const struct subsys_desc *desc);
+ int (*ramdump)(int, const struct subsys_desc *desc);
};
#if defined(CONFIG_MSM_SUBSYSTEM_RESTART)
-int get_restart_level(void);
-int subsystem_restart(const char *subsys_name);
-int ssr_register_subsystem(struct subsys_data *subsys);
+extern int get_restart_level(void);
+extern int subsystem_restart_dev(struct subsys_device *dev);
+extern int subsystem_restart(const char *name);
+
+extern struct subsys_device *subsys_register(struct subsys_desc *desc);
+extern void subsys_unregister(struct subsys_device *dev);
#else
@@ -56,16 +52,24 @@
return 0;
}
-static inline int subsystem_restart(const char *subsystem_name)
+static inline int subsystem_restart_dev(struct subsys_device *dev)
{
return 0;
}
-static inline int ssr_register_subsystem(struct subsys_data *subsys)
+static inline int subsystem_restart(const char *name)
{
return 0;
}
+static inline
+struct subsys_device *subsys_register(struct subsys_desc *desc)
+{
+ return NULL;
+}
+
+static inline void subsys_unregister(struct subsys_device *dev) { }
+
#endif /* CONFIG_MSM_SUBSYSTEM_RESTART */
#endif
diff --git a/arch/arm/mach-msm/krait-scm.c b/arch/arm/mach-msm/krait-scm.c
new file mode 100644
index 0000000..eb48d35
--- /dev/null
+++ b/arch/arm/mach-msm/krait-scm.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2012, 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.
+ */
+#include <linux/kernel.h>
+#include <linux/workqueue.h>
+#include <linux/percpu.h>
+#include <linux/cpu.h>
+#include <linux/smp.h>
+#include <linux/sysfs.h>
+#include <linux/sysdev.h>
+
+#include <mach/scm.h>
+
+#define CPU_CONFIG_CMD 5
+#define CPU_CONFIG_QUERY_CMD 6
+
+static int query_cpu_config(void)
+{
+ struct cpu_config_query_req_resp {
+ u32 id;
+ u32 arg0;
+ u32 arg1;
+ u32 arg2;
+ } request;
+ struct cpu_config_query_resp {
+ u32 ret0;
+ u32 ret1;
+ u32 ret2;
+ u32 ret3;
+ } response = {0};
+ int ret;
+
+ request.id = 1;
+ ret = scm_call(SCM_SVC_BOOT, CPU_CONFIG_QUERY_CMD, &request,
+ sizeof(request), &response, sizeof(response));
+ return ret ? : response.ret0;
+}
+
+static void set_cpu_config(int enable)
+{
+ struct cpu_config_req {
+ u32 id;
+ u32 arg0;
+ u32 arg1;
+ u32 arg2;
+ } request;
+
+ request.id = 1;
+ request.arg0 = enable;
+ scm_call(SCM_SVC_BOOT, CPU_CONFIG_CMD, &request, sizeof(request),
+ NULL, 0);
+}
+
+void enable_cpu_config(struct work_struct *work)
+{
+ set_cpu_config(1);
+}
+
+void disable_cpu_config(struct work_struct *work)
+{
+ set_cpu_config(0);
+}
+
+int cpu_config_on_each_cpu(bool enable)
+{
+ work_func_t func = enable ? enable_cpu_config : disable_cpu_config;
+ return schedule_on_each_cpu(func);
+}
+
+static ssize_t show_cpuctl(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", query_cpu_config());
+}
+
+static ssize_t store_cpuctl(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr, const char *buf,
+ size_t count)
+{
+ unsigned val;
+ int ret;
+
+ ret = kstrtouint(buf, 10, &val);
+ if (ret < 0)
+ return ret;
+ ret = cpu_config_on_each_cpu(val);
+ if (ret < 0)
+ return ret;
+
+ return count;
+}
+
+static SYSDEV_CLASS_ATTR(cpuctl, 0600, show_cpuctl, store_cpuctl);
+
+static int __init init_scm_cpu(void)
+{
+ return sysfs_create_file(&cpu_subsys.dev_root->kobj,
+ &attr_cpuctl.attr);
+}
+module_init(init_scm_cpu);
diff --git a/arch/arm/mach-msm/lpass-8660.c b/arch/arm/mach-msm/lpass-8660.c
index 1018360..be18b68 100644
--- a/arch/arm/mach-msm/lpass-8660.c
+++ b/arch/arm/mach-msm/lpass-8660.c
@@ -19,6 +19,7 @@
#include <linux/stringify.h>
#include <linux/delay.h>
#include <linux/module.h>
+#include <linux/err.h>
#include <mach/irqs.h>
#include <mach/scm.h>
@@ -35,6 +36,8 @@
#define MODULE_NAME "lpass_8x60"
#define SCM_Q6_NMI_CMD 0x1
+static struct subsys_device *subsys_8x60_q6_dev;
+
/* Subsystem restart: QDSP6 data, functions */
static void *q6_ramdump_dev;
static void q6_fatal_fn(struct work_struct *);
@@ -44,7 +47,7 @@
static void q6_fatal_fn(struct work_struct *work)
{
pr_err("%s: Watchdog bite received from Q6!\n", MODULE_NAME);
- subsystem_restart("lpass");
+ subsystem_restart_dev(subsys_8x60_q6_dev);
enable_irq(LPASS_Q6SS_WDOG_EXPIRED);
}
@@ -65,7 +68,7 @@
pr_info("subsystem-fatal-8x60: Q6 NMI was sent.\n");
}
-int subsys_q6_shutdown(const struct subsys_data *crashed_subsys)
+int subsys_q6_shutdown(const struct subsys_desc *crashed_subsys)
{
void __iomem *q6_wdog_addr =
ioremap_nocache(Q6SS_WDOG_ENABLE, 8);
@@ -82,7 +85,7 @@
return 0;
}
-int subsys_q6_powerup(const struct subsys_data *crashed_subsys)
+int subsys_q6_powerup(const struct subsys_desc *crashed_subsys)
{
int ret = pil_force_boot("q6");
enable_irq(LPASS_Q6SS_WDOG_EXPIRED);
@@ -93,7 +96,7 @@
static struct ramdump_segment q6_segments[] = { {0x46700000, 0x47F00000 -
0x46700000}, {0x28400000, 0x12800} };
static int subsys_q6_ramdump(int enable,
- const struct subsys_data *crashed_subsys)
+ const struct subsys_desc *crashed_subsys)
{
if (enable)
return do_ramdump(q6_ramdump_dev, q6_segments,
@@ -102,7 +105,7 @@
return 0;
}
-void subsys_q6_crash_shutdown(const struct subsys_data *crashed_subsys)
+void subsys_q6_crash_shutdown(const struct subsys_desc *crashed_subsys)
{
send_q6_nmi();
}
@@ -117,7 +120,7 @@
return IRQ_HANDLED;
}
-static struct subsys_data subsys_8x60_q6 = {
+static struct subsys_desc subsys_8x60_q6 = {
.name = "lpass",
.shutdown = subsys_q6_shutdown,
.powerup = subsys_q6_powerup,
@@ -127,6 +130,7 @@
static void __exit lpass_fatal_exit(void)
{
+ subsys_unregister(subsys_8x60_q6_dev);
iounmap(q6_wakeup_intr);
free_irq(LPASS_Q6SS_WDOG_EXPIRED, NULL);
}
@@ -156,7 +160,9 @@
if (!q6_wakeup_intr)
pr_warn("lpass-8660: Unable to ioremap q6 wakeup address.");
- ret = ssr_register_subsystem(&subsys_8x60_q6);
+ subsys_8x60_q6_dev = subsys_register(&subsys_8x60_q6);
+ if (IS_ERR(subsys_8x60_q6_dev))
+ ret = PTR_ERR(subsys_8x60_q6_dev);
out:
return ret;
}
diff --git a/arch/arm/mach-msm/lpass-8960.c b/arch/arm/mach-msm/lpass-8960.c
index c58b0e1..b714a7f 100644
--- a/arch/arm/mach-msm/lpass-8960.c
+++ b/arch/arm/mach-msm/lpass-8960.c
@@ -152,7 +152,7 @@
pr_debug("%s: Q6 NMI was sent.\n", __func__);
}
-static int lpass_shutdown(const struct subsys_data *subsys)
+static int lpass_shutdown(const struct subsys_desc *subsys)
{
send_q6_nmi();
pil_force_shutdown("q6");
@@ -161,7 +161,7 @@
return 0;
}
-static int lpass_powerup(const struct subsys_data *subsys)
+static int lpass_powerup(const struct subsys_desc *subsys)
{
int ret = pil_force_boot("q6");
enable_irq(LPASS_Q6SS_WDOG_EXPIRED);
@@ -170,7 +170,7 @@
/* RAM segments - address and size for 8960 */
static struct ramdump_segment q6_segments[] = { {0x8da00000, 0x8f200000 -
0x8da00000}, {0x28400000, 0x20000} };
-static int lpass_ramdump(int enable, const struct subsys_data *subsys)
+static int lpass_ramdump(int enable, const struct subsys_desc *subsys)
{
pr_debug("%s: enable[%d]\n", __func__, enable);
if (enable)
@@ -181,7 +181,7 @@
return 0;
}
-static void lpass_crash_shutdown(const struct subsys_data *subsys)
+static void lpass_crash_shutdown(const struct subsys_desc *subsys)
{
q6_crash_shutdown = 1;
send_q6_nmi();
@@ -198,7 +198,9 @@
return IRQ_HANDLED;
}
-static struct subsys_data lpass_8960 = {
+static struct subsys_device *lpass_8960_dev;
+
+static struct subsys_desc lpass_8960 = {
.name = "lpass",
.shutdown = lpass_shutdown,
.powerup = lpass_powerup,
@@ -208,7 +210,10 @@
static int __init lpass_restart_init(void)
{
- return ssr_register_subsystem(&lpass_8960);
+ lpass_8960_dev = subsys_register(&lpass_8960);
+ if (IS_ERR(lpass_8960_dev))
+ return PTR_ERR(lpass_8960_dev);
+ return 0;
}
static int __init lpass_fatal_init(void)
@@ -275,6 +280,7 @@
{
subsys_notif_unregister_notifier(ssr_notif_hdle, &rnb);
subsys_notif_unregister_notifier(ssr_modem_notif_hdle, &mnb);
+ subsys_unregister(lpass_8960_dev);
free_irq(LPASS_Q6SS_WDOG_EXPIRED, NULL);
}
diff --git a/arch/arm/mach-msm/mdm.c b/arch/arm/mach-msm/mdm.c
index cbdc92a..4280fb4 100644
--- a/arch/arm/mach-msm/mdm.c
+++ b/arch/arm/mach-msm/mdm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, 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
@@ -73,14 +73,14 @@
}
-static int charm_subsys_shutdown(const struct subsys_data *crashed_subsys)
+static int charm_subsys_shutdown(const struct subsys_desc *crashed_subsys)
{
charm_ready = 0;
power_down_charm();
return 0;
}
-static int charm_subsys_powerup(const struct subsys_data *crashed_subsys)
+static int charm_subsys_powerup(const struct subsys_desc *crashed_subsys)
{
power_on_charm();
boot_type = CHARM_NORMAL_BOOT;
@@ -92,7 +92,7 @@
}
static int charm_subsys_ramdumps(int want_dumps,
- const struct subsys_data *crashed_subsys)
+ const struct subsys_desc *crashed_subsys)
{
charm_ram_dump_status = 0;
if (want_dumps) {
@@ -105,7 +105,9 @@
return charm_ram_dump_status;
}
-static struct subsys_data charm_subsystem = {
+static struct subsys_device *charm_subsys;
+
+static struct subsys_desc charm_subsystem = {
.shutdown = charm_subsys_shutdown,
.ramdump = charm_subsys_ramdumps,
.powerup = charm_subsys_powerup,
@@ -229,7 +231,7 @@
static void charm_status_fn(struct work_struct *work)
{
pr_info("Reseting the charm because status changed\n");
- subsystem_restart("external_modem");
+ subsystem_restart_dev(charm_subsys);
}
static DECLARE_WORK(charm_status_work, charm_status_fn);
@@ -239,7 +241,7 @@
pr_info("Reseting the charm due to an errfatal\n");
if (get_restart_level() == RESET_SOC)
pm8xxx_stay_on();
- subsystem_restart("external_modem");
+ subsystem_restart_dev(charm_subsys);
}
static DECLARE_WORK(charm_fatal_work, charm_fatal_fn);
@@ -349,7 +351,11 @@
atomic_notifier_chain_register(&panic_notifier_list, &charm_panic_blk);
charm_debugfs_init();
- ssr_register_subsystem(&charm_subsystem);
+ charm_subsys = subsys_register(&charm_subsystem);
+ if (IS_ERR(charm_subsys)) {
+ ret = PTR_ERR(charm_subsys);
+ goto fatal_err;
+ }
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
diff --git a/arch/arm/mach-msm/mdm_common.c b/arch/arm/mach-msm/mdm_common.c
index 5b181e1..ac9da2e 100644
--- a/arch/arm/mach-msm/mdm_common.c
+++ b/arch/arm/mach-msm/mdm_common.c
@@ -56,6 +56,7 @@
#define EXTERNAL_MODEM "external_modem"
static struct mdm_modem_drv *mdm_drv;
+static struct subsys_device *mdm_subsys_dev;
DECLARE_COMPLETION(mdm_needs_reload);
DECLARE_COMPLETION(mdm_boot);
@@ -154,7 +155,7 @@
pr_err("%s: MDM2AP_STATUS gpio did not go high\n",
__func__);
mdm_drv->mdm_ready = 0;
- subsystem_restart(EXTERNAL_MODEM);
+ subsystem_restart_dev(mdm_subsys_dev);
}
}
@@ -271,7 +272,7 @@
(gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 1)) {
pr_info("%s: Reseting the mdm due to an errfatal\n", __func__);
mdm_drv->mdm_ready = 0;
- subsystem_restart(EXTERNAL_MODEM);
+ subsystem_restart_dev(mdm_subsys_dev);
}
return IRQ_HANDLED;
}
@@ -332,7 +333,7 @@
pr_info("%s: unexpected reset external modem\n", __func__);
mdm_drv->mdm_unexpected_reset_occurred = 1;
mdm_drv->mdm_ready = 0;
- subsystem_restart(EXTERNAL_MODEM);
+ subsystem_restart_dev(mdm_subsys_dev);
} else if (value == 1) {
cancel_delayed_work(&mdm2ap_status_check_work);
pr_info("%s: status = 1: mdm is now ready\n", __func__);
@@ -349,7 +350,7 @@
return IRQ_HANDLED;
}
-static int mdm_subsys_shutdown(const struct subsys_data *crashed_subsys)
+static int mdm_subsys_shutdown(const struct subsys_desc *crashed_subsys)
{
mdm_drv->mdm_ready = 0;
gpio_direction_output(mdm_drv->ap2mdm_errfatal_gpio, 1);
@@ -367,7 +368,7 @@
return 0;
}
-static int mdm_subsys_powerup(const struct subsys_data *crashed_subsys)
+static int mdm_subsys_powerup(const struct subsys_desc *crashed_subsys)
{
gpio_direction_output(mdm_drv->ap2mdm_errfatal_gpio, 0);
gpio_direction_output(mdm_drv->ap2mdm_status_gpio, 1);
@@ -390,7 +391,7 @@
}
static int mdm_subsys_ramdumps(int want_dumps,
- const struct subsys_data *crashed_subsys)
+ const struct subsys_desc *crashed_subsys)
{
mdm_drv->mdm_ram_dump_status = 0;
if (want_dumps) {
@@ -411,7 +412,7 @@
return mdm_drv->mdm_ram_dump_status;
}
-static struct subsys_data mdm_subsystem = {
+static struct subsys_desc mdm_subsystem = {
.shutdown = mdm_subsys_shutdown,
.ramdump = mdm_subsys_ramdumps,
.powerup = mdm_subsys_powerup,
@@ -588,7 +589,11 @@
mdm_debugfs_init();
/* Register subsystem handlers */
- ssr_register_subsystem(&mdm_subsystem);
+ mdm_subsys_dev = subsys_register(&mdm_subsystem);
+ if (IS_ERR(mdm_subsys_dev)) {
+ ret = PTR_ERR(mdm_subsys_dev);
+ goto fatal_err;
+ }
/* ERR_FATAL irq. */
irq = MSM_GPIO_TO_INT(mdm_drv->mdm2ap_errfatal_gpio);
diff --git a/arch/arm/mach-msm/modem-8660.c b/arch/arm/mach-msm/modem-8660.c
index 9c558e4..096ed9c 100644
--- a/arch/arm/mach-msm/modem-8660.c
+++ b/arch/arm/mach-msm/modem-8660.c
@@ -19,6 +19,7 @@
#include <linux/stringify.h>
#include <linux/delay.h>
#include <linux/module.h>
+#include <linux/err.h>
#include <mach/irqs.h>
#include <mach/scm.h>
@@ -48,6 +49,8 @@
module_param(reset_modem, int, 0644);
#endif
+static struct subsys_device *modem_8660_dev;
+
/* Subsystem restart: Modem data, functions */
static void *modem_ramdump_dev;
static void modem_fatal_fn(struct work_struct *);
@@ -75,7 +78,7 @@
mb();
iounmap(hwio_modem_reset_addr);
- subsystem_restart("modem");
+ subsystem_restart_dev(modem_8660_dev);
enable_irq(MARM_WDOG_EXPIRED);
}
@@ -93,7 +96,7 @@
if (modem_state == 0 || modem_state & panic_smsm_states) {
- subsystem_restart("modem");
+ subsystem_restart_dev(modem_8660_dev);
enable_irq(MARM_WDOG_EXPIRED);
} else if (modem_state & reset_smsm_states) {
@@ -135,13 +138,13 @@
goto out;
}
pr_err("%s: Modem error fatal'ed.", MODULE_NAME);
- subsystem_restart("modem");
+ subsystem_restart_dev(modem_8660_dev);
}
out:
return NOTIFY_DONE;
}
-static int modem_shutdown(const struct subsys_data *crashed_subsys)
+static int modem_shutdown(const struct subsys_desc *crashed_subsys)
{
void __iomem *modem_wdog_addr;
@@ -178,7 +181,7 @@
return 0;
}
-static int modem_powerup(const struct subsys_data *crashed_subsys)
+static int modem_powerup(const struct subsys_desc *crashed_subsys)
{
int ret;
@@ -192,8 +195,7 @@
static struct ramdump_segment modem_segments[] = {
{0x42F00000, 0x46000000 - 0x42F00000} };
-static int modem_ramdump(int enable,
- const struct subsys_data *crashed_subsys)
+static int modem_ramdump(int enable, const struct subsys_desc *crashed_subsys)
{
if (enable)
return do_ramdump(modem_ramdump_dev, modem_segments,
@@ -202,8 +204,7 @@
return 0;
}
-static void modem_crash_shutdown(
- const struct subsys_data *crashed_subsys)
+static void modem_crash_shutdown(const struct subsys_desc *crashed_subsys)
{
/* If modem hasn't already crashed, send SMSM_RESET. */
if (!(smsm_get_state(SMSM_MODEM_STATE) & SMSM_RESET)) {
@@ -225,7 +226,7 @@
return IRQ_HANDLED;
}
-static struct subsys_data subsys_8660_modem = {
+static struct subsys_desc subsys_8660_modem = {
.name = "modem",
.shutdown = modem_shutdown,
.powerup = modem_powerup,
@@ -260,13 +261,16 @@
goto out;
}
- ret = ssr_register_subsystem(&subsys_8660_modem);
+ modem_8660_dev = subsys_register(&subsys_8660_modem);
+ if (IS_ERR(modem_8660_dev))
+ ret = PTR_ERR(modem_8660_dev);
out:
return ret;
}
static void __exit modem_8660_exit(void)
{
+ subsys_unregister(modem_8660_dev);
free_irq(MARM_WDOG_EXPIRED, NULL);
}
diff --git a/arch/arm/mach-msm/modem-8960.c b/arch/arm/mach-msm/modem-8960.c
index fd7b7b5..73b9b1f 100644
--- a/arch/arm/mach-msm/modem-8960.c
+++ b/arch/arm/mach-msm/modem-8960.c
@@ -35,6 +35,8 @@
static int crash_shutdown;
+static struct subsys_device *modem_8960_dev;
+
#define MAX_SSR_REASON_LEN 81U
#define Q6_FW_WDOG_ENABLE 0x08882024
#define Q6_SW_WDOG_ENABLE 0x08982024
@@ -66,7 +68,7 @@
static void restart_modem(void)
{
log_modem_sfr();
- subsystem_restart("modem");
+ subsystem_restart_dev(modem_8960_dev);
}
static void modem_wdog_check(struct work_struct *work)
@@ -101,7 +103,7 @@
}
}
-static int modem_shutdown(const struct subsys_data *subsys)
+static int modem_shutdown(const struct subsys_desc *subsys)
{
void __iomem *q6_fw_wdog_addr;
void __iomem *q6_sw_wdog_addr;
@@ -142,7 +144,7 @@
#define MODEM_WDOG_CHECK_TIMEOUT_MS 10000
-static int modem_powerup(const struct subsys_data *subsys)
+static int modem_powerup(const struct subsys_desc *subsys)
{
pil_force_boot("modem_fw");
pil_force_boot("modem");
@@ -153,7 +155,7 @@
return 0;
}
-void modem_crash_shutdown(const struct subsys_data *subsys)
+void modem_crash_shutdown(const struct subsys_desc *subsys)
{
crash_shutdown = 1;
smsm_reset_modem(SMSM_RESET);
@@ -176,8 +178,7 @@
static void *modemsw_ramdump_dev;
static void *smem_ramdump_dev;
-static int modem_ramdump(int enable,
- const struct subsys_data *crashed_subsys)
+static int modem_ramdump(int enable, const struct subsys_desc *crashed_subsys)
{
int ret = 0;
@@ -234,7 +235,7 @@
return IRQ_HANDLED;
}
-static struct subsys_data modem_8960 = {
+static struct subsys_desc modem_8960 = {
.name = "modem",
.shutdown = modem_shutdown,
.powerup = modem_powerup,
@@ -244,13 +245,16 @@
static int modem_subsystem_restart_init(void)
{
- return ssr_register_subsystem(&modem_8960);
+ modem_8960_dev = subsys_register(&modem_8960);
+ if (IS_ERR(modem_8960_dev))
+ return PTR_ERR(modem_8960_dev);
+ return 0;
}
static int modem_debug_set(void *data, u64 val)
{
if (val == 1)
- subsystem_restart("modem");
+ subsystem_restart_dev(modem_8960_dev);
return 0;
}
diff --git a/arch/arm/mach-msm/msm_dsps.c b/arch/arm/mach-msm/msm_dsps.c
index 200d717..6dde576 100644
--- a/arch/arm/mach-msm/msm_dsps.c
+++ b/arch/arm/mach-msm/msm_dsps.c
@@ -722,6 +722,8 @@
.unlocked_ioctl = dsps_ioctl,
};
+static struct subsys_device *dsps_dev;
+
/**
* Fatal error handler
* Resets DSPS.
@@ -735,7 +737,7 @@
pr_err("%s: DSPS already resetting. Count %d\n", __func__,
atomic_read(&drv->crash_in_progress));
} else {
- subsystem_restart("dsps");
+ subsystem_restart_dev(dsps_dev);
}
}
@@ -765,7 +767,7 @@
* called by the restart notifier
*
*/
-static int dsps_shutdown(const struct subsys_data *subsys)
+static int dsps_shutdown(const struct subsys_desc *subsys)
{
pr_debug("%s\n", __func__);
disable_irq_nosync(drv->wdog_irq);
@@ -779,7 +781,7 @@
* called by the restart notifier
*
*/
-static int dsps_powerup(const struct subsys_data *subsys)
+static int dsps_powerup(const struct subsys_desc *subsys)
{
pr_debug("%s\n", __func__);
dsps_power_on_handler();
@@ -794,7 +796,7 @@
* called by the restart notifier
*
*/
-static void dsps_crash_shutdown(const struct subsys_data *subsys)
+static void dsps_crash_shutdown(const struct subsys_desc *subsys)
{
pr_debug("%s\n", __func__);
dsps_crash_shutdown_g = 1;
@@ -806,7 +808,7 @@
* called by the restart notifier
*
*/
-static int dsps_ramdump(int enable, const struct subsys_data *subsys)
+static int dsps_ramdump(int enable, const struct subsys_desc *subsys)
{
int ret = 0;
pr_debug("%s\n", __func__);
@@ -838,7 +840,7 @@
return ret;
}
-static struct subsys_data dsps_ssrops = {
+static struct subsys_desc dsps_ssrops = {
.name = "dsps",
.shutdown = dsps_shutdown,
.powerup = dsps_powerup,
@@ -919,9 +921,10 @@
goto smsm_register_err;
}
- ret = ssr_register_subsystem(&dsps_ssrops);
- if (ret) {
- pr_err("%s: ssr_register_subsystem fail %d\n", __func__,
+ dsps_dev = subsys_register(&dsps_ssrops);
+ if (IS_ERR(dsps_dev)) {
+ ret = PTR_ERR(dsps_dev);
+ pr_err("%s: subsys_register fail %d\n", __func__,
ret);
goto ssr_register_err;
}
@@ -953,6 +956,7 @@
{
pr_debug("%s.\n", __func__);
+ subsys_unregister(dsps_dev);
dsps_power_off_handler();
dsps_free_resources();
diff --git a/arch/arm/mach-msm/msm_xo.c b/arch/arm/mach-msm/msm_xo.c
index 9825ce5..8254502 100644
--- a/arch/arm/mach-msm/msm_xo.c
+++ b/arch/arm/mach-msm/msm_xo.c
@@ -235,7 +235,8 @@
int is_d0 = xo == &msm_xo_sources[MSM_XO_TCXO_D0];
int needs_workaround = cpu_is_msm8960() || cpu_is_apq8064() ||
cpu_is_msm8930() || cpu_is_msm8930aa() ||
- cpu_is_msm9615() || cpu_is_msm8627();
+ cpu_is_msm9615() || cpu_is_msm8627() ||
+ cpu_is_msm8960ab();
if (xo_voter->mode == mode)
return 0;
diff --git a/arch/arm/mach-msm/peripheral-loader.c b/arch/arm/mach-msm/peripheral-loader.c
index 3f6eb95..540ffbb 100644
--- a/arch/arm/mach-msm/peripheral-loader.c
+++ b/arch/arm/mach-msm/peripheral-loader.c
@@ -565,18 +565,6 @@
static void msm_pil_debugfs_remove(struct pil_device *pil) { }
#endif
-static int __msm_pil_shutdown(struct device *dev, void *data)
-{
- pil_shutdown(to_pil_device(dev));
- return 0;
-}
-
-static int msm_pil_shutdown_at_boot(void)
-{
- return bus_for_each_dev(&pil_bus_type, NULL, NULL, __msm_pil_shutdown);
-}
-late_initcall(msm_pil_shutdown_at_boot);
-
static void pil_device_release(struct device *dev)
{
struct pil_device *pil = to_pil_device(dev);
diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c
index 48a236f..5e063a1 100644
--- a/arch/arm/mach-msm/platsmp.c
+++ b/arch/arm/mach-msm/platsmp.c
@@ -143,7 +143,7 @@
return krait_release_secondary_sim(0xf9088000, cpu);
if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm8930aa() ||
- cpu_is_apq8064() || cpu_is_msm8627())
+ cpu_is_apq8064() || cpu_is_msm8627() || cpu_is_msm8960ab())
return krait_release_secondary(0x02088000, cpu);
WARN(1, "unknown CPU case in release_secondary\n");
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index 15a0b6a..42616c6 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -591,7 +591,7 @@
static int64_t msm_pm_timer_enter_suspend(int64_t *period)
{
- int time = 0;
+ int64_t time = 0;
if (msm_pm_use_qtimer)
return sched_clock();
@@ -808,10 +808,15 @@
{
enum msm_pm_sleep_mode mode = per_cpu(msm_pm_last_slp_mode, cpu);
- if (msm_pm_slp_sts)
- if ((mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE) ||
- (mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE))
+ if (msm_pm_slp_sts) {
+ int acc_sts = __raw_readl(msm_pm_slp_sts->base_addr
+ + cpu * msm_pm_slp_sts->cpu_offset);
+
+ if ((acc_sts & msm_pm_slp_sts->mask) &&
+ ((mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE) ||
+ (mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)))
return true;
+ }
return false;
}
diff --git a/arch/arm/mach-msm/pm2.c b/arch/arm/mach-msm/pm2.c
index ae7a3cd..7a8e4c3 100644
--- a/arch/arm/mach-msm/pm2.c
+++ b/arch/arm/mach-msm/pm2.c
@@ -1280,7 +1280,7 @@
static int64_t msm_pm_timer_enter_suspend(int64_t *period)
{
- int time = 0;
+ int64_t time = 0;
time = msm_timer_get_sclk_time(period);
if (!time)
diff --git a/arch/arm/mach-msm/qdsp5/audio_lpa.c b/arch/arm/mach-msm/qdsp5/audio_lpa.c
index 14a9e57..fe7b270 100644
--- a/arch/arm/mach-msm/qdsp5/audio_lpa.c
+++ b/arch/arm/mach-msm/qdsp5/audio_lpa.c
@@ -464,7 +464,8 @@
cfg_dec_cmd[0] = AUDPP_CMD_CFG_DEC_TYPE;
if (enable)
cfg_dec_cmd[1 + audio->dec_id] = AUDPP_CMD_UPDATDE_CFG_DEC |
- AUDPP_CMD_ENA_DEC_V | AUDDEC_DEC_PCM;
+ AUDPP_CMD_ENA_DEC_V | AUDDEC_DEC_PCM |
+ AUDPP_CMD_LPA_MODE;
else
cfg_dec_cmd[1 + audio->dec_id] = AUDPP_CMD_UPDATDE_CFG_DEC |
AUDPP_CMD_DIS_DEC_V;
diff --git a/arch/arm/mach-msm/qdsp5v2/adsp.c b/arch/arm/mach-msm/qdsp5v2/adsp.c
index acd9c4c..8c1413c 100644
--- a/arch/arm/mach-msm/qdsp5v2/adsp.c
+++ b/arch/arm/mach-msm/qdsp5v2/adsp.c
@@ -883,7 +883,7 @@
rc = -ETIMEDOUT;
}
if (module->open_count++ == 0 && module->clk)
- clk_enable(module->clk);
+ clk_prepare_enable(module->clk);
mutex_lock(&adsp_open_lock);
if (adsp_open_count++ == 0)
@@ -938,7 +938,7 @@
mutex_lock(&module->lock);
module->state = ADSP_STATE_DISABLED;
if (--module->open_count == 0 && module->clk)
- clk_disable(module->clk);
+ clk_disable_unprepare(module->clk);
mutex_unlock(&module->lock);
mutex_lock(&adsp_open_lock);
if (--adsp_open_count == 0) {
diff --git a/arch/arm/mach-msm/qdsp5v2/lpa.c b/arch/arm/mach-msm/qdsp5v2/lpa.c
index c4e0fee..98297e3 100644
--- a/arch/arm/mach-msm/qdsp5v2/lpa.c
+++ b/arch/arm/mach-msm/qdsp5v2/lpa.c
@@ -73,7 +73,7 @@
MM_ERR("failed to get adsp clk\n");
goto error;
}
- clk_enable(adsp_clk);
+ clk_prepare_enable(adsp_clk);
lpa_enable_codec(lpa, 0);
LPA_REG_WRITEL(lpa, (LPA_OBUF_RESETS_MISR_RESET |
LPA_OBUF_RESETS_OVERALL_RESET), LPA_OBUF_RESETS);
@@ -83,7 +83,7 @@
LPA_REG_WRITEL(lpa, LPA_OBUF_ACK_RESET_DONE_BMSK, LPA_OBUF_ACK);
mb();
- clk_disable(adsp_clk);
+ clk_disable_unprepare(adsp_clk);
clk_put(adsp_clk);
error:
return;
diff --git a/arch/arm/mach-msm/qdsp5v2/snddev_ecodec.c b/arch/arm/mach-msm/qdsp5v2/snddev_ecodec.c
index a5da912..943489a 100644
--- a/arch/arm/mach-msm/qdsp5v2/snddev_ecodec.c
+++ b/arch/arm/mach-msm/qdsp5v2/snddev_ecodec.c
@@ -60,7 +60,7 @@
goto done;
}
/* config clocks */
- clk_enable(drv->lpa_core_clk);
+ clk_prepare_enable(drv->lpa_core_clk);
/*if long sync is selected in aux PCM interface
ecodec clock is updated to work with 128KHz,
@@ -96,7 +96,7 @@
}
/* enable ecodec clk */
- clk_enable(drv->ecodec_clk);
+ clk_prepare_enable(drv->ecodec_clk);
/* let ADSP confiure AUX PCM regs */
aux_codec_adsp_codec_ctl_en(ADSP_CTL);
@@ -109,7 +109,7 @@
audio_interct_tpcm_source(AUDIO_ADSP_A);
audio_interct_rpcm_source(AUDIO_ADSP_A);
- clk_disable(drv->lpa_core_clk);
+ clk_disable_unprepare(drv->lpa_core_clk);
/* send AUX_CODEC_CONFIG to AFE */
rc = afe_config_aux_codec(ecodec->data->conf_pcm_ctl_val,
@@ -126,7 +126,7 @@
if (IS_ERR_VALUE(rc)) {
if (!drv->tx_active) {
aux_pcm_gpios_free();
- clk_disable(drv->ecodec_clk);
+ clk_disable_unprepare(drv->ecodec_clk);
}
goto done;
}
@@ -136,7 +136,7 @@
error:
aux_pcm_gpios_free();
- clk_disable(drv->ecodec_clk);
+ clk_disable_unprepare(drv->ecodec_clk);
done:
return rc;
}
@@ -148,7 +148,7 @@
/* free GPIO */
if (!drv->tx_active) {
aux_pcm_gpios_free();
- clk_disable(drv->ecodec_clk);
+ clk_disable_unprepare(drv->ecodec_clk);
}
/* disable AFE */
@@ -176,7 +176,7 @@
goto done;
}
/* config clocks */
- clk_enable(drv->lpa_core_clk);
+ clk_prepare_enable(drv->lpa_core_clk);
/*if long sync is selected in aux PCM interface
ecodec clock is updated to work with 128KHz,
@@ -212,7 +212,7 @@
}
/* enable ecodec clk */
- clk_enable(drv->ecodec_clk);
+ clk_prepare_enable(drv->ecodec_clk);
/* let ADSP confiure AUX PCM regs */
aux_codec_adsp_codec_ctl_en(ADSP_CTL);
@@ -225,7 +225,7 @@
audio_interct_tpcm_source(AUDIO_ADSP_A);
audio_interct_rpcm_source(AUDIO_ADSP_A);
- clk_disable(drv->lpa_core_clk);
+ clk_disable_unprepare(drv->lpa_core_clk);
/* send AUX_CODEC_CONFIG to AFE */
rc = afe_config_aux_codec(ecodec->data->conf_pcm_ctl_val,
@@ -242,7 +242,7 @@
if (IS_ERR_VALUE(rc)) {
if (!drv->rx_active) {
aux_pcm_gpios_free();
- clk_disable(drv->ecodec_clk);
+ clk_disable_unprepare(drv->ecodec_clk);
}
goto done;
}
@@ -251,7 +251,7 @@
return 0;
error:
- clk_disable(drv->ecodec_clk);
+ clk_disable_unprepare(drv->ecodec_clk);
aux_pcm_gpios_free();
done:
return rc;
@@ -264,7 +264,7 @@
/* free GPIO */
if (!drv->rx_active) {
aux_pcm_gpios_free();
- clk_disable(drv->ecodec_clk);
+ clk_disable_unprepare(drv->ecodec_clk);
}
/* disable AFE */
diff --git a/arch/arm/mach-msm/qdsp5v2/snddev_icodec.c b/arch/arm/mach-msm/qdsp5v2/snddev_icodec.c
index 80c9a01..c416c07 100644
--- a/arch/arm/mach-msm/qdsp5v2/snddev_icodec.c
+++ b/arch/arm/mach-msm/qdsp5v2/snddev_icodec.c
@@ -199,12 +199,12 @@
SNDDEV_ICODEC_CLK_RATE(icodec->sample_rate));
if (IS_ERR_VALUE(trc))
goto error_invalid_freq;
- clk_enable(drv->rx_mclk);
- clk_enable(drv->rx_sclk);
+ clk_prepare_enable(drv->rx_mclk);
+ clk_prepare_enable(drv->rx_sclk);
/* clk_set_rate(drv->lpa_codec_clk, 1); */ /* Remove if use pcom */
- clk_enable(drv->lpa_p_clk);
- clk_enable(drv->lpa_codec_clk);
- clk_enable(drv->lpa_core_clk);
+ clk_prepare_enable(drv->lpa_p_clk);
+ clk_prepare_enable(drv->lpa_codec_clk);
+ clk_prepare_enable(drv->lpa_core_clk);
/* Enable LPA sub system
*/
@@ -263,11 +263,11 @@
error_adie:
lpa_put(drv->lpa);
error_lpa:
- clk_disable(drv->lpa_p_clk);
- clk_disable(drv->lpa_codec_clk);
- clk_disable(drv->lpa_core_clk);
- clk_disable(drv->rx_sclk);
- clk_disable(drv->rx_mclk);
+ clk_disable_unprepare(drv->lpa_p_clk);
+ clk_disable_unprepare(drv->lpa_codec_clk);
+ clk_disable_unprepare(drv->lpa_core_clk);
+ clk_disable_unprepare(drv->rx_sclk);
+ clk_disable_unprepare(drv->rx_mclk);
error_invalid_freq:
MM_ERR("encounter error\n");
@@ -307,8 +307,8 @@
SNDDEV_ICODEC_CLK_RATE(icodec->sample_rate));
if (IS_ERR_VALUE(trc))
goto error_invalid_freq;
- clk_enable(drv->tx_mclk);
- clk_enable(drv->tx_sclk);
+ clk_prepare_enable(drv->tx_mclk);
+ clk_prepare_enable(drv->tx_sclk);
/* Set MI2S */
mi2s_set_codec_input_path((icodec->data->channel_mode ==
@@ -344,8 +344,8 @@
adie_codec_close(icodec->adie_path);
icodec->adie_path = NULL;
error_adie:
- clk_disable(drv->tx_sclk);
- clk_disable(drv->tx_mclk);
+ clk_disable_unprepare(drv->tx_sclk);
+ clk_disable_unprepare(drv->tx_mclk);
error_invalid_freq:
/* Disable mic bias */
@@ -414,14 +414,14 @@
lpa_put(drv->lpa);
/* Disable LPA clocks */
- clk_disable(drv->lpa_p_clk);
- clk_disable(drv->lpa_codec_clk);
- clk_disable(drv->lpa_core_clk);
+ clk_disable_unprepare(drv->lpa_p_clk);
+ clk_disable_unprepare(drv->lpa_codec_clk);
+ clk_disable_unprepare(drv->lpa_core_clk);
/* Disable MI2S RX master block */
/* Disable MI2S RX bit clock */
- clk_disable(drv->rx_sclk);
- clk_disable(drv->rx_mclk);
+ clk_disable_unprepare(drv->rx_sclk);
+ clk_disable_unprepare(drv->rx_mclk);
icodec->enabled = 0;
@@ -452,8 +452,8 @@
/* Disable MI2S TX master block */
/* Disable MI2S TX bit clock */
- clk_disable(drv->tx_sclk);
- clk_disable(drv->tx_mclk);
+ clk_disable_unprepare(drv->tx_sclk);
+ clk_disable_unprepare(drv->tx_mclk);
/* Disable mic bias */
for (i = 0; i < icodec->data->pmctl_id_sz; i++) {
@@ -889,8 +889,8 @@
/* enable MI2S RX bit clock */
clk_set_rate(drv->rx_mclk,
SNDDEV_ICODEC_CLK_RATE(8000));
- clk_enable(drv->rx_mclk);
- clk_enable(drv->rx_sclk);
+ clk_prepare_enable(drv->rx_mclk);
+ clk_prepare_enable(drv->rx_sclk);
MM_INFO("configure ADIE RX path\n");
/* Configure ADIE */
@@ -905,8 +905,8 @@
/* enable MI2S TX bit clock */
clk_set_rate(drv->tx_mclk,
SNDDEV_ICODEC_CLK_RATE(8000));
- clk_enable(drv->tx_mclk);
- clk_enable(drv->tx_sclk);
+ clk_prepare_enable(drv->tx_mclk);
+ clk_prepare_enable(drv->tx_sclk);
MM_INFO("configure ADIE TX path\n");
/* Configure ADIE */
@@ -927,13 +927,13 @@
/* Disable MI2S RX master block */
/* Disable MI2S RX bit clock */
- clk_disable(drv->rx_sclk);
- clk_disable(drv->rx_mclk);
+ clk_disable_unprepare(drv->rx_sclk);
+ clk_disable_unprepare(drv->rx_mclk);
/* Disable MI2S TX master block */
/* Disable MI2S TX bit clock */
- clk_disable(drv->tx_sclk);
- clk_disable(drv->tx_mclk);
+ clk_disable_unprepare(drv->tx_sclk);
+ clk_disable_unprepare(drv->tx_mclk);
}
}
@@ -955,11 +955,11 @@
SNDDEV_ICODEC_CLK_RATE(8000));
if (IS_ERR_VALUE(trc))
MM_ERR("failed to set clk rate\n");
- clk_enable(drv->rx_mclk);
- clk_enable(drv->rx_sclk);
- clk_enable(drv->lpa_p_clk);
- clk_enable(drv->lpa_codec_clk);
- clk_enable(drv->lpa_core_clk);
+ clk_prepare_enable(drv->rx_mclk);
+ clk_prepare_enable(drv->rx_sclk);
+ clk_prepare_enable(drv->lpa_p_clk);
+ clk_prepare_enable(drv->lpa_codec_clk);
+ clk_prepare_enable(drv->lpa_core_clk);
/* Enable LPA sub system
*/
drv->lpa = lpa_get();
@@ -1003,8 +1003,8 @@
/* enable MI2S TX bit clock */
clk_set_rate(drv->tx_mclk,
SNDDEV_ICODEC_CLK_RATE(8000));
- clk_enable(drv->tx_mclk);
- clk_enable(drv->tx_sclk);
+ clk_prepare_enable(drv->tx_mclk);
+ clk_prepare_enable(drv->tx_sclk);
/* Set MI2S */
mi2s_set_codec_input_path(MI2S_CHAN_MONO_PACKED, WT_16_BIT);
MM_INFO("configure ADIE TX path\n");
@@ -1048,14 +1048,14 @@
lpa_put(drv->lpa);
/* Disable LPA clocks */
- clk_disable(drv->lpa_p_clk);
- clk_disable(drv->lpa_codec_clk);
- clk_disable(drv->lpa_core_clk);
+ clk_disable_unprepare(drv->lpa_p_clk);
+ clk_disable_unprepare(drv->lpa_codec_clk);
+ clk_disable_unprepare(drv->lpa_core_clk);
/* Disable MI2S RX master block */
/* Disable MI2S RX bit clock */
- clk_disable(drv->rx_sclk);
- clk_disable(drv->rx_mclk);
+ clk_disable_unprepare(drv->rx_sclk);
+ clk_disable_unprepare(drv->rx_mclk);
pmapp_smps_mode_vote(SMPS_AUDIO_RECORD_ID,
PMAPP_VREG_S4, PMAPP_SMPS_MODE_VOTE_DONTCARE);
@@ -1069,8 +1069,8 @@
adie_codec_close(debugfs_tx_adie);
/* Disable MI2S TX master block */
/* Disable MI2S TX bit clock */
- clk_disable(drv->tx_sclk);
- clk_disable(drv->tx_mclk);
+ clk_disable_unprepare(drv->tx_sclk);
+ clk_disable_unprepare(drv->tx_mclk);
pmic_hsed_enable(PM_HSED_CONTROLLER_0, PM_HSED_ENABLE_OFF);
MM_INFO("AFE loopback disabled\n");
}
diff --git a/arch/arm/mach-msm/qdsp5v2/snddev_mi2s.c b/arch/arm/mach-msm/qdsp5v2/snddev_mi2s.c
index 939cc8b..b5f3b66 100644
--- a/arch/arm/mach-msm/qdsp5v2/snddev_mi2s.c
+++ b/arch/arm/mach-msm/qdsp5v2/snddev_mi2s.c
@@ -154,12 +154,12 @@
mutex_unlock(&drv->lock);
return -EIO;
}
- clk_enable(drv->mclk);
- clk_enable(drv->sclk);
+ clk_prepare_enable(drv->mclk);
+ clk_prepare_enable(drv->sclk);
drv->clocks_enabled = 1;
- MM_DBG("%s: clks enabled \n", __func__);
+ MM_DBG("%s: clks enabled\n", __func__);
} else
- MM_DBG("%s: clks already enabled \n", __func__);
+ MM_DBG("%s: clks already enabled\n", __func__);
if (snddev_mi2s_data->capability & SNDDEV_CAP_RX) {
@@ -225,8 +225,8 @@
mi2s_data_gpio_failure:
if (!drv->sd_lines_used) {
- clk_disable(drv->sclk);
- clk_disable(drv->mclk);
+ clk_disable_unprepare(drv->sclk);
+ clk_disable_unprepare(drv->mclk);
drv->clocks_enabled = 0;
mi2s_unconfig_clk_gpio();
}
@@ -268,8 +268,8 @@
mi2s_unconfig_data_gpio(dir, snddev_mi2s_data->sd_lines);
if (!drv->sd_lines_used) {
- clk_disable(drv->sclk);
- clk_disable(drv->mclk);
+ clk_disable_unprepare(drv->sclk);
+ clk_disable_unprepare(drv->mclk);
drv->clocks_enabled = 0;
mi2s_unconfig_clk_gpio();
}
diff --git a/arch/arm/mach-msm/ramdump.c b/arch/arm/mach-msm/ramdump.c
index a18acd6..21e81dd 100644
--- a/arch/arm/mach-msm/ramdump.c
+++ b/arch/arm/mach-msm/ramdump.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, 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
@@ -222,6 +222,17 @@
return (void *)rd_dev;
}
+void destroy_ramdump_device(void *dev)
+{
+ struct ramdump_device *rd_dev = dev;
+
+ if (IS_ERR_OR_NULL(rd_dev))
+ return;
+
+ misc_deregister(&rd_dev->device);
+ kfree(rd_dev);
+}
+
int do_ramdump(void *handle, struct ramdump_segment *segments,
int nsegments)
{
diff --git a/arch/arm/mach-msm/ramdump.h b/arch/arm/mach-msm/ramdump.h
index 0b60a44..9006010 100644
--- a/arch/arm/mach-msm/ramdump.h
+++ b/arch/arm/mach-msm/ramdump.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, 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
@@ -19,6 +19,7 @@
};
void *create_ramdump_device(const char *dev_name);
+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-smd.c b/arch/arm/mach-msm/rpm-smd.c
index 0edea3f..697d504 100644
--- a/arch/arm/mach-msm/rpm-smd.c
+++ b/arch/arm/mach-msm/rpm-smd.c
@@ -24,6 +24,7 @@
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>
+#include <linux/string.h>
#include <linux/device.h>
#include <linux/notifier.h>
#include <linux/slab.h>
@@ -36,6 +37,19 @@
#include <mach/rpm-smd.h>
#include "rpm-notifier.h"
+/* Debug Definitions */
+
+enum {
+ MSM_RPM_LOG_REQUEST_PRETTY = BIT(0),
+ MSM_RPM_LOG_REQUEST_RAW = BIT(1),
+ MSM_RPM_LOG_REQUEST_SHOW_MSG_ID = BIT(2),
+};
+
+static int msm_rpm_debug_mask;
+module_param_named(
+ debug_mask, msm_rpm_debug_mask, int, S_IRUGO | S_IWUSR
+);
+
struct msm_rpm_driver_data {
const char *ch_name;
uint32_t ch_type;
@@ -52,7 +66,7 @@
#define ERR "err\0"
#define MAX_ERR_BUFFER_SIZE 60
-static struct atomic_notifier_head msm_rpm_sleep_notifier;
+static ATOMIC_NOTIFIER_HEAD(msm_rpm_sleep_notifier);
static bool standalone;
int msm_rpm_register_notifier(struct notifier_block *nb)
@@ -492,6 +506,140 @@
}
}
+#define DEBUG_PRINT_BUFFER_SIZE 512
+
+static void msm_rpm_log_request(struct msm_rpm_request *cdata)
+{
+ char buf[DEBUG_PRINT_BUFFER_SIZE];
+ size_t buflen = DEBUG_PRINT_BUFFER_SIZE;
+ char name[5];
+ u32 value;
+ int i, j, prev_valid;
+ int valid_count = 0;
+ int pos = 0;
+
+ name[4] = 0;
+
+ for (i = 0; i < cdata->write_idx; i++)
+ if (cdata->kvp[i].valid)
+ valid_count++;
+
+ pos += scnprintf(buf + pos, buflen - pos, "%sRPM req: ", KERN_INFO);
+ if (msm_rpm_debug_mask & MSM_RPM_LOG_REQUEST_SHOW_MSG_ID)
+ pos += scnprintf(buf + pos, buflen - pos, "msg_id=%u, ",
+ cdata->msg_hdr.msg_id);
+ pos += scnprintf(buf + pos, buflen - pos, "s=%s",
+ (cdata->msg_hdr.set == MSM_RPM_CTX_ACTIVE_SET ? "act" : "slp"));
+
+ if ((msm_rpm_debug_mask & MSM_RPM_LOG_REQUEST_PRETTY)
+ && (msm_rpm_debug_mask & MSM_RPM_LOG_REQUEST_RAW)) {
+ /* Both pretty and raw formatting */
+ memcpy(name, &cdata->msg_hdr.resource_type, sizeof(uint32_t));
+ pos += scnprintf(buf + pos, buflen - pos,
+ ", rsc_type=0x%08X (%s), rsc_id=%u; ",
+ cdata->msg_hdr.resource_type, name,
+ cdata->msg_hdr.resource_id);
+
+ for (i = 0, prev_valid = 0; i < cdata->write_idx; i++) {
+ if (!cdata->kvp[i].valid)
+ continue;
+
+ memcpy(name, &cdata->kvp[i].key, sizeof(uint32_t));
+ pos += scnprintf(buf + pos, buflen - pos,
+ "[key=0x%08X (%s), value=%s",
+ cdata->kvp[i].key, name,
+ (cdata->kvp[i].nbytes ? "0x" : "null"));
+
+ for (j = 0; j < cdata->kvp[i].nbytes; j++)
+ pos += scnprintf(buf + pos, buflen - pos,
+ "%02X ",
+ cdata->kvp[i].value[j]);
+
+ if (cdata->kvp[i].nbytes)
+ pos += scnprintf(buf + pos, buflen - pos, "(");
+
+ for (j = 0; j < cdata->kvp[i].nbytes; j += 4) {
+ value = 0;
+ memcpy(&value, &cdata->kvp[i].value[j],
+ min(sizeof(uint32_t),
+ cdata->kvp[i].nbytes - j));
+ pos += scnprintf(buf + pos, buflen - pos, "%u",
+ value);
+ if (j + 4 < cdata->kvp[i].nbytes)
+ pos += scnprintf(buf + pos,
+ buflen - pos, " ");
+ }
+ if (cdata->kvp[i].nbytes)
+ pos += scnprintf(buf + pos, buflen - pos, ")");
+ pos += scnprintf(buf + pos, buflen - pos, "]");
+ if (prev_valid + 1 < valid_count)
+ pos += scnprintf(buf + pos, buflen - pos, ", ");
+ prev_valid++;
+ }
+ } else if (msm_rpm_debug_mask & MSM_RPM_LOG_REQUEST_PRETTY) {
+ /* Pretty formatting only */
+ memcpy(name, &cdata->msg_hdr.resource_type, sizeof(uint32_t));
+ pos += scnprintf(buf + pos, buflen - pos, " %s %u; ", name,
+ cdata->msg_hdr.resource_id);
+
+ for (i = 0, prev_valid = 0; i < cdata->write_idx; i++) {
+ if (!cdata->kvp[i].valid)
+ continue;
+
+ memcpy(name, &cdata->kvp[i].key, sizeof(uint32_t));
+ pos += scnprintf(buf + pos, buflen - pos, "%s=%s",
+ name, (cdata->kvp[i].nbytes ? "" : "null"));
+
+ for (j = 0; j < cdata->kvp[i].nbytes; j += 4) {
+ value = 0;
+ memcpy(&value, &cdata->kvp[i].value[j],
+ min(sizeof(uint32_t),
+ cdata->kvp[i].nbytes - j));
+ pos += scnprintf(buf + pos, buflen - pos, "%u",
+ value);
+
+ if (j + 4 < cdata->kvp[i].nbytes)
+ pos += scnprintf(buf + pos,
+ buflen - pos, " ");
+ }
+ if (prev_valid + 1 < valid_count)
+ pos += scnprintf(buf + pos, buflen - pos, ", ");
+ prev_valid++;
+ }
+ } else {
+ /* Raw formatting only */
+ pos += scnprintf(buf + pos, buflen - pos,
+ ", rsc_type=0x%08X, rsc_id=%u; ",
+ cdata->msg_hdr.resource_type,
+ cdata->msg_hdr.resource_id);
+
+ for (i = 0, prev_valid = 0; i < cdata->write_idx; i++) {
+ if (!cdata->kvp[i].valid)
+ continue;
+
+ pos += scnprintf(buf + pos, buflen - pos,
+ "[key=0x%08X, value=%s",
+ cdata->kvp[i].key,
+ (cdata->kvp[i].nbytes ? "0x" : "null"));
+ for (j = 0; j < cdata->kvp[i].nbytes; j++) {
+ pos += scnprintf(buf + pos, buflen - pos,
+ "%02X",
+ cdata->kvp[i].value[j]);
+ if (j + 1 < cdata->kvp[i].nbytes)
+ pos += scnprintf(buf + pos,
+ buflen - pos, " ");
+ }
+ pos += scnprintf(buf + pos, buflen - pos, "]");
+ if (prev_valid + 1 < valid_count)
+ pos += scnprintf(buf + pos, buflen - pos, ", ");
+ prev_valid++;
+ }
+ }
+
+ pos += scnprintf(buf + pos, buflen - pos, "\n");
+ printk(buf);
+}
+
static int msm_rpm_send_data(struct msm_rpm_request *cdata,
int msg_type, bool noirq)
{
@@ -546,6 +694,10 @@
tmpbuff += cdata->kvp[i].nbytes;
}
+ if (msm_rpm_debug_mask
+ & (MSM_RPM_LOG_REQUEST_PRETTY | MSM_RPM_LOG_REQUEST_RAW))
+ msm_rpm_log_request(cdata);
+
if (standalone) {
for (i = 0; (i < cdata->write_idx); i++)
cdata->kvp[i].valid = false;
diff --git a/arch/arm/mach-msm/rpm_resources.c b/arch/arm/mach-msm/rpm_resources.c
index 667ede0..a88e42e 100644
--- a/arch/arm/mach-msm/rpm_resources.c
+++ b/arch/arm/mach-msm/rpm_resources.c
@@ -1106,7 +1106,7 @@
static int __init msm_rpmrs_l2_init(void)
{
if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm8930aa() ||
- cpu_is_apq8064() || cpu_is_msm8627()) {
+ cpu_is_apq8064() || cpu_is_msm8627() || cpu_is_msm8960ab()) {
msm_pm_set_l2_flush_flag(0);
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 08af4d4..281e7b8 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -259,8 +259,16 @@
/* 9625 IDs */
[134] = MSM_CPU_9625,
- /* 8930AA ID */
+ /* 8960AB IDs */
+ [138] = MSM_CPU_8960AB,
+ [139] = MSM_CPU_8960AB,
+ [140] = MSM_CPU_8960AB,
+ [141] = MSM_CPU_8960AB,
+
+ /* 8930AA IDs */
[142] = MSM_CPU_8930AA,
+ [143] = MSM_CPU_8930AA,
+ [144] = MSM_CPU_8930AA,
/* Uninitialized IDs are not known to run Linux.
MSM_CPU_UNKNOWN is set to 0 to ensure these IDs are
diff --git a/arch/arm/mach-msm/spm_devices.c b/arch/arm/mach-msm/spm_devices.c
index 9d2aedc..9e9b661 100644
--- a/arch/arm/mach-msm/spm_devices.c
+++ b/arch/arm/mach-msm/spm_devices.c
@@ -137,7 +137,7 @@
reg = saw_bases[cpu];
if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm8930aa() ||
- cpu_is_apq8064() || cpu_is_msm8627()) {
+ cpu_is_apq8064() || cpu_is_msm8627() || cpu_is_msm8960ab()) {
val = 0xA4;
reg += 0x14;
timeout = 512;
diff --git a/arch/arm/mach-msm/subsystem_restart.c b/arch/arm/mach-msm/subsystem_restart.c
index a9a25b3..65da903 100644
--- a/arch/arm/mach-msm/subsystem_restart.c
+++ b/arch/arm/mach-msm/subsystem_restart.c
@@ -17,7 +17,6 @@
#include <linux/uaccess.h>
#include <linux/module.h>
#include <linux/fs.h>
-#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <linux/list.h>
#include <linux/io.h>
@@ -25,11 +24,13 @@
#include <linux/time.h>
#include <linux/wakelock.h>
#include <linux/suspend.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
#include <asm/current.h>
#include <mach/peripheral-loader.h>
-#include <mach/scm.h>
#include <mach/socinfo.h>
#include <mach/subsystem_notif.h>
#include <mach/subsystem_restart.h>
@@ -42,30 +43,40 @@
struct mutex shutdown_lock;
struct mutex powerup_lock;
- struct subsys_data *subsys_ptrs[];
-};
-
-struct restart_wq_data {
- struct subsys_data *subsys;
- struct wake_lock ssr_wake_lock;
- char wlname[64];
- int use_restart_order;
- struct work_struct work;
+ struct subsys_device *subsys_ptrs[];
};
struct restart_log {
struct timeval time;
- struct subsys_data *subsys;
+ struct subsys_device *dev;
struct list_head list;
};
-static int restart_level;
+struct subsys_device {
+ struct subsys_desc *desc;
+ struct list_head list;
+ struct wake_lock wake_lock;
+ char wlname[64];
+ struct work_struct work;
+ spinlock_t restart_lock;
+ bool restarting;
+
+ void *notify;
+
+ struct mutex shutdown_lock;
+ struct mutex powerup_lock;
+
+ void *restart_order;
+};
+
static int enable_ramdumps;
+module_param(enable_ramdumps, int, S_IRUGO | S_IWUSR);
+
struct workqueue_struct *ssr_wq;
static LIST_HEAD(restart_log_list);
static LIST_HEAD(subsystem_list);
-static DEFINE_SPINLOCK(subsystem_list_lock);
+static DEFINE_MUTEX(subsystem_list_lock);
static DEFINE_MUTEX(soc_order_reg_lock);
static DEFINE_MUTEX(restart_log_mutex);
@@ -122,10 +133,7 @@
static struct subsys_soc_restart_order **restart_orders;
static int n_restart_orders;
-module_param(enable_ramdumps, int, S_IRUGO | S_IWUSR);
-
-static struct subsys_soc_restart_order *_update_restart_order(
- struct subsys_data *subsys);
+static int restart_level = RESET_SOC;
int get_restart_level()
{
@@ -148,18 +156,14 @@
return ret;
switch (restart_level) {
-
case RESET_SOC:
case RESET_SUBSYS_COUPLED:
case RESET_SUBSYS_INDEPENDENT:
pr_info("Phase %d behavior activated.\n", restart_level);
- break;
-
+ break;
default:
restart_level = old_val;
return -EINVAL;
- break;
-
}
return 0;
}
@@ -167,62 +171,29 @@
module_param_call(restart_level, restart_level_set, param_get_int,
&restart_level, 0644);
-static struct subsys_data *_find_subsystem(const char *subsys_name)
-{
- struct subsys_data *subsys;
- unsigned long flags;
-
- spin_lock_irqsave(&subsystem_list_lock, flags);
- list_for_each_entry(subsys, &subsystem_list, list)
- if (!strncmp(subsys->name, subsys_name,
- SUBSYS_NAME_MAX_LENGTH)) {
- spin_unlock_irqrestore(&subsystem_list_lock, flags);
- return subsys;
- }
- spin_unlock_irqrestore(&subsystem_list_lock, flags);
-
- return NULL;
-}
-
-static struct subsys_soc_restart_order *_update_restart_order(
- struct subsys_data *subsys)
+static struct subsys_soc_restart_order *
+update_restart_order(struct subsys_device *dev)
{
int i, j;
-
- if (!subsys)
- return NULL;
-
- if (!subsys->name)
- return NULL;
+ struct subsys_soc_restart_order *order;
+ const char *name = dev->desc->name;
+ int len = SUBSYS_NAME_MAX_LENGTH;
mutex_lock(&soc_order_reg_lock);
for (j = 0; j < n_restart_orders; j++) {
- for (i = 0; i < restart_orders[j]->count; i++)
- if (!strncmp(restart_orders[j]->subsystem_list[i],
- subsys->name, SUBSYS_NAME_MAX_LENGTH)) {
-
- restart_orders[j]->subsys_ptrs[i] =
- subsys;
- mutex_unlock(&soc_order_reg_lock);
- return restart_orders[j];
+ order = restart_orders[j];
+ for (i = 0; i < order->count; i++) {
+ if (!strncmp(order->subsystem_list[i], name, len)) {
+ order->subsys_ptrs[i] = dev;
+ goto found;
}
+ }
}
-
+ order = NULL;
+found:
mutex_unlock(&soc_order_reg_lock);
- return NULL;
-}
-
-static void _send_notification_to_order(struct subsys_data
- **restart_list, int count,
- enum subsys_notif_type notif_type)
-{
- int i;
-
- for (i = 0; i < count; i++)
- if (restart_list[i])
- subsys_notif_queue_notification(
- restart_list[i]->notif_handle, notif_type);
+ return order;
}
static int max_restarts;
@@ -231,7 +202,7 @@
static long max_history_time = 3600;
module_param(max_history_time, long, 0644);
-static void do_epoch_check(struct subsys_data *subsys)
+static void do_epoch_check(struct subsys_device *dev)
{
int n = 0;
struct timeval *time_first = NULL, *curr_time;
@@ -251,7 +222,7 @@
r_log = kmalloc(sizeof(struct restart_log), GFP_KERNEL);
if (!r_log)
goto out;
- r_log->subsys = subsys;
+ r_log->dev = dev;
do_gettimeofday(&r_log->time);
curr_time = &r_log->time;
INIT_LIST_HEAD(&r_log->list);
@@ -289,42 +260,94 @@
mutex_unlock(&restart_log_mutex);
}
+static void for_each_subsys_device(struct subsys_device **list, unsigned count,
+ void *data, void (*fn)(struct subsys_device *, void *))
+{
+ while (count--) {
+ struct subsys_device *dev = *list++;
+ if (!dev)
+ continue;
+ fn(dev, data);
+ }
+}
+
+static void __send_notification_to_order(struct subsys_device *dev, void *data)
+{
+ enum subsys_notif_type type = (enum subsys_notif_type)data;
+
+ subsys_notif_queue_notification(dev->notify, type);
+}
+
+static void send_notification_to_order(struct subsys_device **l, unsigned n,
+ enum subsys_notif_type t)
+{
+ for_each_subsys_device(l, n, (void *)t, __send_notification_to_order);
+}
+
+static void subsystem_shutdown(struct subsys_device *dev, void *data)
+{
+ const char *name = dev->desc->name;
+
+ pr_info("[%p]: Shutting down %s\n", current, name);
+ if (dev->desc->shutdown(dev->desc) < 0)
+ panic("subsys-restart: [%p]: Failed to shutdown %s!",
+ current, name);
+}
+
+static void subsystem_ramdump(struct subsys_device *dev, void *data)
+{
+ const char *name = dev->desc->name;
+
+ if (dev->desc->ramdump)
+ if (dev->desc->ramdump(enable_ramdumps, dev->desc) < 0)
+ pr_warn("%s[%p]: Ramdump failed.\n", name, current);
+}
+
+static void subsystem_powerup(struct subsys_device *dev, void *data)
+{
+ const char *name = dev->desc->name;
+
+ pr_info("[%p]: Powering up %s\n", current, name);
+ if (dev->desc->powerup(dev->desc) < 0)
+ panic("[%p]: Failed to powerup %s!", current, name);
+}
+
static void subsystem_restart_wq_func(struct work_struct *work)
{
- struct restart_wq_data *r_work = container_of(work,
- struct restart_wq_data, work);
- struct subsys_data **restart_list;
- struct subsys_data *subsys = r_work->subsys;
+ struct subsys_device *dev = container_of(work,
+ struct subsys_device, work);
+ struct subsys_device **list;
+ struct subsys_desc *desc = dev->desc;
struct subsys_soc_restart_order *soc_restart_order = NULL;
-
struct mutex *powerup_lock;
struct mutex *shutdown_lock;
+ unsigned count;
+ unsigned long flags;
- int i;
- int restart_list_count = 0;
+ if (restart_level != RESET_SUBSYS_INDEPENDENT)
+ soc_restart_order = dev->restart_order;
- if (r_work->use_restart_order)
- soc_restart_order = subsys->restart_order;
-
- /* It's OK to not take the registration lock at this point.
+ /*
+ * It's OK to not take the registration lock at this point.
* This is because the subsystem list inside the relevant
* restart order is not being traversed.
*/
if (!soc_restart_order) {
- restart_list = subsys->single_restart_list;
- restart_list_count = 1;
- powerup_lock = &subsys->powerup_lock;
- shutdown_lock = &subsys->shutdown_lock;
+ list = &dev;
+ count = 1;
+ powerup_lock = &dev->powerup_lock;
+ shutdown_lock = &dev->shutdown_lock;
} else {
- restart_list = soc_restart_order->subsys_ptrs;
- restart_list_count = soc_restart_order->count;
+ list = soc_restart_order->subsys_ptrs;
+ count = soc_restart_order->count;
powerup_lock = &soc_restart_order->powerup_lock;
shutdown_lock = &soc_restart_order->shutdown_lock;
}
pr_debug("[%p]: Attempting to get shutdown lock!\n", current);
- /* Try to acquire shutdown_lock. If this fails, these subsystems are
+ /*
+ * Try to acquire shutdown_lock. If this fails, these subsystems are
* already being restarted - return.
*/
if (!mutex_trylock(shutdown_lock))
@@ -332,7 +355,8 @@
pr_debug("[%p]: Attempting to get powerup lock!\n", current);
- /* Now that we've acquired the shutdown lock, either we're the first to
+ /*
+ * Now that we've acquired the shutdown lock, either we're the first to
* restart these subsystems or some other thread is doing the powerup
* sequence for these subsystems. In the latter case, panic and bail
* out, since a subsystem died in its powerup sequence.
@@ -341,38 +365,23 @@
panic("%s[%p]: Subsystem died during powerup!",
__func__, current);
- do_epoch_check(subsys);
+ do_epoch_check(dev);
- /* Now it is necessary to take the registration lock. This is because
- * the subsystem list in the SoC restart order will be traversed
- * and it shouldn't be changed until _this_ restart sequence completes.
+ /*
+ * It's necessary to take the registration lock because the subsystem
+ * list in the SoC restart order will be traversed and it shouldn't be
+ * changed until _this_ restart sequence completes.
*/
mutex_lock(&soc_order_reg_lock);
pr_debug("[%p]: Starting restart sequence for %s\n", current,
- r_work->subsys->name);
+ desc->name);
+ send_notification_to_order(list, count, SUBSYS_BEFORE_SHUTDOWN);
+ for_each_subsys_device(list, count, NULL, subsystem_shutdown);
+ send_notification_to_order(list, count, SUBSYS_AFTER_SHUTDOWN);
- _send_notification_to_order(restart_list,
- restart_list_count,
- SUBSYS_BEFORE_SHUTDOWN);
-
- for (i = 0; i < restart_list_count; i++) {
-
- if (!restart_list[i])
- continue;
-
- pr_info("[%p]: Shutting down %s\n", current,
- restart_list[i]->name);
-
- if (restart_list[i]->shutdown(subsys) < 0)
- panic("subsys-restart: %s[%p]: Failed to shutdown %s!",
- __func__, current, restart_list[i]->name);
- }
-
- _send_notification_to_order(restart_list, restart_list_count,
- SUBSYS_AFTER_SHUTDOWN);
-
- /* Now that we've finished shutting down these subsystems, release the
+ /*
+ * Now that we've finished shutting down these subsystems, release the
* shutdown lock. If a subsystem restart request comes in for a
* subsystem in _this_ restart order after the unlock below, and
* before the powerup lock is released, panic and bail out.
@@ -380,40 +389,14 @@
mutex_unlock(shutdown_lock);
/* Collect ram dumps for all subsystems in order here */
- for (i = 0; i < restart_list_count; i++) {
- if (!restart_list[i])
- continue;
+ for_each_subsys_device(list, count, NULL, subsystem_ramdump);
- if (restart_list[i]->ramdump)
- if (restart_list[i]->ramdump(enable_ramdumps,
- subsys) < 0)
- pr_warn("%s[%p]: Ramdump failed.\n",
- restart_list[i]->name, current);
- }
-
- _send_notification_to_order(restart_list,
- restart_list_count,
- SUBSYS_BEFORE_POWERUP);
-
- for (i = restart_list_count - 1; i >= 0; i--) {
-
- if (!restart_list[i])
- continue;
-
- pr_info("[%p]: Powering up %s\n", current,
- restart_list[i]->name);
-
- if (restart_list[i]->powerup(subsys) < 0)
- panic("%s[%p]: Failed to powerup %s!", __func__,
- current, restart_list[i]->name);
- }
-
- _send_notification_to_order(restart_list,
- restart_list_count,
- SUBSYS_AFTER_POWERUP);
+ send_notification_to_order(list, count, SUBSYS_BEFORE_POWERUP);
+ for_each_subsys_device(list, count, NULL, subsystem_powerup);
+ send_notification_to_order(list, count, SUBSYS_AFTER_POWERUP);
pr_info("[%p]: Restart sequence for %s completed.\n",
- current, r_work->subsys->name);
+ current, desc->name);
mutex_unlock(powerup_lock);
@@ -422,123 +405,119 @@
pr_debug("[%p]: Released powerup lock!\n", current);
out:
- wake_unlock(&r_work->ssr_wake_lock);
- wake_lock_destroy(&r_work->ssr_wake_lock);
- kfree(r_work);
+ spin_lock_irqsave(&dev->restart_lock, flags);
+ wake_unlock(&dev->wake_lock);
+ dev->restarting = false;
+ spin_unlock_irqrestore(&dev->restart_lock, flags);
}
-static void __subsystem_restart(struct subsys_data *subsys)
+static void __subsystem_restart_dev(struct subsys_device *dev)
{
- struct restart_wq_data *data = NULL;
- int rc;
+ struct subsys_desc *desc = dev->desc;
+ unsigned long flags;
- pr_debug("Restarting %s [level=%d]!\n", subsys->name,
+ spin_lock_irqsave(&dev->restart_lock, flags);
+ if (!dev->restarting) {
+ pr_debug("Restarting %s [level=%d]!\n", desc->name,
restart_level);
- data = kzalloc(sizeof(struct restart_wq_data), GFP_ATOMIC);
- if (!data)
- panic("%s: Unable to allocate memory to restart %s.",
- __func__, subsys->name);
-
- data->subsys = subsys;
-
- if (restart_level != RESET_SUBSYS_INDEPENDENT)
- data->use_restart_order = 1;
-
- snprintf(data->wlname, sizeof(data->wlname), "ssr(%s)", subsys->name);
- wake_lock_init(&data->ssr_wake_lock, WAKE_LOCK_SUSPEND, data->wlname);
- wake_lock(&data->ssr_wake_lock);
-
- INIT_WORK(&data->work, subsystem_restart_wq_func);
- rc = queue_work(ssr_wq, &data->work);
- if (rc < 0)
- panic("%s: Unable to schedule work to restart %s (%d).",
- __func__, subsys->name, rc);
+ dev->restarting = true;
+ wake_lock(&dev->wake_lock);
+ queue_work(ssr_wq, &dev->work);
+ }
+ spin_unlock_irqrestore(&dev->restart_lock, flags);
}
-int subsystem_restart(const char *subsys_name)
+int subsystem_restart_dev(struct subsys_device *dev)
{
- struct subsys_data *subsys;
-
- if (!subsys_name) {
- pr_err("Invalid subsystem name.\n");
- return -EINVAL;
- }
+ const char *name = dev->desc->name;
pr_info("Restart sequence requested for %s, restart_level = %d.\n",
- subsys_name, restart_level);
-
- /* List of subsystems is protected by a lock. New subsystems can
- * still come in.
- */
- subsys = _find_subsystem(subsys_name);
-
- if (!subsys) {
- pr_warn("Unregistered subsystem %s!\n", subsys_name);
- return -EINVAL;
- }
+ name, restart_level);
switch (restart_level) {
case RESET_SUBSYS_COUPLED:
case RESET_SUBSYS_INDEPENDENT:
- __subsystem_restart(subsys);
+ __subsystem_restart_dev(dev);
break;
-
case RESET_SOC:
- panic("subsys-restart: Resetting the SoC - %s crashed.",
- subsys->name);
+ panic("subsys-restart: Resetting the SoC - %s crashed.", name);
break;
-
default:
panic("subsys-restart: Unknown restart level!\n");
- break;
-
+ break;
}
return 0;
}
+EXPORT_SYMBOL(subsystem_restart_dev);
+
+int subsystem_restart(const char *name)
+{
+ struct subsys_device *dev;
+
+ mutex_lock(&subsystem_list_lock);
+ list_for_each_entry(dev, &subsystem_list, list)
+ if (!strncmp(dev->desc->name, name, SUBSYS_NAME_MAX_LENGTH))
+ goto found;
+ dev = NULL;
+found:
+ mutex_unlock(&subsystem_list_lock);
+ if (dev)
+ return subsystem_restart_dev(dev);
+ return -ENODEV;
+}
EXPORT_SYMBOL(subsystem_restart);
-int ssr_register_subsystem(struct subsys_data *subsys)
+struct subsys_device *subsys_register(struct subsys_desc *desc)
{
- unsigned long flags;
+ struct subsys_device *dev;
- if (!subsys)
- goto err;
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return ERR_PTR(-ENOMEM);
- if (!subsys->name)
- goto err;
+ dev->desc = desc;
+ dev->notify = subsys_notif_add_subsys(desc->name);
+ dev->restart_order = update_restart_order(dev);
- if (!subsys->powerup || !subsys->shutdown)
- goto err;
+ snprintf(dev->wlname, sizeof(dev->wlname), "ssr(%s)", desc->name);
+ wake_lock_init(&dev->wake_lock, WAKE_LOCK_SUSPEND, dev->wlname);
+ INIT_WORK(&dev->work, subsystem_restart_wq_func);
+ spin_lock_init(&dev->restart_lock);
- subsys->notif_handle = subsys_notif_add_subsys(subsys->name);
- subsys->restart_order = _update_restart_order(subsys);
- subsys->single_restart_list[0] = subsys;
+ mutex_init(&dev->shutdown_lock);
+ mutex_init(&dev->powerup_lock);
- mutex_init(&subsys->shutdown_lock);
- mutex_init(&subsys->powerup_lock);
+ mutex_lock(&subsystem_list_lock);
+ list_add(&dev->list, &subsystem_list);
+ mutex_unlock(&subsystem_list_lock);
- spin_lock_irqsave(&subsystem_list_lock, flags);
- list_add(&subsys->list, &subsystem_list);
- spin_unlock_irqrestore(&subsystem_list_lock, flags);
-
- return 0;
-
-err:
- return -EINVAL;
+ return dev;
}
-EXPORT_SYMBOL(ssr_register_subsystem);
+EXPORT_SYMBOL(subsys_register);
+
+void subsys_unregister(struct subsys_device *dev)
+{
+ if (IS_ERR_OR_NULL(dev))
+ return;
+ mutex_lock(&subsystem_list_lock);
+ list_del(&dev->list);
+ mutex_unlock(&subsystem_list_lock);
+ wake_lock_destroy(&dev->wake_lock);
+ kfree(dev);
+}
+EXPORT_SYMBOL(subsys_unregister);
static int ssr_panic_handler(struct notifier_block *this,
unsigned long event, void *ptr)
{
- struct subsys_data *subsys;
+ struct subsys_device *dev;
- list_for_each_entry(subsys, &subsystem_list, list)
- if (subsys->crash_shutdown)
- subsys->crash_shutdown(subsys);
+ list_for_each_entry(dev, &subsystem_list, list)
+ if (dev->desc->crash_shutdown)
+ dev->desc->crash_shutdown(dev->desc);
return NOTIFY_DONE;
}
@@ -569,7 +548,8 @@
}
if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm8930aa() ||
- cpu_is_msm9615() || cpu_is_apq8064() || cpu_is_msm8627()) {
+ cpu_is_msm9615() || cpu_is_apq8064() || cpu_is_msm8627() ||
+ cpu_is_msm8960ab()) {
if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE) {
restart_orders = restart_orders_8960_sglte;
n_restart_orders =
@@ -594,20 +574,12 @@
static int __init subsys_restart_init(void)
{
- int ret = 0;
-
- restart_level = RESET_SOC;
-
ssr_wq = alloc_workqueue("ssr_wq", 0, 0);
-
if (!ssr_wq)
panic("Couldn't allocate workqueue for subsystem restart.\n");
- ret = ssr_init_soc_restart_orders();
-
- return ret;
+ return ssr_init_soc_restart_orders();
}
-
arch_initcall(subsys_restart_init);
MODULE_DESCRIPTION("Subsystem Restart Driver");
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index 8d31683..668f4cc 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -965,7 +965,8 @@
return 0;
if (cpu_is_msm8x60() || cpu_is_msm8960() || cpu_is_apq8064() ||
- cpu_is_msm8930() || cpu_is_msm8930aa() || cpu_is_msm8627())
+ cpu_is_msm8930() || cpu_is_msm8930aa() || cpu_is_msm8627() ||
+ cpu_is_msm8960ab())
__raw_writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL);
if (__get_cpu_var(first_boot)) {
@@ -1062,7 +1063,8 @@
gpt->flags |= MSM_CLOCK_FLAGS_UNSTABLE_COUNT;
dgt->flags |= MSM_CLOCK_FLAGS_UNSTABLE_COUNT;
} else if (cpu_is_msm8960() || cpu_is_apq8064() || cpu_is_msm8930() ||
- cpu_is_msm8930aa() || cpu_is_msm8627()) {
+ cpu_is_msm8930aa() || cpu_is_msm8627() ||
+ cpu_is_msm8960ab()) {
global_timer_offset = MSM_TMR0_BASE - MSM_TMR_BASE;
dgt->freq = 6750000;
__raw_writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL);
@@ -1072,7 +1074,7 @@
gpt_hz = 32765;
sclk_hz = 32765;
if (!cpu_is_msm8930() && !cpu_is_msm8930aa() &&
- !cpu_is_msm8627()) {
+ !cpu_is_msm8627() && !cpu_is_msm8960ab()) {
gpt->flags |= MSM_CLOCK_FLAGS_UNSTABLE_COUNT;
dgt->flags |= MSM_CLOCK_FLAGS_UNSTABLE_COUNT;
}
@@ -1123,8 +1125,9 @@
ce->irq = clock->irq;
if (cpu_is_msm8x60() || cpu_is_msm8960() || cpu_is_apq8064() ||
- cpu_is_msm8930() || cpu_is_msm8930aa() ||
- cpu_is_msm9615() || cpu_is_msm8625() || cpu_is_msm8627()) {
+ cpu_is_msm8930() || cpu_is_msm9615() || cpu_is_msm8625() ||
+ cpu_is_msm8627() || cpu_is_msm8930aa() ||
+ cpu_is_msm8960ab()) {
clock->percpu_evt = alloc_percpu(struct clock_event_device *);
if (!clock->percpu_evt) {
pr_err("msm_timer_init: memory allocation "
diff --git a/arch/arm/mach-msm/wcnss-ssr-8960.c b/arch/arm/mach-msm/wcnss-ssr-8960.c
index 793ef7f..4295d9b 100644
--- a/arch/arm/mach-msm/wcnss-ssr-8960.c
+++ b/arch/arm/mach-msm/wcnss-ssr-8960.c
@@ -19,6 +19,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/wcnss_wlan.h>
+#include <linux/err.h>
#include <mach/irqs.h>
#include <mach/scm.h>
#include <mach/subsystem_restart.h>
@@ -37,6 +38,7 @@
static int riva_crash;
static int ss_restart_inprogress;
static int enable_riva_ssr;
+static struct subsys_device *riva_8960_dev;
static void smsm_state_cb_hdlr(void *data, uint32_t old_state,
uint32_t new_state)
@@ -83,7 +85,7 @@
}
ss_restart_inprogress = true;
- subsystem_restart("riva");
+ subsystem_restart_dev(riva_8960_dev);
}
static irqreturn_t riva_wdog_bite_irq_hdlr(int irq, void *dev_id)
@@ -100,7 +102,7 @@
panic(MODULE_NAME ": Watchdog bite received from Riva");
ss_restart_inprogress = true;
- subsystem_restart("riva");
+ subsystem_restart_dev(riva_8960_dev);
return IRQ_HANDLED;
}
@@ -126,7 +128,7 @@
}
/* Subsystem handlers */
-static int riva_shutdown(const struct subsys_data *subsys)
+static int riva_shutdown(const struct subsys_desc *subsys)
{
pil_force_shutdown("wcnss");
flush_delayed_work(&cancel_vote_work);
@@ -135,7 +137,7 @@
return 0;
}
-static int riva_powerup(const struct subsys_data *subsys)
+static int riva_powerup(const struct subsys_desc *subsys)
{
struct platform_device *pdev = wcnss_get_platform_device();
struct wcnss_wlan_config *pwlanconfig = wcnss_get_wlan_config();
@@ -158,12 +160,11 @@
return ret;
}
-/* RAM segments for Riva SS;
- * We don't specify the full 5MB allocated for Riva. Only 3MB is specified */
+/* 5MB RAM segments for Riva SS */
static struct ramdump_segment riva_segments[] = {{0x8f200000,
- 0x8f500000 - 0x8f200000} };
+ 0x8f700000 - 0x8f200000} };
-static int riva_ramdump(int enable, const struct subsys_data *subsys)
+static int riva_ramdump(int enable, const struct subsys_desc *subsys)
{
pr_debug("%s: enable[%d]\n", MODULE_NAME, enable);
if (enable)
@@ -175,14 +176,14 @@
}
/* Riva crash handler */
-static void riva_crash_shutdown(const struct subsys_data *subsys)
+static void riva_crash_shutdown(const struct subsys_desc *subsys)
{
pr_err("%s: crash shutdown : %d\n", MODULE_NAME, riva_crash);
if (riva_crash != true)
smsm_riva_reset();
}
-static struct subsys_data riva_8960 = {
+static struct subsys_desc riva_8960 = {
.name = "riva",
.shutdown = riva_shutdown,
.powerup = riva_powerup,
@@ -209,7 +210,10 @@
static int __init riva_restart_init(void)
{
- return ssr_register_subsystem(&riva_8960);
+ riva_8960_dev = subsys_register(&riva_8960);
+ if (IS_ERR(riva_8960_dev))
+ return PTR_ERR(riva_8960_dev);
+ return 0;
}
static int __init riva_ssr_module_init(void)
@@ -254,6 +258,7 @@
static void __exit riva_ssr_module_exit(void)
{
+ subsys_unregister(riva_8960_dev);
free_irq(RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ, NULL);
}
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index a20b6cb..da33be0 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -839,6 +839,79 @@
}
}
+#ifndef CONFIG_ARM_LPAE
+
+/*
+ * The Linux PMD is made of two consecutive section entries covering 2MB
+ * (see definition in include/asm/pgtable-2level.h). However a call to
+ * create_mapping() may optimize static mappings by using individual
+ * 1MB section mappings. This leaves the actual PMD potentially half
+ * initialized if the top or bottom section entry isn't used, leaving it
+ * open to problems if a subsequent ioremap() or vmalloc() tries to use
+ * the virtual space left free by that unused section entry.
+ *
+ * Let's avoid the issue by inserting dummy vm entries covering the unused
+ * PMD halves once the static mappings are in place.
+ */
+
+static void __init pmd_empty_section_gap(unsigned long addr)
+{
+ struct vm_struct *vm;
+
+ vm = early_alloc_aligned(sizeof(*vm), __alignof__(*vm));
+ vm->addr = (void *)addr;
+ vm->size = SECTION_SIZE;
+ vm->flags = VM_IOREMAP | VM_ARM_STATIC_MAPPING;
+ vm->caller = pmd_empty_section_gap;
+ vm_area_add_early(vm);
+}
+
+static void __init fill_pmd_gaps(void)
+{
+ struct vm_struct *vm;
+ unsigned long addr, next = 0;
+ pmd_t *pmd;
+
+ /* we're still single threaded hence no lock needed here */
+ for (vm = vmlist; vm; vm = vm->next) {
+ if (!(vm->flags & VM_ARM_STATIC_MAPPING))
+ continue;
+ addr = (unsigned long)vm->addr;
+ if (addr < next)
+ continue;
+
+ /*
+ * Check if this vm starts on an odd section boundary.
+ * If so and the first section entry for this PMD is free
+ * then we block the corresponding virtual address.
+ */
+ if ((addr & ~PMD_MASK) == SECTION_SIZE) {
+ pmd = pmd_off_k(addr);
+ if (pmd_none(*pmd))
+ pmd_empty_section_gap(addr & PMD_MASK);
+ }
+
+ /*
+ * Then check if this vm ends on an odd section boundary.
+ * If so and the second section entry for this PMD is empty
+ * then we block the corresponding virtual address.
+ */
+ addr += vm->size;
+ if ((addr & ~PMD_MASK) == SECTION_SIZE) {
+ pmd = pmd_off_k(addr) + 1;
+ if (pmd_none(*pmd))
+ pmd_empty_section_gap(addr);
+ }
+
+ /* no need to look at any vm entry until we hit the next PMD */
+ next = (addr + PMD_SIZE - 1) & PMD_MASK;
+ }
+}
+
+#else
+#define fill_pmd_gaps() do { } while (0)
+#endif
+
static void * __initdata vmalloc_min =
(void *)(VMALLOC_END - (240 << 20) - VMALLOC_OFFSET);
@@ -1128,6 +1201,7 @@
*/
if (mdesc->map_io)
mdesc->map_io();
+ fill_pmd_gaps();
/*
* Finally flush the caches and tlb to ensure that we're in a
diff --git a/block/test-iosched.c b/block/test-iosched.c
index 3c38734..ce9527f 100644
--- a/block/test-iosched.c
+++ b/block/test-iosched.c
@@ -127,7 +127,7 @@
test_pr_info("%s: request %d completed, err=%d",
__func__, test_rq->req_id, err);
- test_rq->req_completed = 1;
+ test_rq->req_completed = true;
test_rq->req_result = err;
check_test_completion();
@@ -204,8 +204,8 @@
blk_put_request(rq);
return -ENODEV;
}
- test_rq->req_completed = 0;
- test_rq->req_result = -1;
+ test_rq->req_completed = false;
+ test_rq->req_result = -EINVAL;
test_rq->rq = rq;
test_rq->is_err_expected = is_err_expcted;
rq->elv.priv[0] = (void *)test_rq;
@@ -347,8 +347,8 @@
ptd->num_of_write_bios += num_bios;
test_rq->req_id = ptd->wr_rd_next_req_id++;
- test_rq->req_completed = 0;
- test_rq->req_result = -1;
+ test_rq->req_completed = false;
+ test_rq->req_result = -EINVAL;
test_rq->rq = rq;
test_rq->is_err_expected = is_err_expcted;
rq->elv.priv[0] = (void *)test_rq;
@@ -519,10 +519,26 @@
static void free_test_requests(struct test_data *td)
{
struct test_request *test_rq;
+ struct bio *bio;
+
while (!list_empty(&td->test_queue)) {
test_rq = list_entry(td->test_queue.next, struct test_request,
queuelist);
list_del_init(&test_rq->queuelist);
+ /*
+ * If the request was not completed we need to free its BIOs
+ * and remove it from the packed list
+ */
+ if (!test_rq->req_completed) {
+ test_pr_info(
+ "%s: Freeing memory of an uncompleted request",
+ __func__);
+ list_del_init(&test_rq->rq->queuelist);
+ while ((bio = test_rq->rq->bio) != NULL) {
+ test_rq->rq->bio = bio->bi_next;
+ bio_put(bio);
+ }
+ }
blk_put_request(test_rq->rq);
kfree(test_rq->bios_buffer);
kfree(test_rq);
@@ -606,7 +622,8 @@
test_pr_info(
"%s: Another test is running, try again later",
__func__);
- return -EINVAL;
+ spin_unlock(&ptd->lock);
+ return -EBUSY;
}
if (ptd->start_sector == 0) {
@@ -698,9 +715,8 @@
return -EINVAL;
error:
- ptd->test_result = TEST_FAILED;
- ptd->test_info.testcase = 0;
post_test(ptd);
+ ptd->test_result = TEST_FAILED;
return ret;
}
EXPORT_SYMBOL(test_iosched_start_test);
diff --git a/drivers/bluetooth/hci_smd.c b/drivers/bluetooth/hci_smd.c
index 66bd739..6030520 100644
--- a/drivers/bluetooth/hci_smd.c
+++ b/drivers/bluetooth/hci_smd.c
@@ -42,6 +42,7 @@
*/
#define RX_Q_MONITOR (500) /* 500 milli second */
+#define HCI_REGISTER_SET 0
static int hcismd_set;
@@ -57,7 +58,7 @@
struct hci_smd_data {
struct hci_dev *hdev;
-
+ unsigned long flags;
struct smd_channel *event_channel;
struct smd_channel *data_channel;
struct wake_lock wake_lock_tx;
@@ -403,11 +404,16 @@
struct hci_dev *hdev;
hdev = hsmd->hdev;
-
+ if (test_and_set_bit(HCI_REGISTER_SET, &hsmd->flags)) {
+ BT_ERR("HCI device registered already");
+ return 0;
+ } else
+ BT_INFO("HCI device registration is starting");
if (hci_register_dev(hdev) < 0) {
BT_ERR("Can't register HCI device");
hci_free_dev(hdev);
hsmd->hdev = NULL;
+ clear_bit(HCI_REGISTER_SET, &hsmd->flags);
return -ENODEV;
}
return 0;
@@ -473,6 +479,11 @@
{
tasklet_kill(&hs.rx_task);
+ if (!test_and_clear_bit(HCI_REGISTER_SET, &hsmd->flags)) {
+ BT_ERR("HCI device un-registered already");
+ return;
+ } else
+ BT_INFO("HCI device un-registration going on");
if (hsmd->hdev) {
if (hci_unregister_dev(hsmd->hdev) < 0)
BT_ERR("Can't unregister HCI device %s",
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 6a7b931..2f356f0 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -47,7 +47,7 @@
#define APPS_PROC 1
#define QDSP_PROC 2
#define WCNSS_PROC 3
-#define MSG_MASK_SIZE 9500
+#define MSG_MASK_SIZE 10000
#define LOG_MASK_SIZE 8000
#define EVENT_MASK_SIZE 1000
#define USER_SPACE_DATA 8000
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 74416e5..384c1bf 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -129,6 +129,7 @@
case MSM_CPU_8X60:
return APQ8060_TOOLS_ID;
case MSM_CPU_8960:
+ case MSM_CPU_8960AB:
return AO8960_TOOLS_ID;
case MSM_CPU_8064:
return APQ8064_TOOLS_ID;
@@ -156,6 +157,7 @@
switch (socinfo_get_msm_cpu()) {
case MSM_CPU_8960:
+ case MSM_CPU_8960AB:
case MSM_CPU_8064:
case MSM_CPU_8930:
case MSM_CPU_8930AA:
@@ -178,7 +180,8 @@
if (driver->use_device_tree)
return 1;
else if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm8930aa() ||
- cpu_is_msm9615() || cpu_is_apq8064() || cpu_is_msm8627())
+ cpu_is_msm9615() || cpu_is_apq8064() || cpu_is_msm8627() ||
+ cpu_is_msm8960ab())
return 1;
else
return 0;
@@ -513,6 +516,7 @@
CREATE_MSG_MASK_TBL_ROW(20);
CREATE_MSG_MASK_TBL_ROW(21);
CREATE_MSG_MASK_TBL_ROW(22);
+ CREATE_MSG_MASK_TBL_ROW(23);
}
static void diag_set_msg_mask(int rt_mask)
@@ -1231,7 +1235,8 @@
driver->apps_rsp_buf[1] = 0x1;
driver->apps_rsp_buf[2] = 0x1;
driver->apps_rsp_buf[3] = 0x0;
- *(int *)(driver->apps_rsp_buf + 4) = MSG_MASK_TBL_CNT;
+ /* -1 to un-account for OEM SSID range */
+ *(int *)(driver->apps_rsp_buf + 4) = MSG_MASK_TBL_CNT - 1;
*(uint16_t *)(driver->apps_rsp_buf + 8) = MSG_SSID_0;
*(uint16_t *)(driver->apps_rsp_buf + 10) = MSG_SSID_0_LAST;
*(uint16_t *)(driver->apps_rsp_buf + 12) = MSG_SSID_1;
diff --git a/drivers/char/msm_rotator.c b/drivers/char/msm_rotator.c
index e783a1a..4d34362 100644
--- a/drivers/char/msm_rotator.c
+++ b/drivers/char/msm_rotator.c
@@ -171,11 +171,10 @@
CLK_SUSPEND,
};
-int msm_rotator_iommu_map_buf(int mem_id, unsigned char src,
+int msm_rotator_iommu_map_buf(int mem_id, int domain,
unsigned long *start, unsigned long *len,
- struct ion_handle **pihdl)
+ struct ion_handle **pihdl, unsigned int secure)
{
- int domain;
if (!msm_rotator_dev->client)
return -EINVAL;
@@ -187,16 +186,30 @@
pr_debug("%s(): ion_hdl %p, ion_fd %d\n", __func__, *pihdl,
ion_share_dma_buf(msm_rotator_dev->client, *pihdl));
- if (rot_iommu_split_domain)
- domain = src ? ROTATOR_SRC_DOMAIN : ROTATOR_DST_DOMAIN;
- else
- domain = ROTATOR_SRC_DOMAIN;
-
- if (ion_map_iommu(msm_rotator_dev->client,
- *pihdl, domain, GEN_POOL,
- SZ_4K, 0, start, len, 0, ION_IOMMU_UNMAP_DELAYED)) {
- pr_err("ion_map_iommu() failed\n");
- return -EINVAL;
+ if (rot_iommu_split_domain) {
+ if (secure) {
+ if (ion_phys(msm_rotator_dev->client,
+ *pihdl, start, (unsigned *)len)) {
+ pr_err("%s:%d: ion_phys map failed\n",
+ __func__, __LINE__);
+ return -ENOMEM;
+ }
+ } else {
+ if (ion_map_iommu(msm_rotator_dev->client,
+ *pihdl, domain, GEN_POOL,
+ SZ_4K, 0, start, len, 0,
+ ION_IOMMU_UNMAP_DELAYED)) {
+ pr_err("ion_map_iommu() failed\n");
+ return -EINVAL;
+ }
+ }
+ } else {
+ if (ion_map_iommu(msm_rotator_dev->client,
+ *pihdl, ROTATOR_SRC_DOMAIN, GEN_POOL,
+ SZ_4K, 0, start, len, 0, ION_IOMMU_UNMAP_DELAYED)) {
+ pr_err("ion_map_iommu() failed\n");
+ return -EINVAL;
+ }
}
pr_debug("%s(): mem_id %d, start 0x%lx, len 0x%lx\n",
@@ -813,9 +826,9 @@
return 0;
}
-static int get_img(struct msmfb_data *fbd, unsigned char src,
+static int get_img(struct msmfb_data *fbd, int domain,
unsigned long *start, unsigned long *len, struct file **p_file,
- int *p_need, struct ion_handle **p_ihdl)
+ int *p_need, struct ion_handle **p_ihdl, unsigned int secure)
{
int ret = 0;
#ifdef CONFIG_FB
@@ -857,8 +870,8 @@
#endif
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
- return msm_rotator_iommu_map_buf(fbd->memory_id, src, start,
- len, p_ihdl);
+ return msm_rotator_iommu_map_buf(fbd->memory_id, domain, start,
+ len, p_ihdl, secure);
#endif
#ifdef CONFIG_ANDROID_PMEM
if (!get_pmem_file(fbd->memory_id, start, &vstart, len, p_file))
@@ -870,7 +883,7 @@
}
static void put_img(struct file *p_file, struct ion_handle *p_ihdl,
- unsigned char src)
+ int domain, unsigned int secure)
{
#ifdef CONFIG_ANDROID_PMEM
if (p_file != NULL)
@@ -879,14 +892,15 @@
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
if (!IS_ERR_OR_NULL(p_ihdl)) {
- int domain;
- if (rot_iommu_split_domain)
- domain = src ? ROTATOR_SRC_DOMAIN : ROTATOR_DST_DOMAIN;
- else
- domain = ROTATOR_SRC_DOMAIN;
pr_debug("%s(): p_ihdl %p\n", __func__, p_ihdl);
- ion_unmap_iommu(msm_rotator_dev->client,
- p_ihdl, domain, GEN_POOL);
+ if (rot_iommu_split_domain) {
+ if (!secure)
+ ion_unmap_iommu(msm_rotator_dev->client,
+ p_ihdl, domain, GEN_POOL);
+ } else {
+ ion_unmap_iommu(msm_rotator_dev->client,
+ p_ihdl, ROTATOR_SRC_DOMAIN, GEN_POOL);
+ }
ion_free(msm_rotator_dev->client, p_ihdl);
}
@@ -953,18 +967,18 @@
goto do_rotate_unlock_mutex;
}
- rc = get_img(&info.src, 1, (unsigned long *)&in_paddr,
+ rc = get_img(&info.src, ROTATOR_SRC_DOMAIN, (unsigned long *)&in_paddr,
(unsigned long *)&src_len, &srcp0_file, &ps0_need,
- &srcp0_ihdl);
+ &srcp0_ihdl, 0);
if (rc) {
pr_err("%s: in get_img() failed id=0x%08x\n",
DRIVER_NAME, info.src.memory_id);
goto do_rotate_unlock_mutex;
}
- rc = get_img(&info.dst, 0, (unsigned long *)&out_paddr,
+ rc = get_img(&info.dst, ROTATOR_DST_DOMAIN, (unsigned long *)&out_paddr,
(unsigned long *)&dst_len, &dstp0_file, &p_need,
- &dstp0_ihdl);
+ &dstp0_ihdl, img_info->secure);
if (rc) {
pr_err("%s: out get_img() failed id=0x%08x\n",
DRIVER_NAME, info.dst.memory_id);
@@ -992,20 +1006,20 @@
goto do_rotate_unlock_mutex;
}
- rc = get_img(&info.src_chroma, 1,
+ rc = get_img(&info.src_chroma, ROTATOR_SRC_DOMAIN,
(unsigned long *)&in_chroma_paddr,
(unsigned long *)&src_len, &srcp1_file, &p_need,
- &srcp1_ihdl);
+ &srcp1_ihdl, 0);
if (rc) {
pr_err("%s: in chroma get_img() failed id=0x%08x\n",
DRIVER_NAME, info.src_chroma.memory_id);
goto do_rotate_unlock_mutex;
}
- rc = get_img(&info.dst_chroma, 0,
+ rc = get_img(&info.dst_chroma, ROTATOR_DST_DOMAIN,
(unsigned long *)&out_chroma_paddr,
(unsigned long *)&dst_len, &dstp1_file, &p_need,
- &dstp1_ihdl);
+ &dstp1_ihdl, img_info->secure);
if (rc) {
pr_err("%s: out chroma get_img() failed id=0x%08x\n",
DRIVER_NAME, info.dst_chroma.memory_id);
@@ -1176,15 +1190,17 @@
#endif
schedule_delayed_work(&msm_rotator_dev->rot_clk_work, HZ);
do_rotate_unlock_mutex:
- put_img(dstp1_file, dstp1_ihdl, 0);
- put_img(srcp1_file, srcp1_ihdl, 1);
- put_img(dstp0_file, dstp0_ihdl, 0);
+ put_img(dstp1_file, dstp1_ihdl, ROTATOR_DST_DOMAIN,
+ msm_rotator_dev->img_info[s]->secure);
+ put_img(srcp1_file, srcp1_ihdl, ROTATOR_SRC_DOMAIN, 0);
+ put_img(dstp0_file, dstp0_ihdl, ROTATOR_DST_DOMAIN,
+ msm_rotator_dev->img_info[s]->secure);
/* only source may use frame buffer */
if (info.src.flags & MDP_MEMORY_ID_TYPE_FB)
fput_light(srcp0_file, ps0_need);
else
- put_img(srcp0_file, srcp0_ihdl, 1);
+ put_img(srcp0_file, srcp0_ihdl, ROTATOR_SRC_DOMAIN, 0);
mutex_unlock(&msm_rotator_dev->rotator_lock);
dev_dbg(msm_rotator_dev->device, "%s() returning rc = %d\n",
__func__, rc);
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c
index 2a191d5..cc6d744 100644
--- a/drivers/crypto/msm/qcedev.c
+++ b/drivers/crypto/msm/qcedev.c
@@ -2098,12 +2098,19 @@
return 0;
};
+static struct of_device_id qcedev_match[] = {
+ { .compatible = "qcom,qcedev",
+ },
+ {}
+};
+
static struct platform_driver qcedev_plat_driver = {
.probe = qcedev_probe,
.remove = qcedev_remove,
.driver = {
.name = "qce",
.owner = THIS_MODULE,
+ .of_match_table = qcedev_match,
},
};
@@ -2222,7 +2229,7 @@
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Mona Hossain <mhossain@codeaurora.org>");
MODULE_DESCRIPTION("Qualcomm DEV Crypto driver");
-MODULE_VERSION("1.26");
+MODULE_VERSION("1.27");
module_init(qcedev_init);
module_exit(qcedev_exit);
diff --git a/drivers/crypto/msm/qcrypto.c b/drivers/crypto/msm/qcrypto.c
index a41a64b..c11c36e 100644
--- a/drivers/crypto/msm/qcrypto.c
+++ b/drivers/crypto/msm/qcrypto.c
@@ -3260,12 +3260,20 @@
return rc;
};
+
+static struct of_device_id qcrypto_match[] = {
+ { .compatible = "qcom,qcrypto",
+ },
+ {}
+};
+
static struct platform_driver _qualcomm_crypto = {
.probe = _qcrypto_probe,
.remove = _qcrypto_remove,
.driver = {
.owner = THIS_MODULE,
.name = "qcrypto",
+ .of_match_table = qcrypto_match,
},
};
@@ -3364,4 +3372,4 @@
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Mona Hossain <mhossain@codeaurora.org>");
MODULE_DESCRIPTION("Qualcomm Crypto driver");
-MODULE_VERSION("1.21");
+MODULE_VERSION("1.22");
diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c
index c31f0f0..741d4fa 100644
--- a/drivers/gpu/ion/ion.c
+++ b/drivers/gpu/ion/ion.c
@@ -1294,7 +1294,7 @@
valid_handle = ion_handle_validate(client, handle);
mutex_unlock(&client->lock);
if (!valid_handle) {
- WARN("%s: invalid handle passed to share.\n", __func__);
+ WARN(1, "%s: invalid handle passed to share.\n", __func__);
return -EINVAL;
}
diff --git a/drivers/gpu/msm/a3xx_reg.h b/drivers/gpu/msm/a3xx_reg.h
index f5ee1d7..8ec9431 100644
--- a/drivers/gpu/msm/a3xx_reg.h
+++ b/drivers/gpu/msm/a3xx_reg.h
@@ -151,6 +151,7 @@
#define A3XX_GRAS_CL_USER_PLANE_Y5 0xCB5
#define A3XX_GRAS_CL_USER_PLANE_Z5 0xCB6
#define A3XX_GRAS_CL_USER_PLANE_W5 0xCB7
+#define A3XX_VFD_PERFCOUNTER0_SELECT 0xE44
#define A3XX_VPC_VPC_DEBUG_RAM_SEL 0xE61
#define A3XX_VPC_VPC_DEBUG_RAM_READ 0xE62
#define A3XX_UCHE_CACHE_INVALIDATE0_REG 0xEA0
@@ -289,6 +290,8 @@
#define RB_CLEAR_MODE_RESOLVE 1
#define RB_TILINGMODE_LINEAR 0
#define RB_REF_NEVER 0
+#define RB_FRAG_LESS 1
+#define RB_REF_ALWAYS 7
#define RB_STENCIL_KEEP 0
#define RB_RENDERING_PASS 0
#define RB_TILINGMODE_32X32 2
@@ -326,6 +329,7 @@
#define GRAS_SC_SCREEN_SCISSOR_BR_BR_Y 16
#define GRAS_SC_WINDOW_SCISSOR_BR_BR_X 0
#define GRAS_SC_WINDOW_SCISSOR_BR_BR_Y 16
+#define GRAS_SU_CTRLMODE_LINEHALFWIDTH 03
#define HLSQ_CONSTFSPRESERVEDRANGEREG_ENDENTRY 16
#define HLSQ_CONSTFSPRESERVEDRANGEREG_STARTENTRY 0
#define HLSQ_CTRL0REG_CHUNKDISABLE 26
@@ -396,6 +400,7 @@
#define RB_STENCILCONTROL_STENCIL_ZPASS 14
#define RB_STENCILCONTROL_STENCIL_ZPASS_BF 26
#define SP_FSCTRLREG0_FSFULLREGFOOTPRINT 10
+#define SP_FSCTRLREG0_FSHALFREGFOOTPRINT 4
#define SP_FSCTRLREG0_FSICACHEINVALID 2
#define SP_FSCTRLREG0_FSINOUTREGOVERLAP 18
#define SP_FSCTRLREG0_FSINSTRBUFFERMODE 1
@@ -408,13 +413,16 @@
#define SP_FSCTRLREG1_FSINITIALOUTSTANDING 20
#define SP_FSCTRLREG1_HALFPRECVAROFFSET 24
#define SP_FSMRTREG_REGID 0
+#define SP_FSMRTREG_PRECISION 8
#define SP_FSOUTREG_PAD0 2
#define SP_IMAGEOUTPUTREG_MRTFORMAT 0
+#define SP_IMAGEOUTPUTREG_DEPTHOUTMODE 3
#define SP_IMAGEOUTPUTREG_PAD0 6
#define SP_OBJOFFSETREG_CONSTOBJECTSTARTOFFSET 16
#define SP_OBJOFFSETREG_SHADEROBJOFFSETINIC 25
#define SP_SHADERLENGTH_LEN 0
#define SP_SPCTRLREG_CONSTMODE 18
+#define SP_SPCTRLREG_LOMODE 22
#define SP_SPCTRLREG_SLEEPMODE 20
#define SP_VSCTRLREG0_VSFULLREGFOOTPRINT 10
#define SP_VSCTRLREG0_VSICACHEINVALID 2
@@ -455,6 +463,7 @@
#define VFD_FETCHINSTRUCTIONS_STEPRATE 24
#define VFD_FETCHINSTRUCTIONS_SWITCHNEXT 17
#define VFD_THREADINGTHRESHOLD_REGID_VTXCNT 8
+#define VFD_THREADINGTHRESHOLD_REGID_THRESHOLD 0
#define VFD_THREADINGTHRESHOLD_RESERVED6 4
#define VPC_VPCATTR_LMSIZE 28
#define VPC_VPCATTR_THRHDASSIGN 12
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index ecff3ea..7720df0 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -544,53 +544,16 @@
static unsigned int
a3xx_getchipid(struct kgsl_device *device)
{
- unsigned int majorid = 0, minorid = 0, patchid = 0;
+ struct kgsl_device_platform_data *pdata =
+ kgsl_device_get_drvdata(device);
/*
- * We could detect the chipID from the hardware but it takes multiple
- * registers to find the right combination. Since we traffic exclusively
- * in system on chips, we can be (mostly) confident that a SOC version
- * will match a GPU (at this juncture at least). So do the lazy/quick
- * thing and set the chip_id based on the SoC
+ * All current A3XX chipids are detected at the SOC level. Leave this
+ * function here to support any future GPUs that have working
+ * chip ID registers
*/
- unsigned int version = socinfo_get_version();
-
- if (cpu_is_apq8064()) {
-
- /* A320 */
- majorid = 2;
- minorid = 0;
-
- /*
- * V1.1 has some GPU work arounds that we need to communicate
- * up to user space via the patchid
- */
-
- if ((SOCINFO_VERSION_MAJOR(version) == 1) &&
- (SOCINFO_VERSION_MINOR(version) == 1))
- patchid = 1;
- else
- patchid = 0;
- } else if (cpu_is_msm8930() || cpu_is_msm8930aa() || cpu_is_msm8627()) {
-
- /* A305 */
- majorid = 0;
- minorid = 5;
-
- /*
- * V1.2 has some GPU work arounds that we need to communicate
- * up to user space via the patchid
- */
-
- if ((SOCINFO_VERSION_MAJOR(version) == 1) &&
- (SOCINFO_VERSION_MINOR(version) == 2))
- patchid = 2;
- else
- patchid = 0;
- }
-
- return (0x03 << 24) | (majorid << 16) | (minorid << 8) | patchid;
+ return pdata->chipid;
}
static unsigned int
@@ -598,7 +561,13 @@
{
unsigned int chipid = 0;
unsigned int coreid, majorid, minorid, patchid, revid;
- uint32_t soc_platform_version = socinfo_get_version();
+ struct kgsl_device_platform_data *pdata =
+ kgsl_device_get_drvdata(device);
+
+ /* If the chip id is set at the platform level, then just use that */
+
+ if (pdata->chipid != 0)
+ return pdata->chipid;
adreno_regread(device, REG_RBBM_PERIPHID1, &coreid);
adreno_regread(device, REG_RBBM_PERIPHID2, &majorid);
@@ -608,7 +577,7 @@
* adreno 22x gpus are indicated by coreid 2,
* but REG_RBBM_PERIPHID1 always contains 0 for this field
*/
- if (cpu_is_msm8960() || cpu_is_msm8x60())
+ if (cpu_is_msm8x60())
chipid = 2 << 24;
else
chipid = (coreid & 0xF) << 24;
@@ -620,13 +589,9 @@
patchid = ((revid >> 16) & 0xFF);
/* 8x50 returns 0 for patch release, but it should be 1 */
- /* 8960v3 returns 5 for patch release, but it should be 6 */
/* 8x25 returns 0 for minor id, but it should be 1 */
if (cpu_is_qsd8x50())
patchid = 1;
- else if (cpu_is_msm8960() &&
- SOCINFO_VERSION_MAJOR(soc_platform_version) == 3)
- patchid = 6;
else if (cpu_is_msm8625() && minorid == 0)
minorid = 1;
@@ -638,11 +603,18 @@
static unsigned int
adreno_getchipid(struct kgsl_device *device)
{
- if (cpu_is_apq8064() || cpu_is_msm8930() || cpu_is_msm8930aa() ||
- cpu_is_msm8627())
- return a3xx_getchipid(device);
- else
+ struct kgsl_device_platform_data *pdata =
+ kgsl_device_get_drvdata(device);
+
+ /*
+ * All A3XX chipsets will have pdata set, so assume !pdata->chipid is
+ * an A2XX processor
+ */
+
+ if (pdata->chipid == 0 || ADRENO_CHIPID_MAJOR(pdata->chipid) == 2)
return a2xx_getchipid(device);
+ else
+ return a3xx_getchipid(device);
}
static inline bool _rev_match(unsigned int id, unsigned int entry)
@@ -657,10 +629,10 @@
adreno_dev->chip_id = adreno_getchipid(&adreno_dev->dev);
- core = (adreno_dev->chip_id >> 24) & 0xff;
- major = (adreno_dev->chip_id >> 16) & 0xff;
- minor = (adreno_dev->chip_id >> 8) & 0xff;
- patchid = (adreno_dev->chip_id & 0xff);
+ core = ADRENO_CHIPID_CORE(adreno_dev->chip_id);
+ major = ADRENO_CHIPID_MAJOR(adreno_dev->chip_id);
+ minor = ADRENO_CHIPID_MINOR(adreno_dev->chip_id);
+ patchid = ADRENO_CHIPID_PATCH(adreno_dev->chip_id);
for (i = 0; i < ARRAY_SIZE(adreno_gpulist); i++) {
if (core == adreno_gpulist[i].core &&
@@ -741,7 +713,8 @@
int status = -EINVAL;
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
- kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT);
+ if (KGSL_STATE_DUMP_AND_RECOVER != device->state)
+ kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT);
/* Power up the device */
kgsl_pwrctrl_enable(device);
@@ -785,7 +758,10 @@
status = adreno_ringbuffer_start(&adreno_dev->ringbuffer, init_ram);
if (status == 0) {
- mod_timer(&device->idle_timer, jiffies + FIRST_TIMEOUT);
+ /* While recovery is on we do not want timer to
+ * fire and attempt to change any device state */
+ if (KGSL_STATE_DUMP_AND_RECOVER != device->state)
+ mod_timer(&device->idle_timer, jiffies + FIRST_TIMEOUT);
return 0;
}
@@ -934,6 +910,8 @@
/* Restore valid commands in ringbuffer */
adreno_ringbuffer_restore(rb, rb_buffer, num_rb_contents);
rb->timestamp[KGSL_MEMSTORE_GLOBAL] = timestamp;
+ /* wait for idle */
+ ret = adreno_idle(device, KGSL_TIMEOUT_DEFAULT);
done:
vfree(rb_buffer);
return ret;
@@ -1201,7 +1179,8 @@
err:
KGSL_DRV_ERR(device, "spun too long waiting for RB to idle\n");
- if (!adreno_dump_and_recover(device)) {
+ if (KGSL_STATE_DUMP_AND_RECOVER != device->state &&
+ !adreno_dump_and_recover(device)) {
wait_time = jiffies + wait_timeout;
goto retry;
}
@@ -1595,10 +1574,9 @@
context_id, timestamp, context_id, ts_issued,
adreno_dev->ringbuffer.wptr);
if (!adreno_dump_and_recover(device)) {
- /* wait for idle after recovery as the
- * timestamp that this process wanted
- * to wait on may be invalid */
- if (!adreno_idle(device, KGSL_TIMEOUT_DEFAULT))
+ /* The timestamp that this process wanted
+ * to wait on may be invalid or expired now
+ * after successful recovery */
status = 0;
}
done:
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index e1d1eb9..04dc3d6 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -24,6 +24,11 @@
#define ADRENO_DEVICE(device) \
KGSL_CONTAINER_OF(device, struct adreno_device, dev)
+#define ADRENO_CHIPID_CORE(_id) (((_id) >> 24) & 0xFF)
+#define ADRENO_CHIPID_MAJOR(_id) (((_id) >> 16) & 0xFF)
+#define ADRENO_CHIPID_MINOR(_id) (((_id) >> 8) & 0xFF)
+#define ADRENO_CHIPID_PATCH(_id) ((_id) & 0xFF)
+
/* Flags to control command packet settings */
#define KGSL_CMD_FLAGS_NONE 0x00000000
#define KGSL_CMD_FLAGS_PMODE 0x00000001
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 6eebeb8..bb89067 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -500,26 +500,19 @@
*cmds++ = _SET(VFD_DECODEINSTRUCTIONS_WRITEMASK, 0x0F) |
_SET(VFD_DECODEINSTRUCTIONS_CONSTFILL, 1) |
_SET(VFD_DECODEINSTRUCTIONS_FORMAT, 2) |
- _SET(VFD_DECODEINSTRUCTIONS_REGID, 5) |
_SET(VFD_DECODEINSTRUCTIONS_SHIFTCNT, 12) |
_SET(VFD_DECODEINSTRUCTIONS_LASTCOMPVALID, 1);
*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 5);
*cmds++ = CP_REG(A3XX_HLSQ_CONTROL_0_REG);
/* HLSQ_CONTROL_0_REG */
- *cmds++ = _SET(HLSQ_CTRL0REG_FSTHREADSIZE, HLSQ_TWO_PIX_QUADS) |
+ *cmds++ = _SET(HLSQ_CTRL0REG_FSTHREADSIZE, HLSQ_FOUR_PIX_QUADS) |
_SET(HLSQ_CTRL0REG_FSSUPERTHREADENABLE, 1) |
- _SET(HLSQ_CTRL0REG_SPSHADERRESTART, 1) |
_SET(HLSQ_CTRL0REG_RESERVED2, 1) |
- _SET(HLSQ_CTRL0REG_CHUNKDISABLE, 1) |
- _SET(HLSQ_CTRL0REG_CONSTSWITCHMODE, 1) |
- _SET(HLSQ_CTRL0REG_LAZYUPDATEDISABLE, 1) |
- _SET(HLSQ_CTRL0REG_SPCONSTFULLUPDATE, 1) |
- _SET(HLSQ_CTRL0REG_TPFULLUPDATE, 1);
+ _SET(HLSQ_CTRL0REG_SPCONSTFULLUPDATE, 1);
/* HLSQ_CONTROL_1_REG */
*cmds++ = _SET(HLSQ_CTRL1REG_VSTHREADSIZE, HLSQ_TWO_VTX_QUADS) |
- _SET(HLSQ_CTRL1REG_VSSUPERTHREADENABLE, 1) |
- _SET(HLSQ_CTRL1REG_RESERVED1, 4);
+ _SET(HLSQ_CTRL1REG_VSSUPERTHREADENABLE, 1);
/* HLSQ_CONTROL_2_REG */
*cmds++ = _SET(HLSQ_CTRL2REG_PRIMALLOCTHRESHOLD, 31);
/* HLSQ_CONTROL_3_REG */
@@ -531,7 +524,7 @@
*cmds++ = _SET(HLSQ_VSCTRLREG_VSINSTRLENGTH, 1);
/* HLSQ_FS_CONTROL_REG */
*cmds++ = _SET(HLSQ_FSCTRLREG_FSCONSTLENGTH, 1) |
- _SET(HLSQ_FSCTRLREG_FSCONSTSTARTOFFSET, 272) |
+ _SET(HLSQ_FSCTRLREG_FSCONSTSTARTOFFSET, 128) |
_SET(HLSQ_FSCTRLREG_FSINSTRLENGTH, 1);
/* HLSQ_CONST_VSPRESV_RANGE_REG */
*cmds++ = 0x00000000;
@@ -547,8 +540,8 @@
*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
*cmds++ = CP_REG(A3XX_SP_SP_CTRL_REG);
/* SP_SP_CTRL_REG */
- *cmds++ = _SET(SP_SPCTRLREG_CONSTMODE, 1) |
- _SET(SP_SPCTRLREG_SLEEPMODE, 1);
+ *cmds++ = _SET(SP_SPCTRLREG_SLEEPMODE, 1) |
+ _SET(SP_SPCTRLREG_LOMODE, 1);
*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 12);
*cmds++ = CP_REG(A3XX_SP_VS_CTRL_REG0);
@@ -556,15 +549,14 @@
*cmds++ = _SET(SP_VSCTRLREG0_VSTHREADMODE, SP_MULTI) |
_SET(SP_VSCTRLREG0_VSINSTRBUFFERMODE, SP_BUFFER_MODE) |
_SET(SP_VSCTRLREG0_VSICACHEINVALID, 1) |
- _SET(SP_VSCTRLREG0_VSFULLREGFOOTPRINT, 3) |
+ _SET(SP_VSCTRLREG0_VSFULLREGFOOTPRINT, 1) |
_SET(SP_VSCTRLREG0_VSTHREADSIZE, SP_TWO_VTX_QUADS) |
_SET(SP_VSCTRLREG0_VSSUPERTHREADMODE, 1) |
_SET(SP_VSCTRLREG0_VSLENGTH, 1);
/* SP_VS_CTRL_REG1 */
*cmds++ = _SET(SP_VSCTRLREG1_VSINITIALOUTSTANDING, 4);
/* SP_VS_PARAM_REG */
- *cmds++ = _SET(SP_VSPARAMREG_POSREGID, 1) |
- _SET(SP_VSPARAMREG_PSIZEREGID, 252);
+ *cmds++ = _SET(SP_VSPARAMREG_PSIZEREGID, 252);
/* SP_VS_OUT_REG_0 */
*cmds++ = 0x00000000;
/* SP_VS_OUT_REG_1 */
@@ -605,18 +597,17 @@
*cmds++ = _SET(SP_FSCTRLREG0_FSTHREADMODE, SP_MULTI) |
_SET(SP_FSCTRLREG0_FSINSTRBUFFERMODE, SP_BUFFER_MODE) |
_SET(SP_FSCTRLREG0_FSICACHEINVALID, 1) |
- _SET(SP_FSCTRLREG0_FSFULLREGFOOTPRINT, 2) |
+ _SET(SP_FSCTRLREG0_FSHALFREGFOOTPRINT, 1) |
_SET(SP_FSCTRLREG0_FSINOUTREGOVERLAP, 1) |
- _SET(SP_FSCTRLREG0_FSTHREADSIZE, SP_TWO_VTX_QUADS) |
+ _SET(SP_FSCTRLREG0_FSTHREADSIZE, SP_FOUR_PIX_QUADS) |
_SET(SP_FSCTRLREG0_FSSUPERTHREADMODE, 1) |
_SET(SP_FSCTRLREG0_FSLENGTH, 1);
/* SP_FS_CTRL_REG1 */
*cmds++ = _SET(SP_FSCTRLREG1_FSCONSTLENGTH, 1) |
- _SET(SP_FSCTRLREG1_FSINITIALOUTSTANDING, 2) |
_SET(SP_FSCTRLREG1_HALFPRECVAROFFSET, 63);
/* SP_FS_OBJ_OFFSET_REG */
- *cmds++ = _SET(SP_OBJOFFSETREG_CONSTOBJECTSTARTOFFSET, 272) |
- _SET(SP_OBJOFFSETREG_SHADEROBJOFFSETINIC, 1);
+ *cmds++ = _SET(SP_OBJOFFSETREG_CONSTOBJECTSTARTOFFSET, 128) |
+ _SET(SP_OBJOFFSETREG_SHADEROBJOFFSETINIC, 127);
/* SP_FS_OBJ_START_REG */
*cmds++ = 0x00000000;
@@ -630,12 +621,13 @@
*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
*cmds++ = CP_REG(A3XX_SP_FS_OUTPUT_REG);
/* SP_FS_OUTPUT_REG */
- *cmds++ = _SET(SP_IMAGEOUTPUTREG_PAD0, SP_PIXEL_BASED);
+ *cmds++ = _SET(SP_IMAGEOUTPUTREG_DEPTHOUTMODE, SP_PIXEL_BASED);
*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 5);
*cmds++ = CP_REG(A3XX_SP_FS_MRT_REG_0);
/* SP_FS_MRT_REG_0 */
- *cmds++ = _SET(SP_FSMRTREG_REGID, 1);
+ *cmds++ = _SET(SP_FSMRTREG_PRECISION, 1);
+
/* SP_FS_MRT_REG_1 */
*cmds++ = 0x00000000;
/* SP_FS_MRT_REG_2 */
@@ -676,14 +668,21 @@
| (0 << CP_LOADSTATE_EXTSRCADDR_SHIFT);
/* (sy)(rpt3)mov.f32f32 r0.y, (r)r1.y; */
- *cmds++ = 0x00000005; *cmds++ = 0x30044b01;
+ *cmds++ = 0x00000000; *cmds++ = 0x13001000;
/* end; */
- *cmds++ = 0x00000000; *cmds++ = 0x03000000;
+ *cmds++ = 0x00000000; *cmds++ = 0x00000000;
/* nop; */
*cmds++ = 0x00000000; *cmds++ = 0x00000000;
/* nop; */
*cmds++ = 0x00000000; *cmds++ = 0x00000000;
+
+ *cmds++ = cp_type0_packet(A3XX_VFD_PERFCOUNTER0_SELECT, 1);
+ *cmds++ = 0x00000000;
+
+ *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
+ *cmds++ = 0x00000000;
+
*cmds++ = cp_type3_packet(CP_LOAD_STATE, 10);
*cmds++ = (0 << CP_LOADSTATE_DSTOFFSET_SHIFT)
| (HLSQ_DIRECT << CP_LOADSTATE_STATESRC_SHIFT)
@@ -693,7 +692,7 @@
| (0 << CP_LOADSTATE_EXTSRCADDR_SHIFT);
/* (sy)(rpt3)mov.f32f32 r0.y, (r)c0.x; */
- *cmds++ = 0x00000000; *cmds++ = 0x30244b01;
+ *cmds++ = 0x00000000; *cmds++ = 0x30201b00;
/* end; */
*cmds++ = 0x00000000; *cmds++ = 0x03000000;
/* nop; */
@@ -701,6 +700,15 @@
/* nop; */
*cmds++ = 0x00000000; *cmds++ = 0x00000000;
+
+
+ *cmds++ = cp_type0_packet(A3XX_VFD_PERFCOUNTER0_SELECT, 1);
+ *cmds++ = 0x00000000;
+
+ *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
+ *cmds++ = 0x00000000;
+
+
*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
*cmds++ = CP_REG(A3XX_RB_MSAA_CONTROL);
/* RB_MSAA_CONTROL */
@@ -713,6 +721,23 @@
*cmds++ = _SET(RB_DEPTHCONTROL_Z_TEST_FUNC, RB_FRAG_NEVER);
*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+ *cmds++ = CP_REG(A3XX_RB_STENCIL_CONTROL);
+ /* RB_STENCIL_CONTROL */
+ *cmds++ = _SET(RB_STENCILCONTROL_STENCIL_FUNC, RB_REF_NEVER) |
+ _SET(RB_STENCILCONTROL_STENCIL_FAIL, RB_STENCIL_KEEP) |
+ _SET(RB_STENCILCONTROL_STENCIL_ZPASS, RB_STENCIL_KEEP) |
+ _SET(RB_STENCILCONTROL_STENCIL_ZFAIL, RB_STENCIL_KEEP) |
+ _SET(RB_STENCILCONTROL_STENCIL_FUNC_BF, RB_REF_NEVER) |
+ _SET(RB_STENCILCONTROL_STENCIL_FAIL_BF, RB_STENCIL_KEEP) |
+ _SET(RB_STENCILCONTROL_STENCIL_ZPASS_BF, RB_STENCIL_KEEP) |
+ _SET(RB_STENCILCONTROL_STENCIL_ZFAIL_BF, RB_STENCIL_KEEP);
+
+ *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+ *cmds++ = CP_REG(A3XX_GRAS_SU_MODE_CONTROL);
+ /* GRAS_SU_MODE_CONTROL */
+ *cmds++ = 0x00000000;
+
+ *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
*cmds++ = CP_REG(A3XX_RB_MRT_CONTROL0);
/* RB_MRT_CONTROL0 */
*cmds++ = _SET(RB_MRTCONTROL_READ_DEST_ENABLE, 1) |
@@ -777,7 +802,7 @@
/* VFD_INDEX_MIN */
*cmds++ = 0x00000000;
/* VFD_INDEX_MAX */
- *cmds++ = 0xFFFFFFFF;
+ *cmds++ = 0x155;
/* VFD_INSTANCEID_OFFSET */
*cmds++ = 0x00000000;
/* VFD_INDEX_OFFSET */
@@ -786,7 +811,7 @@
*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
*cmds++ = CP_REG(A3XX_VFD_VS_THREADING_THRESHOLD);
/* VFD_VS_THREADING_THRESHOLD */
- *cmds++ = _SET(VFD_THREADINGTHRESHOLD_RESERVED6, 12) |
+ *cmds++ = _SET(VFD_THREADINGTHRESHOLD_REGID_THRESHOLD, 15) |
_SET(VFD_THREADINGTHRESHOLD_REGID_VTXCNT, 252);
*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
@@ -861,6 +886,46 @@
*cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
*cmds++ = 0x00000000;
+
+ /* oxili_generate_context_roll_packets */
+ *cmds++ = cp_type0_packet(A3XX_SP_VS_CTRL_REG0, 1);
+ *cmds++ = 0x00000400;
+
+ *cmds++ = cp_type0_packet(A3XX_SP_FS_CTRL_REG0, 1);
+ *cmds++ = 0x00000400;
+
+ *cmds++ = cp_type0_packet(A3XX_SP_VS_PVT_MEM_SIZE_REG, 1);
+ *cmds++ = 0x00008000; /* SP_VS_MEM_SIZE_REG */
+
+ *cmds++ = cp_type0_packet(A3XX_SP_FS_PVT_MEM_SIZE_REG, 1);
+ *cmds++ = 0x00008000; /* SP_FS_MEM_SIZE_REG */
+
+ /* Clear cache invalidate bit when re-loading the shader control regs */
+ *cmds++ = cp_type0_packet(A3XX_SP_VS_CTRL_REG0, 1);
+ *cmds++ = _SET(SP_VSCTRLREG0_VSTHREADMODE, SP_MULTI) |
+ _SET(SP_VSCTRLREG0_VSINSTRBUFFERMODE, SP_BUFFER_MODE) |
+ _SET(SP_VSCTRLREG0_VSFULLREGFOOTPRINT, 1) |
+ _SET(SP_VSCTRLREG0_VSTHREADSIZE, SP_TWO_VTX_QUADS) |
+ _SET(SP_VSCTRLREG0_VSSUPERTHREADMODE, 1) |
+ _SET(SP_VSCTRLREG0_VSLENGTH, 1);
+
+ *cmds++ = cp_type0_packet(A3XX_SP_FS_CTRL_REG0, 1);
+ *cmds++ = _SET(SP_FSCTRLREG0_FSTHREADMODE, SP_MULTI) |
+ _SET(SP_FSCTRLREG0_FSINSTRBUFFERMODE, SP_BUFFER_MODE) |
+ _SET(SP_FSCTRLREG0_FSHALFREGFOOTPRINT, 1) |
+ _SET(SP_FSCTRLREG0_FSINOUTREGOVERLAP, 1) |
+ _SET(SP_FSCTRLREG0_FSTHREADSIZE, SP_FOUR_PIX_QUADS) |
+ _SET(SP_FSCTRLREG0_FSSUPERTHREADMODE, 1) |
+ _SET(SP_FSCTRLREG0_FSLENGTH, 1);
+
+ *cmds++ = cp_type0_packet(A3XX_SP_VS_PVT_MEM_SIZE_REG, 1);
+ *cmds++ = 0x00000000; /* SP_VS_MEM_SIZE_REG */
+
+ *cmds++ = cp_type0_packet(A3XX_SP_FS_PVT_MEM_SIZE_REG, 1);
+ *cmds++ = 0x00000000; /* SP_FS_MEM_SIZE_REG */
+
+ /* end oxili_generate_context_roll_packets */
+
/*
* Resolve using two draw calls with a dummy register
* write in between. This is a HLM workaround
@@ -904,7 +969,6 @@
return cmds;
}
-
static void build_shader_save_cmds(struct adreno_device *adreno_dev,
struct adreno_context *drawctxt)
{
@@ -1172,12 +1236,13 @@
*cmds++ = CP_REG(A3XX_HLSQ_CONTROL_0_REG);
/* HLSQ_CONTROL_0_REG */
*cmds++ = _SET(HLSQ_CTRL0REG_FSTHREADSIZE, HLSQ_FOUR_PIX_QUADS) |
+ _SET(HLSQ_CTRL0REG_FSSUPERTHREADENABLE, 1) |
_SET(HLSQ_CTRL0REG_SPSHADERRESTART, 1) |
_SET(HLSQ_CTRL0REG_CHUNKDISABLE, 1) |
- _SET(HLSQ_CTRL0REG_SPCONSTFULLUPDATE, 1) |
- _SET(HLSQ_CTRL0REG_TPFULLUPDATE, 1);
+ _SET(HLSQ_CTRL0REG_SPCONSTFULLUPDATE, 1);
/* HLSQ_CONTROL_1_REG */
- *cmds++ = _SET(HLSQ_CTRL1REG_VSTHREADSIZE, HLSQ_TWO_VTX_QUADS);
+ *cmds++ = _SET(HLSQ_CTRL1REG_VSTHREADSIZE, HLSQ_TWO_VTX_QUADS) |
+ _SET(HLSQ_CTRL1REG_VSSUPERTHREADENABLE, 1);
/* HLSQ_CONTROL_2_REG */
*cmds++ = _SET(HLSQ_CTRL2REG_PRIMALLOCTHRESHOLD, 31);
/* HLSQ_CONTROL3_REG */
@@ -1204,6 +1269,9 @@
*cmds++ = 0x00000240;
*cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_VFD_PERFCOUNTER0_SELECT, 1);
+ *cmds++ = 0x00000000;
+
/* Texture memobjs */
*cmds++ = cp_type3_packet(CP_LOAD_STATE, 6);
*cmds++ = (16 << CP_LOADSTATE_DSTOFFSET_SHIFT)
@@ -1217,6 +1285,9 @@
*cmds++ = (shadow->pitch*4*8) << 9;
*cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_VFD_PERFCOUNTER0_SELECT, 1);
+ *cmds++ = 0x00000000;
+
/* Mipmap bases */
*cmds++ = cp_type3_packet(CP_LOAD_STATE, 16);
*cmds++ = (224 << CP_LOADSTATE_DSTOFFSET_SHIFT)
@@ -1240,6 +1311,9 @@
*cmds++ = 0x00000000;
*cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_VFD_PERFCOUNTER0_SELECT, 1);
+ *cmds++ = 0x00000000;
+
*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 5);
*cmds++ = CP_REG(A3XX_HLSQ_VS_CONTROL_REG);
/* HLSQ_VS_CONTROL_REG */
@@ -1313,9 +1387,11 @@
*cmds++ = _SET(SP_FSCTRLREG0_FSTHREADMODE, SP_MULTI) |
_SET(SP_FSCTRLREG0_FSINSTRBUFFERMODE, SP_BUFFER_MODE) |
_SET(SP_FSCTRLREG0_FSICACHEINVALID, 1) |
- _SET(SP_FSCTRLREG0_FSFULLREGFOOTPRINT, 2) |
+ _SET(SP_FSCTRLREG0_FSHALFREGFOOTPRINT, 1) |
+ _SET(SP_FSCTRLREG0_FSFULLREGFOOTPRINT, 1) |
_SET(SP_FSCTRLREG0_FSINOUTREGOVERLAP, 1) |
_SET(SP_FSCTRLREG0_FSTHREADSIZE, SP_FOUR_PIX_QUADS) |
+ _SET(SP_FSCTRLREG0_FSSUPERTHREADMODE, 1) |
_SET(SP_FSCTRLREG0_PIXLODENABLE, 1) |
_SET(SP_FSCTRLREG0_FSLENGTH, 2);
/* SP_FS_CTRL_REG1 */
@@ -1324,7 +1400,7 @@
_SET(SP_FSCTRLREG1_HALFPRECVAROFFSET, 63);
/* SP_FS_OBJ_OFFSET_REG */
*cmds++ = _SET(SP_OBJOFFSETREG_CONSTOBJECTSTARTOFFSET, 128) |
- _SET(SP_OBJOFFSETREG_SHADEROBJOFFSETINIC, 1);
+ _SET(SP_OBJOFFSETREG_SHADEROBJOFFSETINIC, 126);
/* SP_FS_OBJ_START_REG */
*cmds++ = 0x00000000;
@@ -1343,7 +1419,7 @@
*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 5);
*cmds++ = CP_REG(A3XX_SP_FS_MRT_REG_0);
/* SP_FS_MRT_REG0 */
- *cmds++ = _SET(SP_FSMRTREG_REGID, 4);
+ *cmds++ = _SET(SP_FSMRTREG_PRECISION, 1);
/* SP_FS_MRT_REG1 */
*cmds++ = 0;
/* SP_FS_MRT_REG2 */
@@ -1440,7 +1516,8 @@
*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
*cmds++ = CP_REG(A3XX_SP_SP_CTRL_REG);
/* SP_SP_CTRL_REG */
- *cmds++ = _SET(SP_SPCTRLREG_SLEEPMODE, 1);
+ *cmds++ = _SET(SP_SPCTRLREG_SLEEPMODE, 1) |
+ _SET(SP_SPCTRLREG_LOMODE, 1);
/* Load vertex shader */
*cmds++ = cp_type3_packet(CP_LOAD_STATE, 10);
@@ -1451,7 +1528,7 @@
*cmds++ = (HLSQ_SP_VS_INSTR << CP_LOADSTATE_STATETYPE_SHIFT)
| (0 << CP_LOADSTATE_EXTSRCADDR_SHIFT);
/* (sy)end; */
- *cmds++ = 0x00000000; *cmds++ = 0x13000000;
+ *cmds++ = 0x00000000; *cmds++ = 0x13001000;
/* nop; */
*cmds++ = 0x00000000; *cmds++ = 0x00000000;
/* nop; */
@@ -1459,6 +1536,13 @@
/* nop; */
*cmds++ = 0x00000000; *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_VFD_PERFCOUNTER0_SELECT, 1);
+ *cmds++ = 0x00000000;
+
+ *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
+ *cmds++ = 0x00000000;
+
+
/* Load fragment shader */
*cmds++ = cp_type3_packet(CP_LOAD_STATE, 18);
*cmds++ = (0 << CP_LOADSTATE_DSTOFFSET_SHIFT)
@@ -1468,21 +1552,27 @@
*cmds++ = (HLSQ_SP_FS_INSTR << CP_LOADSTATE_STATETYPE_SHIFT)
| (0 << CP_LOADSTATE_EXTSRCADDR_SHIFT);
/* (sy)(rpt1)bary.f (ei)r0.z, (r)0, r0.x; */
- *cmds++ = 0x00002000; *cmds++ = 0x57368902;
+ *cmds++ = 0x00002000; *cmds++ = 0x57309902;
/* (rpt5)nop; */
*cmds++ = 0x00000000; *cmds++ = 0x00000500;
/* sam (f32)r0.xyzw, r0.z, s#0, t#0; */
*cmds++ = 0x00000005; *cmds++ = 0xa0c01f00;
/* (sy)mov.f32f32 r1.x, r0.x; */
- *cmds++ = 0x00000000; *cmds++ = 0x30044004;
+ *cmds++ = 0x00000000; *cmds++ = 0x30040b00;
/* mov.f32f32 r1.y, r0.y; */
- *cmds++ = 0x00000001; *cmds++ = 0x20044005;
- /* mov.f32f32 r1.z, r0.z; */
- *cmds++ = 0x00000002; *cmds++ = 0x20044006;
- /* mov.f32f32 r1.w, r0.w; */
- *cmds++ = 0x00000003; *cmds++ = 0x20044007;
- /* end; */
*cmds++ = 0x00000000; *cmds++ = 0x03000000;
+ /* mov.f32f32 r1.z, r0.z; */
+ *cmds++ = 0x00000000; *cmds++ = 0x00000000;
+ /* mov.f32f32 r1.w, r0.w; */
+ *cmds++ = 0x00000000; *cmds++ = 0x00000000;
+ /* end; */
+ *cmds++ = 0x00000000; *cmds++ = 0x00000000;
+
+ *cmds++ = cp_type0_packet(A3XX_VFD_PERFCOUNTER0_SELECT, 1);
+ *cmds++ = 0x00000000;
+
+ *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
+ *cmds++ = 0x00000000;
*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
*cmds++ = CP_REG(A3XX_VFD_CONTROL_0);
@@ -1535,16 +1625,16 @@
*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
*cmds++ = CP_REG(A3XX_RB_DEPTH_CONTROL);
/* RB_DEPTH_CONTROL */
- *cmds++ = _SET(RB_DEPTHCONTROL_Z_TEST_FUNC, RB_FRAG_NEVER);
+ *cmds++ = _SET(RB_DEPTHCONTROL_Z_TEST_FUNC, RB_FRAG_LESS);
*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
*cmds++ = CP_REG(A3XX_RB_STENCIL_CONTROL);
/* RB_STENCIL_CONTROL */
- *cmds++ = _SET(RB_STENCILCONTROL_STENCIL_FUNC, RB_REF_NEVER) |
+ *cmds++ = _SET(RB_STENCILCONTROL_STENCIL_FUNC, RB_REF_ALWAYS) |
_SET(RB_STENCILCONTROL_STENCIL_FAIL, RB_STENCIL_KEEP) |
_SET(RB_STENCILCONTROL_STENCIL_ZPASS, RB_STENCIL_KEEP) |
_SET(RB_STENCILCONTROL_STENCIL_ZFAIL, RB_STENCIL_KEEP) |
- _SET(RB_STENCILCONTROL_STENCIL_FUNC_BF, RB_REF_NEVER) |
+ _SET(RB_STENCILCONTROL_STENCIL_FUNC_BF, RB_REF_ALWAYS) |
_SET(RB_STENCILCONTROL_STENCIL_FAIL_BF, RB_STENCIL_KEEP) |
_SET(RB_STENCILCONTROL_STENCIL_ZPASS_BF, RB_STENCIL_KEEP) |
_SET(RB_STENCILCONTROL_STENCIL_ZFAIL_BF, RB_STENCIL_KEEP);
@@ -1570,9 +1660,8 @@
*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
*cmds++ = CP_REG(A3XX_RB_MRT_CONTROL0);
/* RB_MRT_CONTROL0 */
- *cmds++ = _SET(RB_MRTCONTROL_READ_DEST_ENABLE, 1) |
- _SET(RB_MRTCONTROL_ROP_CODE, 12) |
- _SET(RB_MRTCONTROL_DITHER_MODE, RB_DITHER_ALWAYS) |
+ *cmds++ = _SET(RB_MRTCONTROL_ROP_CODE, 12) |
+ _SET(RB_MRTCONTROL_DITHER_MODE, RB_DITHER_DISABLE) |
_SET(RB_MRTCONTROL_COMPONENT_ENABLE, 0xF);
*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
@@ -1587,7 +1676,8 @@
_SET(RB_MRTBLENDCONTROL_CLAMP_ENABLE, 1);
/* RB_MRT_CONTROL1 */
*cmds++ = _SET(RB_MRTCONTROL_READ_DEST_ENABLE, 1) |
- _SET(RB_MRTCONTROL_DITHER_MODE, RB_DITHER_DISABLE) |
+ _SET(RB_MRTCONTROL_ROP_CODE, 12) |
+ _SET(RB_MRTCONTROL_DITHER_MODE, RB_DITHER_ALWAYS) |
_SET(RB_MRTCONTROL_COMPONENT_ENABLE, 0xF);
*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
@@ -1602,7 +1692,8 @@
_SET(RB_MRTBLENDCONTROL_CLAMP_ENABLE, 1);
/* RB_MRT_CONTROL2 */
*cmds++ = _SET(RB_MRTCONTROL_READ_DEST_ENABLE, 1) |
- _SET(RB_MRTCONTROL_DITHER_MODE, RB_DITHER_DISABLE) |
+ _SET(RB_MRTCONTROL_ROP_CODE, 12) |
+ _SET(RB_MRTCONTROL_DITHER_MODE, RB_DITHER_ALWAYS) |
_SET(RB_MRTCONTROL_COMPONENT_ENABLE, 0xF);
*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
@@ -1617,7 +1708,8 @@
_SET(RB_MRTBLENDCONTROL_CLAMP_ENABLE, 1);
/* RB_MRT_CONTROL3 */
*cmds++ = _SET(RB_MRTCONTROL_READ_DEST_ENABLE, 1) |
- _SET(RB_MRTCONTROL_DITHER_MODE, RB_DITHER_DISABLE) |
+ _SET(RB_MRTCONTROL_ROP_CODE, 12) |
+ _SET(RB_MRTCONTROL_DITHER_MODE, RB_DITHER_ALWAYS) |
_SET(RB_MRTCONTROL_COMPONENT_ENABLE, 0xF);
*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
@@ -1636,7 +1728,7 @@
/* VFD_INDEX_MIN */
*cmds++ = 0x00000000;
/* VFD_INDEX_MAX */
- *cmds++ = 0xFFFFFFFF;
+ *cmds++ = 340;
/* VFD_INDEX_OFFSET */
*cmds++ = 0x00000000;
/* TPL1_TP_VS_TEX_OFFSET */
@@ -1645,7 +1737,7 @@
*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
*cmds++ = CP_REG(A3XX_VFD_VS_THREADING_THRESHOLD);
/* VFD_VS_THREADING_THRESHOLD */
- *cmds++ = _SET(VFD_THREADINGTHRESHOLD_RESERVED6, 12) |
+ *cmds++ = _SET(VFD_THREADINGTHRESHOLD_REGID_THRESHOLD, 15) |
_SET(VFD_THREADINGTHRESHOLD_REGID_VTXCNT, 252);
*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
@@ -1670,7 +1762,7 @@
*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
*cmds++ = CP_REG(A3XX_GRAS_SU_MODE_CONTROL);
/* GRAS_SU_MODE_CONTROL */
- *cmds++ = 0x00000000;
+ *cmds++ = _SET(GRAS_SU_CTRLMODE_LINEHALFWIDTH, 2);
*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
*cmds++ = CP_REG(A3XX_GRAS_SC_WINDOW_SCISSOR_TL);
@@ -1726,6 +1818,46 @@
PC_DRAW_TRIANGLES) |
_SET(PC_PRIM_VTX_CONTROL_PROVOKING_VTX_LAST, 1);
+
+ /* oxili_generate_context_roll_packets */
+ *cmds++ = cp_type0_packet(A3XX_SP_VS_CTRL_REG0, 1);
+ *cmds++ = 0x00000400;
+
+ *cmds++ = cp_type0_packet(A3XX_SP_FS_CTRL_REG0, 1);
+ *cmds++ = 0x00000400;
+
+ *cmds++ = cp_type0_packet(A3XX_SP_VS_PVT_MEM_SIZE_REG, 1);
+ *cmds++ = 0x00008000; /* SP_VS_MEM_SIZE_REG */
+
+ *cmds++ = cp_type0_packet(A3XX_SP_FS_PVT_MEM_SIZE_REG, 1);
+ *cmds++ = 0x00008000; /* SP_FS_MEM_SIZE_REG */
+
+ /* Clear cache invalidate bit when re-loading the shader control regs */
+ *cmds++ = cp_type0_packet(A3XX_SP_VS_CTRL_REG0, 1);
+ *cmds++ = _SET(SP_VSCTRLREG0_VSTHREADMODE, SP_MULTI) |
+ _SET(SP_VSCTRLREG0_VSINSTRBUFFERMODE, SP_BUFFER_MODE) |
+ _SET(SP_VSCTRLREG0_VSFULLREGFOOTPRINT, 2) |
+ _SET(SP_VSCTRLREG0_VSTHREADSIZE, SP_TWO_VTX_QUADS) |
+ _SET(SP_VSCTRLREG0_VSLENGTH, 1);
+
+ *cmds++ = cp_type0_packet(A3XX_SP_FS_CTRL_REG0, 1);
+ *cmds++ = _SET(SP_FSCTRLREG0_FSTHREADMODE, SP_MULTI) |
+ _SET(SP_FSCTRLREG0_FSINSTRBUFFERMODE, SP_BUFFER_MODE) |
+ _SET(SP_FSCTRLREG0_FSHALFREGFOOTPRINT, 1) |
+ _SET(SP_FSCTRLREG0_FSFULLREGFOOTPRINT, 1) |
+ _SET(SP_FSCTRLREG0_FSINOUTREGOVERLAP, 1) |
+ _SET(SP_FSCTRLREG0_FSTHREADSIZE, SP_FOUR_PIX_QUADS) |
+ _SET(SP_FSCTRLREG0_FSSUPERTHREADMODE, 1) |
+ _SET(SP_FSCTRLREG0_FSLENGTH, 2);
+
+ *cmds++ = cp_type0_packet(A3XX_SP_VS_PVT_MEM_SIZE_REG, 1);
+ *cmds++ = 0x00000000; /* SP_VS_MEM_SIZE_REG */
+
+ *cmds++ = cp_type0_packet(A3XX_SP_FS_PVT_MEM_SIZE_REG, 1);
+ *cmds++ = 0x00000000; /* SP_FS_MEM_SIZE_REG */
+
+ /* end oxili_generate_context_roll_packets */
+
*cmds++ = cp_type3_packet(CP_DRAW_INDX, 3);
*cmds++ = 0x00000000; /* Viz query info */
*cmds++ = BUILD_PC_DRAW_INITIATOR(PC_DI_PT_RECTLIST,
@@ -1740,6 +1872,7 @@
return cmds;
}
+
static void build_regrestore_cmds(struct adreno_device *adreno_dev,
struct adreno_context *drawctxt)
{
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index 7ffa83b..8a3345b 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -23,6 +23,8 @@
#include <linux/regulator/consumer.h>
#include <linux/mm.h>
+#include <mach/kgsl.h>
+
#define KGSL_NAME "kgsl"
/* The number of memstore arrays limits the number of contexts allowed.
diff --git a/drivers/hwmon/pm8xxx-adc-scale.c b/drivers/hwmon/pm8xxx-adc-scale.c
index fb2f1d5..4a1f58c 100644
--- a/drivers/hwmon/pm8xxx-adc-scale.c
+++ b/drivers/hwmon/pm8xxx-adc-scale.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, 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
@@ -112,127 +112,162 @@
};
static const struct pm8xxx_adc_map_pt adcmap_pa_therm[] = {
- {1677, -30},
- {1671, -29},
- {1663, -28},
- {1656, -27},
- {1648, -26},
- {1640, -25},
- {1632, -24},
- {1623, -23},
- {1615, -22},
- {1605, -21},
- {1596, -20},
- {1586, -19},
- {1576, -18},
- {1565, -17},
- {1554, -16},
- {1543, -15},
- {1531, -14},
- {1519, -13},
- {1507, -12},
- {1494, -11},
- {1482, -10},
- {1468, -9},
- {1455, -8},
- {1441, -7},
- {1427, -6},
- {1412, -5},
- {1398, -4},
- {1383, -3},
- {1367, -2},
- {1352, -1},
- {1336, 0},
- {1320, 1},
- {1304, 2},
- {1287, 3},
- {1271, 4},
- {1254, 5},
- {1237, 6},
- {1219, 7},
- {1202, 8},
- {1185, 9},
- {1167, 10},
- {1149, 11},
- {1131, 12},
- {1114, 13},
- {1096, 14},
- {1078, 15},
- {1060, 16},
- {1042, 17},
- {1024, 18},
- {1006, 19},
- {988, 20},
- {970, 21},
- {952, 22},
- {934, 23},
- {917, 24},
+ {1731, -30},
+ {1726, -29},
+ {1721, -28},
+ {1715, -27},
+ {1710, -26},
+ {1703, -25},
+ {1697, -24},
+ {1690, -23},
+ {1683, -22},
+ {1675, -21},
+ {1667, -20},
+ {1659, -19},
+ {1650, -18},
+ {1641, -17},
+ {1632, -16},
+ {1622, -15},
+ {1611, -14},
+ {1600, -13},
+ {1589, -12},
+ {1577, -11},
+ {1565, -10},
+ {1552, -9},
+ {1539, -8},
+ {1525, -7},
+ {1511, -6},
+ {1496, -5},
+ {1481, -4},
+ {1465, -3},
+ {1449, -2},
+ {1432, -1},
+ {1415, 0},
+ {1398, 1},
+ {1380, 2},
+ {1362, 3},
+ {1343, 4},
+ {1324, 5},
+ {1305, 6},
+ {1285, 7},
+ {1265, 8},
+ {1245, 9},
+ {1224, 10},
+ {1203, 11},
+ {1182, 12},
+ {1161, 13},
+ {1139, 14},
+ {1118, 15},
+ {1096, 16},
+ {1074, 17},
+ {1052, 18},
+ {1030, 19},
+ {1008, 20},
+ {986, 21},
+ {964, 22},
+ {943, 23},
+ {921, 24},
{899, 25},
- {882, 26},
- {865, 27},
- {848, 28},
- {831, 29},
- {814, 30},
- {797, 31},
- {781, 32},
- {764, 33},
- {748, 34},
- {732, 35},
- {717, 36},
- {701, 37},
- {686, 38},
- {671, 39},
- {656, 40},
- {642, 41},
- {627, 42},
- {613, 43},
- {599, 44},
- {586, 45},
- {572, 46},
- {559, 47},
- {546, 48},
- {534, 49},
- {522, 50},
- {509, 51},
- {498, 52},
- {486, 53},
- {475, 54},
- {463, 55},
- {452, 56},
- {442, 57},
- {431, 58},
- {421, 59},
- {411, 60},
- {401, 61},
- {392, 62},
- {383, 63},
- {374, 64},
- {365, 65},
- {356, 66},
- {348, 67},
- {339, 68},
- {331, 69},
- {323, 70},
- {316, 71},
- {308, 72},
- {301, 73},
- {294, 74},
- {287, 75},
- {280, 76},
- {273, 77},
- {267, 78},
- {261, 79},
- {255, 80},
- {249, 81},
- {243, 82},
- {237, 83},
- {232, 84},
- {226, 85},
- {221, 86},
- {216, 87},
- {211, 88},
- {206, 89},
- {201, 90}
+ {878, 26},
+ {857, 27},
+ {836, 28},
+ {815, 29},
+ {794, 30},
+ {774, 31},
+ {754, 32},
+ {734, 33},
+ {714, 34},
+ {695, 35},
+ {676, 36},
+ {657, 37},
+ {639, 38},
+ {621, 39},
+ {604, 40},
+ {586, 41},
+ {570, 42},
+ {553, 43},
+ {537, 44},
+ {521, 45},
+ {506, 46},
+ {491, 47},
+ {476, 48},
+ {462, 49},
+ {448, 50},
+ {435, 51},
+ {421, 52},
+ {409, 53},
+ {396, 54},
+ {384, 55},
+ {372, 56},
+ {361, 57},
+ {350, 58},
+ {339, 59},
+ {329, 60},
+ {318, 61},
+ {309, 62},
+ {299, 63},
+ {290, 64},
+ {281, 65},
+ {272, 66},
+ {264, 67},
+ {256, 68},
+ {248, 69},
+ {240, 70},
+ {233, 71},
+ {226, 72},
+ {219, 73},
+ {212, 74},
+ {206, 75},
+ {199, 76},
+ {193, 77},
+ {187, 78},
+ {182, 79},
+ {176, 80},
+ {171, 81},
+ {166, 82},
+ {161, 83},
+ {156, 84},
+ {151, 85},
+ {147, 86},
+ {142, 87},
+ {138, 88},
+ {134, 89},
+ {130, 90},
+ {126, 91},
+ {122, 92},
+ {119, 93},
+ {115, 94},
+ {112, 95},
+ {109, 96},
+ {106, 97},
+ {103, 98},
+ {100, 99},
+ {97, 100},
+ {94, 101},
+ {91, 102},
+ {89, 103},
+ {86, 104},
+ {84, 105},
+ {82, 106},
+ {79, 107},
+ {77, 108},
+ {75, 109},
+ {73, 110},
+ {71, 111},
+ {69, 112},
+ {67, 113},
+ {65, 114},
+ {64, 115},
+ {62, 116},
+ {60, 117},
+ {59, 118},
+ {57, 119},
+ {56, 120},
+ {54, 121},
+ {53, 122},
+ {51, 123},
+ {50, 124},
+ {49, 125}
};
static const struct pm8xxx_adc_map_pt adcmap_ntcg_104ef_104fb[] = {
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 23317d6..1c70527 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -100,6 +100,7 @@
#define MXT_PROCI_PALM_T41 41
#define MXT_PROCI_TOUCHSUPPRESSION_T42 42
#define MXT_PROCI_STYLUS_T47 47
+#define MXT_PROCI_ADAPTIVETHRESHOLD_T55 55
#define MXT_PROCI_SHIELDLESS_T56 56
#define MXT_PROCG_NOISESUPPRESSION_T48 48
#define MXT_SPT_COMMSCONFIG_T18 18
@@ -228,7 +229,7 @@
#define MXT_BACKUP_VALUE 0x55
#define MXT_BACKUP_TIME 25 /* msec */
#define MXT224_RESET_TIME 65 /* msec */
-#define MXT224E_RESET_TIME 22 /* msec */
+#define MXT224E_RESET_TIME 150 /* msec */
#define MXT1386_RESET_TIME 250 /* msec */
#define MXT_RESET_TIME 250 /* msec */
#define MXT_RESET_NOCHGREAD 400 /* msec */
@@ -386,6 +387,7 @@
case MXT_SPT_USERDATA_T38:
case MXT_SPT_DIGITIZER_T43:
case MXT_SPT_CTECONFIG_T46:
+ case MXT_PROCI_ADAPTIVETHRESHOLD_T55:
return true;
default:
return false;
@@ -419,6 +421,7 @@
case MXT_SPT_USERDATA_T38:
case MXT_SPT_DIGITIZER_T43:
case MXT_SPT_CTECONFIG_T46:
+ case MXT_PROCI_ADAPTIVETHRESHOLD_T55:
return true;
default:
return false;
@@ -732,6 +735,36 @@
return __mxt_read_reg(data->client, reg + offset, 1, val);
}
+static int mxt_get_object_address(struct device *dev, u8 type)
+{
+ struct mxt_data *data = dev_get_drvdata(dev);
+ u8 obj_num, obj_buf[MXT_OBJECT_SIZE];
+ u16 reg;
+ int i, error;
+
+ error = mxt_read_reg(data->client, MXT_OBJECT_NUM, &obj_num);
+
+ if (error) {
+ dev_err(dev, "reading number of objects failed\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < obj_num; i++) {
+ reg = MXT_OBJECT_START + MXT_OBJECT_SIZE * i;
+ error = mxt_read_object_table(data->client,
+ reg, obj_buf);
+ if (error)
+ return error;
+
+ if (obj_buf[0] == type)
+ return obj_buf[2] << 8 | obj_buf[1];
+ }
+ /* If control reaches here, i = obj_num and object not found */
+ dev_err(dev, "Requested object %d not found.\n", type);
+ return -EINVAL;
+
+}
+
static int mxt_write_object(struct mxt_data *data,
u8 type, u8 offset, u8 val)
{
@@ -1543,6 +1576,7 @@
switch (data->info.family_id) {
case MXT224_ID:
+ case MXT224E_ID:
max_frame_size = MXT_SINGLE_FW_MAX_FRAME_SIZE;
break;
case MXT1386_ID:
@@ -1681,11 +1715,12 @@
const char *buf, size_t count)
{
struct mxt_data *data = dev_get_drvdata(dev);
- int error;
+ int error, address;
const char *fw_name;
u8 bootldr_id;
u8 cfg_version[MXT_CFG_VERSION_LEN] = {0};
+
/* If fw_name is set, then the existing firmware has an upgrade */
if (!data->fw_name) {
/*
@@ -1735,6 +1770,16 @@
data->cfg_version_idx = 0;
data->update_cfg = false;
+ /* T38 object address might have changed, read it from
+ touch controller */
+ address = mxt_get_object_address(dev, MXT_SPT_USERDATA_T38);
+ if (address < 0) {
+ dev_err(dev, "T38 required for touch operation\n");
+ return -EINVAL;
+ }
+
+ data->t38_start_addr = address;
+
error = __mxt_write_reg(data->client, data->t38_start_addr,
sizeof(cfg_version), cfg_version);
if (error)
diff --git a/drivers/input/touchscreen/cyttsp-i2c-qc.c b/drivers/input/touchscreen/cyttsp-i2c-qc.c
index 5af4534..d8881a4 100644
--- a/drivers/input/touchscreen/cyttsp-i2c-qc.c
+++ b/drivers/input/touchscreen/cyttsp-i2c-qc.c
@@ -3,6 +3,7 @@
* drivers/input/touchscreen/cyttsp-i2c.c
*
* Copyright (C) 2009, 2010 Cypress Semiconductor, Inc.
+ * Copyright (c) 2012, 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
@@ -41,6 +42,7 @@
#include <linux/pm_runtime.h>
#include <linux/firmware.h>
#include <linux/mutex.h>
+#include <linux/completion.h>
#include <linux/regulator/consumer.h>
#ifdef CONFIG_HAS_EARLYSUSPEND
#include <linux/earlysuspend.h>
@@ -56,6 +58,30 @@
#define FW_FNAME_LEN 40
#define TTSP_BUFF_SIZE 50
+enum cyttsp_powerstate {
+ CY_IDLE = 0, /* IC cannot be reached */
+ CY_READY, /* pre-operational; ready to go to ACTIVE */
+ CY_ACTIVE, /* app is running, IC is scanning */
+ CY_LOW_PWR, /* not currently used */
+ CY_SLEEP, /* app is running, IC is idle */
+ CY_BL, /* bootloader is running */
+ CY_LDR, /* loader is running */
+ CY_SYSINFO, /* switching to sysinfo mode */
+ CY_INVALID, /* always last in the list */
+};
+static char *cyttsp_powerstate_string[] = {
+ /* Order must match enum cyttsp_powerstate above */
+ "IDLE",
+ "READY",
+ "ACTIVE",
+ "LOW_PWR",
+ "SLEEP",
+ "BOOTLOADER",
+ "LOADER",
+ "SYSINFO",
+ "INVALID",
+};
+
/* CY TTSP I2C Driver private data */
struct cyttsp {
struct i2c_client *client;
@@ -65,12 +91,15 @@
char phys[32];
struct cyttsp_platform_data *platform_data;
u8 num_prv_st_tch;
+ u8 power_settings[3];
u16 fw_start_addr;
+ enum cyttsp_powerstate power_state;
u16 act_trk[CY_NUM_TRK_ID];
u16 prv_st_tch[CY_NUM_ST_TCH_ID];
u16 prv_mt_tch[CY_NUM_MT_TCH_ID];
u16 prv_mt_pos[CY_NUM_TRK_ID][2];
atomic_t irq_enabled;
+ struct completion si_int_running;
bool cyttsp_update_fw;
bool cyttsp_fwloader_mode;
bool is_suspended;
@@ -158,6 +187,67 @@
atomic_read(&ts->irq_enabled));
}
+static int cyttsp_hndshk(struct cyttsp *ts, u8 hst_mode)
+{
+ int retval = 0;
+ u8 mode = 0;
+
+ mode = hst_mode & CY_HNDSHK_BIT ?
+ hst_mode & ~CY_HNDSHK_BIT :
+ hst_mode | CY_HNDSHK_BIT;
+
+ retval = i2c_smbus_write_i2c_block_data(ts->client,
+ CY_REG_BASE, sizeof(mode), &mode);
+
+ if (retval < 0) {
+ pr_err("%s: bus write fail on handshake r=%d\n",
+ __func__, retval);
+ }
+
+ return retval;
+}
+
+static void cyttsp_change_state(struct cyttsp *ts,
+ enum cyttsp_powerstate new_state)
+{
+ ts->power_state = new_state;
+ pr_info("%s: %s\n", __func__,
+ (ts->power_state < CY_INVALID) ?
+ cyttsp_powerstate_string[ts->power_state] :
+ "INVALID");
+}
+
+static int cyttsp_wait_ready(struct cyttsp *ts, struct completion *complete,
+ u8 *cmd, size_t cmd_size, unsigned long timeout_ms)
+{
+ unsigned long timeout = 0;
+ unsigned long uretval = 0;
+ int retval = 0;
+
+ timeout = msecs_to_jiffies(timeout_ms);
+ INIT_COMPLETION(*complete);
+ if ((cmd != NULL) && (cmd_size != 0)) {
+ retval = i2c_smbus_write_i2c_block_data(ts->client,
+ CY_REG_BASE, cmd_size, cmd);
+ if (retval < 0) {
+ pr_err("%s: bus write fail switch mode r=%d\n",
+ __func__, retval);
+ cyttsp_change_state(ts, CY_IDLE);
+ goto _cyttsp_wait_ready_exit;
+ }
+ }
+ uretval = wait_for_completion_interruptible_timeout(complete, timeout);
+ if (uretval == 0) {
+ pr_err("%s: Switch Mode Timeout waiting " \
+ "for ready interrupt - try reading regs\n", __func__);
+ /* continue anyway */
+ retval = 0;
+ }
+
+_cyttsp_wait_ready_exit:
+ return retval;
+}
+
static ssize_t cyttsp_irq_enable(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
@@ -329,33 +419,41 @@
} while (tries++ < 10 && (retval < 0));
}
-static void cyttsp_set_sysinfo_mode(struct cyttsp *ts)
+static int cyttsp_set_sysinfo_mode(struct cyttsp *ts, u8 sleep)
{
- int retval, tries = 0;
- u8 host_reg = CY_SYSINFO_MODE;
+ int retval;
+ u8 mode = CY_SYSINFO_MODE + sleep;
- do {
- retval = i2c_smbus_write_i2c_block_data(ts->client,
- CY_REG_BASE, sizeof(host_reg), &host_reg);
- if (retval < 0)
- msleep(20);
- } while (tries++ < 10 && (retval < 0));
+ cyttsp_change_state(ts, CY_SYSINFO);
- /* wait for TTSP Device to complete switch to SysInfo mode */
- if (!(retval < 0)) {
- retval = i2c_smbus_read_i2c_block_data(ts->client,
- CY_REG_BASE,
- sizeof(struct cyttsp_sysinfo_data_t),
- (u8 *)&g_sysinfo_data);
- } else
- pr_err("%s: failed\n", __func__);
+ retval = cyttsp_wait_ready(ts, &ts->si_int_running,
+ &mode, sizeof(mode), CY_HALF_SEC_TMO_MS);
+
+ if (retval < 0) {
+ pr_err("%s: fail wait ready r=%d\n", __func__, retval);
+ goto cyttsp_set_sysinfo_mode_exit;
+ }
+
+ if (GET_HSTMODE(g_sysinfo_data.hst_mode) !=
+ GET_HSTMODE(CY_SYSINFO_MODE)) {
+ pr_err("%s: Fail enter Sysinfo mode hst_mode=0x%02X\n",
+ __func__, g_sysinfo_data.hst_mode);
+ retval = -EIO;
+ } else {
+ cyttsp_debug("%s: Enter Sysinfo mode hst_mode=0x%02X\n",
+ __func__, g_sysinfo_data.hst_mode);
+ }
+
+cyttsp_set_sysinfo_mode_exit:
+ return retval;
}
-static void cyttsp_set_opmode(struct cyttsp *ts)
+static void cyttsp_set_opmode(struct cyttsp *ts, u8 sleep)
{
int retval, tries = 0;
- u8 host_reg = CY_OP_MODE;
+ u8 host_reg = CY_OP_MODE + sleep;
+ cyttsp_change_state(ts, CY_ACTIVE);
do {
retval = i2c_smbus_write_i2c_block_data(ts->client,
CY_REG_BASE, sizeof(host_reg), &host_reg);
@@ -364,6 +462,34 @@
} while (tries++ < 10 && (retval < 0));
}
+static int cyttsp_set_lp_mode(struct cyttsp *ts)
+{
+ int retval = 0, tries = 0;
+
+ retval = cyttsp_set_sysinfo_mode(ts, CY_LOW_PWR_MODE);
+ if (retval < 0) {
+ pr_err("%s: failed to enter sysinfo mode, retval =%x\n",
+ __func__, retval);
+ goto exit_low_power_mode;
+ }
+ do {
+ retval = i2c_smbus_write_i2c_block_data(
+ ts->client,
+ CY_REG_ACT_INTRVL,
+ sizeof(ts->power_settings), ts->power_settings);
+ if (retval < 0)
+ msleep(20);
+ } while ((retval < 0) && (tries++ < 5));
+ if (retval < 0)
+ pr_err("%s: failed to write power_settings, retval =%x\n",
+ __func__, retval);
+ msleep(CY_DLY_SYSINFO);
+exit_low_power_mode:
+ cyttsp_set_opmode(ts, CY_LOW_PWR_MODE);
+ return retval;
+
+}
+
static int str2uc(char *str, u8 *val)
{
char substr[3];
@@ -740,21 +866,19 @@
pr_info("%s: firmware upgrade success\n", __func__);
}
- /* enter bootloader idle mode */
- cyttsp_soft_reset(ts);
- /* exit bootloader mode */
- cyttsp_exit_bl_mode(ts);
- msleep(100);
- /* set sysinfo details */
- cyttsp_set_sysinfo_mode(ts);
- /* enter application mode */
- cyttsp_set_opmode(ts);
-
/* enable interrupts */
if (ts->client->irq == 0)
mod_timer(&ts->timer, jiffies + TOUCHSCREEN_TIMEOUT);
else
enable_irq(ts->client->irq);
+
+ /* enter bootloader idle mode */
+ cyttsp_soft_reset(ts);
+ /* exit bootloader mode */
+ cyttsp_exit_bl_mode(ts);
+ msleep(100);
+ /* set low power mode and enter application mode*/
+ cyttsp_set_lp_mode(ts);
}
static void cyttspfw_upgrade_start(struct cyttsp *ts, const u8 *data,
@@ -958,15 +1082,14 @@
/* compare own irq counter with the device irq counter */
if (ts->client->irq) {
- u8 host_reg;
u8 cur_cnt;
if (ts->platform_data->use_hndshk) {
-
- host_reg = g_xy_data.hst_mode & CY_HNDSHK_BIT ?
- g_xy_data.hst_mode & ~CY_HNDSHK_BIT :
- g_xy_data.hst_mode | CY_HNDSHK_BIT;
- retval = i2c_smbus_write_i2c_block_data(ts->client,
- CY_REG_BASE, sizeof(host_reg), &host_reg);
+ retval = cyttsp_hndshk(ts, g_xy_data.hst_mode);
+ if (retval < 0) {
+ pr_err("%s: Fail write handshake r=%d\n",
+ __func__, retval);
+ retval = 0;
+ }
}
cur_cnt = g_xy_data.tt_undef[CY_IRQ_CNT_REG];
irq_cnt_total++;
@@ -1031,6 +1154,7 @@
tries++ < 100);
cyttsp_putbl(ts, 2, true, false, false);
}
+ cyttsp_set_lp_mode(ts);
goto exit_xy_handler;
} else {
cur_tch = GET_NUM_TOUCHES(g_xy_data.tt_stat);
@@ -1891,10 +2015,40 @@
static irqreturn_t cyttsp_irq(int irq, void *handle)
{
struct cyttsp *ts = (struct cyttsp *) handle;
+ int retval = 0;
cyttsp_xdebug("%s: Got IRQ\n", CY_I2C_NAME);
-
- cyttsp_xy_handler(ts);
+ switch (ts->power_state) {
+ case CY_SYSINFO:
+ retval = i2c_smbus_read_i2c_block_data(ts->client,
+ CY_REG_BASE,
+ sizeof(struct cyttsp_sysinfo_data_t),
+ (u8 *)&g_sysinfo_data);
+ if (retval < 0) {
+ pr_err("%s: Fail read status and version regs r=%d\n",
+ __func__, retval);
+ goto cyttsp_irq_sysinfo_exit;
+ }
+ if (ts->platform_data->use_hndshk) {
+ retval = cyttsp_hndshk(ts, g_sysinfo_data.hst_mode);
+ if (retval < 0) {
+ pr_err("%s: Fail write handshake r=%d\n",
+ __func__, retval);
+ retval = 0;
+ }
+ }
+ udelay(100); /* irq pulse: sysinfo mode switch=50us */
+ complete(&ts->si_int_running);
+cyttsp_irq_sysinfo_exit:
+ break;
+ case CY_ACTIVE:
+ cyttsp_xy_handler(ts);
+ break;
+ default:
+ pr_err("%s: Unexpected power state with interrupt ps=%d\n",
+ __func__, ts->power_state);
+ break;
+ }
return IRQ_HANDLED;
}
@@ -2260,102 +2414,6 @@
}
bypass:
- /* switch to System Information mode to read versions
- * and set interval registers */
- if (!(retval < CY_OK)) {
- cyttsp_debug("switch to sysinfo mode \n");
- host_reg = CY_SYSINFO_MODE;
- retval = i2c_smbus_write_i2c_block_data(ts->client,
- CY_REG_BASE, sizeof(host_reg), &host_reg);
- /* wait for TTSP Device to complete switch to SysInfo mode */
- msleep(100);
- if (!(retval < CY_OK)) {
- retval = i2c_smbus_read_i2c_block_data(ts->client,
- CY_REG_BASE,
- sizeof(struct cyttsp_sysinfo_data_t),
- (u8 *)&g_sysinfo_data);
- cyttsp_debug("SI2: hst_mode=0x%02X mfg_cmd=0x%02X mfg_stat=0x%02X\n", \
- g_sysinfo_data.hst_mode, \
- g_sysinfo_data.mfg_cmd, \
- g_sysinfo_data.mfg_stat);
- cyttsp_debug("SI2: bl_ver=0x%02X%02X\n", \
- g_sysinfo_data.bl_verh, \
- g_sysinfo_data.bl_verl);
- cyttsp_debug("SI2: sysinfo act_int=0x%02X tch_tmout=0x%02X lp_int=0x%02X\n", \
- g_sysinfo_data.act_intrvl, \
- g_sysinfo_data.tch_tmout, \
- g_sysinfo_data.lp_intrvl);
- cyttsp_info("SI%d: tver=%02X%02X a_id=%02X%02X aver=%02X%02X\n", \
- 102, \
- g_sysinfo_data.tts_verh, \
- g_sysinfo_data.tts_verl, \
- g_sysinfo_data.app_idh, \
- g_sysinfo_data.app_idl, \
- g_sysinfo_data.app_verh, \
- g_sysinfo_data.app_verl);
- cyttsp_info("SI%d: c_id=%02X%02X%02X\n", \
- 103, \
- g_sysinfo_data.cid[0], \
- g_sysinfo_data.cid[1], \
- g_sysinfo_data.cid[2]);
- if (!(retval < CY_OK) &&
- (CY_DIFF(ts->platform_data->act_intrvl,
- CY_ACT_INTRVL_DFLT) ||
- CY_DIFF(ts->platform_data->tch_tmout,
- CY_TCH_TMOUT_DFLT) ||
- CY_DIFF(ts->platform_data->lp_intrvl,
- CY_LP_INTRVL_DFLT))) {
- if (!(retval < CY_OK)) {
- u8 intrvl_ray[sizeof(ts->platform_data->act_intrvl) +
- sizeof(ts->platform_data->tch_tmout) +
- sizeof(ts->platform_data->lp_intrvl)];
- u8 i = 0;
-
- intrvl_ray[i++] =
- ts->platform_data->act_intrvl;
- intrvl_ray[i++] =
- ts->platform_data->tch_tmout;
- intrvl_ray[i++] =
- ts->platform_data->lp_intrvl;
-
- cyttsp_debug("SI2: platinfo act_intrvl=0x%02X tch_tmout=0x%02X lp_intrvl=0x%02X\n", \
- ts->platform_data->act_intrvl, \
- ts->platform_data->tch_tmout, \
- ts->platform_data->lp_intrvl);
- /* set intrvl registers */
- retval = i2c_smbus_write_i2c_block_data(
- ts->client,
- CY_REG_ACT_INTRVL,
- sizeof(intrvl_ray), intrvl_ray);
- msleep(CY_DLY_SYSINFO);
- }
- }
- }
- /* switch back to Operational mode */
- cyttsp_debug("switch back to operational mode \n");
- if (!(retval < CY_OK)) {
- host_reg = CY_OP_MODE/* + CY_LOW_PWR_MODE*/;
- retval = i2c_smbus_write_i2c_block_data(ts->client,
- CY_REG_BASE,
- sizeof(host_reg), &host_reg);
- /* wait for TTSP Device to complete
- * switch to Operational mode */
- msleep(100);
- }
- }
- /* init gesture setup;
- * this is required even if not using gestures
- * in order to set the active distance */
- if (!(retval < CY_OK)) {
- u8 gesture_setup;
- cyttsp_debug("init gesture setup \n");
- gesture_setup = ts->platform_data->gest_set;
- retval = i2c_smbus_write_i2c_block_data(ts->client,
- CY_REG_GEST_SET,
- sizeof(gesture_setup), &gesture_setup);
- msleep(CY_DLY_DFLT);
- }
-
if (!(retval < CY_OK))
ts->platform_data->power_state = CY_ACTIVE_STATE;
else
@@ -2454,6 +2512,91 @@
return rc;
}
+static void sysinfo_debug_msg(struct cyttsp *ts)
+{
+ cyttsp_debug("SI2: hst_mode=0x%02X mfg_cmd=0x%02X " \
+ "mfg_stat=0x%02X\n", \
+ g_sysinfo_data.hst_mode, \
+ g_sysinfo_data.mfg_cmd, \
+ g_sysinfo_data.mfg_stat);
+ cyttsp_debug("SI2: bl_ver=0x%02X%02X\n", \
+ g_sysinfo_data.bl_verh, \
+ g_sysinfo_data.bl_verl);
+ cyttsp_debug("SI2: sysinfo act_int=0x%02X " \
+ "tch_tmout=0x%02X lp_int=0x%02X\n", \
+ g_sysinfo_data.act_intrvl, \
+ g_sysinfo_data.tch_tmout, \
+ g_sysinfo_data.lp_intrvl);
+ cyttsp_info("SI%d: tver=%02X%02X a_id=%02X%02X " \
+ "aver=%02X%02X\n", \
+ 102, \
+ g_sysinfo_data.tts_verh, \
+ g_sysinfo_data.tts_verl, \
+ g_sysinfo_data.app_idh, \
+ g_sysinfo_data.app_idl, \
+ g_sysinfo_data.app_verh, \
+ g_sysinfo_data.app_verl);
+ cyttsp_info("SI%d: c_id=%02X%02X%02X\n", \
+ 103, \
+ g_sysinfo_data.cid[0], \
+ g_sysinfo_data.cid[1], \
+ g_sysinfo_data.cid[2]);
+ cyttsp_debug("SI2: platinfo " \
+ "act_intrvl=0x%02X tch_tmout=0x%02X " \
+ "lp_intrvl=0x%02X\n", \
+ ts->platform_data->act_intrvl, \
+ ts->platform_data->tch_tmout, \
+ ts->platform_data->lp_intrvl);
+}
+
+static int set_bypass_modes(struct cyttsp *ts)
+{
+ int retval = 0, tries = 0;
+
+ /* switch to System Information mode to read versions
+ * and set interval registers */
+ retval = cyttsp_set_sysinfo_mode(ts, CY_LOW_PWR_MODE);
+ if (!(retval < CY_OK)) {
+ retval = i2c_smbus_read_i2c_block_data(ts->client,
+ CY_REG_BASE,
+ sizeof(struct cyttsp_sysinfo_data_t),
+ (u8 *)&g_sysinfo_data);
+ sysinfo_debug_msg(ts);
+ /* set power settings registers */
+ do {
+ retval = i2c_smbus_write_i2c_block_data(ts->client,
+ CY_REG_ACT_INTRVL, sizeof(ts->power_settings),
+ ts->power_settings);
+ if (retval < 0)
+ msleep(20);
+ } while ((retval < 0) && (tries++ < 5));
+ if (retval < 0)
+ pr_err("%s: failed to write power_settings, " \
+ "retval =%x\n", __func__, retval);
+ }
+ /* switch back to Operational mode */
+ cyttsp_debug("switch back to operational mode\n");
+ if (!(retval < CY_OK)) {
+ cyttsp_set_opmode(ts, CY_LOW_PWR_MODE);
+ /* wait for TTSP Device to complete
+ * switch to Operational mode */
+ msleep(100);
+ }
+ /* init gesture setup;
+ * this is required even if not using gestures
+ * in order to set the active distance */
+ if (!(retval < CY_OK)) {
+ u8 gesture_setup;
+ cyttsp_debug("init gesture setup\n");
+ gesture_setup = ts->platform_data->gest_set;
+ retval = i2c_smbus_write_i2c_block_data(ts->client,
+ CY_REG_GEST_SET,
+ sizeof(gesture_setup), &gesture_setup);
+ msleep(CY_DLY_DFLT);
+ }
+ return retval;
+}
+
/* cyttsp_initialize: Driver Initialization. This function takes
* care of the following tasks:
* 1. Create and register an input device with input layer
@@ -2491,6 +2634,21 @@
input_device->phys = ts->phys;
input_device->dev.parent = &client->dev;
+ ts->power_state = CY_ACTIVE;
+
+ if (ts->platform_data->act_intrvl)
+ ts->power_settings[0] = ts->platform_data->act_intrvl;
+ else
+ ts->power_settings[0] = CY_ACT_INTRVL_DFLT;
+ if (ts->platform_data->tch_tmout)
+ ts->power_settings[1] = ts->platform_data->tch_tmout;
+ else
+ ts->power_settings[1] = CY_TCH_TMOUT_DFLT;
+ if (ts->platform_data->lp_intrvl)
+ ts->power_settings[2] = ts->platform_data->lp_intrvl;
+ else
+ ts->power_settings[2] = CY_LP_INTRVL_DFLT;
+
/* init the touch structures */
ts->num_prv_st_tch = CY_NTCH;
for (id = 0; id < CY_NUM_TRK_ID; id++) {
@@ -2712,6 +2870,7 @@
goto error_rm_dev_file_fupdate_fw;
}
+ set_bypass_modes(ts);
cyttsp_info("%s: Successful registration\n", CY_I2C_NAME);
goto success;
@@ -2799,6 +2958,8 @@
i2c_set_clientdata(client, ts);
+ init_completion(&ts->si_int_running);
+
error = cyttsp_initialize(client, ts);
if (error) {
cyttsp_xdebug1("err cyttsp_initialize\n");
@@ -2821,6 +2982,7 @@
#endif /* CONFIG_HAS_EARLYSUSPEND */
device_init_wakeup(&client->dev, ts->platform_data->wakeup);
mutex_init(&ts->mutex);
+ retval = cyttsp_set_lp_mode(ts);
cyttsp_info("Start Probe %s\n", \
(retval < CY_OK) ? "FAIL" : "PASS");
@@ -2957,7 +3119,7 @@
cyttsp_debug("Wake Up %s\n", \
(retval < CY_OK) ? "FAIL" : "PASS");
- return retval;
+ return cyttsp_set_lp_mode(ts);
}
/* Function to manage low power suspend */
diff --git a/drivers/iommu/msm_iommu-v2.c b/drivers/iommu/msm_iommu-v2.c
index 6e62e60..26e967d 100644
--- a/drivers/iommu/msm_iommu-v2.c
+++ b/drivers/iommu/msm_iommu-v2.c
@@ -128,7 +128,7 @@
return ret;
}
-static void __reset_iommu(void __iomem *base)
+static void __reset_iommu(void __iomem *base, int smt_size)
{
int i;
@@ -143,15 +143,15 @@
SET_SCR1(base, 0);
SET_SSDR_N(base, 0, 0);
- for (i = 0; i < MAX_NUM_SMR; i++)
+ for (i = 0; i < smt_size; i++)
SET_SMR_VALID(base, i, 0);
mb();
}
-static void __program_iommu(void __iomem *base)
+static void __program_iommu(void __iomem *base, int smt_size)
{
- __reset_iommu(base);
+ __reset_iommu(base, smt_size);
SET_CR0_SMCFCFG(base, 1);
SET_CR0_USFCFG(base, 1);
@@ -182,7 +182,7 @@
static void __program_context(void __iomem *base, int ctx, int ncb,
phys_addr_t pgtable, int redirect,
- u32 *sids, int len)
+ u32 *sids, int len, int smt_size)
{
unsigned int prrr, nmrr;
unsigned int pn;
@@ -227,10 +227,10 @@
/* Program the M2V tables for this context */
for (i = 0; i < len / sizeof(*sids); i++) {
- for (; num < MAX_NUM_SMR; num++)
+ for (; num < smt_size; num++)
if (GET_SMR_VALID(base, num) == 0)
break;
- BUG_ON(num >= MAX_NUM_SMR);
+ BUG_ON(num >= smt_size);
SET_SMR_VALID(base, num, 1);
SET_SMR_MASK(base, num, 0);
@@ -346,8 +346,7 @@
struct msm_iommu_drvdata *iommu_drvdata;
struct msm_iommu_ctx_drvdata *ctx_drvdata;
struct msm_iommu_ctx_drvdata *tmp_drvdata;
- u32 sids[MAX_NUM_SMR];
- int len = 0, ret;
+ int ret;
mutex_lock(&msm_iommu_lock);
@@ -375,14 +374,6 @@
goto fail;
}
- of_get_property(dev->of_node, "qcom,iommu-ctx-sids", &len);
- BUG_ON(len >= sizeof(sids));
- if (of_property_read_u32_array(dev->of_node, "qcom,iommu-ctx-sids",
- sids, len / sizeof(*sids))) {
- ret = -EINVAL;
- goto fail;
- }
-
ret = regulator_enable(iommu_drvdata->gdsc);
if (ret)
goto fail;
@@ -394,11 +385,12 @@
}
if (!msm_iommu_ctx_attached(dev->parent))
- __program_iommu(iommu_drvdata->base);
+ __program_iommu(iommu_drvdata->base, iommu_drvdata->nsmr);
__program_context(iommu_drvdata->base, ctx_drvdata->num,
iommu_drvdata->ncb, __pa(priv->pt.fl_table),
- priv->pt.redirect, sids, len);
+ priv->pt.redirect, ctx_drvdata->sids, ctx_drvdata->nsid,
+ iommu_drvdata->nsmr);
__disable_clocks(iommu_drvdata);
list_add(&(ctx_drvdata->attached_elm), &priv->list_attached);
diff --git a/drivers/iommu/msm_iommu_dev-v2.c b/drivers/iommu/msm_iommu_dev-v2.c
index 87e1a46..d3a088a 100644
--- a/drivers/iommu/msm_iommu_dev-v2.c
+++ b/drivers/iommu/msm_iommu_dev-v2.c
@@ -33,12 +33,25 @@
struct msm_iommu_drvdata *drvdata)
{
struct device_node *child;
- int ret;
+ int ret = 0;
+ u32 nsmr;
ret = device_move(&pdev->dev, &msm_iommu_root_dev->dev, DPM_ORDER_NONE);
if (ret)
- return ret;
+ goto fail;
+ ret = of_property_read_u32(pdev->dev.of_node, "qcom,iommu-smt-size",
+ &nsmr);
+ if (ret)
+ goto fail;
+
+ if (nsmr > MAX_NUM_SMR) {
+ pr_err("Invalid SMT size: %d\n", nsmr);
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ drvdata->nsmr = nsmr;
for_each_child_of_node(pdev->dev.of_node, child) {
drvdata->ncb++;
if (!of_platform_device_create(child, NULL, &pdev->dev))
@@ -46,7 +59,8 @@
}
drvdata->name = dev_name(&pdev->dev);
- return 0;
+fail:
+ return ret;
}
static atomic_t msm_iommu_next_id = ATOMIC_INIT(-1);
@@ -149,6 +163,7 @@
{
struct resource *r, rp;
int irq, ret;
+ u32 nsid;
irq = platform_get_irq(pdev, 0);
if (irq > 0) {
@@ -181,6 +196,19 @@
&ctx_drvdata->name))
ctx_drvdata->name = dev_name(&pdev->dev);
+ if (!of_get_property(pdev->dev.of_node, "qcom,iommu-ctx-sids", &nsid))
+ return -EINVAL;
+
+ if (nsid >= sizeof(ctx_drvdata->sids))
+ return -EINVAL;
+
+ if (of_property_read_u32_array(pdev->dev.of_node, "qcom,iommu-ctx-sids",
+ ctx_drvdata->sids,
+ nsid / sizeof(*ctx_drvdata->sids))) {
+ return -EINVAL;
+ }
+ ctx_drvdata->nsid = nsid;
+
return 0;
}
diff --git a/drivers/media/video/msm/Makefile b/drivers/media/video/msm/Makefile
index 5703d88..eb45271 100644
--- a/drivers/media/video/msm/Makefile
+++ b/drivers/media/video/msm/Makefile
@@ -12,10 +12,11 @@
EXTRA_CFLAGS += -Idrivers/media/video/msm/actuators
EXTRA_CFLAGS += -Idrivers/media/video/msm/server
obj-$(CONFIG_MSM_CAMERA) += msm_isp.o msm.o msm_mem.o msm_mctl.o msm_mctl_buf.o msm_mctl_pp.o msm_vfe_stats_buf.o
- obj-$(CONFIG_MSM_CAMERA) += server/ eeprom/ sensors/ actuators/ csi/
+ obj-$(CONFIG_MSM_CAMERA) += server/
+ obj-$(CONFIG_MSM_CAM_IRQ_ROUTER) += msm_camirq_router.o
+ obj-$(CONFIG_MSM_CAMERA) += eeprom/ sensors/ actuators/ csi/
obj-$(CONFIG_MSM_CPP) += cpp/
obj-$(CONFIG_MSM_CAMERA) += msm_gesture.o
- obj-$(CONFIG_MSM_CAM_IRQ_ROUTER) += msm_camirq_router.o
else
obj-$(CONFIG_MSM_CAMERA) += msm_camera.o
endif
diff --git a/drivers/media/video/msm/io/msm_camera_i2c.h b/drivers/media/video/msm/io/msm_camera_i2c.h
index a0cdd77..188a176 100644
--- a/drivers/media/video/msm/io/msm_camera_i2c.h
+++ b/drivers/media/video/msm/io/msm_camera_i2c.h
@@ -53,9 +53,9 @@
struct msm_camera_i2c_reg_conf {
uint16_t reg_addr;
uint16_t reg_data;
- int16_t mask;
enum msm_camera_i2c_data_type dt;
enum msm_camera_i2c_cmd_type cmd_type;
+ int16_t mask;
};
struct msm_camera_i2c_reg_tbl {
diff --git a/drivers/media/video/msm/msm_camirq_router.c b/drivers/media/video/msm/msm_camirq_router.c
index 52dd175..25a561f 100644
--- a/drivers/media/video/msm/msm_camirq_router.c
+++ b/drivers/media/video/msm/msm_camirq_router.c
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/interrupt.h>
+#include <linux/of.h>
#include <mach/irqs.h>
#include <media/msm_isp.h>
#include <media/v4l2-device.h>
@@ -207,6 +208,10 @@
v4l2_set_subdevdata(&irqrouter_ctrl->subdev, irqrouter_ctrl);
irqrouter_ctrl->pdev = pdev;
+ if (pdev->dev.of_node)
+ of_property_read_u32((&pdev->dev)->of_node,
+ "cell-index", &pdev->id);
+
msm_irqrouter_send_default_irqmap(irqrouter_ctrl);
media_entity_init(&irqrouter_ctrl->subdev.entity, 0, NULL, 0);
@@ -237,16 +242,27 @@
static int __exit irqrouter_exit(struct platform_device *pdev)
{
+ struct v4l2_subdev *subdev = dev_get_drvdata(&pdev->dev);
+ struct irqrouter_ctrl_type *irqrouter_ctrl =
+ v4l2_get_subdevdata(subdev);
kfree(irqrouter_ctrl);
return 0;
}
+static const struct of_device_id msm_irqrouter_dt_match[] = {
+ {.compatible = "qcom,irqrouter"},
+ {}
+};
+
+MODULE_DEVICE_TABLE(of, msm_irqrouter_dt_match);
+
static struct platform_driver msm_irqrouter_driver = {
.probe = irqrouter_probe,
.remove = irqrouter_exit,
.driver = {
.name = MSM_IRQ_ROUTER_DRV_NAME,
.owner = THIS_MODULE,
+ .of_match_table = msm_irqrouter_dt_match,
},
};
diff --git a/drivers/media/video/msm/msm_vfe31_v4l2.c b/drivers/media/video/msm/msm_vfe31_v4l2.c
index 2331fcc..b520a92 100644
--- a/drivers/media/video/msm/msm_vfe31_v4l2.c
+++ b/drivers/media/video/msm/msm_vfe31_v4l2.c
@@ -3138,18 +3138,6 @@
CDBG("%s: droppedStatsFrameCount = %d", __func__,
vfe31_ctrl->csStatsControl.droppedStatsFrameCount);
}
- if (!(vfe31_ctrl->csStatsControl.ackPending)) {
- vfe31_ctrl->csStatsControl.bufToRender =
- vfe31_process_stats_irq_common(STATS_CS_NUM,
- vfe31_ctrl->csStatsControl.nextFrameAddrBuf);
- vfe_send_stats_msg(
- vfe31_ctrl->csStatsControl.bufToRender,
- STATS_CS_NUM);
- } else {
- vfe31_ctrl->csStatsControl.droppedStatsFrameCount++;
- CDBG("%s: droppedStatsFrameCount = %d", __func__,
- vfe31_ctrl->csStatsControl.droppedStatsFrameCount);
- }
}
static void vfe31_process_stats(uint32_t status_bits)
@@ -3882,6 +3870,9 @@
spin_lock_init(&vfe31_ctrl->sd_notify_lock);
INIT_LIST_HEAD(&vfe31_ctrl->tasklet_q);
+ memset(&vfe31_ctrl->stats_ctrl, 0, sizeof(struct msm_stats_bufq_ctrl));
+ memset(&vfe31_ctrl->stats_ops, 0, sizeof(struct msm_stats_ops));
+
vfe31_ctrl->update_linear = false;
vfe31_ctrl->update_rolloff = false;
vfe31_ctrl->update_la = false;
diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c
index 621a016..38954f8 100644
--- a/drivers/media/video/msm/msm_vfe32.c
+++ b/drivers/media/video/msm/msm_vfe32.c
@@ -4716,6 +4716,9 @@
vfe32_ctrl->update_gamma = false;
vfe32_ctrl->hfr_mode = HFR_MODE_OFF;
+ memset(&vfe32_ctrl->stats_ctrl, 0, sizeof(struct msm_stats_bufq_ctrl));
+ memset(&vfe32_ctrl->stats_ops, 0, sizeof(struct msm_stats_ops));
+
return rc;
}
@@ -5294,6 +5297,13 @@
axi_ctrl->fs_vfe = NULL;
}
+ /* Register subdev node before requesting irq since
+ * irq_num is needed by msm_cam_server */
+ sd_info.sdev_type = VFE_DEV;
+ sd_info.sd_index = 0;
+ sd_info.irq_num = axi_ctrl->vfeirq->start;
+ msm_cam_register_subdev_node(&vfe32_ctrl->subdev, &sd_info);
+
/* Request for this device irq from the camera server. If the
* IRQ Router is present on this target, the interrupt will be
* handled by the camera server and the interrupt service
@@ -5333,10 +5343,6 @@
axi32_do_tasklet, (unsigned long)axi_ctrl);
vfe32_ctrl->pdev = pdev;
- sd_info.sdev_type = VFE_DEV;
- sd_info.sd_index = 0;
- sd_info.irq_num = axi_ctrl->vfeirq->start;
- msm_cam_register_subdev_node(&vfe32_ctrl->subdev, &sd_info);
return 0;
vfe32_no_resource:
diff --git a/drivers/media/video/msm/msm_vfe7x27a_v4l2.c b/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
index 5fef610..96047d5 100644
--- a/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
+++ b/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
@@ -1970,6 +1970,8 @@
stopevent.state = 0;
vfe2x_ctrl->vfe_started = 0;
+ memset(&vfe2x_ctrl->stats_ctrl, 0, sizeof(struct msm_stats_bufq_ctrl));
+ memset(&vfe2x_ctrl->stats_ops, 0, sizeof(struct msm_stats_ops));
CDBG("msm_cam_clk_enable: enable vfe_clk\n");
rc = msm_cam_clk_enable(&vfe2x_ctrl->pdev->dev, vfe2x_clk_info,
diff --git a/drivers/media/video/msm/sensors/ov7692_v4l2.c b/drivers/media/video/msm/sensors/ov7692_v4l2.c
index 6fc1da1..71d436e 100644
--- a/drivers/media/video/msm/sensors/ov7692_v4l2.c
+++ b/drivers/media/video/msm/sensors/ov7692_v4l2.c
@@ -173,24 +173,33 @@
};
static struct msm_camera_i2c_reg_conf ov7692_saturation[][4] = {
- {{0x81, 0x33, 0xCC}, {0xd8, 0x00, 0x00}, {0xd9, 0x00, 0x00},
- {0xd2, 0x02, 0x00},}, /* SATURATION LEVEL0*/
- {{0x81, 0x33, 0xCC}, {0xd8, 0x10, 0x00}, {0xd9, 0x10, 0x00},
- {0xd2, 0x02, 0x00},}, /* SATURATION LEVEL1*/
- {{0x81, 0x33, 0xCC}, {0xd8, 0x20, 0x00}, {0xd9, 0x20, 0x00},
- {0xd2, 0x02, 0x00},}, /* SATURATION LEVEL2*/
- {{0x81, 0x33, 0xCC}, {0xd8, 0x30, 0x00}, {0xd9, 0x30, 0x00},
- {0xd2, 0x02, 0x00},}, /* SATURATION LEVEL3*/
- {{0x81, 0x33, 0xCC}, {0xd8, 0x40, 0x00}, {0xd9, 0x40, 0x00},
- {0xd2, 0x02, 0x00},}, /* SATURATION LEVEL4*/
- {{0x81, 0x33, 0xCC}, {0xd8, 0x50, 0x00}, {0xd9, 0x50, 0x00},
- {0xd2, 0x02, 0x00},}, /* SATURATION LEVEL5*/
- {{0x81, 0x33, 0xCC}, {0xd8, 0x60, 0x00}, {0xd9, 0x60, 0x00},
- {0xd2, 0x02, 0x00},}, /* SATURATION LEVEL6*/
- {{0x81, 0x33, 0xCC}, {0xd8, 0x70, 0x00}, {0xd9, 0x70, 0x00},
- {0xd2, 0x02, 0x00},}, /* SATURATION LEVEL7*/
- {{0x81, 0x33, 0xCC}, {0xd8, 0x80, 0x00}, {0xd9, 0x80, 0x00},
- {0xd2, 0x02, 0x00},}, /* SATURATION LEVEL8*/
+ {{0x81, 0x33, 0x00, 0x00, 0xCC}, {0xd8, 0x00, 0x00, 0x00, 0x00},
+ {0xd9, 0x00, 0x00, 0x00, 0x00},
+ {0xd2, 0x02, 0x00, 0x00, 0x00},},/* SATURATION LEVEL0*/
+ {{0x81, 0x33, 0x00, 0x00, 0xCC}, {0xd8, 0x10, 0x00, 0x00, 0x00},
+ {0xd9, 0x10, 0x00, 0x00, 0x00},
+ {0xd2, 0x02, 0x00, 0x00, 0x00},}, /* SATURATION LEVEL1*/
+ {{0x81, 0x33, 0x00, 0x00, 0xCC}, {0xd8, 0x20, 0x00, 0x00, 0x00},
+ {0xd9, 0x20, 0x00, 0x00, 0x00},
+ {0xd2, 0x02, 0x00, 0x00, 0x00},}, /* SATURATION LEVEL2*/
+ {{0x81, 0x33, 0x00, 0x00, 0xCC}, {0xd8, 0x30, 0x00, 0x00, 0x00},
+ {0xd9, 0x30, 0x00, 0x00, 0x00},
+ {0xd2, 0x02, 0x00, 0x00, 0x00},}, /* SATURATION LEVEL3*/
+ {{0x81, 0x33, 0x00, 0x00, 0xCC}, {0xd8, 0x40, 0x00, 0x00, 0x00},
+ {0xd9, 0x40, 0x00, 0x00, 0x00},
+ {0xd2, 0x02, 0x00, 0x00, 0x00},}, /* SATURATION LEVEL4*/
+ {{0x81, 0x33, 0x00, 0x00, 0xCC}, {0xd8, 0x50, 0x00, 0x00, 0x00},
+ {0xd9, 0x50, 0x00, 0x00, 0x00},
+ {0xd2, 0x02, 0x00, 0x00, 0x00},}, /* SATURATION LEVEL5*/
+ {{0x81, 0x33, 0x00, 0x00, 0xCC}, {0xd8, 0x60, 0x00, 0x00, 0x00},
+ {0xd9, 0x60, 0x00, 0x00, 0x00},
+ {0xd2, 0x02, 0x00, 0x00, 0x00},}, /* SATURATION LEVEL6*/
+ {{0x81, 0x33, 0x00, 0x00, 0xCC}, {0xd8, 0x70, 0x00, 0x00, 0x00},
+ {0xd9, 0x70, 0x00, 0x00, 0x00},
+ {0xd2, 0x02, 0x00, 0x00, 0x00},}, /* SATURATION LEVEL7*/
+ {{0x81, 0x33, 0x00, 0x00, 0xCC}, {0xd8, 0x80, 0x00, 0x00, 0x00},
+ {0xd9, 0x80, 0x00, 0x00, 0x00},
+ {0xd2, 0x02, 0x00, 0x00, 0x00},}, /* SATURATION LEVEL8*/
};
static struct msm_camera_i2c_conf_array ov7692_saturation_confs[][1] = {
{{ov7692_saturation[0], ARRAY_SIZE(ov7692_saturation[0]), 0,
@@ -327,12 +336,18 @@
.data_type = MSM_CAMERA_I2C_BYTE_DATA,
};
static struct msm_camera_i2c_reg_conf ov7692_sharpness[][2] = {
- {{0xb4, 0x20, 0xDF}, {0xb6, 0x00, 0xE0},}, /* SHARPNESS LEVEL 0*/
- {{0xb4, 0x20, 0xDF}, {0xb6, 0x01, 0xE0},}, /* SHARPNESS LEVEL 1*/
- {{0xb4, 0x00, 0xDF}, {0xb6, 0x00, 0xE0},}, /* SHARPNESS LEVEL 2*/
- {{0xb4, 0x20, 0xDF}, {0xb6, 0x66, 0xE0},}, /* SHARPNESS LEVEL 3*/
- {{0xb4, 0x20, 0xDF}, {0xb6, 0x99, 0xE0},}, /* SHARPNESS LEVEL 4*/
- {{0xb4, 0x20, 0xDF}, {0xb6, 0xcc, 0xE0},}, /* SHARPNESS LEVEL 5*/
+ {{0xb4, 0x20, 0x00, 0x00, 0xDF},
+ {0xb6, 0x00, 0x00, 0x00, 0xE0},}, /* SHARPNESS LEVEL 0*/
+ {{0xb4, 0x20, 0x00, 0x00, 0xDF},
+ {0xb6, 0x01, 0x00, 0x00, 0xE0},}, /* SHARPNESS LEVEL 1*/
+ {{0xb4, 0x00, 0x00, 0x00, 0xDF},
+ {0xb6, 0x00, 0x00, 0x00, 0xE0},}, /* SHARPNESS LEVEL 2*/
+ {{0xb4, 0x20, 0x00, 0x00, 0xDF},
+ {0xb6, 0x66, 0x00, 0x00, 0xE0},}, /* SHARPNESS LEVEL 3*/
+ {{0xb4, 0x20, 0x00, 0x00, 0xDF},
+ {0xb6, 0x99, 0x00, 0x00, 0xE0},}, /* SHARPNESS LEVEL 4*/
+ {{0xb4, 0x20, 0x00, 0x00, 0xDF},
+ {0xb6, 0xcc, 0x00, 0x00, 0xE0},}, /* SHARPNESS LEVEL 5*/
};
static struct msm_camera_i2c_conf_array ov7692_sharpness_confs[][1] = {
@@ -407,13 +422,13 @@
};
static struct msm_camera_i2c_reg_conf ov7692_iso[][1] = {
- {{0x14, 0x20, 0x8F},}, /*ISO_AUTO*/
- {{0x14, 0x20, 0x8F},}, /*ISO_DEBLUR*/
- {{0x14, 0x00, 0x8F},}, /*ISO_100*/
- {{0x14, 0x10, 0x8F},}, /*ISO_200*/
- {{0x14, 0x20, 0x8F},}, /*ISO_400*/
- {{0x14, 0x30, 0x8F},}, /*ISO_800*/
- {{0x14, 0x40, 0x8F},}, /*ISO_1600*/
+ {{0x14, 0x20, 0x00, 0x00, 0x8F},}, /*ISO_AUTO*/
+ {{0x14, 0x20, 0x00, 0x00, 0x8F},}, /*ISO_DEBLUR*/
+ {{0x14, 0x00, 0x00, 0x00, 0x8F},}, /*ISO_100*/
+ {{0x14, 0x10, 0x00, 0x00, 0x8F},}, /*ISO_200*/
+ {{0x14, 0x20, 0x00, 0x00, 0x8F},}, /*ISO_400*/
+ {{0x14, 0x30, 0x00, 0x00, 0x8F},}, /*ISO_800*/
+ {{0x14, 0x40, 0x00, 0x00, 0x8F},}, /*ISO_1600*/
};
@@ -453,7 +468,7 @@
};
static struct msm_camera_i2c_reg_conf ov7692_no_effect[] = {
- {0x81, 0x00, 0xDF},
+ {0x81, 0x00, 0x00, 0x00, 0xDF},
{0x28, 0x00,},
{0xd2, 0x00,},
{0xda, 0x80,},
@@ -467,32 +482,41 @@
};
static struct msm_camera_i2c_reg_conf ov7692_special_effect[][5] = {
- {{0x81, 0x20, 0xDF}, {0x28, 0x00,}, {0xd2, 0x18,}, {0xda, 0x80,},
- {0xdb, 0x80,},}, /*for special effect OFF*/
- {{0x81, 0x20, 0xDF}, {0x28, 0x00,}, {0xd2, 0x18,}, {0xda, 0x80,},
- {0xdb, 0x80,},}, /*for special effect MONO*/
- {{0x81, 0x20, 0xDF}, {0x28, 0x80,}, {0xd2, 0x40,}, {0xda, 0x80,},
- {0xdb, 0x80,},}, /*for special efefct Negative*/
- {{-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1},
- {-1, -1, -1},}, /*Solarize is not supported by sensor*/
- {{0x81, 0x20, 0xDF}, {0x28, 0x00,}, {0xd2, 0x18,}, {0xda, 0x40,},
- {0xdb, 0xa0,},}, /*for sepia*/
- {{-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1},
- {-1, -1, -1},}, /* Posteraize not supported */
- {{-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1},
- {-1, -1, -1},}, /* White board not supported*/
- {{-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1},
- {-1, -1, -1},}, /*Blackboard not supported*/
- {{-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1},
- {-1, -1, -1},}, /*Aqua not supported*/
- {{-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1},
- {-1, -1, -1},}, /*Emboss not supported */
- {{-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1},
- {-1, -1, -1},}, /*sketch not supported*/
- {{-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1},
- {-1, -1, -1},}, /*Neon not supported*/
- {{-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1},
- {-1, -1, -1},}, /*MAX value*/
+ {{0x81, 0x20, 0x00, 0x00, 0xDF}, {0x28, 0x00,}, {0xd2, 0x18,},
+ {0xda, 0x80,}, {0xdb, 0x80,},}, /*for special effect OFF*/
+ {{0x81, 0x20, 0x00, 0x00, 0xDF}, {0x28, 0x00,}, {0xd2, 0x18,},
+ {0xda, 0x80,}, {0xdb, 0x80,},}, /*for special effect MONO*/
+ {{0x81, 0x20, 0x00, 0x00, 0xDF}, {0x28, 0x80,}, {0xd2, 0x40,},
+ {0xda, 0x80,}, {0xdb, 0x80,},}, /*for special efefct Negative*/
+ {{-1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1},
+ {-1, -1, -1, -1, -1},
+ {-1, -1, -1, -1, -1},},/*Solarize is not supported by sensor*/
+ {{0x81, 0x20, 0x00, 0x00, 0xDF}, {0x28, 0x00,}, {0xd2, 0x18,},
+ {0xda, 0x40,}, {0xdb, 0xa0,},}, /*for sepia*/
+ {{-1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1},
+ {-1, -1, -1, -1, -1},
+ {-1, -1, -1, -1, -1},}, /* Posteraize not supported */
+ {{-1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1},
+ {-1, -1, -1, -1, -1},
+ {-1, -1, -1, -1, -1},}, /* White board not supported*/
+ {{-1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1},
+ {-1, -1, -1, -1, -1},
+ {-1, -1, -1, -1, -1},}, /*Blackboard not supported*/
+ {{-1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1},
+ {-1, -1, -1, -1, -1},
+ {-1, -1, -1, -1, -1},}, /*Aqua not supported*/
+ {{-1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1},
+ {-1, -1, -1, -1, -1},
+ {-1, -1, -1, -1, -1},}, /*Emboss not supported */
+ {{-1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1},
+ {-1, -1, -1, -1, -1},
+ {-1, -1, -1, -1, -1},}, /*sketch not supported*/
+ {{-1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1},
+ {-1, -1, -1, -1, -1},
+ {-1, -1, -1, -1, -1},}, /*Neon not supported*/
+ {{-1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1},
+ {-1, -1, -1, -1, -1},
+ {-1, -1, -1, -1, -1},}, /*MAX value*/
};
static struct msm_camera_i2c_conf_array ov7692_special_effect_confs[][1] = {
@@ -551,9 +575,12 @@
};
static struct msm_camera_i2c_reg_conf ov7692_antibanding[][2] = {
- {{0x13, 0x20, 0xDF}, {0x14, 0x16, 0xE8},}, /*ANTIBANDING 60HZ*/
- {{0x13, 0x20, 0xDF}, {0x14, 0x17, 0xE8},}, /*ANTIBANDING 50HZ*/
- {{0x13, 0x20, 0xDF}, {0x14, 0x14, 0xE8},}, /* ANTIBANDING AUTO*/
+ {{0x13, 0x20, 0x00, 0x00, 0xDF},
+ {0x14, 0x16, 0x00, 0x00, 0xE8},}, /*ANTIBANDING 60HZ*/
+ {{0x13, 0x20, 0x00, 0x00, 0xDF},
+ {0x14, 0x17, 0x00, 0x00, 0xE8},}, /*ANTIBANDING 50HZ*/
+ {{0x13, 0x20, 0x00, 0x00, 0xDF},
+ {0x14, 0x14, 0x00, 0x00, 0xE8},}, /* ANTIBANDING AUTO*/
};
@@ -583,16 +610,16 @@
};
static struct msm_camera_i2c_reg_conf ov7692_wb_oem[][4] = {
- {{-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1},
- {-1, -1, -1},},/*WHITEBALNACE OFF*/
- {{0x13, 0xf7}, {0x15, 0x00}, {-1, -1, -1},
- {-1, -1, -1},}, /*WHITEBALNACE AUTO*/
+ {{-1, -1, -1, -1 , -1}, {-1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1},
+ {-1, -1, -1, -1, -1},},/*WHITEBALNACE OFF*/
+ {{0x13, 0xf7}, {0x15, 0x00}, {-1, -1, -1, -1, -1},
+ {-1, -1, -1, -1, -1},}, /*WHITEBALNACE AUTO*/
{{0x13, 0xf5}, {0x01, 0x56}, {0x02, 0x50},
{0x15, 0x00},}, /*WHITEBALNACE CUSTOM*/
{{0x13, 0xf5}, {0x01, 0x66}, {0x02, 0x40},
{0x15, 0x00},}, /*INCANDISCENT*/
- {{-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1},
- {-1, -1, -1},}, /*FLOURESECT NOT SUPPORTED */
+ {{-1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1},
+ {-1, -1, -1, -1, -1},}, /*FLOURESECT NOT SUPPORTED */
{{0x13, 0xf5}, {0x01, 0x43}, {0x02, 0x5d},
{0x15, 0x00},}, /*DAYLIGHT*/
{{0x13, 0xf5}, {0x01, 0x48}, {0x02, 0x63},
diff --git a/drivers/media/video/msm/server/msm_cam_server.c b/drivers/media/video/msm/server/msm_cam_server.c
index 05f3c4a..2d3022f 100644
--- a/drivers/media/video/msm/server/msm_cam_server.c
+++ b/drivers/media/video/msm/server/msm_cam_server.c
@@ -1703,10 +1703,10 @@
sizeof(struct intr_table_entry));
D("%s Saving Entry %d %d %d %p",
__func__,
- ind_irq_tbl[irq_req->cam_hw_idx].irq_num,
- ind_irq_tbl[irq_req->cam_hw_idx].cam_hw_idx,
- ind_irq_tbl[irq_req->cam_hw_idx].is_composite,
- ind_irq_tbl[irq_req->cam_hw_idx].subdev_list[0]);
+ ind_irq_tbl[irq_req->irq_idx].irq_num,
+ ind_irq_tbl[irq_req->irq_idx].cam_hw_idx,
+ ind_irq_tbl[irq_req->irq_idx].is_composite,
+ ind_irq_tbl[irq_req->irq_idx].subdev_list[0]);
spin_unlock_irqrestore(&g_server_dev.intr_table_lock,
flags);
@@ -1859,10 +1859,16 @@
break;
case ISPIF_DEV:
+ if (index >= MAX_NUM_ISPIF_DEV) {
+ pr_err("%s Invalid ISPIF idx %d", __func__, index);
+ err = -EINVAL;
+ break;
+ }
+ cam_hw_idx = MSM_CAM_HW_ISPIF + index;
g_server_dev.ispif_device = sd;
if (g_server_dev.irqr_device) {
g_server_dev.subdev_table[cam_hw_idx] = sd;
- err = msm_cam_server_fill_sdev_irqnum(MSM_CAM_HW_ISPIF,
+ err = msm_cam_server_fill_sdev_irqnum(cam_hw_idx,
sd_info->irq_num);
}
break;
diff --git a/drivers/media/video/msm_vidc/msm_vdec.c b/drivers/media/video/msm_vidc/msm_vdec.c
index 09c7215..dca9f1d 100644
--- a/drivers/media/video/msm_vidc/msm_vdec.c
+++ b/drivers/media/video/msm_vidc/msm_vdec.c
@@ -154,7 +154,11 @@
static u32 get_frame_size_nv12(int plane,
u32 height, u32 width)
{
- return (ALIGN(height, 32) * ALIGN(width, 32) * 3) / 2;
+ int luma_stride = ALIGN(width, 32);
+ int luma_slice = ALIGN(height, 32);
+ int chroma_stride = ALIGN(roundup(width, 2)/2, 32);
+ int chroma_slice = ALIGN(roundup(height, 2)/2, 32);
+ return (luma_stride * luma_slice) + (chroma_stride * chroma_slice) * 2;
}
static u32 get_frame_size_nv21(int plane,
u32 height, u32 width)
@@ -165,7 +169,7 @@
static u32 get_frame_size_compressed(int plane,
u32 height, u32 width)
{
- return 0x500000;
+ return height * width * 3/2;
}
static const struct msm_vidc_format vdec_formats[] = {
diff --git a/drivers/media/video/msm_vidc/msm_vidc.c b/drivers/media/video/msm_vidc/msm_vidc.c
index 11fbcf4..28fe2b8 100644
--- a/drivers/media/video/msm_vidc/msm_vidc.c
+++ b/drivers/media/video/msm_vidc/msm_vidc.c
@@ -29,19 +29,16 @@
struct vb2_buffer *out_vb = NULL;
struct vb2_buffer *cap_vb = NULL;
unsigned long flags;
- poll_wait(filp, &inst->event_handler.wait, wait);
- if (v4l2_event_pending(&inst->event_handler))
- return POLLPRI;
if (!outq->streaming && !capq->streaming) {
pr_err("Returning POLLERR from here: %d, %d\n",
outq->streaming, capq->streaming);
return POLLERR;
}
poll_wait(filp, &inst->event_handler.wait, wait);
- if (v4l2_event_pending(&inst->event_handler))
- return POLLPRI;
poll_wait(filp, &capq->done_wq, wait);
poll_wait(filp, &outq->done_wq, wait);
+ if (v4l2_event_pending(&inst->event_handler))
+ rc |= POLLPRI;
spin_lock_irqsave(&capq->done_lock, flags);
if (!list_empty(&capq->done_list))
cap_vb = list_first_entry(&capq->done_list, struct vb2_buffer,
diff --git a/drivers/media/video/msm_vidc/msm_vidc_common.c b/drivers/media/video/msm_vidc/msm_vidc_common.c
index a5cff9c..4a86cf5 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_common.c
+++ b/drivers/media/video/msm_vidc/msm_vidc_common.c
@@ -933,12 +933,56 @@
{
int rc = 0;
struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance;
+ bool ip_flush = false,
+ op_flush = false;
+
mutex_lock(&inst->sync_lock);
- if (dec->cmd != V4L2_DEC_CMD_STOP)
- return -EINVAL;
- rc = vidc_hal_session_flush((void *)inst->session, HAL_FLUSH_OUTPUT);
+
+ switch (dec->cmd) {
+ case V4L2_DEC_QCOM_CMD_FLUSH:
+ ip_flush = dec->flags & V4L2_DEC_QCOM_CMD_FLUSH_OUTPUT;
+ op_flush = dec->flags & V4L2_DEC_QCOM_CMD_FLUSH_CAPTURE;
+ /* Only support flush on decoder (for now)*/
+ if (inst->session_type == MSM_VIDC_ENCODER) {
+ pr_err("Buffer flushing not supported for encoder\n");
+ rc = -ENOTSUPP;
+ break;
+ }
+
+ /* Certain types of flushes aren't supported such as: */
+ /* 1) Input only flush */
+ if (ip_flush && !op_flush) {
+ pr_err("Input only flush not supported\n");
+ rc = -ENOTSUPP;
+ break;
+ }
+
+ /* 2) Output only flush when in reconfig */
+ if (!ip_flush && op_flush && !inst->in_reconfig) {
+ pr_err("Output only flush only supported when reconfiguring\n");
+ rc = -ENOTSUPP;
+ break;
+ }
+
+ /* Finally flush */
+ if (op_flush && ip_flush)
+ rc = vidc_hal_session_flush(inst->session,
+ HAL_FLUSH_ALL);
+ else if (ip_flush)
+ rc = vidc_hal_session_flush(inst->session,
+ HAL_FLUSH_INPUT);
+ else if (op_flush)
+ rc = vidc_hal_session_flush(inst->session,
+ HAL_FLUSH_OUTPUT);
+
+ break;
+ default:
+ rc = -ENOTSUPP;
+ goto exit;
+ }
+
if (rc) {
- pr_err("Failed to get property\n");
+ pr_err("Failed to exec decoder cmd %d\n", dec->cmd);
goto exit;
}
exit:
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 b604d0a..ded9f11 100644
--- a/drivers/media/video/msm_vidc/vidc_hal_interrupt_handler.c
+++ b/drivers/media/video/msm_vidc/vidc_hal_interrupt_handler.c
@@ -98,6 +98,18 @@
cmd_done.status = VIDC_ERR_NONE;
cmd_done.size = sizeof(struct msm_vidc_cb_event);
num_properties_changed = pkt->event_data2;
+ switch (pkt->event_data1) {
+ case HFI_EVENT_DATA_SEQUENCE_CHANGED_SUFFICIENT_BUFFER_RESOURCES:
+ event_notify.hal_event_type =
+ HAL_EVENT_SEQ_CHANGED_SUFFICIENT_RESOURCES;
+ break;
+ case HFI_EVENT_DATA_SEQUENCE_CHANGED_INSUFFICIENT_BUFFER_RESOURCES:
+ event_notify.hal_event_type =
+ HAL_EVENT_SEQ_CHANGED_INSUFFICIENT_RESOURCES;
+ break;
+ default:
+ break;
+ }
if (num_properties_changed) {
data_ptr = (u8 *) &pkt->rg_ext_event_data[0];
do {
diff --git a/drivers/media/video/vcap_v4l2.c b/drivers/media/video/vcap_v4l2.c
index 0a033ae..4f7c585 100644
--- a/drivers/media/video/vcap_v4l2.c
+++ b/drivers/media/video/vcap_v4l2.c
@@ -303,6 +303,105 @@
cd->set_vp_o = false;
}
+/* VCAP Internal QBUF and DQBUF for VC + VP */
+int vcvp_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
+{
+ struct vb2_buffer *vb;
+
+ if (q->fileio) {
+ dprintk(1, "%s: file io in progress\n", __func__);
+ return -EBUSY;
+ }
+
+ if (b->type != q->type) {
+ dprintk(1, "%s: invalid buffer type\n", __func__);
+ return -EINVAL;
+ }
+
+ if (b->index >= q->num_buffers) {
+ dprintk(1, "%s: buffer index out of range\n", __func__);
+ return -EINVAL;
+ }
+
+ vb = q->bufs[b->index];
+ if (NULL == vb) {
+ dprintk(1, "%s: buffer is NULL\n", __func__);
+ return -EINVAL;
+ }
+
+ if (b->memory != q->memory) {
+ dprintk(1, "%s: invalid memory type\n", __func__);
+ return -EINVAL;
+ }
+
+ if (vb->state != VB2_BUF_STATE_DEQUEUED &&
+ vb->state != VB2_BUF_STATE_PREPARED) {
+ dprintk(1, "%s: buffer already in use\n", __func__);
+ return -EINVAL;
+ }
+
+ list_add_tail(&vb->queued_entry, &q->queued_list);
+ vb->state = VB2_BUF_STATE_QUEUED;
+
+ if (q->streaming) {
+ vb->state = VB2_BUF_STATE_ACTIVE;
+ atomic_inc(&q->queued_count);
+ q->ops->buf_queue(vb);
+ }
+ return 0;
+}
+
+int vcvp_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b)
+{
+ struct vb2_buffer *vb = NULL;
+ unsigned long flags;
+
+ if (q->fileio) {
+ dprintk(1, "%s: file io in progress\n", __func__);
+ return -EBUSY;
+ }
+
+ if (b->type != q->type) {
+ dprintk(1, "%s: invalid buffer type\n", __func__);
+ return -EINVAL;
+ }
+
+ if (!q->streaming) {
+ dprintk(1, "Streaming off, will not wait for buffers\n");
+ return -EINVAL;
+ }
+
+ if (!list_empty(&q->done_list)) {
+ spin_lock_irqsave(&q->done_lock, flags);
+ vb = list_first_entry(&q->done_list, struct vb2_buffer,
+ done_entry);
+ list_del(&vb->done_entry);
+ spin_unlock_irqrestore(&q->done_lock, flags);
+
+ switch (vb->state) {
+ case VB2_BUF_STATE_DONE:
+ dprintk(3, "%s: Returning done buffer\n", __func__);
+ break;
+ case VB2_BUF_STATE_ERROR:
+ dprintk(3, "%s: Ret done buf with err\n", __func__);
+ break;
+ default:
+ dprintk(1, "%s: Invalid buffer state\n", __func__);
+ return -EINVAL;
+ }
+
+ memcpy(b, &vb->v4l2_buf, offsetof(struct v4l2_buffer, m));
+
+ list_del(&vb->queued_entry);
+
+ vb->state = VB2_BUF_STATE_DEQUEUED;
+ return 0;
+ }
+
+ dprintk(1, "No buffers to dequeue\n");
+ return -EAGAIN;
+}
+
int get_phys_addr(struct vcap_dev *dev, struct vb2_queue *q,
struct v4l2_buffer *b)
{
@@ -889,6 +988,14 @@
dprintk(1, "qbuf: buffer already in use\n");
return -EINVAL;
}
+ rc = get_phys_addr(c_data->dev, &c_data->vc_vidq, p);
+ if (rc < 0)
+ return rc;
+ rc = vcvp_qbuf(&c_data->vc_vidq, p);
+ if (rc < 0)
+ free_ion_handle(c_data->dev,
+ &c_data->vc_vidq, p);
+ return rc;
}
rc = get_phys_addr(c_data->dev, &c_data->vc_vidq, p);
if (rc < 0)
diff --git a/drivers/media/video/vcap_vc.c b/drivers/media/video/vcap_vc.c
index ad0718e..62cc306 100644
--- a/drivers/media/video/vcap_vc.c
+++ b/drivers/media/video/vcap_vc.c
@@ -62,19 +62,19 @@
struct vcap_buffer *buf_vp;
int rc;
- p.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
p.memory = V4L2_MEMORY_USERPTR;
while (1) {
+ p.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (!vp_work->cd->streaming)
return;
- rc = vb2_dqbuf(&vp_work->cd->vc_vidq, &p, O_NONBLOCK);
+ rc = vcvp_dqbuf(&vp_work->cd->vc_vidq, &p);
if (rc < 0)
return;
vb_vc = vp_work->cd->vc_vidq.bufs[p.index];
if (NULL == vb_vc) {
dprintk(1, "%s: buffer is NULL\n", __func__);
- vb2_qbuf(&vp_work->cd->vc_vidq, &p);
+ vcvp_qbuf(&vp_work->cd->vc_vidq, &p);
return;
}
buf_vc = container_of(vb_vc, struct vcap_buffer, vb);
@@ -82,7 +82,7 @@
vb_vp = vp_work->cd->vp_in_vidq.bufs[p.index];
if (NULL == vb_vp) {
dprintk(1, "%s: buffer is NULL\n", __func__);
- vb2_qbuf(&vp_work->cd->vc_vidq, &p);
+ vcvp_qbuf(&vp_work->cd->vc_vidq, &p);
return;
}
buf_vp = container_of(vb_vp, struct vcap_buffer, vb);
@@ -94,7 +94,7 @@
p.type = V4L2_BUF_TYPE_INTERLACED_IN_DECODER;
/* This call should not fail */
- rc = vb2_qbuf(&vp_work->cd->vp_in_vidq, &p);
+ rc = vcvp_qbuf(&vp_work->cd->vp_in_vidq, &p);
if (rc < 0) {
pr_err("%s: qbuf to vp_in failed\n", __func__);
buf_vc->ion_handle = buf_vp->ion_handle;
@@ -102,7 +102,7 @@
buf_vp->ion_handle = NULL;
buf_vp->paddr = 0;
p.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- vb2_qbuf(&vp_work->cd->vc_vidq, &p);
+ vcvp_qbuf(&vp_work->cd->vc_vidq, &p);
}
}
}
diff --git a/drivers/media/video/vcap_vp.c b/drivers/media/video/vcap_vp.c
index 1b503ba..db38902 100644
--- a/drivers/media/video/vcap_vp.c
+++ b/drivers/media/video/vcap_vp.c
@@ -117,21 +117,21 @@
struct vcap_buffer *buf_vp;
int rc;
- p.type = V4L2_BUF_TYPE_INTERLACED_IN_DECODER;
p.memory = V4L2_MEMORY_USERPTR;
/* This loop exits when there is no more buffers left */
while (1) {
+ p.type = V4L2_BUF_TYPE_INTERLACED_IN_DECODER;
if (!vp_work->cd->streaming)
return;
- rc = vb2_dqbuf(&vp_work->cd->vp_in_vidq, &p, O_NONBLOCK);
+ rc = vcvp_dqbuf(&vp_work->cd->vp_in_vidq, &p);
if (rc < 0)
return;
vb_vc = vp_work->cd->vc_vidq.bufs[p.index];
if (NULL == vb_vc) {
dprintk(1, "%s: buffer is NULL\n", __func__);
- vb2_qbuf(&vp_work->cd->vp_in_vidq, &p);
+ vcvp_qbuf(&vp_work->cd->vp_in_vidq, &p);
return;
}
buf_vc = container_of(vb_vc, struct vcap_buffer, vb);
@@ -139,7 +139,7 @@
vb_vp = vp_work->cd->vp_in_vidq.bufs[p.index];
if (NULL == vb_vp) {
dprintk(1, "%s: buffer is NULL\n", __func__);
- vb2_qbuf(&vp_work->cd->vp_in_vidq, &p);
+ vcvp_qbuf(&vp_work->cd->vp_in_vidq, &p);
return;
}
buf_vp = container_of(vb_vp, struct vcap_buffer, vb);
@@ -150,7 +150,7 @@
p.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
/* This call should not fail */
- rc = vb2_qbuf(&vp_work->cd->vc_vidq, &p);
+ rc = vcvp_qbuf(&vp_work->cd->vc_vidq, &p);
if (rc < 0) {
dprintk(1, "%s: qbuf to vc failed\n", __func__);
buf_vp->ion_handle = buf_vc->ion_handle;
@@ -158,7 +158,7 @@
buf_vc->ion_handle = NULL;
buf_vc->paddr = 0;
p.type = V4L2_BUF_TYPE_INTERLACED_IN_DECODER;
- vb2_qbuf(&vp_work->cd->vp_in_vidq, &p);
+ vcvp_qbuf(&vp_work->cd->vp_in_vidq, &p);
}
}
}
diff --git a/drivers/mfd/wcd9xxx-core.c b/drivers/mfd/wcd9xxx-core.c
index 021dcf1..2256f67 100644
--- a/drivers/mfd/wcd9xxx-core.c
+++ b/drivers/mfd/wcd9xxx-core.c
@@ -297,7 +297,6 @@
static int wcd9xxx_device_init(struct wcd9xxx *wcd9xxx, int irq)
{
int ret;
- u8 idbyte_0, idbyte_1, idbyte_2, idbyte_3;
struct mfd_cell *wcd9xxx_dev = NULL;
int wcd9xxx_dev_size = 0;
@@ -321,49 +320,26 @@
goto err;
}
- idbyte_0 = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_0);
- idbyte_1 = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_1);
- idbyte_2 = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_2);
- idbyte_3 = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_3);
+ wcd9xxx->idbyte_0 = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_0);
+ wcd9xxx->idbyte_1 = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_1);
+ wcd9xxx->idbyte_2 = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_2);
+ wcd9xxx->idbyte_3 = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_3);
wcd9xxx->version = wcd9xxx_reg_read(wcd9xxx,
WCD9XXX_A_CHIP_VERSION) & 0x1F;
pr_info("%s : Codec version %u initialized\n",
__func__, wcd9xxx->version);
- pr_info("idbyte_0[%08x] idbyte_1[%08x] idbyte_2[%08x] idbyte_3[%08x]\n",
- idbyte_0, idbyte_1, idbyte_2, idbyte_3);
- if (wcd9xxx->slim != NULL) {
- if (!strncmp(wcd9xxx->slim->name, "tabla", 5)) {
- if (TABLA_IS_1_X(wcd9xxx->version)) {
- wcd9xxx_dev = tabla1x_devs;
- wcd9xxx_dev_size = ARRAY_SIZE(tabla1x_devs);
- } else {
- wcd9xxx_dev = tabla_devs;
- wcd9xxx_dev_size = ARRAY_SIZE(tabla_devs);
- }
- } else {
- wcd9xxx_dev = sitar_devs;
- wcd9xxx_dev_size = ARRAY_SIZE(sitar_devs);
- }
- } else {
- /* Need to add here check for Tabla.
- * For now the read of version takes
- * care of now only tabla.
- */
- pr_debug("%s : Read codec version using I2C\n", __func__);
- if (!strncmp(wcd9xxx_modules[0].client->name, "sitar", 5)) {
- wcd9xxx_dev = sitar_devs;
- wcd9xxx_dev_size = ARRAY_SIZE(sitar_devs);
- } else if (TABLA_IS_1_X(wcd9xxx->version)) {
- wcd9xxx_dev = tabla1x_devs;
- wcd9xxx_dev_size = ARRAY_SIZE(tabla1x_devs);
- } else if (TABLA_IS_2_0(wcd9xxx->version)) {
- wcd9xxx_dev = tabla_devs;
- wcd9xxx_dev_size = ARRAY_SIZE(tabla_devs);
- }
+ if (wcd9xxx->idbyte_0 == 0x2) {
+ wcd9xxx_dev = tabla_devs;
+ wcd9xxx_dev_size = ARRAY_SIZE(tabla_devs);
+ } else if (wcd9xxx->idbyte_0 == 0x1) {
+ wcd9xxx_dev = tabla1x_devs;
+ wcd9xxx_dev_size = ARRAY_SIZE(tabla1x_devs);
+ } else if (wcd9xxx->idbyte_0 == 0x0) {
+ wcd9xxx_dev = sitar_devs;
+ wcd9xxx_dev_size = ARRAY_SIZE(sitar_devs);
}
-
ret = mfd_add_devices(wcd9xxx->dev, -1,
wcd9xxx_dev, wcd9xxx_dev_size,
NULL, 0);
@@ -766,21 +742,22 @@
wcd9xxx->irq = pdata->irq;
wcd9xxx->irq_base = pdata->irq_base;
- /*read the tabla status before initializing the device type*/
- ret = wcd9xxx_read(wcd9xxx, WCD9XXX_A_CHIP_STATUS, 1, &val, 0);
- if (!strncmp(wcd9xxx_modules[0].client->name, "sitar", 5))
- i2c_mode = SITAR_I2C_MODE;
- else if (!strncmp(wcd9xxx_modules[0].client->name, "tabla", 5))
- i2c_mode = TABLA_I2C_MODE;
-
- if ((ret < 0) || (val != i2c_mode))
- pr_err("failed to read the wcd9xxx status ret = %d\n", ret);
-
ret = wcd9xxx_device_init(wcd9xxx, wcd9xxx->irq);
if (ret) {
pr_err("%s: error, initializing device failed\n", __func__);
goto err_device_init;
}
+
+ if ((wcd9xxx->idbyte_0 == 0x2) || (wcd9xxx->idbyte_0 == 0x1))
+ i2c_mode = TABLA_I2C_MODE;
+ else if (wcd9xxx->idbyte_0 == 0x0)
+ i2c_mode = SITAR_I2C_MODE;
+
+ ret = wcd9xxx_read(wcd9xxx, WCD9XXX_A_CHIP_STATUS, 1, &val, 0);
+
+ if ((ret < 0) || (val != i2c_mode))
+ pr_err("failed to read the wcd9xxx status ret = %d\n", ret);
+
wcd9xxx_intf = WCD9XXX_INTERFACE_TYPE_I2C;
return ret;
@@ -1127,15 +1104,6 @@
};
MODULE_DEVICE_TABLE(i2c, tabla_id_table);
-static struct i2c_device_id sitar_id_table[] = {
- {"sitar top level", WCD9XXX_I2C_TOP_LEVEL},
- {"sitar analog", WCD9XXX_I2C_ANALOG},
- {"sitar digital1", WCD9XXX_I2C_DIGITAL_1},
- {"sitar digital2", WCD9XXX_I2C_DIGITAL_2},
- {}
-};
-MODULE_DEVICE_TABLE(i2c, tabla_id_table);
-
static struct i2c_driver tabla_i2c_driver = {
.driver = {
.owner = THIS_MODULE,
@@ -1148,21 +1116,9 @@
.suspend = wcd9xxx_i2c_suspend,
};
-static struct i2c_driver sitar_i2c_driver = {
- .driver = {
- .owner = THIS_MODULE,
- .name = "sitar-i2c-core",
- },
- .id_table = sitar_id_table,
- .probe = wcd9xxx_i2c_probe,
- .remove = __devexit_p(wcd9xxx_i2c_remove),
- .resume = wcd9xxx_i2c_resume,
- .suspend = wcd9xxx_i2c_suspend,
-};
-
static int __init wcd9xxx_init(void)
{
- int ret1, ret2, ret3, ret4, ret5, ret6;
+ int ret1, ret2, ret3, ret4, ret5;
ret1 = slim_driver_register(&tabla_slim_driver);
if (ret1 != 0)
@@ -1184,11 +1140,7 @@
if (ret5 != 0)
pr_err("Failed to register sitar SB driver: %d\n", ret5);
- ret6 = i2c_add_driver(&sitar_i2c_driver);
- if (ret6 != 0)
- pr_err("failed to add the I2C driver\n");
-
- return (ret1 && ret2 && ret3 && ret4 && ret5 && ret6) ? -1 : 0;
+ return (ret1 && ret2 && ret3 && ret4 && ret5) ? -1 : 0;
}
module_init(wcd9xxx_init);
diff --git a/drivers/misc/tspp.c b/drivers/misc/tspp.c
index 4d7553e..cc65929 100644
--- a/drivers/misc/tspp.c
+++ b/drivers/misc/tspp.c
@@ -1818,11 +1818,12 @@
goto err_bam;
}
- if (device->tsif_pclk && clk_enable(device->tsif_pclk) != 0) {
+ if (device->tsif_pclk && clk_prepare_enable(device->tsif_pclk) != 0) {
dev_err(&pdev->dev, "Can't start pclk");
goto err_pclk;
}
- if (device->tsif_ref_clk && clk_enable(device->tsif_ref_clk) != 0) {
+ if (device->tsif_ref_clk &&
+ clk_prepare_enable(device->tsif_ref_clk) != 0) {
dev_err(&pdev->dev, "Can't start ref clk");
goto err_refclk;
}
@@ -1849,7 +1850,7 @@
err_refclk:
if (device->tsif_pclk)
- clk_disable(device->tsif_pclk);
+ clk_disable_unprepare(device->tsif_pclk);
err_pclk:
sps_deregister_bam_device(device->bam_handle);
err_bam:
diff --git a/drivers/mmc/card/mmc_block_test.c b/drivers/mmc/card/mmc_block_test.c
index 0ace608..3d4b477 100644
--- a/drivers/mmc/card/mmc_block_test.c
+++ b/drivers/mmc/card/mmc_block_test.c
@@ -83,6 +83,25 @@
TEST_CMD23_BITS_16TO29_SET,
TEST_CMD23_HDR_BLK_NOT_IN_COUNT,
INVALID_CMD_MAX_TESTCASE = TEST_CMD23_HDR_BLK_NOT_IN_COUNT,
+
+ /*
+ * Start of packing control test group.
+ * in these next testcases the abbreviation FB = followed by
+ */
+ PACKING_CONTROL_MIN_TESTCASE,
+ TEST_PACKING_EXP_ONE_OVER_TRIGGER_FB_READ =
+ PACKING_CONTROL_MIN_TESTCASE,
+ TEST_PACKING_EXP_N_OVER_TRIGGER,
+ TEST_PACKING_EXP_N_OVER_TRIGGER_FB_READ,
+ TEST_PACKING_EXP_N_OVER_TRIGGER_FLUSH_N,
+ TEST_PACKING_EXP_THRESHOLD_OVER_TRIGGER,
+ TEST_PACKING_NOT_EXP_LESS_THAN_TRIGGER_REQUESTS,
+ TEST_PACKING_NOT_EXP_TRIGGER_REQUESTS,
+ TEST_PACKING_NOT_EXP_TRIGGER_READ_TRIGGER,
+ TEST_PACKING_NOT_EXP_TRIGGER_FLUSH_TRIGGER,
+ TEST_PACK_MIX_PACKED_NO_PACKED_PACKED,
+ TEST_PACK_MIX_NO_PACKED_PACKED_NO_PACKED,
+ PACKING_CONTROL_MAX_TESTCASE = TEST_PACK_MIX_NO_PACKED_PACKED_NO_PACKED,
};
enum mmc_block_test_group {
@@ -91,6 +110,7 @@
TEST_SEND_WRITE_PACKING_GROUP,
TEST_ERR_CHECK_GROUP,
TEST_SEND_INVALID_GROUP,
+ TEST_PACKING_CONTROL_GROUP,
};
struct mmc_block_test_debug {
@@ -98,6 +118,7 @@
struct dentry *err_check_test;
struct dentry *send_invalid_packed_test;
struct dentry *random_test_seed;
+ struct dentry *packing_control_test;
};
struct mmc_block_test_data {
@@ -454,6 +475,28 @@
return "Test invalid - cmd23 bits [16-29] set";
case TEST_CMD23_HDR_BLK_NOT_IN_COUNT:
return "Test invalid - cmd23 header block not in count";
+ case TEST_PACKING_EXP_N_OVER_TRIGGER:
+ return "\nTest packing control - pack n";
+ case TEST_PACKING_EXP_N_OVER_TRIGGER_FB_READ:
+ return "\nTest packing control - pack n followed by read";
+ case TEST_PACKING_EXP_N_OVER_TRIGGER_FLUSH_N:
+ return "\nTest packing control - pack n followed by flush";
+ case TEST_PACKING_EXP_ONE_OVER_TRIGGER_FB_READ:
+ return "\nTest packing control - pack one followed by read";
+ case TEST_PACKING_EXP_THRESHOLD_OVER_TRIGGER:
+ return "\nTest packing control - pack threshold";
+ case TEST_PACKING_NOT_EXP_LESS_THAN_TRIGGER_REQUESTS:
+ return "\nTest packing control - no packing";
+ case TEST_PACKING_NOT_EXP_TRIGGER_REQUESTS:
+ return "\nTest packing control - no packing, trigger requests";
+ case TEST_PACKING_NOT_EXP_TRIGGER_READ_TRIGGER:
+ return "\nTest packing control - no pack, trigger-read-trigger";
+ case TEST_PACKING_NOT_EXP_TRIGGER_FLUSH_TRIGGER:
+ return "\nTest packing control- no pack, trigger-flush-trigger";
+ case TEST_PACK_MIX_PACKED_NO_PACKED_PACKED:
+ return "\nTest packing control - mix: pack -> no pack -> pack";
+ case TEST_PACK_MIX_NO_PACKED_PACKED_NO_PACKED:
+ return "\nTest packing control - mix: no pack->pack->no pack";
default:
return "Unknown testcase";
}
@@ -505,7 +548,7 @@
stop_reason = mmc_packed_stats->pack_stop_reason;
- for (i = 1 ; i <= max_packed_reqs ; ++i) {
+ for (i = 1; i <= max_packed_reqs; ++i) {
if (mmc_packed_stats->packing_events[i] !=
expected_stats.packing_events[i]) {
test_pr_err(
@@ -710,7 +753,7 @@
test_pr_info("%s: Adding %d write requests, first req_id=%d", __func__,
num_requests, td->wr_rd_next_req_id);
- for (i = 1 ; i <= num_requests ; i++) {
+ for (i = 1; i <= num_requests; i++) {
start_sec = td->start_sector + 4096 * td->num_of_write_bios;
if (is_random)
pseudo_rnd_num_of_bios(bio_seed, &num_bios);
@@ -826,6 +869,185 @@
}
/*
+ * Prepare the write, read and flush requests for the packing control
+ * testcases
+ */
+static int prepare_packed_control_tests_requests(struct test_data *td,
+ int is_err_expected, int num_requests, int is_random)
+{
+ int ret = 0;
+ struct mmc_queue *mq;
+ int max_packed_reqs;
+ int temp_num_req = num_requests;
+ struct request_queue *req_q;
+ int test_packed_trigger;
+ int num_packed_reqs;
+
+ if (!td) {
+ test_pr_err("%s: NULL td\n", __func__);
+ return -EINVAL;
+ }
+
+ req_q = td->req_q;
+
+ if (!req_q) {
+ test_pr_err("%s: NULL request queue\n", __func__);
+ return -EINVAL;
+ }
+
+ mq = req_q->queuedata;
+ if (!mq) {
+ test_pr_err("%s: NULL mq", __func__);
+ return -EINVAL;
+ }
+
+ max_packed_reqs = mq->card->ext_csd.max_packed_writes;
+ test_packed_trigger = mq->num_wr_reqs_to_start_packing;
+ num_packed_reqs = num_requests - test_packed_trigger;
+
+ if (mbtd->random_test_seed == 0) {
+ mbtd->random_test_seed =
+ (unsigned int)(get_jiffies_64() & 0xFFFF);
+ test_pr_info("%s: got seed from jiffies %d",
+ __func__, mbtd->random_test_seed);
+ }
+
+ mmc_blk_init_packed_statistics(mq->card);
+
+ if (td->test_info.testcase ==
+ TEST_PACK_MIX_NO_PACKED_PACKED_NO_PACKED) {
+ temp_num_req = num_requests;
+ num_requests = test_packed_trigger - 1;
+ }
+
+ /* Verify that the packing is disabled before starting the test */
+ mq->wr_packing_enabled = false;
+ mq->num_of_potential_packed_wr_reqs = 0;
+
+ if (td->test_info.testcase == TEST_PACK_MIX_PACKED_NO_PACKED_PACKED) {
+ mq->num_of_potential_packed_wr_reqs = test_packed_trigger + 1;
+ mq->wr_packing_enabled = true;
+ num_requests = test_packed_trigger + 2;
+ }
+
+ ret = prepare_request_add_write_reqs(td, num_requests, is_err_expected,
+ is_random);
+ if (ret)
+ goto exit;
+
+ if (td->test_info.testcase == TEST_PACK_MIX_NO_PACKED_PACKED_NO_PACKED)
+ num_requests = temp_num_req;
+
+ memset((void *)mbtd->exp_packed_stats.pack_stop_reason, 0,
+ sizeof(mbtd->exp_packed_stats.pack_stop_reason));
+ memset(mbtd->exp_packed_stats.packing_events, 0,
+ (max_packed_reqs + 1) * sizeof(u32));
+
+ switch (td->test_info.testcase) {
+ case TEST_PACKING_EXP_N_OVER_TRIGGER_FB_READ:
+ case TEST_PACKING_EXP_ONE_OVER_TRIGGER_FB_READ:
+ ret = prepare_request_add_read(td);
+ if (ret)
+ goto exit;
+
+ mbtd->exp_packed_stats.pack_stop_reason[WRONG_DATA_DIR] = 1;
+ mbtd->exp_packed_stats.packing_events[num_packed_reqs] = 1;
+ break;
+ case TEST_PACKING_EXP_N_OVER_TRIGGER_FLUSH_N:
+ ret = prepare_request_add_flush(td);
+ if (ret)
+ goto exit;
+
+ ret = prepare_request_add_write_reqs(td, num_packed_reqs,
+ is_err_expected, is_random);
+ if (ret)
+ goto exit;
+
+ mbtd->exp_packed_stats.pack_stop_reason[EMPTY_QUEUE] = 1;
+ mbtd->exp_packed_stats.pack_stop_reason[FLUSH_OR_DISCARD] = 1;
+ mbtd->exp_packed_stats.packing_events[num_packed_reqs] = 2;
+ break;
+ case TEST_PACKING_NOT_EXP_TRIGGER_READ_TRIGGER:
+ ret = prepare_request_add_read(td);
+ if (ret)
+ goto exit;
+
+ ret = prepare_request_add_write_reqs(td, test_packed_trigger,
+ is_err_expected, is_random);
+ if (ret)
+ goto exit;
+
+ mbtd->exp_packed_stats.packing_events[num_packed_reqs] = 1;
+ break;
+ case TEST_PACKING_NOT_EXP_TRIGGER_FLUSH_TRIGGER:
+ ret = prepare_request_add_flush(td);
+ if (ret)
+ goto exit;
+
+ ret = prepare_request_add_write_reqs(td, test_packed_trigger,
+ is_err_expected, is_random);
+ if (ret)
+ goto exit;
+
+ mbtd->exp_packed_stats.packing_events[num_packed_reqs] = 1;
+ break;
+ case TEST_PACK_MIX_PACKED_NO_PACKED_PACKED:
+ ret = prepare_request_add_read(td);
+ if (ret)
+ goto exit;
+
+ ret = prepare_request_add_write_reqs(td, test_packed_trigger-1,
+ is_err_expected, is_random);
+ if (ret)
+ goto exit;
+
+ ret = prepare_request_add_write_reqs(td, num_requests,
+ is_err_expected, is_random);
+ if (ret)
+ goto exit;
+
+ mbtd->exp_packed_stats.packing_events[num_requests] = 1;
+ mbtd->exp_packed_stats.packing_events[num_requests-1] = 1;
+ mbtd->exp_packed_stats.pack_stop_reason[WRONG_DATA_DIR] = 1;
+ mbtd->exp_packed_stats.pack_stop_reason[EMPTY_QUEUE] = 1;
+ break;
+ case TEST_PACK_MIX_NO_PACKED_PACKED_NO_PACKED:
+ ret = prepare_request_add_read(td);
+ if (ret)
+ goto exit;
+
+ ret = prepare_request_add_write_reqs(td, num_requests,
+ is_err_expected, is_random);
+ if (ret)
+ goto exit;
+
+ ret = prepare_request_add_read(td);
+ if (ret)
+ goto exit;
+
+ ret = prepare_request_add_write_reqs(td, test_packed_trigger-1,
+ is_err_expected, is_random);
+ if (ret)
+ goto exit;
+
+ mbtd->exp_packed_stats.pack_stop_reason[WRONG_DATA_DIR] = 1;
+ mbtd->exp_packed_stats.packing_events[num_packed_reqs] = 1;
+ break;
+ case TEST_PACKING_NOT_EXP_LESS_THAN_TRIGGER_REQUESTS:
+ case TEST_PACKING_NOT_EXP_TRIGGER_REQUESTS:
+ mbtd->exp_packed_stats.packing_events[num_packed_reqs] = 1;
+ break;
+ default:
+ mbtd->exp_packed_stats.pack_stop_reason[EMPTY_QUEUE] = 1;
+ mbtd->exp_packed_stats.packing_events[num_packed_reqs] = 1;
+ }
+ mbtd->num_requests = num_requests;
+
+exit:
+ return ret;
+}
+
+/*
* Prepare requests for the TEST_RET_PARTIAL_FOLLOWED_BY_ABORT testcase.
* In this testcase we have mixed error expectations from different
* write requests, hence the special prepare function.
@@ -848,13 +1070,14 @@
mmc_blk_init_packed_statistics(mq->card);
- for (i = 1 ; i <= num_requests ; i++) {
+ for (i = 1; i <= num_requests; i++) {
if (i > (num_requests / 2))
is_err_expected = 1;
- start_address = td->start_sector + 4096*td->num_of_write_bios;
+ start_address = td->start_sector + 4096 * td->num_of_write_bios;
ret = test_iosched_add_wr_rd_test_req(is_err_expected, WRITE,
- start_address, (i%5)+1, TEST_PATTERN_5A, NULL);
+ start_address, (i % 5) + 1, TEST_PATTERN_5A,
+ NULL);
if (ret) {
test_pr_err("%s: failed to add a write request",
__func__);
@@ -888,6 +1111,8 @@
int num_requests;
int min_num_requests = 2;
int is_random = mbtd->is_random;
+ int max_for_double;
+ int test_packed_trigger;
req_q = test_iosched_get_req_queue();
if (req_q)
@@ -904,16 +1129,52 @@
max_num_requests = mq->card->ext_csd.max_packed_writes;
num_requests = max_num_requests - 2;
+ test_packed_trigger = mq->num_wr_reqs_to_start_packing;
+
+ /*
+ * Here max_for_double is intended for packed control testcases
+ * in which we issue many write requests. It's purpose is to prevent
+ * exceeding max number of req_queue requests.
+ */
+ max_for_double = max_num_requests - 10;
+
+ if (td->test_info.testcase ==
+ TEST_PACKING_NOT_EXP_LESS_THAN_TRIGGER_REQUESTS)
+ /* Don't expect packing, so issue up to trigger-1 reqs */
+ num_requests = test_packed_trigger - 1;
if (is_random) {
if (td->test_info.testcase ==
TEST_RET_PARTIAL_FOLLOWED_BY_ABORT)
+ /*
+ * Here we don't want num_requests to be less than 1
+ * as a consequence of division by 2.
+ */
min_num_requests = 3;
+ if (td->test_info.testcase ==
+ TEST_PACKING_NOT_EXP_LESS_THAN_TRIGGER_REQUESTS)
+ /* Don't expect packing, so issue up to trigger reqs */
+ max_num_requests = test_packed_trigger;
+
num_requests = pseudo_random_seed(seed, min_num_requests,
max_num_requests - 1);
}
+ if (td->test_info.testcase ==
+ TEST_PACKING_NOT_EXP_LESS_THAN_TRIGGER_REQUESTS)
+ num_requests -= test_packed_trigger;
+
+ if (td->test_info.testcase == TEST_PACKING_EXP_N_OVER_TRIGGER_FLUSH_N)
+ num_requests =
+ num_requests > max_for_double ? max_for_double : num_requests;
+
+ if (mbtd->test_group == TEST_PACKING_CONTROL_GROUP)
+ num_requests += test_packed_trigger;
+
+ if (td->test_info.testcase == TEST_PACKING_NOT_EXP_TRIGGER_REQUESTS)
+ num_requests = test_packed_trigger;
+
return num_requests;
}
@@ -929,6 +1190,7 @@
int num_requests = 0;
int ret = 0;
int is_random = mbtd->is_random;
+ int test_packed_trigger = mq->num_wr_reqs_to_start_packing;
if (!mq) {
test_pr_err("%s: NULL mq", __func__);
@@ -997,6 +1259,33 @@
case TEST_HDR_CMD23_PACKED_BIT_SET:
ret = prepare_packed_requests(td, 1, num_requests, is_random);
break;
+ case TEST_PACKING_EXP_N_OVER_TRIGGER:
+ case TEST_PACKING_EXP_N_OVER_TRIGGER_FB_READ:
+ case TEST_PACKING_NOT_EXP_TRIGGER_REQUESTS:
+ case TEST_PACKING_NOT_EXP_LESS_THAN_TRIGGER_REQUESTS:
+ case TEST_PACK_MIX_PACKED_NO_PACKED_PACKED:
+ case TEST_PACK_MIX_NO_PACKED_PACKED_NO_PACKED:
+ ret = prepare_packed_control_tests_requests(td, 0, num_requests,
+ is_random);
+ break;
+ case TEST_PACKING_EXP_THRESHOLD_OVER_TRIGGER:
+ ret = prepare_packed_control_tests_requests(td, 0,
+ max_num_requests, is_random);
+ break;
+ case TEST_PACKING_EXP_ONE_OVER_TRIGGER_FB_READ:
+ ret = prepare_packed_control_tests_requests(td, 0,
+ test_packed_trigger + 1,
+ is_random);
+ break;
+ case TEST_PACKING_EXP_N_OVER_TRIGGER_FLUSH_N:
+ ret = prepare_packed_control_tests_requests(td, 0, num_requests,
+ is_random);
+ break;
+ case TEST_PACKING_NOT_EXP_TRIGGER_READ_TRIGGER:
+ case TEST_PACKING_NOT_EXP_TRIGGER_FLUSH_TRIGGER:
+ ret = prepare_packed_control_tests_requests(td, 0,
+ test_packed_trigger, is_random);
+ break;
default:
test_pr_info("%s: Invalid test case...", __func__);
return -EINVAL;
@@ -1084,6 +1373,9 @@
/* disable the packing control */
host->caps2 &= ~MMC_CAP2_PACKED_WR_CONTROL;
break;
+ case TEST_PACKING_CONTROL_GROUP:
+ host->caps2 |= MMC_CAP2_PACKED_WR_CONTROL;
+ break;
default:
break;
}
@@ -1135,12 +1427,12 @@
mbtd->test_info.get_test_case_str_fn = get_test_case_str;
mbtd->test_info.post_test_fn = post_test;
- for (i = 0 ; i < number ; ++i) {
+ for (i = 0; i < number; ++i) {
test_pr_info("%s: Cycle # %d / %d", __func__, i+1, number);
test_pr_info("%s: ====================", __func__);
- for (j = SEND_WRITE_PACKING_MIN_TESTCASE ;
- j <= SEND_WRITE_PACKING_MAX_TESTCASE ; j++) {
+ for (j = SEND_WRITE_PACKING_MIN_TESTCASE;
+ j <= SEND_WRITE_PACKING_MAX_TESTCASE; j++) {
mbtd->test_info.testcase = j;
mbtd->is_random = RANDOM_TEST;
@@ -1233,7 +1525,7 @@
mbtd->test_info.get_test_case_str_fn = get_test_case_str;
mbtd->test_info.post_test_fn = post_test;
- for (i = 0 ; i < number ; ++i) {
+ for (i = 0; i < number; ++i) {
test_pr_info("%s: Cycle # %d / %d", __func__, i+1, number);
test_pr_info("%s: ====================", __func__);
@@ -1332,7 +1624,7 @@
mbtd->test_info.get_test_case_str_fn = get_test_case_str;
mbtd->test_info.post_test_fn = post_test;
- for (i = 0 ; i < number ; ++i) {
+ for (i = 0; i < number; ++i) {
test_pr_info("%s: Cycle # %d / %d", __func__, i+1, number);
test_pr_info("%s: ====================", __func__);
@@ -1408,12 +1700,123 @@
.read = send_invalid_packed_test_read,
};
+/* packing_control TEST */
+static ssize_t write_packing_control_test_write(struct file *file,
+ const char __user *buf,
+ size_t count,
+ loff_t *ppos)
+{
+ int ret = 0;
+ int i = 0;
+ int number = -1;
+ int j = 0;
+ struct mmc_queue *mq = test_iosched_get_req_queue()->queuedata;
+ int max_num_requests = mq->card->ext_csd.max_packed_writes;
+ int test_successful = 1;
+
+ test_pr_info("%s: -- write_packing_control TEST --", __func__);
+
+ sscanf(buf, "%d", &number);
+
+ if (number <= 0)
+ number = 1;
+
+ test_pr_info("%s: max_num_requests = %d ", __func__,
+ max_num_requests);
+
+ memset(&mbtd->test_info, 0, sizeof(struct test_info));
+ mbtd->test_group = TEST_PACKING_CONTROL_GROUP;
+
+ if (validate_packed_commands_settings())
+ return count;
+
+ mbtd->test_info.data = mbtd;
+ mbtd->test_info.prepare_test_fn = prepare_test;
+ mbtd->test_info.check_test_result_fn = check_wr_packing_statistics;
+ mbtd->test_info.get_test_case_str_fn = get_test_case_str;
+
+ for (i = 0; i < number; ++i) {
+ test_pr_info("%s: Cycle # %d / %d", __func__, i+1, number);
+ test_pr_info("%s: ====================", __func__);
+
+ for (j = PACKING_CONTROL_MIN_TESTCASE;
+ j <= PACKING_CONTROL_MAX_TESTCASE; j++) {
+
+ test_successful = 1;
+ mbtd->test_info.testcase = j;
+ mbtd->is_random = RANDOM_TEST;
+ ret = test_iosched_start_test(&mbtd->test_info);
+ if (ret) {
+ test_successful = 0;
+ break;
+ }
+ /* Allow FS requests to be dispatched */
+ msleep(1000);
+
+ mbtd->test_info.testcase = j;
+ mbtd->is_random = NON_RANDOM_TEST;
+ ret = test_iosched_start_test(&mbtd->test_info);
+ if (ret) {
+ test_successful = 0;
+ break;
+ }
+ /* Allow FS requests to be dispatched */
+ msleep(1000);
+ }
+
+ if (!test_successful)
+ break;
+ }
+
+ test_pr_info("%s: Completed all the test cases.", __func__);
+
+ return count;
+}
+
+static ssize_t write_packing_control_test_read(struct file *file,
+ char __user *buffer,
+ size_t count,
+ loff_t *offset)
+{
+ memset((void *)buffer, 0, count);
+
+ snprintf(buffer, count,
+ "\nwrite_packing_control_test\n"
+ "=========\n"
+ "Description:\n"
+ "This test checks the following scenarios\n"
+ "- Packing expected - one over trigger\n"
+ "- Packing expected - N over trigger\n"
+ "- Packing expected - N over trigger followed by read\n"
+ "- Packing expected - N over trigger followed by flush\n"
+ "- Packing expected - threshold over trigger FB by flush\n"
+ "- Packing not expected - less than trigger\n"
+ "- Packing not expected - trigger requests\n"
+ "- Packing not expected - trigger, read, trigger\n"
+ "- Mixed state - packing -> no packing -> packing\n"
+ "- Mixed state - no packing -> packing -> no packing\n");
+
+ if (message_repeat == 1) {
+ message_repeat = 0;
+ return strnlen(buffer, count);
+ } else {
+ return 0;
+ }
+}
+
+const struct file_operations write_packing_control_test_ops = {
+ .open = test_open,
+ .write = write_packing_control_test_write,
+ .read = write_packing_control_test_read,
+};
+
static void mmc_block_test_debugfs_cleanup(void)
{
debugfs_remove(mbtd->debug.random_test_seed);
debugfs_remove(mbtd->debug.send_write_packing_test);
debugfs_remove(mbtd->debug.err_check_test);
debugfs_remove(mbtd->debug.send_invalid_packed_test);
+ debugfs_remove(mbtd->debug.packing_control_test);
}
static int mmc_block_test_debugfs_init(void)
@@ -1465,6 +1868,16 @@
if (!mbtd->debug.send_invalid_packed_test)
goto err_nomem;
+ mbtd->debug.packing_control_test = debugfs_create_file(
+ "packing_control_test",
+ S_IRUGO | S_IWUGO,
+ tests_root,
+ NULL,
+ &write_packing_control_test_ops);
+
+ if (!mbtd->debug.packing_control_test)
+ goto err_nomem;
+
return 0;
err_nomem:
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index a4af6c9..d1d8358 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -236,6 +236,14 @@
pr_err("%s:msmsdcc_sps_reset_ep(cons) error=%d\n",
mmc_hostname(host->mmc), rc);
+ if (host->sps.reset_device) {
+ rc = sps_device_reset(host->sps.bam_handle);
+ if (rc)
+ pr_err("%s: sps_device_reset error=%d\n",
+ mmc_hostname(host->mmc), rc);
+ host->sps.reset_device = false;
+ }
+
/* Restore all BAM pipes connections */
rc = msmsdcc_sps_restore_ep(host, &host->sps.prod);
if (rc)
@@ -4323,6 +4331,96 @@
}
/**
+ * Handle BAM device's global error condition
+ *
+ * This is an error handler for the SDCC bam device
+ *
+ * This function is registered as a callback with SPS-BAM
+ * driver and will called in case there are an errors for
+ * the SDCC BAM deivce. Any error conditions in the BAM
+ * device are global and will be result in this function
+ * being called once per device.
+ *
+ * This function will be called from the sps driver's
+ * interrupt context.
+ *
+ * @sps_cb_case - indicates what error it is
+ * @user - Pointer to sdcc host structure
+ */
+static void
+msmsdcc_sps_bam_global_irq_cb(enum sps_callback_case sps_cb_case, void *user)
+{
+ struct msmsdcc_host *host = (struct msmsdcc_host *)user;
+ struct mmc_request *mrq;
+ unsigned long flags;
+ int32_t error = 0;
+
+ BUG_ON(!host);
+ BUG_ON(!is_sps_mode(host));
+
+ if (sps_cb_case == SPS_CALLBACK_BAM_ERROR_IRQ) {
+ /**
+ * Reset the all endpoints along with reseting the sps device.
+ */
+ host->sps.pipe_reset_pending = true;
+ host->sps.reset_device = true;
+
+ pr_err("%s: BAM Global ERROR IRQ happened\n",
+ mmc_hostname(host->mmc));
+ error = EAGAIN;
+ } else if (sps_cb_case == SPS_CALLBACK_BAM_HRESP_ERR_IRQ) {
+ /**
+ * This means that there was an AHB access error and
+ * the address we are trying to read/write is something
+ * we dont have priviliges to do so.
+ */
+ pr_err("%s: BAM HRESP_ERR_IRQ happened\n",
+ mmc_hostname(host->mmc));
+ error = EACCES;
+ } else {
+ /**
+ * This should not have happened ideally. If this happens
+ * there is some seriously wrong.
+ */
+ pr_err("%s: BAM global IRQ callback received, type:%d\n",
+ mmc_hostname(host->mmc), (u32) sps_cb_case);
+ error = EIO;
+ }
+
+ spin_lock_irqsave(&host->lock, flags);
+
+ mrq = host->curr.mrq;
+
+ if (mrq && mrq->cmd) {
+ msmsdcc_dump_sdcc_state(host);
+
+ if (!mrq->cmd->error)
+ mrq->cmd->error = -error;
+ if (host->curr.data) {
+ if (mrq->data && !mrq->data->error)
+ mrq->data->error = -error;
+ host->curr.data_xfered = 0;
+ if (host->sps.sg && is_sps_mode(host)) {
+ /* Stop current SPS transfer */
+ msmsdcc_sps_exit_curr_xfer(host);
+ } else {
+ /* this condition should not have happened */
+ pr_err("%s: something is seriously wrong. "\
+ "Funtion: %s, line: %d\n",
+ mmc_hostname(host->mmc),
+ __func__, __LINE__);
+ }
+ } else {
+ /* this condition should not have happened */
+ pr_err("%s: something is seriously wrong. Funtion: "\
+ "%s, line: %d\n", mmc_hostname(host->mmc),
+ __func__, __LINE__);
+ }
+ }
+ spin_unlock_irqrestore(&host->lock, flags);
+}
+
+/**
* Initialize SPS HW connected with SDCC core
*
* This function register BAM HW resources with
@@ -4371,6 +4469,8 @@
/* SPS driver wll handle the SDCC BAM IRQ */
bam.irq = (u32)host->bam_irqres->start;
bam.manage = SPS_BAM_MGR_LOCAL;
+ bam.callback = msmsdcc_sps_bam_global_irq_cb;
+ bam.user = (void *)host;
pr_info("%s: bam physical base=0x%x\n", mmc_hostname(host->mmc),
(u32)bam.phys_addr);
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index baeabd2..655f2b9 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -321,6 +321,7 @@
unsigned int busy;
unsigned int xfer_req_cnt;
bool pipe_reset_pending;
+ bool reset_device;
struct tasklet_struct tlet;
};
diff --git a/drivers/net/usb/rmnet_usb_ctrl.c b/drivers/net/usb/rmnet_usb_ctrl.c
index 2972af0..186d07d 100644
--- a/drivers/net/usb/rmnet_usb_ctrl.c
+++ b/drivers/net/usb/rmnet_usb_ctrl.c
@@ -16,6 +16,7 @@
#include <linux/device.h>
#include <linux/uaccess.h>
#include <linux/termios.h>
+#include <linux/poll.h>
#include <linux/ratelimit.h>
#include <linux/debugfs.h>
#include "rmnet_usb_ctrl.h"
@@ -529,6 +530,28 @@
return 0;
}
+static unsigned int rmnet_ctl_poll(struct file *file, poll_table *wait)
+{
+ unsigned int mask = 0;
+ struct rmnet_ctrl_dev *dev;
+
+ dev = file->private_data;
+ if (!dev)
+ return POLLERR;
+
+ poll_wait(file, &dev->read_wait_queue, wait);
+ if (!is_dev_connected(dev)) {
+ dev_dbg(dev->devicep, "%s: Device not connected\n",
+ __func__);
+ return POLLERR;
+ }
+
+ if (!list_empty(&dev->rx_list))
+ mask |= POLLIN | POLLRDNORM;
+
+ return mask;
+}
+
static ssize_t rmnet_ctl_read(struct file *file, char __user *buf, size_t count,
loff_t *ppos)
{
@@ -722,6 +745,7 @@
.unlocked_ioctl = rmnet_ctrl_ioctl,
.open = rmnet_ctl_open,
.release = rmnet_ctl_release,
+ .poll = rmnet_ctl_poll,
};
int rmnet_usb_ctrl_probe(struct usb_interface *intf,
diff --git a/drivers/net/usb/rmnet_usb_data.c b/drivers/net/usb/rmnet_usb_data.c
index 55020a1..eb57693 100644
--- a/drivers/net/usb/rmnet_usb_data.c
+++ b/drivers/net/usb/rmnet_usb_data.c
@@ -558,6 +558,8 @@
udev = unet->udev;
+ usb_enable_autosuspend(udev);
+
/* allow modem to wake up suspended system */
device_set_wakeup_enable(&udev->dev, 1);
diff --git a/drivers/platform/msm/sps/sps.c b/drivers/platform/msm/sps/sps.c
index 1329f6c..0371f5a 100644
--- a/drivers/platform/msm/sps/sps.c
+++ b/drivers/platform/msm/sps/sps.c
@@ -2028,30 +2028,30 @@
goto device_create_err;
}
- if (!d_type) {
- sps->dfab_clk = clk_get(sps->dev, "dfab_clk");
- if (IS_ERR(sps->dfab_clk)) {
- SPS_ERR("sps:fail to get dfab_clk.");
+ sps->dfab_clk = clk_get(sps->dev, "dfab_clk");
+ if (IS_ERR(sps->dfab_clk)) {
+ SPS_ERR("sps:fail to get dfab_clk.");
+ goto clk_err;
+ } else {
+ ret = clk_set_rate(sps->dfab_clk, 64000000);
+ if (ret) {
+ SPS_ERR("sps:failed to set dfab_clk rate.");
+ clk_put(sps->dfab_clk);
goto clk_err;
- } else {
- ret = clk_set_rate(sps->dfab_clk, 64000000);
- if (ret) {
- SPS_ERR("sps:failed to set dfab_clk rate.");
- clk_put(sps->dfab_clk);
- goto clk_err;
- }
}
}
- sps->pmem_clk = clk_get(sps->dev, "mem_clk");
- if (IS_ERR(sps->pmem_clk)) {
- SPS_ERR("sps:fail to get pmem_clk.");
- goto clk_err;
- } else {
- ret = clk_prepare_enable(sps->pmem_clk);
- if (ret) {
- SPS_ERR("sps:failed to enable pmem_clk. ret=%d", ret);
+ if (!d_type) {
+ sps->pmem_clk = clk_get(sps->dev, "mem_clk");
+ if (IS_ERR(sps->pmem_clk)) {
+ SPS_ERR("sps:fail to get pmem_clk.");
goto clk_err;
+ } else {
+ ret = clk_prepare_enable(sps->pmem_clk);
+ if (ret) {
+ SPS_ERR("sps:failed to enable pmem_clk.");
+ goto clk_err;
+ }
}
}
@@ -2068,26 +2068,22 @@
}
}
- if (!d_type) {
- ret = clk_prepare_enable(sps->dfab_clk);
- if (ret) {
- SPS_ERR("sps:failed to enable dfab_clk. ret=%d", ret);
- goto clk_err;
- }
+ ret = clk_prepare_enable(sps->dfab_clk);
+ if (ret) {
+ SPS_ERR("sps:failed to enable dfab_clk. ret=%d", ret);
+ goto clk_err;
}
#endif
ret = sps_device_init();
if (ret) {
SPS_ERR("sps:sps_device_init err.");
#ifdef CONFIG_SPS_SUPPORT_BAMDMA
- if (!d_type)
- clk_disable_unprepare(sps->dfab_clk);
+ clk_disable_unprepare(sps->dfab_clk);
#endif
goto sps_device_init_err;
}
#ifdef CONFIG_SPS_SUPPORT_BAMDMA
- if (!d_type)
- clk_disable_unprepare(sps->dfab_clk);
+ clk_disable_unprepare(sps->dfab_clk);
#endif
sps->is_ready = true;
@@ -2114,9 +2110,9 @@
class_destroy(sps->dev_class);
sps_device_de_init();
+ clk_put(sps->dfab_clk);
if (!d_type)
- clk_put(sps->dfab_clk);
- clk_put(sps->pmem_clk);
+ clk_put(sps->pmem_clk);
clk_put(sps->bamdma_clk);
return 0;
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 7cb4a51..57cde45 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -2348,9 +2348,12 @@
{
struct regulator_dev *rdev = regulator->rdev;
struct regulator *consumer;
- int ret, output_uV, input_uV, total_uA_load = 0;
+ int ret, output_uV, input_uV = 0, total_uA_load = 0;
unsigned int mode;
+ if (rdev->supply)
+ input_uV = regulator_get_voltage(rdev->supply);
+
mutex_lock(&rdev->mutex);
/*
@@ -2380,10 +2383,7 @@
goto out;
}
- /* get input voltage */
- input_uV = 0;
- if (rdev->supply)
- input_uV = regulator_get_voltage(rdev->supply);
+ /* No supply? Use constraint voltage */
if (input_uV <= 0)
input_uV = rdev->constraints->input_uV;
if (input_uV <= 0) {
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index fc0d02a..1849118 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -1169,4 +1169,13 @@
This driver can also be built as a module. If so, the module
will be called rtc-ls1x.
+config RTC_DRV_QPNP
+ tristate "Qualcomm QPNP PMIC RTC"
+ depends on SPMI && OF_SPMI && MSM_QPNP_INT
+ help
+ Say Y here if you want to support the Qualcomm QPNP PMIC RTC.
+
+ To compile this driver as a module, choose M here: the
+ module will be called qpnp-rtc.
+
endif # RTC_CLASS
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 8a3cecd..295f927 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -88,6 +88,7 @@
obj-$(CONFIG_RTC_DRV_PS3) += rtc-ps3.o
obj-$(CONFIG_RTC_DRV_PUV3) += rtc-puv3.o
obj-$(CONFIG_RTC_DRV_PXA) += rtc-pxa.o
+obj-$(CONFIG_RTC_DRV_QPNP) += qpnp-rtc.o
obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o
obj-$(CONFIG_RTC_DRV_RP5C01) += rtc-rp5c01.o
obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o
diff --git a/drivers/rtc/qpnp-rtc.c b/drivers/rtc/qpnp-rtc.c
new file mode 100644
index 0000000..5650e74
--- /dev/null
+++ b/drivers/rtc/qpnp-rtc.c
@@ -0,0 +1,641 @@
+/* Copyright (c) 2012, 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.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/rtc.h>
+#include <linux/pm.h>
+#include <linux/slab.h>
+#include <linux/idr.h>
+#include <linux/of_device.h>
+#include <linux/spmi.h>
+#include <linux/spinlock.h>
+#include <linux/spmi.h>
+
+/* RTC/ALARM Register offsets */
+#define REG_OFFSET_ALARM_RW 0x40
+#define REG_OFFSET_ALARM_CTRL1 0x46
+#define REG_OFFSET_ALARM_CTRL2 0x48
+#define REG_OFFSET_RTC_WRITE 0x40
+#define REG_OFFSET_RTC_CTRL 0x46
+#define REG_OFFSET_RTC_READ 0x48
+#define REG_OFFSET_PERP_SUBTYPE 0x05
+
+/* RTC_CTRL register bit fields */
+#define BIT_RTC_ENABLE BIT(7)
+#define BIT_RTC_ALARM_ENABLE BIT(7)
+#define BIT_RTC_ABORT_ENABLE BIT(0)
+#define BIT_RTC_ALARM_CLEAR BIT(0)
+
+/* RTC/ALARM peripheral subtype values */
+#define RTC_PERPH_SUBTYPE 0x1
+#define ALARM_PERPH_SUBTYPE 0x3
+
+#define NUM_8_BIT_RTC_REGS 0x4
+
+#define TO_SECS(arr) (arr[0] | (arr[1] << 8) | (arr[2] << 16) | \
+ (arr[3] << 24))
+
+/* rtc driver internal structure */
+struct qpnp_rtc {
+ u8 rtc_ctrl_reg;
+ u8 alarm_ctrl_reg1;
+ u16 rtc_base;
+ u16 alarm_base;
+ u32 rtc_write_enable;
+ u32 rtc_alarm_powerup;
+ int rtc_alarm_irq;
+ struct device *rtc_dev;
+ struct rtc_device *rtc;
+ struct spmi_device *spmi;
+ spinlock_t alarm_ctrl_lock;
+};
+
+static int qpnp_read_wrapper(struct qpnp_rtc *rtc_dd, u8 *rtc_val,
+ u16 base, int count)
+{
+ int rc;
+ struct spmi_device *spmi = rtc_dd->spmi;
+
+ rc = spmi_ext_register_readl(spmi->ctrl, spmi->sid, base, rtc_val,
+ count);
+ if (rc) {
+ dev_err(rtc_dd->rtc_dev, "SPMI read failed\n");
+ return rc;
+ }
+ return 0;
+}
+
+static int qpnp_write_wrapper(struct qpnp_rtc *rtc_dd, u8 *rtc_val,
+ u16 base, int count)
+{
+ int rc;
+ struct spmi_device *spmi = rtc_dd->spmi;
+
+ rc = spmi_ext_register_writel(spmi->ctrl, spmi->sid, base, rtc_val,
+ count);
+ if (rc) {
+ dev_err(rtc_dd->rtc_dev, "SPMI write failed\n");
+ return rc;
+ }
+
+ return 0;
+}
+
+static int
+qpnp_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ int rc;
+ unsigned long secs, irq_flags;
+ u8 value[4], reg = 0, alarm_enabled = 0, ctrl_reg;
+ struct qpnp_rtc *rtc_dd = dev_get_drvdata(dev);
+
+ rtc_tm_to_time(tm, &secs);
+
+ value[0] = secs & 0xFF;
+ value[1] = (secs >> 8) & 0xFF;
+ value[2] = (secs >> 16) & 0xFF;
+ value[3] = (secs >> 24) & 0xFF;
+
+ dev_dbg(dev, "Seconds value to be written to RTC = %lu\n", secs);
+
+ spin_lock_irqsave(&rtc_dd->alarm_ctrl_lock, irq_flags);
+ ctrl_reg = rtc_dd->alarm_ctrl_reg1;
+
+ if (ctrl_reg & BIT_RTC_ALARM_ENABLE) {
+ alarm_enabled = 1;
+ ctrl_reg &= ~BIT_RTC_ALARM_ENABLE;
+ rc = qpnp_write_wrapper(rtc_dd, &ctrl_reg,
+ rtc_dd->alarm_base + REG_OFFSET_ALARM_CTRL1, 1);
+ if (rc) {
+ dev_err(dev, "Write to ALARM ctrl reg failed\n");
+ goto rtc_rw_fail;
+ }
+ } else
+ spin_unlock_irqrestore(&rtc_dd->alarm_ctrl_lock, irq_flags);
+
+ /*
+ * 32 bit seconds value is coverted to four 8 bit values
+ * |<------ 32 bit time value in seconds ------>|
+ * <- 8 bit ->|<- 8 bit ->|<- 8 bit ->|<- 8 bit ->|
+ * ----------------------------------------------
+ * | BYTE[3] | BYTE[2] | BYTE[1] | BYTE[0] |
+ * ----------------------------------------------
+ *
+ * RTC has four 8 bit registers for writting time in seconds:
+ * WDATA[3], WDATA[2], WDATA[1], WDATA[0]
+ *
+ * Write to the RTC registers should be done in following order
+ * Clear WDATA[0] register
+ *
+ * Write BYTE[1], BYTE[2] and BYTE[3] of time to
+ * RTC WDATA[3], WDATA[2], WDATA[1] registers
+ *
+ * Write BYTE[0] of time to RTC WDATA[0] register
+ *
+ * Clearing BYTE[0] and writting in the end will prevent any
+ * unintentional overflow from WDATA[0] to higher bytes during the
+ * write operation
+ */
+
+ /* Clear WDATA[0] */
+ reg = 0x0;
+ rc = qpnp_write_wrapper(rtc_dd, ®,
+ rtc_dd->rtc_base + REG_OFFSET_RTC_WRITE, 1);
+ if (rc) {
+ dev_err(dev, "Write to RTC reg failed\n");
+ goto rtc_rw_fail;
+ }
+
+ /* Write to WDATA[3], WDATA[2] and WDATA[1] */
+ rc = qpnp_write_wrapper(rtc_dd, &value[1],
+ rtc_dd->rtc_base + REG_OFFSET_RTC_WRITE + 1, 3);
+ if (rc) {
+ dev_err(dev, "Write to RTC reg failed\n");
+ goto rtc_rw_fail;
+ }
+
+ /* Write to WDATA[0] */
+ rc = qpnp_write_wrapper(rtc_dd, value,
+ rtc_dd->rtc_base + REG_OFFSET_RTC_WRITE, 1);
+ if (rc) {
+ dev_err(dev, "Write to RTC reg failed\n");
+ goto rtc_rw_fail;
+ }
+
+ if (alarm_enabled) {
+ ctrl_reg |= BIT_RTC_ALARM_ENABLE;
+ rc = qpnp_write_wrapper(rtc_dd, &ctrl_reg,
+ rtc_dd->alarm_base + REG_OFFSET_ALARM_CTRL1, 1);
+ if (rc) {
+ dev_err(dev, "Write to ALARM ctrl reg failed\n");
+ goto rtc_rw_fail;
+ }
+ }
+
+ rtc_dd->alarm_ctrl_reg1 = ctrl_reg;
+
+rtc_rw_fail:
+ if (alarm_enabled)
+ spin_unlock_irqrestore(&rtc_dd->alarm_ctrl_lock, irq_flags);
+
+ return rc;
+}
+
+static int
+qpnp_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ int rc;
+ u8 value[4], reg;
+ unsigned long secs;
+ struct qpnp_rtc *rtc_dd = dev_get_drvdata(dev);
+
+ rc = qpnp_read_wrapper(rtc_dd, value,
+ rtc_dd->rtc_base + REG_OFFSET_RTC_READ,
+ NUM_8_BIT_RTC_REGS);
+ if (rc) {
+ dev_err(dev, "Read from RTC reg failed\n");
+ return rc;
+ }
+
+ /*
+ * Read the LSB again and check if there has been a carry over
+ * If there is, redo the read operation
+ */
+ rc = qpnp_read_wrapper(rtc_dd, ®,
+ rtc_dd->rtc_base + REG_OFFSET_RTC_READ, 1);
+ if (rc) {
+ dev_err(dev, "Read from RTC reg failed\n");
+ return rc;
+ }
+
+ if (reg < value[0]) {
+ rc = qpnp_read_wrapper(rtc_dd, value,
+ rtc_dd->rtc_base + REG_OFFSET_RTC_READ,
+ NUM_8_BIT_RTC_REGS);
+ if (rc) {
+ dev_err(dev, "Read from RTC reg failed\n");
+ return rc;
+ }
+ }
+
+ secs = TO_SECS(value);
+
+ rtc_time_to_tm(secs, tm);
+
+ rc = rtc_valid_tm(tm);
+ if (rc) {
+ dev_err(dev, "Invalid time read from RTC\n");
+ return rc;
+ }
+
+ dev_dbg(dev, "secs = %lu, h:m:s == %d:%d:%d, d/m/y = %d/%d/%d\n",
+ secs, tm->tm_hour, tm->tm_min, tm->tm_sec,
+ tm->tm_mday, tm->tm_mon, tm->tm_year);
+
+ return 0;
+}
+
+static int
+qpnp_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+ int rc;
+ u8 value[4], ctrl_reg;
+ unsigned long secs, secs_rtc, irq_flags;
+ struct qpnp_rtc *rtc_dd = dev_get_drvdata(dev);
+ struct rtc_time rtc_tm;
+
+ rtc_tm_to_time(&alarm->time, &secs);
+
+ /*
+ * Read the current RTC time and verify if the alarm time is in the
+ * past. If yes, return invalid
+ */
+ rc = qpnp_rtc_read_time(dev, &rtc_tm);
+ if (rc) {
+ dev_err(dev, "Unable to read RTC time\n");
+ return -EINVAL;
+ }
+
+ rtc_tm_to_time(&rtc_tm, &secs_rtc);
+ if (secs < secs_rtc) {
+ dev_err(dev, "Trying to set alarm in the past\n");
+ return -EINVAL;
+ }
+
+ value[0] = secs & 0xFF;
+ value[1] = (secs >> 8) & 0xFF;
+ value[2] = (secs >> 16) & 0xFF;
+ value[3] = (secs >> 24) & 0xFF;
+
+ spin_lock_irqsave(&rtc_dd->alarm_ctrl_lock, irq_flags);
+
+ rc = qpnp_write_wrapper(rtc_dd, value,
+ rtc_dd->alarm_base + REG_OFFSET_ALARM_RW,
+ NUM_8_BIT_RTC_REGS);
+ if (rc) {
+ dev_err(dev, "Write to ALARM reg failed\n");
+ goto rtc_rw_fail;
+ }
+
+ ctrl_reg = (alarm->enabled) ?
+ (rtc_dd->alarm_ctrl_reg1 | BIT_RTC_ALARM_ENABLE) :
+ (rtc_dd->alarm_ctrl_reg1 & ~BIT_RTC_ALARM_ENABLE);
+
+ rc = qpnp_write_wrapper(rtc_dd, &ctrl_reg,
+ rtc_dd->alarm_base + REG_OFFSET_ALARM_CTRL1, 1);
+ if (rc) {
+ dev_err(dev, "Write to ALARM cntrol reg failed\n");
+ goto rtc_rw_fail;
+ }
+
+ rtc_dd->alarm_ctrl_reg1 = ctrl_reg;
+
+ dev_dbg(dev, "Alarm Set for h:r:s=%d:%d:%d, d/m/y=%d/%d/%d\n",
+ alarm->time.tm_hour, alarm->time.tm_min,
+ alarm->time.tm_sec, alarm->time.tm_mday,
+ alarm->time.tm_mon, alarm->time.tm_year);
+rtc_rw_fail:
+ spin_unlock_irqrestore(&rtc_dd->alarm_ctrl_lock, irq_flags);
+ return rc;
+}
+
+static int
+qpnp_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+ int rc;
+ u8 value[4];
+ unsigned long secs;
+ struct qpnp_rtc *rtc_dd = dev_get_drvdata(dev);
+
+ rc = qpnp_read_wrapper(rtc_dd, value,
+ rtc_dd->alarm_base + REG_OFFSET_ALARM_RW,
+ NUM_8_BIT_RTC_REGS);
+ if (rc) {
+ dev_err(dev, "Read from ALARM reg failed\n");
+ return rc;
+ }
+
+ secs = TO_SECS(value);
+ rtc_time_to_tm(secs, &alarm->time);
+
+ rc = rtc_valid_tm(&alarm->time);
+ if (rc) {
+ dev_err(dev, "Invalid time read from RTC\n");
+ return rc;
+ }
+
+ dev_dbg(dev, "Alarm set for - h:r:s=%d:%d:%d, d/m/y=%d/%d/%d\n",
+ alarm->time.tm_hour, alarm->time.tm_min,
+ alarm->time.tm_sec, alarm->time.tm_mday,
+ alarm->time.tm_mon, alarm->time.tm_year);
+
+ return 0;
+}
+
+
+static int
+qpnp_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+ int rc;
+ unsigned long irq_flags;
+ struct qpnp_rtc *rtc_dd = dev_get_drvdata(dev);
+ u8 ctrl_reg;
+
+ spin_lock_irqsave(&rtc_dd->alarm_ctrl_lock, irq_flags);
+ ctrl_reg = rtc_dd->alarm_ctrl_reg1;
+ ctrl_reg = enabled ? (ctrl_reg | BIT_RTC_ALARM_ENABLE) :
+ (ctrl_reg & ~BIT_RTC_ALARM_ENABLE);
+
+ rc = qpnp_write_wrapper(rtc_dd, &ctrl_reg,
+ rtc_dd->alarm_base + REG_OFFSET_ALARM_CTRL1, 1);
+ if (rc) {
+ dev_err(dev, "Write to ALARM control reg failed\n");
+ goto rtc_rw_fail;
+ }
+
+ rtc_dd->alarm_ctrl_reg1 = ctrl_reg;
+
+rtc_rw_fail:
+ spin_unlock_irqrestore(&rtc_dd->alarm_ctrl_lock, irq_flags);
+ return rc;
+}
+
+static struct rtc_class_ops qpnp_rtc_ops = {
+ .read_time = qpnp_rtc_read_time,
+ .set_alarm = qpnp_rtc_set_alarm,
+ .read_alarm = qpnp_rtc_read_alarm,
+ .alarm_irq_enable = qpnp_rtc_alarm_irq_enable,
+};
+
+static irqreturn_t qpnp_alarm_trigger(int irq, void *dev_id)
+{
+ struct qpnp_rtc *rtc_dd = dev_id;
+ u8 ctrl_reg;
+ int rc;
+ unsigned long irq_flags;
+
+ rtc_update_irq(rtc_dd->rtc, 1, RTC_IRQF | RTC_AF);
+
+ spin_lock_irqsave(&rtc_dd->alarm_ctrl_lock, irq_flags);
+
+ /* Clear the alarm enable bit */
+ ctrl_reg = rtc_dd->alarm_ctrl_reg1;
+ ctrl_reg &= ~BIT_RTC_ALARM_ENABLE;
+
+ rc = qpnp_write_wrapper(rtc_dd, &ctrl_reg,
+ rtc_dd->alarm_base + REG_OFFSET_ALARM_CTRL1, 1);
+ if (rc) {
+ spin_unlock_irqrestore(&rtc_dd->alarm_ctrl_lock, irq_flags);
+ dev_err(rtc_dd->rtc_dev,
+ "Write to ALARM control reg failed\n");
+ goto rtc_alarm_handled;
+ }
+
+ rtc_dd->alarm_ctrl_reg1 = ctrl_reg;
+ spin_unlock_irqrestore(&rtc_dd->alarm_ctrl_lock, irq_flags);
+
+ /* Set ALARM_CLR bit */
+ ctrl_reg = 0x1;
+ rc = qpnp_write_wrapper(rtc_dd, &ctrl_reg,
+ rtc_dd->alarm_base + REG_OFFSET_ALARM_CTRL2, 1);
+ if (rc)
+ dev_err(rtc_dd->rtc_dev,
+ "Write to ALARM control reg failed\n");
+
+rtc_alarm_handled:
+ return IRQ_HANDLED;
+}
+
+static int __devinit qpnp_rtc_probe(struct spmi_device *spmi)
+{
+ int rc;
+ u8 subtype;
+ struct qpnp_rtc *rtc_dd;
+ struct resource *resource;
+ struct spmi_resource *spmi_resource;
+
+ rtc_dd = devm_kzalloc(&spmi->dev, sizeof(*rtc_dd), GFP_KERNEL);
+ if (rtc_dd == NULL) {
+ dev_err(&spmi->dev, "Unable to allocate memory!\n");
+ return -ENOMEM;
+ }
+
+ /* Get the rtc write property */
+ rc = of_property_read_u32(spmi->dev.of_node, "qcom,qpnp-rtc-write",
+ &rtc_dd->rtc_write_enable);
+ if (rc && rc != -EINVAL) {
+ dev_err(&spmi->dev,
+ "Error reading rtc_write_enable property %d\n", rc);
+ return rc;
+ }
+
+ rc = of_property_read_u32(spmi->dev.of_node,
+ "qcom,qpnp-rtc-alarm-pwrup",
+ &rtc_dd->rtc_alarm_powerup);
+ if (rc && rc != -EINVAL) {
+ dev_err(&spmi->dev,
+ "Error reading rtc_alarm_powerup property %d\n", rc);
+ return rc;
+ }
+
+ /* Initialise spinlock to protect RTC control register */
+ spin_lock_init(&rtc_dd->alarm_ctrl_lock);
+
+ rtc_dd->rtc_dev = &(spmi->dev);
+ rtc_dd->spmi = spmi;
+
+ /* Get RTC/ALARM resources */
+ spmi_for_each_container_dev(spmi_resource, spmi) {
+ if (!spmi_resource) {
+ dev_err(&spmi->dev,
+ "%s: rtc_alarm: spmi resource absent!\n",
+ __func__);
+ rc = -ENXIO;
+ goto fail_rtc_enable;
+ }
+
+ resource = spmi_get_resource(spmi, spmi_resource,
+ IORESOURCE_MEM, 0);
+ if (!(resource && resource->start)) {
+ dev_err(&spmi->dev,
+ "%s: node %s IO resource absent!\n",
+ __func__, spmi->dev.of_node->full_name);
+ rc = -ENXIO;
+ goto fail_rtc_enable;
+ }
+
+ rc = qpnp_read_wrapper(rtc_dd, &subtype,
+ resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
+ if (rc) {
+ dev_err(&spmi->dev,
+ "Peripheral subtype read failed\n");
+ goto fail_rtc_enable;
+ }
+
+ switch (subtype) {
+ case RTC_PERPH_SUBTYPE:
+ rtc_dd->rtc_base = resource->start;
+ break;
+ case ALARM_PERPH_SUBTYPE:
+ rtc_dd->alarm_base = resource->start;
+ rtc_dd->rtc_alarm_irq =
+ spmi_get_irq(spmi, spmi_resource, 0);
+ if (rtc_dd->rtc_alarm_irq < 0) {
+ dev_err(&spmi->dev, "ALARM IRQ absent\n");
+ rc = -ENXIO;
+ goto fail_rtc_enable;
+ }
+ break;
+ default:
+ dev_err(&spmi->dev, "Invalid peripheral subtype\n");
+ rc = -EINVAL;
+ goto fail_rtc_enable;
+ }
+ }
+
+ rtc_dd->rtc_ctrl_reg = BIT_RTC_ENABLE;
+ rc = qpnp_write_wrapper(rtc_dd, &rtc_dd->rtc_ctrl_reg,
+ rtc_dd->rtc_base + REG_OFFSET_RTC_CTRL, 1);
+ if (rc) {
+ dev_err(&spmi->dev,
+ "Write to RTC control reg failed\n");
+ goto fail_rtc_enable;
+ }
+
+ /* Enable abort enable feature */
+ rtc_dd->alarm_ctrl_reg1 = BIT_RTC_ABORT_ENABLE;
+ rc = qpnp_write_wrapper(rtc_dd, &rtc_dd->alarm_ctrl_reg1,
+ rtc_dd->alarm_base + REG_OFFSET_ALARM_CTRL1, 1);
+ if (rc) {
+ dev_err(&spmi->dev, "SPMI write failed!\n");
+ goto fail_rtc_enable;
+ }
+
+ if (rtc_dd->rtc_write_enable == true)
+ qpnp_rtc_ops.set_time = qpnp_rtc_set_time;
+
+ dev_set_drvdata(&spmi->dev, rtc_dd);
+
+ /* Register the RTC device */
+ rtc_dd->rtc = rtc_device_register("qpnp_rtc", &spmi->dev,
+ &qpnp_rtc_ops, THIS_MODULE);
+ if (IS_ERR(rtc_dd->rtc)) {
+ dev_err(&spmi->dev, "%s: RTC registration failed (%ld)\n",
+ __func__, PTR_ERR(rtc_dd->rtc));
+ rc = PTR_ERR(rtc_dd->rtc);
+ goto fail_rtc_enable;
+ }
+
+ /* Request the alarm IRQ */
+ rc = request_any_context_irq(rtc_dd->rtc_alarm_irq,
+ qpnp_alarm_trigger, IRQF_TRIGGER_RISING,
+ "qpnp_rtc_alarm", rtc_dd);
+ if (rc) {
+ dev_err(&spmi->dev, "Request IRQ failed (%d)\n", rc);
+ goto fail_req_irq;
+ }
+
+ device_init_wakeup(&spmi->dev, 1);
+ enable_irq_wake(rtc_dd->rtc_alarm_irq);
+
+ dev_dbg(&spmi->dev, "Probe success !!\n");
+
+ return 0;
+
+fail_req_irq:
+ rtc_device_unregister(rtc_dd->rtc);
+fail_rtc_enable:
+ dev_set_drvdata(&spmi->dev, NULL);
+
+ return rc;
+}
+
+static int __devexit qpnp_rtc_remove(struct spmi_device *spmi)
+{
+ struct qpnp_rtc *rtc_dd = dev_get_drvdata(&spmi->dev);
+
+ device_init_wakeup(&spmi->dev, 0);
+ free_irq(rtc_dd->rtc_alarm_irq, rtc_dd);
+ rtc_device_unregister(rtc_dd->rtc);
+ dev_set_drvdata(&spmi->dev, NULL);
+
+ return 0;
+}
+
+static void qpnp_rtc_shutdown(struct spmi_device *spmi)
+{
+ u8 value[4] = {0};
+ u8 reg;
+ int rc;
+ unsigned long irq_flags;
+ struct qpnp_rtc *rtc_dd = dev_get_drvdata(&spmi->dev);
+ bool rtc_alarm_powerup = rtc_dd->rtc_alarm_powerup;
+
+ if (!rtc_alarm_powerup) {
+ spin_lock_irqsave(&rtc_dd->alarm_ctrl_lock, irq_flags);
+ dev_dbg(&spmi->dev, "Disabling alarm interrupts\n");
+
+ /* Disable RTC alarms */
+ reg = rtc_dd->alarm_ctrl_reg1;
+ reg &= ~BIT_RTC_ALARM_ENABLE;
+ rc = qpnp_write_wrapper(rtc_dd, ®,
+ rtc_dd->alarm_base + REG_OFFSET_ALARM_CTRL1, 1);
+ if (rc) {
+ dev_err(rtc_dd->rtc_dev, "SPMI write failed\n");
+ goto fail_alarm_disable;
+ }
+
+ /* Clear Alarm register */
+ rc = qpnp_write_wrapper(rtc_dd, value,
+ rtc_dd->alarm_base + REG_OFFSET_ALARM_RW,
+ NUM_8_BIT_RTC_REGS);
+ if (rc)
+ dev_err(rtc_dd->rtc_dev, "SPMI write failed\n");
+
+fail_alarm_disable:
+ spin_unlock_irqrestore(&rtc_dd->alarm_ctrl_lock, irq_flags);
+ }
+}
+
+static struct of_device_id spmi_match_table[] = {
+ {
+ .compatible = "qcom,qpnp-rtc",
+ },
+ {}
+};
+
+static struct spmi_driver qpnp_rtc_driver = {
+ .probe = qpnp_rtc_probe,
+ .remove = __devexit_p(qpnp_rtc_remove),
+ .shutdown = qpnp_rtc_shutdown,
+ .driver = {
+ .name = "qcom,qpnp-rtc",
+ .owner = THIS_MODULE,
+ .of_match_table = spmi_match_table,
+ },
+};
+
+static int __init qpnp_rtc_init(void)
+{
+ return spmi_driver_register(&qpnp_rtc_driver);
+}
+module_init(qpnp_rtc_init);
+
+static void __exit qpnp_rtc_exit(void)
+{
+ spmi_driver_unregister(&qpnp_rtc_driver);
+}
+module_exit(qpnp_rtc_exit);
+
+MODULE_DESCRIPTION("SMPI PMIC RTC driver");
+MODULE_LICENSE("GPL V2");
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index d99a02a..b2d2f74 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -52,6 +52,16 @@
Also able to set threshold temperature for both hot and cold and update
when a threshold is reached.
+config THERMAL_TSENS8974
+ tristate "Qualcomm 8974 TSENS Temperature driver"
+ depends on THERMAL
+ help
+ This enables the thermal sysfs driver for the TSENS device. It shows
+ up in Sysfs as a thermal zone with multiple trip points. Also able
+ to set threshold temperature for both warm and cool and update
+ thermal userspace client when a threshold is reached. Warm/Cool
+ temperature thresholds can be set independently for each sensor.
+
config THERMAL_PM8XXX
tristate "Qualcomm PMIC PM8xxx Temperature Alarm"
depends on THERMAL
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 275a692..f7e7cc6 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -8,4 +8,5 @@
obj-$(CONFIG_THERMAL_TSENS8960) += msm8960_tsens.o
obj-$(CONFIG_THERMAL_PM8XXX) += pm8xxx-tm.o
obj-$(CONFIG_THERMAL_MONITOR) += msm_thermal.o
-obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o
\ No newline at end of file
+obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o
+obj-$(CONFIG_THERMAL_TSENS8974) += msm8974-tsens.o
diff --git a/drivers/thermal/msm8974-tsens.c b/drivers/thermal/msm8974-tsens.c
new file mode 100644
index 0000000..6628b79
--- /dev/null
+++ b/drivers/thermal/msm8974-tsens.c
@@ -0,0 +1,870 @@
+/* Copyright (c) 2012, 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.
+ *
+ */
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/thermal.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/msm_tsens.h>
+#include <linux/err.h>
+#include <linux/of.h>
+
+#include <mach/msm_iomap.h>
+
+#define TSENS_DRIVER_NAME "msm-tsens"
+/* TSENS register info */
+#define TSENS_UPPER_LOWER_INTERRUPT_CTRL(n) ((n) + 0x1000)
+#define TSENS_INTERRUPT_EN BIT(0)
+
+#define TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR(n) ((n) + 0x1004)
+#define TSENS_UPPER_STATUS_CLR BIT(21)
+#define TSENS_LOWER_STATUS_CLR BIT(20)
+#define TSENS_UPPER_THRESHOLD_MASK 0xffc00
+#define TSENS_LOWER_THRESHOLD_MASK 0x3ff
+#define TSENS_UPPER_THRESHOLD_SHIFT 10
+
+#define TSENS_S0_STATUS_ADDR(n) ((n) + 0x1030)
+#define TSENS_SN_ADDR_OFFSET 0x4
+#define TSENS_SN_STATUS_TEMP_MASK 0x3ff
+#define TSENS_SN_STATUS_LOWER_STATUS BIT(11)
+#define TSENS_SN_STATUS_UPPER_STATUS BIT(12)
+#define TSENS_STATUS_ADDR_OFFSET 2
+
+#define TSENS_TRDY_ADDR(n) ((n) + 0x105c)
+#define TSENS_TRDY_MASK BIT(0)
+
+#define TSENS_CTRL_ADDR(n) (n)
+#define TSENS_SW_RST BIT(1)
+#define TSENS_SN_MIN_MAX_STATUS_CTRL(n) ((n) + 4)
+#define TSENS_GLOBAL_CONFIG(n) ((n) + 0x34)
+#define TSENS_S0_MAIN_CONFIG(n) ((n) + 0x38)
+#define TSENS_SN_REMOTE_CONFIG(n) ((n) + 0x3c)
+
+/* TSENS calibration Mask data */
+#define TSENS_BASE1_MASK 0xff
+#define TSENS0_POINT1_MASK 0x3f00
+#define TSENS1_POINT1_MASK 0xfc000
+#define TSENS2_POINT1_MASK 0x3f00000
+#define TSENS3_POINT1_MASK 0xfc000000
+#define TSENS4_POINT1_MASK 0x3f
+#define TSENS5_POINT1_MASK 0xfc00
+#define TSENS6_POINT1_MASK 0x3f000
+#define TSENS7_POINT1_MASK 0xfc0000
+#define TSENS8_POINT1_MASK 0x3f000000
+#define TSENS9_POINT1_MASK 0x3f
+#define TSENS10_POINT1_MASK 0xfc00
+#define TSENS_CAL_SEL_0_1 0xc0000000
+#define TSENS_CAL_SEL_2 BIT(30)
+#define TSENS_CAL_SEL_SHIFT 30
+#define TSENS_CAL_SEL_SHIFT_2 28
+#define TSENS_ONE_POINT_CALIB 0x3
+#define TSENS_TWO_POINT_CALIB 0x2
+
+#define TSENS_BASE2_MASK 0xff000
+#define TSENS0_POINT2_MASK 0x3f00000
+#define TSENS1_POINT2_MASK 0xfc000000
+#define TSENS2_POINT2_MASK 0x3f
+#define TSENS3_POINT2_MASK 0xfc00
+#define TSENS4_POINT2_MASK 0x3f000
+#define TSENS5_POINT2_MASK 0xfc0000
+#define TSENS6_POINT2_MASK 0x3f000000
+#define TSENS7_POINT2_MASK 0x3f
+#define TSENS8_POINT2_MASK 0xfc00
+#define TSENS9_POINT2_MASK 0x3f000
+#define TSENS10_POINT2_MASK 0xfc0000
+
+#define TSENS_BIT_APPEND 0x3
+#define TSENS_CAL_DEGC_POINT1 30
+#define TSENS_CAL_DEGC_POINT2 120
+#define TSENS_SLOPE_FACTOR 1000
+
+/* TSENS register data */
+#define TSENS_TRDY_RDY_MIN_TIME 2000
+#define TSENS_TRDY_RDY_MAX_TIME 2100
+#define TSENS_THRESHOLD_MAX_CODE 0x3ff
+#define TSENS_THRESHOLD_MIN_CODE 0x0
+
+#define TSENS_CTRL_INIT_DATA1 0x3fffff9
+#define TSENS_GLOBAL_INIT_DATA 0x20013
+#define TSENS_S0_MAIN_CFG_INIT_DATA 0x1ba
+#define TSENS_SN_MIN_MAX_STATUS_CTRL_DATA 0x3ffc00
+#define TSENS_SN_REMOTE_CFG_DATA 0xdba
+
+/* Trips: warm and cool */
+enum tsens_trip_type {
+ TSENS_TRIP_WARM = 0,
+ TSENS_TRIP_COOL,
+ TSENS_TRIP_NUM,
+};
+
+struct tsens_tm_device_sensor {
+ struct thermal_zone_device *tz_dev;
+ enum thermal_device_mode mode;
+ unsigned int sensor_num;
+ struct work_struct work;
+ int offset;
+ int calib_data_point1;
+ int calib_data_point2;
+ uint32_t slope_mul_tsens_factor;
+};
+
+struct tsens_tm_device {
+ struct platform_device *pdev;
+ bool prev_reading_avail;
+ int tsens_factor;
+ uint32_t tsens_num_sensor;
+ int tsens_irq;
+ void *tsens_addr;
+ void *tsens_calib_addr;
+ int tsens_len;
+ int calib_len;
+ struct resource *res_tsens_mem;
+ struct resource *res_calib_mem;
+ struct tsens_tm_device_sensor sensor[0];
+};
+
+struct tsens_tm_device *tmdev;
+
+static int tsens_tz_code_to_degc(int adc_code, int sensor_num)
+{
+ int degcbeforefactor, degc;
+ degcbeforefactor = (adc_code *
+ tmdev->sensor[sensor_num].slope_mul_tsens_factor
+ + tmdev->sensor[sensor_num].offset);
+
+ if (degcbeforefactor == 0)
+ degc = degcbeforefactor;
+ else if (degcbeforefactor > 0)
+ degc = (degcbeforefactor + tmdev->tsens_factor/2)
+ / tmdev->tsens_factor;
+ else
+ degc = (degcbeforefactor - tmdev->tsens_factor/2)
+ / tmdev->tsens_factor;
+ return degc;
+}
+
+static int tsens_tz_degc_to_code(int degc, int sensor_num)
+{
+ int code = (degc * tmdev->tsens_factor -
+ tmdev->sensor[sensor_num].offset
+ + tmdev->sensor[sensor_num].slope_mul_tsens_factor/2)
+ / tmdev->sensor[sensor_num].slope_mul_tsens_factor;
+
+ if (code > TSENS_THRESHOLD_MAX_CODE)
+ code = TSENS_THRESHOLD_MAX_CODE;
+ else if (code < TSENS_THRESHOLD_MIN_CODE)
+ code = TSENS_THRESHOLD_MIN_CODE;
+ return code;
+}
+
+static void msm_tsens_get_temp(int sensor_num, unsigned long *temp)
+{
+ unsigned int code, sensor_addr;
+
+ if (!tmdev->prev_reading_avail) {
+ while (!(readl_relaxed(TSENS_TRDY_ADDR(tmdev->tsens_addr))
+ & TSENS_TRDY_MASK))
+ usleep_range(TSENS_TRDY_RDY_MIN_TIME,
+ TSENS_TRDY_RDY_MAX_TIME);
+ tmdev->prev_reading_avail = true;
+ }
+
+ sensor_addr =
+ (unsigned int)TSENS_S0_STATUS_ADDR(tmdev->tsens_addr);
+ code = readl_relaxed(sensor_addr +
+ (sensor_num << TSENS_STATUS_ADDR_OFFSET));
+ *temp = tsens_tz_code_to_degc((code & TSENS_SN_STATUS_TEMP_MASK),
+ sensor_num);
+}
+
+static int tsens_tz_get_temp(struct thermal_zone_device *thermal,
+ unsigned long *temp)
+{
+ struct tsens_tm_device_sensor *tm_sensor = thermal->devdata;
+
+ if (!tm_sensor || tm_sensor->mode != THERMAL_DEVICE_ENABLED || !temp)
+ return -EINVAL;
+
+ msm_tsens_get_temp(tm_sensor->sensor_num, temp);
+
+ return 0;
+}
+
+int tsens_get_temp(struct tsens_device *device, unsigned long *temp)
+{
+ if (!tmdev)
+ return -ENODEV;
+
+ msm_tsens_get_temp(device->sensor_num, temp);
+
+ return 0;
+}
+EXPORT_SYMBOL(msm_tsens_get_temp);
+
+static int tsens_tz_get_mode(struct thermal_zone_device *thermal,
+ enum thermal_device_mode *mode)
+{
+ struct tsens_tm_device_sensor *tm_sensor = thermal->devdata;
+
+ if (!tm_sensor || !mode)
+ return -EINVAL;
+
+ *mode = tm_sensor->mode;
+
+ return 0;
+}
+
+static int tsens_tz_get_trip_type(struct thermal_zone_device *thermal,
+ int trip, enum thermal_trip_type *type)
+{
+ struct tsens_tm_device_sensor *tm_sensor = thermal->devdata;
+
+ if (!tm_sensor || trip < 0 || !type)
+ return -EINVAL;
+
+ switch (trip) {
+ case TSENS_TRIP_WARM:
+ *type = THERMAL_TRIP_CONFIGURABLE_HI;
+ break;
+ case TSENS_TRIP_COOL:
+ *type = THERMAL_TRIP_CONFIGURABLE_LOW;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int tsens_tz_activate_trip_type(struct thermal_zone_device *thermal,
+ int trip, enum thermal_trip_activation_mode mode)
+{
+ struct tsens_tm_device_sensor *tm_sensor = thermal->devdata;
+ unsigned int reg_cntl, code, hi_code, lo_code, mask;
+
+ if (!tm_sensor || trip < 0)
+ return -EINVAL;
+
+ lo_code = TSENS_THRESHOLD_MIN_CODE;
+ hi_code = TSENS_THRESHOLD_MAX_CODE;
+
+ reg_cntl = readl_relaxed((TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR
+ (tmdev->tsens_addr) +
+ (tm_sensor->sensor_num * 4)));
+ switch (trip) {
+ case TSENS_TRIP_WARM:
+ code = (reg_cntl & TSENS_UPPER_THRESHOLD_MASK)
+ >> TSENS_UPPER_THRESHOLD_SHIFT;
+ mask = TSENS_UPPER_STATUS_CLR;
+
+ if (!(reg_cntl & TSENS_LOWER_STATUS_CLR))
+ lo_code = (reg_cntl & TSENS_LOWER_THRESHOLD_MASK);
+ break;
+ case TSENS_TRIP_COOL:
+ code = (reg_cntl & TSENS_LOWER_THRESHOLD_MASK);
+ mask = TSENS_LOWER_STATUS_CLR;
+
+ if (!(reg_cntl & TSENS_UPPER_STATUS_CLR))
+ hi_code = (reg_cntl & TSENS_UPPER_THRESHOLD_MASK)
+ >> TSENS_UPPER_THRESHOLD_SHIFT;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (mode == THERMAL_TRIP_ACTIVATION_DISABLED)
+ writel_relaxed(reg_cntl | mask,
+ (TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR
+ (tmdev->tsens_addr) +
+ (tm_sensor->sensor_num * 4)));
+ else {
+ if (code < lo_code || code > hi_code) {
+ pr_err("%s with invalid code %x\n", __func__, code);
+ return -EINVAL;
+ }
+ writel_relaxed(reg_cntl & ~mask,
+ (TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR(tmdev->tsens_addr) +
+ (tm_sensor->sensor_num * 4)));
+ }
+ mb();
+ return 0;
+}
+
+static int tsens_tz_get_trip_temp(struct thermal_zone_device *thermal,
+ int trip, unsigned long *temp)
+{
+ struct tsens_tm_device_sensor *tm_sensor = thermal->devdata;
+ unsigned int reg;
+
+ if (!tm_sensor || trip < 0 || !temp)
+ return -EINVAL;
+
+ reg = readl_relaxed(TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR
+ (tmdev->tsens_addr) +
+ (tm_sensor->sensor_num * TSENS_SN_ADDR_OFFSET));
+ switch (trip) {
+ case TSENS_TRIP_WARM:
+ reg = (reg & TSENS_UPPER_THRESHOLD_MASK) >>
+ TSENS_UPPER_THRESHOLD_SHIFT;
+ break;
+ case TSENS_TRIP_COOL:
+ reg = (reg & TSENS_LOWER_THRESHOLD_MASK);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ *temp = tsens_tz_code_to_degc(reg, tm_sensor->sensor_num);
+
+ return 0;
+}
+
+static int tsens_tz_notify(struct thermal_zone_device *thermal,
+ int count, enum thermal_trip_type type)
+{
+ /* TSENS driver does not shutdown the device.
+ All Thermal notification are sent to the
+ thermal daemon to take appropriate action */
+ pr_debug("%s debug\n", __func__);
+ return 1;
+}
+
+static int tsens_tz_set_trip_temp(struct thermal_zone_device *thermal,
+ int trip, long temp)
+{
+ struct tsens_tm_device_sensor *tm_sensor = thermal->devdata;
+ unsigned int reg_cntl;
+ int code, hi_code, lo_code, code_err_chk;
+
+ code_err_chk = code = tsens_tz_degc_to_code(temp,
+ tm_sensor->sensor_num);
+ if (!tm_sensor || trip < 0)
+ return -EINVAL;
+
+ lo_code = TSENS_THRESHOLD_MIN_CODE;
+ hi_code = TSENS_THRESHOLD_MAX_CODE;
+
+ reg_cntl = readl_relaxed(TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR
+ (tmdev->tsens_addr) +
+ (tm_sensor->sensor_num * TSENS_SN_ADDR_OFFSET));
+ switch (trip) {
+ case TSENS_TRIP_WARM:
+ code <<= TSENS_UPPER_THRESHOLD_SHIFT;
+ reg_cntl &= ~TSENS_UPPER_THRESHOLD_MASK;
+ if (!(reg_cntl & TSENS_LOWER_STATUS_CLR))
+ lo_code = (reg_cntl & TSENS_LOWER_THRESHOLD_MASK);
+ break;
+ case TSENS_TRIP_COOL:
+ reg_cntl &= ~TSENS_LOWER_THRESHOLD_MASK;
+ if (!(reg_cntl & TSENS_UPPER_STATUS_CLR))
+ hi_code = (reg_cntl & TSENS_UPPER_THRESHOLD_MASK)
+ >> TSENS_UPPER_THRESHOLD_SHIFT;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (code_err_chk < lo_code || code_err_chk > hi_code)
+ return -EINVAL;
+
+ writel_relaxed(reg_cntl | code, (TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR
+ (tmdev->tsens_addr) +
+ (tm_sensor->sensor_num *
+ TSENS_SN_ADDR_OFFSET)));
+ mb();
+ return 0;
+}
+
+static struct thermal_zone_device_ops tsens_thermal_zone_ops = {
+ .get_temp = tsens_tz_get_temp,
+ .get_mode = tsens_tz_get_mode,
+ .get_trip_type = tsens_tz_get_trip_type,
+ .activate_trip_type = tsens_tz_activate_trip_type,
+ .get_trip_temp = tsens_tz_get_trip_temp,
+ .set_trip_temp = tsens_tz_set_trip_temp,
+ .notify = tsens_tz_notify,
+};
+
+static void notify_uspace_tsens_fn(struct work_struct *work)
+{
+ struct tsens_tm_device_sensor *tm = container_of(work,
+ struct tsens_tm_device_sensor, work);
+
+ sysfs_notify(&tm->tz_dev->device.kobj,
+ NULL, "type");
+}
+
+static irqreturn_t tsens_isr(int irq, void *data)
+{
+ struct tsens_tm_device *tm = data;
+ unsigned int i, status, threshold;
+ unsigned int sensor_status_addr, sensor_status_ctrl_addr;
+
+ sensor_status_addr =
+ (unsigned int)TSENS_S0_STATUS_ADDR(tmdev->tsens_addr);
+ sensor_status_ctrl_addr =
+ (unsigned int)TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR
+ (tmdev->tsens_addr);
+ for (i = 0; i < tmdev->tsens_num_sensor; i++) {
+ bool upper_thr = false, lower_thr = false;
+ status = readl_relaxed(sensor_status_addr);
+ threshold = readl_relaxed(sensor_status_ctrl_addr);
+ if (status & TSENS_SN_STATUS_UPPER_STATUS) {
+ writel_relaxed(threshold | TSENS_UPPER_STATUS_CLR,
+ sensor_status_ctrl_addr);
+ upper_thr = true;
+ }
+ if (status & TSENS_SN_STATUS_LOWER_STATUS) {
+ writel_relaxed(threshold | TSENS_LOWER_STATUS_CLR,
+ sensor_status_ctrl_addr);
+ lower_thr = true;
+ }
+ if (upper_thr || lower_thr) {
+ /* Notify user space */
+ schedule_work(&tm->sensor[i].work);
+ pr_debug("sensor:%d trigger temp (%d degC)\n", i,
+ tsens_tz_code_to_degc((status &
+ TSENS_SN_STATUS_TEMP_MASK), i));
+ }
+ sensor_status_addr += TSENS_SN_ADDR_OFFSET;
+ sensor_status_ctrl_addr += TSENS_SN_ADDR_OFFSET;
+ }
+ mb();
+ return IRQ_HANDLED;
+}
+
+static void tsens_hw_init(void)
+{
+ unsigned int reg_cntl = 0;
+ unsigned int i;
+
+ reg_cntl = readl_relaxed(TSENS_CTRL_ADDR(tmdev->tsens_addr));
+ writel_relaxed(reg_cntl | TSENS_SW_RST,
+ TSENS_CTRL_ADDR(tmdev->tsens_addr));
+ writel_relaxed(TSENS_CTRL_INIT_DATA1,
+ TSENS_CTRL_ADDR(tmdev->tsens_addr));
+ writel_relaxed(TSENS_GLOBAL_INIT_DATA,
+ TSENS_GLOBAL_CONFIG(tmdev->tsens_addr));
+ writel_relaxed(TSENS_S0_MAIN_CFG_INIT_DATA,
+ TSENS_S0_MAIN_CONFIG(tmdev->tsens_addr));
+ for (i = 0; i < tmdev->tsens_num_sensor; i++) {
+ writel_relaxed(TSENS_SN_MIN_MAX_STATUS_CTRL_DATA,
+ TSENS_SN_MIN_MAX_STATUS_CTRL(tmdev->tsens_addr)
+ + (i * TSENS_SN_ADDR_OFFSET));
+ writel_relaxed(TSENS_SN_REMOTE_CFG_DATA,
+ TSENS_SN_REMOTE_CONFIG(tmdev->tsens_addr)
+ + (i * TSENS_SN_ADDR_OFFSET));
+ }
+ writel_relaxed(TSENS_INTERRUPT_EN,
+ TSENS_UPPER_LOWER_INTERRUPT_CTRL(tmdev->tsens_addr));
+}
+
+static int tsens_calib_sensors(void)
+{
+ int i, tsens_base1_data, tsens0_point1, tsens1_point1;
+ int tsens2_point1, tsens3_point1, tsens4_point1, tsens5_point1;
+ int tsens6_point1, tsens7_point1, tsens8_point1, tsens9_point1;
+ int tsens10_point1, tsens0_point2, tsens1_point2, tsens2_point2;
+ int tsens3_point2, tsens4_point2, tsens5_point2, tsens6_point2;
+ int tsens7_point2, tsens8_point2, tsens9_point2, tsens10_point2;
+ int tsens_base2_data, tsens_calibration_mode, temp;
+ uint32_t calib_data[5];
+
+ for (i = 0; i < 5; i++)
+ calib_data[i] = readl_relaxed(tmdev->tsens_calib_addr
+ + (i * TSENS_SN_ADDR_OFFSET));
+
+ tsens_calibration_mode = (calib_data[1] & TSENS_CAL_SEL_0_1
+ >> TSENS_CAL_SEL_SHIFT);
+ temp = (calib_data[3] & TSENS_CAL_SEL_2
+ >> TSENS_CAL_SEL_SHIFT_2);
+ tsens_calibration_mode |= temp;
+ /* Remove this after bringup */
+ tsens_calibration_mode = TSENS_ONE_POINT_CALIB;
+
+ if (!tsens_calibration_mode) {
+ pr_err("TSENS not calibrated\n");
+ return -ENODEV;
+ } else if (tsens_calibration_mode == TSENS_ONE_POINT_CALIB ||
+ TSENS_TWO_POINT_CALIB) {
+ tsens_base1_data = calib_data[0] & TSENS_BASE1_MASK;
+ tsens0_point1 = calib_data[0] & TSENS0_POINT1_MASK;
+ tsens1_point1 = calib_data[0] & TSENS1_POINT1_MASK;
+ tsens2_point1 = calib_data[0] & TSENS2_POINT1_MASK;
+ tsens3_point1 = calib_data[0] & TSENS3_POINT1_MASK;
+ tsens4_point1 = calib_data[1] & TSENS4_POINT1_MASK;
+ tsens5_point1 = calib_data[1] & TSENS5_POINT1_MASK;
+ tsens6_point1 = calib_data[1] & TSENS6_POINT1_MASK;
+ tsens7_point1 = calib_data[1] & TSENS7_POINT1_MASK;
+ tsens8_point1 = calib_data[1] & TSENS8_POINT1_MASK;
+ tsens9_point1 = calib_data[2] & TSENS9_POINT1_MASK;
+ tsens10_point1 = calib_data[2] & TSENS10_POINT1_MASK;
+ } else if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) {
+ tsens_base2_data = calib_data[2] & TSENS_BASE2_MASK;
+ tsens0_point2 = calib_data[2] & TSENS0_POINT2_MASK;
+ tsens1_point2 = calib_data[2] & TSENS1_POINT2_MASK;
+ tsens2_point2 = calib_data[3] & TSENS2_POINT2_MASK;
+ tsens3_point2 = calib_data[3] & TSENS3_POINT2_MASK;
+ tsens4_point2 = calib_data[3] & TSENS4_POINT2_MASK;
+ tsens5_point2 = calib_data[3] & TSENS5_POINT2_MASK;
+ tsens6_point2 = calib_data[3] & TSENS6_POINT2_MASK;
+ tsens7_point2 = calib_data[4] & TSENS7_POINT2_MASK;
+ tsens8_point2 = calib_data[4] & TSENS8_POINT2_MASK;
+ tsens9_point2 = calib_data[4] & TSENS9_POINT2_MASK;
+ tsens10_point2 = calib_data[4] & TSENS10_POINT2_MASK;
+ } else
+ pr_debug("Calibration mode is unknown: %d\n",
+ tsens_calibration_mode);
+
+ tmdev->sensor[0].calib_data_point1 =
+ (((tsens_base1_data + tsens0_point1) << 2) | TSENS_BIT_APPEND);
+ tmdev->sensor[0].calib_data_point2 =
+ (((tsens_base2_data + tsens0_point2) << 2) | TSENS_BIT_APPEND);
+ tmdev->sensor[1].calib_data_point1 =
+ (((tsens_base1_data + tsens1_point1) << 2) | TSENS_BIT_APPEND);
+ tmdev->sensor[1].calib_data_point2 =
+ (((tsens_base2_data + tsens1_point2) << 2) | TSENS_BIT_APPEND);
+ tmdev->sensor[2].calib_data_point1 =
+ (((tsens_base1_data + tsens2_point1) << 2) | TSENS_BIT_APPEND);
+ tmdev->sensor[2].calib_data_point2 =
+ (((tsens_base2_data + tsens2_point2) << 2) | TSENS_BIT_APPEND);
+ tmdev->sensor[3].calib_data_point1 =
+ (((tsens_base1_data + tsens3_point1) << 2) | TSENS_BIT_APPEND);
+ tmdev->sensor[3].calib_data_point2 =
+ (((tsens_base2_data + tsens3_point2) << 2) | TSENS_BIT_APPEND);
+ tmdev->sensor[4].calib_data_point1 =
+ (((tsens_base1_data + tsens4_point1) << 2) | TSENS_BIT_APPEND);
+ tmdev->sensor[4].calib_data_point2 =
+ (((tsens_base2_data + tsens4_point2) << 2) | TSENS_BIT_APPEND);
+ tmdev->sensor[5].calib_data_point1 =
+ (((tsens_base1_data + tsens5_point1) << 2) | TSENS_BIT_APPEND);
+ tmdev->sensor[5].calib_data_point2 =
+ (((tsens_base2_data + tsens5_point2) << 2) | TSENS_BIT_APPEND);
+ tmdev->sensor[6].calib_data_point1 =
+ (((tsens_base1_data + tsens6_point1) << 2) | TSENS_BIT_APPEND);
+ tmdev->sensor[6].calib_data_point2 =
+ (((tsens_base2_data + tsens6_point2) << 2) | TSENS_BIT_APPEND);
+ tmdev->sensor[7].calib_data_point1 =
+ (((tsens_base1_data + tsens7_point1) << 2) | TSENS_BIT_APPEND);
+ tmdev->sensor[7].calib_data_point2 =
+ (((tsens_base2_data + tsens7_point2) << 2) | TSENS_BIT_APPEND);
+ tmdev->sensor[8].calib_data_point1 =
+ (((tsens_base1_data + tsens8_point1) << 2) | TSENS_BIT_APPEND);
+ tmdev->sensor[8].calib_data_point2 =
+ (((tsens_base2_data + tsens8_point2) << 2) | TSENS_BIT_APPEND);
+ tmdev->sensor[9].calib_data_point1 =
+ (((tsens_base1_data + tsens9_point1) << 2) | TSENS_BIT_APPEND);
+ tmdev->sensor[9].calib_data_point2 =
+ (((tsens_base2_data + tsens9_point2) < 2) | TSENS_BIT_APPEND);
+ tmdev->sensor[10].calib_data_point1 =
+ (((tsens_base1_data + tsens10_point1) << 2) | TSENS_BIT_APPEND);
+ tmdev->sensor[10].calib_data_point2 =
+ (((tsens_base2_data + tsens10_point2) << 2) | TSENS_BIT_APPEND);
+
+ for (i = 0; i < tmdev->tsens_num_sensor; i++) {
+ int32_t num = 0, den = 0;
+ num = TSENS_CAL_DEGC_POINT2 - TSENS_CAL_DEGC_POINT2;
+ den = tmdev->sensor[i].calib_data_point2 -
+ tmdev->sensor[i].calib_data_point1;
+ num *= tmdev->tsens_factor;
+ if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB)
+ tmdev->sensor[i].slope_mul_tsens_factor = num/den;
+ tmdev->sensor[i].offset = (TSENS_CAL_DEGC_POINT1 *
+ tmdev->tsens_factor)
+ - (tmdev->sensor[i].calib_data_point1 *
+ tmdev->sensor[i].slope_mul_tsens_factor);
+ INIT_WORK(&tmdev->sensor[i].work, notify_uspace_tsens_fn);
+ tmdev->prev_reading_avail = false;
+ }
+
+ return 0;
+}
+
+static int get_device_tree_data(struct platform_device *pdev)
+{
+ const struct device_node *of_node = pdev->dev.of_node;
+ struct resource *res_mem = NULL;
+ u32 *tsens_slope_data;
+ u32 rc = 0, i, tsens_num_sensors;
+
+ rc = of_property_read_u32(of_node,
+ "qcom,sensors", &tsens_num_sensors);
+ if (rc) {
+ dev_err(&pdev->dev, "missing sensor number\n");
+ return -ENODEV;
+ }
+
+ tsens_slope_data = devm_kzalloc(&pdev->dev,
+ tsens_num_sensors, GFP_KERNEL);
+ if (!tsens_slope_data) {
+ dev_err(&pdev->dev, "can not allocate slope data\n");
+ return -ENOMEM;
+ }
+
+ rc = of_property_read_u32_array(of_node,
+ "qcom,slope", tsens_slope_data, tsens_num_sensors/sizeof(u32));
+ if (rc) {
+ dev_err(&pdev->dev, "invalid or missing property: tsens-slope\n");
+ return rc;
+ };
+
+ tmdev = devm_kzalloc(&pdev->dev,
+ sizeof(struct tsens_tm_device) +
+ tsens_num_sensors *
+ sizeof(struct tsens_tm_device_sensor),
+ GFP_KERNEL);
+ if (tmdev == NULL) {
+ pr_err("%s: kzalloc() failed.\n", __func__);
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < tsens_num_sensors; i++)
+ tmdev->sensor[i].slope_mul_tsens_factor = tsens_slope_data[i];
+ tmdev->tsens_factor = TSENS_SLOPE_FACTOR;
+ tmdev->tsens_num_sensor = tsens_num_sensors;
+
+ tmdev->tsens_irq = platform_get_irq(pdev, 0);
+ if (tmdev->tsens_irq < 0) {
+ pr_err("Invalid get irq\n");
+ return tmdev->tsens_irq;
+ }
+
+ tmdev->res_tsens_mem = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM, "tsens_physical");
+ if (!tmdev->res_tsens_mem) {
+ pr_err("Could not get tsens physical address resource\n");
+ rc = -EINVAL;
+ goto fail_free_irq;
+ }
+
+ tmdev->tsens_len = tmdev->res_tsens_mem->end -
+ tmdev->res_tsens_mem->start + 1;
+
+ res_mem = request_mem_region(tmdev->res_tsens_mem->start,
+ tmdev->tsens_len, tmdev->res_tsens_mem->name);
+ if (!res_mem) {
+ pr_err("Request tsens physical memory region failed\n");
+ rc = -EINVAL;
+ goto fail_free_irq;
+ }
+
+ tmdev->tsens_addr = ioremap(res_mem->start, tmdev->tsens_len);
+ if (!tmdev->tsens_addr) {
+ pr_err("Failed to IO map TSENS registers.\n");
+ rc = -EINVAL;
+ goto fail_unmap_tsens_region;
+ }
+
+ tmdev->res_calib_mem = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM, "tsens_eeprom_physical");
+ if (!tmdev->res_calib_mem) {
+ pr_err("Could not get qfprom physical address resource\n");
+ rc = -EINVAL;
+ goto fail_unmap_tsens;
+ }
+
+ tmdev->calib_len = tmdev->res_calib_mem->end -
+ tmdev->res_calib_mem->start + 1;
+
+ res_mem = request_mem_region(tmdev->res_calib_mem->start,
+ tmdev->calib_len, tmdev->res_calib_mem->name);
+ if (!res_mem) {
+ pr_err("Request calibration memory region failed\n");
+ rc = -EINVAL;
+ goto fail_unmap_tsens;
+ }
+
+ tmdev->tsens_calib_addr = ioremap(res_mem->start,
+ tmdev->calib_len);
+ if (!tmdev->tsens_calib_addr) {
+ pr_err("Failed to IO map EEPROM registers.\n");
+ rc = -EINVAL;
+ goto fail_unmap_calib_region;
+ }
+
+ return 0;
+
+fail_unmap_calib_region:
+ if (tmdev->res_calib_mem)
+ release_mem_region(tmdev->res_calib_mem->start,
+ tmdev->calib_len);
+fail_unmap_tsens:
+ if (tmdev->tsens_addr)
+ iounmap(tmdev->tsens_addr);
+fail_unmap_tsens_region:
+ if (tmdev->res_tsens_mem)
+ release_mem_region(tmdev->res_tsens_mem->start,
+ tmdev->tsens_len);
+fail_free_irq:
+ free_irq(tmdev->tsens_irq, tmdev);
+
+ return rc;
+}
+
+static int __devinit tsens_tm_probe(struct platform_device *pdev)
+{
+ int rc;
+
+ if (tmdev) {
+ pr_err("TSENS device already in use\n");
+ return -EBUSY;
+ }
+
+ if (pdev->dev.of_node)
+ rc = get_device_tree_data(pdev);
+ else
+ return -ENODEV;
+
+ tmdev->pdev = pdev;
+ rc = tsens_calib_sensors();
+ if (rc < 0)
+ goto fail;
+
+ tsens_hw_init();
+ tmdev->prev_reading_avail = true;
+
+ platform_set_drvdata(pdev, tmdev);
+
+ return 0;
+fail:
+ if (tmdev->tsens_calib_addr)
+ iounmap(tmdev->tsens_calib_addr);
+ if (tmdev->res_calib_mem)
+ release_mem_region(tmdev->res_calib_mem->start,
+ tmdev->calib_len);
+ if (tmdev->tsens_addr)
+ iounmap(tmdev->tsens_addr);
+ if (tmdev->res_tsens_mem)
+ release_mem_region(tmdev->res_tsens_mem->start,
+ tmdev->tsens_len);
+ free_irq(tmdev->tsens_irq, tmdev);
+ kfree(tmdev);
+
+ return rc;
+}
+
+static int __devinit _tsens_register_thermal(void)
+{
+ struct platform_device *pdev = tmdev->pdev;
+ int rc, i;
+
+ if (!tmdev) {
+ pr_err("%s: TSENS early init not done\n", __func__);
+ return -ENODEV;
+ }
+
+ for (i = 0; i < tmdev->tsens_num_sensor; i++) {
+ char name[18];
+ snprintf(name, sizeof(name), "tsens_tz_sensor%d", i);
+ tmdev->sensor[i].mode = THERMAL_DEVICE_ENABLED;
+ tmdev->sensor[i].sensor_num = i;
+ tmdev->sensor[i].tz_dev = thermal_zone_device_register(name,
+ TSENS_TRIP_NUM, &tmdev->sensor[i],
+ &tsens_thermal_zone_ops, 0, 0, 0, 0);
+ if (IS_ERR(tmdev->sensor[i].tz_dev)) {
+ pr_err("%s: thermal_zone_device_register() failed.\n",
+ __func__);
+ rc = -ENODEV;
+ goto fail;
+ }
+ }
+ rc = request_irq(tmdev->tsens_irq, tsens_isr,
+ IRQF_TRIGGER_RISING, "tsens_interrupt", tmdev);
+ if (rc < 0) {
+ pr_err("%s: request_irq FAIL: %d\n", __func__, rc);
+ for (i = 0; i < tmdev->tsens_num_sensor; i++)
+ thermal_zone_device_unregister(tmdev->sensor[i].tz_dev);
+ goto fail;
+ }
+ platform_set_drvdata(pdev, tmdev);
+
+ return 0;
+fail:
+ if (tmdev->tsens_calib_addr)
+ iounmap(tmdev->tsens_calib_addr);
+ if (tmdev->res_calib_mem)
+ release_mem_region(tmdev->res_calib_mem->start,
+ tmdev->calib_len);
+ if (tmdev->tsens_addr)
+ iounmap(tmdev->tsens_addr);
+ if (tmdev->res_tsens_mem)
+ release_mem_region(tmdev->res_tsens_mem->start,
+ tmdev->tsens_len);
+ kfree(tmdev);
+
+ return rc;
+}
+
+static int __devexit tsens_tm_remove(struct platform_device *pdev)
+{
+ struct tsens_tm_device *tmdev = platform_get_drvdata(pdev);
+ int i;
+
+ for (i = 0; i < tmdev->tsens_num_sensor; i++)
+ thermal_zone_device_unregister(tmdev->sensor[i].tz_dev);
+ if (tmdev->tsens_calib_addr)
+ iounmap(tmdev->tsens_calib_addr);
+ if (tmdev->res_calib_mem)
+ release_mem_region(tmdev->res_calib_mem->start,
+ tmdev->calib_len);
+ if (tmdev->tsens_addr)
+ iounmap(tmdev->tsens_addr);
+ if (tmdev->res_tsens_mem)
+ release_mem_region(tmdev->res_tsens_mem->start,
+ tmdev->tsens_len);
+ free_irq(tmdev->tsens_irq, tmdev);
+ platform_set_drvdata(pdev, NULL);
+ kfree(tmdev);
+
+ return 0;
+}
+
+static struct of_device_id tsens_match[] = {
+ { .compatible = "qcom,msm-tsens",
+ },
+ {}
+};
+
+static struct platform_driver tsens_tm_driver = {
+ .probe = tsens_tm_probe,
+ .remove = tsens_tm_remove,
+ .driver = {
+ .name = "msm-tsens",
+ .owner = THIS_MODULE,
+ .of_match_table = tsens_match,
+ },
+};
+
+static int __init tsens_tm_init_driver(void)
+{
+ return platform_driver_register(&tsens_tm_driver);
+}
+arch_initcall(tsens_tm_init_driver);
+
+static int __init tsens_thermal_register(void)
+{
+ return _tsens_register_thermal();
+}
+module_init(tsens_thermal_register);
+
+static void __exit _tsens_tm_remove(void)
+{
+ platform_driver_unregister(&tsens_tm_driver);
+}
+module_exit(_tsens_tm_remove);
+
+MODULE_ALIAS("platform:" TSENS_DRIVER_NAME);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 1fbfdd8..41f8106 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -373,6 +373,17 @@
dwc3_writel(dwc->regs, DWC3_GCTL, reg);
/*
+ * The default value of GUCTL[31:22] should be 0x8. But on cores
+ * revision < 2.30a, the default value is mistakenly overridden
+ * with 0x0. Restore the correct default value.
+ */
+ if (dwc->revision < DWC3_REVISION_230A) {
+ reg = dwc3_readl(dwc->regs, DWC3_GUCTL);
+ reg &= ~DWC3_GUCTL_REFCLKPER;
+ reg |= 0x8 << __ffs(DWC3_GUCTL_REFCLKPER);
+ dwc3_writel(dwc->regs, DWC3_GUCTL, reg);
+ }
+ /*
* Currently, the default and the recommended value for GUSB3PIPECTL
* [21:19] in the RTL is 3'b100 or 32 consecutive errors. Based on
* analysis and experiments in the lab, it is found that there is a
@@ -395,6 +406,11 @@
reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
reg &= ~DWC3_GUSB3PIPECTL_DELAY_P1P2P3;
reg |= 1 << __ffs(DWC3_GUSB3PIPECTL_DELAY_P1P2P3);
+ /*
+ * Receiver Detection in U3/Rx.Det is mistakenly disabled in
+ * cores < 2.30a. Fix it here.
+ */
+ reg &= ~DWC3_GUSB3PIPECTL_DIS_RXDET_U3_RXDET;
dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
}
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 98adff7..92e28f5 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -180,6 +180,9 @@
#define DWC3_GCTL_DISSCRAMBLE (1 << 3)
#define DWC3_GCTL_DSBLCLKGTNG (1 << 0)
+/* Global User Control Register */
+#define DWC3_GUCTL_REFCLKPER (0x3FF << 22)
+
/* Global USB2 PHY Configuration Register */
#define DWC3_GUSB2PHYCFG_PHYSOFTRST (1 << 31)
#define DWC3_GUSB2PHYCFG_SUSPHY (1 << 6)
@@ -188,6 +191,7 @@
#define DWC3_GUSB3PIPECTL_PHYSOFTRST (1 << 31)
#define DWC3_GUSB3PIPECTL_SUSPHY (1 << 17)
#define DWC3_GUSB3PIPECTL_DELAY_P1P2P3 (7 << 19)
+#define DWC3_GUSB3PIPECTL_DIS_RXDET_U3_RXDET (1 << 22)
/* Global TX Fifo Size Register */
#define DWC3_GTXFIFOSIZ_TXFDEF(n) ((n) & 0xffff)
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index a13b5da..2ed642a 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -1065,9 +1065,12 @@
static int mass_storage_function_init(struct android_usb_function *f,
struct usb_composite_dev *cdev)
{
+ struct android_dev *dev = _android_dev;
struct mass_storage_function_config *config;
struct fsg_common *common;
int err;
+ int i;
+ const char *name[2];
config = kzalloc(sizeof(struct mass_storage_function_config),
GFP_KERNEL);
@@ -1075,6 +1078,15 @@
return -ENOMEM;
config->fsg.nluns = 1;
+ name[0] = "lun";
+ if (dev->pdata->cdrom) {
+ config->fsg.nluns = 2;
+ config->fsg.luns[1].cdrom = 1;
+ config->fsg.luns[1].ro = 1;
+ config->fsg.luns[1].removable = 1;
+ name[1] = "lun0";
+ }
+
config->fsg.luns[0].removable = 1;
common = fsg_common_init(NULL, cdev, &config->fsg);
@@ -1083,18 +1095,24 @@
return PTR_ERR(common);
}
- err = sysfs_create_link(&f->dev->kobj,
- &common->luns[0].dev.kobj,
- "lun");
- if (err) {
- fsg_common_release(&common->ref);
- kfree(config);
- return err;
+ for (i = 0; i < config->fsg.nluns; i++) {
+ err = sysfs_create_link(&f->dev->kobj,
+ &common->luns[i].dev.kobj,
+ name[i]);
+ if (err)
+ goto error;
}
config->common = common;
f->config = config;
return 0;
+error:
+ for (; i > 0 ; i--)
+ sysfs_remove_link(&f->dev->kobj, name[i-1]);
+
+ fsg_common_release(&common->ref);
+ kfree(config);
+ return err;
}
static void mass_storage_function_cleanup(struct android_usb_function *f)
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 18f0721..4d15d4d 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -1957,6 +1957,8 @@
mReq->req.length)
mEpTemp = &_udc->ep0in;
mReq->req.complete(&mEpTemp->ep, &mReq->req);
+ if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
+ mReq->req.complete = NULL;
spin_lock(mEp->lock);
}
}
@@ -2803,7 +2805,12 @@
dbg_event(_usb_addr(mEp), "DEQUEUE", 0);
- hw_ep_flush(mEp->num, mEp->dir);
+ if ((mEp->type == USB_ENDPOINT_XFER_CONTROL)) {
+ hw_ep_flush(_udc->ep0out.num, RX);
+ hw_ep_flush(_udc->ep0in.num, TX);
+ } else {
+ hw_ep_flush(mEp->num, mEp->dir);
+ }
/* pop request */
list_del_init(&mReq->queue);
@@ -2821,6 +2828,8 @@
mReq->req.length)
mEpTemp = &_udc->ep0in;
mReq->req.complete(&mEpTemp->ep, &mReq->req);
+ if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
+ mReq->req.complete = NULL;
spin_lock(mEp->lock);
}
diff --git a/drivers/usb/gadget/f_tcm.c b/drivers/usb/gadget/f_tcm.c
new file mode 100644
index 0000000..d944745
--- /dev/null
+++ b/drivers/usb/gadget/f_tcm.c
@@ -0,0 +1,2434 @@
+/* Target based USB-Gadget Function
+ *
+ * UAS protocol handling, target callbacks, configfs handling,
+ * BBB (USB Mass Storage Class Bulk-Only (BBB) and Transport protocol handling.
+ *
+ * Author: Sebastian Andrzej Siewior <bigeasy at linutronix dot de>
+ * License: GPLv2 as published by FSF.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/configfs.h>
+#include <linux/ctype.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/composite.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/storage.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_tcq.h>
+#include <target/target_core_base.h>
+#include <target/target_core_fabric.h>
+#include <target/target_core_fabric_configfs.h>
+#include <target/target_core_configfs.h>
+#include <target/configfs_macros.h>
+#include <asm/unaligned.h>
+
+#include "f_tcm.h"
+
+static struct target_fabric_configfs *usbg_fabric_configfs;
+static int (*usbg_connect_cb) (bool connect);
+
+static inline struct f_uas *to_f_uas(struct usb_function *f)
+{
+ return container_of(f, struct f_uas, function);
+}
+
+static void usbg_cmd_release(struct kref *);
+
+static inline void usbg_cleanup_cmd(struct usbg_cmd *cmd)
+{
+ kref_put(&cmd->ref, usbg_cmd_release);
+}
+
+/* Start bot.c code */
+
+static int bot_enqueue_cmd_cbw(struct f_uas *fu)
+{
+ int ret;
+
+ if (fu->flags & USBG_BOT_CMD_PEND)
+ return 0;
+
+ ret = usb_ep_queue(fu->ep_out, fu->cmd.req, GFP_ATOMIC);
+ if (!ret)
+ fu->flags |= USBG_BOT_CMD_PEND;
+ return ret;
+}
+
+static void bot_status_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ struct usbg_cmd *cmd = req->context;
+ struct f_uas *fu = cmd->fu;
+
+ usbg_cleanup_cmd(cmd);
+ if (req->status < 0) {
+ pr_err("ERR %s(%d)\n", __func__, __LINE__);
+ return;
+ }
+
+ /* CSW completed, wait for next CBW */
+ bot_enqueue_cmd_cbw(fu);
+}
+
+static void bot_enqueue_sense_code(struct f_uas *fu, struct usbg_cmd *cmd)
+{
+ struct bulk_cs_wrap *csw = &fu->bot_status.csw;
+ int ret;
+ u8 *sense;
+ unsigned int csw_stat;
+
+ csw_stat = cmd->csw_code;
+
+ /*
+ * We can't send SENSE as a response. So we take ASC & ASCQ from our
+ * sense buffer and queue it and hope the host sends a REQUEST_SENSE
+ * command where it learns why we failed.
+ */
+ sense = cmd->sense_iu.sense;
+
+ csw->Tag = cmd->bot_tag;
+ csw->Status = csw_stat;
+ fu->bot_status.req->context = cmd;
+ ret = usb_ep_queue(fu->ep_in, fu->bot_status.req, GFP_ATOMIC);
+ if (ret)
+ pr_err("%s(%d) ERR: %d\n", __func__, __LINE__, ret);
+}
+
+static void bot_err_compl(struct usb_ep *ep, struct usb_request *req)
+{
+ struct usbg_cmd *cmd = req->context;
+ struct f_uas *fu = cmd->fu;
+
+ if (req->status < 0)
+ pr_err("ERR %s(%d)\n", __func__, __LINE__);
+
+ if (cmd->data_len) {
+ if (cmd->data_len > ep->maxpacket) {
+ req->length = ep->maxpacket;
+ cmd->data_len -= ep->maxpacket;
+ } else {
+ req->length = cmd->data_len;
+ cmd->data_len = 0;
+ }
+
+ usb_ep_queue(ep, req, GFP_ATOMIC);
+ return ;
+ }
+ bot_enqueue_sense_code(fu, cmd);
+}
+
+static void bot_send_bad_status(struct usbg_cmd *cmd)
+{
+ struct f_uas *fu = cmd->fu;
+ struct bulk_cs_wrap *csw = &fu->bot_status.csw;
+ struct usb_request *req;
+ struct usb_ep *ep;
+
+ csw->Residue = cpu_to_le32(cmd->data_len);
+
+ if (cmd->data_len) {
+ if (cmd->is_read) {
+ ep = fu->ep_in;
+ req = fu->bot_req_in;
+ } else {
+ ep = fu->ep_out;
+ req = fu->bot_req_out;
+ }
+
+ if (cmd->data_len > fu->ep_in->maxpacket) {
+ req->length = ep->maxpacket;
+ cmd->data_len -= ep->maxpacket;
+ } else {
+ req->length = cmd->data_len;
+ cmd->data_len = 0;
+ }
+ req->complete = bot_err_compl;
+ req->context = cmd;
+ req->buf = fu->cmd.buf;
+ usb_ep_queue(ep, req, GFP_KERNEL);
+ } else {
+ bot_enqueue_sense_code(fu, cmd);
+ }
+}
+
+static int bot_send_status(struct usbg_cmd *cmd, bool moved_data)
+{
+ struct f_uas *fu = cmd->fu;
+ struct bulk_cs_wrap *csw = &fu->bot_status.csw;
+ int ret;
+
+ if (cmd->se_cmd.scsi_status == SAM_STAT_GOOD) {
+ if (!moved_data && cmd->data_len) {
+ /*
+ * the host wants to move data, we don't. Fill / empty
+ * the pipe and then send the csw with reside set.
+ */
+ cmd->csw_code = US_BULK_STAT_OK;
+ bot_send_bad_status(cmd);
+ return 0;
+ }
+
+ csw->Tag = cmd->bot_tag;
+ csw->Residue = cpu_to_le32(0);
+ csw->Status = US_BULK_STAT_OK;
+ fu->bot_status.req->context = cmd;
+
+ ret = usb_ep_queue(fu->ep_in, fu->bot_status.req, GFP_KERNEL);
+ if (ret)
+ pr_err("%s(%d) ERR: %d\n", __func__, __LINE__, ret);
+ } else {
+ cmd->csw_code = US_BULK_STAT_FAIL;
+ bot_send_bad_status(cmd);
+ }
+ return 0;
+}
+
+/*
+ * Called after command (no data transfer) or after the write (to device)
+ * operation is completed
+ */
+static int bot_send_status_response(struct usbg_cmd *cmd)
+{
+ bool moved_data = false;
+
+ if (!cmd->is_read)
+ moved_data = true;
+ return bot_send_status(cmd, moved_data);
+}
+
+/* Read request completed, now we have to send the CSW */
+static void bot_read_compl(struct usb_ep *ep, struct usb_request *req)
+{
+ struct usbg_cmd *cmd = req->context;
+
+ if (req->status < 0)
+ pr_err("ERR %s(%d)\n", __func__, __LINE__);
+
+ bot_send_status(cmd, true);
+}
+
+static int bot_send_read_response(struct usbg_cmd *cmd)
+{
+ struct f_uas *fu = cmd->fu;
+ struct se_cmd *se_cmd = &cmd->se_cmd;
+ struct usb_gadget *gadget = fuas_to_gadget(fu);
+ int ret;
+
+ if (!cmd->data_len) {
+ cmd->csw_code = US_BULK_STAT_PHASE;
+ bot_send_bad_status(cmd);
+ return 0;
+ }
+
+ if (!gadget->sg_supported) {
+ cmd->data_buf = kmalloc(se_cmd->data_length, GFP_ATOMIC);
+ if (!cmd->data_buf)
+ return -ENOMEM;
+
+ sg_copy_to_buffer(se_cmd->t_data_sg,
+ se_cmd->t_data_nents,
+ cmd->data_buf,
+ se_cmd->data_length);
+
+ fu->bot_req_in->buf = cmd->data_buf;
+ } else {
+ fu->bot_req_in->buf = NULL;
+ fu->bot_req_in->num_sgs = se_cmd->t_data_nents;
+ fu->bot_req_in->sg = se_cmd->t_data_sg;
+ }
+
+ fu->bot_req_in->complete = bot_read_compl;
+ fu->bot_req_in->length = se_cmd->data_length;
+ fu->bot_req_in->context = cmd;
+ ret = usb_ep_queue(fu->ep_in, fu->bot_req_in, GFP_ATOMIC);
+ if (ret)
+ pr_err("%s(%d)\n", __func__, __LINE__);
+ return 0;
+}
+
+static void usbg_data_write_cmpl(struct usb_ep *, struct usb_request *);
+static int usbg_prepare_w_request(struct usbg_cmd *, struct usb_request *);
+
+static int bot_send_write_request(struct usbg_cmd *cmd)
+{
+ struct f_uas *fu = cmd->fu;
+ struct se_cmd *se_cmd = &cmd->se_cmd;
+ struct usb_gadget *gadget = fuas_to_gadget(fu);
+ int ret;
+
+ init_completion(&cmd->write_complete);
+ cmd->fu = fu;
+
+ if (!cmd->data_len) {
+ cmd->csw_code = US_BULK_STAT_PHASE;
+ return -EINVAL;
+ }
+
+ if (!gadget->sg_supported) {
+ cmd->data_buf = kmalloc(se_cmd->data_length, GFP_KERNEL);
+ if (!cmd->data_buf)
+ return -ENOMEM;
+
+ fu->bot_req_out->buf = cmd->data_buf;
+ } else {
+ fu->bot_req_out->buf = NULL;
+ fu->bot_req_out->num_sgs = se_cmd->t_data_nents;
+ fu->bot_req_out->sg = se_cmd->t_data_sg;
+ }
+
+ fu->bot_req_out->complete = usbg_data_write_cmpl;
+ fu->bot_req_out->length = se_cmd->data_length;
+ fu->bot_req_out->context = cmd;
+
+ ret = usbg_prepare_w_request(cmd, fu->bot_req_out);
+ if (ret)
+ goto cleanup;
+ ret = usb_ep_queue(fu->ep_out, fu->bot_req_out, GFP_KERNEL);
+ if (ret)
+ pr_err("%s(%d)\n", __func__, __LINE__);
+
+ wait_for_completion(&cmd->write_complete);
+ transport_generic_process_write(se_cmd);
+cleanup:
+ return ret;
+}
+
+static int bot_submit_command(struct f_uas *, void *, unsigned int);
+
+static void bot_cmd_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ struct f_uas *fu = req->context;
+ int ret;
+
+ fu->flags &= ~USBG_BOT_CMD_PEND;
+
+ if (req->status < 0)
+ return;
+
+ ret = bot_submit_command(fu, req->buf, req->actual);
+ if (ret)
+ pr_err("%s(%d): %d\n", __func__, __LINE__, ret);
+}
+
+static int bot_prepare_reqs(struct f_uas *fu)
+{
+ int ret;
+
+ fu->bot_req_in = usb_ep_alloc_request(fu->ep_in, GFP_KERNEL);
+ if (!fu->bot_req_in)
+ goto err;
+
+ fu->bot_req_out = usb_ep_alloc_request(fu->ep_out, GFP_KERNEL);
+ if (!fu->bot_req_out)
+ goto err_out;
+
+ fu->cmd.req = usb_ep_alloc_request(fu->ep_out, GFP_KERNEL);
+ if (!fu->cmd.req)
+ goto err_cmd;
+
+ fu->bot_status.req = usb_ep_alloc_request(fu->ep_in, GFP_KERNEL);
+ if (!fu->bot_status.req)
+ goto err_sts;
+
+ fu->bot_status.req->buf = &fu->bot_status.csw;
+ fu->bot_status.req->length = US_BULK_CS_WRAP_LEN;
+ fu->bot_status.req->complete = bot_status_complete;
+ fu->bot_status.csw.Signature = cpu_to_le32(US_BULK_CS_SIGN);
+
+ fu->cmd.buf = kmalloc(fu->ep_out->maxpacket, GFP_KERNEL);
+ if (!fu->cmd.buf)
+ goto err_buf;
+
+ fu->cmd.req->complete = bot_cmd_complete;
+ fu->cmd.req->buf = fu->cmd.buf;
+ fu->cmd.req->length = fu->ep_out->maxpacket;
+ fu->cmd.req->context = fu;
+
+ ret = bot_enqueue_cmd_cbw(fu);
+ if (ret)
+ goto err_queue;
+ return 0;
+err_queue:
+ kfree(fu->cmd.buf);
+ fu->cmd.buf = NULL;
+err_buf:
+ usb_ep_free_request(fu->ep_in, fu->bot_status.req);
+err_sts:
+ usb_ep_free_request(fu->ep_out, fu->cmd.req);
+ fu->cmd.req = NULL;
+err_cmd:
+ usb_ep_free_request(fu->ep_out, fu->bot_req_out);
+ fu->bot_req_out = NULL;
+err_out:
+ usb_ep_free_request(fu->ep_in, fu->bot_req_in);
+ fu->bot_req_in = NULL;
+err:
+ pr_err("BOT: endpoint setup failed\n");
+ return -ENOMEM;
+}
+
+void bot_cleanup_old_alt(struct f_uas *fu)
+{
+ if (!(fu->flags & USBG_ENABLED))
+ return;
+
+ usb_ep_disable(fu->ep_in);
+ usb_ep_disable(fu->ep_out);
+
+ if (!fu->bot_req_in)
+ return;
+
+ usb_ep_free_request(fu->ep_in, fu->bot_req_in);
+ usb_ep_free_request(fu->ep_out, fu->bot_req_out);
+ usb_ep_free_request(fu->ep_out, fu->cmd.req);
+ usb_ep_free_request(fu->ep_out, fu->bot_status.req);
+
+ kfree(fu->cmd.buf);
+
+ fu->bot_req_in = NULL;
+ fu->bot_req_out = NULL;
+ fu->cmd.req = NULL;
+ fu->bot_status.req = NULL;
+ fu->cmd.buf = NULL;
+}
+
+static void bot_set_alt(struct f_uas *fu)
+{
+ struct usb_function *f = &fu->function;
+ struct usb_gadget *gadget = f->config->cdev->gadget;
+ int ret;
+
+ fu->flags = USBG_IS_BOT;
+
+ config_ep_by_speed(gadget, f, fu->ep_in);
+ ret = usb_ep_enable(fu->ep_in);
+ if (ret)
+ goto err_b_in;
+
+ config_ep_by_speed(gadget, f, fu->ep_out);
+ ret = usb_ep_enable(fu->ep_out);
+ if (ret)
+ goto err_b_out;
+
+ ret = bot_prepare_reqs(fu);
+ if (ret)
+ goto err_wq;
+ fu->flags |= USBG_ENABLED;
+ pr_info("Using the BOT protocol\n");
+ return;
+err_wq:
+ usb_ep_disable(fu->ep_out);
+err_b_out:
+ usb_ep_disable(fu->ep_in);
+err_b_in:
+ fu->flags = USBG_IS_BOT;
+}
+
+static int usbg_bot_setup(struct usb_function *f,
+ const struct usb_ctrlrequest *ctrl)
+{
+ struct f_uas *fu = to_f_uas(f);
+ struct usb_composite_dev *cdev = f->config->cdev;
+ u16 w_value = le16_to_cpu(ctrl->wValue);
+ u16 w_length = le16_to_cpu(ctrl->wLength);
+ int luns;
+ u8 *ret_lun;
+
+ switch (ctrl->bRequest) {
+ case US_BULK_GET_MAX_LUN:
+ if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_CLASS |
+ USB_RECIP_INTERFACE))
+ return -ENOTSUPP;
+
+ if (w_length < 1)
+ return -EINVAL;
+ if (w_value != 0)
+ return -EINVAL;
+ luns = atomic_read(&fu->tpg->tpg_port_count);
+ if (!luns) {
+ pr_err("No LUNs configured?\n");
+ return -EINVAL;
+ }
+ /*
+ * If 4 LUNs are present we return 3 i.e. LUN 0..3 can be
+ * accessed. The upper limit is 0xf
+ */
+ luns--;
+ if (luns > 0xf) {
+ pr_info_once("Limiting the number of luns to 16\n");
+ luns = 0xf;
+ }
+ ret_lun = cdev->req->buf;
+ *ret_lun = luns;
+ cdev->req->length = 1;
+ return usb_ep_queue(cdev->gadget->ep0, cdev->req, GFP_ATOMIC);
+ break;
+
+ case US_BULK_RESET_REQUEST:
+ /* XXX maybe we should remove previous requests for IN + OUT */
+ bot_enqueue_cmd_cbw(fu);
+ return 0;
+ break;
+ };
+ return -ENOTSUPP;
+}
+
+/* Start uas.c code */
+
+static void uasp_cleanup_one_stream(struct f_uas *fu, struct uas_stream *stream)
+{
+ /* We have either all three allocated or none */
+ if (!stream->req_in)
+ return;
+
+ usb_ep_free_request(fu->ep_in, stream->req_in);
+ usb_ep_free_request(fu->ep_out, stream->req_out);
+ usb_ep_free_request(fu->ep_status, stream->req_status);
+
+ stream->req_in = NULL;
+ stream->req_out = NULL;
+ stream->req_status = NULL;
+}
+
+static void uasp_free_cmdreq(struct f_uas *fu)
+{
+ usb_ep_free_request(fu->ep_cmd, fu->cmd.req);
+ kfree(fu->cmd.buf);
+ fu->cmd.req = NULL;
+ fu->cmd.buf = NULL;
+}
+
+static void uasp_cleanup_old_alt(struct f_uas *fu)
+{
+ int i;
+
+ if (!(fu->flags & USBG_ENABLED))
+ return;
+
+ usb_ep_disable(fu->ep_in);
+ usb_ep_disable(fu->ep_out);
+ usb_ep_disable(fu->ep_status);
+ usb_ep_disable(fu->ep_cmd);
+
+ for (i = 0; i < UASP_SS_EP_COMP_NUM_STREAMS; i++)
+ uasp_cleanup_one_stream(fu, &fu->stream[i]);
+ uasp_free_cmdreq(fu);
+}
+
+static void uasp_status_data_cmpl(struct usb_ep *ep, struct usb_request *req);
+
+static int uasp_prepare_r_request(struct usbg_cmd *cmd)
+{
+ struct se_cmd *se_cmd = &cmd->se_cmd;
+ struct f_uas *fu = cmd->fu;
+ struct usb_gadget *gadget = fuas_to_gadget(fu);
+ struct uas_stream *stream = cmd->stream;
+
+ if (!gadget->sg_supported) {
+ cmd->data_buf = kmalloc(se_cmd->data_length, GFP_ATOMIC);
+ if (!cmd->data_buf)
+ return -ENOMEM;
+
+ sg_copy_to_buffer(se_cmd->t_data_sg,
+ se_cmd->t_data_nents,
+ cmd->data_buf,
+ se_cmd->data_length);
+
+ stream->req_in->buf = cmd->data_buf;
+ } else {
+ stream->req_in->buf = NULL;
+ stream->req_in->num_sgs = se_cmd->t_data_nents;
+ stream->req_in->sg = se_cmd->t_data_sg;
+ }
+
+ stream->req_in->complete = uasp_status_data_cmpl;
+ stream->req_in->length = se_cmd->data_length;
+ stream->req_in->context = cmd;
+
+ cmd->state = UASP_SEND_STATUS;
+ return 0;
+}
+
+static void uasp_prepare_status(struct usbg_cmd *cmd)
+{
+ struct se_cmd *se_cmd = &cmd->se_cmd;
+ struct sense_iu *iu = &cmd->sense_iu;
+ struct uas_stream *stream = cmd->stream;
+
+ cmd->state = UASP_QUEUE_COMMAND;
+ iu->iu_id = IU_ID_STATUS;
+ iu->tag = cpu_to_be16(cmd->tag);
+
+ /*
+ * iu->status_qual = cpu_to_be16(STATUS QUALIFIER SAM-4. Where R U?);
+ */
+ iu->len = cpu_to_be16(se_cmd->scsi_sense_length);
+ iu->status = se_cmd->scsi_status;
+ stream->req_status->context = cmd;
+ stream->req_status->length = se_cmd->scsi_sense_length + 16;
+ stream->req_status->buf = iu;
+ stream->req_status->complete = uasp_status_data_cmpl;
+}
+
+static void uasp_status_data_cmpl(struct usb_ep *ep, struct usb_request *req)
+{
+ struct usbg_cmd *cmd = req->context;
+ struct uas_stream *stream = cmd->stream;
+ struct f_uas *fu = cmd->fu;
+ int ret;
+
+ if (req->status < 0)
+ goto cleanup;
+
+ switch (cmd->state) {
+ case UASP_SEND_DATA:
+ ret = uasp_prepare_r_request(cmd);
+ if (ret)
+ goto cleanup;
+ ret = usb_ep_queue(fu->ep_in, stream->req_in, GFP_ATOMIC);
+ if (ret)
+ pr_err("%s(%d) => %d\n", __func__, __LINE__, ret);
+ break;
+
+ case UASP_RECEIVE_DATA:
+ ret = usbg_prepare_w_request(cmd, stream->req_out);
+ if (ret)
+ goto cleanup;
+ ret = usb_ep_queue(fu->ep_out, stream->req_out, GFP_ATOMIC);
+ if (ret)
+ pr_err("%s(%d) => %d\n", __func__, __LINE__, ret);
+ break;
+
+ case UASP_SEND_STATUS:
+ uasp_prepare_status(cmd);
+ ret = usb_ep_queue(fu->ep_status, stream->req_status,
+ GFP_ATOMIC);
+ if (ret)
+ pr_err("%s(%d) => %d\n", __func__, __LINE__, ret);
+ break;
+
+ case UASP_QUEUE_COMMAND:
+ usbg_cleanup_cmd(cmd);
+ usb_ep_queue(fu->ep_cmd, fu->cmd.req, GFP_ATOMIC);
+ break;
+
+ default:
+ BUG();
+ };
+ return;
+
+cleanup:
+ usbg_cleanup_cmd(cmd);
+}
+
+static int uasp_send_status_response(struct usbg_cmd *cmd)
+{
+ struct f_uas *fu = cmd->fu;
+ struct uas_stream *stream = cmd->stream;
+ struct sense_iu *iu = &cmd->sense_iu;
+
+ iu->tag = cpu_to_be16(cmd->tag);
+ stream->req_status->complete = uasp_status_data_cmpl;
+ stream->req_status->context = cmd;
+ cmd->fu = fu;
+ uasp_prepare_status(cmd);
+ return usb_ep_queue(fu->ep_status, stream->req_status, GFP_ATOMIC);
+}
+
+static int uasp_send_read_response(struct usbg_cmd *cmd)
+{
+ struct f_uas *fu = cmd->fu;
+ struct uas_stream *stream = cmd->stream;
+ struct sense_iu *iu = &cmd->sense_iu;
+ int ret;
+
+ cmd->fu = fu;
+
+ iu->tag = cpu_to_be16(cmd->tag);
+ if (fu->flags & USBG_USE_STREAMS) {
+
+ ret = uasp_prepare_r_request(cmd);
+ if (ret)
+ goto out;
+ ret = usb_ep_queue(fu->ep_in, stream->req_in, GFP_ATOMIC);
+ if (ret) {
+ pr_err("%s(%d) => %d\n", __func__, __LINE__, ret);
+ kfree(cmd->data_buf);
+ cmd->data_buf = NULL;
+ }
+
+ } else {
+
+ iu->iu_id = IU_ID_READ_READY;
+ iu->tag = cpu_to_be16(cmd->tag);
+
+ stream->req_status->complete = uasp_status_data_cmpl;
+ stream->req_status->context = cmd;
+
+ cmd->state = UASP_SEND_DATA;
+ stream->req_status->buf = iu;
+ stream->req_status->length = sizeof(struct iu);
+
+ ret = usb_ep_queue(fu->ep_status, stream->req_status,
+ GFP_ATOMIC);
+ if (ret)
+ pr_err("%s(%d) => %d\n", __func__, __LINE__, ret);
+ }
+out:
+ return ret;
+}
+
+static int uasp_send_write_request(struct usbg_cmd *cmd)
+{
+ struct f_uas *fu = cmd->fu;
+ struct se_cmd *se_cmd = &cmd->se_cmd;
+ struct uas_stream *stream = cmd->stream;
+ struct sense_iu *iu = &cmd->sense_iu;
+ int ret;
+
+ init_completion(&cmd->write_complete);
+ cmd->fu = fu;
+
+ iu->tag = cpu_to_be16(cmd->tag);
+
+ if (fu->flags & USBG_USE_STREAMS) {
+
+ ret = usbg_prepare_w_request(cmd, stream->req_out);
+ if (ret)
+ goto cleanup;
+ ret = usb_ep_queue(fu->ep_out, stream->req_out, GFP_ATOMIC);
+ if (ret)
+ pr_err("%s(%d)\n", __func__, __LINE__);
+
+ } else {
+
+ iu->iu_id = IU_ID_WRITE_READY;
+ iu->tag = cpu_to_be16(cmd->tag);
+
+ stream->req_status->complete = uasp_status_data_cmpl;
+ stream->req_status->context = cmd;
+
+ cmd->state = UASP_RECEIVE_DATA;
+ stream->req_status->buf = iu;
+ stream->req_status->length = sizeof(struct iu);
+
+ ret = usb_ep_queue(fu->ep_status, stream->req_status,
+ GFP_ATOMIC);
+ if (ret)
+ pr_err("%s(%d)\n", __func__, __LINE__);
+ }
+
+ wait_for_completion(&cmd->write_complete);
+ transport_generic_process_write(se_cmd);
+cleanup:
+ return ret;
+}
+
+static int usbg_submit_command(struct f_uas *, void *, unsigned int);
+
+static void uasp_cmd_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ struct f_uas *fu = req->context;
+ int ret;
+
+ if (req->status < 0)
+ return;
+
+ ret = usbg_submit_command(fu, req->buf, req->actual);
+ /*
+ * Once we tune for performance enqueue the command req here again so
+ * we can receive a second command while we processing this one. Pay
+ * attention to properly sync STAUS endpoint with DATA IN + OUT so you
+ * don't break HS.
+ */
+ if (!ret)
+ return;
+ usb_ep_queue(fu->ep_cmd, fu->cmd.req, GFP_ATOMIC);
+}
+
+static int uasp_alloc_stream_res(struct f_uas *fu, struct uas_stream *stream)
+{
+ stream->req_in = usb_ep_alloc_request(fu->ep_in, GFP_KERNEL);
+ if (!stream->req_in)
+ goto out;
+
+ stream->req_out = usb_ep_alloc_request(fu->ep_out, GFP_KERNEL);
+ if (!stream->req_out)
+ goto err_out;
+
+ stream->req_status = usb_ep_alloc_request(fu->ep_status, GFP_KERNEL);
+ if (!stream->req_status)
+ goto err_sts;
+
+ return 0;
+err_sts:
+ usb_ep_free_request(fu->ep_status, stream->req_status);
+ stream->req_status = NULL;
+err_out:
+ usb_ep_free_request(fu->ep_out, stream->req_out);
+ stream->req_out = NULL;
+out:
+ return -ENOMEM;
+}
+
+static int uasp_alloc_cmd(struct f_uas *fu)
+{
+ fu->cmd.req = usb_ep_alloc_request(fu->ep_cmd, GFP_KERNEL);
+ if (!fu->cmd.req)
+ goto err;
+
+ fu->cmd.buf = kmalloc(fu->ep_cmd->maxpacket, GFP_KERNEL);
+ if (!fu->cmd.buf)
+ goto err_buf;
+
+ fu->cmd.req->complete = uasp_cmd_complete;
+ fu->cmd.req->buf = fu->cmd.buf;
+ fu->cmd.req->length = fu->ep_cmd->maxpacket;
+ fu->cmd.req->context = fu;
+ return 0;
+
+err_buf:
+ usb_ep_free_request(fu->ep_cmd, fu->cmd.req);
+err:
+ return -ENOMEM;
+}
+
+static void uasp_setup_stream_res(struct f_uas *fu, int max_streams)
+{
+ int i;
+
+ for (i = 0; i < max_streams; i++) {
+ struct uas_stream *s = &fu->stream[i];
+
+ s->req_in->stream_id = i + 1;
+ s->req_out->stream_id = i + 1;
+ s->req_status->stream_id = i + 1;
+ }
+}
+
+static int uasp_prepare_reqs(struct f_uas *fu)
+{
+ int ret;
+ int i;
+ int max_streams;
+
+ if (fu->flags & USBG_USE_STREAMS)
+ max_streams = UASP_SS_EP_COMP_NUM_STREAMS;
+ else
+ max_streams = 1;
+
+ for (i = 0; i < max_streams; i++) {
+ ret = uasp_alloc_stream_res(fu, &fu->stream[i]);
+ if (ret)
+ goto err_cleanup;
+ }
+
+ ret = uasp_alloc_cmd(fu);
+ if (ret)
+ goto err_free_stream;
+ uasp_setup_stream_res(fu, max_streams);
+
+ ret = usb_ep_queue(fu->ep_cmd, fu->cmd.req, GFP_ATOMIC);
+ if (ret)
+ goto err_free_stream;
+
+ return 0;
+
+err_free_stream:
+ uasp_free_cmdreq(fu);
+
+err_cleanup:
+ if (i) {
+ do {
+ uasp_cleanup_one_stream(fu, &fu->stream[i - 1]);
+ i--;
+ } while (i);
+ }
+ pr_err("UASP: endpoint setup failed\n");
+ return ret;
+}
+
+static void uasp_set_alt(struct f_uas *fu)
+{
+ struct usb_function *f = &fu->function;
+ struct usb_gadget *gadget = f->config->cdev->gadget;
+ int ret;
+
+ fu->flags = USBG_IS_UAS;
+
+ if (gadget->speed == USB_SPEED_SUPER)
+ fu->flags |= USBG_USE_STREAMS;
+
+ config_ep_by_speed(gadget, f, fu->ep_in);
+ ret = usb_ep_enable(fu->ep_in);
+ if (ret)
+ goto err_b_in;
+
+ config_ep_by_speed(gadget, f, fu->ep_out);
+ ret = usb_ep_enable(fu->ep_out);
+ if (ret)
+ goto err_b_out;
+
+ config_ep_by_speed(gadget, f, fu->ep_cmd);
+ ret = usb_ep_enable(fu->ep_cmd);
+ if (ret)
+ goto err_cmd;
+ config_ep_by_speed(gadget, f, fu->ep_status);
+ ret = usb_ep_enable(fu->ep_status);
+ if (ret)
+ goto err_status;
+
+ ret = uasp_prepare_reqs(fu);
+ if (ret)
+ goto err_wq;
+ fu->flags |= USBG_ENABLED;
+
+ pr_info("Using the UAS protocol\n");
+ return;
+err_wq:
+ usb_ep_disable(fu->ep_status);
+err_status:
+ usb_ep_disable(fu->ep_cmd);
+err_cmd:
+ usb_ep_disable(fu->ep_out);
+err_b_out:
+ usb_ep_disable(fu->ep_in);
+err_b_in:
+ fu->flags = 0;
+}
+
+static int get_cmd_dir(const unsigned char *cdb)
+{
+ int ret;
+
+ switch (cdb[0]) {
+ case READ_6:
+ case READ_10:
+ case READ_12:
+ case READ_16:
+ case INQUIRY:
+ case MODE_SENSE:
+ case MODE_SENSE_10:
+ case SERVICE_ACTION_IN:
+ case MAINTENANCE_IN:
+ case PERSISTENT_RESERVE_IN:
+ case SECURITY_PROTOCOL_IN:
+ case ACCESS_CONTROL_IN:
+ case REPORT_LUNS:
+ case READ_BLOCK_LIMITS:
+ case READ_POSITION:
+ case READ_CAPACITY:
+ case READ_TOC:
+ case READ_FORMAT_CAPACITIES:
+ case REQUEST_SENSE:
+ ret = DMA_FROM_DEVICE;
+ break;
+
+ case WRITE_6:
+ case WRITE_10:
+ case WRITE_12:
+ case WRITE_16:
+ case MODE_SELECT:
+ case MODE_SELECT_10:
+ case WRITE_VERIFY:
+ case WRITE_VERIFY_12:
+ case PERSISTENT_RESERVE_OUT:
+ case MAINTENANCE_OUT:
+ case SECURITY_PROTOCOL_OUT:
+ case ACCESS_CONTROL_OUT:
+ ret = DMA_TO_DEVICE;
+ break;
+ case ALLOW_MEDIUM_REMOVAL:
+ case TEST_UNIT_READY:
+ case SYNCHRONIZE_CACHE:
+ case START_STOP:
+ case ERASE:
+ case REZERO_UNIT:
+ case SEEK_10:
+ case SPACE:
+ case VERIFY:
+ case WRITE_FILEMARKS:
+ ret = DMA_NONE;
+ break;
+ default:
+ pr_warn("target: Unknown data direction for SCSI Opcode "
+ "0x%02x\n", cdb[0]);
+ ret = -EINVAL;
+ }
+ return ret;
+}
+
+static void usbg_data_write_cmpl(struct usb_ep *ep, struct usb_request *req)
+{
+ struct usbg_cmd *cmd = req->context;
+ struct se_cmd *se_cmd = &cmd->se_cmd;
+
+ if (req->status < 0) {
+ pr_err("%s() state %d transfer failed\n", __func__, cmd->state);
+ goto cleanup;
+ }
+
+ if (req->num_sgs == 0) {
+ sg_copy_from_buffer(se_cmd->t_data_sg,
+ se_cmd->t_data_nents,
+ cmd->data_buf,
+ se_cmd->data_length);
+ }
+
+ complete(&cmd->write_complete);
+ return;
+
+cleanup:
+ usbg_cleanup_cmd(cmd);
+}
+
+static int usbg_prepare_w_request(struct usbg_cmd *cmd, struct usb_request *req)
+{
+ struct se_cmd *se_cmd = &cmd->se_cmd;
+ struct f_uas *fu = cmd->fu;
+ struct usb_gadget *gadget = fuas_to_gadget(fu);
+
+ if (!gadget->sg_supported) {
+ cmd->data_buf = kmalloc(se_cmd->data_length, GFP_ATOMIC);
+ if (!cmd->data_buf)
+ return -ENOMEM;
+
+ req->buf = cmd->data_buf;
+ } else {
+ req->buf = NULL;
+ req->num_sgs = se_cmd->t_data_nents;
+ req->sg = se_cmd->t_data_sg;
+ }
+
+ req->complete = usbg_data_write_cmpl;
+ req->length = se_cmd->data_length;
+ req->context = cmd;
+ return 0;
+}
+
+static int usbg_send_status_response(struct se_cmd *se_cmd)
+{
+ struct usbg_cmd *cmd = container_of(se_cmd, struct usbg_cmd,
+ se_cmd);
+ struct f_uas *fu = cmd->fu;
+
+ if (fu->flags & USBG_IS_BOT)
+ return bot_send_status_response(cmd);
+ else
+ return uasp_send_status_response(cmd);
+}
+
+static int usbg_send_write_request(struct se_cmd *se_cmd)
+{
+ struct usbg_cmd *cmd = container_of(se_cmd, struct usbg_cmd,
+ se_cmd);
+ struct f_uas *fu = cmd->fu;
+
+ if (fu->flags & USBG_IS_BOT)
+ return bot_send_write_request(cmd);
+ else
+ return uasp_send_write_request(cmd);
+}
+
+static int usbg_send_read_response(struct se_cmd *se_cmd)
+{
+ struct usbg_cmd *cmd = container_of(se_cmd, struct usbg_cmd,
+ se_cmd);
+ struct f_uas *fu = cmd->fu;
+
+ if (fu->flags & USBG_IS_BOT)
+ return bot_send_read_response(cmd);
+ else
+ return uasp_send_read_response(cmd);
+}
+
+static void usbg_cmd_work(struct work_struct *work)
+{
+ struct usbg_cmd *cmd = container_of(work, struct usbg_cmd, work);
+ struct se_cmd *se_cmd;
+ struct tcm_usbg_nexus *tv_nexus;
+ struct usbg_tpg *tpg;
+ int dir;
+
+ se_cmd = &cmd->se_cmd;
+ tpg = cmd->fu->tpg;
+ tv_nexus = tpg->tpg_nexus;
+ dir = get_cmd_dir(cmd->cmd_buf);
+ if (dir < 0) {
+ transport_init_se_cmd(se_cmd,
+ tv_nexus->tvn_se_sess->se_tpg->se_tpg_tfo,
+ tv_nexus->tvn_se_sess, cmd->data_len, DMA_NONE,
+ cmd->prio_attr, cmd->sense_iu.sense);
+
+ transport_send_check_condition_and_sense(se_cmd,
+ TCM_UNSUPPORTED_SCSI_OPCODE, 1);
+ usbg_cleanup_cmd(cmd);
+ return;
+ }
+
+ target_submit_cmd(se_cmd, tv_nexus->tvn_se_sess,
+ cmd->cmd_buf, cmd->sense_iu.sense, cmd->unpacked_lun,
+ 0, cmd->prio_attr, dir, TARGET_SCF_UNKNOWN_SIZE);
+}
+
+static int usbg_submit_command(struct f_uas *fu,
+ void *cmdbuf, unsigned int len)
+{
+ struct command_iu *cmd_iu = cmdbuf;
+ struct usbg_cmd *cmd;
+ struct usbg_tpg *tpg;
+ struct se_cmd *se_cmd;
+ struct tcm_usbg_nexus *tv_nexus;
+ u32 cmd_len;
+ int ret;
+
+ if (cmd_iu->iu_id != IU_ID_COMMAND) {
+ pr_err("Unsupported type %d\n", cmd_iu->iu_id);
+ return -EINVAL;
+ }
+
+ cmd = kzalloc(sizeof *cmd, GFP_ATOMIC);
+ if (!cmd)
+ return -ENOMEM;
+
+ cmd->fu = fu;
+
+ /* XXX until I figure out why I can't free in on complete */
+ kref_init(&cmd->ref);
+ kref_get(&cmd->ref);
+
+ tpg = fu->tpg;
+ cmd_len = (cmd_iu->len & ~0x3) + 16;
+ if (cmd_len > USBG_MAX_CMD)
+ goto err;
+
+ memcpy(cmd->cmd_buf, cmd_iu->cdb, cmd_len);
+
+ cmd->tag = be16_to_cpup(&cmd_iu->tag);
+ if (fu->flags & USBG_USE_STREAMS) {
+ if (cmd->tag > UASP_SS_EP_COMP_NUM_STREAMS)
+ goto err;
+ if (!cmd->tag)
+ cmd->stream = &fu->stream[0];
+ else
+ cmd->stream = &fu->stream[cmd->tag - 1];
+ } else {
+ cmd->stream = &fu->stream[0];
+ }
+
+ tv_nexus = tpg->tpg_nexus;
+ if (!tv_nexus) {
+ pr_err("Missing nexus, ignoring command\n");
+ goto err;
+ }
+
+ switch (cmd_iu->prio_attr & 0x7) {
+ case UAS_HEAD_TAG:
+ cmd->prio_attr = MSG_HEAD_TAG;
+ break;
+ case UAS_ORDERED_TAG:
+ cmd->prio_attr = MSG_ORDERED_TAG;
+ break;
+ case UAS_ACA:
+ cmd->prio_attr = MSG_ACA_TAG;
+ break;
+ default:
+ pr_debug_once("Unsupported prio_attr: %02x.\n",
+ cmd_iu->prio_attr);
+ case UAS_SIMPLE_TAG:
+ cmd->prio_attr = MSG_SIMPLE_TAG;
+ break;
+ }
+
+ se_cmd = &cmd->se_cmd;
+ cmd->unpacked_lun = scsilun_to_int(&cmd_iu->lun);
+
+ INIT_WORK(&cmd->work, usbg_cmd_work);
+ ret = queue_work(tpg->workqueue, &cmd->work);
+ if (ret < 0)
+ goto err;
+
+ return 0;
+err:
+ kfree(cmd);
+ return -EINVAL;
+}
+
+static void bot_cmd_work(struct work_struct *work)
+{
+ struct usbg_cmd *cmd = container_of(work, struct usbg_cmd, work);
+ struct se_cmd *se_cmd;
+ struct tcm_usbg_nexus *tv_nexus;
+ struct usbg_tpg *tpg;
+ int dir;
+
+ se_cmd = &cmd->se_cmd;
+ tpg = cmd->fu->tpg;
+ tv_nexus = tpg->tpg_nexus;
+ dir = get_cmd_dir(cmd->cmd_buf);
+ if (dir < 0) {
+ transport_init_se_cmd(se_cmd,
+ tv_nexus->tvn_se_sess->se_tpg->se_tpg_tfo,
+ tv_nexus->tvn_se_sess, cmd->data_len, DMA_NONE,
+ cmd->prio_attr, cmd->sense_iu.sense);
+
+ transport_send_check_condition_and_sense(se_cmd,
+ TCM_UNSUPPORTED_SCSI_OPCODE, 1);
+ usbg_cleanup_cmd(cmd);
+ return;
+ }
+
+ target_submit_cmd(se_cmd, tv_nexus->tvn_se_sess,
+ cmd->cmd_buf, cmd->sense_iu.sense, cmd->unpacked_lun,
+ cmd->data_len, cmd->prio_attr, dir, 0);
+}
+
+static int bot_submit_command(struct f_uas *fu,
+ void *cmdbuf, unsigned int len)
+{
+ struct bulk_cb_wrap *cbw = cmdbuf;
+ struct usbg_cmd *cmd;
+ struct usbg_tpg *tpg;
+ struct se_cmd *se_cmd;
+ struct tcm_usbg_nexus *tv_nexus;
+ u32 cmd_len;
+ int ret;
+
+ if (cbw->Signature != cpu_to_le32(US_BULK_CB_SIGN)) {
+ pr_err("Wrong signature on CBW\n");
+ return -EINVAL;
+ }
+ if (len != 31) {
+ pr_err("Wrong length for CBW\n");
+ return -EINVAL;
+ }
+
+ cmd_len = cbw->Length;
+ if (cmd_len < 1 || cmd_len > 16)
+ return -EINVAL;
+
+ cmd = kzalloc(sizeof *cmd, GFP_ATOMIC);
+ if (!cmd)
+ return -ENOMEM;
+
+ cmd->fu = fu;
+
+ /* XXX until I figure out why I can't free in on complete */
+ kref_init(&cmd->ref);
+ kref_get(&cmd->ref);
+
+ tpg = fu->tpg;
+
+ memcpy(cmd->cmd_buf, cbw->CDB, cmd_len);
+
+ cmd->bot_tag = cbw->Tag;
+
+ tv_nexus = tpg->tpg_nexus;
+ if (!tv_nexus) {
+ pr_err("Missing nexus, ignoring command\n");
+ goto err;
+ }
+
+ cmd->prio_attr = MSG_SIMPLE_TAG;
+ se_cmd = &cmd->se_cmd;
+ cmd->unpacked_lun = cbw->Lun;
+ cmd->is_read = cbw->Flags & US_BULK_FLAG_IN ? 1 : 0;
+ cmd->data_len = le32_to_cpu(cbw->DataTransferLength);
+
+ INIT_WORK(&cmd->work, bot_cmd_work);
+ ret = queue_work(tpg->workqueue, &cmd->work);
+ if (ret < 0)
+ goto err;
+
+ return 0;
+err:
+ kfree(cmd);
+ return -EINVAL;
+}
+
+/* Start fabric.c code */
+
+static int usbg_check_true(struct se_portal_group *se_tpg)
+{
+ return 1;
+}
+
+static int usbg_check_false(struct se_portal_group *se_tpg)
+{
+ return 0;
+}
+
+static char *usbg_get_fabric_name(void)
+{
+ return "usb_gadget";
+}
+
+static u8 usbg_get_fabric_proto_ident(struct se_portal_group *se_tpg)
+{
+ struct usbg_tpg *tpg = container_of(se_tpg,
+ struct usbg_tpg, se_tpg);
+ struct usbg_tport *tport = tpg->tport;
+ u8 proto_id;
+
+ switch (tport->tport_proto_id) {
+ case SCSI_PROTOCOL_SAS:
+ default:
+ proto_id = sas_get_fabric_proto_ident(se_tpg);
+ break;
+ }
+
+ return proto_id;
+}
+
+static char *usbg_get_fabric_wwn(struct se_portal_group *se_tpg)
+{
+ struct usbg_tpg *tpg = container_of(se_tpg,
+ struct usbg_tpg, se_tpg);
+ struct usbg_tport *tport = tpg->tport;
+
+ return &tport->tport_name[0];
+}
+
+static u16 usbg_get_tag(struct se_portal_group *se_tpg)
+{
+ struct usbg_tpg *tpg = container_of(se_tpg,
+ struct usbg_tpg, se_tpg);
+ return tpg->tport_tpgt;
+}
+
+static u32 usbg_get_default_depth(struct se_portal_group *se_tpg)
+{
+ return 1;
+}
+
+static u32 usbg_get_pr_transport_id(
+ struct se_portal_group *se_tpg,
+ struct se_node_acl *se_nacl,
+ struct t10_pr_registration *pr_reg,
+ int *format_code,
+ unsigned char *buf)
+{
+ struct usbg_tpg *tpg = container_of(se_tpg,
+ struct usbg_tpg, se_tpg);
+ struct usbg_tport *tport = tpg->tport;
+ int ret = 0;
+
+ switch (tport->tport_proto_id) {
+ case SCSI_PROTOCOL_SAS:
+ default:
+ ret = sas_get_pr_transport_id(se_tpg, se_nacl, pr_reg,
+ format_code, buf);
+ break;
+ }
+
+ return ret;
+}
+
+static u32 usbg_get_pr_transport_id_len(
+ struct se_portal_group *se_tpg,
+ struct se_node_acl *se_nacl,
+ struct t10_pr_registration *pr_reg,
+ int *format_code)
+{
+ struct usbg_tpg *tpg = container_of(se_tpg,
+ struct usbg_tpg, se_tpg);
+ struct usbg_tport *tport = tpg->tport;
+ int ret = 0;
+
+ switch (tport->tport_proto_id) {
+ case SCSI_PROTOCOL_SAS:
+ default:
+ ret = sas_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg,
+ format_code);
+ break;
+ }
+
+ return ret;
+}
+
+static char *usbg_parse_pr_out_transport_id(
+ struct se_portal_group *se_tpg,
+ const char *buf,
+ u32 *out_tid_len,
+ char **port_nexus_ptr)
+{
+ struct usbg_tpg *tpg = container_of(se_tpg,
+ struct usbg_tpg, se_tpg);
+ struct usbg_tport *tport = tpg->tport;
+ char *tid = NULL;
+
+ switch (tport->tport_proto_id) {
+ case SCSI_PROTOCOL_SAS:
+ default:
+ tid = sas_parse_pr_out_transport_id(se_tpg, buf, out_tid_len,
+ port_nexus_ptr);
+ }
+
+ return tid;
+}
+
+static struct se_node_acl *usbg_alloc_fabric_acl(struct se_portal_group *se_tpg)
+{
+ struct usbg_nacl *nacl;
+
+ nacl = kzalloc(sizeof(struct usbg_nacl), GFP_KERNEL);
+ if (!nacl) {
+ printk(KERN_ERR "Unable to alocate struct usbg_nacl\n");
+ return NULL;
+ }
+
+ return &nacl->se_node_acl;
+}
+
+static void usbg_release_fabric_acl(
+ struct se_portal_group *se_tpg,
+ struct se_node_acl *se_nacl)
+{
+ struct usbg_nacl *nacl = container_of(se_nacl,
+ struct usbg_nacl, se_node_acl);
+ kfree(nacl);
+}
+
+static u32 usbg_tpg_get_inst_index(struct se_portal_group *se_tpg)
+{
+ return 1;
+}
+
+static int usbg_new_cmd(struct se_cmd *se_cmd)
+{
+ struct usbg_cmd *cmd = container_of(se_cmd, struct usbg_cmd,
+ se_cmd);
+ int ret;
+
+ ret = target_setup_cmd_from_cdb(se_cmd, cmd->cmd_buf);
+ if (ret)
+ return ret;
+
+ return transport_generic_map_mem_to_cmd(se_cmd, NULL, 0, NULL, 0);
+}
+
+static void usbg_cmd_release(struct kref *ref)
+{
+ struct usbg_cmd *cmd = container_of(ref, struct usbg_cmd,
+ ref);
+
+ transport_generic_free_cmd(&cmd->se_cmd, 0);
+}
+
+static void usbg_release_cmd(struct se_cmd *se_cmd)
+{
+ struct usbg_cmd *cmd = container_of(se_cmd, struct usbg_cmd,
+ se_cmd);
+ kfree(cmd->data_buf);
+ kfree(cmd);
+ return;
+}
+
+static int usbg_shutdown_session(struct se_session *se_sess)
+{
+ return 0;
+}
+
+static void usbg_close_session(struct se_session *se_sess)
+{
+ return;
+}
+
+static u32 usbg_sess_get_index(struct se_session *se_sess)
+{
+ return 0;
+}
+
+/*
+ * XXX Error recovery: return != 0 if we expect writes. Dunno when that could be
+ */
+static int usbg_write_pending_status(struct se_cmd *se_cmd)
+{
+ return 0;
+}
+
+static void usbg_set_default_node_attrs(struct se_node_acl *nacl)
+{
+ return;
+}
+
+static u32 usbg_get_task_tag(struct se_cmd *se_cmd)
+{
+ struct usbg_cmd *cmd = container_of(se_cmd, struct usbg_cmd,
+ se_cmd);
+ struct f_uas *fu = cmd->fu;
+
+ if (fu->flags & USBG_IS_BOT)
+ return le32_to_cpu(cmd->bot_tag);
+ else
+ return cmd->tag;
+}
+
+static int usbg_get_cmd_state(struct se_cmd *se_cmd)
+{
+ return 0;
+}
+
+static int usbg_queue_tm_rsp(struct se_cmd *se_cmd)
+{
+ return 0;
+}
+
+static u16 usbg_set_fabric_sense_len(struct se_cmd *se_cmd, u32 sense_length)
+{
+ return 0;
+}
+
+static u16 usbg_get_fabric_sense_len(void)
+{
+ return 0;
+}
+
+static const char *usbg_check_wwn(const char *name)
+{
+ const char *n;
+ unsigned int len;
+
+ n = strstr(name, "naa.");
+ if (!n)
+ return NULL;
+ n += 4;
+ len = strlen(n);
+ if (len == 0 || len > USBG_NAMELEN - 1)
+ return NULL;
+ return n;
+}
+
+static struct se_node_acl *usbg_make_nodeacl(
+ struct se_portal_group *se_tpg,
+ struct config_group *group,
+ const char *name)
+{
+ struct se_node_acl *se_nacl, *se_nacl_new;
+ struct usbg_nacl *nacl;
+ u64 wwpn = 0;
+ u32 nexus_depth;
+ const char *wnn_name;
+
+ wnn_name = usbg_check_wwn(name);
+ if (!wnn_name)
+ return ERR_PTR(-EINVAL);
+ se_nacl_new = usbg_alloc_fabric_acl(se_tpg);
+ if (!(se_nacl_new))
+ return ERR_PTR(-ENOMEM);
+
+ nexus_depth = 1;
+ /*
+ * se_nacl_new may be released by core_tpg_add_initiator_node_acl()
+ * when converting a NodeACL from demo mode -> explict
+ */
+ se_nacl = core_tpg_add_initiator_node_acl(se_tpg, se_nacl_new,
+ name, nexus_depth);
+ if (IS_ERR(se_nacl)) {
+ usbg_release_fabric_acl(se_tpg, se_nacl_new);
+ return se_nacl;
+ }
+ /*
+ * Locate our struct usbg_nacl and set the FC Nport WWPN
+ */
+ nacl = container_of(se_nacl, struct usbg_nacl, se_node_acl);
+ nacl->iport_wwpn = wwpn;
+ snprintf(nacl->iport_name, sizeof(nacl->iport_name), "%s", name);
+ return se_nacl;
+}
+
+static void usbg_drop_nodeacl(struct se_node_acl *se_acl)
+{
+ struct usbg_nacl *nacl = container_of(se_acl,
+ struct usbg_nacl, se_node_acl);
+ core_tpg_del_initiator_node_acl(se_acl->se_tpg, se_acl, 1);
+ kfree(nacl);
+}
+
+struct usbg_tpg *the_only_tpg_I_currently_have;
+
+static struct se_portal_group *usbg_make_tpg(
+ struct se_wwn *wwn,
+ struct config_group *group,
+ const char *name)
+{
+ struct usbg_tport *tport = container_of(wwn, struct usbg_tport,
+ tport_wwn);
+ struct usbg_tpg *tpg;
+ unsigned long tpgt;
+ int ret;
+
+ if (strstr(name, "tpgt_") != name)
+ return ERR_PTR(-EINVAL);
+ if (kstrtoul(name + 5, 0, &tpgt) || tpgt > UINT_MAX)
+ return ERR_PTR(-EINVAL);
+ if (the_only_tpg_I_currently_have) {
+ pr_err("Until the gadget framework can't handle multiple\n");
+ pr_err("gadgets, you can't do this here.\n");
+ return ERR_PTR(-EBUSY);
+ }
+
+ tpg = kzalloc(sizeof(struct usbg_tpg), GFP_KERNEL);
+ if (!tpg) {
+ printk(KERN_ERR "Unable to allocate struct usbg_tpg");
+ return ERR_PTR(-ENOMEM);
+ }
+ mutex_init(&tpg->tpg_mutex);
+ atomic_set(&tpg->tpg_port_count, 0);
+ tpg->workqueue = alloc_workqueue("tcm_usb_gadget", 0, 1);
+ if (!tpg->workqueue) {
+ kfree(tpg);
+ return NULL;
+ }
+
+ tpg->tport = tport;
+ tpg->tport_tpgt = tpgt;
+
+ ret = core_tpg_register(&usbg_fabric_configfs->tf_ops, wwn,
+ &tpg->se_tpg, tpg,
+ TRANSPORT_TPG_TYPE_NORMAL);
+ if (ret < 0) {
+ destroy_workqueue(tpg->workqueue);
+ kfree(tpg);
+ return NULL;
+ }
+ the_only_tpg_I_currently_have = tpg;
+ return &tpg->se_tpg;
+}
+
+static void usbg_drop_tpg(struct se_portal_group *se_tpg)
+{
+ struct usbg_tpg *tpg = container_of(se_tpg,
+ struct usbg_tpg, se_tpg);
+
+ core_tpg_deregister(se_tpg);
+ destroy_workqueue(tpg->workqueue);
+ kfree(tpg);
+ the_only_tpg_I_currently_have = NULL;
+}
+
+static struct se_wwn *usbg_make_tport(
+ struct target_fabric_configfs *tf,
+ struct config_group *group,
+ const char *name)
+{
+ struct usbg_tport *tport;
+ const char *wnn_name;
+ u64 wwpn = 0;
+
+ wnn_name = usbg_check_wwn(name);
+ if (!wnn_name)
+ return ERR_PTR(-EINVAL);
+
+ tport = kzalloc(sizeof(struct usbg_tport), GFP_KERNEL);
+ if (!(tport)) {
+ printk(KERN_ERR "Unable to allocate struct usbg_tport");
+ return ERR_PTR(-ENOMEM);
+ }
+ tport->tport_wwpn = wwpn;
+ snprintf(tport->tport_name, sizeof(tport->tport_name), wnn_name);
+ return &tport->tport_wwn;
+}
+
+static void usbg_drop_tport(struct se_wwn *wwn)
+{
+ struct usbg_tport *tport = container_of(wwn,
+ struct usbg_tport, tport_wwn);
+ kfree(tport);
+}
+
+/*
+ * If somebody feels like dropping the version property, go ahead.
+ */
+static ssize_t usbg_wwn_show_attr_version(
+ struct target_fabric_configfs *tf,
+ char *page)
+{
+ return sprintf(page, "usb-gadget fabric module\n");
+}
+TF_WWN_ATTR_RO(usbg, version);
+
+static struct configfs_attribute *usbg_wwn_attrs[] = {
+ &usbg_wwn_version.attr,
+ NULL,
+};
+
+static ssize_t tcm_usbg_tpg_show_enable(
+ struct se_portal_group *se_tpg,
+ char *page)
+{
+ struct usbg_tpg *tpg = container_of(se_tpg, struct usbg_tpg, se_tpg);
+
+ return snprintf(page, PAGE_SIZE, "%u\n", tpg->gadget_connect);
+}
+
+static int usbg_attach(struct usbg_tpg *tpg)
+{
+ return usbg_connect_cb(true);
+}
+
+static void usbg_detach(struct usbg_tpg *tpg)
+{
+ usbg_connect_cb(false);
+}
+
+static ssize_t tcm_usbg_tpg_store_enable(
+ struct se_portal_group *se_tpg,
+ const char *page,
+ size_t count)
+{
+ struct usbg_tpg *tpg = container_of(se_tpg, struct usbg_tpg, se_tpg);
+ unsigned long op;
+ ssize_t ret;
+
+ ret = kstrtoul(page, 0, &op);
+ if (ret < 0)
+ return -EINVAL;
+ if (op > 1)
+ return -EINVAL;
+
+ if (op && tpg->gadget_connect)
+ goto out;
+ if (!op && !tpg->gadget_connect)
+ goto out;
+
+ if (op) {
+ ret = usbg_attach(tpg);
+ if (ret)
+ goto out;
+ } else {
+ usbg_detach(tpg);
+ }
+ tpg->gadget_connect = op;
+out:
+ return count;
+}
+TF_TPG_BASE_ATTR(tcm_usbg, enable, S_IRUGO | S_IWUSR);
+
+static ssize_t tcm_usbg_tpg_show_nexus(
+ struct se_portal_group *se_tpg,
+ char *page)
+{
+ struct usbg_tpg *tpg = container_of(se_tpg, struct usbg_tpg, se_tpg);
+ struct tcm_usbg_nexus *tv_nexus;
+ ssize_t ret;
+
+ mutex_lock(&tpg->tpg_mutex);
+ tv_nexus = tpg->tpg_nexus;
+ if (!tv_nexus) {
+ ret = -ENODEV;
+ goto out;
+ }
+ ret = snprintf(page, PAGE_SIZE, "%s\n",
+ tv_nexus->tvn_se_sess->se_node_acl->initiatorname);
+out:
+ mutex_unlock(&tpg->tpg_mutex);
+ return ret;
+}
+
+static int tcm_usbg_make_nexus(struct usbg_tpg *tpg, char *name)
+{
+ struct se_portal_group *se_tpg;
+ struct tcm_usbg_nexus *tv_nexus;
+ int ret;
+
+ mutex_lock(&tpg->tpg_mutex);
+ if (tpg->tpg_nexus) {
+ ret = -EEXIST;
+ pr_debug("tpg->tpg_nexus already exists\n");
+ goto err_unlock;
+ }
+ se_tpg = &tpg->se_tpg;
+
+ ret = -ENOMEM;
+ tv_nexus = kzalloc(sizeof(*tv_nexus), GFP_KERNEL);
+ if (!tv_nexus) {
+ pr_err("Unable to allocate struct tcm_vhost_nexus\n");
+ goto err_unlock;
+ }
+ tv_nexus->tvn_se_sess = transport_init_session();
+ if (IS_ERR(tv_nexus->tvn_se_sess))
+ goto err_free;
+
+ /*
+ * Since we are running in 'demo mode' this call with generate a
+ * struct se_node_acl for the tcm_vhost struct se_portal_group with
+ * the SCSI Initiator port name of the passed configfs group 'name'.
+ */
+ tv_nexus->tvn_se_sess->se_node_acl = core_tpg_check_initiator_node_acl(
+ se_tpg, name);
+ if (!tv_nexus->tvn_se_sess->se_node_acl) {
+ pr_debug("core_tpg_check_initiator_node_acl() failed"
+ " for %s\n", name);
+ goto err_session;
+ }
+ /*
+ * Now register the TCM vHost virtual I_T Nexus as active with the
+ * call to __transport_register_session()
+ */
+ __transport_register_session(se_tpg, tv_nexus->tvn_se_sess->se_node_acl,
+ tv_nexus->tvn_se_sess, tv_nexus);
+ tpg->tpg_nexus = tv_nexus;
+ mutex_unlock(&tpg->tpg_mutex);
+ return 0;
+
+err_session:
+ transport_free_session(tv_nexus->tvn_se_sess);
+err_free:
+ kfree(tv_nexus);
+err_unlock:
+ mutex_unlock(&tpg->tpg_mutex);
+ return ret;
+}
+
+static int tcm_usbg_drop_nexus(struct usbg_tpg *tpg)
+{
+ struct se_session *se_sess;
+ struct tcm_usbg_nexus *tv_nexus;
+ int ret = -ENODEV;
+
+ mutex_lock(&tpg->tpg_mutex);
+ tv_nexus = tpg->tpg_nexus;
+ if (!tv_nexus)
+ goto out;
+
+ se_sess = tv_nexus->tvn_se_sess;
+ if (!se_sess)
+ goto out;
+
+ if (atomic_read(&tpg->tpg_port_count)) {
+ ret = -EPERM;
+ pr_err("Unable to remove Host I_T Nexus with"
+ " active TPG port count: %d\n",
+ atomic_read(&tpg->tpg_port_count));
+ goto out;
+ }
+
+ pr_debug("Removing I_T Nexus to Initiator Port: %s\n",
+ tv_nexus->tvn_se_sess->se_node_acl->initiatorname);
+ /*
+ * Release the SCSI I_T Nexus to the emulated vHost Target Port
+ */
+ transport_deregister_session(tv_nexus->tvn_se_sess);
+ tpg->tpg_nexus = NULL;
+
+ kfree(tv_nexus);
+out:
+ mutex_unlock(&tpg->tpg_mutex);
+ return 0;
+}
+
+static ssize_t tcm_usbg_tpg_store_nexus(
+ struct se_portal_group *se_tpg,
+ const char *page,
+ size_t count)
+{
+ struct usbg_tpg *tpg = container_of(se_tpg, struct usbg_tpg, se_tpg);
+ unsigned char i_port[USBG_NAMELEN], *ptr;
+ int ret;
+
+ if (!strncmp(page, "NULL", 4)) {
+ ret = tcm_usbg_drop_nexus(tpg);
+ return (!ret) ? count : ret;
+ }
+ if (strlen(page) > USBG_NAMELEN) {
+ pr_err("Emulated NAA Sas Address: %s, exceeds"
+ " max: %d\n", page, USBG_NAMELEN);
+ return -EINVAL;
+ }
+ snprintf(i_port, USBG_NAMELEN, "%s", page);
+
+ ptr = strstr(i_port, "naa.");
+ if (!ptr) {
+ pr_err("Missing 'naa.' prefix\n");
+ return -EINVAL;
+ }
+
+ if (i_port[strlen(i_port) - 1] == '\n')
+ i_port[strlen(i_port) - 1] = '\0';
+
+ ret = tcm_usbg_make_nexus(tpg, &i_port[4]);
+ if (ret < 0)
+ return ret;
+ return count;
+}
+TF_TPG_BASE_ATTR(tcm_usbg, nexus, S_IRUGO | S_IWUSR);
+
+static struct configfs_attribute *usbg_base_attrs[] = {
+ &tcm_usbg_tpg_enable.attr,
+ &tcm_usbg_tpg_nexus.attr,
+ NULL,
+};
+
+static int usbg_port_link(struct se_portal_group *se_tpg, struct se_lun *lun)
+{
+ struct usbg_tpg *tpg = container_of(se_tpg, struct usbg_tpg, se_tpg);
+
+ atomic_inc(&tpg->tpg_port_count);
+ smp_mb__after_atomic_inc();
+ return 0;
+}
+
+static void usbg_port_unlink(struct se_portal_group *se_tpg,
+ struct se_lun *se_lun)
+{
+ struct usbg_tpg *tpg = container_of(se_tpg, struct usbg_tpg, se_tpg);
+
+ atomic_dec(&tpg->tpg_port_count);
+ smp_mb__after_atomic_dec();
+}
+
+static int usbg_check_stop_free(struct se_cmd *se_cmd)
+{
+ struct usbg_cmd *cmd = container_of(se_cmd, struct usbg_cmd,
+ se_cmd);
+
+ kref_put(&cmd->ref, usbg_cmd_release);
+ return 1;
+}
+
+static struct target_core_fabric_ops usbg_ops = {
+ .get_fabric_name = usbg_get_fabric_name,
+ .get_fabric_proto_ident = usbg_get_fabric_proto_ident,
+ .tpg_get_wwn = usbg_get_fabric_wwn,
+ .tpg_get_tag = usbg_get_tag,
+ .tpg_get_default_depth = usbg_get_default_depth,
+ .tpg_get_pr_transport_id = usbg_get_pr_transport_id,
+ .tpg_get_pr_transport_id_len = usbg_get_pr_transport_id_len,
+ .tpg_parse_pr_out_transport_id = usbg_parse_pr_out_transport_id,
+ .tpg_check_demo_mode = usbg_check_true,
+ .tpg_check_demo_mode_cache = usbg_check_false,
+ .tpg_check_demo_mode_write_protect = usbg_check_false,
+ .tpg_check_prod_mode_write_protect = usbg_check_false,
+ .tpg_alloc_fabric_acl = usbg_alloc_fabric_acl,
+ .tpg_release_fabric_acl = usbg_release_fabric_acl,
+ .tpg_get_inst_index = usbg_tpg_get_inst_index,
+ .new_cmd_map = usbg_new_cmd,
+ .release_cmd = usbg_release_cmd,
+ .shutdown_session = usbg_shutdown_session,
+ .close_session = usbg_close_session,
+ .sess_get_index = usbg_sess_get_index,
+ .sess_get_initiator_sid = NULL,
+ .write_pending = usbg_send_write_request,
+ .write_pending_status = usbg_write_pending_status,
+ .set_default_node_attributes = usbg_set_default_node_attrs,
+ .get_task_tag = usbg_get_task_tag,
+ .get_cmd_state = usbg_get_cmd_state,
+ .queue_data_in = usbg_send_read_response,
+ .queue_status = usbg_send_status_response,
+ .queue_tm_rsp = usbg_queue_tm_rsp,
+ .get_fabric_sense_len = usbg_get_fabric_sense_len,
+ .set_fabric_sense_len = usbg_set_fabric_sense_len,
+ .check_stop_free = usbg_check_stop_free,
+
+ .fabric_make_wwn = usbg_make_tport,
+ .fabric_drop_wwn = usbg_drop_tport,
+ .fabric_make_tpg = usbg_make_tpg,
+ .fabric_drop_tpg = usbg_drop_tpg,
+ .fabric_post_link = usbg_port_link,
+ .fabric_pre_unlink = usbg_port_unlink,
+ .fabric_make_np = NULL,
+ .fabric_drop_np = NULL,
+ .fabric_make_nodeacl = usbg_make_nodeacl,
+ .fabric_drop_nodeacl = usbg_drop_nodeacl,
+};
+
+static int usbg_register_configfs(void)
+{
+ struct target_fabric_configfs *fabric;
+ int ret;
+
+ fabric = target_fabric_configfs_init(THIS_MODULE, "usb_gadget");
+ if (IS_ERR(fabric)) {
+ printk(KERN_ERR "target_fabric_configfs_init() failed\n");
+ return PTR_ERR(fabric);
+ }
+
+ fabric->tf_ops = usbg_ops;
+ TF_CIT_TMPL(fabric)->tfc_wwn_cit.ct_attrs = usbg_wwn_attrs;
+ TF_CIT_TMPL(fabric)->tfc_tpg_base_cit.ct_attrs = usbg_base_attrs;
+ TF_CIT_TMPL(fabric)->tfc_tpg_attrib_cit.ct_attrs = NULL;
+ TF_CIT_TMPL(fabric)->tfc_tpg_param_cit.ct_attrs = NULL;
+ TF_CIT_TMPL(fabric)->tfc_tpg_np_base_cit.ct_attrs = NULL;
+ TF_CIT_TMPL(fabric)->tfc_tpg_nacl_base_cit.ct_attrs = NULL;
+ TF_CIT_TMPL(fabric)->tfc_tpg_nacl_attrib_cit.ct_attrs = NULL;
+ TF_CIT_TMPL(fabric)->tfc_tpg_nacl_auth_cit.ct_attrs = NULL;
+ TF_CIT_TMPL(fabric)->tfc_tpg_nacl_param_cit.ct_attrs = NULL;
+ ret = target_fabric_configfs_register(fabric);
+ if (ret < 0) {
+ printk(KERN_ERR "target_fabric_configfs_register() failed"
+ " for usb-gadget\n");
+ return ret;
+ }
+ usbg_fabric_configfs = fabric;
+ return 0;
+};
+
+static void usbg_deregister_configfs(void)
+{
+ if (!(usbg_fabric_configfs))
+ return;
+
+ target_fabric_configfs_deregister(usbg_fabric_configfs);
+ usbg_fabric_configfs = NULL;
+};
+
+/* Start gadget.c code */
+
+static struct usb_interface_descriptor bot_intf_desc = {
+ .bLength = sizeof(bot_intf_desc),
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 2,
+ .bAlternateSetting = USB_G_ALT_INT_BBB,
+ .bInterfaceClass = USB_CLASS_MASS_STORAGE,
+ .bInterfaceSubClass = USB_SC_SCSI,
+ .bInterfaceProtocol = USB_PR_BULK,
+ /* .iInterface = DYNAMIC */
+};
+
+static struct usb_interface_descriptor uasp_intf_desc = {
+ .bLength = sizeof(uasp_intf_desc),
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bNumEndpoints = 4,
+ .bAlternateSetting = USB_G_ALT_INT_UAS,
+ .bInterfaceClass = USB_CLASS_MASS_STORAGE,
+ .bInterfaceSubClass = USB_SC_SCSI,
+ .bInterfaceProtocol = USB_PR_UAS,
+ /* .iInterface = DYNAMIC */
+};
+
+static struct usb_endpoint_descriptor uasp_bi_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor uasp_fs_bi_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_pipe_usage_descriptor uasp_bi_pipe_desc = {
+ .bLength = sizeof(uasp_bi_pipe_desc),
+ .bDescriptorType = USB_DT_PIPE_USAGE,
+ .bPipeID = DATA_IN_PIPE_ID,
+};
+
+static struct usb_endpoint_descriptor uasp_ss_bi_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = cpu_to_le16(1024),
+};
+
+static struct usb_ss_ep_comp_descriptor uasp_bi_ep_comp_desc = {
+ .bLength = sizeof(uasp_bi_ep_comp_desc),
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+ .bMaxBurst = 0,
+ .bmAttributes = UASP_SS_EP_COMP_LOG_STREAMS,
+ .wBytesPerInterval = 0,
+};
+
+static struct usb_ss_ep_comp_descriptor bot_bi_ep_comp_desc = {
+ .bLength = sizeof(bot_bi_ep_comp_desc),
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+ .bMaxBurst = 0,
+};
+
+static struct usb_endpoint_descriptor uasp_bo_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor uasp_fs_bo_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_pipe_usage_descriptor uasp_bo_pipe_desc = {
+ .bLength = sizeof(uasp_bo_pipe_desc),
+ .bDescriptorType = USB_DT_PIPE_USAGE,
+ .bPipeID = DATA_OUT_PIPE_ID,
+};
+
+static struct usb_endpoint_descriptor uasp_ss_bo_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = cpu_to_le16(0x400),
+};
+
+static struct usb_ss_ep_comp_descriptor uasp_bo_ep_comp_desc = {
+ .bLength = sizeof(uasp_bo_ep_comp_desc),
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+ .bmAttributes = UASP_SS_EP_COMP_LOG_STREAMS,
+};
+
+static struct usb_ss_ep_comp_descriptor bot_bo_ep_comp_desc = {
+ .bLength = sizeof(bot_bo_ep_comp_desc),
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+};
+
+static struct usb_endpoint_descriptor uasp_status_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor uasp_fs_status_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_pipe_usage_descriptor uasp_status_pipe_desc = {
+ .bLength = sizeof(uasp_status_pipe_desc),
+ .bDescriptorType = USB_DT_PIPE_USAGE,
+ .bPipeID = STATUS_PIPE_ID,
+};
+
+static struct usb_endpoint_descriptor uasp_ss_status_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = cpu_to_le16(1024),
+};
+
+static struct usb_ss_ep_comp_descriptor uasp_status_in_ep_comp_desc = {
+ .bLength = sizeof(uasp_status_in_ep_comp_desc),
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+ .bmAttributes = UASP_SS_EP_COMP_LOG_STREAMS,
+};
+
+static struct usb_endpoint_descriptor uasp_cmd_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor uasp_fs_cmd_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_pipe_usage_descriptor uasp_cmd_pipe_desc = {
+ .bLength = sizeof(uasp_cmd_pipe_desc),
+ .bDescriptorType = USB_DT_PIPE_USAGE,
+ .bPipeID = CMD_PIPE_ID,
+};
+
+static struct usb_endpoint_descriptor uasp_ss_cmd_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = cpu_to_le16(1024),
+};
+
+static struct usb_ss_ep_comp_descriptor uasp_cmd_comp_desc = {
+ .bLength = sizeof(uasp_cmd_comp_desc),
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+};
+
+static struct usb_descriptor_header *uasp_fs_function_desc[] = {
+ (struct usb_descriptor_header *) &bot_intf_desc,
+ (struct usb_descriptor_header *) &uasp_fs_bi_desc,
+ (struct usb_descriptor_header *) &uasp_fs_bo_desc,
+
+ (struct usb_descriptor_header *) &uasp_intf_desc,
+ (struct usb_descriptor_header *) &uasp_fs_bi_desc,
+ (struct usb_descriptor_header *) &uasp_bi_pipe_desc,
+ (struct usb_descriptor_header *) &uasp_fs_bo_desc,
+ (struct usb_descriptor_header *) &uasp_bo_pipe_desc,
+ (struct usb_descriptor_header *) &uasp_fs_status_desc,
+ (struct usb_descriptor_header *) &uasp_status_pipe_desc,
+ (struct usb_descriptor_header *) &uasp_fs_cmd_desc,
+ (struct usb_descriptor_header *) &uasp_cmd_pipe_desc,
+};
+
+static struct usb_descriptor_header *uasp_hs_function_desc[] = {
+ (struct usb_descriptor_header *) &bot_intf_desc,
+ (struct usb_descriptor_header *) &uasp_bi_desc,
+ (struct usb_descriptor_header *) &uasp_bo_desc,
+
+ (struct usb_descriptor_header *) &uasp_intf_desc,
+ (struct usb_descriptor_header *) &uasp_bi_desc,
+ (struct usb_descriptor_header *) &uasp_bi_pipe_desc,
+ (struct usb_descriptor_header *) &uasp_bo_desc,
+ (struct usb_descriptor_header *) &uasp_bo_pipe_desc,
+ (struct usb_descriptor_header *) &uasp_status_desc,
+ (struct usb_descriptor_header *) &uasp_status_pipe_desc,
+ (struct usb_descriptor_header *) &uasp_cmd_desc,
+ (struct usb_descriptor_header *) &uasp_cmd_pipe_desc,
+ NULL,
+};
+
+static struct usb_descriptor_header *uasp_ss_function_desc[] = {
+ (struct usb_descriptor_header *) &bot_intf_desc,
+ (struct usb_descriptor_header *) &uasp_ss_bi_desc,
+ (struct usb_descriptor_header *) &bot_bi_ep_comp_desc,
+ (struct usb_descriptor_header *) &uasp_ss_bo_desc,
+ (struct usb_descriptor_header *) &bot_bo_ep_comp_desc,
+
+ (struct usb_descriptor_header *) &uasp_intf_desc,
+ (struct usb_descriptor_header *) &uasp_ss_bi_desc,
+ (struct usb_descriptor_header *) &uasp_bi_ep_comp_desc,
+ (struct usb_descriptor_header *) &uasp_bi_pipe_desc,
+ (struct usb_descriptor_header *) &uasp_ss_bo_desc,
+ (struct usb_descriptor_header *) &uasp_bo_ep_comp_desc,
+ (struct usb_descriptor_header *) &uasp_bo_pipe_desc,
+ (struct usb_descriptor_header *) &uasp_ss_status_desc,
+ (struct usb_descriptor_header *) &uasp_status_in_ep_comp_desc,
+ (struct usb_descriptor_header *) &uasp_status_pipe_desc,
+ (struct usb_descriptor_header *) &uasp_ss_cmd_desc,
+ (struct usb_descriptor_header *) &uasp_cmd_comp_desc,
+ (struct usb_descriptor_header *) &uasp_cmd_pipe_desc,
+ NULL,
+};
+
+static struct usb_string tcm_us_strings[] = {
+ [0].s = "Bulk Only Transport",
+ [1].s = "USB Attached SCSI",
+ { } /* end of list */
+};
+
+static struct usb_gadget_strings tcm_stringtab = {
+ .language = 0x0409,
+ .strings = tcm_us_strings,
+};
+
+static struct usb_gadget_strings *tcm_strings[] = {
+ &tcm_stringtab,
+ NULL,
+};
+
+static void give_back_ep(struct usb_ep **pep)
+{
+ struct usb_ep *ep = *pep;
+ if (!ep)
+ return;
+ ep->driver_data = NULL;
+}
+
+static int usbg_bind(struct usb_configuration *c, struct usb_function *f)
+{
+ struct f_uas *fu = to_f_uas(f);
+ struct usb_gadget *gadget = c->cdev->gadget;
+ struct usb_ep *ep;
+ int iface;
+
+ iface = usb_interface_id(c, f);
+ if (iface < 0)
+ return iface;
+
+ bot_intf_desc.bInterfaceNumber = iface;
+ uasp_intf_desc.bInterfaceNumber = iface;
+ fu->iface = iface;
+ ep = usb_ep_autoconfig_ss(gadget, &uasp_ss_bi_desc,
+ &uasp_bi_ep_comp_desc);
+ if (!ep)
+ goto ep_fail;
+
+ ep->driver_data = fu;
+ fu->ep_in = ep;
+
+ ep = usb_ep_autoconfig_ss(gadget, &uasp_ss_bo_desc,
+ &uasp_bo_ep_comp_desc);
+ if (!ep)
+ goto ep_fail;
+ ep->driver_data = fu;
+ fu->ep_out = ep;
+
+ ep = usb_ep_autoconfig_ss(gadget, &uasp_ss_status_desc,
+ &uasp_status_in_ep_comp_desc);
+ if (!ep)
+ goto ep_fail;
+ ep->driver_data = fu;
+ fu->ep_status = ep;
+
+ ep = usb_ep_autoconfig_ss(gadget, &uasp_ss_cmd_desc,
+ &uasp_cmd_comp_desc);
+ if (!ep)
+ goto ep_fail;
+ ep->driver_data = fu;
+ fu->ep_cmd = ep;
+
+ /* Assume endpoint addresses are the same for both speeds */
+ uasp_bi_desc.bEndpointAddress = uasp_ss_bi_desc.bEndpointAddress;
+ uasp_bo_desc.bEndpointAddress = uasp_ss_bo_desc.bEndpointAddress;
+ uasp_status_desc.bEndpointAddress =
+ uasp_ss_status_desc.bEndpointAddress;
+ uasp_cmd_desc.bEndpointAddress = uasp_ss_cmd_desc.bEndpointAddress;
+
+ uasp_fs_bi_desc.bEndpointAddress = uasp_ss_bi_desc.bEndpointAddress;
+ uasp_fs_bo_desc.bEndpointAddress = uasp_ss_bo_desc.bEndpointAddress;
+ uasp_fs_status_desc.bEndpointAddress =
+ uasp_ss_status_desc.bEndpointAddress;
+ uasp_fs_cmd_desc.bEndpointAddress = uasp_ss_cmd_desc.bEndpointAddress;
+
+ return 0;
+ep_fail:
+ pr_err("Can't claim all required eps\n");
+
+ give_back_ep(&fu->ep_in);
+ give_back_ep(&fu->ep_out);
+ give_back_ep(&fu->ep_status);
+ give_back_ep(&fu->ep_cmd);
+ return -ENOTSUPP;
+}
+
+static void usbg_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+ struct f_uas *fu = to_f_uas(f);
+
+ kfree(fu);
+}
+
+struct guas_setup_wq {
+ struct work_struct work;
+ struct f_uas *fu;
+ unsigned int alt;
+};
+
+static void usbg_delayed_set_alt(struct work_struct *wq)
+{
+ struct guas_setup_wq *work = container_of(wq, struct guas_setup_wq,
+ work);
+ struct f_uas *fu = work->fu;
+ int alt = work->alt;
+
+ kfree(work);
+
+ if (fu->flags & USBG_IS_BOT)
+ bot_cleanup_old_alt(fu);
+ if (fu->flags & USBG_IS_UAS)
+ uasp_cleanup_old_alt(fu);
+
+ if (alt == USB_G_ALT_INT_BBB)
+ bot_set_alt(fu);
+ else if (alt == USB_G_ALT_INT_UAS)
+ uasp_set_alt(fu);
+ usb_composite_setup_continue(fu->function.config->cdev);
+}
+
+static int usbg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+{
+ struct f_uas *fu = to_f_uas(f);
+
+ if ((alt == USB_G_ALT_INT_BBB) || (alt == USB_G_ALT_INT_UAS)) {
+ struct guas_setup_wq *work;
+
+ work = kmalloc(sizeof(*work), GFP_ATOMIC);
+ if (!work)
+ return -ENOMEM;
+ INIT_WORK(&work->work, usbg_delayed_set_alt);
+ work->fu = fu;
+ work->alt = alt;
+ schedule_work(&work->work);
+ return USB_GADGET_DELAYED_STATUS;
+ }
+ return -EOPNOTSUPP;
+}
+
+static void usbg_disable(struct usb_function *f)
+{
+ struct f_uas *fu = to_f_uas(f);
+
+ if (fu->flags & USBG_IS_UAS)
+ uasp_cleanup_old_alt(fu);
+ else if (fu->flags & USBG_IS_BOT)
+ bot_cleanup_old_alt(fu);
+ fu->flags = 0;
+}
+
+static int usbg_setup(struct usb_function *f,
+ const struct usb_ctrlrequest *ctrl)
+{
+ struct f_uas *fu = to_f_uas(f);
+
+ if (!(fu->flags & USBG_IS_BOT))
+ return -EOPNOTSUPP;
+
+ return usbg_bot_setup(f, ctrl);
+}
+
+static int tcm_bind_config(struct usb_configuration *c)
+{
+ struct f_uas *fu;
+ int ret;
+
+ fu = kzalloc(sizeof(*fu), GFP_KERNEL);
+ if (!fu)
+ return -ENOMEM;
+ fu->function.name = "Target Function";
+ fu->function.descriptors = uasp_fs_function_desc;
+ fu->function.hs_descriptors = uasp_hs_function_desc;
+ fu->function.ss_descriptors = uasp_ss_function_desc;
+ fu->function.strings = tcm_strings;
+ fu->function.bind = usbg_bind;
+ fu->function.unbind = usbg_unbind;
+ fu->function.set_alt = usbg_set_alt;
+ fu->function.setup = usbg_setup;
+ fu->function.disable = usbg_disable;
+ fu->tpg = the_only_tpg_I_currently_have;
+
+ /* BOT interface string */
+ ret = usb_string_id(c->cdev);
+ if (ret < 0)
+ goto err;
+ tcm_us_strings[0].id = ret;
+ bot_intf_desc.iInterface = ret;
+
+ /* data interface label */
+ ret = usb_string_id(c->cdev);
+ if (ret < 0)
+ goto err;
+ tcm_us_strings[1].id = ret;
+ uasp_intf_desc.iInterface = ret;
+
+ ret = usb_add_function(c, &fu->function);
+ if (ret)
+ goto err;
+
+ return 0;
+err:
+ kfree(fu);
+ return ret;
+}
+
+static int f_tcm_init(int (*connect_cb)(bool connect))
+{
+ int ret;
+
+ usbg_connect_cb = connect_cb;
+ ret = usbg_register_configfs();
+ return ret;
+}
+
+static void f_tcm_exit(void)
+{
+ usbg_deregister_configfs();
+ usbg_connect_cb = NULL;
+}
diff --git a/drivers/usb/gadget/tcm_usb_gadget.h b/drivers/usb/gadget/f_tcm.h
similarity index 93%
rename from drivers/usb/gadget/tcm_usb_gadget.h
rename to drivers/usb/gadget/f_tcm.h
index bb18999..bed8435 100644
--- a/drivers/usb/gadget/tcm_usb_gadget.h
+++ b/drivers/usb/gadget/f_tcm.h
@@ -16,13 +16,6 @@
#define UASP_SS_EP_COMP_LOG_STREAMS 4
#define UASP_SS_EP_COMP_NUM_STREAMS (1 << UASP_SS_EP_COMP_LOG_STREAMS)
-#define USB_G_STR_MANUFACTOR 1
-#define USB_G_STR_PRODUCT 2
-#define USB_G_STR_SERIAL 3
-#define USB_G_STR_CONFIG 4
-#define USB_G_STR_INT_UAS 5
-#define USB_G_STR_INT_BBB 6
-
#define USB_G_ALT_INT_BBB 0
#define USB_G_ALT_INT_UAS 1
diff --git a/drivers/usb/gadget/tcm_usb_gadget.c b/drivers/usb/gadget/tcm_usb_gadget.c
index c46439c..8787768 100644
--- a/drivers/usb/gadget/tcm_usb_gadget.c
+++ b/drivers/usb/gadget/tcm_usb_gadget.c
@@ -1,4 +1,4 @@
-/* Target based USB-Gadget
+/* Target based USB-Gadget Function
*
* UAS protocol handling, target callbacks, configfs handling,
* BBB (USB Mass Storage Class Bulk-Only (BBB) and Transport protocol handling.
@@ -6,2208 +6,28 @@
* Author: Sebastian Andrzej Siewior <bigeasy at linutronix dot de>
* License: GPLv2 as published by FSF.
*/
-#include <linux/kernel.h>
+
+#include <linux/init.h>
#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/configfs.h>
-#include <linux/ctype.h>
-#include <linux/usb/ch9.h>
+
#include <linux/usb/composite.h>
#include <linux/usb/gadget.h>
-#include <linux/usb/storage.h>
-#include <scsi/scsi.h>
-#include <scsi/scsi_tcq.h>
-#include <target/target_core_base.h>
-#include <target/target_core_fabric.h>
-#include <target/target_core_fabric_configfs.h>
-#include <target/target_core_configfs.h>
-#include <target/configfs_macros.h>
-#include <asm/unaligned.h>
#include "usbstring.c"
#include "epautoconf.c"
#include "config.c"
#include "composite.c"
-#include "tcm_usb_gadget.h"
-
-static struct target_fabric_configfs *usbg_fabric_configfs;
-
-static inline struct f_uas *to_f_uas(struct usb_function *f)
-{
- return container_of(f, struct f_uas, function);
-}
-
-static void usbg_cmd_release(struct kref *);
-
-static inline void usbg_cleanup_cmd(struct usbg_cmd *cmd)
-{
- kref_put(&cmd->ref, usbg_cmd_release);
-}
-
-/* Start bot.c code */
-
-static int bot_enqueue_cmd_cbw(struct f_uas *fu)
-{
- int ret;
-
- if (fu->flags & USBG_BOT_CMD_PEND)
- return 0;
-
- ret = usb_ep_queue(fu->ep_out, fu->cmd.req, GFP_ATOMIC);
- if (!ret)
- fu->flags |= USBG_BOT_CMD_PEND;
- return ret;
-}
-
-static void bot_status_complete(struct usb_ep *ep, struct usb_request *req)
-{
- struct usbg_cmd *cmd = req->context;
- struct f_uas *fu = cmd->fu;
-
- usbg_cleanup_cmd(cmd);
- if (req->status < 0) {
- pr_err("ERR %s(%d)\n", __func__, __LINE__);
- return;
- }
-
- /* CSW completed, wait for next CBW */
- bot_enqueue_cmd_cbw(fu);
-}
-
-static void bot_enqueue_sense_code(struct f_uas *fu, struct usbg_cmd *cmd)
-{
- struct bulk_cs_wrap *csw = &fu->bot_status.csw;
- int ret;
- u8 *sense;
- unsigned int csw_stat;
-
- csw_stat = cmd->csw_code;
-
- /*
- * We can't send SENSE as a response. So we take ASC & ASCQ from our
- * sense buffer and queue it and hope the host sends a REQUEST_SENSE
- * command where it learns why we failed.
- */
- sense = cmd->sense_iu.sense;
-
- csw->Tag = cmd->bot_tag;
- csw->Status = csw_stat;
- fu->bot_status.req->context = cmd;
- ret = usb_ep_queue(fu->ep_in, fu->bot_status.req, GFP_ATOMIC);
- if (ret)
- pr_err("%s(%d) ERR: %d\n", __func__, __LINE__, ret);
-}
-
-static void bot_err_compl(struct usb_ep *ep, struct usb_request *req)
-{
- struct usbg_cmd *cmd = req->context;
- struct f_uas *fu = cmd->fu;
-
- if (req->status < 0)
- pr_err("ERR %s(%d)\n", __func__, __LINE__);
-
- if (cmd->data_len) {
- if (cmd->data_len > ep->maxpacket) {
- req->length = ep->maxpacket;
- cmd->data_len -= ep->maxpacket;
- } else {
- req->length = cmd->data_len;
- cmd->data_len = 0;
- }
-
- usb_ep_queue(ep, req, GFP_ATOMIC);
- return ;
- }
- bot_enqueue_sense_code(fu, cmd);
-}
-
-static void bot_send_bad_status(struct usbg_cmd *cmd)
-{
- struct f_uas *fu = cmd->fu;
- struct bulk_cs_wrap *csw = &fu->bot_status.csw;
- struct usb_request *req;
- struct usb_ep *ep;
-
- csw->Residue = cpu_to_le32(cmd->data_len);
-
- if (cmd->data_len) {
- if (cmd->is_read) {
- ep = fu->ep_in;
- req = fu->bot_req_in;
- } else {
- ep = fu->ep_out;
- req = fu->bot_req_out;
- }
-
- if (cmd->data_len > fu->ep_in->maxpacket) {
- req->length = ep->maxpacket;
- cmd->data_len -= ep->maxpacket;
- } else {
- req->length = cmd->data_len;
- cmd->data_len = 0;
- }
- req->complete = bot_err_compl;
- req->context = cmd;
- req->buf = fu->cmd.buf;
- usb_ep_queue(ep, req, GFP_KERNEL);
- } else {
- bot_enqueue_sense_code(fu, cmd);
- }
-}
-
-static int bot_send_status(struct usbg_cmd *cmd, bool moved_data)
-{
- struct f_uas *fu = cmd->fu;
- struct bulk_cs_wrap *csw = &fu->bot_status.csw;
- int ret;
-
- if (cmd->se_cmd.scsi_status == SAM_STAT_GOOD) {
- if (!moved_data && cmd->data_len) {
- /*
- * the host wants to move data, we don't. Fill / empty
- * the pipe and then send the csw with reside set.
- */
- cmd->csw_code = US_BULK_STAT_OK;
- bot_send_bad_status(cmd);
- return 0;
- }
-
- csw->Tag = cmd->bot_tag;
- csw->Residue = cpu_to_le32(0);
- csw->Status = US_BULK_STAT_OK;
- fu->bot_status.req->context = cmd;
-
- ret = usb_ep_queue(fu->ep_in, fu->bot_status.req, GFP_KERNEL);
- if (ret)
- pr_err("%s(%d) ERR: %d\n", __func__, __LINE__, ret);
- } else {
- cmd->csw_code = US_BULK_STAT_FAIL;
- bot_send_bad_status(cmd);
- }
- return 0;
-}
-
-/*
- * Called after command (no data transfer) or after the write (to device)
- * operation is completed
- */
-static int bot_send_status_response(struct usbg_cmd *cmd)
-{
- bool moved_data = false;
-
- if (!cmd->is_read)
- moved_data = true;
- return bot_send_status(cmd, moved_data);
-}
-
-/* Read request completed, now we have to send the CSW */
-static void bot_read_compl(struct usb_ep *ep, struct usb_request *req)
-{
- struct usbg_cmd *cmd = req->context;
-
- if (req->status < 0)
- pr_err("ERR %s(%d)\n", __func__, __LINE__);
-
- bot_send_status(cmd, true);
-}
-
-static int bot_send_read_response(struct usbg_cmd *cmd)
-{
- struct f_uas *fu = cmd->fu;
- struct se_cmd *se_cmd = &cmd->se_cmd;
- struct usb_gadget *gadget = fuas_to_gadget(fu);
- int ret;
-
- if (!cmd->data_len) {
- cmd->csw_code = US_BULK_STAT_PHASE;
- bot_send_bad_status(cmd);
- return 0;
- }
-
- if (!gadget->sg_supported) {
- cmd->data_buf = kmalloc(se_cmd->data_length, GFP_ATOMIC);
- if (!cmd->data_buf)
- return -ENOMEM;
-
- sg_copy_to_buffer(se_cmd->t_data_sg,
- se_cmd->t_data_nents,
- cmd->data_buf,
- se_cmd->data_length);
-
- fu->bot_req_in->buf = cmd->data_buf;
- } else {
- fu->bot_req_in->buf = NULL;
- fu->bot_req_in->num_sgs = se_cmd->t_data_nents;
- fu->bot_req_in->sg = se_cmd->t_data_sg;
- }
-
- fu->bot_req_in->complete = bot_read_compl;
- fu->bot_req_in->length = se_cmd->data_length;
- fu->bot_req_in->context = cmd;
- ret = usb_ep_queue(fu->ep_in, fu->bot_req_in, GFP_ATOMIC);
- if (ret)
- pr_err("%s(%d)\n", __func__, __LINE__);
- return 0;
-}
-
-static void usbg_data_write_cmpl(struct usb_ep *, struct usb_request *);
-static int usbg_prepare_w_request(struct usbg_cmd *, struct usb_request *);
-
-static int bot_send_write_request(struct usbg_cmd *cmd)
-{
- struct f_uas *fu = cmd->fu;
- struct se_cmd *se_cmd = &cmd->se_cmd;
- struct usb_gadget *gadget = fuas_to_gadget(fu);
- int ret;
-
- init_completion(&cmd->write_complete);
- cmd->fu = fu;
-
- if (!cmd->data_len) {
- cmd->csw_code = US_BULK_STAT_PHASE;
- return -EINVAL;
- }
-
- if (!gadget->sg_supported) {
- cmd->data_buf = kmalloc(se_cmd->data_length, GFP_KERNEL);
- if (!cmd->data_buf)
- return -ENOMEM;
-
- fu->bot_req_out->buf = cmd->data_buf;
- } else {
- fu->bot_req_out->buf = NULL;
- fu->bot_req_out->num_sgs = se_cmd->t_data_nents;
- fu->bot_req_out->sg = se_cmd->t_data_sg;
- }
-
- fu->bot_req_out->complete = usbg_data_write_cmpl;
- fu->bot_req_out->length = se_cmd->data_length;
- fu->bot_req_out->context = cmd;
-
- ret = usbg_prepare_w_request(cmd, fu->bot_req_out);
- if (ret)
- goto cleanup;
- ret = usb_ep_queue(fu->ep_out, fu->bot_req_out, GFP_KERNEL);
- if (ret)
- pr_err("%s(%d)\n", __func__, __LINE__);
-
- wait_for_completion(&cmd->write_complete);
- transport_generic_process_write(se_cmd);
-cleanup:
- return ret;
-}
-
-static int bot_submit_command(struct f_uas *, void *, unsigned int);
-
-static void bot_cmd_complete(struct usb_ep *ep, struct usb_request *req)
-{
- struct f_uas *fu = req->context;
- int ret;
-
- fu->flags &= ~USBG_BOT_CMD_PEND;
-
- if (req->status < 0)
- return;
-
- ret = bot_submit_command(fu, req->buf, req->actual);
- if (ret)
- pr_err("%s(%d): %d\n", __func__, __LINE__, ret);
-}
-
-static int bot_prepare_reqs(struct f_uas *fu)
-{
- int ret;
-
- fu->bot_req_in = usb_ep_alloc_request(fu->ep_in, GFP_KERNEL);
- if (!fu->bot_req_in)
- goto err;
-
- fu->bot_req_out = usb_ep_alloc_request(fu->ep_out, GFP_KERNEL);
- if (!fu->bot_req_out)
- goto err_out;
-
- fu->cmd.req = usb_ep_alloc_request(fu->ep_out, GFP_KERNEL);
- if (!fu->cmd.req)
- goto err_cmd;
-
- fu->bot_status.req = usb_ep_alloc_request(fu->ep_in, GFP_KERNEL);
- if (!fu->bot_status.req)
- goto err_sts;
-
- fu->bot_status.req->buf = &fu->bot_status.csw;
- fu->bot_status.req->length = US_BULK_CS_WRAP_LEN;
- fu->bot_status.req->complete = bot_status_complete;
- fu->bot_status.csw.Signature = cpu_to_le32(US_BULK_CS_SIGN);
-
- fu->cmd.buf = kmalloc(fu->ep_out->maxpacket, GFP_KERNEL);
- if (!fu->cmd.buf)
- goto err_buf;
-
- fu->cmd.req->complete = bot_cmd_complete;
- fu->cmd.req->buf = fu->cmd.buf;
- fu->cmd.req->length = fu->ep_out->maxpacket;
- fu->cmd.req->context = fu;
-
- ret = bot_enqueue_cmd_cbw(fu);
- if (ret)
- goto err_queue;
- return 0;
-err_queue:
- kfree(fu->cmd.buf);
- fu->cmd.buf = NULL;
-err_buf:
- usb_ep_free_request(fu->ep_in, fu->bot_status.req);
-err_sts:
- usb_ep_free_request(fu->ep_out, fu->cmd.req);
- fu->cmd.req = NULL;
-err_cmd:
- usb_ep_free_request(fu->ep_out, fu->bot_req_out);
- fu->bot_req_out = NULL;
-err_out:
- usb_ep_free_request(fu->ep_in, fu->bot_req_in);
- fu->bot_req_in = NULL;
-err:
- pr_err("BOT: endpoint setup failed\n");
- return -ENOMEM;
-}
-
-void bot_cleanup_old_alt(struct f_uas *fu)
-{
- if (!(fu->flags & USBG_ENABLED))
- return;
-
- usb_ep_disable(fu->ep_in);
- usb_ep_disable(fu->ep_out);
-
- if (!fu->bot_req_in)
- return;
-
- usb_ep_free_request(fu->ep_in, fu->bot_req_in);
- usb_ep_free_request(fu->ep_out, fu->bot_req_out);
- usb_ep_free_request(fu->ep_out, fu->cmd.req);
- usb_ep_free_request(fu->ep_out, fu->bot_status.req);
-
- kfree(fu->cmd.buf);
-
- fu->bot_req_in = NULL;
- fu->bot_req_out = NULL;
- fu->cmd.req = NULL;
- fu->bot_status.req = NULL;
- fu->cmd.buf = NULL;
-}
-
-static void bot_set_alt(struct f_uas *fu)
-{
- struct usb_function *f = &fu->function;
- struct usb_gadget *gadget = f->config->cdev->gadget;
- int ret;
-
- fu->flags = USBG_IS_BOT;
-
- config_ep_by_speed(gadget, f, fu->ep_in);
- ret = usb_ep_enable(fu->ep_in);
- if (ret)
- goto err_b_in;
-
- config_ep_by_speed(gadget, f, fu->ep_out);
- ret = usb_ep_enable(fu->ep_out);
- if (ret)
- goto err_b_out;
-
- ret = bot_prepare_reqs(fu);
- if (ret)
- goto err_wq;
- fu->flags |= USBG_ENABLED;
- pr_info("Using the BOT protocol\n");
- return;
-err_wq:
- usb_ep_disable(fu->ep_out);
-err_b_out:
- usb_ep_disable(fu->ep_in);
-err_b_in:
- fu->flags = USBG_IS_BOT;
-}
-
-static int usbg_bot_setup(struct usb_function *f,
- const struct usb_ctrlrequest *ctrl)
-{
- struct f_uas *fu = to_f_uas(f);
- struct usb_composite_dev *cdev = f->config->cdev;
- u16 w_value = le16_to_cpu(ctrl->wValue);
- u16 w_length = le16_to_cpu(ctrl->wLength);
- int luns;
- u8 *ret_lun;
-
- switch (ctrl->bRequest) {
- case US_BULK_GET_MAX_LUN:
- if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_CLASS |
- USB_RECIP_INTERFACE))
- return -ENOTSUPP;
-
- if (w_length < 1)
- return -EINVAL;
- if (w_value != 0)
- return -EINVAL;
- luns = atomic_read(&fu->tpg->tpg_port_count);
- if (!luns) {
- pr_err("No LUNs configured?\n");
- return -EINVAL;
- }
- /*
- * If 4 LUNs are present we return 3 i.e. LUN 0..3 can be
- * accessed. The upper limit is 0xf
- */
- luns--;
- if (luns > 0xf) {
- pr_info_once("Limiting the number of luns to 16\n");
- luns = 0xf;
- }
- ret_lun = cdev->req->buf;
- *ret_lun = luns;
- cdev->req->length = 1;
- return usb_ep_queue(cdev->gadget->ep0, cdev->req, GFP_ATOMIC);
- break;
-
- case US_BULK_RESET_REQUEST:
- /* XXX maybe we should remove previous requests for IN + OUT */
- bot_enqueue_cmd_cbw(fu);
- return 0;
- break;
- };
- return -ENOTSUPP;
-}
-
-/* Start uas.c code */
-
-static void uasp_cleanup_one_stream(struct f_uas *fu, struct uas_stream *stream)
-{
- /* We have either all three allocated or none */
- if (!stream->req_in)
- return;
-
- usb_ep_free_request(fu->ep_in, stream->req_in);
- usb_ep_free_request(fu->ep_out, stream->req_out);
- usb_ep_free_request(fu->ep_status, stream->req_status);
-
- stream->req_in = NULL;
- stream->req_out = NULL;
- stream->req_status = NULL;
-}
-
-static void uasp_free_cmdreq(struct f_uas *fu)
-{
- usb_ep_free_request(fu->ep_cmd, fu->cmd.req);
- kfree(fu->cmd.buf);
- fu->cmd.req = NULL;
- fu->cmd.buf = NULL;
-}
-
-static void uasp_cleanup_old_alt(struct f_uas *fu)
-{
- int i;
-
- if (!(fu->flags & USBG_ENABLED))
- return;
-
- usb_ep_disable(fu->ep_in);
- usb_ep_disable(fu->ep_out);
- usb_ep_disable(fu->ep_status);
- usb_ep_disable(fu->ep_cmd);
-
- for (i = 0; i < UASP_SS_EP_COMP_NUM_STREAMS; i++)
- uasp_cleanup_one_stream(fu, &fu->stream[i]);
- uasp_free_cmdreq(fu);
-}
-
-static void uasp_status_data_cmpl(struct usb_ep *ep, struct usb_request *req);
-
-static int uasp_prepare_r_request(struct usbg_cmd *cmd)
-{
- struct se_cmd *se_cmd = &cmd->se_cmd;
- struct f_uas *fu = cmd->fu;
- struct usb_gadget *gadget = fuas_to_gadget(fu);
- struct uas_stream *stream = cmd->stream;
-
- if (!gadget->sg_supported) {
- cmd->data_buf = kmalloc(se_cmd->data_length, GFP_ATOMIC);
- if (!cmd->data_buf)
- return -ENOMEM;
-
- sg_copy_to_buffer(se_cmd->t_data_sg,
- se_cmd->t_data_nents,
- cmd->data_buf,
- se_cmd->data_length);
-
- stream->req_in->buf = cmd->data_buf;
- } else {
- stream->req_in->buf = NULL;
- stream->req_in->num_sgs = se_cmd->t_data_nents;
- stream->req_in->sg = se_cmd->t_data_sg;
- }
-
- stream->req_in->complete = uasp_status_data_cmpl;
- stream->req_in->length = se_cmd->data_length;
- stream->req_in->context = cmd;
-
- cmd->state = UASP_SEND_STATUS;
- return 0;
-}
-
-static void uasp_prepare_status(struct usbg_cmd *cmd)
-{
- struct se_cmd *se_cmd = &cmd->se_cmd;
- struct sense_iu *iu = &cmd->sense_iu;
- struct uas_stream *stream = cmd->stream;
-
- cmd->state = UASP_QUEUE_COMMAND;
- iu->iu_id = IU_ID_STATUS;
- iu->tag = cpu_to_be16(cmd->tag);
-
- /*
- * iu->status_qual = cpu_to_be16(STATUS QUALIFIER SAM-4. Where R U?);
- */
- iu->len = cpu_to_be16(se_cmd->scsi_sense_length);
- iu->status = se_cmd->scsi_status;
- stream->req_status->context = cmd;
- stream->req_status->length = se_cmd->scsi_sense_length + 16;
- stream->req_status->buf = iu;
- stream->req_status->complete = uasp_status_data_cmpl;
-}
-
-static void uasp_status_data_cmpl(struct usb_ep *ep, struct usb_request *req)
-{
- struct usbg_cmd *cmd = req->context;
- struct uas_stream *stream = cmd->stream;
- struct f_uas *fu = cmd->fu;
- int ret;
-
- if (req->status < 0)
- goto cleanup;
-
- switch (cmd->state) {
- case UASP_SEND_DATA:
- ret = uasp_prepare_r_request(cmd);
- if (ret)
- goto cleanup;
- ret = usb_ep_queue(fu->ep_in, stream->req_in, GFP_ATOMIC);
- if (ret)
- pr_err("%s(%d) => %d\n", __func__, __LINE__, ret);
- break;
-
- case UASP_RECEIVE_DATA:
- ret = usbg_prepare_w_request(cmd, stream->req_out);
- if (ret)
- goto cleanup;
- ret = usb_ep_queue(fu->ep_out, stream->req_out, GFP_ATOMIC);
- if (ret)
- pr_err("%s(%d) => %d\n", __func__, __LINE__, ret);
- break;
-
- case UASP_SEND_STATUS:
- uasp_prepare_status(cmd);
- ret = usb_ep_queue(fu->ep_status, stream->req_status,
- GFP_ATOMIC);
- if (ret)
- pr_err("%s(%d) => %d\n", __func__, __LINE__, ret);
- break;
-
- case UASP_QUEUE_COMMAND:
- usbg_cleanup_cmd(cmd);
- usb_ep_queue(fu->ep_cmd, fu->cmd.req, GFP_ATOMIC);
- break;
-
- default:
- BUG();
- };
- return;
-
-cleanup:
- usbg_cleanup_cmd(cmd);
-}
-
-static int uasp_send_status_response(struct usbg_cmd *cmd)
-{
- struct f_uas *fu = cmd->fu;
- struct uas_stream *stream = cmd->stream;
- struct sense_iu *iu = &cmd->sense_iu;
-
- iu->tag = cpu_to_be16(cmd->tag);
- stream->req_status->complete = uasp_status_data_cmpl;
- stream->req_status->context = cmd;
- cmd->fu = fu;
- uasp_prepare_status(cmd);
- return usb_ep_queue(fu->ep_status, stream->req_status, GFP_ATOMIC);
-}
-
-static int uasp_send_read_response(struct usbg_cmd *cmd)
-{
- struct f_uas *fu = cmd->fu;
- struct uas_stream *stream = cmd->stream;
- struct sense_iu *iu = &cmd->sense_iu;
- int ret;
-
- cmd->fu = fu;
-
- iu->tag = cpu_to_be16(cmd->tag);
- if (fu->flags & USBG_USE_STREAMS) {
-
- ret = uasp_prepare_r_request(cmd);
- if (ret)
- goto out;
- ret = usb_ep_queue(fu->ep_in, stream->req_in, GFP_ATOMIC);
- if (ret) {
- pr_err("%s(%d) => %d\n", __func__, __LINE__, ret);
- kfree(cmd->data_buf);
- cmd->data_buf = NULL;
- }
-
- } else {
-
- iu->iu_id = IU_ID_READ_READY;
- iu->tag = cpu_to_be16(cmd->tag);
-
- stream->req_status->complete = uasp_status_data_cmpl;
- stream->req_status->context = cmd;
-
- cmd->state = UASP_SEND_DATA;
- stream->req_status->buf = iu;
- stream->req_status->length = sizeof(struct iu);
-
- ret = usb_ep_queue(fu->ep_status, stream->req_status,
- GFP_ATOMIC);
- if (ret)
- pr_err("%s(%d) => %d\n", __func__, __LINE__, ret);
- }
-out:
- return ret;
-}
-
-static int uasp_send_write_request(struct usbg_cmd *cmd)
-{
- struct f_uas *fu = cmd->fu;
- struct se_cmd *se_cmd = &cmd->se_cmd;
- struct uas_stream *stream = cmd->stream;
- struct sense_iu *iu = &cmd->sense_iu;
- int ret;
-
- init_completion(&cmd->write_complete);
- cmd->fu = fu;
-
- iu->tag = cpu_to_be16(cmd->tag);
-
- if (fu->flags & USBG_USE_STREAMS) {
-
- ret = usbg_prepare_w_request(cmd, stream->req_out);
- if (ret)
- goto cleanup;
- ret = usb_ep_queue(fu->ep_out, stream->req_out, GFP_ATOMIC);
- if (ret)
- pr_err("%s(%d)\n", __func__, __LINE__);
-
- } else {
-
- iu->iu_id = IU_ID_WRITE_READY;
- iu->tag = cpu_to_be16(cmd->tag);
-
- stream->req_status->complete = uasp_status_data_cmpl;
- stream->req_status->context = cmd;
-
- cmd->state = UASP_RECEIVE_DATA;
- stream->req_status->buf = iu;
- stream->req_status->length = sizeof(struct iu);
-
- ret = usb_ep_queue(fu->ep_status, stream->req_status,
- GFP_ATOMIC);
- if (ret)
- pr_err("%s(%d)\n", __func__, __LINE__);
- }
-
- wait_for_completion(&cmd->write_complete);
- transport_generic_process_write(se_cmd);
-cleanup:
- return ret;
-}
-
-static int usbg_submit_command(struct f_uas *, void *, unsigned int);
-
-static void uasp_cmd_complete(struct usb_ep *ep, struct usb_request *req)
-{
- struct f_uas *fu = req->context;
- int ret;
-
- if (req->status < 0)
- return;
-
- ret = usbg_submit_command(fu, req->buf, req->actual);
- /*
- * Once we tune for performance enqueue the command req here again so
- * we can receive a second command while we processing this one. Pay
- * attention to properly sync STAUS endpoint with DATA IN + OUT so you
- * don't break HS.
- */
- if (!ret)
- return;
- usb_ep_queue(fu->ep_cmd, fu->cmd.req, GFP_ATOMIC);
-}
-
-static int uasp_alloc_stream_res(struct f_uas *fu, struct uas_stream *stream)
-{
- stream->req_in = usb_ep_alloc_request(fu->ep_in, GFP_KERNEL);
- if (!stream->req_in)
- goto out;
-
- stream->req_out = usb_ep_alloc_request(fu->ep_out, GFP_KERNEL);
- if (!stream->req_out)
- goto err_out;
-
- stream->req_status = usb_ep_alloc_request(fu->ep_status, GFP_KERNEL);
- if (!stream->req_status)
- goto err_sts;
-
- return 0;
-err_sts:
- usb_ep_free_request(fu->ep_status, stream->req_status);
- stream->req_status = NULL;
-err_out:
- usb_ep_free_request(fu->ep_out, stream->req_out);
- stream->req_out = NULL;
-out:
- return -ENOMEM;
-}
-
-static int uasp_alloc_cmd(struct f_uas *fu)
-{
- fu->cmd.req = usb_ep_alloc_request(fu->ep_cmd, GFP_KERNEL);
- if (!fu->cmd.req)
- goto err;
-
- fu->cmd.buf = kmalloc(fu->ep_cmd->maxpacket, GFP_KERNEL);
- if (!fu->cmd.buf)
- goto err_buf;
-
- fu->cmd.req->complete = uasp_cmd_complete;
- fu->cmd.req->buf = fu->cmd.buf;
- fu->cmd.req->length = fu->ep_cmd->maxpacket;
- fu->cmd.req->context = fu;
- return 0;
-
-err_buf:
- usb_ep_free_request(fu->ep_cmd, fu->cmd.req);
-err:
- return -ENOMEM;
-}
-
-static void uasp_setup_stream_res(struct f_uas *fu, int max_streams)
-{
- int i;
-
- for (i = 0; i < max_streams; i++) {
- struct uas_stream *s = &fu->stream[i];
-
- s->req_in->stream_id = i + 1;
- s->req_out->stream_id = i + 1;
- s->req_status->stream_id = i + 1;
- }
-}
-
-static int uasp_prepare_reqs(struct f_uas *fu)
-{
- int ret;
- int i;
- int max_streams;
-
- if (fu->flags & USBG_USE_STREAMS)
- max_streams = UASP_SS_EP_COMP_NUM_STREAMS;
- else
- max_streams = 1;
-
- for (i = 0; i < max_streams; i++) {
- ret = uasp_alloc_stream_res(fu, &fu->stream[i]);
- if (ret)
- goto err_cleanup;
- }
-
- ret = uasp_alloc_cmd(fu);
- if (ret)
- goto err_free_stream;
- uasp_setup_stream_res(fu, max_streams);
-
- ret = usb_ep_queue(fu->ep_cmd, fu->cmd.req, GFP_ATOMIC);
- if (ret)
- goto err_free_stream;
-
- return 0;
-
-err_free_stream:
- uasp_free_cmdreq(fu);
-
-err_cleanup:
- if (i) {
- do {
- uasp_cleanup_one_stream(fu, &fu->stream[i - 1]);
- i--;
- } while (i);
- }
- pr_err("UASP: endpoint setup failed\n");
- return ret;
-}
-
-static void uasp_set_alt(struct f_uas *fu)
-{
- struct usb_function *f = &fu->function;
- struct usb_gadget *gadget = f->config->cdev->gadget;
- int ret;
-
- fu->flags = USBG_IS_UAS;
-
- if (gadget->speed == USB_SPEED_SUPER)
- fu->flags |= USBG_USE_STREAMS;
-
- config_ep_by_speed(gadget, f, fu->ep_in);
- ret = usb_ep_enable(fu->ep_in);
- if (ret)
- goto err_b_in;
-
- config_ep_by_speed(gadget, f, fu->ep_out);
- ret = usb_ep_enable(fu->ep_out);
- if (ret)
- goto err_b_out;
-
- config_ep_by_speed(gadget, f, fu->ep_cmd);
- ret = usb_ep_enable(fu->ep_cmd);
- if (ret)
- goto err_cmd;
- config_ep_by_speed(gadget, f, fu->ep_status);
- ret = usb_ep_enable(fu->ep_status);
- if (ret)
- goto err_status;
-
- ret = uasp_prepare_reqs(fu);
- if (ret)
- goto err_wq;
- fu->flags |= USBG_ENABLED;
-
- pr_info("Using the UAS protocol\n");
- return;
-err_wq:
- usb_ep_disable(fu->ep_status);
-err_status:
- usb_ep_disable(fu->ep_cmd);
-err_cmd:
- usb_ep_disable(fu->ep_out);
-err_b_out:
- usb_ep_disable(fu->ep_in);
-err_b_in:
- fu->flags = 0;
-}
-
-static int get_cmd_dir(const unsigned char *cdb)
-{
- int ret;
-
- switch (cdb[0]) {
- case READ_6:
- case READ_10:
- case READ_12:
- case READ_16:
- case INQUIRY:
- case MODE_SENSE:
- case MODE_SENSE_10:
- case SERVICE_ACTION_IN:
- case MAINTENANCE_IN:
- case PERSISTENT_RESERVE_IN:
- case SECURITY_PROTOCOL_IN:
- case ACCESS_CONTROL_IN:
- case REPORT_LUNS:
- case READ_BLOCK_LIMITS:
- case READ_POSITION:
- case READ_CAPACITY:
- case READ_TOC:
- case READ_FORMAT_CAPACITIES:
- case REQUEST_SENSE:
- ret = DMA_FROM_DEVICE;
- break;
-
- case WRITE_6:
- case WRITE_10:
- case WRITE_12:
- case WRITE_16:
- case MODE_SELECT:
- case MODE_SELECT_10:
- case WRITE_VERIFY:
- case WRITE_VERIFY_12:
- case PERSISTENT_RESERVE_OUT:
- case MAINTENANCE_OUT:
- case SECURITY_PROTOCOL_OUT:
- case ACCESS_CONTROL_OUT:
- ret = DMA_TO_DEVICE;
- break;
- case ALLOW_MEDIUM_REMOVAL:
- case TEST_UNIT_READY:
- case SYNCHRONIZE_CACHE:
- case START_STOP:
- case ERASE:
- case REZERO_UNIT:
- case SEEK_10:
- case SPACE:
- case VERIFY:
- case WRITE_FILEMARKS:
- ret = DMA_NONE;
- break;
- default:
- pr_warn("target: Unknown data direction for SCSI Opcode "
- "0x%02x\n", cdb[0]);
- ret = -EINVAL;
- }
- return ret;
-}
-
-static void usbg_data_write_cmpl(struct usb_ep *ep, struct usb_request *req)
-{
- struct usbg_cmd *cmd = req->context;
- struct se_cmd *se_cmd = &cmd->se_cmd;
-
- if (req->status < 0) {
- pr_err("%s() state %d transfer failed\n", __func__, cmd->state);
- goto cleanup;
- }
-
- if (req->num_sgs == 0) {
- sg_copy_from_buffer(se_cmd->t_data_sg,
- se_cmd->t_data_nents,
- cmd->data_buf,
- se_cmd->data_length);
- }
-
- complete(&cmd->write_complete);
- return;
-
-cleanup:
- usbg_cleanup_cmd(cmd);
-}
-
-static int usbg_prepare_w_request(struct usbg_cmd *cmd, struct usb_request *req)
-{
- struct se_cmd *se_cmd = &cmd->se_cmd;
- struct f_uas *fu = cmd->fu;
- struct usb_gadget *gadget = fuas_to_gadget(fu);
-
- if (!gadget->sg_supported) {
- cmd->data_buf = kmalloc(se_cmd->data_length, GFP_ATOMIC);
- if (!cmd->data_buf)
- return -ENOMEM;
-
- req->buf = cmd->data_buf;
- } else {
- req->buf = NULL;
- req->num_sgs = se_cmd->t_data_nents;
- req->sg = se_cmd->t_data_sg;
- }
-
- req->complete = usbg_data_write_cmpl;
- req->length = se_cmd->data_length;
- req->context = cmd;
- return 0;
-}
-
-static int usbg_send_status_response(struct se_cmd *se_cmd)
-{
- struct usbg_cmd *cmd = container_of(se_cmd, struct usbg_cmd,
- se_cmd);
- struct f_uas *fu = cmd->fu;
-
- if (fu->flags & USBG_IS_BOT)
- return bot_send_status_response(cmd);
- else
- return uasp_send_status_response(cmd);
-}
-
-static int usbg_send_write_request(struct se_cmd *se_cmd)
-{
- struct usbg_cmd *cmd = container_of(se_cmd, struct usbg_cmd,
- se_cmd);
- struct f_uas *fu = cmd->fu;
-
- if (fu->flags & USBG_IS_BOT)
- return bot_send_write_request(cmd);
- else
- return uasp_send_write_request(cmd);
-}
-
-static int usbg_send_read_response(struct se_cmd *se_cmd)
-{
- struct usbg_cmd *cmd = container_of(se_cmd, struct usbg_cmd,
- se_cmd);
- struct f_uas *fu = cmd->fu;
-
- if (fu->flags & USBG_IS_BOT)
- return bot_send_read_response(cmd);
- else
- return uasp_send_read_response(cmd);
-}
-
-static void usbg_cmd_work(struct work_struct *work)
-{
- struct usbg_cmd *cmd = container_of(work, struct usbg_cmd, work);
- struct se_cmd *se_cmd;
- struct tcm_usbg_nexus *tv_nexus;
- struct usbg_tpg *tpg;
- int dir;
-
- se_cmd = &cmd->se_cmd;
- tpg = cmd->fu->tpg;
- tv_nexus = tpg->tpg_nexus;
- dir = get_cmd_dir(cmd->cmd_buf);
- if (dir < 0) {
- transport_init_se_cmd(se_cmd,
- tv_nexus->tvn_se_sess->se_tpg->se_tpg_tfo,
- tv_nexus->tvn_se_sess, cmd->data_len, DMA_NONE,
- cmd->prio_attr, cmd->sense_iu.sense);
-
- transport_send_check_condition_and_sense(se_cmd,
- TCM_UNSUPPORTED_SCSI_OPCODE, 1);
- usbg_cleanup_cmd(cmd);
- return;
- }
-
- target_submit_cmd(se_cmd, tv_nexus->tvn_se_sess,
- cmd->cmd_buf, cmd->sense_iu.sense, cmd->unpacked_lun,
- 0, cmd->prio_attr, dir, TARGET_SCF_UNKNOWN_SIZE);
-}
-
-static int usbg_submit_command(struct f_uas *fu,
- void *cmdbuf, unsigned int len)
-{
- struct command_iu *cmd_iu = cmdbuf;
- struct usbg_cmd *cmd;
- struct usbg_tpg *tpg;
- struct se_cmd *se_cmd;
- struct tcm_usbg_nexus *tv_nexus;
- u32 cmd_len;
- int ret;
-
- if (cmd_iu->iu_id != IU_ID_COMMAND) {
- pr_err("Unsupported type %d\n", cmd_iu->iu_id);
- return -EINVAL;
- }
-
- cmd = kzalloc(sizeof *cmd, GFP_ATOMIC);
- if (!cmd)
- return -ENOMEM;
-
- cmd->fu = fu;
-
- /* XXX until I figure out why I can't free in on complete */
- kref_init(&cmd->ref);
- kref_get(&cmd->ref);
-
- tpg = fu->tpg;
- cmd_len = (cmd_iu->len & ~0x3) + 16;
- if (cmd_len > USBG_MAX_CMD)
- goto err;
-
- memcpy(cmd->cmd_buf, cmd_iu->cdb, cmd_len);
-
- cmd->tag = be16_to_cpup(&cmd_iu->tag);
- if (fu->flags & USBG_USE_STREAMS) {
- if (cmd->tag > UASP_SS_EP_COMP_NUM_STREAMS)
- goto err;
- if (!cmd->tag)
- cmd->stream = &fu->stream[0];
- else
- cmd->stream = &fu->stream[cmd->tag - 1];
- } else {
- cmd->stream = &fu->stream[0];
- }
-
- tv_nexus = tpg->tpg_nexus;
- if (!tv_nexus) {
- pr_err("Missing nexus, ignoring command\n");
- goto err;
- }
-
- switch (cmd_iu->prio_attr & 0x7) {
- case UAS_HEAD_TAG:
- cmd->prio_attr = MSG_HEAD_TAG;
- break;
- case UAS_ORDERED_TAG:
- cmd->prio_attr = MSG_ORDERED_TAG;
- break;
- case UAS_ACA:
- cmd->prio_attr = MSG_ACA_TAG;
- break;
- default:
- pr_debug_once("Unsupported prio_attr: %02x.\n",
- cmd_iu->prio_attr);
- case UAS_SIMPLE_TAG:
- cmd->prio_attr = MSG_SIMPLE_TAG;
- break;
- }
-
- se_cmd = &cmd->se_cmd;
- cmd->unpacked_lun = scsilun_to_int(&cmd_iu->lun);
-
- INIT_WORK(&cmd->work, usbg_cmd_work);
- ret = queue_work(tpg->workqueue, &cmd->work);
- if (ret < 0)
- goto err;
-
- return 0;
-err:
- kfree(cmd);
- return -EINVAL;
-}
-
-static void bot_cmd_work(struct work_struct *work)
-{
- struct usbg_cmd *cmd = container_of(work, struct usbg_cmd, work);
- struct se_cmd *se_cmd;
- struct tcm_usbg_nexus *tv_nexus;
- struct usbg_tpg *tpg;
- int dir;
-
- se_cmd = &cmd->se_cmd;
- tpg = cmd->fu->tpg;
- tv_nexus = tpg->tpg_nexus;
- dir = get_cmd_dir(cmd->cmd_buf);
- if (dir < 0) {
- transport_init_se_cmd(se_cmd,
- tv_nexus->tvn_se_sess->se_tpg->se_tpg_tfo,
- tv_nexus->tvn_se_sess, cmd->data_len, DMA_NONE,
- cmd->prio_attr, cmd->sense_iu.sense);
-
- transport_send_check_condition_and_sense(se_cmd,
- TCM_UNSUPPORTED_SCSI_OPCODE, 1);
- usbg_cleanup_cmd(cmd);
- return;
- }
-
- target_submit_cmd(se_cmd, tv_nexus->tvn_se_sess,
- cmd->cmd_buf, cmd->sense_iu.sense, cmd->unpacked_lun,
- cmd->data_len, cmd->prio_attr, dir, 0);
-}
-
-static int bot_submit_command(struct f_uas *fu,
- void *cmdbuf, unsigned int len)
-{
- struct bulk_cb_wrap *cbw = cmdbuf;
- struct usbg_cmd *cmd;
- struct usbg_tpg *tpg;
- struct se_cmd *se_cmd;
- struct tcm_usbg_nexus *tv_nexus;
- u32 cmd_len;
- int ret;
-
- if (cbw->Signature != cpu_to_le32(US_BULK_CB_SIGN)) {
- pr_err("Wrong signature on CBW\n");
- return -EINVAL;
- }
- if (len != 31) {
- pr_err("Wrong length for CBW\n");
- return -EINVAL;
- }
-
- cmd_len = cbw->Length;
- if (cmd_len < 1 || cmd_len > 16)
- return -EINVAL;
-
- cmd = kzalloc(sizeof *cmd, GFP_ATOMIC);
- if (!cmd)
- return -ENOMEM;
-
- cmd->fu = fu;
-
- /* XXX until I figure out why I can't free in on complete */
- kref_init(&cmd->ref);
- kref_get(&cmd->ref);
-
- tpg = fu->tpg;
-
- memcpy(cmd->cmd_buf, cbw->CDB, cmd_len);
-
- cmd->bot_tag = cbw->Tag;
-
- tv_nexus = tpg->tpg_nexus;
- if (!tv_nexus) {
- pr_err("Missing nexus, ignoring command\n");
- goto err;
- }
-
- cmd->prio_attr = MSG_SIMPLE_TAG;
- se_cmd = &cmd->se_cmd;
- cmd->unpacked_lun = cbw->Lun;
- cmd->is_read = cbw->Flags & US_BULK_FLAG_IN ? 1 : 0;
- cmd->data_len = le32_to_cpu(cbw->DataTransferLength);
-
- INIT_WORK(&cmd->work, bot_cmd_work);
- ret = queue_work(tpg->workqueue, &cmd->work);
- if (ret < 0)
- goto err;
-
- return 0;
-err:
- kfree(cmd);
- return -EINVAL;
-}
-
-/* Start fabric.c code */
-
-static int usbg_check_true(struct se_portal_group *se_tpg)
-{
- return 1;
-}
-
-static int usbg_check_false(struct se_portal_group *se_tpg)
-{
- return 0;
-}
-
-static char *usbg_get_fabric_name(void)
-{
- return "usb_gadget";
-}
-
-static u8 usbg_get_fabric_proto_ident(struct se_portal_group *se_tpg)
-{
- struct usbg_tpg *tpg = container_of(se_tpg,
- struct usbg_tpg, se_tpg);
- struct usbg_tport *tport = tpg->tport;
- u8 proto_id;
-
- switch (tport->tport_proto_id) {
- case SCSI_PROTOCOL_SAS:
- default:
- proto_id = sas_get_fabric_proto_ident(se_tpg);
- break;
- }
-
- return proto_id;
-}
-
-static char *usbg_get_fabric_wwn(struct se_portal_group *se_tpg)
-{
- struct usbg_tpg *tpg = container_of(se_tpg,
- struct usbg_tpg, se_tpg);
- struct usbg_tport *tport = tpg->tport;
-
- return &tport->tport_name[0];
-}
-
-static u16 usbg_get_tag(struct se_portal_group *se_tpg)
-{
- struct usbg_tpg *tpg = container_of(se_tpg,
- struct usbg_tpg, se_tpg);
- return tpg->tport_tpgt;
-}
-
-static u32 usbg_get_default_depth(struct se_portal_group *se_tpg)
-{
- return 1;
-}
-
-static u32 usbg_get_pr_transport_id(
- struct se_portal_group *se_tpg,
- struct se_node_acl *se_nacl,
- struct t10_pr_registration *pr_reg,
- int *format_code,
- unsigned char *buf)
-{
- struct usbg_tpg *tpg = container_of(se_tpg,
- struct usbg_tpg, se_tpg);
- struct usbg_tport *tport = tpg->tport;
- int ret = 0;
-
- switch (tport->tport_proto_id) {
- case SCSI_PROTOCOL_SAS:
- default:
- ret = sas_get_pr_transport_id(se_tpg, se_nacl, pr_reg,
- format_code, buf);
- break;
- }
-
- return ret;
-}
-
-static u32 usbg_get_pr_transport_id_len(
- struct se_portal_group *se_tpg,
- struct se_node_acl *se_nacl,
- struct t10_pr_registration *pr_reg,
- int *format_code)
-{
- struct usbg_tpg *tpg = container_of(se_tpg,
- struct usbg_tpg, se_tpg);
- struct usbg_tport *tport = tpg->tport;
- int ret = 0;
-
- switch (tport->tport_proto_id) {
- case SCSI_PROTOCOL_SAS:
- default:
- ret = sas_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg,
- format_code);
- break;
- }
-
- return ret;
-}
-
-static char *usbg_parse_pr_out_transport_id(
- struct se_portal_group *se_tpg,
- const char *buf,
- u32 *out_tid_len,
- char **port_nexus_ptr)
-{
- struct usbg_tpg *tpg = container_of(se_tpg,
- struct usbg_tpg, se_tpg);
- struct usbg_tport *tport = tpg->tport;
- char *tid = NULL;
-
- switch (tport->tport_proto_id) {
- case SCSI_PROTOCOL_SAS:
- default:
- tid = sas_parse_pr_out_transport_id(se_tpg, buf, out_tid_len,
- port_nexus_ptr);
- }
-
- return tid;
-}
-
-static struct se_node_acl *usbg_alloc_fabric_acl(struct se_portal_group *se_tpg)
-{
- struct usbg_nacl *nacl;
-
- nacl = kzalloc(sizeof(struct usbg_nacl), GFP_KERNEL);
- if (!nacl) {
- printk(KERN_ERR "Unable to alocate struct usbg_nacl\n");
- return NULL;
- }
-
- return &nacl->se_node_acl;
-}
-
-static void usbg_release_fabric_acl(
- struct se_portal_group *se_tpg,
- struct se_node_acl *se_nacl)
-{
- struct usbg_nacl *nacl = container_of(se_nacl,
- struct usbg_nacl, se_node_acl);
- kfree(nacl);
-}
-
-static u32 usbg_tpg_get_inst_index(struct se_portal_group *se_tpg)
-{
- return 1;
-}
-
-static int usbg_new_cmd(struct se_cmd *se_cmd)
-{
- struct usbg_cmd *cmd = container_of(se_cmd, struct usbg_cmd,
- se_cmd);
- int ret;
-
- ret = target_setup_cmd_from_cdb(se_cmd, cmd->cmd_buf);
- if (ret)
- return ret;
-
- return transport_generic_map_mem_to_cmd(se_cmd, NULL, 0, NULL, 0);
-}
-
-static void usbg_cmd_release(struct kref *ref)
-{
- struct usbg_cmd *cmd = container_of(ref, struct usbg_cmd,
- ref);
-
- transport_generic_free_cmd(&cmd->se_cmd, 0);
-}
-
-static void usbg_release_cmd(struct se_cmd *se_cmd)
-{
- struct usbg_cmd *cmd = container_of(se_cmd, struct usbg_cmd,
- se_cmd);
- kfree(cmd->data_buf);
- kfree(cmd);
- return;
-}
-
-static int usbg_shutdown_session(struct se_session *se_sess)
-{
- return 0;
-}
-
-static void usbg_close_session(struct se_session *se_sess)
-{
- return;
-}
-
-static u32 usbg_sess_get_index(struct se_session *se_sess)
-{
- return 0;
-}
-
-/*
- * XXX Error recovery: return != 0 if we expect writes. Dunno when that could be
- */
-static int usbg_write_pending_status(struct se_cmd *se_cmd)
-{
- return 0;
-}
-
-static void usbg_set_default_node_attrs(struct se_node_acl *nacl)
-{
- return;
-}
-
-static u32 usbg_get_task_tag(struct se_cmd *se_cmd)
-{
- struct usbg_cmd *cmd = container_of(se_cmd, struct usbg_cmd,
- se_cmd);
- struct f_uas *fu = cmd->fu;
-
- if (fu->flags & USBG_IS_BOT)
- return le32_to_cpu(cmd->bot_tag);
- else
- return cmd->tag;
-}
-
-static int usbg_get_cmd_state(struct se_cmd *se_cmd)
-{
- return 0;
-}
-
-static int usbg_queue_tm_rsp(struct se_cmd *se_cmd)
-{
- return 0;
-}
-
-static u16 usbg_set_fabric_sense_len(struct se_cmd *se_cmd, u32 sense_length)
-{
- return 0;
-}
-
-static u16 usbg_get_fabric_sense_len(void)
-{
- return 0;
-}
-
-static const char *usbg_check_wwn(const char *name)
-{
- const char *n;
- unsigned int len;
-
- n = strstr(name, "naa.");
- if (!n)
- return NULL;
- n += 4;
- len = strlen(n);
- if (len == 0 || len > USBG_NAMELEN - 1)
- return NULL;
- return n;
-}
-
-static struct se_node_acl *usbg_make_nodeacl(
- struct se_portal_group *se_tpg,
- struct config_group *group,
- const char *name)
-{
- struct se_node_acl *se_nacl, *se_nacl_new;
- struct usbg_nacl *nacl;
- u64 wwpn = 0;
- u32 nexus_depth;
- const char *wnn_name;
-
- wnn_name = usbg_check_wwn(name);
- if (!wnn_name)
- return ERR_PTR(-EINVAL);
- se_nacl_new = usbg_alloc_fabric_acl(se_tpg);
- if (!(se_nacl_new))
- return ERR_PTR(-ENOMEM);
-
- nexus_depth = 1;
- /*
- * se_nacl_new may be released by core_tpg_add_initiator_node_acl()
- * when converting a NodeACL from demo mode -> explict
- */
- se_nacl = core_tpg_add_initiator_node_acl(se_tpg, se_nacl_new,
- name, nexus_depth);
- if (IS_ERR(se_nacl)) {
- usbg_release_fabric_acl(se_tpg, se_nacl_new);
- return se_nacl;
- }
- /*
- * Locate our struct usbg_nacl and set the FC Nport WWPN
- */
- nacl = container_of(se_nacl, struct usbg_nacl, se_node_acl);
- nacl->iport_wwpn = wwpn;
- snprintf(nacl->iport_name, sizeof(nacl->iport_name), "%s", name);
- return se_nacl;
-}
-
-static void usbg_drop_nodeacl(struct se_node_acl *se_acl)
-{
- struct usbg_nacl *nacl = container_of(se_acl,
- struct usbg_nacl, se_node_acl);
- core_tpg_del_initiator_node_acl(se_acl->se_tpg, se_acl, 1);
- kfree(nacl);
-}
-
-struct usbg_tpg *the_only_tpg_I_currently_have;
-
-static struct se_portal_group *usbg_make_tpg(
- struct se_wwn *wwn,
- struct config_group *group,
- const char *name)
-{
- struct usbg_tport *tport = container_of(wwn, struct usbg_tport,
- tport_wwn);
- struct usbg_tpg *tpg;
- unsigned long tpgt;
- int ret;
-
- if (strstr(name, "tpgt_") != name)
- return ERR_PTR(-EINVAL);
- if (kstrtoul(name + 5, 0, &tpgt) || tpgt > UINT_MAX)
- return ERR_PTR(-EINVAL);
- if (the_only_tpg_I_currently_have) {
- pr_err("Until the gadget framework can't handle multiple\n");
- pr_err("gadgets, you can't do this here.\n");
- return ERR_PTR(-EBUSY);
- }
-
- tpg = kzalloc(sizeof(struct usbg_tpg), GFP_KERNEL);
- if (!tpg) {
- printk(KERN_ERR "Unable to allocate struct usbg_tpg");
- return ERR_PTR(-ENOMEM);
- }
- mutex_init(&tpg->tpg_mutex);
- atomic_set(&tpg->tpg_port_count, 0);
- tpg->workqueue = alloc_workqueue("tcm_usb_gadget", 0, 1);
- if (!tpg->workqueue) {
- kfree(tpg);
- return NULL;
- }
-
- tpg->tport = tport;
- tpg->tport_tpgt = tpgt;
-
- ret = core_tpg_register(&usbg_fabric_configfs->tf_ops, wwn,
- &tpg->se_tpg, tpg,
- TRANSPORT_TPG_TYPE_NORMAL);
- if (ret < 0) {
- destroy_workqueue(tpg->workqueue);
- kfree(tpg);
- return NULL;
- }
- the_only_tpg_I_currently_have = tpg;
- return &tpg->se_tpg;
-}
-
-static void usbg_drop_tpg(struct se_portal_group *se_tpg)
-{
- struct usbg_tpg *tpg = container_of(se_tpg,
- struct usbg_tpg, se_tpg);
-
- core_tpg_deregister(se_tpg);
- destroy_workqueue(tpg->workqueue);
- kfree(tpg);
- the_only_tpg_I_currently_have = NULL;
-}
-
-static struct se_wwn *usbg_make_tport(
- struct target_fabric_configfs *tf,
- struct config_group *group,
- const char *name)
-{
- struct usbg_tport *tport;
- const char *wnn_name;
- u64 wwpn = 0;
-
- wnn_name = usbg_check_wwn(name);
- if (!wnn_name)
- return ERR_PTR(-EINVAL);
-
- tport = kzalloc(sizeof(struct usbg_tport), GFP_KERNEL);
- if (!(tport)) {
- printk(KERN_ERR "Unable to allocate struct usbg_tport");
- return ERR_PTR(-ENOMEM);
- }
- tport->tport_wwpn = wwpn;
- snprintf(tport->tport_name, sizeof(tport->tport_name), wnn_name);
- return &tport->tport_wwn;
-}
-
-static void usbg_drop_tport(struct se_wwn *wwn)
-{
- struct usbg_tport *tport = container_of(wwn,
- struct usbg_tport, tport_wwn);
- kfree(tport);
-}
-
-/*
- * If somebody feels like dropping the version property, go ahead.
- */
-static ssize_t usbg_wwn_show_attr_version(
- struct target_fabric_configfs *tf,
- char *page)
-{
- return sprintf(page, "usb-gadget fabric module\n");
-}
-TF_WWN_ATTR_RO(usbg, version);
-
-static struct configfs_attribute *usbg_wwn_attrs[] = {
- &usbg_wwn_version.attr,
- NULL,
-};
-
-static ssize_t tcm_usbg_tpg_show_enable(
- struct se_portal_group *se_tpg,
- char *page)
-{
- struct usbg_tpg *tpg = container_of(se_tpg, struct usbg_tpg, se_tpg);
-
- return snprintf(page, PAGE_SIZE, "%u\n", tpg->gadget_connect);
-}
-
-static int usbg_attach(struct usbg_tpg *);
-static void usbg_detach(struct usbg_tpg *);
-
-static ssize_t tcm_usbg_tpg_store_enable(
- struct se_portal_group *se_tpg,
- const char *page,
- size_t count)
-{
- struct usbg_tpg *tpg = container_of(se_tpg, struct usbg_tpg, se_tpg);
- unsigned long op;
- ssize_t ret;
-
- ret = kstrtoul(page, 0, &op);
- if (ret < 0)
- return -EINVAL;
- if (op > 1)
- return -EINVAL;
-
- if (op && tpg->gadget_connect)
- goto out;
- if (!op && !tpg->gadget_connect)
- goto out;
-
- if (op) {
- ret = usbg_attach(tpg);
- if (ret)
- goto out;
- } else {
- usbg_detach(tpg);
- }
- tpg->gadget_connect = op;
-out:
- return count;
-}
-TF_TPG_BASE_ATTR(tcm_usbg, enable, S_IRUGO | S_IWUSR);
-
-static ssize_t tcm_usbg_tpg_show_nexus(
- struct se_portal_group *se_tpg,
- char *page)
-{
- struct usbg_tpg *tpg = container_of(se_tpg, struct usbg_tpg, se_tpg);
- struct tcm_usbg_nexus *tv_nexus;
- ssize_t ret;
-
- mutex_lock(&tpg->tpg_mutex);
- tv_nexus = tpg->tpg_nexus;
- if (!tv_nexus) {
- ret = -ENODEV;
- goto out;
- }
- ret = snprintf(page, PAGE_SIZE, "%s\n",
- tv_nexus->tvn_se_sess->se_node_acl->initiatorname);
-out:
- mutex_unlock(&tpg->tpg_mutex);
- return ret;
-}
-
-static int tcm_usbg_make_nexus(struct usbg_tpg *tpg, char *name)
-{
- struct se_portal_group *se_tpg;
- struct tcm_usbg_nexus *tv_nexus;
- int ret;
-
- mutex_lock(&tpg->tpg_mutex);
- if (tpg->tpg_nexus) {
- ret = -EEXIST;
- pr_debug("tpg->tpg_nexus already exists\n");
- goto err_unlock;
- }
- se_tpg = &tpg->se_tpg;
-
- ret = -ENOMEM;
- tv_nexus = kzalloc(sizeof(*tv_nexus), GFP_KERNEL);
- if (!tv_nexus) {
- pr_err("Unable to allocate struct tcm_vhost_nexus\n");
- goto err_unlock;
- }
- tv_nexus->tvn_se_sess = transport_init_session();
- if (IS_ERR(tv_nexus->tvn_se_sess))
- goto err_free;
-
- /*
- * Since we are running in 'demo mode' this call with generate a
- * struct se_node_acl for the tcm_vhost struct se_portal_group with
- * the SCSI Initiator port name of the passed configfs group 'name'.
- */
- tv_nexus->tvn_se_sess->se_node_acl = core_tpg_check_initiator_node_acl(
- se_tpg, name);
- if (!tv_nexus->tvn_se_sess->se_node_acl) {
- pr_debug("core_tpg_check_initiator_node_acl() failed"
- " for %s\n", name);
- goto err_session;
- }
- /*
- * Now register the TCM vHost virtual I_T Nexus as active with the
- * call to __transport_register_session()
- */
- __transport_register_session(se_tpg, tv_nexus->tvn_se_sess->se_node_acl,
- tv_nexus->tvn_se_sess, tv_nexus);
- tpg->tpg_nexus = tv_nexus;
- mutex_unlock(&tpg->tpg_mutex);
- return 0;
-
-err_session:
- transport_free_session(tv_nexus->tvn_se_sess);
-err_free:
- kfree(tv_nexus);
-err_unlock:
- mutex_unlock(&tpg->tpg_mutex);
- return ret;
-}
-
-static int tcm_usbg_drop_nexus(struct usbg_tpg *tpg)
-{
- struct se_session *se_sess;
- struct tcm_usbg_nexus *tv_nexus;
- int ret = -ENODEV;
-
- mutex_lock(&tpg->tpg_mutex);
- tv_nexus = tpg->tpg_nexus;
- if (!tv_nexus)
- goto out;
-
- se_sess = tv_nexus->tvn_se_sess;
- if (!se_sess)
- goto out;
-
- if (atomic_read(&tpg->tpg_port_count)) {
- ret = -EPERM;
- pr_err("Unable to remove Host I_T Nexus with"
- " active TPG port count: %d\n",
- atomic_read(&tpg->tpg_port_count));
- goto out;
- }
-
- pr_debug("Removing I_T Nexus to Initiator Port: %s\n",
- tv_nexus->tvn_se_sess->se_node_acl->initiatorname);
- /*
- * Release the SCSI I_T Nexus to the emulated vHost Target Port
- */
- transport_deregister_session(tv_nexus->tvn_se_sess);
- tpg->tpg_nexus = NULL;
-
- kfree(tv_nexus);
-out:
- mutex_unlock(&tpg->tpg_mutex);
- return 0;
-}
-
-static ssize_t tcm_usbg_tpg_store_nexus(
- struct se_portal_group *se_tpg,
- const char *page,
- size_t count)
-{
- struct usbg_tpg *tpg = container_of(se_tpg, struct usbg_tpg, se_tpg);
- unsigned char i_port[USBG_NAMELEN], *ptr;
- int ret;
-
- if (!strncmp(page, "NULL", 4)) {
- ret = tcm_usbg_drop_nexus(tpg);
- return (!ret) ? count : ret;
- }
- if (strlen(page) > USBG_NAMELEN) {
- pr_err("Emulated NAA Sas Address: %s, exceeds"
- " max: %d\n", page, USBG_NAMELEN);
- return -EINVAL;
- }
- snprintf(i_port, USBG_NAMELEN, "%s", page);
-
- ptr = strstr(i_port, "naa.");
- if (!ptr) {
- pr_err("Missing 'naa.' prefix\n");
- return -EINVAL;
- }
-
- if (i_port[strlen(i_port) - 1] == '\n')
- i_port[strlen(i_port) - 1] = '\0';
-
- ret = tcm_usbg_make_nexus(tpg, &i_port[4]);
- if (ret < 0)
- return ret;
- return count;
-}
-TF_TPG_BASE_ATTR(tcm_usbg, nexus, S_IRUGO | S_IWUSR);
-
-static struct configfs_attribute *usbg_base_attrs[] = {
- &tcm_usbg_tpg_enable.attr,
- &tcm_usbg_tpg_nexus.attr,
- NULL,
-};
-
-static int usbg_port_link(struct se_portal_group *se_tpg, struct se_lun *lun)
-{
- struct usbg_tpg *tpg = container_of(se_tpg, struct usbg_tpg, se_tpg);
-
- atomic_inc(&tpg->tpg_port_count);
- smp_mb__after_atomic_inc();
- return 0;
-}
-
-static void usbg_port_unlink(struct se_portal_group *se_tpg,
- struct se_lun *se_lun)
-{
- struct usbg_tpg *tpg = container_of(se_tpg, struct usbg_tpg, se_tpg);
-
- atomic_dec(&tpg->tpg_port_count);
- smp_mb__after_atomic_dec();
-}
-
-static int usbg_check_stop_free(struct se_cmd *se_cmd)
-{
- struct usbg_cmd *cmd = container_of(se_cmd, struct usbg_cmd,
- se_cmd);
-
- kref_put(&cmd->ref, usbg_cmd_release);
- return 1;
-}
-
-static struct target_core_fabric_ops usbg_ops = {
- .get_fabric_name = usbg_get_fabric_name,
- .get_fabric_proto_ident = usbg_get_fabric_proto_ident,
- .tpg_get_wwn = usbg_get_fabric_wwn,
- .tpg_get_tag = usbg_get_tag,
- .tpg_get_default_depth = usbg_get_default_depth,
- .tpg_get_pr_transport_id = usbg_get_pr_transport_id,
- .tpg_get_pr_transport_id_len = usbg_get_pr_transport_id_len,
- .tpg_parse_pr_out_transport_id = usbg_parse_pr_out_transport_id,
- .tpg_check_demo_mode = usbg_check_true,
- .tpg_check_demo_mode_cache = usbg_check_false,
- .tpg_check_demo_mode_write_protect = usbg_check_false,
- .tpg_check_prod_mode_write_protect = usbg_check_false,
- .tpg_alloc_fabric_acl = usbg_alloc_fabric_acl,
- .tpg_release_fabric_acl = usbg_release_fabric_acl,
- .tpg_get_inst_index = usbg_tpg_get_inst_index,
- .new_cmd_map = usbg_new_cmd,
- .release_cmd = usbg_release_cmd,
- .shutdown_session = usbg_shutdown_session,
- .close_session = usbg_close_session,
- .sess_get_index = usbg_sess_get_index,
- .sess_get_initiator_sid = NULL,
- .write_pending = usbg_send_write_request,
- .write_pending_status = usbg_write_pending_status,
- .set_default_node_attributes = usbg_set_default_node_attrs,
- .get_task_tag = usbg_get_task_tag,
- .get_cmd_state = usbg_get_cmd_state,
- .queue_data_in = usbg_send_read_response,
- .queue_status = usbg_send_status_response,
- .queue_tm_rsp = usbg_queue_tm_rsp,
- .get_fabric_sense_len = usbg_get_fabric_sense_len,
- .set_fabric_sense_len = usbg_set_fabric_sense_len,
- .check_stop_free = usbg_check_stop_free,
-
- .fabric_make_wwn = usbg_make_tport,
- .fabric_drop_wwn = usbg_drop_tport,
- .fabric_make_tpg = usbg_make_tpg,
- .fabric_drop_tpg = usbg_drop_tpg,
- .fabric_post_link = usbg_port_link,
- .fabric_pre_unlink = usbg_port_unlink,
- .fabric_make_np = NULL,
- .fabric_drop_np = NULL,
- .fabric_make_nodeacl = usbg_make_nodeacl,
- .fabric_drop_nodeacl = usbg_drop_nodeacl,
-};
-
-static int usbg_register_configfs(void)
-{
- struct target_fabric_configfs *fabric;
- int ret;
-
- fabric = target_fabric_configfs_init(THIS_MODULE, "usb_gadget");
- if (IS_ERR(fabric)) {
- printk(KERN_ERR "target_fabric_configfs_init() failed\n");
- return PTR_ERR(fabric);
- }
-
- fabric->tf_ops = usbg_ops;
- TF_CIT_TMPL(fabric)->tfc_wwn_cit.ct_attrs = usbg_wwn_attrs;
- TF_CIT_TMPL(fabric)->tfc_tpg_base_cit.ct_attrs = usbg_base_attrs;
- TF_CIT_TMPL(fabric)->tfc_tpg_attrib_cit.ct_attrs = NULL;
- TF_CIT_TMPL(fabric)->tfc_tpg_param_cit.ct_attrs = NULL;
- TF_CIT_TMPL(fabric)->tfc_tpg_np_base_cit.ct_attrs = NULL;
- TF_CIT_TMPL(fabric)->tfc_tpg_nacl_base_cit.ct_attrs = NULL;
- TF_CIT_TMPL(fabric)->tfc_tpg_nacl_attrib_cit.ct_attrs = NULL;
- TF_CIT_TMPL(fabric)->tfc_tpg_nacl_auth_cit.ct_attrs = NULL;
- TF_CIT_TMPL(fabric)->tfc_tpg_nacl_param_cit.ct_attrs = NULL;
- ret = target_fabric_configfs_register(fabric);
- if (ret < 0) {
- printk(KERN_ERR "target_fabric_configfs_register() failed"
- " for usb-gadget\n");
- return ret;
- }
- usbg_fabric_configfs = fabric;
- return 0;
-};
-
-static void usbg_deregister_configfs(void)
-{
- if (!(usbg_fabric_configfs))
- return;
-
- target_fabric_configfs_deregister(usbg_fabric_configfs);
- usbg_fabric_configfs = NULL;
-};
-
-/* Start gadget.c code */
-
-static struct usb_interface_descriptor bot_intf_desc = {
- .bLength = sizeof(bot_intf_desc),
- .bDescriptorType = USB_DT_INTERFACE,
- .bAlternateSetting = 0,
- .bNumEndpoints = 2,
- .bAlternateSetting = USB_G_ALT_INT_BBB,
- .bInterfaceClass = USB_CLASS_MASS_STORAGE,
- .bInterfaceSubClass = USB_SC_SCSI,
- .bInterfaceProtocol = USB_PR_BULK,
- .iInterface = USB_G_STR_INT_UAS,
-};
-
-static struct usb_interface_descriptor uasp_intf_desc = {
- .bLength = sizeof(uasp_intf_desc),
- .bDescriptorType = USB_DT_INTERFACE,
- .bNumEndpoints = 4,
- .bAlternateSetting = USB_G_ALT_INT_UAS,
- .bInterfaceClass = USB_CLASS_MASS_STORAGE,
- .bInterfaceSubClass = USB_SC_SCSI,
- .bInterfaceProtocol = USB_PR_UAS,
- .iInterface = USB_G_STR_INT_BBB,
-};
-
-static struct usb_endpoint_descriptor uasp_bi_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = USB_DIR_IN,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = cpu_to_le16(512),
-};
-
-static struct usb_endpoint_descriptor uasp_fs_bi_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = USB_DIR_IN,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
-};
-
-static struct usb_pipe_usage_descriptor uasp_bi_pipe_desc = {
- .bLength = sizeof(uasp_bi_pipe_desc),
- .bDescriptorType = USB_DT_PIPE_USAGE,
- .bPipeID = DATA_IN_PIPE_ID,
-};
-
-static struct usb_endpoint_descriptor uasp_ss_bi_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = USB_DIR_IN,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = cpu_to_le16(1024),
-};
-
-static struct usb_ss_ep_comp_descriptor uasp_bi_ep_comp_desc = {
- .bLength = sizeof(uasp_bi_ep_comp_desc),
- .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
- .bMaxBurst = 0,
- .bmAttributes = UASP_SS_EP_COMP_LOG_STREAMS,
- .wBytesPerInterval = 0,
-};
-
-static struct usb_ss_ep_comp_descriptor bot_bi_ep_comp_desc = {
- .bLength = sizeof(bot_bi_ep_comp_desc),
- .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
- .bMaxBurst = 0,
-};
-
-static struct usb_endpoint_descriptor uasp_bo_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = USB_DIR_OUT,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = cpu_to_le16(512),
-};
-
-static struct usb_endpoint_descriptor uasp_fs_bo_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = USB_DIR_OUT,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
-};
-
-static struct usb_pipe_usage_descriptor uasp_bo_pipe_desc = {
- .bLength = sizeof(uasp_bo_pipe_desc),
- .bDescriptorType = USB_DT_PIPE_USAGE,
- .bPipeID = DATA_OUT_PIPE_ID,
-};
-
-static struct usb_endpoint_descriptor uasp_ss_bo_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = USB_DIR_OUT,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = cpu_to_le16(0x400),
-};
-
-static struct usb_ss_ep_comp_descriptor uasp_bo_ep_comp_desc = {
- .bLength = sizeof(uasp_bo_ep_comp_desc),
- .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
- .bmAttributes = UASP_SS_EP_COMP_LOG_STREAMS,
-};
-
-static struct usb_ss_ep_comp_descriptor bot_bo_ep_comp_desc = {
- .bLength = sizeof(bot_bo_ep_comp_desc),
- .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
-};
-
-static struct usb_endpoint_descriptor uasp_status_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = USB_DIR_IN,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = cpu_to_le16(512),
-};
-
-static struct usb_endpoint_descriptor uasp_fs_status_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = USB_DIR_IN,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
-};
-
-static struct usb_pipe_usage_descriptor uasp_status_pipe_desc = {
- .bLength = sizeof(uasp_status_pipe_desc),
- .bDescriptorType = USB_DT_PIPE_USAGE,
- .bPipeID = STATUS_PIPE_ID,
-};
-
-static struct usb_endpoint_descriptor uasp_ss_status_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = USB_DIR_IN,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = cpu_to_le16(1024),
-};
-
-static struct usb_ss_ep_comp_descriptor uasp_status_in_ep_comp_desc = {
- .bLength = sizeof(uasp_status_in_ep_comp_desc),
- .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
- .bmAttributes = UASP_SS_EP_COMP_LOG_STREAMS,
-};
-
-static struct usb_endpoint_descriptor uasp_cmd_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = USB_DIR_OUT,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = cpu_to_le16(512),
-};
-
-static struct usb_endpoint_descriptor uasp_fs_cmd_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = USB_DIR_OUT,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
-};
-
-static struct usb_pipe_usage_descriptor uasp_cmd_pipe_desc = {
- .bLength = sizeof(uasp_cmd_pipe_desc),
- .bDescriptorType = USB_DT_PIPE_USAGE,
- .bPipeID = CMD_PIPE_ID,
-};
-
-static struct usb_endpoint_descriptor uasp_ss_cmd_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = USB_DIR_OUT,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = cpu_to_le16(1024),
-};
-
-static struct usb_ss_ep_comp_descriptor uasp_cmd_comp_desc = {
- .bLength = sizeof(uasp_cmd_comp_desc),
- .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
-};
-
-static struct usb_descriptor_header *uasp_fs_function_desc[] = {
- (struct usb_descriptor_header *) &bot_intf_desc,
- (struct usb_descriptor_header *) &uasp_fs_bi_desc,
- (struct usb_descriptor_header *) &uasp_fs_bo_desc,
-
- (struct usb_descriptor_header *) &uasp_intf_desc,
- (struct usb_descriptor_header *) &uasp_fs_bi_desc,
- (struct usb_descriptor_header *) &uasp_bi_pipe_desc,
- (struct usb_descriptor_header *) &uasp_fs_bo_desc,
- (struct usb_descriptor_header *) &uasp_bo_pipe_desc,
- (struct usb_descriptor_header *) &uasp_fs_status_desc,
- (struct usb_descriptor_header *) &uasp_status_pipe_desc,
- (struct usb_descriptor_header *) &uasp_fs_cmd_desc,
- (struct usb_descriptor_header *) &uasp_cmd_pipe_desc,
-};
-
-static struct usb_descriptor_header *uasp_hs_function_desc[] = {
- (struct usb_descriptor_header *) &bot_intf_desc,
- (struct usb_descriptor_header *) &uasp_bi_desc,
- (struct usb_descriptor_header *) &uasp_bo_desc,
-
- (struct usb_descriptor_header *) &uasp_intf_desc,
- (struct usb_descriptor_header *) &uasp_bi_desc,
- (struct usb_descriptor_header *) &uasp_bi_pipe_desc,
- (struct usb_descriptor_header *) &uasp_bo_desc,
- (struct usb_descriptor_header *) &uasp_bo_pipe_desc,
- (struct usb_descriptor_header *) &uasp_status_desc,
- (struct usb_descriptor_header *) &uasp_status_pipe_desc,
- (struct usb_descriptor_header *) &uasp_cmd_desc,
- (struct usb_descriptor_header *) &uasp_cmd_pipe_desc,
- NULL,
-};
-
-static struct usb_descriptor_header *uasp_ss_function_desc[] = {
- (struct usb_descriptor_header *) &bot_intf_desc,
- (struct usb_descriptor_header *) &uasp_ss_bi_desc,
- (struct usb_descriptor_header *) &bot_bi_ep_comp_desc,
- (struct usb_descriptor_header *) &uasp_ss_bo_desc,
- (struct usb_descriptor_header *) &bot_bo_ep_comp_desc,
-
- (struct usb_descriptor_header *) &uasp_intf_desc,
- (struct usb_descriptor_header *) &uasp_ss_bi_desc,
- (struct usb_descriptor_header *) &uasp_bi_ep_comp_desc,
- (struct usb_descriptor_header *) &uasp_bi_pipe_desc,
- (struct usb_descriptor_header *) &uasp_ss_bo_desc,
- (struct usb_descriptor_header *) &uasp_bo_ep_comp_desc,
- (struct usb_descriptor_header *) &uasp_bo_pipe_desc,
- (struct usb_descriptor_header *) &uasp_ss_status_desc,
- (struct usb_descriptor_header *) &uasp_status_in_ep_comp_desc,
- (struct usb_descriptor_header *) &uasp_status_pipe_desc,
- (struct usb_descriptor_header *) &uasp_ss_cmd_desc,
- (struct usb_descriptor_header *) &uasp_cmd_comp_desc,
- (struct usb_descriptor_header *) &uasp_cmd_pipe_desc,
- NULL,
-};
+#include "f_tcm.c"
#define UAS_VENDOR_ID 0x0525 /* NetChip */
#define UAS_PRODUCT_ID 0xa4a5 /* Linux-USB File-backed Storage Gadget */
+#define USB_G_STR_MANUFACTOR 1
+#define USB_G_STR_PRODUCT 2
+#define USB_G_STR_SERIAL 3
+#define USB_G_STR_CONFIG 4
+
static struct usb_device_descriptor usbg_device_desc = {
.bLength = sizeof(usbg_device_desc),
.bDescriptorType = USB_DT_DEVICE,
@@ -2227,8 +47,6 @@
{ USB_G_STR_PRODUCT, "Target Product"},
{ USB_G_STR_SERIAL, "000000000001"},
{ USB_G_STR_CONFIG, "default config"},
- { USB_G_STR_INT_UAS, "USB Attached SCSI"},
- { USB_G_STR_INT_BBB, "Bulk Only Transport"},
{ },
};
@@ -2242,11 +60,6 @@
NULL,
};
-static int guas_unbind(struct usb_composite_dev *cdev)
-{
- return 0;
-}
-
static struct usb_configuration usbg_config_driver = {
.label = "Linux Target",
.bConfigurationValue = 1,
@@ -2254,183 +67,9 @@
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
};
-static void give_back_ep(struct usb_ep **pep)
-{
- struct usb_ep *ep = *pep;
- if (!ep)
- return;
- ep->driver_data = NULL;
-}
-
-static int usbg_bind(struct usb_configuration *c, struct usb_function *f)
-{
- struct f_uas *fu = to_f_uas(f);
- struct usb_gadget *gadget = c->cdev->gadget;
- struct usb_ep *ep;
- int iface;
-
- iface = usb_interface_id(c, f);
- if (iface < 0)
- return iface;
-
- bot_intf_desc.bInterfaceNumber = iface;
- uasp_intf_desc.bInterfaceNumber = iface;
- fu->iface = iface;
- ep = usb_ep_autoconfig_ss(gadget, &uasp_ss_bi_desc,
- &uasp_bi_ep_comp_desc);
- if (!ep)
- goto ep_fail;
-
- ep->driver_data = fu;
- fu->ep_in = ep;
-
- ep = usb_ep_autoconfig_ss(gadget, &uasp_ss_bo_desc,
- &uasp_bo_ep_comp_desc);
- if (!ep)
- goto ep_fail;
- ep->driver_data = fu;
- fu->ep_out = ep;
-
- ep = usb_ep_autoconfig_ss(gadget, &uasp_ss_status_desc,
- &uasp_status_in_ep_comp_desc);
- if (!ep)
- goto ep_fail;
- ep->driver_data = fu;
- fu->ep_status = ep;
-
- ep = usb_ep_autoconfig_ss(gadget, &uasp_ss_cmd_desc,
- &uasp_cmd_comp_desc);
- if (!ep)
- goto ep_fail;
- ep->driver_data = fu;
- fu->ep_cmd = ep;
-
- /* Assume endpoint addresses are the same for both speeds */
- uasp_bi_desc.bEndpointAddress = uasp_ss_bi_desc.bEndpointAddress;
- uasp_bo_desc.bEndpointAddress = uasp_ss_bo_desc.bEndpointAddress;
- uasp_status_desc.bEndpointAddress =
- uasp_ss_status_desc.bEndpointAddress;
- uasp_cmd_desc.bEndpointAddress = uasp_ss_cmd_desc.bEndpointAddress;
-
- uasp_fs_bi_desc.bEndpointAddress = uasp_ss_bi_desc.bEndpointAddress;
- uasp_fs_bo_desc.bEndpointAddress = uasp_ss_bo_desc.bEndpointAddress;
- uasp_fs_status_desc.bEndpointAddress =
- uasp_ss_status_desc.bEndpointAddress;
- uasp_fs_cmd_desc.bEndpointAddress = uasp_ss_cmd_desc.bEndpointAddress;
-
- return 0;
-ep_fail:
- pr_err("Can't claim all required eps\n");
-
- give_back_ep(&fu->ep_in);
- give_back_ep(&fu->ep_out);
- give_back_ep(&fu->ep_status);
- give_back_ep(&fu->ep_cmd);
- return -ENOTSUPP;
-}
-
-static void usbg_unbind(struct usb_configuration *c, struct usb_function *f)
-{
- struct f_uas *fu = to_f_uas(f);
-
- kfree(fu);
-}
-
-struct guas_setup_wq {
- struct work_struct work;
- struct f_uas *fu;
- unsigned int alt;
-};
-
-static void usbg_delayed_set_alt(struct work_struct *wq)
-{
- struct guas_setup_wq *work = container_of(wq, struct guas_setup_wq,
- work);
- struct f_uas *fu = work->fu;
- int alt = work->alt;
-
- kfree(work);
-
- if (fu->flags & USBG_IS_BOT)
- bot_cleanup_old_alt(fu);
- if (fu->flags & USBG_IS_UAS)
- uasp_cleanup_old_alt(fu);
-
- if (alt == USB_G_ALT_INT_BBB)
- bot_set_alt(fu);
- else if (alt == USB_G_ALT_INT_UAS)
- uasp_set_alt(fu);
- usb_composite_setup_continue(fu->function.config->cdev);
-}
-
-static int usbg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
-{
- struct f_uas *fu = to_f_uas(f);
-
- if ((alt == USB_G_ALT_INT_BBB) || (alt == USB_G_ALT_INT_UAS)) {
- struct guas_setup_wq *work;
-
- work = kmalloc(sizeof(*work), GFP_ATOMIC);
- if (!work)
- return -ENOMEM;
- INIT_WORK(&work->work, usbg_delayed_set_alt);
- work->fu = fu;
- work->alt = alt;
- schedule_work(&work->work);
- return USB_GADGET_DELAYED_STATUS;
- }
- return -EOPNOTSUPP;
-}
-
-static void usbg_disable(struct usb_function *f)
-{
- struct f_uas *fu = to_f_uas(f);
-
- if (fu->flags & USBG_IS_UAS)
- uasp_cleanup_old_alt(fu);
- else if (fu->flags & USBG_IS_BOT)
- bot_cleanup_old_alt(fu);
- fu->flags = 0;
-}
-
-static int usbg_setup(struct usb_function *f,
- const struct usb_ctrlrequest *ctrl)
-{
- struct f_uas *fu = to_f_uas(f);
-
- if (!(fu->flags & USBG_IS_BOT))
- return -EOPNOTSUPP;
-
- return usbg_bot_setup(f, ctrl);
-}
-
static int usbg_cfg_bind(struct usb_configuration *c)
{
- struct f_uas *fu;
- int ret;
-
- fu = kzalloc(sizeof(*fu), GFP_KERNEL);
- if (!fu)
- return -ENOMEM;
- fu->function.name = "Target Function";
- fu->function.descriptors = uasp_fs_function_desc;
- fu->function.hs_descriptors = uasp_hs_function_desc;
- fu->function.ss_descriptors = uasp_ss_function_desc;
- fu->function.bind = usbg_bind;
- fu->function.unbind = usbg_unbind;
- fu->function.set_alt = usbg_set_alt;
- fu->function.setup = usbg_setup;
- fu->function.disable = usbg_disable;
- fu->tpg = the_only_tpg_I_currently_have;
-
- ret = usb_add_function(c, &fu->function);
- if (ret)
- goto err;
-
- return 0;
-err:
- kfree(fu);
- return ret;
+ return tcm_bind_config(c);
}
static int usb_target_bind(struct usb_composite_dev *cdev)
@@ -2439,6 +78,11 @@
ret = usb_add_config(cdev, &usbg_config_driver,
usbg_cfg_bind);
+ return ret;
+}
+
+static int guas_unbind(struct usb_composite_dev *cdev)
+{
return 0;
}
@@ -2450,28 +94,30 @@
.unbind = guas_unbind,
};
-static int usbg_attach(struct usbg_tpg *tpg)
+static int usbg_attach_cb(bool connect)
{
- return usb_composite_probe(&usbg_driver, usb_target_bind);
-}
+ int ret = 0;
-static void usbg_detach(struct usbg_tpg *tpg)
-{
- usb_composite_unregister(&usbg_driver);
+ if (connect)
+ ret = usb_composite_probe(&usbg_driver, usb_target_bind);
+ else
+ usb_composite_unregister(&usbg_driver);
+
+ return ret;
}
static int __init usb_target_gadget_init(void)
{
int ret;
- ret = usbg_register_configfs();
+ ret = f_tcm_init(&usbg_attach_cb);
return ret;
}
module_init(usb_target_gadget_init);
static void __exit usb_target_gadget_exit(void)
{
- usbg_deregister_configfs();
+ f_tcm_exit();
}
module_exit(usb_target_gadget_exit);
diff --git a/drivers/usb/gadget/u_data_hsuart.c b/drivers/usb/gadget/u_data_hsuart.c
index b2c57c4..91b1190 100644
--- a/drivers/usb/gadget/u_data_hsuart.c
+++ b/drivers/usb/gadget/u_data_hsuart.c
@@ -1062,7 +1062,7 @@
{
struct dentry *ghsuart_data_dfile;
- ghsuart_data_dent = debugfs_create_dir("ghsic_data_xport", 0);
+ ghsuart_data_dent = debugfs_create_dir("ghsuart_data_xport", 0);
if (!ghsuart_data_dent || IS_ERR(ghsuart_data_dent))
return -ENODEV;
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
index 877b1ff..0655daf 100644
--- a/drivers/video/msm/hdmi_msm.c
+++ b/drivers/video/msm/hdmi_msm.c
@@ -763,9 +763,18 @@
static void hdmi_msm_hpd_state_work(struct work_struct *work)
{
- boolean hpd_state;
+ boolean hpd_state = false;
char *envp[2];
+ if (hdmi_msm_state->is_mhl_enabled) {
+ /*
+ * HPD will be controlled from MHL
+ */
+ envp[0] = "";
+ DEV_DBG("%s %u\n", envp[0], hpd_state);
+ return;
+ }
+
if (!hdmi_msm_state || !hdmi_msm_state->hpd_initialized ||
!MSM_HDMI_BASE) {
DEV_DBG("%s: ignored, probe failed\n", __func__);
@@ -4301,12 +4310,17 @@
static int hdmi_msm_power_ctrl(boolean enable)
{
int rc = 0;
- if (!hdmi_prim_display && !external_common_state->hpd_feature_on)
- return 0;
if (enable) {
- DEV_DBG("%s: Turning HPD ciruitry on\n", __func__);
- rc = hdmi_msm_hpd_on(true);
+ /*
+ * Enable HPD only if the UI option is on or if
+ * HDMI is configured as the primary display
+ */
+ if (hdmi_prim_display ||
+ external_common_state->hpd_feature_on) {
+ DEV_DBG("%s: Turning HPD ciruitry on\n", __func__);
+ rc = hdmi_msm_hpd_on(true);
+ }
} else {
DEV_DBG("%s: Turning HPD ciruitry off\n", __func__);
hdmi_msm_hpd_off();
@@ -4356,6 +4370,50 @@
return 0;
}
+void mhl_connect_api(boolean on)
+{
+ char *envp[2];
+
+ /* Simulating a HPD event based on MHL event */
+ hdmi_msm_state->hpd_cable_chg_detected = FALSE;
+ /* QDSP OFF preceding the HPD event notification */
+ switch_set_state(&external_common_state->sdev, 0);
+ DEV_INFO("Hdmi state switch to %d: %s\n",
+ external_common_state->sdev.state, __func__);
+ if (on) {
+ hdmi_msm_read_edid();
+ if (hdmi_msm_has_hdcp())
+ hdmi_msm_state->reauth = FALSE ;
+ /* Build EDID table */
+ hdmi_msm_turn_on();
+ DEV_INFO("HDMI HPD: sense CONNECTED: send ONLINE\n");
+ kobject_uevent(external_common_state->uevent_kobj,
+ KOBJ_ONLINE);
+ hdmi_msm_hdcp_enable();
+ envp[0] = 0;
+ if (!hdmi_msm_has_hdcp()) {
+ /* Send Audio for HDMI Compliance Cases*/
+ envp[0] = "HDCP_STATE=PASS";
+ envp[1] = NULL;
+ DEV_INFO("HDMI HPD: sense : send HDCP_PASS\n");
+ kobject_uevent_env(external_common_state->uevent_kobj,
+ KOBJ_CHANGE, envp);
+ switch_set_state(&external_common_state->sdev, 1);
+ DEV_INFO("Hdmi state switch to %d: %s\n",
+ external_common_state->sdev.state, __func__);
+ }
+ } else {
+ DEV_INFO("HDMI HPD: sense DISCONNECTED: send OFFLINE\n"
+ );
+ kobject_uevent(external_common_state->uevent_kobj,
+ KOBJ_OFFLINE);
+ switch_set_state(&external_common_state->sdev, 0);
+ DEV_INFO("Hdmi state switch to %d: %s\n",
+ external_common_state->sdev.state, __func__);
+ }
+}
+EXPORT_SYMBOL(mhl_connect_api);
+
/* Note that power-off will also be called when the cable-remove event is
* processed on the user-space and as a result the framebuffer is powered
* down. However, we are still required to be able to detect a cable-insert
@@ -4461,6 +4519,8 @@
goto error;
}
+ hdmi_msm_state->is_mhl_enabled = hdmi_msm_state->pd->is_mhl_enabled;
+
rc = check_hdmi_features();
if (rc) {
DEV_ERR("Init FAILED: check_hdmi_features rc=%d\n", rc);
@@ -4528,10 +4588,11 @@
} else
DEV_ERR("Init FAILED: failed to add fb device\n");
- rc = hdmi_msm_hpd_on(true);
- if (rc)
- goto error;
- DEV_INFO("HDMI HPD: ON\n");
+ if (hdmi_prim_display) {
+ rc = hdmi_msm_hpd_on(true);
+ if (rc)
+ goto error;
+ }
if (hdmi_msm_has_hdcp()) {
/* Don't Set Encryption in case of non HDCP builds */
@@ -4678,7 +4739,7 @@
}
external_common_state = &hdmi_msm_state->common;
- external_common_state->video_resolution = HDMI_VFRMT_1920x1080p60_16_9;
+ external_common_state->video_resolution = HDMI_VFRMT_1920x1080p30_16_9;
#ifdef CONFIG_FB_MSM_HDMI_3D
external_common_state->switch_3d = hdmi_msm_switch_3d;
#endif
diff --git a/drivers/video/msm/hdmi_msm.h b/drivers/video/msm/hdmi_msm.h
index 06ebb06..243a27b 100644
--- a/drivers/video/msm/hdmi_msm.h
+++ b/drivers/video/msm/hdmi_msm.h
@@ -110,6 +110,7 @@
void __iomem *hdmi_io;
struct external_common_state_type common;
+ boolean is_mhl_enabled;
};
extern struct hdmi_msm_state_type *hdmi_msm_state;
@@ -134,5 +135,5 @@
void hdmi_msm_cec_one_touch_play(void);
void hdmi_msm_cec_msg_send(struct hdmi_msm_cec_msg *msg);
#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT */
-
+void mhl_connect_api(boolean on);
#endif /* __HDMI_MSM_H__ */
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index 2cbef69..3c869cc 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -848,8 +848,11 @@
MDP_OUTP(base + 0x0018, INTR_HIST_DONE | INTR_HIST_RESET_SEQ_DONE);
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
- mgmt->hist = NULL;
- complete(&mgmt->mdp_hist_comp);
+ if (mgmt->hist != NULL) {
+ mgmt->hist = NULL;
+ complete(&mgmt->mdp_hist_comp);
+ }
+
mdp_disable_irq(mgmt->irq_term);
return 0;
}
@@ -964,8 +967,10 @@
if (!mfd->panel_power_on) {
mgmt->mdp_is_hist_data = FALSE;
- mgmt->hist = NULL;
- complete(&mgmt->mdp_hist_comp);
+ if (mgmt->hist != NULL) {
+ mgmt->hist = NULL;
+ complete(&mgmt->mdp_hist_comp);
+ }
ret = -EINVAL;
goto error_lock;
}
@@ -1132,7 +1137,8 @@
*/
if (!ret && mgmt->mdp_is_hist_valid && mgmt->mdp_is_hist_init) {
mgmt->hist = NULL;
- complete(&mgmt->mdp_hist_comp);
+ if (waitqueue_active(&mgmt->mdp_hist_comp.wait))
+ complete(&mgmt->mdp_hist_comp);
}
if (mgmt->mdp_is_hist_valid == FALSE)
@@ -1233,6 +1239,7 @@
ret = -EPERM;
goto error_lock;
}
+ INIT_COMPLETION(mgmt->mdp_hist_comp);
mgmt->hist = hist;
mutex_unlock(&mgmt->mdp_hist_mutex);
diff --git a/drivers/video/msm/mdp.h b/drivers/video/msm/mdp.h
index f8d54bd..3fd51ba 100644
--- a/drivers/video/msm/mdp.h
+++ b/drivers/video/msm/mdp.h
@@ -75,7 +75,8 @@
struct mdp_buf_type {
struct ion_handle *ihdl;
- u32 phys_addr;
+ u32 write_addr;
+ u32 read_addr;
u32 size;
};
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index 1557eed..c9bdf27 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -26,6 +26,7 @@
extern struct mdp4_statistic mdp4_stat;
extern uint32 mdp4_extn_disp;
extern char *mmss_cc_base; /* mutimedia sub system clock control */
+extern spinlock_t dsi_clk_lock;
#define MDP4_OVERLAYPROC0_BASE 0x10000
#define MDP4_OVERLAYPROC1_BASE 0x18000
@@ -337,7 +338,8 @@
uint32 element1; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */
uint32 element0; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */
struct completion comp;
- ulong blt_addr; /* blt mode addr */
+ ulong ov_blt_addr; /* blt mode addr */
+ ulong dma_blt_addr; /* blt mode addr */
ulong blt_base;
ulong blt_offset;
uint32 blt_cnt;
@@ -718,6 +720,14 @@
struct mdp4_overlay_pipe *pipe);
void mdp4_dsi_cmd_overlay_restore(void);
void mdp_dsi_cmd_overlay_suspend(struct msm_fb_data_type *mfd);
+#ifdef CONFIG_FB_MSM_MDP303
+static inline void mdp4_dsi_cmd_del_timer(void)
+{
+ /* empty */
+}
+#else
+void mdp4_dsi_cmd_del_timer(void);
+#endif
#else
static inline void mdp4_dsi_cmd_dma_busy_wait(struct msm_fb_data_type *mfd)
{
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index 3afe28b..d045e69 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -346,7 +346,7 @@
MDP_OUTP(MDP_BASE + 0xb0004,
(pipe->src_height << 16 | pipe->src_width));
- if (pipe->blt_addr) {
+ if (pipe->dma_blt_addr) {
uint32 off, bpp;
#ifdef BLT_RGB565
bpp = 2; /* overlay ouput is RGB565 */
@@ -356,7 +356,7 @@
off = 0;
if (pipe->ov_cnt & 0x01)
off = pipe->src_height * pipe->src_width * bpp;
- MDP_OUTP(MDP_BASE + 0xb0008, pipe->blt_addr + off);
+ MDP_OUTP(MDP_BASE + 0xb0008, pipe->dma_blt_addr + off);
/* RGB888, output of overlay blending */
MDP_OUTP(MDP_BASE + 0xb000c, pipe->src_width * bpp);
} else {
@@ -424,7 +424,7 @@
if (mdp_is_in_isr == FALSE)
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
- if (pipe->blt_addr) {
+ if (pipe->dma_blt_addr) {
#ifdef BLT_RGB565
bpp = 2; /* overlay ouput is RGB565 */
#else
@@ -433,7 +433,7 @@
off = 0;
if (pipe->dmap_cnt & 0x01)
off = pipe->src_height * pipe->src_width * bpp;
- MDP_OUTP(MDP_BASE + 0x90008, pipe->blt_addr + off);
+ MDP_OUTP(MDP_BASE + 0x90008, pipe->dma_blt_addr + off);
/* RGB888, output of overlay blending */
MDP_OUTP(MDP_BASE + 0x9000c, pipe->src_width * bpp);
} else {
@@ -1321,7 +1321,7 @@
/*
* BLT support both primary and external external
*/
- if (pipe->blt_addr) {
+ if (pipe->ov_blt_addr) {
int off, bpp;
#ifdef BLT_RGB565
bpp = 2; /* overlay ouput is RGB565 */
@@ -1338,10 +1338,10 @@
if (pipe->ov_cnt & 0x01)
off = pipe->src_height * pipe->src_width * bpp;
- outpdw(overlay_base + 0x000c, pipe->blt_addr + off);
+ outpdw(overlay_base + 0x000c, pipe->ov_blt_addr + off);
/* overlay ouput is RGB888 */
outpdw(overlay_base + 0x0010, pipe->src_width * bpp);
- outpdw(overlay_base + 0x001c, pipe->blt_addr + off);
+ outpdw(overlay_base + 0x001c, pipe->ov_blt_addr + off);
/* MDDI - BLT + on demand */
outpdw(overlay_base + 0x0004, 0x08);
@@ -1361,19 +1361,19 @@
pipe->src_width * bpp;
outpdw(overlay_base + 0x000c,
- pipe->blt_addr + off);
+ pipe->ov_blt_addr + off);
/* overlay ouput is RGB888 */
outpdw(overlay_base + 0x0010,
((pipe->src_width << 16) |
pipe->src_width));
outpdw(overlay_base + 0x001c,
- pipe->blt_addr + off);
+ pipe->ov_blt_addr + off);
off = pipe->src_height * pipe->src_width;
/* align chroma to 2k address */
off = (off + 2047) & ~2047;
/* UV plane adress */
outpdw(overlay_base + 0x0020,
- pipe->blt_addr + off);
+ pipe->ov_blt_addr + off);
/* MDDI - BLT + on demand */
outpdw(overlay_base + 0x0004, 0x08);
/* pseudo planar + writeback */
diff --git a/drivers/video/msm/mdp4_overlay_dsi_cmd.c b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
index 8ebf8a0..d0ac1a6 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_cmd.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
@@ -61,12 +61,14 @@
static void dsi_clock_tout(unsigned long data)
{
+ spin_lock(&dsi_clk_lock);
if (mipi_dsi_clk_on) {
if (dsi_state == ST_DSI_PLAYING) {
mipi_dsi_turn_off_clks();
mdp4_overlay_dsi_state_set(ST_DSI_CLK_OFF);
}
}
+ spin_unlock(&dsi_clk_lock);
}
static __u32 msm_fb_line_length(__u32 fb_index, __u32 xres, int bpp)
@@ -84,6 +86,11 @@
return xres * bpp;
}
+void mdp4_dsi_cmd_del_timer(void)
+{
+ del_timer_sync(&dsi_clock_timer);
+}
+
void mdp4_mipi_vsync_enable(struct msm_fb_data_type *mfd,
struct mdp4_overlay_pipe *pipe, int which)
{
@@ -162,7 +169,8 @@
dsi_pipe = pipe; /* keep it */
mdp4_init_writeback_buf(mfd, MDP4_MIXER0);
- pipe->blt_addr = 0;
+ pipe->ov_blt_addr = 0;
+ pipe->dma_blt_addr = 0;
} else {
pipe = dsi_pipe;
@@ -321,24 +329,25 @@
{
unsigned long flag;
- pr_debug("%s: blt_end=%d blt_addr=%x pid=%d\n",
- __func__, dsi_pipe->blt_end, (int)dsi_pipe->blt_addr, current->pid);
+ pr_debug("%s: blt_end=%d ov_blt_addr=%x pid=%d\n",
+ __func__, dsi_pipe->blt_end, (int)dsi_pipe->ov_blt_addr, current->pid);
mdp4_allocate_writeback_buf(mfd, MDP4_MIXER0);
- if (mfd->ov0_wb_buf->phys_addr == 0) {
+ if (mfd->ov0_wb_buf->write_addr == 0) {
pr_info("%s: no blt_base assigned\n", __func__);
return -EBUSY;
}
- if (dsi_pipe->blt_addr == 0) {
+ if (dsi_pipe->ov_blt_addr == 0) {
mdp4_dsi_cmd_dma_busy_wait(mfd);
spin_lock_irqsave(&mdp_spin_lock, flag);
dsi_pipe->blt_end = 0;
dsi_pipe->blt_cnt = 0;
dsi_pipe->ov_cnt = 0;
dsi_pipe->dmap_cnt = 0;
- dsi_pipe->blt_addr = mfd->ov0_wb_buf->phys_addr;
+ dsi_pipe->ov_blt_addr = mfd->ov0_wb_buf->write_addr;
+ dsi_pipe->dma_blt_addr = mfd->ov0_wb_buf->read_addr;
mdp4_stat.blt_dsi_cmd++;
spin_unlock_irqrestore(&mdp_spin_lock, flag);
return 0;
@@ -352,10 +361,10 @@
unsigned long flag;
- pr_debug("%s: blt_end=%d blt_addr=%x\n",
- __func__, dsi_pipe->blt_end, (int)dsi_pipe->blt_addr);
+ pr_debug("%s: blt_end=%d ov_blt_addr=%x\n",
+ __func__, dsi_pipe->blt_end, (int)dsi_pipe->ov_blt_addr);
- if ((dsi_pipe->blt_end == 0) && dsi_pipe->blt_addr) {
+ if ((dsi_pipe->blt_end == 0) && dsi_pipe->ov_blt_addr) {
spin_lock_irqsave(&mdp_spin_lock, flag);
dsi_pipe->blt_end = 1; /* mark as end */
spin_unlock_irqrestore(&mdp_spin_lock, flag);
@@ -393,7 +402,7 @@
char *overlay_base;
- if (pipe->blt_addr == 0)
+ if (pipe->ov_blt_addr == 0)
return;
@@ -405,7 +414,7 @@
off = 0;
if (pipe->dmap_cnt & 0x01)
off = pipe->src_height * pipe->src_width * bpp;
- addr = pipe->blt_addr + off;
+ addr = pipe->dma_blt_addr + off;
/* dmap */
MDP_OUTP(MDP_BASE + 0x90008, addr);
@@ -413,7 +422,7 @@
off = 0;
if (pipe->ov_cnt & 0x01)
off = pipe->src_height * pipe->src_width * bpp;
- addr2 = pipe->blt_addr + off;
+ addr2 = pipe->ov_blt_addr + off;
/* overlay 0 */
overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
outpdw(overlay_base + 0x000c, addr2);
@@ -441,7 +450,8 @@
spin_unlock(&mdp_spin_lock);
if (dsi_pipe->blt_end) {
dsi_pipe->blt_end = 0;
- dsi_pipe->blt_addr = 0;
+ dsi_pipe->dma_blt_addr = 0;
+ dsi_pipe->ov_blt_addr = 0;
pr_debug("%s: END, ov_cnt=%d dmap_cnt=%d\n",
__func__, dsi_pipe->ov_cnt, dsi_pipe->dmap_cnt);
mdp_intr_mask &= ~INTR_DMA_P_DONE;
@@ -479,7 +489,7 @@
{
int diff;
- if (dsi_pipe->blt_addr == 0) {
+ if (dsi_pipe->ov_blt_addr == 0) {
mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
spin_lock(&mdp_spin_lock);
dma->busy = FALSE;
@@ -539,7 +549,7 @@
mipi_dsi_mdp_busy_wait(dsi_mfd);
mdp4_overlay_update_dsi_cmd(dsi_mfd);
- if (dsi_pipe->blt_addr)
+ if (dsi_pipe->ov_blt_addr)
mdp4_dsi_blt_dmap_busy_wait(dsi_mfd);
mdp4_dsi_cmd_overlay_kickoff(dsi_mfd, dsi_pipe);
}
@@ -588,11 +598,10 @@
__func__, current->pid, mipi_dsi_clk_on);
/* satrt dsi clock if necessary */
- if (mipi_dsi_clk_on == 0) {
- local_bh_disable();
+ spin_lock_bh(&dsi_clk_lock);
+ if (mipi_dsi_clk_on == 0)
mipi_dsi_turn_on_clks();
- local_bh_enable();
- }
+ spin_unlock_bh(&dsi_clk_lock);
spin_lock_irqsave(&mdp_spin_lock, flag);
if (mfd->dma->busy == TRUE) {
@@ -622,17 +631,17 @@
* to be called before kickoff.
* vice versa for blt disabled.
*/
- if (dsi_pipe->blt_addr && dsi_pipe->blt_cnt == 0)
+ if (dsi_pipe->ov_blt_addr && dsi_pipe->blt_cnt == 0)
mdp4_overlay_update_dsi_cmd(mfd); /* first time */
- else if (dsi_pipe->blt_addr == 0 && dsi_pipe->blt_cnt) {
+ else if (dsi_pipe->ov_blt_addr == 0 && dsi_pipe->blt_cnt) {
mdp4_overlay_update_dsi_cmd(mfd); /* last time */
dsi_pipe->blt_cnt = 0;
}
- pr_debug("%s: blt_addr=%d blt_cnt=%d\n",
- __func__, (int)dsi_pipe->blt_addr, dsi_pipe->blt_cnt);
+ pr_debug("%s: ov_blt_addr=%d blt_cnt=%d\n",
+ __func__, (int)dsi_pipe->ov_blt_addr, dsi_pipe->blt_cnt);
- if (dsi_pipe->blt_addr)
+ if (dsi_pipe->ov_blt_addr)
mdp4_dsi_blt_dmap_busy_wait(dsi_mfd);
mdp4_dsi_cmd_overlay_kickoff(mfd, pipe);
@@ -658,7 +667,7 @@
mipi_dsi_mdp_busy_wait(mfd);
- if (dsi_pipe->blt_addr == 0)
+ if (dsi_pipe->ov_blt_addr == 0)
mipi_dsi_cmd_mdp_start();
mdp4_overlay_dsi_state_set(ST_DSI_PLAYING);
@@ -666,7 +675,7 @@
spin_lock_irqsave(&mdp_spin_lock, flag);
mdp_enable_irq(MDP_OVERLAY0_TERM);
mfd->dma->busy = TRUE;
- if (dsi_pipe->blt_addr)
+ if (dsi_pipe->ov_blt_addr)
mfd->dma->dmap_busy = TRUE;
/* start OVERLAY pipe */
spin_unlock_irqrestore(&mdp_spin_lock, flag);
@@ -700,7 +709,7 @@
if (mfd && mfd->panel_power_on) {
mdp4_dsi_cmd_dma_busy_wait(mfd);
- if (dsi_pipe && dsi_pipe->blt_addr)
+ if (dsi_pipe && dsi_pipe->ov_blt_addr)
mdp4_dsi_blt_dmap_busy_wait(mfd);
mdp4_overlay_update_dsi_cmd(mfd);
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index b0f3e17..bc4476e 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -152,7 +152,8 @@
init_completion(&dsi_video_comp);
mdp4_init_writeback_buf(mfd, MDP4_MIXER0);
- pipe->blt_addr = 0;
+ pipe->ov_blt_addr = 0;
+ pipe->dma_blt_addr = 0;
} else {
pipe = dsi_pipe;
@@ -416,7 +417,7 @@
char *overlay_base;
- if (pipe->blt_addr == 0)
+ if (pipe->ov_blt_addr == 0)
return;
@@ -428,7 +429,7 @@
off = 0;
if (pipe->ov_cnt & 0x01)
off = pipe->src_height * pipe->src_width * bpp;
- addr = pipe->blt_addr + off;
+ addr = pipe->ov_blt_addr + off;
/* overlay 0 */
overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
@@ -441,7 +442,7 @@
uint32 off, addr;
int bpp;
- if (pipe->blt_addr == 0)
+ if (pipe->ov_blt_addr == 0)
return;
@@ -453,7 +454,7 @@
off = 0;
if (pipe->dmap_cnt & 0x01)
off = pipe->src_height * pipe->src_width * bpp;
- addr = pipe->blt_addr + off;
+ addr = pipe->dma_blt_addr + off;
/* dmap */
MDP_OUTP(MDP_BASE + 0x90008, addr);
@@ -529,7 +530,7 @@
if (pipe->flags & MDP_OV_PLAY_NOWAIT)
return;
- if (dsi_pipe->blt_addr) {
+ if (dsi_pipe->ov_blt_addr) {
mdp4_overlay_dsi_video_dma_busy_wait(mfd);
mdp4_dsi_video_blt_ov_update(dsi_pipe);
@@ -569,10 +570,15 @@
{
if (blt_cfg_changed) {
mdp_is_in_isr = TRUE;
- mdp4_overlayproc_cfg(dsi_pipe);
- mdp4_overlay_dmap_xy(dsi_pipe);
+ if (dsi_pipe->ov_blt_addr) {
+ mdp4_overlay_dmap_xy(dsi_pipe);
+ mdp4_overlayproc_cfg(dsi_pipe);
+ } else {
+ mdp4_overlayproc_cfg(dsi_pipe);
+ mdp4_overlay_dmap_xy(dsi_pipe);
+ }
mdp_is_in_isr = FALSE;
- if (dsi_pipe->blt_addr) {
+ if (dsi_pipe->ov_blt_addr) {
mdp4_dsi_video_blt_ov_update(dsi_pipe);
dsi_pipe->ov_cnt++;
outp32(MDP_INTR_CLEAR, INTR_OVERLAY0_DONE);
@@ -595,7 +601,7 @@
{
spin_lock(&mdp_spin_lock);
dma->busy = FALSE;
- if (dsi_pipe->blt_addr == 0) {
+ if (dsi_pipe->ov_blt_addr == 0) {
spin_unlock(&mdp_spin_lock);
return;
}
@@ -618,21 +624,23 @@
mdp4_allocate_writeback_buf(mfd, MDP4_MIXER0);
- if (mfd->ov0_wb_buf->phys_addr == 0) {
+ if (mfd->ov0_wb_buf->write_addr == 0) {
pr_info("%s: no blt_base assigned\n", __func__);
return;
}
spin_lock_irqsave(&mdp_spin_lock, flag);
- if (enable && dsi_pipe->blt_addr == 0) {
- dsi_pipe->blt_addr = mfd->ov0_wb_buf->phys_addr;
+ if (enable && dsi_pipe->ov_blt_addr == 0) {
+ dsi_pipe->ov_blt_addr = mfd->ov0_wb_buf->write_addr;
+ dsi_pipe->dma_blt_addr = mfd->ov0_wb_buf->read_addr;
dsi_pipe->blt_cnt = 0;
dsi_pipe->ov_cnt = 0;
dsi_pipe->dmap_cnt = 0;
mdp4_stat.blt_dsi_video++;
change++;
- } else if (enable == 0 && dsi_pipe->blt_addr) {
- dsi_pipe->blt_addr = 0;
+ } else if (enable == 0 && dsi_pipe->ov_blt_addr) {
+ dsi_pipe->ov_blt_addr = 0;
+ dsi_pipe->dma_blt_addr = 0;
change++;
}
@@ -641,8 +649,8 @@
return;
}
- pr_debug("%s: enable=%d blt_addr=%x\n", __func__,
- enable, (int)dsi_pipe->blt_addr);
+ pr_debug("%s: enable=%d ov_blt_addr=%x\n", __func__,
+ enable, (int)dsi_pipe->ov_blt_addr);
blt_cfg_changed = 1;
spin_unlock_irqrestore(&mdp_spin_lock, flag);
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index e26522b..b90812f 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -377,7 +377,8 @@
return -ENODEV;
mdp4_init_writeback_buf(mfd, MDP4_MIXER1);
- dtv_pipe->blt_addr = 0;
+ dtv_pipe->ov_blt_addr = 0;
+ dtv_pipe->dma_blt_addr = 0;
return mdp4_dtv_start(mfd);
}
@@ -408,7 +409,7 @@
int bpp;
char *overlay_base;
- if (pipe->blt_addr == 0)
+ if (pipe->ov_blt_addr == 0)
return;
#ifdef BLT_RGB565
bpp = 2; /* overlay ouput is RGB565 */
@@ -418,7 +419,7 @@
off = (pipe->ov_cnt & 0x01) ?
pipe->src_height * pipe->src_width * bpp : 0;
- addr = pipe->blt_addr + off;
+ addr = pipe->ov_blt_addr + off;
pr_debug("%s overlay addr 0x%x\n", __func__, addr);
/* overlay 1 */
overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
@@ -431,7 +432,7 @@
uint32 off, addr;
int bpp;
- if (pipe->blt_addr == 0)
+ if (pipe->ov_blt_addr == 0)
return;
#ifdef BLT_RGB565
@@ -441,7 +442,7 @@
#endif
off = (pipe->dmae_cnt & 0x01) ?
pipe->src_height * pipe->src_width * bpp : 0;
- addr = pipe->blt_addr + off;
+ addr = pipe->dma_blt_addr + off;
MDP_OUTP(MDP_BASE + 0xb0008, addr);
}
@@ -464,7 +465,7 @@
return;
}
- if (dtv_pipe->blt_addr) {
+ if (dtv_pipe->ov_blt_addr) {
mdp4_dtv_blt_ov_update(dtv_pipe);
dtv_pipe->ov_cnt++;
mdp4_overlay_dtv_ov_kick_start();
@@ -524,7 +525,7 @@
msecs_to_jiffies(VSYNC_PERIOD * 3));
mdp_disable_irq(MDP_OVERLAY1_TERM);
- if (dtv_pipe->blt_addr)
+ if (dtv_pipe->ov_blt_addr)
mdp4_overlay_dtv_wait4dmae(mfd);
}
@@ -581,7 +582,7 @@
{
if (!dtv_pipe)
return;
- if (dtv_pipe->blt_addr) {
+ if (dtv_pipe->ov_blt_addr) {
mdp4_dtv_blt_dmae_update(dtv_pipe);
dtv_pipe->dmae_cnt++;
}
@@ -642,7 +643,7 @@
unsigned long flag;
int change = 0;
- if (!mfd->ov1_wb_buf->phys_addr) {
+ if (!mfd->ov1_wb_buf->write_addr) {
pr_debug("%s: no writeback buf assigned\n", __func__);
return;
}
@@ -654,16 +655,18 @@
}
spin_lock_irqsave(&mdp_spin_lock, flag);
- if (enable && dtv_pipe->blt_addr == 0) {
- dtv_pipe->blt_addr = mfd->ov1_wb_buf->phys_addr;
+ if (enable && dtv_pipe->ov_blt_addr == 0) {
+ dtv_pipe->ov_blt_addr = mfd->ov1_wb_buf->write_addr;
+ dtv_pipe->dma_blt_addr = mfd->ov1_wb_buf->read_addr;
change++;
dtv_pipe->ov_cnt = 0;
dtv_pipe->dmae_cnt = 0;
- } else if (enable == 0 && dtv_pipe->blt_addr) {
- dtv_pipe->blt_addr = 0;
+ } else if (enable == 0 && dtv_pipe->ov_blt_addr) {
+ dtv_pipe->ov_blt_addr = 0;
+ dtv_pipe->dma_blt_addr = 0;
change++;
}
- pr_debug("%s: blt_addr=%x\n", __func__, (int)dtv_pipe->blt_addr);
+ pr_debug("%s: ov_blt_addr=%x\n", __func__, (int)dtv_pipe->ov_blt_addr);
spin_unlock_irqrestore(&mdp_spin_lock, flag);
if (!change)
@@ -675,8 +678,8 @@
msleep(20);
}
- mdp4_overlayproc_cfg(dtv_pipe);
mdp4_overlay_dmae_xy(dtv_pipe);
+ mdp4_overlayproc_cfg(dtv_pipe);
MDP_OUTP(MDP_BASE + DTV_BASE, 1); /* start dtv */
}
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index 98c8191..bcc4ea6 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -133,8 +133,8 @@
init_completion(&lcdc_comp);
mdp4_init_writeback_buf(mfd, MDP4_MIXER0);
- pipe->blt_addr = 0;
-
+ pipe->ov_blt_addr = 0;
+ pipe->dma_blt_addr = 0;
} else {
pipe = lcdc_pipe;
}
@@ -325,7 +325,7 @@
char *overlay_base;
- if (pipe->blt_addr == 0)
+ if (pipe->ov_blt_addr == 0)
return;
@@ -337,7 +337,7 @@
off = 0;
if (pipe->ov_cnt & 0x01)
off = pipe->src_height * pipe->src_width * bpp;
- addr = pipe->blt_addr + off;
+ addr = pipe->ov_blt_addr + off;
/* overlay 0 */
overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
@@ -350,7 +350,7 @@
uint32 off, addr;
int bpp;
- if (pipe->blt_addr == 0)
+ if (pipe->ov_blt_addr == 0)
return;
@@ -362,7 +362,7 @@
off = 0;
if (pipe->dmap_cnt & 0x01)
off = pipe->src_height * pipe->src_width * bpp;
- addr = pipe->blt_addr + off;
+ addr = pipe->dma_blt_addr + off;
/* dmap */
MDP_OUTP(MDP_BASE + 0x90008, addr);
@@ -438,7 +438,7 @@
if (pipe->flags & MDP_OV_PLAY_NOWAIT)
return;
- if (lcdc_pipe->blt_addr) {
+ if (lcdc_pipe->ov_blt_addr) {
mdp4_overlay_lcdc_dma_busy_wait(mfd);
mdp4_lcdc_blt_ov_update(lcdc_pipe);
@@ -485,7 +485,7 @@
{
spin_lock(&mdp_spin_lock);
dma->busy = FALSE;
- if (lcdc_pipe->blt_addr == 0) {
+ if (lcdc_pipe->ov_blt_addr == 0) {
spin_unlock(&mdp_spin_lock);
return;
}
@@ -500,7 +500,7 @@
{
unsigned long flag;
- if (lcdc_pipe->blt_addr) {
+ if (lcdc_pipe->ov_blt_addr) {
mdp4_overlay_lcdc_dma_busy_wait(mfd);
mdp4_lcdc_blt_ov_update(lcdc_pipe);
@@ -530,24 +530,26 @@
mdp4_allocate_writeback_buf(mfd, MDP4_MIXER0);
- if (!mfd->ov0_wb_buf->phys_addr) {
+ if (!mfd->ov0_wb_buf->write_addr) {
pr_debug("%s: no blt_base assigned\n", __func__);
return;
}
spin_lock_irqsave(&mdp_spin_lock, flag);
- if (enable && lcdc_pipe->blt_addr == 0) {
- lcdc_pipe->blt_addr = mfd->ov0_wb_buf->phys_addr;
+ if (enable && lcdc_pipe->ov_blt_addr == 0) {
+ lcdc_pipe->ov_blt_addr = mfd->ov0_wb_buf->write_addr;
+ lcdc_pipe->dma_blt_addr = mfd->ov0_wb_buf->read_addr;
change++;
lcdc_pipe->blt_cnt = 0;
lcdc_pipe->ov_cnt = 0;
lcdc_pipe->dmap_cnt = 0;
mdp4_stat.blt_lcdc++;
- } else if (enable == 0 && lcdc_pipe->blt_addr) {
- lcdc_pipe->blt_addr = 0;
+ } else if (enable == 0 && lcdc_pipe->ov_blt_addr) {
+ lcdc_pipe->ov_blt_addr = 0;
+ lcdc_pipe->dma_blt_addr = 0;
change++;
}
- pr_info("%s: blt_addr=%x\n", __func__, (int)lcdc_pipe->blt_addr);
+ pr_info("%s: ov_blt_addr=%x\n", __func__, (int)lcdc_pipe->ov_blt_addr);
spin_unlock_irqrestore(&mdp_spin_lock, flag);
if (!change)
@@ -559,9 +561,9 @@
msleep(20);
}
- mdp4_overlayproc_cfg(lcdc_pipe);
mdp4_overlay_dmap_xy(lcdc_pipe);
- if (lcdc_pipe->blt_addr) {
+ mdp4_overlayproc_cfg(lcdc_pipe);
+ if (lcdc_pipe->ov_blt_addr) {
mdp4_overlay_lcdc_prefill(mfd);
mdp4_overlay_lcdc_prefill(mfd);
}
diff --git a/drivers/video/msm/mdp4_overlay_mddi.c b/drivers/video/msm/mdp4_overlay_mddi.c
index 82864918..c4e6793 100644
--- a/drivers/video/msm/mdp4_overlay_mddi.c
+++ b/drivers/video/msm/mdp4_overlay_mddi.c
@@ -163,7 +163,8 @@
MDP_OUTP(MDP_BASE + 0x00098, 0x01);
mdp4_init_writeback_buf(mfd, MDP4_MIXER0);
- pipe->blt_addr = 0;
+ pipe->ov_blt_addr = 0;
+ pipe->dma_blt_addr = 0;
} else {
pipe = mddi_pipe;
}
@@ -254,23 +255,25 @@
unsigned long flag;
pr_debug("%s: blt_end=%d blt_addr=%x pid=%d\n",
- __func__, mddi_pipe->blt_end, (int)mddi_pipe->blt_addr, current->pid);
+ __func__, mddi_pipe->blt_end,
+ (int)mddi_pipe->ov_blt_addr, current->pid);
mdp4_allocate_writeback_buf(mfd, MDP4_MIXER0);
- if (mfd->ov0_wb_buf->phys_addr == 0) {
+ if (mfd->ov0_wb_buf->write_addr == 0) {
pr_info("%s: no blt_base assigned\n", __func__);
return -EBUSY;
}
- if (mddi_pipe->blt_addr == 0) {
+ if (mddi_pipe->ov_blt_addr == 0) {
mdp4_mddi_dma_busy_wait(mfd);
spin_lock_irqsave(&mdp_spin_lock, flag);
mddi_pipe->blt_end = 0;
mddi_pipe->blt_cnt = 0;
mddi_pipe->ov_cnt = 0;
mddi_pipe->dmap_cnt = 0;
- mddi_pipe->blt_addr = mfd->ov0_wb_buf->phys_addr;
+ mddi_pipe->ov_blt_addr = mfd->ov0_wb_buf->write_addr;
+ mddi_pipe->dma_blt_addr = mfd->ov0_wb_buf->write_addr;
mdp4_stat.blt_mddi++;
spin_unlock_irqrestore(&mdp_spin_lock, flag);
return 0;
@@ -284,9 +287,9 @@
unsigned long flag;
pr_debug("%s: blt_end=%d blt_addr=%x\n",
- __func__, mddi_pipe->blt_end, (int)mddi_pipe->blt_addr);
+ __func__, mddi_pipe->blt_end, (int)mddi_pipe->ov_blt_addr);
- if ((mddi_pipe->blt_end == 0) && mddi_pipe->blt_addr) {
+ if ((mddi_pipe->blt_end == 0) && mddi_pipe->ov_blt_addr) {
spin_lock_irqsave(&mdp_spin_lock, flag);
mddi_pipe->blt_end = 1; /* mark as end */
spin_unlock_irqrestore(&mdp_spin_lock, flag);
@@ -323,7 +326,7 @@
int bpp;
char *overlay_base;
- if (pipe->blt_addr == 0)
+ if (pipe->ov_blt_addr == 0)
return;
@@ -336,7 +339,7 @@
if (pipe->dmap_cnt & 0x01)
off = pipe->src_height * pipe->src_width * bpp;
- addr = pipe->blt_addr + off;
+ addr = pipe->ov_blt_addr + off;
/* dmap */
MDP_OUTP(MDP_BASE + 0x90008, addr);
@@ -344,7 +347,7 @@
off = 0;
if (pipe->ov_cnt & 0x01)
off = pipe->src_height * pipe->src_width * bpp;
- addr2 = pipe->blt_addr + off;
+ addr2 = pipe->ov_blt_addr + off;
/* overlay 0 */
overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
outpdw(overlay_base + 0x000c, addr2);
@@ -371,7 +374,8 @@
if (mddi_pipe->blt_end) {
mddi_pipe->blt_end = 0;
- mddi_pipe->blt_addr = 0;
+ mddi_pipe->ov_blt_addr = 0;
+ mddi_pipe->dma_blt_addr = 0;
pr_debug("%s: END, ov_cnt=%d dmap_cnt=%d\n", __func__,
mddi_pipe->ov_cnt, mddi_pipe->dmap_cnt);
mdp_intr_mask &= ~INTR_DMA_P_DONE;
@@ -406,7 +410,7 @@
{
int diff;
- if (mddi_pipe->blt_addr == 0) {
+ if (mddi_pipe->ov_blt_addr == 0) {
mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
spin_lock(&mdp_spin_lock);
dma->busy = FALSE;
@@ -473,7 +477,7 @@
mdp4_mddi_dma_busy_wait(mddi_mfd);
mdp4_overlay_update_lcd(mddi_mfd);
- if (mddi_pipe->blt_addr)
+ if (mddi_pipe->ov_blt_addr)
mdp4_mddi_blt_dmap_busy_wait(mddi_mfd);
mdp4_mddi_overlay_kickoff(mddi_mfd, mddi_pipe);
mddi_mfd->dma_update_flag = 1;
@@ -539,17 +543,17 @@
* to be called before kickoff.
* vice versa for blt disabled.
*/
- if (mddi_pipe->blt_addr && mddi_pipe->blt_cnt == 0)
+ if (mddi_pipe->ov_blt_addr && mddi_pipe->blt_cnt == 0)
mdp4_overlay_update_lcd(mfd); /* first time */
- else if (mddi_pipe->blt_addr == 0 && mddi_pipe->blt_cnt) {
+ else if (mddi_pipe->ov_blt_addr == 0 && mddi_pipe->blt_cnt) {
mdp4_overlay_update_lcd(mfd); /* last time */
mddi_pipe->blt_cnt = 0;
}
pr_debug("%s: blt_addr=%d blt_cnt=%d\n",
- __func__, (int)mddi_pipe->blt_addr, mddi_pipe->blt_cnt);
+ __func__, (int)mddi_pipe->ov_blt_addr, mddi_pipe->blt_cnt);
- if (mddi_pipe->blt_addr)
+ if (mddi_pipe->ov_blt_addr)
mdp4_mddi_blt_dmap_busy_wait(mddi_mfd);
mdp4_mddi_overlay_kickoff(mfd, pipe);
}
@@ -572,7 +576,7 @@
mdp_enable_irq(MDP_OVERLAY0_TERM);
spin_lock_irqsave(&mdp_spin_lock, flag);
mfd->dma->busy = TRUE;
- if (mddi_pipe->blt_addr)
+ if (mddi_pipe->ov_blt_addr)
mfd->dma->dmap_busy = TRUE;
spin_unlock_irqrestore(&mdp_spin_lock, flag);
/* start OVERLAY pipe */
@@ -657,7 +661,7 @@
mdp_enable_irq(MDP_DMA_S_TERM);
- if (mddi_pipe->blt_addr == 0)
+ if (mddi_pipe->ov_blt_addr == 0)
mfd->dma->busy = TRUE;
mfd->ibuf_flushed = TRUE;
@@ -688,7 +692,7 @@
if (mfd && mfd->panel_power_on) {
mdp4_mddi_dma_busy_wait(mfd);
- if (mddi_pipe && mddi_pipe->blt_addr)
+ if (mddi_pipe && mddi_pipe->ov_blt_addr)
mdp4_mddi_blt_dmap_busy_wait(mfd);
mdp4_overlay_update_lcd(mfd);
diff --git a/drivers/video/msm/mdp4_overlay_writeback.c b/drivers/video/msm/mdp4_overlay_writeback.c
index f426f8c..32fe141 100644
--- a/drivers/video/msm/mdp4_overlay_writeback.c
+++ b/drivers/video/msm/mdp4_overlay_writeback.c
@@ -272,11 +272,11 @@
}
mutex_unlock(&mfd->writeback_mutex);
- writeback_pipe->blt_addr = (ulong) (node ? node->addr : NULL);
+ writeback_pipe->ov_blt_addr = (ulong) (node ? node->addr : NULL);
- if (!writeback_pipe->blt_addr) {
+ if (!writeback_pipe->ov_blt_addr) {
pr_err("%s: no writeback buffer 0x%x, %p\n", __func__,
- (unsigned int)writeback_pipe->blt_addr, node);
+ (unsigned int)writeback_pipe->ov_blt_addr, node);
mutex_unlock(&mfd->unregister_mutex);
return;
}
@@ -324,13 +324,13 @@
}
mutex_unlock(&mfd->writeback_mutex);
- writeback_pipe->blt_addr = (ulong) (node ? node->addr : NULL);
+ writeback_pipe->ov_blt_addr = (ulong) (node ? node->addr : NULL);
mutex_lock(&mfd->dma->ov_mutex);
pr_debug("%s in writeback\n", __func__);
- if (writeback_pipe && !writeback_pipe->blt_addr) {
+ if (writeback_pipe && !writeback_pipe->ov_blt_addr) {
pr_err("%s: no writeback buffer 0x%x\n", __func__,
- (unsigned int)writeback_pipe->blt_addr);
+ (unsigned int)writeback_pipe->ov_blt_addr);
ret = mdp4_overlay_writeback_update(mfd);
if (ret)
pr_err("%s: update failed writeback pipe NULL\n",
@@ -351,7 +351,7 @@
}
pr_debug("%s: in writeback pan display 0x%x\n", __func__,
- (unsigned int)writeback_pipe->blt_addr);
+ (unsigned int)writeback_pipe->ov_blt_addr);
mdp4_writeback_kickoff_ui(mfd, writeback_pipe);
mdp4_iommu_unmap(writeback_pipe);
diff --git a/drivers/video/msm/mdp4_util.c b/drivers/video/msm/mdp4_util.c
index 8bd125b..4c0e28f 100644
--- a/drivers/video/msm/mdp4_util.c
+++ b/drivers/video/msm/mdp4_util.c
@@ -2559,13 +2559,14 @@
buf = mfd->ov1_wb_buf;
buf->ihdl = NULL;
- buf->phys_addr = 0;
+ buf->write_addr = 0;
+ buf->read_addr = 0;
}
u32 mdp4_allocate_writeback_buf(struct msm_fb_data_type *mfd, u32 mix_num)
{
struct mdp_buf_type *buf;
- ion_phys_addr_t addr;
+ ion_phys_addr_t addr, read_addr = 0;
size_t buffer_size;
unsigned long len;
@@ -2574,7 +2575,7 @@
else
buf = mfd->ov1_wb_buf;
- if (buf->phys_addr || !IS_ERR_OR_NULL(buf->ihdl))
+ if (buf->write_addr || !IS_ERR_OR_NULL(buf->ihdl))
return 0;
if (!buf->size) {
@@ -2592,6 +2593,12 @@
mfd->mem_hid);
if (!IS_ERR_OR_NULL(buf->ihdl)) {
if (mdp_iommu_split_domain) {
+ if (ion_map_iommu(mfd->iclient, buf->ihdl,
+ DISPLAY_READ_DOMAIN, GEN_POOL, SZ_4K,
+ 0, &read_addr, &len, 0, 0)) {
+ pr_err("ion_map_iommu() read failed\n");
+ return -ENOMEM;
+ }
if (mfd->mem_hid & ION_SECURE) {
if (ion_phys(mfd->iclient, buf->ihdl,
&addr, (size_t *)&len)) {
@@ -2612,7 +2619,7 @@
if (ion_map_iommu(mfd->iclient, buf->ihdl,
DISPLAY_READ_DOMAIN, GEN_POOL, SZ_4K,
0, &addr, &len, 0, 0)) {
- pr_err("ion_map_iommu() failed\n");
+ pr_err("ion_map_iommu() write failed\n");
return -ENOMEM;
}
}
@@ -2628,7 +2635,13 @@
if (addr) {
pr_info("allocating %d bytes at %x for mdp writeback\n",
buffer_size, (u32) addr);
- buf->phys_addr = addr;
+ buf->write_addr = addr;
+
+ if (read_addr)
+ buf->read_addr = read_addr;
+ else
+ buf->read_addr = buf->write_addr;
+
return 0;
} else {
pr_err("%s cannot allocate memory for mdp writeback!\n",
@@ -2652,6 +2665,8 @@
if (!(mfd->mem_hid & ION_SECURE))
ion_unmap_iommu(mfd->iclient, buf->ihdl,
DISPLAY_WRITE_DOMAIN, GEN_POOL);
+ ion_unmap_iommu(mfd->iclient, buf->ihdl,
+ DISPLAY_READ_DOMAIN, GEN_POOL);
} else {
ion_unmap_iommu(mfd->iclient, buf->ihdl,
DISPLAY_READ_DOMAIN, GEN_POOL);
@@ -2662,13 +2677,14 @@
buf->ihdl = NULL;
}
} else {
- if (buf->phys_addr) {
- free_contiguous_memory_by_paddr(buf->phys_addr);
+ if (buf->write_addr) {
+ free_contiguous_memory_by_paddr(buf->write_addr);
pr_debug("%s:%d free writeback pmem\n", __func__,
__LINE__);
}
}
- buf->phys_addr = 0;
+ buf->write_addr = 0;
+ buf->read_addr = 0;
}
static int mdp4_update_pcc_regs(uint32_t offset,
diff --git a/drivers/video/msm/mdp_dma.c b/drivers/video/msm/mdp_dma.c
index 2ba2c85..3a7513a 100644
--- a/drivers/video/msm/mdp_dma.c
+++ b/drivers/video/msm/mdp_dma.c
@@ -301,8 +301,11 @@
spin_lock_irqsave(&mdp_spin_lock, flag);
#ifdef DSI_CLK_CTRL
+
+ spin_lock_bh(&dsi_clk_lock);
if (mipi_dsi_clk_on == 0)
mipi_dsi_turn_on_clks();
+ spin_unlock_bh(&dsi_clk_lock);
#endif
if (mfd->dma->busy == TRUE) {
diff --git a/drivers/video/msm/mhl/mhl_8334.c b/drivers/video/msm/mhl/mhl_8334.c
index 43280a5..d6e3f6f 100644
--- a/drivers/video/msm/mhl/mhl_8334.c
+++ b/drivers/video/msm/mhl/mhl_8334.c
@@ -27,16 +27,16 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
+#include <linux/regulator/consumer.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include "msm_fb.h"
#include "external_common.h"
+#include "hdmi_msm.h"
#include "mhl_8334.h"
#include "mhl_i2c_utils.h"
-#define DEBUG
-
static struct i2c_device_id mhl_sii_i2c_id[] = {
{ MHL_DRIVER_NAME, 0 },
@@ -65,6 +65,163 @@
.id_table = mhl_sii_i2c_id,
};
+static void mhl_sii_reset_pin(int on)
+{
+ gpio_set_value(mhl_msm_state->mhl_data->gpio_mhl_reset, on);
+ return;
+}
+
+static int mhl_sii_reg_enable(void)
+{
+ static struct regulator *reg_8038_l20;
+ static struct regulator *reg_8038_l11;
+ int rc;
+
+ pr_debug("Inside %s\n", __func__);
+ if (!reg_8038_l20) {
+ reg_8038_l20 = regulator_get(&mhl_msm_state->i2c_client->dev,
+ "mhl_avcc12");
+ if (IS_ERR(reg_8038_l20)) {
+ pr_err("could not get reg_8038_l20, rc = %ld\n",
+ PTR_ERR(reg_8038_l20));
+ return -ENODEV;
+ }
+ rc = regulator_enable(reg_8038_l20);
+ if (rc) {
+ pr_err("'%s' regulator enable failed, rc=%d\n",
+ "mhl_l20", rc);
+ return rc;
+ } else
+ pr_debug("REGULATOR L20 ENABLED\n");
+ }
+
+ if (!reg_8038_l11) {
+ reg_8038_l11 = regulator_get(&mhl_msm_state->i2c_client->dev,
+ "mhl_iovcc18");
+ if (IS_ERR(reg_8038_l11)) {
+ pr_err("could not get reg_8038_l11, rc = %ld\n",
+ PTR_ERR(reg_8038_l11));
+ return -ENODEV;
+ }
+ rc = regulator_enable(reg_8038_l11);
+ if (rc) {
+ pr_err("'%s' regulator enable failed, rc=%d\n",
+ "mhl_l11", rc);
+ return rc;
+ } else
+ pr_debug("REGULATOR L11 ENABLED\n");
+ }
+
+ return rc;
+}
+
+
+static void mhl_sii_power_on(void)
+{
+ int ret;
+ pr_debug("MHL SII POWER ON\n");
+ if (!mhl_msm_state->mhl_data->gpio_mhl_power) {
+ pr_warn("%s: no power reqd for this platform\n", __func__);
+ return;
+ }
+
+ ret = gpio_request(mhl_msm_state->mhl_data->gpio_mhl_power, "W_PWR");
+ if (ret < 0) {
+ pr_err("MHL_POWER_GPIO req failed: %d\n",
+ ret);
+ return;
+ }
+ ret = gpio_direction_output(mhl_msm_state->mhl_data->gpio_mhl_power,
+ 1);
+ if (ret < 0) {
+ pr_err(
+ "SET GPIO MHL_POWER_GPIO direction failed: %d\n",
+ ret);
+ gpio_free(mhl_msm_state->mhl_data->gpio_mhl_power);
+ return;
+ }
+ gpio_set_value(mhl_msm_state->mhl_data->gpio_mhl_power, 1);
+
+ if (mhl_sii_reg_enable())
+ pr_err("Regulator enable failed\n");
+
+ pr_debug("MHL SII POWER ON Successful\n");
+ return;
+}
+
+/*
+ * Request for GPIO allocations
+ * Set appropriate GPIO directions
+ */
+static int mhl_sii_gpio_setup(int on)
+{
+ int ret;
+ if (on) {
+ if (mhl_msm_state->mhl_data->gpio_hdmi_mhl_mux) {
+ ret = gpio_request(mhl_msm_state->\
+ mhl_data->gpio_hdmi_mhl_mux, "W_MUX");
+ if (ret < 0) {
+ pr_err("GPIO HDMI_MHL MUX req failed:%d\n",
+ ret);
+ return -EBUSY;
+ }
+ ret = gpio_direction_output(
+ mhl_msm_state->mhl_data->gpio_hdmi_mhl_mux, 0);
+ if (ret < 0) {
+ pr_err("SET GPIO HDMI_MHL dir failed:%d\n",
+ ret);
+ gpio_free(mhl_msm_state->\
+ mhl_data->gpio_hdmi_mhl_mux);
+ return -EBUSY;
+ }
+ msleep(50);
+ gpio_set_value(mhl_msm_state->\
+ mhl_data->gpio_hdmi_mhl_mux, 0);
+ pr_debug("SET GPIO HDMI MHL MUX %d to 0\n",
+ mhl_msm_state->mhl_data->gpio_hdmi_mhl_mux);
+ }
+
+ ret = gpio_request(mhl_msm_state->mhl_data->gpio_mhl_reset,
+ "W_RST#");
+ if (ret < 0) {
+ pr_err("GPIO RESET request failed: %d\n", ret);
+ return -EBUSY;
+ }
+ ret = gpio_direction_output(mhl_msm_state->\
+ mhl_data->gpio_mhl_reset, 1);
+ if (ret < 0) {
+ pr_err("SET GPIO RESET direction failed: %d\n", ret);
+ gpio_free(mhl_msm_state->mhl_data->gpio_mhl_reset);
+ gpio_free(mhl_msm_state->mhl_data->gpio_hdmi_mhl_mux);
+ return -EBUSY;
+ }
+ ret = gpio_request(mhl_msm_state->mhl_data->gpio_mhl_int,
+ "W_INT");
+ if (ret < 0) {
+ pr_err("GPIO INT request failed: %d\n", ret);
+ gpio_free(mhl_msm_state->mhl_data->gpio_mhl_reset);
+ gpio_free(mhl_msm_state->mhl_data->gpio_hdmi_mhl_mux);
+ return -EBUSY;
+ }
+ ret = gpio_direction_input(mhl_msm_state->\
+ mhl_data->gpio_mhl_int);
+ if (ret < 0) {
+ pr_err("SET GPIO INTR direction failed: %d\n", ret);
+ gpio_free(mhl_msm_state->mhl_data->gpio_mhl_reset);
+ gpio_free(mhl_msm_state->mhl_data->gpio_mhl_int);
+ gpio_free(mhl_msm_state->mhl_data->gpio_hdmi_mhl_mux);
+ return -EBUSY;
+ }
+ } else {
+ gpio_free(mhl_msm_state->mhl_data->gpio_mhl_reset);
+ gpio_free(mhl_msm_state->mhl_data->gpio_mhl_int);
+ gpio_free(mhl_msm_state->mhl_data->gpio_hdmi_mhl_mux);
+ gpio_free(mhl_msm_state->mhl_data->gpio_mhl_power);
+ }
+
+ return 0;
+}
+
bool mhl_is_connected(void)
{
return true;
@@ -194,6 +351,11 @@
/* Power up 1.2V core */
mhl_i2c_reg_write(TX_PAGE_L1, 0x003D, 0x3F);
+ /*
+ * Wait for the source power to be enabled
+ * before enabling pll clocks.
+ */
+ msleep(50);
/* Enable Tx PLL Clock */
mhl_i2c_reg_write(TX_PAGE_2, 0x0011, 0x01);
/* Enable Tx Clock Path and Equalizer */
@@ -255,7 +417,7 @@
mhl_i2c_reg_write(TX_PAGE_3, 0x0017, 0x82);
mhl_i2c_reg_write(TX_PAGE_3, 0x0018, 0x24);
/* Pull-up resistance off for IDLE state */
- mhl_i2c_reg_write(TX_PAGE_3, 0x0013, 0x84);
+ mhl_i2c_reg_write(TX_PAGE_3, 0x0013, 0x8C);
/* Enable CBUS Discovery */
mhl_i2c_reg_write(TX_PAGE_3, 0x0010, 0x27);
mhl_i2c_reg_write(TX_PAGE_3, 0x0016, 0x20);
@@ -282,9 +444,11 @@
pr_debug("MHL: chip rev ID read=[%x]\n", mhl_msm_state->chip_rev_id);
/* Reset the TX chip */
- mhl_msm_state->mhl_data->reset_pin(0);
+ mhl_sii_reset_pin(1);
msleep(20);
- mhl_msm_state->mhl_data->reset_pin(1);
+ mhl_sii_reset_pin(0);
+ msleep(20);
+ mhl_sii_reset_pin(1);
/* MHL spec requires a 100 ms wait here. */
msleep(100);
@@ -305,34 +469,40 @@
static int mhl_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- int ret;
+ int ret = -ENODEV;
mhl_msm_state->mhl_data = kzalloc(sizeof(struct msm_mhl_platform_data),
GFP_KERNEL);
if (!(mhl_msm_state->mhl_data)) {
ret = -ENOMEM;
+ pr_err("MHL I2C Probe failed - no mem\n");
goto probe_exit;
}
- pr_debug("Inside probe\n");
mhl_msm_state->i2c_client = client;
spin_lock_init(&mhl_state_lock);
i2c_set_clientdata(client, mhl_msm_state);
mhl_msm_state->mhl_data = client->dev.platform_data;
+ pr_debug("MHL: mhl_msm_state->mhl_data->irq=[%d]\n",
+ mhl_msm_state->mhl_data->irq);
/* Init GPIO stuff here */
- ret = mhl_msm_state->mhl_data->gpio_setup(1);
+ ret = mhl_sii_gpio_setup(1);
if (ret == -1) {
pr_err("MHL: mhl_gpio_init has failed\n");
ret = -ENODEV;
goto probe_exit;
}
+
+ mhl_sii_power_on();
+
+ pr_debug("I2C PROBE successful\n");
return 0;
probe_exit:
if (mhl_msm_state->mhl_data) {
/* free the gpios */
- mhl_msm_state->mhl_data->gpio_setup(0);
+ mhl_sii_gpio_setup(0);
kfree(mhl_msm_state->mhl_data);
mhl_msm_state->mhl_data = NULL;
}
@@ -341,8 +511,8 @@
static int mhl_i2c_remove(struct i2c_client *client)
{
- pr_debug("inside i2c remove\n");
- mhl_msm_state->mhl_data->gpio_setup(0);
+ pr_debug("%s\n", __func__);
+ mhl_sii_gpio_setup(0);
kfree(mhl_msm_state->mhl_data);
return 0;
}
@@ -351,6 +521,7 @@
{
int32_t ret;
+ pr_debug("%s\n", __func__);
mhl_msm_state = kzalloc(sizeof(struct mhl_msm_state_t), GFP_KERNEL);
if (!mhl_msm_state) {
pr_err("mhl_msm_init FAILED: out of memory\n");
@@ -366,11 +537,11 @@
goto init_exit;
} else {
if (mhl_msm_state->i2c_client == NULL) {
- pr_err("JSR: I2C driver add failed\n");
+ pr_err("MHL: I2C driver add failed\n");
ret = -ENODEV;
goto init_exit;
}
- pr_debug("MHL: I2C driver added\n");
+ pr_info("MHL: I2C driver added\n");
}
/* Request IRQ stuff here */
@@ -385,7 +556,8 @@
ret);
ret = -EACCES; /* Error code???? */
goto init_exit;
- }
+ } else
+ pr_debug("request_threaded_irq succeeded\n");
mhl_msm_state->cur_state = POWER_STATE_D0_MHL;
@@ -482,7 +654,8 @@
uint8_t val;
unsigned long flags;
- pr_err("%s: cur state = [0x%x]\n", __func__, mhl_msm_state->cur_state);
+ pr_debug("%s: cur state = [0x%x]\n", __func__,
+ mhl_msm_state->cur_state);
if (mhl_msm_state->cur_state == POWER_STATE_D0_MHL) {
/* Already in D0 - MHL power state */
@@ -510,7 +683,6 @@
static void mhl_msm_disconnection(void)
{
uint8_t reg;
-
/* Clear interrupts - REG INTR4 */
reg = mhl_i2c_reg_read(TX_PAGE_3, 0x0021);
mhl_i2c_reg_write(TX_PAGE_3, 0x0021, reg);
@@ -594,7 +766,10 @@
* a previous interrupt brought us here,
* do nothing.
*/
- pr_debug("MHL: MRR Interrupt status is = %02X\n", (int) status);
+ if ((0x00 == status) && (mhl_msm_state->cur_state == POWER_STATE_D3)) {
+ mhl_chip_init();
+ return;
+ }
if (0xFF != status) {
if ((status & BIT0) && (mhl_msm_state->chip_rev_id < 1)) {
uint8_t tmds_cstat;
@@ -624,23 +799,25 @@
}
if (status & BIT1)
- pr_err("MHL: INT4 BIT1 is set\n");
+ pr_debug("MHL: INT4 BIT1 is set\n");
/* MHL_EST interrupt */
if (status & BIT2) {
- pr_err("MHL: Calling mhl_msm_connection() from ISR\n");
+ pr_debug("mhl_msm_connection() from ISR\n");
+ mhl_connect_api(true);
mhl_msm_connection();
- pr_err("MHL Connect Drv: INT4 Status = %02X\n",
+ pr_debug("MHL Connect Drv: INT4 Status = %02X\n",
(int) status);
} else if (status & BIT3) {
- pr_err("MHL: uUSB-A type device detected.\n");
+ pr_debug("MHL: uUSB-A type device detected.\n");
mhl_i2c_reg_write(TX_PAGE_3, 0x001C, 0x80);
switch_mode(POWER_STATE_D3);
}
if (status & BIT5) {
+ mhl_connect_api(false);
mhl_msm_disconnection();
- pr_err("MHL Disconnect Drv: INT4 Status = %02X\n",
+ pr_debug("MHL Disconn Drv: INT4 Status = %02X\n",
(int)status);
}
@@ -734,7 +911,7 @@
if (regval)
mhl_i2c_reg_write(TX_PAGE_CBUS, 0x08, regval);
- pr_err("%s: CBUS_INT = %02x\n", __func__, regval);
+ pr_debug("%s: CBUS_INT = %02x\n", __func__, regval);
/* MSC_MSG (RCP/RAP) */
if (regval & BIT(3)) {
@@ -755,7 +932,7 @@
if (regval)
mhl_i2c_reg_write(TX_PAGE_CBUS, 0x1E, regval);
- pr_err("%s: CBUS_MSC_INT2 = %02x\n", __func__, regval);
+ pr_debug("%s: CBUS_MSC_INT2 = %02x\n", __func__, regval);
/* received SET_INT */
if (regval & BIT(2)) {
@@ -774,9 +951,9 @@
if (regval & BIT(3)) {
uint8_t stat;
stat = mhl_i2c_reg_read(TX_PAGE_CBUS, 0xB0);
- pr_err("%s: MHL_STATUS_0 = %02x\n", __func__, stat);
+ pr_debug("%s: MHL_STATUS_0 = %02x\n", __func__, stat);
stat = mhl_i2c_reg_read(TX_PAGE_CBUS, 0xB1);
- pr_err("%s: MHL_STATUS_1 = %02x\n", __func__, stat);
+ pr_debug("%s: MHL_STATUS_1 = %02x\n", __func__, stat);
mhl_i2c_reg_write(TX_PAGE_CBUS, 0xB0, 0xFF);
mhl_i2c_reg_write(TX_PAGE_CBUS, 0xB1, 0xFF);
@@ -797,12 +974,6 @@
static irqreturn_t mhl_tx_isr(int irq, void *dev_id)
{
/*
- * Check discovery interrupt
- * if not yet connected
- */
- pr_debug("MHL: Current POWER state is [0x%x]\n",
- mhl_msm_state->cur_state);
- /*
* Check RGND, MHL_EST, CBUS_LOCKOUT, SCDT
* interrupts. In D3, we get only RGND
*/
diff --git a/drivers/video/msm/mhl/mhl_8334.h b/drivers/video/msm/mhl/mhl_8334.h
index c1d9030..eba544a 100644
--- a/drivers/video/msm/mhl/mhl_8334.h
+++ b/drivers/video/msm/mhl/mhl_8334.h
@@ -21,9 +21,6 @@
#include "mhl_devcap.h"
#include "mhl_defs.h"
-#define GPIO_MHL_RESET 15
-#define GPIO_MHL_INT 4
-
#define MHL_DEVICE_NAME "sii8334"
#define MHL_DRIVER_NAME "sii8334"
diff --git a/drivers/video/msm/mhl/mhl_i2c_utils.c b/drivers/video/msm/mhl/mhl_i2c_utils.c
index 596af2e..aab6e02 100644
--- a/drivers/video/msm/mhl/mhl_i2c_utils.c
+++ b/drivers/video/msm/mhl/mhl_i2c_utils.c
@@ -15,8 +15,6 @@
#include "mhl_i2c_utils.h"
#include "mhl_8334.h"
-#define DEBUG
-
uint8_t slave_addrs[MAX_PAGES] = {
DEV_PAGE_TPI_0 ,
DEV_PAGE_TX_L0_0 ,
@@ -60,7 +58,7 @@
pr_err("I2C READ FAILED=[%d]\n", ret);
return -EACCES;
}
- pr_err("Buffer is [%x]\n", buffer);
+ pr_debug("Buffer is [%x]\n", buffer);
return buffer;
}
diff --git a/drivers/video/msm/mipi_dsi.c b/drivers/video/msm/mipi_dsi.c
index 1ba1444..ff8fd17 100644
--- a/drivers/video/msm/mipi_dsi.c
+++ b/drivers/video/msm/mipi_dsi.c
@@ -86,6 +86,7 @@
*/
if (mfd->panel_info.type == MIPI_CMD_PANEL) {
if (mdp_rev >= MDP_REV_41) {
+ mdp4_dsi_cmd_del_timer();
mdp4_dsi_cmd_dma_busy_wait(mfd);
mdp4_dsi_blt_dmap_busy_wait(mfd);
mipi_dsi_mdp_busy_wait(mfd);
@@ -119,19 +120,16 @@
mdp_bus_scale_update_request(0);
#endif
- local_bh_disable();
+ spin_lock_bh(&dsi_clk_lock);
mipi_dsi_clk_disable();
- local_bh_enable();
/* disbale dsi engine */
MIPI_OUTP(MIPI_DSI_BASE + 0x0000, 0);
mipi_dsi_phy_ctrl(0);
-
- local_bh_disable();
mipi_dsi_ahb_ctrl(0);
- local_bh_enable();
+ spin_unlock_bh(&dsi_clk_lock);
mipi_dsi_unprepare_clocks();
if (mipi_dsi_pdata && mipi_dsi_pdata->dsi_power_save)
@@ -173,9 +171,7 @@
cont_splash_clk_ctrl(0);
mipi_dsi_prepare_clocks();
- local_bh_disable();
mipi_dsi_ahb_ctrl(1);
- local_bh_enable();
clk_rate = mfd->fbi->var.pixclock;
clk_rate = min(clk_rate, mfd->panel_info.clk_max);
@@ -187,9 +183,7 @@
mipi_dsi_phy_init(0, &(mfd->panel_info), target_type);
- local_bh_disable();
mipi_dsi_clk_enable();
- local_bh_enable();
MIPI_OUTP(MIPI_DSI_BASE + 0x114, 1);
MIPI_OUTP(MIPI_DSI_BASE + 0x114, 0);
diff --git a/drivers/video/msm/mipi_dsi_host.c b/drivers/video/msm/mipi_dsi_host.c
index dbf45b0..7f1a435 100644
--- a/drivers/video/msm/mipi_dsi_host.c
+++ b/drivers/video/msm/mipi_dsi_host.c
@@ -45,6 +45,7 @@
static int dsi_irq_enabled;
static spinlock_t dsi_irq_lock;
static spinlock_t dsi_mdp_lock;
+spinlock_t dsi_clk_lock;
static int dsi_mdp_busy;
static struct list_head pre_kickoff_list;
@@ -90,6 +91,7 @@
mipi_dsi_buf_alloc(&dsi_tx_buf, DSI_BUF_SIZE);
spin_lock_init(&dsi_irq_lock);
spin_lock_init(&dsi_mdp_lock);
+ spin_lock_init(&dsi_clk_lock);
INIT_LIST_HEAD(&pre_kickoff_list);
INIT_LIST_HEAD(&post_kickoff_list);
@@ -146,18 +148,14 @@
void mipi_dsi_turn_on_clks(void)
{
- local_bh_disable();
mipi_dsi_ahb_ctrl(1);
mipi_dsi_clk_enable();
- local_bh_enable();
}
void mipi_dsi_turn_off_clks(void)
{
- local_bh_disable();
mipi_dsi_clk_disable();
mipi_dsi_ahb_ctrl(0);
- local_bh_enable();
}
static void mipi_dsi_action(struct list_head *act_list)
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 18ee3e6..5f58af7 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -107,6 +107,9 @@
static int msm_fb_ioctl(struct fb_info *info, unsigned int cmd,
unsigned long arg);
static int msm_fb_mmap(struct fb_info *info, struct vm_area_struct * vma);
+static int mdp_bl_scale_config(struct msm_fb_data_type *mfd,
+ struct mdp_bl_scale_data *data);
+static void msm_fb_scale_bl(__u32 *bl_lvl);
#ifdef MSM_FB_ENABLE_DBGFS
@@ -116,6 +119,7 @@
int msm_fb_debugfs_file_index;
struct dentry *msm_fb_debugfs_root;
struct dentry *msm_fb_debugfs_file[MSM_FB_MAX_DBGFS];
+static int bl_scale, bl_min_lvl;
DEFINE_MUTEX(msm_fb_notify_update_sem);
void msmfb_no_update_notify_timer_cb(unsigned long data)
@@ -372,6 +376,8 @@
mfd->panel_info.frame_count = 0;
mfd->bl_level = 0;
+ bl_scale = 1024;
+ bl_min_lvl = 255;
#ifdef CONFIG_FB_MSM_OVERLAY
mfd->overlay_play_enable = 1;
#endif
@@ -746,11 +752,41 @@
static int unset_bl_level, bl_updated;
static int bl_level_old;
+static int mdp_bl_scale_config(struct msm_fb_data_type *mfd,
+ struct mdp_bl_scale_data *data)
+{
+ int ret = 0;
+ int curr_bl = mfd->bl_level;
+ bl_scale = data->scale;
+ bl_min_lvl = data->min_lvl;
+ pr_debug("%s: update scale = %d, min_lvl = %d\n", __func__, bl_scale,
+ bl_min_lvl);
+
+ /* update current backlight to use new scaling*/
+ msm_fb_set_backlight(mfd, curr_bl);
+
+ return ret;
+}
+
+static void msm_fb_scale_bl(__u32 *bl_lvl)
+{
+ __u32 temp = *bl_lvl;
+ if (temp >= bl_min_lvl) {
+ /* bl_scale is the numerator of scaling fraction (x/1024)*/
+ temp = ((*bl_lvl) * bl_scale) / 1024;
+
+ /*if less than minimum level, use min level*/
+ if (temp < bl_min_lvl)
+ temp = bl_min_lvl;
+ }
+
+ (*bl_lvl) = temp;
+}
void msm_fb_set_backlight(struct msm_fb_data_type *mfd, __u32 bkl_lvl)
{
struct msm_fb_panel_data *pdata;
-
+ __u32 temp = bkl_lvl;
if (!mfd->panel_power_on || !bl_updated) {
unset_bl_level = bkl_lvl;
return;
@@ -758,17 +794,19 @@
unset_bl_level = 0;
}
+ msm_fb_scale_bl(&temp);
pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
if ((pdata) && (pdata->set_backlight)) {
down(&mfd->sem);
- if (bl_level_old == bkl_lvl) {
+ if (bl_level_old == temp) {
up(&mfd->sem);
return;
}
- mfd->bl_level = bkl_lvl;
+ mfd->bl_level = temp;
pdata->set_backlight(mfd);
- bl_level_old = mfd->bl_level;
+ mfd->bl_level = bkl_lvl;
+ bl_level_old = temp;
up(&mfd->sem);
}
}
@@ -3133,7 +3171,8 @@
return 0;
}
-static int msmfb_handle_pp_ioctl(struct msmfb_mdp_pp *pp_ptr)
+static int msmfb_handle_pp_ioctl(struct msm_fb_data_type *mfd,
+ struct msmfb_mdp_pp *pp_ptr)
{
int ret = -1;
@@ -3178,6 +3217,11 @@
&pp_ptr->data.qseed_cfg_data);
break;
#endif
+ case mdp_bl_scale_cfg:
+ ret = mdp_bl_scale_config(mfd, (struct mdp_bl_scale_data *)
+ &pp_ptr->data.bl_scale_data);
+ break;
+
default:
pr_warn("Unsupported request to MDP_PP IOCTL.\n");
ret = -EINVAL;
@@ -3496,7 +3540,7 @@
if (ret)
return ret;
- ret = msmfb_handle_pp_ioctl(&mdp_pp);
+ ret = msmfb_handle_pp_ioctl(mfd, &mdp_pp);
break;
default:
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 28c0917..b2b79b1 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -259,6 +259,7 @@
header-y += msdos_fs.h
header-y += msg.h
header-y += msm_adc.h
+header-y += epm_adc.h
header-y += mtio.h
header-y += n_r3964.h
header-y += nbd.h
diff --git a/include/linux/cyttsp-qc.h b/include/linux/cyttsp-qc.h
index 0e5cac7..e1ab6fe 100644
--- a/include/linux/cyttsp-qc.h
+++ b/include/linux/cyttsp-qc.h
@@ -356,6 +356,7 @@
#define CY_DLY_BL 300
#define CY_DLY_DNLOAD 100 /* ms */
#define CY_NUM_RETRY 4 /* max num touch data read */
+#define CY_HALF_SEC_TMO_MS 500
/* handshake bit in the hst_mode reg */
#define CY_HNDSHK_BIT 0x80
diff --git a/include/linux/diagchar.h b/include/linux/diagchar.h
index 4ff1147..fbffdd2 100644
--- a/include/linux/diagchar.h
+++ b/include/linux/diagchar.h
@@ -107,7 +107,7 @@
/* This needs to be modified manually now, when we add
a new RANGE of SSIDs to the msg_mask_tbl */
-#define MSG_MASK_TBL_CNT 23
+#define MSG_MASK_TBL_CNT 24
#define EVENT_LAST_ID 0x08AD
#define MSG_SSID_0 0
@@ -156,6 +156,8 @@
#define MSG_SSID_21_LAST 10300
#define MSG_SSID_22 10350
#define MSG_SSID_22_LAST 10361
+#define MSG_SSID_23 0xC000
+#define MSG_SSID_23_LAST 0xC063
struct diagpkt_delay_params {
void *rsp_ptr;
diff --git a/include/linux/epm_adc.h b/include/linux/epm_adc.h
index 1af97fe..9cf2acf 100644
--- a/include/linux/epm_adc.h
+++ b/include/linux/epm_adc.h
@@ -1,16 +1,3 @@
-/*
- * Copyright (c) 2012, 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 __EPM_ADC_H
#define __EPM_ADC_H
@@ -26,6 +13,7 @@
int32_t physical;
};
+#ifdef __KERNEL__
struct epm_chan_properties {
uint32_t resistorValue;
uint32_t gain;
@@ -41,6 +29,7 @@
uint32_t bus_id;
uint32_t gpio_expander_base_addr;
};
+#endif
#define EPM_ADC_IOCTL_CODE 0x91
diff --git a/include/linux/mfd/wcd9xxx/core.h b/include/linux/mfd/wcd9xxx/core.h
index 2657ec3..17be2cb 100644
--- a/include/linux/mfd/wcd9xxx/core.h
+++ b/include/linux/mfd/wcd9xxx/core.h
@@ -155,6 +155,11 @@
int num_rx_port;
int num_tx_port;
+
+ u8 idbyte_0;
+ u8 idbyte_1;
+ u8 idbyte_2;
+ u8 idbyte_3;
};
int wcd9xxx_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg);
diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h
index e67190f..7afc896 100644
--- a/include/linux/msm_kgsl.h
+++ b/include/linux/msm_kgsl.h
@@ -49,8 +49,6 @@
KGSL_CTX_STAT_UNKNOWN_CONTEXT_RESET_EXT = 0x00000003
};
-#define KGSL_MAX_PWRLEVELS 5
-
#define KGSL_CONVERT_TO_MBPS(val) \
(val*1000*1000U)
@@ -135,12 +133,6 @@
unsigned int flags; /* contains KGSL_FLAGS_ values */
};
-struct kgsl_pwrlevel {
- unsigned int gpu_freq;
- unsigned int bus_freq;
- unsigned int io_fraction;
-};
-
struct kgsl_version {
unsigned int drv_major;
unsigned int drv_minor;
@@ -148,50 +140,6 @@
unsigned int dev_minor;
};
-#ifdef __KERNEL__
-
-#define KGSL_3D0_REG_MEMORY "kgsl_3d0_reg_memory"
-#define KGSL_3D0_IRQ "kgsl_3d0_irq"
-#define KGSL_2D0_REG_MEMORY "kgsl_2d0_reg_memory"
-#define KGSL_2D0_IRQ "kgsl_2d0_irq"
-#define KGSL_2D1_REG_MEMORY "kgsl_2d1_reg_memory"
-#define KGSL_2D1_IRQ "kgsl_2d1_irq"
-
-enum kgsl_iommu_context_id {
- KGSL_IOMMU_CONTEXT_USER = 0,
- KGSL_IOMMU_CONTEXT_PRIV = 1,
-};
-
-struct kgsl_iommu_ctx {
- const char *iommu_ctx_name;
- enum kgsl_iommu_context_id ctx_id;
-};
-
-struct kgsl_device_iommu_data {
- const struct kgsl_iommu_ctx *iommu_ctxs;
- int iommu_ctx_count;
- unsigned int physstart;
- unsigned int physend;
-};
-
-struct kgsl_device_platform_data {
- struct kgsl_pwrlevel pwrlevel[KGSL_MAX_PWRLEVELS];
- int init_level;
- int num_levels;
- int (*set_grp_async)(void);
- unsigned int idle_timeout;
- bool strtstp_sleepwake;
- unsigned int nap_allowed;
- unsigned int clk_map;
- unsigned int idle_needed;
- struct msm_bus_scale_pdata *bus_scale_table;
- struct kgsl_device_iommu_data *iommu_data;
- int iommu_count;
- struct msm_dcvs_core_info *core_info;
-};
-
-#endif
-
/* structure holds list of ibs */
struct kgsl_ibdesc {
unsigned int gpuaddr;
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 19728fe..d8edbc8 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -434,7 +434,6 @@
uint32_t *data;
};
-
struct mdp_lut_cfg_data {
uint32_t lut_type;
union {
@@ -452,12 +451,17 @@
uint32_t *data;
};
+struct mdp_bl_scale_data {
+ uint32_t min_lvl;
+ uint32_t scale;
+};
enum {
mdp_op_pcc_cfg,
mdp_op_csc_cfg,
mdp_op_lut_cfg,
mdp_op_qseed_cfg,
+ mdp_bl_scale_cfg,
mdp_op_max,
};
@@ -468,6 +472,7 @@
struct mdp_csc_cfg_data csc_cfg_data;
struct mdp_lut_cfg_data lut_cfg_data;
struct mdp_qseed_cfg_data qseed_cfg_data;
+ struct mdp_bl_scale_data bl_scale_data;
} data;
};
diff --git a/include/linux/msm_rotator.h b/include/linux/msm_rotator.h
index 463e5ce..17ae867 100644
--- a/include/linux/msm_rotator.h
+++ b/include/linux/msm_rotator.h
@@ -31,6 +31,7 @@
unsigned char rotations;
int enable;
unsigned int downscale_ratio;
+ unsigned int secure;
};
struct msm_rotator_data_info {
diff --git a/include/linux/usb/android.h b/include/linux/usb/android.h
index bf65ebb..7c2b33b 100644
--- a/include/linux/usb/android.h
+++ b/include/linux/usb/android.h
@@ -21,6 +21,7 @@
int (*update_pid_and_serial_num)(uint32_t, const char *);
u32 swfi_latency;
u8 usb_core_id;
+ bool cdrom;
};
#endif /* __LINUX_USB_ANDROID_H */
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 42f7349..f5e1ffa 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -2047,6 +2047,7 @@
#define V4L2_DEC_CMD_STOP (1)
#define V4L2_DEC_CMD_PAUSE (2)
#define V4L2_DEC_CMD_RESUME (3)
+#define V4L2_DEC_QCOM_CMD_FLUSH (4)
/* Flags for V4L2_DEC_CMD_START */
#define V4L2_DEC_CMD_START_MUTE_AUDIO (1 << 0)
@@ -2058,6 +2059,10 @@
#define V4L2_DEC_CMD_STOP_TO_BLACK (1 << 0)
#define V4L2_DEC_CMD_STOP_IMMEDIATELY (1 << 1)
+/* Flags for V4L2_DEC_QCOM_CMD_FLUSH */
+#define V4L2_DEC_QCOM_CMD_FLUSH_OUTPUT (1 << 0)
+#define V4L2_DEC_QCOM_CMD_FLUSH_CAPTURE (1 << 1)
+
/* Play format requirements (returned by the driver): */
/* The decoder has no special format requirements */
diff --git a/include/media/vcap_v4l2.h b/include/media/vcap_v4l2.h
index 045c107..e1d69d5 100644
--- a/include/media/vcap_v4l2.h
+++ b/include/media/vcap_v4l2.h
@@ -226,4 +226,8 @@
int get_phys_addr(struct vcap_dev *dev, struct vb2_queue *q,
struct v4l2_buffer *b);
+
+int vcvp_qbuf(struct vb2_queue *q, struct v4l2_buffer *b);
+int vcvp_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b);
+
#endif
diff --git a/include/sound/q6asm.h b/include/sound/q6asm.h
index d38dbd5..60268b4 100644
--- a/include/sound/q6asm.h
+++ b/include/sound/q6asm.h
@@ -151,6 +151,7 @@
atomic_t cmd_state;
atomic_t time_flag;
+ atomic_t nowait_cmd_cnt;
wait_queue_head_t cmd_wait;
wait_queue_head_t time_wait;
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 2b14423..eb5a0cc 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2084,6 +2084,9 @@
opcode = __le16_to_cpu(ev->opcode);
+ if (test_bit(HCI_RESET, &hdev->flags) && (opcode != HCI_OP_RESET))
+ return;
+
switch (opcode) {
case HCI_OP_INQUIRY_CANCEL:
hci_cc_inquiry_cancel(hdev, skb);
diff --git a/sound/soc/msm/apq8064.c b/sound/soc/msm/apq8064.c
index 2da5c6a..a4bc2ef 100644
--- a/sound/soc/msm/apq8064.c
+++ b/sound/soc/msm/apq8064.c
@@ -1339,6 +1339,17 @@
return 0;
}
+static int msm_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 msm_aux_pcm_get_gpios(void)
{
@@ -1764,6 +1775,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
+ .be_hw_params_fixup = msm_proxy_be_hw_params_fixup,
.ignore_pmdown_time = 1, /* this dainlink has playback support */
},
{
@@ -1775,6 +1787,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
+ .be_hw_params_fixup = msm_proxy_be_hw_params_fixup,
},
/* AUX PCM Backend DAI Links */
{
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index afc14f5..7e8e282 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -2446,20 +2446,26 @@
{"BE_OUT", NULL, "PRI_I2S_RX"},
{"BE_OUT", NULL, "SEC_I2S_RX"},
{"BE_OUT", NULL, "SLIMBUS_0_RX"},
+ {"BE_OUT", NULL, "SLIMBUS_1_RX"},
+ {"BE_OUT", NULL, "SLIMBUS_3_RX"},
+ {"BE_OUT", NULL, "SLIMBUS_4_RX"},
{"BE_OUT", NULL, "HDMI"},
{"BE_OUT", NULL, "MI2S_RX"},
{"PRI_I2S_TX", NULL, "BE_IN"},
{"MI2S_TX", NULL, "BE_IN"},
{"SLIMBUS_0_TX", NULL, "BE_IN" },
+ {"SLIMBUS_1_TX", NULL, "BE_IN" },
+ {"SLIMBUS_3_TX", NULL, "BE_IN" },
+ {"SLIMBUS_4_TX", NULL, "BE_IN" },
{"BE_OUT", NULL, "INT_BT_SCO_RX"},
{"INT_BT_SCO_TX", NULL, "BE_IN"},
{"BE_OUT", NULL, "INT_FM_RX"},
{"INT_FM_TX", NULL, "BE_IN"},
{"BE_OUT", NULL, "PCM_RX"},
{"PCM_TX", NULL, "BE_IN"},
- {"BE_OUT", NULL, "SLIMBUS_3_RX"},
{"BE_OUT", NULL, "STUB_RX"},
{"STUB_TX", NULL, "BE_IN"},
+ {"STUB_1_TX", NULL, "BE_IN"},
{"BE_OUT", NULL, "SEC_AUX_PCM_RX"},
{"SEC_AUX_PCM_TX", NULL, "BE_IN"},
{"BE_OUT", NULL, "AUX_PCM_RX"},
diff --git a/sound/soc/msm/msm8960.c b/sound/soc/msm/msm8960.c
index 5de3855..5f8a63e 100644
--- a/sound/soc/msm/msm8960.c
+++ b/sound/soc/msm/msm8960.c
@@ -1042,6 +1042,17 @@
return 0;
}
+static int msm8960_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 msm8960_aux_pcm_get_gpios(void)
{
int ret = 0;
@@ -1407,6 +1418,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
+ .be_hw_params_fixup = msm8960_proxy_be_hw_params_fixup,
.ignore_pmdown_time = 1, /* this dainlink has playback support */
},
{
@@ -1418,6 +1430,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
+ .be_hw_params_fixup = msm8960_proxy_be_hw_params_fixup,
},
/* AUX PCM Backend DAI Links */
{
@@ -1675,7 +1688,7 @@
{
int ret;
- if (!cpu_is_msm8960()) {
+ if (!cpu_is_msm8960() && !cpu_is_msm8960ab()) {
pr_debug("%s: Not the right machine type\n", __func__);
return -ENODEV ;
}
@@ -1740,7 +1753,7 @@
static void __exit msm8960_audio_exit(void)
{
- if (!cpu_is_msm8960()) {
+ if (!cpu_is_msm8960() && !cpu_is_msm8960ab()) {
pr_debug("%s: Not the right machine type\n", __func__);
return ;
}
diff --git a/sound/soc/msm/qdsp6/q6asm.c b/sound/soc/msm/qdsp6/q6asm.c
index 2993e37..02c6245 100644
--- a/sound/soc/msm/qdsp6/q6asm.c
+++ b/sound/soc/msm/qdsp6/q6asm.c
@@ -805,6 +805,7 @@
uint32_t token;
unsigned long dsp_flags;
uint32_t *payload;
+ uint32_t wakeup_flag = 1;
if ((ac == NULL) || (data == NULL)) {
@@ -816,7 +817,13 @@
ac->session);
return -EINVAL;
}
-
+ if (atomic_read(&ac->nowait_cmd_cnt) > 0) {
+ pr_debug("%s: nowait_cmd_cnt %d\n",
+ __func__,
+ atomic_read(&ac->nowait_cmd_cnt));
+ atomic_dec(&ac->nowait_cmd_cnt);
+ wakeup_flag = 0;
+ }
payload = data->payload;
if (data->opcode == RESET_EVENTS) {
@@ -862,7 +869,7 @@
case ASM_STREAM_CMD_SET_ENCDEC_PARAM:
case ASM_STREAM_CMD_OPEN_WRITE_COMPRESSED:
case ASM_STREAM_CMD_OPEN_READ_COMPRESSED:
- if (atomic_read(&ac->cmd_state)) {
+ if (atomic_read(&ac->cmd_state) && wakeup_flag) {
atomic_set(&ac->cmd_state, 0);
if (payload[1] == ADSP_EUNSUPPORTED)
atomic_set(&ac->cmd_response, 1);
@@ -1618,12 +1625,12 @@
run.flags = flags;
run.msw_ts = msw_ts;
run.lsw_ts = lsw_ts;
-
rc = apr_send_pkt(ac->apr, (uint32_t *) &run);
if (rc < 0) {
pr_err("%s:Commmand run failed[%d]", __func__, rc);
return -EINVAL;
}
+ atomic_inc(&ac->nowait_cmd_cnt);
return 0;
}
@@ -3406,7 +3413,7 @@
pr_err("APR handle NULL\n");
return -EINVAL;
}
- q6asm_add_hdr(ac, &hdr, sizeof(hdr), TRUE);
+ q6asm_add_hdr(ac, &hdr, sizeof(hdr), FALSE);
hdr.opcode = ASM_SESSION_CMD_GET_SESSION_TIME;
atomic_set(&ac->time_flag, 1);
@@ -3541,11 +3548,13 @@
pr_debug("%s:session[%d]opcode[0x%x] ", __func__,
ac->session,
hdr.opcode);
+
rc = apr_send_pkt(ac->apr, (uint32_t *) &hdr);
if (rc < 0) {
pr_err("%s:Commmand 0x%x failed\n", __func__, hdr.opcode);
goto fail_cmd;
}
+ atomic_inc(&ac->nowait_cmd_cnt);
return 0;
fail_cmd:
return -EINVAL;
diff --git a/sound/soc/msm/qdsp6/q6voice.c b/sound/soc/msm/qdsp6/q6voice.c
index f66a01c..1cf32aa 100644
--- a/sound/soc/msm/qdsp6/q6voice.c
+++ b/sound/soc/msm/qdsp6/q6voice.c
@@ -467,9 +467,9 @@
cvs_session_cmd.hdr.opcode =
VSS_ISTREAM_CMD_CREATE_PASSIVE_CONTROL_SESSION;
if (is_volte_session(v->session_id)) {
- strlcpy(mvm_session_cmd.mvm_session.name,
+ strlcpy(cvs_session_cmd.cvs_session.name,
"default volte voice",
- sizeof(mvm_session_cmd.mvm_session.name) - 1);
+ sizeof(cvs_session_cmd.cvs_session.name) - 1);
} else if (is_sglte_session(v->session_id)) {
strlcpy(cvs_session_cmd.cvs_session.name,
"default modem voice2",