Merge "msm: Kconfig: sync the 8226 and 8610 config options"
diff --git a/Documentation/devicetree/bindings/arm/msm/mpm_counter.txt b/Documentation/devicetree/bindings/arm/msm/mpm_counter.txt
index e62b9ec..9ac1cbd 100644
--- a/Documentation/devicetree/bindings/arm/msm/mpm_counter.txt
+++ b/Documentation/devicetree/bindings/arm/msm/mpm_counter.txt
@@ -1,4 +1,4 @@
-* MSM Timetick counter (mpm-v2)
+* MSM MPM sleep counter (mpm-v2)
The MPM provides a timetick that starts when the device is powered up and
is not reset by any of the boot loaders or the HLOS. The MPM timetick counter
@@ -6,12 +6,14 @@
The required nodes for the MPM timetick counter driver are:
-- compatible: "qcom,mpm-counter"
+- compatible: "qcom,mpm2-sleep-counter"
- reg: Specifies the physical address of the timetick count register.
+- clock-frequency: the physical counter frequency.
Example:
- qcom,mpm-counter@fc4a3000 {
- compatible = "qcom,mpm-counter";
+ qcom,mpm2-sleep-counter@fc4a3000 {
+ compatible = "qcom,mpm2-sleep-counter";
reg = <0xfc4a3000 0x1000>;
+ clock-frequency = <32768>;
};
diff --git a/Documentation/devicetree/bindings/arm/msm/pmu.txt b/Documentation/devicetree/bindings/arm/msm/pmu.txt
new file mode 100644
index 0000000..0bd5e58
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/pmu.txt
@@ -0,0 +1,40 @@
+* Qcom Performance Monitor Units
+Qcom cores have several PMUs for counting CPU side, L2 and bus side events.
+
+For the L1CC PMU:
+In most cases the L1 cache controller PMU is a per cpu unit. The irq-is-percpu
+flag becomes a requirement if this is the case.
+
+Required Properties:
+
+- compatible : Should be "qcom,krait-pmu"
+- interrupts : 1 combined interrupt or 1 per core. See the devicetree/bindings/gic.txt for more details on this format.
+
+Optional:
+
+- qcom,irq-is-percpu: Define this if the IRQ of the PMU is a PPI. This will tell perf to use
+ the per_cpu IRQ API for request and free.
+
+Example:
+
+ arm-pmu {
+ compatible = "qcom,krait-pmu";
+ qcom,irq-is-percpu;
+ interrupts = <1 7 0xf00>;
+ };
+
+For the L2CC PMU:
+If the L2 cache controller PMU is available, its DT bindings should be defined as
+follows.
+
+Required Properties:
+
+- compatible: Should be "qcom,l2-pmu"
+- interrupts : 1 combined interrupt.
+
+Example:
+
+ l2-pmu {
+ compatible = "qcom,l2-pmu";
+ interrupts = <0 1 0>;
+ };
diff --git a/Documentation/devicetree/bindings/platform/msm/qpnp-coincell.txt b/Documentation/devicetree/bindings/platform/msm/qpnp-coincell.txt
new file mode 100644
index 0000000..10c1bbf
--- /dev/null
+++ b/Documentation/devicetree/bindings/platform/msm/qpnp-coincell.txt
@@ -0,0 +1,44 @@
+Qualcomm QPNP Coincell - coincell battery charger devices
+
+Required properties:
+- compatible: Must be "qcom,qpnp-coincell".
+- reg: Specifies the SPMI address and size for this coincell device.
+
+Required structure:
+- A qcom,qpnp-coincell node must be a child of an SPMI node that has specified
+ the spmi-slave-container property.
+
+Optional properties:
+- qcom,rset-ohms: Specifies the resistance of the current limiting
+ resistor in ohms. Four values are supported:
+ 800, 1200, 1700, and 2100.
+- qcom,vset-millivolts: Specifies the coincell charging voltage in millivolts.
+ Four values are supported: 2500, 3000, 3100, and 3200.
+- qcom,charge-enable: Specifies if coincell charging should be enabled or not.
+ 0 = disable charging, 1 = enabled charging
+
+If any of the optional properties are not specified, then the hardware default
+values for the unspecified properties will be used instead.
+
+Example:
+ qcom,spmi@fc4c0000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+
+ qcom,pm8941@1 {
+ spmi-slave-container;
+ reg = <0x1>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ qcom,coincell@2800 {
+ compatible = "qcom,qpnp-coincell";
+ reg = <0x2800 0x100>;
+ qcom,rset-ohms = <800>;
+ qcom,vset-millivolts = <3100>;
+ qcom,charge-enable = <1>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/power/qpnp-charger.txt b/Documentation/devicetree/bindings/power/qpnp-charger.txt
index 4590227..9b58464 100644
--- a/Documentation/devicetree/bindings/power/qpnp-charger.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-charger.txt
@@ -26,7 +26,6 @@
- qcom,chg-vddmax-mv: Target voltage of battery in mV.
- qcom,chg-vddsafe-mv: Maximum Vdd voltage in mV.
- qcom,chg-vinmin-mv: Minimum input voltage in mV.
-- qcom,chg-vbatdet-mv: Battery charging resume voltage in mV.
- qcom,chg-ibatmax-ma: Maximum battery charge current in mA
- qcom,chg-ibatterm-ma: Current at which charging is terminated.
- qcom,chg-ibatsafe-ma: Safety battery current setting
@@ -36,6 +35,7 @@
Parent node optional properties:
- qcom,chg-maxinput-usb-ma: Maximum input current USB.
- qcom,chg-maxinput-dc-ma: Maximum input current DC.
+- qcom,chg-vbatdet-delta-mv: Battery charging resume delta.
- qcom,chg-charging-disabled: Set this property to disable charging
by default. This can then be overriden
writing the the module parameter
@@ -44,6 +44,16 @@
battery temperature of 250 decidegree
Celsius, state of charge to be 50%
and disable charging.
+- qcom,chg-warm-bat-degc: Warm battery temperature in degC.
+- qcom,chg-cool-bat-degc: Cool battery temperature in degC.
+ Note that if both warm and cool battery
+ temperatures are set, the corresponding
+ ibatmax and bat-mv properties are
+ required to be set.
+- qcom,chg-ibatmax-cool-ma: Maximum cool battery charge current.
+- qcom,chg-ibatmax-warm-ma: Maximum warm battery charge current.
+- qcom,chg-warm-bat-mv: Warm temperature battery target voltage.
+- qcom,chg-cool-bat-mv: Cool temperature battery target voltage.
Sub node required structure:
- A qcom,chg node must be a child of an SPMI node that has specified
@@ -132,11 +142,17 @@
qcom,chg-vddmax-mv = <4200>;
qcom,chg-vddsafe-mv = <4200>;
qcom,chg-vinmin-mv = <4200>;
- qcom,chg-vbatdet-mv = <4200>;
qcom,chg-ibatmax-ma = <1500>;
qcom,chg-ibatterm-ma = <200>;
qcom,chg-ibatsafe-ma = <1500>;
qcom,chg-thermal-mitigation = <1500 700 600 325>;
+ qcom,chg-cool-bat-degc = <10>;
+ qcom,chg-cool-bat-mv = <4100>;
+ qcom,chg-ibatmax-warm-ma = <350>;
+ qcom,chg-warm-bat-degc = <45>;
+ qcom,chg-warm-bat-mv = <4100>;
+ qcom,chg-ibatmax-cool-ma = <350>;
+ qcom,chg-vbatdet-delta-mv = <60>;
qcom,chg-chgr@1000 {
reg = <0x1000 0x100>;
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index 6cf59ee..df88caa 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -114,6 +114,7 @@
- qcom,usb2-enable-hsphy2: If present, select second PHY for USB operation.
- qcom,pool-64-bit-align: If present then the pool's memory will be aligned
to 64 bits
+- qcom,enable_hbm: if present host bus manager is enabled.
Example MSM HSUSB EHCI controller device node :
ehci: qcom,ehci-host@f9a55000 {
diff --git a/arch/arm/boot/dts/msm-pm8226-rpm-regulator.dtsi b/arch/arm/boot/dts/msm-pm8226-rpm-regulator.dtsi
new file mode 100644
index 0000000..ded9494
--- /dev/null
+++ b/arch/arm/boot/dts/msm-pm8226-rpm-regulator.dtsi
@@ -0,0 +1,492 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+&rpm_bus {
+ rpm-regulator-smpa1 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "smpa";
+ qcom,resource-id = <1>;
+ qcom,regulator-type = <1>;
+ qcom,hpm-min-load = <100000>;
+ status = "disabled";
+
+ regulator-s1 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8226_s1";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-smpa3 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "smpa";
+ qcom,resource-id = <3>;
+ qcom,regulator-type = <1>;
+ qcom,hpm-min-load = <100000>;
+ status = "disabled";
+
+ regulator-s3 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8226_s3";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-smpa4 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "smpa";
+ qcom,resource-id = <4>;
+ qcom,regulator-type = <1>;
+ qcom,hpm-min-load = <100000>;
+ status = "disabled";
+
+ regulator-s4 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8226_s4";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-smpa5 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "smpa";
+ qcom,resource-id = <5>;
+ qcom,regulator-type = <1>;
+ qcom,hpm-min-load = <100000>;
+ status = "disabled";
+
+ regulator-s5 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8226_s5";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa1 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <1>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l1 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8226_l1";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa2 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <2>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l2 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8226_l2";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa3 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <3>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l3 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8226_l3";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa4 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <4>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l4 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8226_l4";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa5 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <5>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l5 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8226_l5";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa6 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <6>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l6 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8226_l6";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa7 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <7>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l7 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8226_l7";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa8 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <8>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <5000>;
+ status = "disabled";
+
+ regulator-l8 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8226_l8";
+ qcom,set = <1>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa9 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <9>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l9 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8226_l9";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa10 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <10>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <5000>;
+ status = "disabled";
+
+ regulator-l10 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8226_l10";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa12 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <12>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l12 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8226_l12";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa14 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <14>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <5000>;
+ status = "disabled";
+
+ regulator-l14 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8226_l14";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa15 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <15>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l15 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8226_l15";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa16 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <16>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l16 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8226_l16";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa17 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <17>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l17 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8226_l17";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa18 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <18>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l18 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8226_l18";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa19 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <19>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l19 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8226_l19";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa20 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <20>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <5000>;
+ status = "disabled";
+
+ regulator-l20 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8226_l20";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa21 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <21>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <5000>;
+ status = "disabled";
+
+ regulator-l21 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8226_l21";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa22 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <22>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l22 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8226_l22";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa23 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <23>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l23 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8226_l23";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa24 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <24>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l24 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8226_l24";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa26 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <26>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l26 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8226_l26";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa27 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <27>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l27 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8226_l27";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa28 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <28>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l28 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8226_l28";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-vsa1 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "vsa";
+ qcom,resource-id = <1>;
+ qcom,regulator-type = <2>;
+ status = "disabled";
+
+ regulator-lvs1 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8226_lvs1";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 28ca985..79acd7f 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -85,6 +85,11 @@
qcom,sample-rate = <4>;
};
+ pm8941_coincell: qcom,coincell@2800 {
+ compatible = "qcom,qpnp-coincell";
+ reg = <0x2800 0x100>;
+ };
+
pm8941_bms: qcom,bms {
spmi-dev-container;
compatible = "qcom,qpnp-bms";
@@ -161,11 +166,17 @@
qcom,chg-vddmax-mv = <4200>;
qcom,chg-vddsafe-mv = <4200>;
qcom,chg-vinmin-mv = <4200>;
- qcom,chg-vbatdet-mv = <4100>;
qcom,chg-ibatmax-ma = <1500>;
qcom,chg-ibatterm-ma = <200>;
qcom,chg-ibatsafe-ma = <1500>;
qcom,chg-thermal-mitigation = <1500 700 600 325>;
+ qcom,chg-cool-bat-degc = <10>;
+ qcom,chg-cool-bat-mv = <4100>;
+ qcom,chg-ibatmax-warm-ma = <350>;
+ qcom,chg-warm-bat-degc = <45>;
+ qcom,chg-warm-bat-mv = <4100>;
+ qcom,chg-ibatmax-cool-ma = <350>;
+ qcom,chg-vbatdet-delta-mv = <350>;
qcom,chg-chgr@1000 {
status = "disabled";
diff --git a/arch/arm/boot/dts/msm8226-iommu.dtsi b/arch/arm/boot/dts/msm8226-iommu.dtsi
index bddafc9..460068b 100644
--- a/arch/arm/boot/dts/msm8226-iommu.dtsi
+++ b/arch/arm/boot/dts/msm8226-iommu.dtsi
@@ -14,6 +14,7 @@
&jpeg_iommu {
status = "ok";
+ qcom,iommu-enable-halt;
qcom,iommu-bfb-regs = <0x204c
0x2050
@@ -50,6 +51,7 @@
&mdp_iommu {
status = "ok";
+ qcom,iommu-enable-halt;
qcom,iommu-bfb-regs = <0x204c
0x2050
@@ -92,6 +94,7 @@
&venus_iommu {
status = "ok";
+ qcom,iommu-enable-halt;
qcom,iommu-bfb-regs = <0x204c
0x2050
@@ -154,6 +157,7 @@
&kgsl_iommu {
status = "ok";
+ qcom,iommu-enable-halt;
qcom,iommu-bfb-regs = <0x204c
0x2050
@@ -184,6 +188,7 @@
&vfe_iommu {
status = "ok";
+ qcom,iommu-enable-halt;
qcom,iommu-bfb-regs = <0x204c
0x2050
diff --git a/arch/arm/boot/dts/msm8226-regulator.dtsi b/arch/arm/boot/dts/msm8226-regulator.dtsi
index 8168826..c39d987 100644
--- a/arch/arm/boot/dts/msm8226-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8226-regulator.dtsi
@@ -10,300 +10,374 @@
* GNU General Public License for more details.
*/
-/* Stub Regulators */
-
-/ {
- pm8226_s1_corner: regulator-s1-corner {
- compatible = "qcom,stub-regulator";
- regulator-name = "8226_s1_corner";
- qcom,hpm-min-load = <100000>;
- regulator-min-microvolt = <1>;
- regulator-max-microvolt = <7>;
- qcom,consumer-supplies = "vdd_dig", "";
- };
-};
-
/* QPNP controlled regulators: */
&spmi_bus {
-
qcom,pm8226@1 {
-
- pm8226_s1: regulator@1400 {
- status = "okay";
- regulator-name = "8226_s1";
- qcom,enable-time = <500>;
- qcom,system-load = <100000>;
- regulator-always-on;
- regulator-min-microvolt = <1150000>;
- regulator-max-microvolt = <1150000>;
- };
-
pm8226_s2: regulator@1700 {
status = "okay";
regulator-name = "8226_s2";
qcom,enable-time = <500>;
qcom,system-load = <100000>;
- regulator-always-on;
regulator-min-microvolt = <1050000>;
regulator-max-microvolt = <1150000>;
- };
-
- pm8226_s3: regulator@1a00 {
- status = "okay";
- regulator-name = "8226_s3";
- qcom,enable-time = <500>;
- qcom,system-load = <100000>;
regulator-always-on;
- regulator-min-microvolt = <1300000>;
+ };
+ };
+};
+
+/* RPM controlled regulators: */
+
+&rpm_bus {
+ rpm-regulator-smpa1 {
+ status = "okay";
+ pm8226_s1: regulator-s1 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1275000>;
+ status = "okay";
+ };
+ pm8226_s1_corner: regulator-s1-corner {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8226_s1_corner";
+ qcom,set = <3>;
+ regulator-min-microvolt = <1>;
+ regulator-max-microvolt = <7>;
+ qcom,use-voltage-corner;
+ qcom,consumer-supplies = "vdd_dig", "";
+ };
+ pm8226_s1_corner_ao: regulator-s1-corner-ao {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8226_s1_corner_ao";
+ qcom,set = <1>;
+ regulator-min-microvolt = <1>;
+ regulator-max-microvolt = <7>;
+ qcom,use-voltage-corner;
+ };
+ };
+
+ rpm-regulator-smpa3 {
+ status = "okay";
+ pm8226_s3: regulator-s3 {
+ regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1300000>;
- };
-
- pm8226_s4: regulator@1d00 {
+ qcom,init-voltage = <1200000>;
status = "okay";
- regulator-name = "8226_s4";
- qcom,enable-time = <500>;
- qcom,system-load = <100000>;
- regulator-always-on;
+ };
+ };
+
+ rpm-regulator-smpa4 {
+ status = "okay";
+ pm8226_s4: regulator-s4 {
regulator-min-microvolt = <2100000>;
regulator-max-microvolt = <2100000>;
- };
-
- pm8226_s5: regulator@2000 {
+ qcom,init-voltage = <2100000>;
status = "okay";
- regulator-name = "8226_s5";
- qcom,enable-time = <500>;
+ };
+ };
+
+ rpm-regulator-smpa5 {
+ status = "okay";
+ pm8226_s5: regulator-s5 {
regulator-min-microvolt = <1150000>;
regulator-max-microvolt = <1150000>;
- };
-
- pm8226_l1: regulator@4000 {
+ qcom,init-voltage = <1150000>;
status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa1 {
+ status = "okay";
+ pm8226_l1: regulator-l1 {
regulator-name = "8226_l1";
- parent-supply = <&pm8226_s3>;
- qcom,enable-time = <200>;
regulator-min-microvolt = <1225000>;
regulator-max-microvolt = <1225000>;
- };
-
- pm8226_l2: regulator@4100 {
+ qcom,init-voltage = <1225000>;
status = "okay";
- regulator-name = "8226_l2";
- parent-supply = <&pm8226_s3>;
- regulator-always-on;
- qcom,enable-time = <200>;
- qcom,system-load = <10000>;
+ };
+ };
+
+ rpm-regulator-ldoa2 {
+ status = "okay";
+ pm8226_l2: regulator-l2 {
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
- };
-
- pm8226_l3: regulator@4200 {
+ qcom,init-voltage = <1200000>;
status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa3 {
+ status = "okay";
+ pm8226_l3: regulator-l3 {
regulator-name = "8226_l3";
- parent-supply = <&pm8226_s3>;
- qcom,system-load = <10000>;
- regulator-always-on;
- qcom,enable-time = <200>;
- regulator-min-microvolt = <1150000>;
- regulator-max-microvolt = <1150000>;
- };
-
- pm8226_l4: regulator@4300 {
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <1275000>;
status = "okay";
+ };
+ pm8226_l3_ao: regulator-3-ao {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8226_l3_ao";
+ qcom,set = <1>;
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <1275000>;
+ status = "okay";
+ };
+ pm8226_l3_so: regulator-l3-so {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8226_l3_so";
+ qcom,set = <2>;
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <1275000>;
+ qcom,init-voltage = <750000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa4 {
+ status = "okay";
+ pm8226_l4: regulator-l4 {
regulator-name = "8226_l4";
- parent-supply = <&pm8226_s3>;
- qcom,enable-time = <200>;
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
- };
-
- pm8226_l5: regulator@4400 {
+ qcom,init-voltage = <1200000>;
status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa5 {
+ status = "okay";
+ pm8226_l5: regulator-l5 {
regulator-name = "8226_l5";
- parent-supply = <&pm8226_s3>;
- qcom,enable-time = <200>;
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
- };
-
- pm8226_l6: regulator@4500 {
+ qcom,init-voltage = <1200000>;
status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa6 {
+ status = "okay";
+ pm8226_l6: regulator-l6 {
regulator-name = "8226_l6";
- parent-supply = <&pm8226_s4>;
- qcom,system-load = <10000>;
- regulator-always-on;
- qcom,enable-time = <200>;
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
- };
-
- pm8226_l7: regulator@4600 {
+ qcom,init-voltage = <1800000>;
status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa7 {
+ status = "okay";
+ pm8226_l7: regulator-l7 {
regulator-name = "8226_l7";
- parent-supply = <&pm8226_s4>;
- qcom,enable-time = <200>;
regulator-min-microvolt = <1850000>;
regulator-max-microvolt = <1850000>;
- };
-
- pm8226_l8: regulator@4700 {
+ qcom,init-voltage = <1850000>;
status = "okay";
- regulator-name = "8226_l8";
- parent-supply = <&pm8226_s4>;
- qcom,enable-time = <200>;
+ };
+ };
+
+ rpm-regulator-ldoa8 {
+ status = "okay";
+ pm8226_l8: regulator-l8 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ status = "okay";
qcom,consumer-supplies = "vdd_sr2_pll", "";
};
+ };
- pm8226_l9: regulator@4800 {
- status = "okay";
+ rpm-regulator-ldoa9 {
+ status = "okay";
+ pm8226_l9: regulator-l9 {
regulator-name = "8226_l9";
- parent-supply = <&pm8226_s4>;
- qcom,enable-time = <200>;
regulator-min-microvolt = <2050000>;
regulator-max-microvolt = <2050000>;
- };
-
- pm8226_l10: regulator@4900 {
+ qcom,init-voltage = <2050000>;
status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa10 {
+ status = "okay";
+ pm8226_l10: regulator-l10 {
regulator-name = "8226_l10";
- parent-supply = <&pm8226_s4>;
- qcom,enable-time = <200>;
- qcom,system-load = <5000>;
- regulator-always-on;
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
- };
-
- pm8226_l12: regulator@4b00 {
+ qcom,init-voltage = <1800000>;
status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa12 {
+ status = "okay";
+ pm8226_l12: regulator-l12 {
regulator-name = "8226_l12";
- qcom,enable-time = <200>;
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
- };
-
- pm8226_l14: regulator@4d00 {
+ qcom,init-voltage = <1800000>;
status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa14 {
+ status = "okay";
+ pm8226_l14: regulator-l14 {
regulator-name = "8226_l14";
- qcom,enable-time = <200>;
regulator-min-microvolt = <2750000>;
regulator-max-microvolt = <2750000>;
- };
-
- pm8226_l15: regulator@4e00 {
+ qcom,init-voltage = <2750000>;
status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa15 {
+ status = "okay";
+ pm8226_l15: regulator-l15 {
regulator-name = "8226_l15";
- qcom,enable-time = <200>;
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>;
- };
-
- pm8226_l16: regulator@4f00 {
+ qcom,init-voltage = <2800000>;
status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa16 {
+ status = "okay";
+ pm8226_l16: regulator-l16 {
regulator-name = "8226_l16";
- qcom,enable-time = <200>;
regulator-min-microvolt = <3000000>;
regulator-max-microvolt = <3300000>;
- };
-
- pm8226_l17: regulator@5000 {
+ qcom,init-voltage = <3300000>;
status = "okay";
- regulator-name = "8226_l17";
- qcom,enable-time = <200>;
+ };
+ };
+
+ rpm-regulator-ldoa17 {
+ status = "okay";
+ pm8226_l17: regulator-l17 {
regulator-min-microvolt = <2950000>;
regulator-max-microvolt = <2950000>;
- };
-
- pm8226_l18: regulator@5100 {
+ qcom,init-voltage = <2950000>;
status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa18 {
+ status = "okay";
+ pm8226_l18: regulator-l18 {
regulator-name = "8226_l18";
- qcom,enable-time = <200>;
regulator-min-microvolt = <2950000>;
regulator-max-microvolt = <2950000>;
- };
-
- pm8226_l19: regulator@5200 {
+ qcom,init-voltage = <2950000>;
status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa19 {
+ status = "okay";
+ pm8226_l19: regulator-l19 {
regulator-name = "8226_l19";
- qcom,enable-time = <200>;
regulator-min-microvolt = <2850000>;
regulator-max-microvolt = <2850000>;
- };
-
- pm8226_l20: regulator@5300 {
+ qcom,init-voltage = <2850000>;
status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa20 {
+ status = "okay";
+ pm8226_l20: regulator-l20 {
regulator-name = "8226_l20";
- qcom,enable-time = <200>;
regulator-min-microvolt = <3075000>;
regulator-max-microvolt = <3075000>;
- };
-
- pm8226_l21: regulator@5400 {
+ qcom,init-voltage = <3075000>;
status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa21 {
+ status = "okay";
+ pm8226_l21: regulator-l21 {
regulator-name = "8226_l21";
- qcom,enable-time = <200>;
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <2950000>;
- };
-
- pm8226_l22: regulator@5500 {
+ qcom,init-voltage = <2950000>;
status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa22 {
+ status = "okay";
+ pm8226_l22: regulator-l22 {
regulator-name = "8226_l22";
- qcom,enable-time = <200>;
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <2950000>;
- };
-
- pm8226_l23: regulator@5600 {
+ qcom,init-voltage = <2950000>;
status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa23 {
+ status = "okay";
+ pm8226_l23: regulator-l23 {
regulator-name = "8226_l23";
- qcom,enable-time = <200>;
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <2950000>;
- };
-
- pm8226_l24: regulator@5700 {
+ qcom,init-voltage = <2950000>;
status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa24 {
+ status = "okay";
+ pm8226_l24: regulator-l24 {
regulator-name = "8226_l24";
- parent-supply = <&pm8226_s3>;
- qcom,enable-time = <200>;
regulator-min-microvolt = <1300000>;
regulator-max-microvolt = <1300000>;
- };
-
- pm8226_l26: regulator@5900 {
+ qcom,init-voltage = <1300000>;
status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa26 {
+ status = "okay";
+ pm8226_l26: regulator-l26 {
regulator-name = "8226_l26";
- parent-supply = <&pm8226_s3>;
- qcom,enable-time = <200>;
regulator-min-microvolt = <1225000>;
regulator-max-microvolt = <1225000>;
- };
-
- pm8226_l27: regulator@5a00 {
+ qcom,init-voltage = <1225000>;
status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa27 {
+ status = "okay";
+ pm8226_l27: regulator-l27 {
regulator-name = "8226_l27";
- parent-supply = <&pm8226_s4>;
- qcom,enable-time = <200>;
regulator-min-microvolt = <2050000>;
regulator-max-microvolt = <2050000>;
- };
-
- pm8226_l28: regulator@5b00 {
+ qcom,init-voltage = <2050000>;
status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa28 {
+ status = "okay";
+ pm8226_l28: regulator-l28 {
regulator-name = "8226_l28";
- qcom,enable-time = <200>;
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <2950000>;
- };
-
- pm8226_lvs1: regulator@8000 {
+ qcom,init-voltage = <2950000>;
status = "okay";
- regulator-name = "8226_lvs1";
- parent-supply = <&pm8226_l6>;
- qcom,enable-time = <200>;
+ };
+ };
+
+ rpm-regulator-vsa1 {
+ status = "okay";
+ pm8226_lvs1: regulator-lvs1 {
+ status = "okay";
};
};
};
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 2ceaaaa..f0cddfb 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -504,7 +504,7 @@
reg = <0xfdd00000 0x2000>,
<0xfdd02000 0x2000>,
<0xfe039000 0x400>,
- <0xfec00000 0x180000>;
+ <0xfec00000 0x20000>;
reg-names = "ocmem_ctrl_physical", "dm_ctrl_physical", "br_ctrl_physical", "ocmem_physical";
interrupts = <0 76 0 0 77 0>;
interrupt-names = "ocmem_irq", "dm_irq";
@@ -513,12 +513,12 @@
qcom,resource-type = <0x706d636f>;
#address-cells = <1>;
#size-cells = <1>;
- ranges = <0x0 0xfec00000 0x180000>;
+ ranges = <0x0 0xfec00000 0x20000>;
partition@0 {
- reg = <0x0 0x100000>;
+ reg = <0x0 0x20000>;
qcom,ocmem-part-name = "graphics";
- qcom,ocmem-part-min = <0x80000>;
+ qcom,ocmem-part-min = <0x20000>;
};
};
@@ -637,6 +637,11 @@
qcom,memory-reservation-type = "EBI1";
qcom,memory-reservation-size = <0x100000>; /* 1M EBI1 buffer */
};
+ qcom,msm-rng@f9bff000 {
+ compatible = "qcom,msm-rng";
+ reg = <0xf9bff000 0x200>;
+ qcom,msm-rng-iface-clk;
+ };
};
&gdsc_venus {
@@ -663,6 +668,7 @@
status = "ok";
};
+/include/ "msm-pm8226-rpm-regulator.dtsi"
/include/ "msm-pm8226.dtsi"
/include/ "msm8226-regulator.dtsi"
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index 2dff4c7..fe0ebf9 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -437,6 +437,19 @@
vdd_cx-supply = <&pm8110_s1_corner>;
qcom,firmware-name = "adsp";
};
+
+ tsens: tsens@fc4a8000 {
+ compatible = "qcom,msm-tsens";
+ reg = <0xfc4a8000 0x2000>,
+ <0xfc4b8000 0x1000>;
+ reg-names = "tsens_physical", "tsens_eeprom_physical";
+ interrupts = <0 184 0>;
+ qcom,sensors = <2>;
+ qcom,slope = <2901 2846>;
+ qcom,calib-mode = "fuse_map2";
+ qcom,calibration-less-mode;
+ };
+
};
&gdsc_vfe {
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 99886c7..3ebdbb6 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -84,9 +84,10 @@
clock-frequency = <19200000>;
};
- qcom,mpm-counter@fc4a3000 {
- compatible = "qcom,mpm-counter";
+ qcom,mpm2-sleep-counter@fc4a3000 {
+ compatible = "qcom,mpm2-sleep-counter";
reg = <0xfc4a3000 0x1000>;
+ clock-frequency = <32768>;
};
msm_vidc: qcom,vidc@fdc00000 {
@@ -1382,6 +1383,17 @@
reg = <0xfa00000 0x200000>;
status = "disable";
};
+
+ cpu-pmu {
+ compatible = "qcom,krait-pmu";
+ qcom,irq-is-percpu;
+ interrupts = <1 7 0xf00>;
+ };
+
+ l2-pmu {
+ compatible = "qcom,l2-pmu";
+ interrupts = <0 1 0>;
+ };
};
&gdsc_venus {
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index e1501ac..78786f6 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -52,6 +52,12 @@
qcom,direct-connect-irqs = <8>;
};
+ qcom,mpm2-sleep-counter@fc4a3000 {
+ compatible = "qcom,mpm2-sleep-counter";
+ reg = <0xfc4a3000 0x1000>;
+ clock-frequency = <32768>;
+ };
+
timer: msm-qtimer@f9021000 {
compatible = "arm,armv7-timer";
reg = <0xF9021000 0x1000>;
@@ -731,6 +737,17 @@
status = "disable";
};
+ cpu-pmu {
+ compatible = "arm,cortex-a5-pmu";
+ qcom,irq-is-percpu;
+ interrupts = <1 7 0x00>;
+ };
+
+ l2-pmu {
+ compatible = "qcom,l2-pmu";
+ interrupts = <0 1 0>;
+ };
+
};
/include/ "msm-pm8019-rpm-regulator.dtsi"
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index fc6bcd6..c59c4fc 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -141,6 +141,7 @@
CONFIG_SERIAL_MSM_HSL_CONSOLE=y
CONFIG_DIAG_CHAR=y
CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_MSM=y
CONFIG_SPMI=y
CONFIG_SPMI_MSM_PMIC_ARB=y
CONFIG_MSM_QPNP_INT=y
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index 9a2e82e..ea10007 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -291,6 +291,7 @@
CONFIG_SPMI=y
CONFIG_SPMI_MSM_PMIC_ARB=y
CONFIG_MSM_QPNP_INT=y
+CONFIG_QPNP_REVID=y
CONFIG_SLIMBUS_MSM_NGD=y
CONFIG_DEBUG_GPIO=y
CONFIG_GPIO_SYSFS=y
@@ -422,6 +423,7 @@
CONFIG_QPNP_PWM=y
CONFIG_QPNP_POWER_ON=y
CONFIG_QPNP_CLKDIV=y
+CONFIG_QPNP_COINCELL=y
CONFIG_MSM_IOMMU=y
CONFIG_MOBICORE_SUPPORT=m
CONFIG_MOBICORE_API=m
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 85f29b9..077c7a6 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -296,6 +296,7 @@
CONFIG_SPMI=y
CONFIG_SPMI_MSM_PMIC_ARB=y
CONFIG_MSM_QPNP_INT=y
+CONFIG_QPNP_REVID=y
CONFIG_SLIMBUS_MSM_NGD=y
CONFIG_DEBUG_GPIO=y
CONFIG_GPIO_SYSFS=y
@@ -430,6 +431,7 @@
CONFIG_QPNP_PWM=y
CONFIG_QPNP_POWER_ON=y
CONFIG_QPNP_CLKDIV=y
+CONFIG_QPNP_COINCELL=y
CONFIG_MSM_IOMMU=y
CONFIG_MSM_IOMMU_PMON=y
CONFIG_MOBICORE_SUPPORT=m
diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h
index d1a3e61..e1fc42f 100644
--- a/arch/arm/include/asm/pmu.h
+++ b/arch/arm/include/asm/pmu.h
@@ -52,6 +52,10 @@
void (*disable_irq)(int irq);
};
+extern int multicore_request_irq(int irq, irq_handler_t *handle_irq);
+extern void multicore_free_irq(int irq);
+extern struct arm_pmu_platdata multicore_data;
+
#ifdef CONFIG_CPU_HAS_PMU
/**
@@ -151,9 +155,6 @@
struct hw_perf_event *hwc,
int idx);
-extern void enable_irq_callback(void *);
-extern void disable_irq_callback(void *);
-
#endif /* CONFIG_HW_PERF_EVENTS */
#endif /* __ARM_PMU_H__ */
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index 5311d74..cef66ec 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -21,6 +21,7 @@
#include <linux/spinlock.h>
#include <linux/uaccess.h>
#include <linux/irq.h>
+#include <linux/of.h>
#include <asm/cputype.h>
#include <asm/irq.h>
@@ -51,6 +52,8 @@
/* Set at runtime when we know what CPU type we are. */
static struct arm_pmu *cpu_pmu;
+static int per_cpu_irq;
+
enum arm_perf_pmu_ids
armpmu_get_pmu_id(void)
{
@@ -381,6 +384,58 @@
return plat->handle_irq(irq, dev, armpmu->handle_irq);
}
+static DEFINE_PER_CPU(u32, pmu_irq_cookie);
+
+void enable_irq_callback(void *info)
+{
+ int irq = *(unsigned int *)info;
+ enable_percpu_irq(irq, IRQ_TYPE_EDGE_RISING);
+}
+
+void disable_irq_callback(void *info)
+{
+ int irq = *(unsigned int *)info;
+ disable_percpu_irq(irq);
+}
+
+int
+multicore_request_irq(int irq, irq_handler_t *handle_irq)
+{
+ int err = 0;
+ int cpu;
+
+ err = request_percpu_irq(irq, *handle_irq, "l1-armpmu",
+ &pmu_irq_cookie);
+
+ if (!err) {
+ for_each_cpu(cpu, cpu_online_mask) {
+ smp_call_function_single(cpu,
+ enable_irq_callback, &irq, 1);
+ }
+ }
+
+ return err;
+}
+
+void
+multicore_free_irq(int irq)
+{
+ int cpu;
+
+ if (irq >= 0) {
+ for_each_cpu(cpu, cpu_online_mask) {
+ smp_call_function_single(cpu,
+ disable_irq_callback, &irq, 1);
+ }
+ free_percpu_irq(irq, &pmu_irq_cookie);
+ }
+}
+
+struct arm_pmu_platdata multicore_data = {
+ .request_pmu_irq = multicore_request_irq,
+ .free_pmu_irq = multicore_free_irq,
+};
+
int
armpmu_generic_request_irq(int irq, irq_handler_t *handle_irq)
{
@@ -689,11 +744,12 @@
{.compatible = "arm,cortex-a8-pmu"},
{.compatible = "arm,arm1136-pmu"},
{.compatible = "arm,arm1176-pmu"},
+ {.compatible = "qcom,krait-pmu"},
{},
};
static struct platform_device_id armpmu_plat_device_ids[] = {
- {.name = "cpu-arm-pmu"},
+ {.name = "cpu-pmu"},
{},
};
@@ -703,12 +759,16 @@
return -ENODEV;
cpu_pmu->plat_device = pdev;
+
+ if (per_cpu_irq == 1)
+ cpu_pmu->plat_device->dev.platform_data = &multicore_data;
+
return 0;
}
static struct platform_driver armpmu_driver = {
.driver = {
- .name = "cpu-arm-pmu",
+ .name = "cpu-pmu",
.of_match_table = armpmu_of_device_ids,
},
.probe = armpmu_device_probe,
@@ -756,18 +816,6 @@
return 0;
}
-void enable_irq_callback(void *info)
-{
- int irq = *(unsigned int *)info;
- enable_percpu_irq(irq, IRQ_TYPE_EDGE_RISING);
-}
-
-void disable_irq_callback(void *info)
-{
- int irq = *(unsigned int *)info;
- disable_percpu_irq(irq);
-}
-
/*
* PMU hardware loses all context when a CPU goes offline.
* When a CPU is hotplugged back in, since some hardware registers are
@@ -881,6 +929,24 @@
.notifier_call = perf_cpu_pm_notifier,
};
+#ifdef CONFIG_OF
+static inline int get_dt_irq_prop(void)
+{
+ struct device_node *np = NULL;
+ int err = -1;
+
+ np = of_find_matching_node(NULL, armpmu_of_device_ids);
+ if (np)
+ err = of_property_read_bool(np, "qcom,irq-is-percpu");
+ else
+ pr_err("Perf: can't find DT node.\n");
+
+ return err;
+}
+#else
+static inline int get_dt_irq_prop(void) {return 0; }
+#endif
+
/*
* CPU PMU identification and registration.
*/
@@ -956,6 +1022,8 @@
register_cpu_notifier(&pmu_cpu_notifier);
armpmu_register(cpu_pmu, "cpu", PERF_TYPE_RAW);
cpu_pm_register_notifier(&perf_cpu_pm_notifier_block);
+ per_cpu_irq = get_dt_irq_prop();
+
} else {
pr_info("no hardware support available\n");
}
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 7d0f051..ce557b1 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -2859,4 +2859,12 @@
depends on SERIAL_MSM_HS
help
Select if BLSP based UART Core v.14 or higher is present.
+
+config MSM_BOOT_STATS
+ bool "Use MSM boot stats reporting"
+ help
+ Use this to report msm boot stats such as bootloader throughput,
+ display init, total boot time.
+ This figures are reported in mpm sleep clock cycles and have a
+ resolution of 31 bits as 1 bit is used as an overflow check.
endif
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index cb5e712..fb7e4e3 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -29,15 +29,17 @@
obj-$(CONFIG_DEBUG_FS) += acpuclock-krait-debug.o
endif
obj-$(CONFIG_ARCH_MSM7X27) += acpuclock-7627.o acpuclock-8625q.o clock-pll.o
-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
+ifndef CONFIG_OF
+obj-$(CONFIG_HW_PERF_EVENTS) += pmu.o
+endif
+obj-$(CONFIG_ARCH_MSM_KRAIT) += msm-krait-l2-accessors.o perf_event_msm_krait_l2.o
obj-$(CONFIG_ARCH_MSM_KRAIT) += krait-scm.o
ifdef CONFIG_HW_PERF_EVENTS
-obj-$(CONFIG_ARCH_MSM7X27A) += pmu.o perf_event_msm_pl310.o
-obj-$(CONFIG_ARCH_MSM9625) += pmu.o perf_event_msm_pl310.o
-obj-$(CONFIG_ARCH_MSM8625) += pmu.o perf_event_msm_pl310.o
-obj-$(CONFIG_ARCH_MSM9615) += pmu.o perf_event_msm_pl310.o
+obj-$(CONFIG_ARCH_MSM7X27A) += perf_event_msm_pl310.o
+obj-$(CONFIG_ARCH_MSM9625) += perf_event_msm_pl310.o
+obj-$(CONFIG_ARCH_MSM8625) += perf_event_msm_pl310.o
+obj-$(CONFIG_ARCH_MSM9615) += perf_event_msm_pl310.o
obj-$(CONFIG_DEBUG_FS) += perf_debug.o
endif
@@ -193,6 +195,7 @@
obj-$(CONFIG_ARCH_MSM8X60) += clock-rpm.o
obj-$(CONFIG_ARCH_MSM8X60) += saw-regulator.o
obj-$(CONFIG_ARCH_MSM8X60) += footswitch-8x60.o
+obj-$(CONFIG_MSM_BOOT_STATS) += boot_stats.o
ifdef CONFIG_MSM_RPM_REGULATOR
obj-y += rpm-regulator.o
@@ -300,7 +303,7 @@
obj-$(CONFIG_ARCH_MSM8930) += acpuclock-8930.o acpuclock-8627.o acpuclock-8930aa.o acpuclock-8930ab.o
obj-$(CONFIG_ARCH_MPQ8092) += board-8092.o board-8092-gpiomux.o
obj-$(CONFIG_ARCH_MSM8226) += board-8226.o board-8226-gpiomux.o
-obj-$(CONFIG_ARCH_MSM8226) += clock-local2.o clock-pll.o clock-8226.o clock-rpm.o clock-voter.o clock-mdss-8974.o
+obj-$(CONFIG_ARCH_MSM8226) += clock-local2.o clock-pll.o clock-8226.o clock-rpm.o clock-voter.o clock-mdss-8226.o
obj-$(CONFIG_ARCH_MSM8226) += acpuclock-8226.o acpuclock-cortex.o
obj-$(CONFIG_ARCH_MSM8610) += board-8610.o board-8610-gpiomux.o
obj-$(CONFIG_ARCH_MSM8610) += clock-local2.o clock-pll.o clock-8610.o clock-rpm.o clock-voter.o
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index efd0045..83c14a8 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -308,6 +308,168 @@
{ 0, { 0 } }
};
+static struct acpu_level acpu_freq_tbl_2g_pvs1[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 400000 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(3), 810000, 3200000 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(3), 820000, 3200000 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(6), 830000, 3200000 },
+ { 1, { 576000, HFPLL, 1, 30 }, L2(6), 840000, 3200000 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(7), 850000, 3200000 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(7), 860000, 3200000 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(10), 875000, 3200000 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(10), 885000, 3200000 },
+ { 0, { 960000, HFPLL, 1, 50 }, L2(10), 895000, 3200000 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 910000, 3200000 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 920000, 3200000 },
+ { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 930000, 3200000 },
+ { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 945000, 3200000 },
+ { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 960000, 3200000 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 975000, 3200000 },
+ { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 990000, 3200000 },
+ { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 1005000, 3200000 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 1020000, 3200000 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 1030000, 3200000 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 1045000, 3200000 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 1060000, 3200000 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1075000, 3200000 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_2g_pvs2[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 785000, 400000 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(3), 795000, 3200000 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(3), 805000, 3200000 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(6), 815000, 3200000 },
+ { 1, { 576000, HFPLL, 1, 30 }, L2(6), 825000, 3200000 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(7), 835000, 3200000 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(7), 845000, 3200000 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(10), 855000, 3200000 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(10), 865000, 3200000 },
+ { 0, { 960000, HFPLL, 1, 50 }, L2(10), 875000, 3200000 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 890000, 3200000 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 900000, 3200000 },
+ { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 910000, 3200000 },
+ { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 925000, 3200000 },
+ { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 940000, 3200000 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 955000, 3200000 },
+ { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 970000, 3200000 },
+ { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 980000, 3200000 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 995000, 3200000 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 1005000, 3200000 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 1020000, 3200000 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 1035000, 3200000 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1050000, 3200000 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_2g_pvs3[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 400000 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(3), 780000, 3200000 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(3), 790000, 3200000 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(6), 800000, 3200000 },
+ { 1, { 576000, HFPLL, 1, 30 }, L2(6), 810000, 3200000 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(7), 820000, 3200000 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(7), 830000, 3200000 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(10), 840000, 3200000 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(10), 850000, 3200000 },
+ { 0, { 960000, HFPLL, 1, 50 }, L2(10), 860000, 3200000 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 875000, 3200000 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 885000, 3200000 },
+ { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 895000, 3200000 },
+ { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 910000, 3200000 },
+ { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 925000, 3200000 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 935000, 3200000 },
+ { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 950000, 3200000 },
+ { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 960000, 3200000 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 970000, 3200000 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 985000, 3200000 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 995000, 3200000 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 1010000, 3200000 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1025000, 3200000 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_2g_pvs4[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 400000 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(3), 775000, 3200000 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(3), 780000, 3200000 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(6), 790000, 3200000 },
+ { 1, { 576000, HFPLL, 1, 30 }, L2(6), 800000, 3200000 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(7), 810000, 3200000 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(7), 820000, 3200000 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(10), 830000, 3200000 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(10), 840000, 3200000 },
+ { 0, { 960000, HFPLL, 1, 50 }, L2(10), 850000, 3200000 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 860000, 3200000 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 870000, 3200000 },
+ { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 880000, 3200000 },
+ { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 895000, 3200000 },
+ { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 910000, 3200000 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 920000, 3200000 },
+ { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 930000, 3200000 },
+ { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 940000, 3200000 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 950000, 3200000 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 960000, 3200000 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 975000, 3200000 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 985000, 3200000 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1000000, 3200000 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_2g_pvs5[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 400000 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(3), 760000, 3200000 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(3), 770000, 3200000 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(6), 780000, 3200000 },
+ { 1, { 576000, HFPLL, 1, 30 }, L2(6), 790000, 3200000 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(7), 800000, 3200000 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(7), 810000, 3200000 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(10), 820000, 3200000 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(10), 830000, 3200000 },
+ { 0, { 960000, HFPLL, 1, 50 }, L2(10), 840000, 3200000 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 850000, 3200000 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 860000, 3200000 },
+ { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 870000, 3200000 },
+ { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 880000, 3200000 },
+ { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 890000, 3200000 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 900000, 3200000 },
+ { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 910000, 3200000 },
+ { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 920000, 3200000 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 930000, 3200000 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 940000, 3200000 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 955000, 3200000 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 965000, 3200000 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 975000, 3200000 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_2g_pvs6[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 400000 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(3), 750000, 3200000 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(3), 760000, 3200000 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(6), 770000, 3200000 },
+ { 1, { 576000, HFPLL, 1, 30 }, L2(6), 780000, 3200000 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(7), 790000, 3200000 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(7), 800000, 3200000 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(10), 810000, 3200000 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(10), 820000, 3200000 },
+ { 0, { 960000, HFPLL, 1, 50 }, L2(10), 830000, 3200000 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 840000, 3200000 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 850000, 3200000 },
+ { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 860000, 3200000 },
+ { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 870000, 3200000 },
+ { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 875000, 3200000 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 885000, 3200000 },
+ { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 895000, 3200000 },
+ { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 905000, 3200000 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 915000, 3200000 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 920000, 3200000 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 930000, 3200000 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 940000, 3200000 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 950000, 3200000 },
+ { 0, { 0 } }
+};
+
static struct acpu_level acpu_freq_tbl_2p3g_pvs0[] __initdata = {
{ 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 400000 },
{ 0, { 345600, HFPLL, 2, 36 }, L2(3), 800000, 3200000 },
@@ -339,6 +501,192 @@
{ 0, { 0 } }
};
+static struct acpu_level acpu_freq_tbl_2p3g_pvs1[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 400000 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(3), 800000, 3200000 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(3), 800000, 3200000 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(6), 800000, 3200000 },
+ { 1, { 576000, HFPLL, 1, 30 }, L2(6), 800000, 3200000 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(7), 810000, 3200000 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(7), 820000, 3200000 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(10), 830000, 3200000 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(10), 840000, 3200000 },
+ { 0, { 960000, HFPLL, 1, 50 }, L2(10), 850000, 3200000 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 860000, 3200000 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 875000, 3200000 },
+ { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 885000, 3200000 },
+ { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 895000, 3200000 },
+ { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 910000, 3200000 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 920000, 3200000 },
+ { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 930000, 3200000 },
+ { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 945000, 3200000 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 960000, 3200000 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 975000, 3200000 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 990000, 3200000 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 1005000, 3200000 },
+ { 0, { 1958400, HFPLL, 1, 102 }, L2(19), 1020000, 3200000 },
+ { 1, { 2035200, HFPLL, 1, 106 }, L2(19), 1030000, 3200000 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1045000, 3200000 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1060000, 3200000 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1075000, 3200000 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_2p3g_pvs2[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 400000 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(3), 775000, 3200000 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(3), 775000, 3200000 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(6), 775000, 3200000 },
+ { 1, { 576000, HFPLL, 1, 30 }, L2(6), 785000, 3200000 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(7), 795000, 3200000 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(7), 805000, 3200000 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(10), 815000, 3200000 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(10), 825000, 3200000 },
+ { 0, { 960000, HFPLL, 1, 50 }, L2(10), 835000, 3200000 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 845000, 3200000 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 855000, 3200000 },
+ { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 865000, 3200000 },
+ { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 875000, 3200000 },
+ { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 890000, 3200000 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 900000, 3200000 },
+ { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 910000, 3200000 },
+ { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 925000, 3200000 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 940000, 3200000 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 955000, 3200000 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 970000, 3200000 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 980000, 3200000 },
+ { 0, { 1958400, HFPLL, 1, 102 }, L2(19), 995000, 3200000 },
+ { 1, { 2035200, HFPLL, 1, 106 }, L2(19), 1005000, 3200000 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1020000, 3200000 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1035000, 3200000 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1050000, 3200000 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_2p3g_pvs3[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 400000 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(3), 775000, 3200000 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(3), 775000, 3200000 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(6), 775000, 3200000 },
+ { 1, { 576000, HFPLL, 1, 30 }, L2(6), 775000, 3200000 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(7), 780000, 3200000 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(7), 790000, 3200000 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(10), 800000, 3200000 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(10), 810000, 3200000 },
+ { 0, { 960000, HFPLL, 1, 50 }, L2(10), 820000, 3200000 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 830000, 3200000 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 840000, 3200000 },
+ { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 850000, 3200000 },
+ { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 860000, 3200000 },
+ { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 875000, 3200000 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 885000, 3200000 },
+ { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 895000, 3200000 },
+ { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 910000, 3200000 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 925000, 3200000 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 935000, 3200000 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 950000, 3200000 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 960000, 3200000 },
+ { 0, { 1958400, HFPLL, 1, 102 }, L2(19), 970000, 3200000 },
+ { 1, { 2035200, HFPLL, 1, 106 }, L2(19), 985000, 3200000 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 995000, 3200000 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1010000, 3200000 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1025000, 3200000 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_2p3g_pvs4[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 400000 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(3), 775000, 3200000 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(3), 775000, 3200000 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(6), 775000, 3200000 },
+ { 1, { 576000, HFPLL, 1, 30 }, L2(6), 775000, 3200000 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(7), 775000, 3200000 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(7), 780000, 3200000 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(10), 790000, 3200000 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(10), 800000, 3200000 },
+ { 0, { 960000, HFPLL, 1, 50 }, L2(10), 810000, 3200000 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 820000, 3200000 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 830000, 3200000 },
+ { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 840000, 3200000 },
+ { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 850000, 3200000 },
+ { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 860000, 3200000 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 870000, 3200000 },
+ { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 880000, 3200000 },
+ { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 895000, 3200000 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 910000, 3200000 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 920000, 3200000 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 930000, 3200000 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 940000, 3200000 },
+ { 0, { 1958400, HFPLL, 1, 102 }, L2(19), 950000, 3200000 },
+ { 1, { 2035200, HFPLL, 1, 106 }, L2(19), 960000, 3200000 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 975000, 3200000 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 985000, 3200000 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1000000, 3200000 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_2p3g_pvs5[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 400000 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(3), 750000, 3200000 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(3), 750000, 3200000 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(6), 750000, 3200000 },
+ { 1, { 576000, HFPLL, 1, 30 }, L2(6), 750000, 3200000 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(7), 760000, 3200000 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(7), 770000, 3200000 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(10), 780000, 3200000 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(10), 790000, 3200000 },
+ { 0, { 960000, HFPLL, 1, 50 }, L2(10), 800000, 3200000 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 810000, 3200000 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 820000, 3200000 },
+ { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 830000, 3200000 },
+ { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 840000, 3200000 },
+ { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 850000, 3200000 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 860000, 3200000 },
+ { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 870000, 3200000 },
+ { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 880000, 3200000 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 890000, 3200000 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 900000, 3200000 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 910000, 3200000 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 920000, 3200000 },
+ { 0, { 1958400, HFPLL, 1, 102 }, L2(19), 930000, 3200000 },
+ { 1, { 2035200, HFPLL, 1, 106 }, L2(19), 940000, 3200000 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 955000, 3200000 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 965000, 3200000 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 975000, 3200000 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_2p3g_pvs6[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 400000 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(3), 750000, 3200000 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(3), 750000, 3200000 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(6), 750000, 3200000 },
+ { 1, { 576000, HFPLL, 1, 30 }, L2(6), 750000, 3200000 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(7), 750000, 3200000 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(7), 760000, 3200000 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(10), 770000, 3200000 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(10), 780000, 3200000 },
+ { 0, { 960000, HFPLL, 1, 50 }, L2(10), 790000, 3200000 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 800000, 3200000 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 810000, 3200000 },
+ { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 820000, 3200000 },
+ { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 830000, 3200000 },
+ { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 840000, 3200000 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 850000, 3200000 },
+ { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 860000, 3200000 },
+ { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 870000, 3200000 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 875000, 3200000 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 885000, 3200000 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 895000, 3200000 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 905000, 3200000 },
+ { 0, { 1958400, HFPLL, 1, 102 }, L2(19), 915000, 3200000 },
+ { 1, { 2035200, HFPLL, 1, 106 }, L2(19), 920000, 3200000 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 930000, 3200000 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 940000, 3200000 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 950000, 3200000 },
+ { 0, { 0 } }
+};
+
static struct pvs_table pvs_v1[NUM_SPEED_BINS][NUM_PVS] __initdata = {
/* 8974v1 1.7GHz Parts */
[0][0] = { acpu_freq_tbl_v1_pvs0, sizeof(acpu_freq_tbl_v1_pvs0) },
@@ -351,23 +699,23 @@
static struct pvs_table pvs_v2[NUM_SPEED_BINS][NUM_PVS] __initdata = {
/* 8974v2 2.0GHz Parts */
[0][0] = { acpu_freq_tbl_2g_pvs0, sizeof(acpu_freq_tbl_2g_pvs0) },
- [0][1] = { acpu_freq_tbl_2g_pvs0, sizeof(acpu_freq_tbl_2g_pvs0) },
- [0][2] = { acpu_freq_tbl_2g_pvs0, sizeof(acpu_freq_tbl_2g_pvs0) },
- [0][3] = { acpu_freq_tbl_2g_pvs0, sizeof(acpu_freq_tbl_2g_pvs0) },
- [0][4] = { acpu_freq_tbl_2g_pvs0, sizeof(acpu_freq_tbl_2g_pvs0) },
- [0][5] = { acpu_freq_tbl_2g_pvs0, sizeof(acpu_freq_tbl_2g_pvs0) },
- [0][6] = { acpu_freq_tbl_2g_pvs0, sizeof(acpu_freq_tbl_2g_pvs0) },
- [0][7] = { acpu_freq_tbl_2g_pvs0, sizeof(acpu_freq_tbl_2g_pvs0) },
+ [0][1] = { acpu_freq_tbl_2g_pvs1, sizeof(acpu_freq_tbl_2g_pvs1) },
+ [0][2] = { acpu_freq_tbl_2g_pvs2, sizeof(acpu_freq_tbl_2g_pvs2) },
+ [0][3] = { acpu_freq_tbl_2g_pvs3, sizeof(acpu_freq_tbl_2g_pvs3) },
+ [0][4] = { acpu_freq_tbl_2g_pvs4, sizeof(acpu_freq_tbl_2g_pvs4) },
+ [0][5] = { acpu_freq_tbl_2g_pvs5, sizeof(acpu_freq_tbl_2g_pvs5) },
+ [0][6] = { acpu_freq_tbl_2g_pvs6, sizeof(acpu_freq_tbl_2g_pvs6) },
+ [0][7] = { acpu_freq_tbl_2g_pvs6, sizeof(acpu_freq_tbl_2g_pvs6) },
/* 8974v2 2.3GHz Parts */
[1][0] = { acpu_freq_tbl_2p3g_pvs0, sizeof(acpu_freq_tbl_2p3g_pvs0) },
- [1][1] = { acpu_freq_tbl_2p3g_pvs0, sizeof(acpu_freq_tbl_2p3g_pvs0) },
- [1][2] = { acpu_freq_tbl_2p3g_pvs0, sizeof(acpu_freq_tbl_2p3g_pvs0) },
- [1][3] = { acpu_freq_tbl_2p3g_pvs0, sizeof(acpu_freq_tbl_2p3g_pvs0) },
- [1][4] = { acpu_freq_tbl_2p3g_pvs0, sizeof(acpu_freq_tbl_2p3g_pvs0) },
- [1][5] = { acpu_freq_tbl_2p3g_pvs0, sizeof(acpu_freq_tbl_2p3g_pvs0) },
- [1][6] = { acpu_freq_tbl_2p3g_pvs0, sizeof(acpu_freq_tbl_2p3g_pvs0) },
- [1][7] = { acpu_freq_tbl_2p3g_pvs0, sizeof(acpu_freq_tbl_2p3g_pvs0) },
+ [1][1] = { acpu_freq_tbl_2p3g_pvs1, sizeof(acpu_freq_tbl_2p3g_pvs1) },
+ [1][2] = { acpu_freq_tbl_2p3g_pvs2, sizeof(acpu_freq_tbl_2p3g_pvs2) },
+ [1][3] = { acpu_freq_tbl_2p3g_pvs3, sizeof(acpu_freq_tbl_2p3g_pvs3) },
+ [1][4] = { acpu_freq_tbl_2p3g_pvs4, sizeof(acpu_freq_tbl_2p3g_pvs4) },
+ [1][5] = { acpu_freq_tbl_2p3g_pvs5, sizeof(acpu_freq_tbl_2p3g_pvs5) },
+ [1][6] = { acpu_freq_tbl_2p3g_pvs6, sizeof(acpu_freq_tbl_2p3g_pvs6) },
+ [1][7] = { acpu_freq_tbl_2p3g_pvs6, sizeof(acpu_freq_tbl_2p3g_pvs6) },
};
static struct msm_bus_scale_pdata bus_scale_data __initdata = {
diff --git a/arch/arm/mach-msm/board-8226-gpiomux.c b/arch/arm/mach-msm/board-8226-gpiomux.c
index 5db52dd..41263f8 100644
--- a/arch/arm/mach-msm/board-8226-gpiomux.c
+++ b/arch/arm/mach-msm/board-8226-gpiomux.c
@@ -114,6 +114,29 @@
},
};
+static struct gpiomux_setting lcd_rst_act_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+ .dir = GPIOMUX_OUT_LOW,
+};
+
+static struct gpiomux_setting lcd_rst_sus_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct msm_gpiomux_config msm_lcd_configs[] __initdata = {
+ {
+ .gpio = 25,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &lcd_rst_act_cfg,
+ [GPIOMUX_SUSPENDED] = &lcd_rst_sus_cfg,
+ },
+ }
+};
+
static struct msm_gpiomux_config msm_blsp_configs[] __initdata = {
{
.gpio = 0, /* BLSP1 QUP1 SPI_DATA_MOSI */
@@ -225,4 +248,6 @@
msm_gpiomux_install(&sd_card_det, 1);
msm_gpiomux_install(msm_synaptics_configs,
ARRAY_SIZE(msm_synaptics_configs));
+ msm_gpiomux_install_nowrite(msm_lcd_configs,
+ ARRAY_SIZE(msm_lcd_configs));
}
diff --git a/arch/arm/mach-msm/boot_stats.c b/arch/arm/mach-msm/boot_stats.c
new file mode 100644
index 0000000..afb4374
--- /dev/null
+++ b/arch/arm/mach-msm/boot_stats.c
@@ -0,0 +1,100 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/smp.h>
+#include <linux/clk.h>
+#include <linux/cpu.h>
+#include <linux/sched.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <mach/msm_iomap.h>
+
+#include "boot_stats.h"
+
+#define MSM_BOOT_STATS_IMEM_START (MSM_IMEM_BASE+0x6b0)
+
+static void __iomem *mpm_counter_base;
+static uint32_t mpm_counter_freq;
+static struct boot_stats *boot_stats =
+ (void __iomem *)(MSM_BOOT_STATS_IMEM_START);
+
+static const struct of_device_id mpm_counter_of_match[] = {
+ { .compatible = "qcom,mpm2-sleep-counter", },
+ {},
+};
+
+static int mpm_parse_dt(void)
+{
+ struct device_node *np;
+ u32 freq;
+
+ np = of_find_matching_node(NULL, mpm_counter_of_match);
+ if (!np) {
+ pr_err("mpm_counter: can't find DT node\n");
+ return -ENODEV;
+ }
+
+ if (!of_property_read_u32(np, "clock-frequency", &freq))
+ mpm_counter_freq = freq;
+ else
+ return -ENODEV;
+
+ if (of_get_address(np, 0, NULL, NULL)) {
+ mpm_counter_base = of_iomap(np, 0);
+ if (!mpm_counter_base) {
+ pr_err("mpm_counter: cant map counter base\n");
+ return -ENODEV;
+ }
+ }
+
+ return 0;
+}
+
+static void print_boot_stats(void)
+{
+ pr_info("KPI: Bootloader start count = %u\n",
+ boot_stats->bootloader_start);
+ pr_info("KPI: Bootloader end count = %u\n",
+ boot_stats->bootloader_end);
+ pr_info("KPI: Bootloader display count = %u\n",
+ boot_stats->bootloader_display);
+ pr_info("KPI: Bootloader load kernel count = %u\n",
+ boot_stats->bootloader_load_kernel);
+ pr_info("KPI: Kernel MPM timestamp = %u\n",
+ __raw_readl(mpm_counter_base));
+ pr_info("KPI: Kernel MPM Clock frequency = %u\n",
+ mpm_counter_freq);
+}
+
+int boot_stats_init(void)
+{
+ int ret;
+
+ if (!boot_stats)
+ return -ENODEV;
+
+ ret = mpm_parse_dt();
+ if (ret < 0)
+ return -ENODEV;
+
+ print_boot_stats();
+
+ return 0;
+}
+
diff --git a/arch/arm/mach-msm/boot_stats.h b/arch/arm/mach-msm/boot_stats.h
new file mode 100644
index 0000000..93e36a2
--- /dev/null
+++ b/arch/arm/mach-msm/boot_stats.h
@@ -0,0 +1,24 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+struct boot_stats {
+ uint32_t bootloader_start;
+ uint32_t bootloader_end;
+ uint32_t bootloader_display;
+ uint32_t bootloader_load_kernel;
+};
+
+#ifdef CONFIG_MSM_BOOT_STATS
+int boot_stats_init(void);
+#else
+static inline int boot_stats_init(void) { return 0; }
+#endif
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index 5b8ee92..813b210 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -3342,7 +3342,7 @@
"fdc84000.qcom,iommu"),
CLK_LOOKUP("iface_clk", venus0_ahb_clk.c, "fdc84000.qcom,iommu"),
CLK_LOOKUP("core_clk", venus0_axi_clk.c, "fdc84000.qcom,iommu"),
-
+ CLK_LOOKUP("iface_clk", gcc_prng_ahb_clk.c, "f9bff000.qcom,msm-rng"),
CLK_LOOKUP("cam_gp0_clk", camss_gp0_clk.c, ""),
CLK_LOOKUP("cam_gp1_clk", camss_gp1_clk.c, ""),
CLK_LOOKUP("iface_clk", camss_micro_ahb_clk.c, ""),
diff --git a/arch/arm/mach-msm/clock-mdss-8226.c b/arch/arm/mach-msm/clock-mdss-8226.c
new file mode 100644
index 0000000..e7eca7b
--- /dev/null
+++ b/arch/arm/mach-msm/clock-mdss-8226.c
@@ -0,0 +1,346 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/iopoll.h>
+#include <linux/clk.h>
+
+#include <asm/processor.h>
+#include <mach/msm_iomap.h>
+#include <mach/clk-provider.h>
+
+#include "clock-mdss-8226.h"
+
+#define REG_R(addr) readl_relaxed(addr)
+#define REG_W(data, addr) writel_relaxed(data, addr)
+
+#define GDSC_PHYS 0xFD8C2304
+#define GDSC_SIZE 0x4
+
+#define DSI_PHY_PHYS 0xFD922800
+#define DSI_PHY_SIZE 0x00000800
+
+static unsigned char *mdss_dsi_base;
+static unsigned char *gdsc_base;
+static int pll_byte_clk_rate;
+static int pll_pclk_rate;
+static int pll_initialized;
+static struct clk *mdss_dsi_ahb_clk;
+static unsigned long dsi_pll_rate;
+
+void __init mdss_clk_ctrl_pre_init(struct clk *ahb_clk)
+{
+ BUG_ON(ahb_clk == NULL);
+
+ gdsc_base = ioremap(GDSC_PHYS, GDSC_SIZE);
+ if (!gdsc_base)
+ pr_err("%s: unable to remap gdsc base", __func__);
+
+ mdss_dsi_base = ioremap(DSI_PHY_PHYS, DSI_PHY_SIZE);
+ if (!mdss_dsi_base)
+ pr_err("%s: unable to remap dsi base", __func__);
+
+ mdss_dsi_ahb_clk = ahb_clk;
+}
+
+#define PLL_POLL_MAX_READS 10
+#define PLL_POLL_TIMEOUT_US 50
+
+static int mdss_gdsc_enabled(void)
+{
+ if (!gdsc_base)
+ return 0;
+
+ return !!(readl_relaxed(gdsc_base) & BIT(31));
+}
+
+static int mdss_dsi_check_pll_lock(void)
+{
+ u32 status;
+
+ clk_prepare_enable(mdss_dsi_ahb_clk);
+ /* poll for PLL ready status */
+ if (readl_poll_timeout_noirq((mdss_dsi_base + 0x02c0),
+ status,
+ ((status & BIT(0)) == 1),
+ PLL_POLL_MAX_READS, PLL_POLL_TIMEOUT_US)) {
+ pr_err("%s: DSI PLL status=%x failed to Lock\n",
+ __func__, status);
+ pll_initialized = 0;
+ } else {
+ pll_initialized = 1;
+ }
+ clk_disable_unprepare(mdss_dsi_ahb_clk);
+
+ return pll_initialized;
+}
+
+static long mdss_dsi_pll_byte_round_rate(struct clk *c, unsigned long rate)
+{
+ if (pll_initialized) {
+ return pll_byte_clk_rate;
+ } else {
+ pr_err("%s: DSI PLL not configured\n", __func__);
+ return -EINVAL;
+ }
+}
+
+static long mdss_dsi_pll_pixel_round_rate(struct clk *c, unsigned long rate)
+{
+ if (pll_initialized) {
+ return pll_pclk_rate;
+ } else {
+ pr_err("%s: Configure Byte clk first\n", __func__);
+ return -EINVAL;
+ }
+}
+
+static int mdss_dsi_pll_pixel_set_rate(struct clk *c, unsigned long rate)
+{
+ if (pll_initialized) {
+ pll_pclk_rate = (rate * 3) / 2;
+ pr_debug("%s: pll_pclk_rate=%d\n", __func__, pll_pclk_rate);
+ return 0;
+ } else {
+ pr_err("%s: Configure Byte clk first\n", __func__);
+ return -EINVAL;
+ }
+}
+
+static int __mdss_dsi_pll_byte_set_rate(struct clk *c, unsigned long rate)
+{
+ pr_debug("%s: rate=%ld\n", __func__, rate);
+
+ if (pll_initialized)
+ return 0;
+
+ REG_W(0x70, mdss_dsi_base + 0x0230); /* LPFC1 CFG */
+ REG_W(0x08, mdss_dsi_base + 0x022c); /* LPFR CFG */
+ REG_W(0x02, mdss_dsi_base + 0x0210); /* VREG CFG */
+ REG_W(0x00, mdss_dsi_base + 0x0204); /* postDiv1 */
+ REG_W(0x01, mdss_dsi_base + 0x0200); /* REFCLK CFG */
+ REG_W(0x03, mdss_dsi_base + 0x0224); /* postDiv2 */
+ REG_W(0x00, mdss_dsi_base + 0x0238); /* SDM CFG0 */
+ REG_W(0x0b, mdss_dsi_base + 0x023c); /* SDM CFG1 */
+ REG_W(0x00, mdss_dsi_base + 0x0240); /* SDM CFG2 */
+ REG_W(0x6c, mdss_dsi_base + 0x0244); /* SDM CFG3 */
+ REG_W(0x02, mdss_dsi_base + 0x0208); /* ChgPump */
+ REG_W(0x31, mdss_dsi_base + 0x020c); /* VCOLPF CFG */
+ REG_W(0x15, mdss_dsi_base + 0x0234); /* LPFC2 CFG */
+
+ REG_W(0x30, mdss_dsi_base + 0x0284); /* CAL CFG6 */
+ REG_W(0x00, mdss_dsi_base + 0x0288); /* CAL CFG7 */
+ REG_W(0x60, mdss_dsi_base + 0x028c); /* CAL CFG8 */
+ REG_W(0x00, mdss_dsi_base + 0x0290); /* CAL CFG9 */
+ REG_W(0xdd, mdss_dsi_base + 0x0294); /* CAL CFG10 */
+ REG_W(0x01, mdss_dsi_base + 0x0298); /* CAL CFG11 */
+
+ REG_W(0x03, mdss_dsi_base + 0x0228); /* postDiv3 */
+ REG_W(0x2b, mdss_dsi_base + 0x0278); /* Cal CFG3 */
+ REG_W(0x66, mdss_dsi_base + 0x027c); /* Cal CFG4 */
+ REG_W(0x05, mdss_dsi_base + 0x0264); /* LKDET CFG2 */
+ REG_W(0x00, mdss_dsi_base + 0x0248); /* SDM CFG4 */
+ REG_W(0x00, mdss_dsi_base + 0x0214); /* PWRGEN CFG */
+ REG_W(0x0a, mdss_dsi_base + 0x026c); /* CAL CFG0 */
+ REG_W(0x20, mdss_dsi_base + 0x029c); /* EFUSE CFG */
+
+ dsi_pll_rate = rate;
+ pll_byte_clk_rate = rate;
+
+ pr_debug("%s: PLL initialized. bcl=%d\n", __func__, pll_byte_clk_rate);
+ pll_initialized = 1;
+
+ return 0;
+}
+
+static int mdss_dsi_pll_byte_set_rate(struct clk *c, unsigned long rate)
+{
+ int ret;
+
+ clk_prepare_enable(mdss_dsi_ahb_clk);
+ ret = __mdss_dsi_pll_byte_set_rate(c, rate);
+ clk_disable_unprepare(mdss_dsi_ahb_clk);
+
+ return ret;
+}
+
+static void mdss_dsi_uniphy_pll_lock_detect_setting(void)
+{
+ REG_W(0x04, mdss_dsi_base + 0x0264); /* LKDetect CFG2 */
+ udelay(100);
+ REG_W(0x05, mdss_dsi_base + 0x0264); /* LKDetect CFG2 */
+ udelay(500);
+}
+
+static void mdss_dsi_uniphy_pll_sw_reset(void)
+{
+ REG_W(0x01, mdss_dsi_base + 0x0268); /* PLL TEST CFG */
+ udelay(1);
+ REG_W(0x00, mdss_dsi_base + 0x0268); /* PLL TEST CFG */
+ udelay(1);
+}
+
+static int __mdss_dsi_pll_enable(struct clk *c)
+{
+ u32 status;
+ u32 max_reads, timeout_us;
+ int i;
+
+ if (!pll_initialized) {
+ if (dsi_pll_rate)
+ __mdss_dsi_pll_byte_set_rate(c, dsi_pll_rate);
+ else
+ pr_err("%s: Calling clk_en before set_rate\n",
+ __func__);
+ }
+
+ mdss_dsi_uniphy_pll_sw_reset();
+ /* PLL power up */
+ /* Add HW recommended delay between
+ register writes for the update to propagate */
+ REG_W(0x01, mdss_dsi_base + 0x0220); /* GLB CFG */
+ udelay(20);
+ REG_W(0x05, mdss_dsi_base + 0x0220); /* GLB CFG */
+ udelay(100);
+ REG_W(0x0d, mdss_dsi_base + 0x0220); /* GLB CFG */
+ udelay(20);
+ REG_W(0x0f, mdss_dsi_base + 0x0220); /* GLB CFG */
+ udelay(200);
+
+ for (i = 0; i < 3; i++) {
+ mdss_dsi_uniphy_pll_lock_detect_setting();
+ /* poll for PLL ready status */
+ max_reads = 5;
+ timeout_us = 100;
+ if (readl_poll_timeout_noirq((mdss_dsi_base + 0x02c0),
+ status,
+ ((status & 0x01) == 1),
+ max_reads, timeout_us)) {
+ pr_debug("%s: DSI PLL status=%x failed to Lock\n",
+ __func__, status);
+ pr_debug("%s:Trying to power UP PLL again\n",
+ __func__);
+ } else
+ break;
+
+ mdss_dsi_uniphy_pll_sw_reset();
+ udelay(1000);
+ /* Add HW recommended delay between
+ register writes for the update to propagate */
+ REG_W(0x01, mdss_dsi_base + 0x0220); /* GLB CFG */
+ udelay(20);
+ REG_W(0x05, mdss_dsi_base + 0x0220); /* GLB CFG */
+ udelay(100);
+ REG_W(0x0d, mdss_dsi_base + 0x0220); /* GLB CFG */
+ udelay(20);
+ REG_W(0x0f, mdss_dsi_base + 0x0220); /* GLB CFG */
+ udelay(200);
+ }
+
+ if ((status & 0x01) != 1) {
+ pr_err("%s: DSI PLL status=%x failed to Lock\n",
+ __func__, status);
+ return -EINVAL;
+ }
+
+ pr_debug("%s: **** PLL Lock success\n", __func__);
+
+ return 0;
+}
+
+static void __mdss_dsi_pll_disable(void)
+{
+ writel_relaxed(0x00, mdss_dsi_base + 0x0220); /* GLB CFG */
+ pr_debug("%s: **** disable pll Initialize\n", __func__);
+ pll_initialized = 0;
+}
+
+static DEFINE_SPINLOCK(dsipll_lock);
+static int dsipll_refcount;
+
+static void mdss_dsi_pll_disable(struct clk *c)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&dsipll_lock, flags);
+ if (WARN(dsipll_refcount == 0, "DSI PLL clock is unbalanced"))
+ goto out;
+ if (dsipll_refcount == 1)
+ __mdss_dsi_pll_disable();
+ dsipll_refcount--;
+out:
+ spin_unlock_irqrestore(&dsipll_lock, flags);
+}
+
+static int mdss_dsi_pll_enable(struct clk *c)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&dsipll_lock, flags);
+ if (dsipll_refcount == 0) {
+ ret = __mdss_dsi_pll_enable(c);
+ if (ret < 0)
+ goto out;
+ }
+ dsipll_refcount++;
+out:
+ spin_unlock_irqrestore(&dsipll_lock, flags);
+ return ret;
+}
+
+/* todo: Adjust these values appropriately */
+static enum handoff mdss_dsi_pll_byte_handoff(struct clk *c)
+{
+ if (mdss_gdsc_enabled() && mdss_dsi_check_pll_lock()) {
+ c->rate = 59000000;
+ dsi_pll_rate = 59000000;
+ pll_byte_clk_rate = 59000000;
+ pll_pclk_rate = 117000000;
+ dsipll_refcount++;
+ return HANDOFF_ENABLED_CLK;
+ }
+
+ return HANDOFF_DISABLED_CLK;
+}
+
+/* todo: Adjust these values appropriately */
+static enum handoff mdss_dsi_pll_pixel_handoff(struct clk *c)
+{
+ if (mdss_gdsc_enabled() && mdss_dsi_check_pll_lock()) {
+ c->rate = 117000000;
+ dsipll_refcount++;
+ return HANDOFF_ENABLED_CLK;
+ }
+
+ return HANDOFF_DISABLED_CLK;
+}
+
+struct clk_ops clk_ops_dsi_pixel_pll = {
+ .enable = mdss_dsi_pll_enable,
+ .disable = mdss_dsi_pll_disable,
+ .set_rate = mdss_dsi_pll_pixel_set_rate,
+ .round_rate = mdss_dsi_pll_pixel_round_rate,
+ .handoff = mdss_dsi_pll_pixel_handoff,
+};
+
+struct clk_ops clk_ops_dsi_byte_pll = {
+ .enable = mdss_dsi_pll_enable,
+ .disable = mdss_dsi_pll_disable,
+ .set_rate = mdss_dsi_pll_byte_set_rate,
+ .round_rate = mdss_dsi_pll_byte_round_rate,
+ .handoff = mdss_dsi_pll_byte_handoff,
+};
diff --git a/arch/arm/mach-msm/clock-mdss-8226.h b/arch/arm/mach-msm/clock-mdss-8226.h
new file mode 100644
index 0000000..dcf4f92
--- /dev/null
+++ b/arch/arm/mach-msm/clock-mdss-8226.h
@@ -0,0 +1,22 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ARCH_ARM_MACH_MSM_CLOCK_MDSS_8226
+#define __ARCH_ARM_MACH_MSM_CLOCK_MDSS_8226
+
+extern struct clk_ops clk_ops_dsi_byte_pll;
+extern struct clk_ops clk_ops_dsi_pixel_pll;
+
+void mdss_clk_ctrl_pre_init(struct clk *ahb_clk);
+void mdss_clk_ctrl_post_init(void);
+
+#endif /* __ARCH_ARM_MACH_MSM_CLOCK_MDSS_8226 */
diff --git a/arch/arm/mach-msm/include/mach/memory.h b/arch/arm/mach-msm/include/mach/memory.h
index d3574c8..8c53ea5 100644
--- a/arch/arm/mach-msm/include/mach/memory.h
+++ b/arch/arm/mach-msm/include/mach/memory.h
@@ -69,7 +69,6 @@
#endif
#ifndef __ASSEMBLY__
-void *alloc_bootmem_aligned(unsigned long size, unsigned long alignment);
void *allocate_contiguous_ebi(unsigned long, unsigned long, int);
unsigned long allocate_contiguous_ebi_nomap(unsigned long, unsigned long);
void clean_and_invalidate_caches(unsigned long, unsigned long, unsigned long);
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index f3bd34a..5f11806 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -107,34 +107,6 @@
outer_inv_range(pstart, pstart + length);
}
-void * __init alloc_bootmem_aligned(unsigned long size, unsigned long alignment)
-{
- void *unused_addr = NULL;
- unsigned long addr, tmp_size, unused_size;
-
- /* Allocate maximum size needed, see where it ends up.
- * Then free it -- in this path there are no other allocators
- * so we can depend on getting the same address back
- * when we allocate a smaller piece that is aligned
- * at the end (if necessary) and the piece we really want,
- * then free the unused first piece.
- */
-
- tmp_size = size + alignment - PAGE_SIZE;
- addr = (unsigned long)alloc_bootmem(tmp_size);
- free_bootmem(__pa(addr), tmp_size);
-
- unused_size = alignment - (addr % alignment);
- if (unused_size)
- unused_addr = alloc_bootmem(unused_size);
-
- addr = (unsigned long)alloc_bootmem(size);
- if (unused_size)
- free_bootmem(__pa(unused_addr), unused_size);
-
- return (void *)addr;
-}
-
char *memtype_name[] = {
"SMI_KERNEL",
"SMI",
diff --git a/arch/arm/mach-msm/msm_mpmctr.c b/arch/arm/mach-msm/msm_mpmctr.c
index 4ab82ab..cc0c1c3 100644
--- a/arch/arm/mach-msm/msm_mpmctr.c
+++ b/arch/arm/mach-msm/msm_mpmctr.c
@@ -54,7 +54,7 @@
}
static struct of_device_id msm_mpmctr_of_match[] = {
- {.compatible = "qcom,mpm-counter"},
+ {.compatible = "qcom,mpm2-sleep-counter"},
{}
};
diff --git a/arch/arm/mach-msm/perf_debug.c b/arch/arm/mach-msm/perf_debug.c
index 0579145..7f2f528 100644
--- a/arch/arm/mach-msm/perf_debug.c
+++ b/arch/arm/mach-msm/perf_debug.c
@@ -27,6 +27,7 @@
"2 Perf: Toggle PMU IRQ when CPU's are hotplugged\n"
"3 Perf: Correct irq for CPU hotplug detection\n"
"4 Perf: Check perf activity on correct CPU\n"
+ "5 Perf: Add DT support for L1 and L2 PMU\n"
;
static ssize_t desc_read(struct file *fp, char __user *buf,
diff --git a/arch/arm/mach-msm/perf_event_msm_krait_l2.c b/arch/arm/mach-msm/perf_event_msm_krait_l2.c
index 34b9426..ad34457 100644
--- a/arch/arm/mach-msm/perf_event_msm_krait_l2.c
+++ b/arch/arm/mach-msm/perf_event_msm_krait_l2.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2012 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2013 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -564,6 +564,14 @@
.pmu.attr_groups = msm_l2_pmu_attr_grps,
};
+/*
+ * PMU platform driver and devicetree bindings.
+ */
+static struct of_device_id l2pmu_of_device_ids[] = {
+ {.compatible = "qcom,l2-pmu"},
+ {},
+};
+
static int __devinit krait_l2_pmu_device_probe(struct platform_device *pdev)
{
krait_l2_pmu.plat_device = pdev;
@@ -576,7 +584,8 @@
static struct platform_driver krait_l2_pmu_driver = {
.driver = {
- .name = "l2-arm-pmu",
+ .name = "l2-pmu",
+ .of_match_table = l2pmu_of_device_ids,
},
.probe = krait_l2_pmu_device_probe,
};
diff --git a/arch/arm/mach-msm/perf_event_msm_l2.c b/arch/arm/mach-msm/perf_event_msm_l2.c
index f78487a..efd5e21 100644
--- a/arch/arm/mach-msm/perf_event_msm_l2.c
+++ b/arch/arm/mach-msm/perf_event_msm_l2.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2012 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2013 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -917,7 +917,7 @@
static struct platform_driver scorpion_l2_pmu_driver = {
.driver = {
- .name = "l2-arm-pmu",
+ .name = "l2-pmu",
},
.probe = scorpion_l2_pmu_device_probe,
};
diff --git a/arch/arm/mach-msm/perf_event_msm_pl310.c b/arch/arm/mach-msm/perf_event_msm_pl310.c
index e2a580f..a0d96bf 100644
--- a/arch/arm/mach-msm/perf_event_msm_pl310.c
+++ b/arch/arm/mach-msm/perf_event_msm_pl310.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2007 ARM Limited
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -415,9 +415,18 @@
return 0;
}
+/*
+ * PMU platform driver and devicetree bindings.
+ */
+static struct of_device_id l2pmu_of_device_ids[] = {
+ {.compatible = "qcom,l2-pmu"},
+ {},
+};
+
static struct platform_driver l2x0pmu_driver = {
.driver = {
- .name = "l2-arm-pmu",
+ .name = "l2-pmu",
+ .of_match_table = l2pmu_of_device_ids,
},
.probe = l2x0pmu_device_probe,
};
diff --git a/arch/arm/mach-msm/pmu.c b/arch/arm/mach-msm/pmu.c
index febeb19..57378c7 100644
--- a/arch/arm/mach-msm/pmu.c
+++ b/arch/arm/mach-msm/pmu.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -15,62 +15,6 @@
#include <mach/irqs.h>
#include <mach/socinfo.h>
-/*
- * If a GIC is present, then all IRQ's < 32 are PPI's and can only be
- * requested and free'd using the percpu IRQ API.
- * If a VIC is present, then only the traditional request, free API works.
- *
- * All MPCore's have GIC's. The Cortex A5 however may or may not be MPcore, but
- * it still has a GIC. Except, the 7x27a, which is an A5 and yet has a VIC.
- * So if the chip is A5 but does not have a GIC, default to the traditional
- * IRQ {request, free}_irq API.
- */
-
-#if defined(CONFIG_ARCH_MSM_KRAITMP) || defined(CONFIG_ARCH_MSM_SCORPIONMP) \
- || defined(CONFIG_ARCH_MSM8625) || \
- (defined(CONFIG_ARCH_MSM_CORTEX_A5) && !defined(CONFIG_MSM_VIC))
-
-static DEFINE_PER_CPU(u32, pmu_irq_cookie);
-
-static int
-multicore_request_irq(int irq, irq_handler_t *handle_irq)
-{
- int err = 0;
- int cpu;
-
- err = request_percpu_irq(irq, *handle_irq, "l1-armpmu",
- &pmu_irq_cookie);
-
- if (!err) {
- for_each_cpu(cpu, cpu_online_mask) {
- smp_call_function_single(cpu,
- enable_irq_callback, &irq, 1);
- }
- }
-
- return err;
-}
-
-static void
-multicore_free_irq(int irq)
-{
- int cpu;
-
- if (irq >= 0) {
- for_each_cpu(cpu, cpu_online_mask) {
- smp_call_function_single(cpu,
- disable_irq_callback, &irq, 1);
- }
- free_percpu_irq(irq, &pmu_irq_cookie);
- }
-}
-
-static struct arm_pmu_platdata multicore_data = {
- .request_pmu_irq = multicore_request_irq,
- .free_pmu_irq = multicore_free_irq,
-};
-#endif
-
static struct resource cpu_pmu_resource[] = {
{
.start = INT_ARMQC_PERFMON,
@@ -89,7 +33,7 @@
};
static struct platform_device l2_pmu_device = {
- .name = "l2-arm-pmu",
+ .name = "l2-pmu",
.id = ARM_PMU_DEVICE_L2CC,
.resource = l2_pmu_resource,
.num_resources = ARRAY_SIZE(l2_pmu_resource),
@@ -98,7 +42,7 @@
#endif
static struct platform_device cpu_pmu_device = {
- .name = "cpu-arm-pmu",
+ .name = "cpu-pmu",
.id = ARM_PMU_DEVICE_CPU,
.resource = cpu_pmu_resource,
.num_resources = ARRAY_SIZE(cpu_pmu_resource),
@@ -120,7 +64,7 @@
};
static struct platform_device msm8625_cpu_pmu_device = {
- .name = "cpu-arm-pmu",
+ .name = "cpu-pmu",
.id = ARM_PMU_DEVICE_CPU,
.resource = msm8625_cpu_pmu_resource,
.num_resources = ARRAY_SIZE(msm8625_cpu_pmu_resource),
@@ -135,7 +79,7 @@
};
static struct platform_device msm8625_l2_pmu_device = {
- .name = "l2-arm-pmu",
+ .name = "l2-pmu",
.id = ARM_PMU_DEVICE_L2CC,
.resource = msm8625_l2_pmu_resource,
.num_resources = ARRAY_SIZE(msm8625_l2_pmu_resource),
@@ -156,7 +100,6 @@
* handlers to call the percpu API.
* Defaults to unicore API {request,free}_irq().
* See arch/arm/kernel/perf_event.c
- * See Comment above on the A5 and MSM_VIC.
*/
#if defined(CONFIG_ARCH_MSM_KRAITMP) || defined(CONFIG_ARCH_MSM_SCORPIONMP) \
|| (defined(CONFIG_ARCH_MSM_CORTEX_A5) && !defined(CONFIG_MSM_VIC))
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 3da1c63..efbd8c6 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -29,6 +29,7 @@
#include <mach/socinfo.h>
#include "smd_private.h"
+#include "boot_stats.h"
#define BUILD_ID_LENGTH 32
@@ -1139,6 +1140,7 @@
if (socinfo->v1.id < ARRAY_SIZE(cpu_of_id))
cur_cpu = cpu_of_id[socinfo->v1.id];
+ boot_stats_init();
socinfo_print();
return 0;
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index be71347..3d5614b 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -787,6 +787,8 @@
spin_lock_irqsave(&cpufreq_driver_lock, flags);
cpumask_copy(managed_policy->cpus, policy->cpus);
+ cpumask_and(managed_policy->cpus,
+ managed_policy->cpus, cpu_online_mask);
per_cpu(cpufreq_cpu_data, cpu) = managed_policy;
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
diff --git a/drivers/crypto/msm/qce.c b/drivers/crypto/msm/qce.c
index 7f8460b..5c1cc5a 100644
--- a/drivers/crypto/msm/qce.c
+++ b/drivers/crypto/msm/qce.c
@@ -505,19 +505,6 @@
return nents;
}
-static int dma_map_pmem_sg(struct buf_info *pmem, unsigned entries,
- struct scatterlist *sg)
-{
- int i = 0;
- for (i = 0; i < entries; i++) {
-
- sg->dma_address = (dma_addr_t)pmem->offset;
- sg++;
- pmem++;
- }
- return 0;
-}
-
static int _probe_ce_engine(struct qce_device *pce_dev)
{
unsigned int val;
@@ -1084,52 +1071,6 @@
return 0;
};
-static int _ablk_cipher_use_pmem_complete(struct qce_device *pce_dev)
-{
- struct ablkcipher_request *areq;
- uint32_t iv_out[4];
- unsigned char iv[4 * sizeof(uint32_t)];
- uint32_t status;
-
- areq = (struct ablkcipher_request *) pce_dev->areq;
-
- /* check ce error status */
- status = readl_relaxed(pce_dev->iobase + CRYPTO_STATUS_REG);
- if (status & (1 << CRYPTO_SW_ERR)) {
- pce_dev->err++;
- dev_err(pce_dev->pdev,
- "Qualcomm Crypto Error at 0x%x, status%x\n",
- pce_dev->phy_iobase, status);
- _init_ce_engine(pce_dev);
- clk_disable(pce_dev->ce_clk);
- pce_dev->qce_cb(areq, NULL, NULL, -ENXIO);
- return 0;
- };
-
- /* get iv out */
- if (pce_dev->mode == QCE_MODE_ECB) {
- clk_disable(pce_dev->ce_clk);
- pce_dev->qce_cb(areq, NULL, NULL, pce_dev->chan_ce_in_status |
- pce_dev->chan_ce_out_status);
- } else {
- iv_out[0] = readl_relaxed(pce_dev->iobase +
- CRYPTO_CNTR0_IV0_REG);
- iv_out[1] = readl_relaxed(pce_dev->iobase +
- CRYPTO_CNTR1_IV1_REG);
- iv_out[2] = readl_relaxed(pce_dev->iobase +
- CRYPTO_CNTR2_IV2_REG);
- iv_out[3] = readl_relaxed(pce_dev->iobase +
- CRYPTO_CNTR3_IV3_REG);
-
- _net_words_to_byte_stream(iv_out, iv, sizeof(iv));
- clk_disable(pce_dev->ce_clk);
- pce_dev->qce_cb(areq, NULL, iv, pce_dev->chan_ce_in_status |
- pce_dev->chan_ce_out_status);
- }
-
- return 0;
-};
-
static int qce_split_and_insert_dm_desc(struct dmov_desc *pdesc,
unsigned int plen, unsigned int paddr, int *index)
{
@@ -1555,53 +1496,6 @@
};
-static void _ablk_cipher_ce_in_call_back_pmem(struct msm_dmov_cmd *cmd_ptr,
- unsigned int result, struct msm_dmov_errdata *err)
-{
- struct qce_device *pce_dev;
-
- pce_dev = (struct qce_device *) cmd_ptr->user;
- if (result != ADM_STATUS_OK) {
- dev_err(pce_dev->pdev, "Qualcomm ADM status error %x\n",
- result);
- pce_dev->chan_ce_in_status = -1;
- } else
- pce_dev->chan_ce_in_status = 0;
-
- pce_dev->chan_ce_in_state = QCE_CHAN_STATE_COMP;
- if (pce_dev->chan_ce_out_state == QCE_CHAN_STATE_COMP) {
- pce_dev->chan_ce_in_state = QCE_CHAN_STATE_IDLE;
- pce_dev->chan_ce_out_state = QCE_CHAN_STATE_IDLE;
-
- /* done */
- _ablk_cipher_use_pmem_complete(pce_dev);
- }
-};
-
-static void _ablk_cipher_ce_out_call_back_pmem(struct msm_dmov_cmd *cmd_ptr,
- unsigned int result, struct msm_dmov_errdata *err)
-{
- struct qce_device *pce_dev;
-
- pce_dev = (struct qce_device *) cmd_ptr->user;
- if (result != ADM_STATUS_OK) {
- dev_err(pce_dev->pdev, "Qualcomm ADM status error %x\n",
- result);
- pce_dev->chan_ce_out_status = -1;
- } else {
- pce_dev->chan_ce_out_status = 0;
- };
-
- pce_dev->chan_ce_out_state = QCE_CHAN_STATE_COMP;
- if (pce_dev->chan_ce_in_state == QCE_CHAN_STATE_COMP) {
- pce_dev->chan_ce_in_state = QCE_CHAN_STATE_IDLE;
- pce_dev->chan_ce_out_state = QCE_CHAN_STATE_IDLE;
-
- /* done */
- _ablk_cipher_use_pmem_complete(pce_dev);
- }
-};
-
static int _setup_cmd_template(struct qce_device *pce_dev)
{
dmov_sg *pcmd;
@@ -2183,14 +2077,9 @@
/* cipher input */
pce_dev->src_nents = count_sg(areq->src, areq->nbytes);
- if (c_req->use_pmem != 1)
- qce_dma_map_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
+ qce_dma_map_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
(areq->src == areq->dst) ? DMA_BIDIRECTIONAL :
DMA_TO_DEVICE);
- else
- dma_map_pmem_sg(&c_req->pmem->src[0], pce_dev->src_nents,
- areq->src);
-
if (_chain_sg_buffer_in(pce_dev, areq->src, areq->nbytes) < 0) {
rc = -ENOMEM;
goto bad;
@@ -2199,12 +2088,8 @@
/* cipher output */
if (areq->src != areq->dst) {
pce_dev->dst_nents = count_sg(areq->dst, areq->nbytes);
- if (c_req->use_pmem != 1)
- qce_dma_map_sg(pce_dev->pdev, areq->dst,
+ qce_dma_map_sg(pce_dev->pdev, areq->dst,
pce_dev->dst_nents, DMA_FROM_DEVICE);
- else
- dma_map_pmem_sg(&c_req->pmem->dst[0],
- pce_dev->dst_nents, areq->dst);
};
if (_chain_sg_buffer_out(pce_dev, areq->dst, areq->nbytes) < 0) {
rc = -ENOMEM;
@@ -2241,34 +2126,25 @@
/* setup for callback, and issue command to adm */
pce_dev->areq = areq;
pce_dev->qce_cb = c_req->qce_cb;
- if (c_req->use_pmem == 1) {
- pce_dev->chan_ce_in_cmd->complete_func =
- _ablk_cipher_ce_in_call_back_pmem;
- pce_dev->chan_ce_out_cmd->complete_func =
- _ablk_cipher_ce_out_call_back_pmem;
- } else {
- pce_dev->chan_ce_in_cmd->complete_func =
+ pce_dev->chan_ce_in_cmd->complete_func =
_ablk_cipher_ce_in_call_back;
- pce_dev->chan_ce_out_cmd->complete_func =
+ pce_dev->chan_ce_out_cmd->complete_func =
_ablk_cipher_ce_out_call_back;
- }
rc = _qce_start_dma(pce_dev, true, true);
if (rc == 0)
return 0;
bad:
- if (c_req->use_pmem != 1) {
- if (pce_dev->dst_nents) {
- qce_dma_unmap_sg(pce_dev->pdev, areq->dst,
- pce_dev->dst_nents, DMA_FROM_DEVICE);
- }
- if (pce_dev->src_nents) {
- qce_dma_unmap_sg(pce_dev->pdev, areq->src,
- pce_dev->src_nents,
- (areq->src == areq->dst) ?
- DMA_BIDIRECTIONAL :
- DMA_TO_DEVICE);
- }
+ if (pce_dev->dst_nents) {
+ qce_dma_unmap_sg(pce_dev->pdev, areq->dst,
+ pce_dev->dst_nents, DMA_FROM_DEVICE);
+ }
+ if (pce_dev->src_nents) {
+ qce_dma_unmap_sg(pce_dev->pdev, areq->src,
+ pce_dev->src_nents,
+ (areq->src == areq->dst) ?
+ DMA_BIDIRECTIONAL :
+ DMA_TO_DEVICE);
}
return rc;
}
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c
index 41ab8dc..2440404 100644
--- a/drivers/crypto/msm/qcedev.c
+++ b/drivers/crypto/msm/qcedev.c
@@ -12,7 +12,7 @@
* GNU General Public License for more details.
*/
#include <linux/mman.h>
-#include <linux/android_pmem.h>
+
#include <linux/types.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
@@ -454,14 +454,12 @@
/* start the command on the podev->active_command */
qcedev_areq = podev->active_command;
-
qcedev_areq->cipher_req.cookie = qcedev_areq->handle;
- creq.use_pmem = qcedev_areq->cipher_op_req.use_pmem;
- if (qcedev_areq->cipher_op_req.use_pmem == QCEDEV_USE_PMEM)
- creq.pmem = &qcedev_areq->cipher_op_req.pmem;
- else
- creq.pmem = NULL;
-
+ if (qcedev_areq->cipher_op_req.use_pmem == QCEDEV_USE_PMEM) {
+ pr_err("%s: Use of PMEM is not supported\n", __func__);
+ goto unsupported;
+ }
+ creq.pmem = NULL;
switch (qcedev_areq->cipher_op_req.alg) {
case QCEDEV_ALG_DES:
creq.alg = CIPHER_ALG_DES;
@@ -1274,224 +1272,6 @@
return qcedev_hmac_final(areq, handle);
}
-#ifdef CONFIG_ANDROID_PMEM
-static int qcedev_pmem_ablk_cipher_max_xfer(struct qcedev_async_req *areq,
- struct qcedev_handle *handle)
-{
- int i = 0;
- int err = 0;
- struct scatterlist *sg_src = NULL;
- struct scatterlist *sg_dst = NULL;
- struct scatterlist *sg_ndex = NULL;
- struct file *file_src = NULL;
- struct file *file_dst = NULL;
- unsigned long paddr;
- unsigned long kvaddr;
- unsigned long len;
-
- sg_src = kmalloc((sizeof(struct scatterlist) *
- areq->cipher_op_req.entries), GFP_KERNEL);
- if (sg_src == NULL) {
- pr_err("%s: Can't Allocate memory:sg_src 0x%x\n",
- __func__, (uint32_t)sg_src);
- return -ENOMEM;
-
- }
- memset(sg_src, 0, (sizeof(struct scatterlist) *
- areq->cipher_op_req.entries));
- sg_ndex = sg_src;
- areq->cipher_req.creq.src = sg_src;
-
- /* address src */
- get_pmem_file(areq->cipher_op_req.pmem.fd_src, &paddr,
- &kvaddr, &len, &file_src);
-
- for (i = 0; i < areq->cipher_op_req.entries; i++) {
- sg_set_buf(sg_ndex,
- ((uint8_t *)(areq->cipher_op_req.pmem.src[i].offset) + kvaddr),
- areq->cipher_op_req.pmem.src[i].len);
- sg_ndex++;
- }
- sg_mark_end(--sg_ndex);
-
- for (i = 0; i < areq->cipher_op_req.entries; i++)
- areq->cipher_op_req.pmem.src[i].offset += (uint32_t)paddr;
-
- /* address dst */
- /* If not place encryption/decryption */
- if (areq->cipher_op_req.in_place_op != 1) {
- sg_dst = kmalloc((sizeof(struct scatterlist) *
- areq->cipher_op_req.entries), GFP_KERNEL);
- if (sg_dst == NULL) {
- pr_err("%s: Can't Allocate memory: sg_dst 0x%x\n",
- __func__, (uint32_t)sg_dst);
- return -ENOMEM;
- }
- memset(sg_dst, 0, (sizeof(struct scatterlist) *
- areq->cipher_op_req.entries));
- areq->cipher_req.creq.dst = sg_dst;
- sg_ndex = sg_dst;
-
- get_pmem_file(areq->cipher_op_req.pmem.fd_dst, &paddr,
- &kvaddr, &len, &file_dst);
- for (i = 0; i < areq->cipher_op_req.entries; i++)
- sg_set_buf(sg_ndex++,
- ((uint8_t *)(areq->cipher_op_req.pmem.dst[i].offset)
- + kvaddr), areq->cipher_op_req.pmem.dst[i].len);
- sg_mark_end(--sg_ndex);
-
- for (i = 0; i < areq->cipher_op_req.entries; i++)
- areq->cipher_op_req.pmem.dst[i].offset +=
- (uint32_t)paddr;
- } else {
- areq->cipher_req.creq.dst = sg_src;
- for (i = 0; i < areq->cipher_op_req.entries; i++) {
- areq->cipher_op_req.pmem.dst[i].offset =
- areq->cipher_op_req.pmem.src[i].offset;
- areq->cipher_op_req.pmem.dst[i].len =
- areq->cipher_op_req.pmem.src[i].len;
- }
- }
-
- areq->cipher_req.creq.nbytes = areq->cipher_op_req.data_len;
- areq->cipher_req.creq.info = areq->cipher_op_req.iv;
-
- err = submit_req(areq, handle);
-
- kfree(sg_src);
- kfree(sg_dst);
-
- if (file_dst)
- put_pmem_file(file_dst);
- if (file_src)
- put_pmem_file(file_src);
-
- return err;
-};
-
-
-static int qcedev_pmem_ablk_cipher(struct qcedev_async_req *qcedev_areq,
- struct qcedev_handle *handle)
-{
- int err = 0;
- int i = 0;
- int j = 0;
- int k = 0;
- int num_entries = 0;
- uint32_t total = 0;
- struct qcedev_cipher_op_req *saved_req;
- struct qcedev_cipher_op_req *creq = &qcedev_areq->cipher_op_req;
-
- saved_req = kmalloc(sizeof(struct qcedev_cipher_op_req), GFP_KERNEL);
- if (saved_req == NULL) {
- pr_err(KERN_ERR "%s:Can't Allocate mem:saved_req 0x%x\n",
- __func__, (uint32_t)saved_req);
- return -ENOMEM;
- }
- memcpy(saved_req, creq, sizeof(struct qcedev_cipher_op_req));
-
- if (qcedev_areq->cipher_op_req.data_len > QCE_MAX_OPER_DATA) {
-
- struct qcedev_cipher_op_req req;
-
- /* save the original req structure */
- memcpy(&req, creq, sizeof(struct qcedev_cipher_op_req));
-
- i = 0;
- /* Address 32 KB at a time */
- while ((i < req.entries) && (err == 0)) {
- if (creq->pmem.src[i].len > QCE_MAX_OPER_DATA) {
- creq->pmem.src[0].len = QCE_MAX_OPER_DATA;
- if (i > 0) {
- creq->pmem.src[0].offset =
- creq->pmem.src[i].offset;
- }
-
- creq->data_len = QCE_MAX_OPER_DATA;
- creq->entries = 1;
-
- err =
- qcedev_pmem_ablk_cipher_max_xfer(qcedev_areq,
- handle);
-
- creq->pmem.src[i].len = req.pmem.src[i].len -
- QCE_MAX_OPER_DATA;
- creq->pmem.src[i].offset =
- req.pmem.src[i].offset +
- QCE_MAX_OPER_DATA;
- req.pmem.src[i].offset =
- creq->pmem.src[i].offset;
- req.pmem.src[i].len = creq->pmem.src[i].len;
- } else {
- total = 0;
- for (j = i; j < req.entries; j++) {
- num_entries++;
- if ((total + creq->pmem.src[j].len)
- >= QCE_MAX_OPER_DATA) {
- creq->pmem.src[j].len =
- QCE_MAX_OPER_DATA - total;
- total = QCE_MAX_OPER_DATA;
- break;
- }
- total += creq->pmem.src[j].len;
- }
-
- creq->data_len = total;
- if (i > 0)
- for (k = 0; k < num_entries; k++) {
- creq->pmem.src[k].len =
- creq->pmem.src[i+k].len;
- creq->pmem.src[k].offset =
- creq->pmem.src[i+k].offset;
- }
- creq->entries = num_entries;
-
- i = j;
- err =
- qcedev_pmem_ablk_cipher_max_xfer(qcedev_areq,
- handle);
- num_entries = 0;
-
- creq->pmem.src[i].offset =
- req.pmem.src[i].offset +
- creq->pmem.src[i].len;
- creq->pmem.src[i].len =
- req.pmem.src[i].len -
- creq->pmem.src[i].len;
- req.pmem.src[i].offset =
- creq->pmem.src[i].offset;
- req.pmem.src[i].len =
- creq->pmem.src[i].len;
-
- if (creq->pmem.src[i].len == 0)
- i++;
- }
-
- } /* end of while ((i < req.entries) && (err == 0)) */
-
- } else
- err = qcedev_pmem_ablk_cipher_max_xfer(qcedev_areq, handle);
-
- /* Restore the original req structure */
- for (i = 0; i < saved_req->entries; i++) {
- creq->pmem.src[i].len = saved_req->pmem.src[i].len;
- creq->pmem.src[i].offset = saved_req->pmem.src[i].offset;
- }
- creq->entries = saved_req->entries;
- creq->data_len = saved_req->data_len;
- kfree(saved_req);
-
- return err;
-
-}
-#else
-static int qcedev_pmem_ablk_cipher(struct qcedev_async_req *qcedev_areq,
- struct qcedev_handle *handle)
-{
- return -EPERM;
-}
-#endif/*CONFIG_ANDROID_PMEM*/
-
static int qcedev_vbuf_ablk_cipher_max_xfer(struct qcedev_async_req *areq,
int *di, struct qcedev_handle *handle,
uint8_t *k_align_src)
@@ -1753,6 +1533,10 @@
static int qcedev_check_cipher_params(struct qcedev_cipher_op_req *req,
struct qcedev_control *podev)
{
+ if (req->use_pmem) {
+ pr_err("%s: Use of PMEM is not supported\n", __func__);
+ goto error;
+ }
if ((req->entries == 0) || (req->data_len == 0))
goto error;
if ((req->alg >= QCEDEV_ALG_LAST) ||
@@ -1792,15 +1576,6 @@
if (req->byteoffset) {
if (req->mode != QCEDEV_AES_MODE_CTR)
goto error;
- else { /* if using CTR mode make sure not using Pmem */
- if (req->use_pmem)
- goto error;
- }
- }
- /* if using PMEM with non-zero byteoffset, ensure it is in_place_op */
- if (req->use_pmem) {
- if (!req->in_place_op)
- goto error;
}
/* Ensure zer ivlen for ECB mode */
if (req->ivlen != 0) {
@@ -1890,10 +1665,7 @@
podev))
return -EINVAL;
- if (qcedev_areq.cipher_op_req.use_pmem)
- err = qcedev_pmem_ablk_cipher(&qcedev_areq, handle);
- else
- err = qcedev_vbuf_ablk_cipher(&qcedev_areq, handle);
+ err = qcedev_vbuf_ablk_cipher(&qcedev_areq, handle);
if (err)
return err;
if (__copy_to_user((void __user *)arg,
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index b1a45bf..bf45a63 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -251,23 +251,19 @@
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
- result = kgsl_mmu_map_global(pagetable, &rb->buffer_desc,
- GSL_PT_PAGE_RV);
+ result = kgsl_mmu_map_global(pagetable, &rb->buffer_desc);
if (result)
goto error;
- result = kgsl_mmu_map_global(pagetable, &rb->memptrs_desc,
- GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
+ result = kgsl_mmu_map_global(pagetable, &rb->memptrs_desc);
if (result)
goto unmap_buffer_desc;
- result = kgsl_mmu_map_global(pagetable, &device->memstore,
- GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
+ result = kgsl_mmu_map_global(pagetable, &device->memstore);
if (result)
goto unmap_memptrs_desc;
- result = kgsl_mmu_map_global(pagetable, &device->mmu.setstate_memory,
- GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
+ result = kgsl_mmu_map_global(pagetable, &device->mmu.setstate_memory);
if (result)
goto unmap_memstore_desc;
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 5cdf911..69b34fa 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -485,6 +485,7 @@
*/
rb->sizedwords = KGSL_RB_SIZE >> 2;
+ rb->buffer_desc.flags = KGSL_MEMFLAGS_GPUREADONLY;
/* allocate memory for ringbuffer */
status = kgsl_allocate_contiguous(&rb->buffer_desc,
(rb->sizedwords << 2));
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 130474a..6e1ecd1 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -1871,10 +1871,7 @@
else if (entry->memdesc.size >= SZ_64K)
kgsl_memdesc_set_align(&entry->memdesc, ilog2(SZ_64));
- result = kgsl_mmu_map(private->pagetable,
- &entry->memdesc,
- GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
-
+ result = kgsl_mmu_map(private->pagetable, &entry->memdesc);
if (result)
goto error_put_file_ptr;
@@ -2065,8 +2062,7 @@
if (result)
return result;
- result = kgsl_mmu_map(private->pagetable, &entry->memdesc,
- kgsl_memdesc_protflags(&entry->memdesc));
+ result = kgsl_mmu_map(private->pagetable, &entry->memdesc);
if (result)
goto err;
@@ -2104,8 +2100,7 @@
goto err;
if (!kgsl_memdesc_use_cpu_map(&entry->memdesc)) {
- result = kgsl_mmu_map(private->pagetable, &entry->memdesc,
- kgsl_memdesc_protflags(&entry->memdesc));
+ result = kgsl_mmu_map(private->pagetable, &entry->memdesc);
if (result)
goto err;
}
@@ -2719,8 +2714,7 @@
if (kgsl_memdesc_use_cpu_map(&entry->memdesc)) {
entry->memdesc.gpuaddr = vma->vm_start;
- ret = kgsl_mmu_map(private->pagetable, &entry->memdesc,
- kgsl_memdesc_protflags(&entry->memdesc));
+ ret = kgsl_mmu_map(private->pagetable, &entry->memdesc);
if (ret) {
kgsl_mem_entry_put(entry);
return ret;
@@ -2753,6 +2747,29 @@
}
vma->vm_ops = &kgsl_gpumem_vm_ops;
+
+ if (cache == KGSL_CACHEMODE_WRITEBACK
+ || cache == KGSL_CACHEMODE_WRITETHROUGH) {
+ struct scatterlist *s;
+ int i;
+ int sglen = entry->memdesc.sglen;
+ unsigned long addr = vma->vm_start;
+
+ /* don't map in the guard page, it should always fault */
+ if (kgsl_memdesc_has_guard_page(&entry->memdesc))
+ sglen--;
+
+ for_each_sg(entry->memdesc.sg, s, sglen, i) {
+ int j;
+ for (j = 0; j < (sg_dma_len(s) >> PAGE_SHIFT); j++) {
+ struct page *page = sg_page(s);
+ page = nth_page(page, j);
+ vm_insert_page(vma, addr, page);
+ addr += PAGE_SIZE;
+ }
+ }
+ }
+
vma->vm_file = file;
entry->memdesc.useraddr = vma->vm_start;
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index 3eb8831..70a704b 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -149,6 +149,8 @@
#define KGSL_MEMDESC_GUARD_PAGE BIT(0)
/* Set if the memdesc is mapped into all pagetables */
#define KGSL_MEMDESC_GLOBAL BIT(1)
+/* The memdesc is frozen during a snapshot */
+#define KGSL_MEMDESC_FROZEN BIT(2)
/* shared memory allocation */
struct kgsl_memdesc {
@@ -175,15 +177,10 @@
#define KGSL_MEM_ENTRY_ION 4
#define KGSL_MEM_ENTRY_MAX 5
-/* List of flags */
-
-#define KGSL_MEM_ENTRY_FROZEN (1 << 0)
-
struct kgsl_mem_entry {
struct kref refcount;
struct kgsl_memdesc memdesc;
int memtype;
- int flags;
void *priv_data;
struct rb_node node;
unsigned int id;
diff --git a/drivers/gpu/msm/kgsl_drm.c b/drivers/gpu/msm/kgsl_drm.c
index c24e03b..11d6ffa 100644
--- a/drivers/gpu/msm/kgsl_drm.c
+++ b/drivers/gpu/msm/kgsl_drm.c
@@ -210,8 +210,7 @@
return result;
}
- result = kgsl_mmu_map(priv->pagetable, &priv->memdesc,
- GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
+ result = kgsl_mmu_map(priv->pagetable, &priv->memdesc);
if (result) {
DRM_ERROR(
"kgsl_mmu_map failed. result = %d\n", result);
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index df8e1d0..93b7e5d 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -43,6 +43,8 @@
{ 0x820, 0, 0 }, /* RESUME */
{ 0x03C, 0, 0 }, /* TLBLKCR */
{ 0x818, 0, 0 }, /* V2PUR */
+ { 0x2C, 0, 0 }, /* FSYNR0 */
+ { 0x2C, 0, 0 }, /* FSYNR0 */
};
static struct kgsl_iommu_register_list kgsl_iommuv1_reg[KGSL_IOMMU_REG_MAX] = {
@@ -51,7 +53,11 @@
{ 0x28, 0x00FFFFFF, 14 }, /* TTBR1 */
{ 0x58, 0, 0 }, /* FSR */
{ 0x618, 0, 0 }, /* TLBIALL */
- { 0x008, 0, 0 } /* RESUME */
+ { 0x008, 0, 0 }, /* RESUME */
+ { 0, 0, 0 }, /* TLBLKCR */
+ { 0, 0, 0 }, /* V2PUR */
+ { 0x68, 0, 0 }, /* FSYNR0 */
+ { 0x6C, 0, 0 } /* FSYNR1 */
};
struct remote_iommu_petersons_spinlock kgsl_iommu_sync_lock_vars;
@@ -118,6 +124,7 @@
unsigned int gpuaddr;
unsigned int size;
unsigned int flags;
+ unsigned int priv;
pid_t pid;
};
@@ -146,7 +153,8 @@
if (entry->memdesc.gpuaddr > ret->gpuaddr) {
ret->gpuaddr = entry->memdesc.gpuaddr;
ret->size = entry->memdesc.size;
- ret->flags = entry->flags;
+ ret->flags = entry->memdesc.flags;
+ ret->priv = entry->memdesc.priv;
ret->pid = priv->pid;
}
@@ -179,7 +187,8 @@
if (entry->memdesc.gpuaddr < ret->gpuaddr) {
ret->gpuaddr = entry->memdesc.gpuaddr;
ret->size = entry->memdesc.size;
- ret->flags = entry->flags;
+ ret->flags = entry->memdesc.flags;
+ ret->priv = entry->memdesc.priv;
ret->pid = priv->pid;
}
@@ -224,9 +233,10 @@
kgsl_get_memory_usage(name, sizeof(name) - 1, entry->flags);
KGSL_LOG_DUMP(device,
- "[%8.8X - %8.8X] (pid = %d) (%s)\n",
+ "[%8.8X - %8.8X] %s (pid = %d) (%s)\n",
entry->gpuaddr,
entry->gpuaddr + entry->size,
+ entry->priv & KGSL_MEMDESC_GUARD_PAGE ? "(+guard)" : "",
entry->pid, name);
}
@@ -275,6 +285,8 @@
unsigned int pid;
struct _mem_entry prev, next;
+ unsigned int fsynr0, fsynr1;
+ int write;
ret = get_iommu_unit(dev, &mmu, &iommu_unit);
if (ret)
@@ -292,12 +304,25 @@
fsr = KGSL_IOMMU_GET_CTX_REG(iommu, iommu_unit,
iommu_dev->ctx_id, FSR);
+ fsynr0 = KGSL_IOMMU_GET_CTX_REG(iommu, iommu_unit,
+ iommu_dev->ctx_id, FSYNR0);
+ fsynr1 = KGSL_IOMMU_GET_CTX_REG(iommu, iommu_unit,
+ iommu_dev->ctx_id, FSYNR1);
+
+ if (msm_soc_version_supports_iommu_v0())
+ write = ((fsynr1 & (KGSL_IOMMU_FSYNR1_AWRITE_MASK <<
+ KGSL_IOMMU_FSYNR1_AWRITE_SHIFT)) ? 1 : 0);
+ else
+ write = ((fsynr0 & (KGSL_IOMMU_V1_FSYNR0_WNR_MASK <<
+ KGSL_IOMMU_V1_FSYNR0_WNR_SHIFT)) ? 1 : 0);
pid = kgsl_mmu_get_ptname_from_ptbase(mmu, ptbase);
KGSL_MEM_CRIT(iommu_dev->kgsldev,
"GPU PAGE FAULT: addr = %lX pid = %d\n", addr, pid);
- KGSL_MEM_CRIT(iommu_dev->kgsldev, "context = %d FSR = %X\n",
- iommu_dev->ctx_id, fsr);
+ KGSL_MEM_CRIT(iommu_dev->kgsldev,
+ "context = %d FSR = %X FSYNR0 = %X FSYNR1 = %X(%s fault)\n",
+ iommu_dev->ctx_id, fsr, fsynr0, fsynr1,
+ write ? "write" : "read");
_check_if_freed(iommu_dev, addr, pid);
@@ -321,7 +346,8 @@
iommu_dev->fault = 1;
trace_kgsl_mmu_pagefault(iommu_dev->kgsldev, addr,
- kgsl_mmu_get_ptname_from_ptbase(mmu, ptbase), 0);
+ kgsl_mmu_get_ptname_from_ptbase(mmu, ptbase),
+ write ? "write" : "read");
/*
* We do not want the h/w to resume fetching data from an iommu unit
@@ -1118,16 +1144,14 @@
for (i = 0; i < iommu->unit_count; i++) {
status = kgsl_mmu_map_global(pt,
- &(iommu->iommu_units[i].reg_map),
- GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
+ &(iommu->iommu_units[i].reg_map));
if (status)
goto err;
}
/* Map Lock variables to GPU pagetable */
if (iommu->sync_lock_initialized) {
- status = kgsl_mmu_map_global(pt, &iommu->sync_lock_desc,
- GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
+ status = kgsl_mmu_map_global(pt, &iommu->sync_lock_desc);
if (status)
goto err;
}
@@ -1499,25 +1523,39 @@
unsigned int iommu_virt_addr;
struct kgsl_iommu_pt *iommu_pt = mmu_specific_pt;
int size = kgsl_sg_size(memdesc->sg, memdesc->sglen);
- unsigned int iommu_flags = IOMMU_READ;
BUG_ON(NULL == iommu_pt);
- if (protflags & GSL_PT_PAGE_WV)
- iommu_flags |= IOMMU_WRITE;
+ /* if there's a guard page, we'll map it read only below */
+ if ((protflags & IOMMU_WRITE) && kgsl_memdesc_has_guard_page(memdesc))
+ size -= PAGE_SIZE;
iommu_virt_addr = memdesc->gpuaddr;
ret = iommu_map_range(iommu_pt->domain, iommu_virt_addr, memdesc->sg,
- size, iommu_flags);
+ size, protflags);
if (ret) {
- KGSL_CORE_ERR("iommu_map_range(%p, %x, %p, %d, %d) "
- "failed with err: %d\n", iommu_pt->domain,
- iommu_virt_addr, memdesc->sg, size,
- iommu_flags, ret);
+ KGSL_CORE_ERR("iommu_map_range(%p, %x, %p, %d, %x) err: %d\n",
+ iommu_pt->domain, iommu_virt_addr, memdesc->sg, size,
+ protflags, ret);
return ret;
}
+ if ((protflags & IOMMU_WRITE) && kgsl_memdesc_has_guard_page(memdesc)) {
+ struct scatterlist *sg = &memdesc->sg[memdesc->sglen - 1];
+ ret = iommu_map(iommu_pt->domain, iommu_virt_addr + size,
+ kgsl_get_sg_pa(sg), PAGE_SIZE,
+ protflags & ~IOMMU_WRITE);
+ if (ret) {
+ KGSL_CORE_ERR("iommu_map(%p, %x, %x, %x) err: %d\n",
+ iommu_pt->domain, iommu_virt_addr + size,
+ kgsl_get_sg_pa(sg), protflags & ~IOMMU_WRITE,
+ ret);
+ /* cleanup the partial mapping */
+ iommu_unmap_range(iommu_pt->domain, iommu_virt_addr,
+ size);
+ }
+ }
return ret;
}
diff --git a/drivers/gpu/msm/kgsl_iommu.h b/drivers/gpu/msm/kgsl_iommu.h
index bf40113..c09bc4b 100644
--- a/drivers/gpu/msm/kgsl_iommu.h
+++ b/drivers/gpu/msm/kgsl_iommu.h
@@ -19,7 +19,7 @@
#define KGSL_IOMMU_CTX_OFFSET_V1 0x8000
#define KGSL_IOMMU_CTX_SHIFT 12
-/* TLBLKCR feilds */
+/* TLBLKCR fields */
#define KGSL_IOMMU_TLBLKCR_LKE_MASK 0x00000001
#define KGSL_IOMMU_TLBLKCR_LKE_SHIFT 0
#define KGSL_IOMMU_TLBLKCR_TLBIALLCFG_MASK 0x00000001
@@ -33,12 +33,19 @@
#define KGSL_IOMMU_TLBLKCR_VICTIM_MASK 0x000000FF
#define KGSL_IOMMU_TLBLKCR_VICTIM_SHIFT 16
-/* V2PXX feilds */
+/* V2PXX fields */
#define KGSL_IOMMU_V2PXX_INDEX_MASK 0x000000FF
#define KGSL_IOMMU_V2PXX_INDEX_SHIFT 0
#define KGSL_IOMMU_V2PXX_VA_MASK 0x000FFFFF
#define KGSL_IOMMU_V2PXX_VA_SHIFT 12
+/* FSYNR1 V0 fields */
+#define KGSL_IOMMU_FSYNR1_AWRITE_MASK 0x00000001
+#define KGSL_IOMMU_FSYNR1_AWRITE_SHIFT 8
+/* FSYNR0 V1 fields */
+#define KGSL_IOMMU_V1_FSYNR0_WNR_MASK 0x00000001
+#define KGSL_IOMMU_V1_FSYNR0_WNR_SHIFT 4
+
enum kgsl_iommu_reg_map {
KGSL_IOMMU_GLOBAL_BASE = 0,
KGSL_IOMMU_CTX_TTBR0,
@@ -48,6 +55,8 @@
KGSL_IOMMU_CTX_RESUME,
KGSL_IOMMU_CTX_TLBLKCR,
KGSL_IOMMU_CTX_V2PUR,
+ KGSL_IOMMU_CTX_FSYNR0,
+ KGSL_IOMMU_CTX_FSYNR1,
KGSL_IOMMU_REG_MAX
};
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index f71cf8c..83cf83d 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -580,13 +580,13 @@
int
kgsl_mmu_map(struct kgsl_pagetable *pagetable,
- struct kgsl_memdesc *memdesc,
- unsigned int protflags)
+ struct kgsl_memdesc *memdesc)
{
int ret;
struct gen_pool *pool = NULL;
int size;
int page_align = ilog2(PAGE_SIZE);
+ unsigned int protflags = kgsl_memdesc_protflags(memdesc);
if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE) {
if (memdesc->sglen == 1) {
@@ -738,7 +738,7 @@
EXPORT_SYMBOL(kgsl_mmu_unmap);
int kgsl_mmu_map_global(struct kgsl_pagetable *pagetable,
- struct kgsl_memdesc *memdesc, unsigned int protflags)
+ struct kgsl_memdesc *memdesc)
{
int result = -EINVAL;
unsigned int gpuaddr = 0;
@@ -750,11 +750,10 @@
/* Not all global mappings are needed for all MMU types */
if (!memdesc->size)
return 0;
-
gpuaddr = memdesc->gpuaddr;
memdesc->priv |= KGSL_MEMDESC_GLOBAL;
- result = kgsl_mmu_map(pagetable, memdesc, protflags);
+ result = kgsl_mmu_map(pagetable, memdesc);
if (result)
goto error;
diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h
index 2b33baf..0458a13 100644
--- a/drivers/gpu/msm/kgsl_mmu.h
+++ b/drivers/gpu/msm/kgsl_mmu.h
@@ -201,10 +201,9 @@
int kgsl_mmu_start(struct kgsl_device *device);
int kgsl_mmu_close(struct kgsl_device *device);
int kgsl_mmu_map(struct kgsl_pagetable *pagetable,
- struct kgsl_memdesc *memdesc,
- unsigned int protflags);
+ struct kgsl_memdesc *memdesc);
int kgsl_mmu_map_global(struct kgsl_pagetable *pagetable,
- struct kgsl_memdesc *memdesc, unsigned int protflags);
+ struct kgsl_memdesc *memdesc);
int kgsl_mmu_unmap(struct kgsl_pagetable *pagetable,
struct kgsl_memdesc *memdesc);
unsigned int kgsl_virtaddr_to_physaddr(void *virtaddr);
diff --git a/drivers/gpu/msm/kgsl_sharedmem.h b/drivers/gpu/msm/kgsl_sharedmem.h
index 27b9151..279490f 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.h
+++ b/drivers/gpu/msm/kgsl_sharedmem.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -19,6 +19,7 @@
#include "kgsl_mmu.h"
#include <linux/slab.h>
#include <linux/kmemleak.h>
+#include <linux/iommu.h>
#include "kgsl_log.h"
@@ -195,15 +196,24 @@
/*
* kgsl_memdesc_protflags - get mmu protection flags
* @memdesc - the memdesc
- * Returns a mask of GSL_PT_PAGE* values based on the
- * memdesc flags.
+ * Returns a mask of GSL_PT_PAGE* or IOMMU* values based
+ * on the memdesc flags.
*/
static inline unsigned int
kgsl_memdesc_protflags(const struct kgsl_memdesc *memdesc)
{
- unsigned int protflags = GSL_PT_PAGE_RV;
- if (!(memdesc->flags & KGSL_MEMFLAGS_GPUREADONLY))
- protflags |= GSL_PT_PAGE_WV;
+ unsigned int protflags = 0;
+ enum kgsl_mmutype mmutype = kgsl_mmu_get_mmutype();
+
+ if (mmutype == KGSL_MMU_TYPE_GPU) {
+ protflags = GSL_PT_PAGE_RV;
+ if (!(memdesc->flags & KGSL_MEMFLAGS_GPUREADONLY))
+ protflags |= GSL_PT_PAGE_WV;
+ } else if (mmutype == KGSL_MMU_TYPE_IOMMU) {
+ protflags = IOMMU_READ;
+ if (!(memdesc->flags & KGSL_MEMFLAGS_GPUREADONLY))
+ protflags |= IOMMU_WRITE;
+ }
return protflags;
}
@@ -248,8 +258,7 @@
ret = kgsl_sharedmem_page_alloc(memdesc, pagetable, size);
if (ret)
return ret;
- ret = kgsl_mmu_map(pagetable, memdesc,
- kgsl_memdesc_protflags(memdesc));
+ ret = kgsl_mmu_map(pagetable, memdesc);
if (ret)
kgsl_sharedmem_free(memdesc);
return ret;
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index 0935f64..c4647a1 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -283,7 +283,7 @@
{
list_del(&obj->node);
- obj->entry->flags &= ~KGSL_MEM_ENTRY_FROZEN;
+ obj->entry->memdesc.priv &= ~KGSL_MEMDESC_FROZEN;
kgsl_mem_entry_put(obj->entry);
kfree(obj);
@@ -416,10 +416,10 @@
* 0 so it doesn't get counted twice
*/
- if (entry->flags & KGSL_MEM_ENTRY_FROZEN)
+ if (entry->memdesc.priv & KGSL_MEMDESC_FROZEN)
return 0;
- entry->flags |= KGSL_MEM_ENTRY_FROZEN;
+ entry->memdesc.priv |= KGSL_MEMDESC_FROZEN;
return entry->memdesc.size;
}
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index e578b0e..f0410d6 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -244,20 +244,17 @@
int result = 0;
struct z180_device *z180_dev = Z180_DEVICE(device);
- result = kgsl_mmu_map_global(pagetable, &device->mmu.setstate_memory,
- GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
+ result = kgsl_mmu_map_global(pagetable, &device->mmu.setstate_memory);
if (result)
goto error;
- result = kgsl_mmu_map_global(pagetable, &device->memstore,
- GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
+ result = kgsl_mmu_map_global(pagetable, &device->memstore);
if (result)
goto error_unmap_dummy;
result = kgsl_mmu_map_global(pagetable,
- &z180_dev->ringbuffer.cmdbufdesc,
- GSL_PT_PAGE_RV);
+ &z180_dev->ringbuffer.cmdbufdesc);
if (result)
goto error_unmap_memstore;
/*
@@ -498,6 +495,7 @@
struct z180_device *z180_dev = Z180_DEVICE(device);
memset(&z180_dev->ringbuffer, 0, sizeof(struct z180_ringbuffer));
z180_dev->ringbuffer.prevctx = Z180_INVALID_CONTEXT;
+ z180_dev->ringbuffer.cmdbufdesc.flags = KGSL_MEMFLAGS_GPUREADONLY;
return kgsl_allocate_contiguous(&z180_dev->ringbuffer.cmdbufdesc,
Z180_RB_SIZE);
}
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 8c30b6c..1b7ecf0 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -164,6 +164,11 @@
}
qinfo = (struct vidc_iface_q_info *) info;
+ if (!qinfo || !qinfo->q_array.align_virtual_addr) {
+ dprintk(VIDC_WARN, "Queues have already been freed\n");
+ return -EINVAL;
+ }
+
venus_hfi_sim_modify_cmd_packet(packet);
queue = (struct hfi_queue_header *) qinfo->q_hdr;
@@ -282,6 +287,10 @@
}
qinfo = (struct vidc_iface_q_info *) info;
+ if (!qinfo || !qinfo->q_array.align_virtual_addr) {
+ dprintk(VIDC_WARN, "Queues have already been freed\n");
+ return -EINVAL;
+ }
queue = (struct hfi_queue_header *) qinfo->q_hdr;
if (!queue) {
@@ -634,6 +643,8 @@
int num_entries = sizeof(venus_qdss_entries)/(2 * sizeof(u32));
int domain, partition;
+ mutex_lock(&device->write_lock);
+ mutex_lock(&device->read_lock);
if (device->qdss.mem_data) {
qdss = (struct hfi_mem_map_table *)
device->qdss.align_virtual_addr;
@@ -674,6 +685,8 @@
msm_smem_delete_client(device->hal_client);
device->hal_client = NULL;
+ mutex_unlock(&device->read_lock);
+ mutex_unlock(&device->write_lock);
}
static int venus_hfi_get_qdss_iommu_virtual_addr(struct hfi_mem_map *mem_map,
int domain, int partition)
@@ -937,7 +950,6 @@
}
dev->intr_status = 0;
- enable_irq(dev->hal_data->irq);
INIT_LIST_HEAD(&dev->sess_head);
mutex_init(&dev->read_lock);
mutex_init(&dev->write_lock);
@@ -966,6 +978,7 @@
rc = -EEXIST;
goto err_core_init;
}
+ enable_irq(dev->hal_data->irq);
venus_hfi_write_register(dev->hal_data->register_base_addr,
VIDC_CTRL_INIT, 0x1, 0);
rc = venus_hfi_core_start_cpu(dev);
diff --git a/drivers/platform/msm/Kconfig b/drivers/platform/msm/Kconfig
index 46b4651..88e8d43 100644
--- a/drivers/platform/msm/Kconfig
+++ b/drivers/platform/msm/Kconfig
@@ -91,6 +91,16 @@
in the kernel log along with the PMIC option status. The PMIC
type is mapped to a Qualcomm chip part number and logged as well.
+config QPNP_COINCELL
+ tristate "Qualcomm QPNP coincell charger support"
+ depends on SPMI && OF_SPMI
+ help
+ This driver supports the QPNP coincell peripheral found inside of
+ Qualcomm QPNP PMIC devices. The coincell charger provides a means to
+ charge a coincell battery or backup capacitor which is used to
+ maintain PMIC register state when the main battery is removed from the
+ mobile device.
+
config IPA
tristate "IPA support"
depends on SPS
diff --git a/drivers/platform/msm/Makefile b/drivers/platform/msm/Makefile
index 6b9c5ad..efb78e5 100644
--- a/drivers/platform/msm/Makefile
+++ b/drivers/platform/msm/Makefile
@@ -9,6 +9,7 @@
obj-$(CONFIG_QPNP_POWER_ON) += qpnp-power-on.o
obj-$(CONFIG_QPNP_VIBRATOR) += qpnp-vibrator.o
obj-$(CONFIG_QPNP_CLKDIV) += qpnp-clkdiv.o
+obj-$(CONFIG_QPNP_COINCELL) += qpnp-coincell.o
obj-$(CONFIG_MSM_AVTIMER) += avtimer.o
obj-$(CONFIG_SSM) += ssm.o
obj-$(CONFIG_QPNP_REVID) += qpnp-revid.o
diff --git a/drivers/platform/msm/ipa/ipa.c b/drivers/platform/msm/ipa/ipa.c
index 1142094..42a0016 100644
--- a/drivers/platform/msm/ipa/ipa.c
+++ b/drivers/platform/msm/ipa/ipa.c
@@ -1919,22 +1919,26 @@
ipa_ctx->aggregation_byte_limit = 1;
ipa_ctx->aggregation_time_limit = 0;
- /* Initialize IPA RM (resource manager) */
- result = ipa_rm_initialize();
- if (result) {
- IPAERR(":cdev_add err=%d\n", -result);
- result = -ENODEV;
- goto fail_ipa_rm_init;
+ if (ipa_ctx->ipa_hw_mode != IPA_HW_MODE_PCIE) {
+ /* Initialize IPA RM (resource manager) */
+ result = ipa_rm_initialize();
+ if (result) {
+ IPAERR(":cdev_add err=%d\n", -result);
+ result = -ENODEV;
+ goto fail_ipa_rm_init;
+ }
}
- a2_mux_init();
+ if (ipa_ctx->ipa_hw_mode == IPA_HW_MODE_NORMAL) {
+ a2_mux_init();
- /* Initialize the tethering bridge driver */
- result = teth_bridge_driver_init();
- if (result) {
- IPAERR(":teth_bridge_driver_init() failed\n");
- result = -ENODEV;
- goto fail_cdev_add;
+ /* Initialize the tethering bridge driver */
+ result = teth_bridge_driver_init();
+ if (result) {
+ IPAERR(":teth_bridge_driver_init() failed\n");
+ result = -ENODEV;
+ goto fail_cdev_add;
+ }
}
/* gate IPA clocks */
diff --git a/drivers/platform/msm/ipa/teth_bridge.c b/drivers/platform/msm/ipa/teth_bridge.c
index 76e2eee..29253cd 100644
--- a/drivers/platform/msm/ipa/teth_bridge.c
+++ b/drivers/platform/msm/ipa/teth_bridge.c
@@ -69,6 +69,11 @@
bool device_mac_addr_known;
};
+struct stats {
+ u64 a2_to_usb_num_sw_tx_packets;
+ u64 usb_to_a2_num_sw_tx_packets;
+};
+
struct teth_bridge_ctx {
struct class *class;
dev_t dev_num;
@@ -90,6 +95,7 @@
struct work_struct comp_hw_bridge_work;
bool comp_hw_bridge_in_progress;
struct teth_aggr_capabilities *aggr_caps;
+ struct stats stats;
};
static struct teth_bridge_ctx *teth_ctx;
@@ -806,6 +812,7 @@
&teth_ctx->mac_addresses.device_mac_addr_known);
/* Send the packet to A2, using a2_service driver API */
+ teth_ctx->stats.usb_to_a2_num_sw_tx_packets++;
res = a2_mux_write(A2_MUX_TETHERED_0, skb);
if (res) {
TETH_ERR("Packet send failure, dropping packet !\n");
@@ -843,6 +850,7 @@
mac_addresses.host_pc_mac_addr_known);
/* Send the packet to USB */
+ teth_ctx->stats.a2_to_usb_num_sw_tx_packets++;
res = ipa_tx_dp(IPA_CLIENT_USB_CONS, skb, NULL);
if (res) {
TETH_ERR("Packet send failure, dropping packet !\n");
@@ -1216,6 +1224,8 @@
static struct dentry *dfile_link_protocol;
static struct dentry *dfile_get_aggr_params;
static struct dentry *dfile_set_aggr_protocol;
+static struct dentry *dfile_stats;
+static struct dentry *dfile_is_hw_bridge_complete;
static ssize_t teth_debugfs_read_link_protocol(struct file *file,
char __user *ubuf,
@@ -1351,6 +1361,43 @@
return count;
}
+static ssize_t teth_debugfs_stats(struct file *file,
+ char __user *ubuf,
+ size_t count,
+ loff_t *ppos)
+{
+ int nbytes = 0;
+
+ nbytes += scnprintf(&dbg_buff[nbytes],
+ TETH_MAX_MSG_LEN - nbytes,
+ "USB to A2 SW Tx packets: %lld\n",
+ teth_ctx->stats.usb_to_a2_num_sw_tx_packets);
+ nbytes += scnprintf(&dbg_buff[nbytes],
+ TETH_MAX_MSG_LEN - nbytes,
+ "A2 to USB SW Tx packets: %lld\n",
+ teth_ctx->stats.a2_to_usb_num_sw_tx_packets);
+ return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, nbytes);
+}
+
+static ssize_t teth_debugfs_hw_bridge_status(struct file *file,
+ char __user *ubuf,
+ size_t count,
+ loff_t *ppos)
+{
+ int nbytes = 0;
+
+ if (teth_ctx->is_hw_bridge_complete)
+ nbytes += scnprintf(&dbg_buff[nbytes],
+ TETH_MAX_MSG_LEN - nbytes,
+ "HW bridge is in use.\n");
+ else
+ nbytes += scnprintf(&dbg_buff[nbytes],
+ TETH_MAX_MSG_LEN - nbytes,
+ "SW bridge is in use. HW bridge not complete yet.\n");
+
+ return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, nbytes);
+}
+
const struct file_operations teth_link_protocol_ops = {
.read = teth_debugfs_read_link_protocol,
.write = teth_debugfs_write_link_protocol,
@@ -1364,6 +1411,14 @@
.write = teth_debugfs_set_aggr_protocol,
};
+const struct file_operations teth_stats_ops = {
+ .read = teth_debugfs_stats,
+};
+
+const struct file_operations teth_hw_bridge_status_ops = {
+ .read = teth_debugfs_hw_bridge_status,
+};
+
void teth_debugfs_init(void)
{
const mode_t read_only_mode = S_IRUSR | S_IRGRP | S_IROTH;
@@ -1400,6 +1455,23 @@
goto fail;
}
+ dfile_stats =
+ debugfs_create_file("stats", read_only_mode, dent,
+ 0, &teth_stats_ops);
+ if (!dfile_stats || IS_ERR(dfile_stats)) {
+ IPAERR("fail to create file stats\n");
+ goto fail;
+ }
+
+ dfile_is_hw_bridge_complete =
+ debugfs_create_file("is_hw_bridge_complete", read_only_mode,
+ dent, 0, &teth_hw_bridge_status_ops);
+ if (!dfile_is_hw_bridge_complete ||
+ IS_ERR(dfile_is_hw_bridge_complete)) {
+ IPAERR("fail to create file is_hw_bridge_complete\n");
+ goto fail;
+ }
+
return;
fail:
debugfs_remove_recursive(dent);
diff --git a/drivers/platform/msm/qpnp-coincell.c b/drivers/platform/msm/qpnp-coincell.c
new file mode 100644
index 0000000..e08fd7d
--- /dev/null
+++ b/drivers/platform/msm/qpnp-coincell.c
@@ -0,0 +1,266 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/spmi.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#define QPNP_COINCELL_DRIVER_NAME "qcom,qpnp-coincell"
+
+struct qpnp_coincell {
+ struct spmi_device *spmi_dev;
+ u16 base_addr;
+};
+
+#define QPNP_COINCELL_REG_TYPE 0x04
+#define QPNP_COINCELL_REG_SUBTYPE 0x05
+#define QPNP_COINCELL_REG_RSET 0x44
+#define QPNP_COINCELL_REG_VSET 0x45
+#define QPNP_COINCELL_REG_ENABLE 0x46
+
+#define QPNP_COINCELL_TYPE 0x02
+#define QPNP_COINCELL_SUBTYPE 0x20
+#define QPNP_COINCELL_ENABLE 0x80
+#define QPNP_COINCELL_DISABLE 0x00
+
+static const int qpnp_rset_map[] = {2100, 1700, 1200, 800};
+static const int qpnp_vset_map[] = {2500, 3200, 3100, 3000};
+
+static int qpnp_coincell_set_resistance(struct qpnp_coincell *chip, int rset)
+{
+ int i, rc;
+ u8 reg;
+
+ for (i = 0; i < ARRAY_SIZE(qpnp_rset_map); i++)
+ if (rset == qpnp_rset_map[i])
+ break;
+
+ if (i >= ARRAY_SIZE(qpnp_rset_map)) {
+ pr_err("invalid rset=%d value\n", rset);
+ return -EINVAL;
+ }
+
+ reg = i;
+ rc = spmi_ext_register_writel(chip->spmi_dev->ctrl, chip->spmi_dev->sid,
+ chip->base_addr + QPNP_COINCELL_REG_RSET, ®, 1);
+ if (rc)
+ dev_err(&chip->spmi_dev->dev, "%s: could not write to RSET register, rc=%d\n",
+ __func__, rc);
+
+ return rc;
+}
+
+static int qpnp_coincell_set_voltage(struct qpnp_coincell *chip, int vset)
+{
+ int i, rc;
+ u8 reg;
+
+ for (i = 0; i < ARRAY_SIZE(qpnp_vset_map); i++)
+ if (vset == qpnp_vset_map[i])
+ break;
+
+ if (i >= ARRAY_SIZE(qpnp_vset_map)) {
+ pr_err("invalid vset=%d value\n", vset);
+ return -EINVAL;
+ }
+
+ reg = i;
+ rc = spmi_ext_register_writel(chip->spmi_dev->ctrl, chip->spmi_dev->sid,
+ chip->base_addr + QPNP_COINCELL_REG_VSET, ®, 1);
+ if (rc)
+ dev_err(&chip->spmi_dev->dev, "%s: could not write to VSET register, rc=%d\n",
+ __func__, rc);
+
+ return rc;
+}
+
+static int qpnp_coincell_set_charge(struct qpnp_coincell *chip, bool enabled)
+{
+ int rc;
+ u8 reg;
+
+ reg = enabled ? QPNP_COINCELL_ENABLE : QPNP_COINCELL_DISABLE;
+ rc = spmi_ext_register_writel(chip->spmi_dev->ctrl, chip->spmi_dev->sid,
+ chip->base_addr + QPNP_COINCELL_REG_ENABLE, ®, 1);
+ if (rc)
+ dev_err(&chip->spmi_dev->dev, "%s: could not write to ENABLE register, rc=%d\n",
+ __func__, rc);
+
+ return rc;
+}
+
+static void qpnp_coincell_charger_show_state(struct qpnp_coincell *chip)
+{
+ int rc, rset, vset, temp;
+ bool enabled;
+ u8 reg[QPNP_COINCELL_REG_ENABLE - QPNP_COINCELL_REG_RSET + 1];
+
+ rc = spmi_ext_register_readl(chip->spmi_dev->ctrl, chip->spmi_dev->sid,
+ chip->base_addr + QPNP_COINCELL_REG_RSET, reg, ARRAY_SIZE(reg));
+ if (rc) {
+ dev_err(&chip->spmi_dev->dev, "%s: could not read RSET register, rc=%d\n",
+ __func__, rc);
+ return;
+ }
+
+ temp = reg[QPNP_COINCELL_REG_RSET - QPNP_COINCELL_REG_RSET];
+ if (temp >= ARRAY_SIZE(qpnp_rset_map)) {
+ dev_err(&chip->spmi_dev->dev, "unknown RSET=0x%02X register value\n",
+ temp);
+ return;
+ }
+ rset = qpnp_rset_map[temp];
+
+ temp = reg[QPNP_COINCELL_REG_VSET - QPNP_COINCELL_REG_RSET];
+ if (temp >= ARRAY_SIZE(qpnp_vset_map)) {
+ dev_err(&chip->spmi_dev->dev, "unknown VSET=0x%02X register value\n",
+ temp);
+ return;
+ }
+ vset = qpnp_vset_map[temp];
+
+ temp = reg[QPNP_COINCELL_REG_ENABLE - QPNP_COINCELL_REG_RSET];
+ enabled = temp & QPNP_COINCELL_ENABLE;
+
+ pr_info("enabled=%c, voltage=%d mV, resistance=%d ohm\n",
+ (enabled ? 'Y' : 'N'), vset, rset);
+}
+
+static int qpnp_coincell_check_type(struct qpnp_coincell *chip)
+{
+ int rc;
+ u8 type[2];
+
+ rc = spmi_ext_register_readl(chip->spmi_dev->ctrl, chip->spmi_dev->sid,
+ chip->base_addr + QPNP_COINCELL_REG_TYPE, type, 2);
+ if (rc) {
+ dev_err(&chip->spmi_dev->dev, "%s: could not read type register, rc=%d\n",
+ __func__, rc);
+ return rc;
+ }
+
+ if (type[0] != QPNP_COINCELL_TYPE || type[1] != QPNP_COINCELL_SUBTYPE) {
+ dev_err(&chip->spmi_dev->dev, "%s: invalid type=0x%02X or subtype=0x%02X register value\n",
+ __func__, type[0], type[1]);
+ return -ENODEV;
+ }
+
+ return rc;
+}
+
+static int qpnp_coincell_probe(struct spmi_device *spmi)
+{
+ struct device_node *node = spmi->dev.of_node;
+ struct qpnp_coincell *chip;
+ struct resource *res;
+ u32 temp;
+ int rc = 0;
+
+ if (!node) {
+ dev_err(&spmi->dev, "%s: device node missing\n", __func__);
+ return -ENODEV;
+ }
+
+ chip = devm_kzalloc(&spmi->dev, sizeof(*chip), GFP_KERNEL);
+ if (!chip) {
+ dev_err(&spmi->dev, "%s: cannot allocate qpnp_coincell\n",
+ __func__);
+ return -ENOMEM;
+ }
+ chip->spmi_dev = spmi;
+
+ res = spmi_get_resource(spmi, NULL, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&spmi->dev, "%s: node is missing base address\n",
+ __func__);
+ return -EINVAL;
+ }
+ chip->base_addr = res->start;
+
+ rc = qpnp_coincell_check_type(chip);
+ if (rc)
+ return rc;
+
+ rc = of_property_read_u32(node, "qcom,rset-ohms", &temp);
+ if (!rc) {
+ rc = qpnp_coincell_set_resistance(chip, temp);
+ if (rc)
+ return rc;
+ }
+
+ rc = of_property_read_u32(node, "qcom,vset-millivolts", &temp);
+ if (!rc) {
+ rc = qpnp_coincell_set_voltage(chip, temp);
+ if (rc)
+ return rc;
+ }
+
+ rc = of_property_read_u32(node, "qcom,charge-enable", &temp);
+ if (!rc) {
+ rc = qpnp_coincell_set_charge(chip, temp);
+ if (rc)
+ return rc;
+ }
+
+ qpnp_coincell_charger_show_state(chip);
+
+ return 0;
+}
+
+static int __devexit qpnp_coincell_remove(struct spmi_device *spmi)
+{
+ return 0;
+}
+
+static struct of_device_id qpnp_coincell_match_table[] = {
+ { .compatible = QPNP_COINCELL_DRIVER_NAME, },
+ {}
+};
+
+static const struct spmi_device_id qpnp_coincell_id[] = {
+ { QPNP_COINCELL_DRIVER_NAME, 0 },
+ {}
+};
+MODULE_DEVICE_TABLE(spmi, qpnp_coincell_id);
+
+static struct spmi_driver qpnp_coincell_driver = {
+ .driver = {
+ .name = QPNP_COINCELL_DRIVER_NAME,
+ .of_match_table = qpnp_coincell_match_table,
+ .owner = THIS_MODULE,
+ },
+ .probe = qpnp_coincell_probe,
+ .remove = __devexit_p(qpnp_coincell_remove),
+ .id_table = qpnp_coincell_id,
+};
+
+static int __init qpnp_coincell_init(void)
+{
+ return spmi_driver_register(&qpnp_coincell_driver);
+}
+
+static void __exit qpnp_coincell_exit(void)
+{
+ spmi_driver_unregister(&qpnp_coincell_driver);
+}
+
+MODULE_DESCRIPTION("QPNP PMIC coincell charger driver");
+MODULE_LICENSE("GPL v2");
+
+module_init(qpnp_coincell_init);
+module_exit(qpnp_coincell_exit);
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index bc2e2ae..0d161b7 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -432,6 +432,7 @@
tristate "QPNP Charger driver"
depends on SPMI
depends on OF_SPMI
+ depends on THERMAL_QPNP_ADC_TM
help
Say Y here to enable the switch mode battery charger
and boost device which supports USB detection and charging. The driver
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 7833afa..8789b19 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -171,17 +171,27 @@
* @boost_base: boost peripheral base address
* @misc_base: misc peripheral base address
* @freq_base: freq peripheral base address
+ * @bat_is_cool: indicates that battery is cool
+ * @bat_is_warm: indicates that battery is warm
* @chg_done: indicates that charging is completed
* @usb_present: present status of usb
* @dc_present: present status of dc
+ * @batt_present: present status of battery
* @use_default_batt_values: flag to report default battery properties
* @max_voltage_mv: the max volts the batt should be charged up to
* @min_voltage_mv: min battery voltage before turning the FET on
- * @resume_voltage_mv: voltage at which the battery resumes charging
+ * @max_bat_chg_current: maximum battery charge current in mA
+ * @warm_bat_chg_ma: warm battery maximum charge current in mA
+ * @cool_bat_chg_ma: cool battery maximum charge current in mA
+ * @warm_bat_mv: warm temperature battery target voltage
+ * @cool_bat_mv: cool temperature battery target voltage
+ * @resume_delta_mv: voltage delta at which battery resumes charging
* @term_current: the charging based term current
* @safe_current: battery safety current setting
* @maxinput_usb_ma: Maximum Input current USB
* @maxinput_dc_ma: Maximum Input current DC
+ * @warm_bat_degc Warm battery temperature in degree Celsius
+ * @cool_bat_degc Cool battery temperature in degree Celsius
* @revision: PMIC revision
* @thermal_levels amount of thermal mitigation levels
* @thermal_mitigation thermal mitigation level values
@@ -208,20 +218,32 @@
unsigned int usbin_valid_irq;
unsigned int dcin_valid_irq;
unsigned int chg_done_irq;
+ unsigned int chg_fastchg_irq;
+ unsigned int chg_trklchg_irq;
unsigned int chg_failed_irq;
+ unsigned int batt_pres_irq;
+ bool bat_is_cool;
+ bool bat_is_warm;
bool chg_done;
bool usb_present;
bool dc_present;
+ bool batt_present;
bool charging_disabled;
bool use_default_batt_values;
unsigned int max_bat_chg_current;
+ unsigned int warm_bat_chg_ma;
+ unsigned int cool_bat_chg_ma;
unsigned int safe_voltage_mv;
unsigned int max_voltage_mv;
unsigned int min_voltage_mv;
- unsigned int resume_voltage_mv;
+ unsigned int warm_bat_mv;
+ unsigned int cool_bat_mv;
+ unsigned int resume_delta_mv;
unsigned int term_current;
unsigned int maxinput_usb_ma;
unsigned int maxinput_dc_ma;
+ unsigned int warm_bat_degc;
+ unsigned int cool_bat_degc;
unsigned int safe_current;
unsigned int revision;
unsigned int thermal_levels;
@@ -232,6 +254,7 @@
struct power_supply *bms_psy;
struct power_supply batt_psy;
uint32_t flags;
+ struct qpnp_adc_tm_btm_param adc_param;
};
static struct of_device_id qpnp_charger_match_table[] = {
@@ -323,6 +346,23 @@
return (usb_otg_en & USB_OTG_EN_BIT) ? 1 : 0;
}
+static int
+qpnp_chg_is_batt_present(struct qpnp_chg_chip *chip)
+{
+ u8 batt_pres_rt_sts;
+ int rc;
+
+ rc = qpnp_chg_read(chip, &batt_pres_rt_sts,
+ INT_RT_STS(chip->bat_if_base), 1);
+ if (rc) {
+ pr_err("spmi read failed: addr=%03X, rc=%d\n",
+ INT_RT_STS(chip->bat_if_base), rc);
+ return rc;
+ }
+
+ return (batt_pres_rt_sts & BATT_PRES_IRQ) ? 1 : 0;
+}
+
#define USB_VALID_BIT BIT(7)
static int
qpnp_chg_is_usb_chg_plugged_in(struct qpnp_chg_chip *chip)
@@ -493,6 +533,23 @@
}
static irqreturn_t
+qpnp_chg_bat_if_batt_pres_irq_handler(int irq, void *_chip)
+{
+ struct qpnp_chg_chip *chip = _chip;
+ int batt_present;
+
+ batt_present = qpnp_chg_is_batt_present(chip);
+ pr_debug("batt-pres triggered: %d\n", batt_present);
+
+ if (chip->batt_present ^ batt_present) {
+ chip->batt_present = batt_present;
+ power_supply_changed(&chip->batt_psy);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t
qpnp_chg_dc_dcin_valid_irq_handler(int irq, void *_chip)
{
struct qpnp_chg_chip *chip = _chip;
@@ -527,12 +584,47 @@
}
static irqreturn_t
-qpnp_chg_chgr_chg_done_irq_handler(int irq, void *_chip)
+qpnp_chg_chgr_chg_trklchg_irq_handler(int irq, void *_chip)
{
struct qpnp_chg_chip *chip = _chip;
+ pr_debug("TRKL IRQ triggered\n");
+
+ chip->chg_done = false;
+ power_supply_changed(&chip->batt_psy);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t
+qpnp_chg_chgr_chg_fastchg_irq_handler(int irq, void *_chip)
+{
+ struct qpnp_chg_chip *chip = _chip;
+
+ pr_debug("FAST_CHG IRQ triggered\n");
+
+ chip->chg_done = false;
+ power_supply_changed(&chip->batt_psy);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t
+qpnp_chg_chgr_chg_done_irq_handler(int irq, void *_chip)
+{
+ struct qpnp_chg_chip *chip = _chip;
+ u8 chgr_sts;
+ int rc;
+
pr_debug("CHG_DONE IRQ triggered\n");
+
+ rc = qpnp_chg_read(chip, &chgr_sts,
+ INT_RT_STS(chip->chgr_base), 1);
+ if (rc)
+ pr_err("failed to read interrupt sts %d\n", rc);
+
chip->chg_done = true;
+ power_supply_changed(&chip->batt_psy);
return IRQ_HANDLED;
}
@@ -597,8 +689,8 @@
return rc;
}
-static
-int switch_usb_to_charge_mode(struct qpnp_chg_chip *chip)
+static int
+switch_usb_to_charge_mode(struct qpnp_chg_chip *chip)
{
int rc;
@@ -625,8 +717,8 @@
return 0;
}
-static
-int switch_usb_to_host_mode(struct qpnp_chg_chip *chip)
+static int
+switch_usb_to_host_mode(struct qpnp_chg_chip *chip)
{
int rc;
@@ -791,19 +883,16 @@
int rc;
u8 chgr_sts;
+ if (chip->chg_done)
+ return POWER_SUPPLY_STATUS_FULL;
+
rc = qpnp_chg_read(chip, &chgr_sts,
INT_RT_STS(chip->chgr_base), 1);
if (rc) {
pr_err("failed to read interrupt sts %d\n", rc);
- return POWER_SUPPLY_STATUS_DISCHARGING;
+ return POWER_SUPPLY_CHARGE_TYPE_NONE;
}
- pr_debug("chgr sts 0x%x\n", chgr_sts);
- if (chgr_sts & CHG_DONE_IRQ || chip->chg_done)
- return POWER_SUPPLY_STATUS_FULL;
- else
- chip->chg_done = false;
-
if (chgr_sts & TRKL_CHG_ON_IRQ)
return POWER_SUPPLY_STATUS_CHARGING;
if (chgr_sts & FAST_CHG_ON_IRQ)
@@ -1147,8 +1236,33 @@
temp = (voltage - QPNP_CHG_V_MIN_MV) / QPNP_CHG_V_STEP_MV;
pr_debug("voltage=%d setting %02x\n", voltage, temp);
- return qpnp_chg_write(chip, &temp,
- chip->chgr_base + CHGR_VDD_MAX, 1);
+ return qpnp_chg_write(chip, &temp, chip->chgr_base + CHGR_VDD_MAX, 1);
+}
+
+/* JEITA compliance logic */
+static void
+qpnp_chg_set_appropriate_vddmax(struct qpnp_chg_chip *chip)
+{
+ if (chip->bat_is_cool)
+ qpnp_chg_vddmax_set(chip, chip->cool_bat_mv);
+ else if (chip->bat_is_warm)
+ qpnp_chg_vddmax_set(chip, chip->warm_bat_mv);
+ else
+ qpnp_chg_vddmax_set(chip, chip->max_voltage_mv);
+}
+
+static void
+qpnp_chg_set_appropriate_vbatdet(struct qpnp_chg_chip *chip)
+{
+ if (chip->bat_is_cool)
+ qpnp_chg_vbatdet_set(chip, chip->cool_bat_mv
+ - chip->resume_delta_mv);
+ else if (chip->bat_is_warm)
+ qpnp_chg_vbatdet_set(chip, chip->warm_bat_mv
+ - chip->resume_delta_mv);
+ else
+ qpnp_chg_vbatdet_set(chip, chip->max_voltage_mv
+ - chip->resume_delta_mv);
}
static void
@@ -1156,6 +1270,12 @@
{
unsigned int chg_current = chip->max_bat_chg_current;
+ if (chip->bat_is_cool)
+ chg_current = min(chg_current, chip->cool_bat_chg_ma);
+
+ if (chip->bat_is_warm)
+ chg_current = min(chg_current, chip->warm_bat_chg_ma);
+
if (chip->therm_lvl_sel != 0 && chip->thermal_mitigation)
chg_current = min(chg_current,
chip->thermal_mitigation[chip->therm_lvl_sel]);
@@ -1181,6 +1301,58 @@
}
}
+#define TEMP_HYSTERISIS_DEGC 2
+static void
+qpnp_chg_adc_notification(enum qpnp_tm_state state, void *ctx)
+{
+ struct qpnp_chg_chip *chip = ctx;
+ bool bat_warm = 0, bat_cool = 0;
+
+ if (state >= ADC_TM_STATE_NUM) {
+ pr_err("invalid notification %d\n", state);
+ return;
+ }
+
+ pr_debug("state = %s\n", state == ADC_TM_HIGH_STATE ? "high" : "low");
+
+ if (state == ADC_TM_HIGH_STATE) {
+ if (!chip->bat_is_warm) {
+ bat_warm = true;
+ bat_cool = false;
+ chip->adc_param.low_temp =
+ chip->warm_bat_degc - TEMP_HYSTERISIS_DEGC;
+ } else if (chip->bat_is_cool) {
+ bat_warm = false;
+ bat_cool = false;
+ chip->adc_param.high_temp = chip->warm_bat_degc;
+ }
+ } else {
+ if (!chip->bat_is_cool) {
+ bat_cool = true;
+ bat_warm = false;
+ chip->adc_param.high_temp =
+ chip->cool_bat_degc + TEMP_HYSTERISIS_DEGC;
+ } else if (chip->bat_is_warm) {
+ bat_cool = false;
+ bat_warm = false;
+ chip->adc_param.low_temp = chip->cool_bat_degc;
+ }
+ }
+
+ if (chip->bat_is_cool ^ bat_cool || chip->bat_is_warm ^ bat_warm) {
+ /* set appropriate voltages and currents */
+ qpnp_chg_set_appropriate_vddmax(chip);
+ qpnp_chg_set_appropriate_battery_current(chip);
+ qpnp_chg_set_appropriate_vbatdet(chip);
+
+ chip->bat_is_cool = bat_cool;
+ chip->bat_is_warm = bat_warm;
+ }
+
+ /* re-arm ADC interrupt */
+ qpnp_adc_tm_btm_configure(&chip->adc_param);
+}
+
static int
qpnp_batt_power_set_property(struct power_supply *psy,
enum power_supply_property psp,
@@ -1231,20 +1403,37 @@
return -ENXIO;
}
+ chip->chg_fastchg_irq = spmi_get_irq_byname(chip->spmi,
+ spmi_resource, "fast-chg-on");
+ if (chip->chg_fastchg_irq < 0) {
+ pr_err("Unable to get fast-chg-on irq\n");
+ return -ENXIO;
+ }
+
+ chip->chg_trklchg_irq = spmi_get_irq_byname(chip->spmi,
+ spmi_resource, "trkl-chg-on");
+ if (chip->chg_trklchg_irq < 0) {
+ pr_err("Unable to get trkl-chg-on irq\n");
+ return -ENXIO;
+ }
+
chip->chg_failed_irq = spmi_get_irq_byname(chip->spmi,
spmi_resource, "chg-failed");
if (chip->chg_failed_irq < 0) {
pr_err("Unable to get chg_failed irq\n");
return -ENXIO;
}
+
rc |= devm_request_irq(chip->dev, chip->chg_done_irq,
qpnp_chg_chgr_chg_done_irq_handler,
- IRQF_TRIGGER_RISING, "chg_done", chip);
+ IRQF_TRIGGER_RISING,
+ "chg_done", chip);
if (rc < 0) {
pr_err("Can't request %d chg_done for chg: %d\n",
chip->chg_done_irq, rc);
return -ENXIO;
}
+
rc |= devm_request_irq(chip->dev, chip->chg_failed_irq,
qpnp_chg_chgr_chg_failed_irq_handler,
IRQF_TRIGGER_RISING, "chg_failed", chip);
@@ -1254,6 +1443,26 @@
return -ENXIO;
}
+ rc |= devm_request_irq(chip->dev, chip->chg_fastchg_irq,
+ qpnp_chg_chgr_chg_fastchg_irq_handler,
+ IRQF_TRIGGER_RISING,
+ "fast-chg-on", chip);
+ if (rc < 0) {
+ pr_err("Can't request %d fast-chg-on for chg: %d\n",
+ chip->chg_fastchg_irq, rc);
+ return -ENXIO;
+ }
+
+ rc |= devm_request_irq(chip->dev, chip->chg_trklchg_irq,
+ qpnp_chg_chgr_chg_trklchg_irq_handler,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ "fast-chg-on", chip);
+ if (rc < 0) {
+ pr_err("Can't request %d trkl-chg-on for chg: %d\n",
+ chip->chg_trklchg_irq, rc);
+ return -ENXIO;
+ }
+
rc = qpnp_chg_vinmin_set(chip, chip->min_voltage_mv);
if (rc) {
pr_debug("failed setting min_voltage rc=%d\n", rc);
@@ -1269,7 +1478,8 @@
pr_debug("failed setting safe_voltage rc=%d\n", rc);
return rc;
}
- rc = qpnp_chg_vbatdet_set(chip, chip->resume_voltage_mv);
+ rc = qpnp_chg_vbatdet_set(chip,
+ chip->max_voltage_mv - chip->resume_delta_mv);
if (rc) {
pr_debug("failed setting resume_voltage rc=%d\n", rc);
return rc;
@@ -1298,6 +1508,9 @@
CHGR_IBAT_TERM_CHGR,
0x80, 0x80, 1);
+ enable_irq_wake(chip->chg_fastchg_irq);
+ enable_irq_wake(chip->chg_trklchg_irq);
+ enable_irq_wake(chip->chg_failed_irq);
enable_irq_wake(chip->chg_done_irq);
break;
case SMBB_BUCK_SUBTYPE:
@@ -1313,6 +1526,23 @@
break;
case SMBB_BAT_IF_SUBTYPE:
case SMBBP_BAT_IF_SUBTYPE:
+ chip->batt_pres_irq = spmi_get_irq_byname(chip->spmi,
+ spmi_resource, "batt-pres");
+ if (chip->batt_pres_irq < 0) {
+ pr_err("Unable to get batt-pres irq\n");
+ return -ENXIO;
+ }
+ rc = devm_request_irq(chip->dev, chip->batt_pres_irq,
+ qpnp_chg_bat_if_batt_pres_irq_handler,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ "bat_if_batt_pres", chip);
+ if (rc < 0) {
+ pr_err("Can't request %d batt-pres irq for chg: %d\n",
+ chip->batt_pres_irq, rc);
+ return -ENXIO;
+ }
+
+ enable_irq_wake(chip->batt_pres_irq);
break;
case SMBB_USB_CHGPTH_SUBTYPE:
case SMBBP_USB_CHGPTH_SUBTYPE:
@@ -1427,7 +1657,7 @@
/* Get the vddmax property */
rc = of_property_read_u32(spmi->dev.of_node, "qcom,chg-vddmax-mv",
&chip->max_voltage_mv);
- if (rc && rc != -EINVAL) {
+ if (rc) {
pr_err("Error reading vddmax property %d\n", rc);
goto fail_chg_enable;
}
@@ -1435,7 +1665,7 @@
/* Get the vinmin property */
rc = of_property_read_u32(spmi->dev.of_node, "qcom,chg-vinmin-mv",
&chip->min_voltage_mv);
- if (rc && rc != -EINVAL) {
+ if (rc) {
pr_err("Error reading vddmax property %d\n", rc);
goto fail_chg_enable;
}
@@ -1443,17 +1673,17 @@
/* Get the vddmax property */
rc = of_property_read_u32(spmi->dev.of_node, "qcom,chg-vddsafe-mv",
&chip->safe_voltage_mv);
- if (rc && rc != -EINVAL) {
+ if (rc) {
pr_err("Error reading vddsave property %d\n", rc);
goto fail_chg_enable;
}
- /* Get the ibatsafe property */
+ /* Get the vbatdet-delta property */
rc = of_property_read_u32(spmi->dev.of_node,
- "qcom,chg-vbatdet-mv",
- &chip->resume_voltage_mv);
- if (rc) {
- pr_err("Error reading vbatdet property %d\n", rc);
+ "qcom,chg-vbatdet-delta-mv",
+ &chip->resume_delta_mv);
+ if (rc && rc != -EINVAL) {
+ pr_err("Error reading vbatdet-delta property %d\n", rc);
goto fail_chg_enable;
}
@@ -1478,17 +1708,8 @@
/* Get the ibatmax property */
rc = of_property_read_u32(spmi->dev.of_node, "qcom,chg-ibatmax-ma",
&chip->max_bat_chg_current);
- if (rc && rc != -EINVAL) {
- pr_err("Error reading ibatmax property %d\n", rc);
- goto fail_chg_enable;
- }
-
- /* Get the ibatsafe property */
- rc = of_property_read_u32(spmi->dev.of_node,
- "qcom,chg-vbatdet-mv",
- &chip->resume_voltage_mv);
if (rc) {
- pr_err("Error reading vbatdet property %d\n", rc);
+ pr_err("Error reading ibatmax property %d\n", rc);
goto fail_chg_enable;
}
@@ -1514,6 +1735,67 @@
chip->charging_disabled = of_property_read_bool(spmi->dev.of_node,
"qcom,chg-charging-disabled");
+ /* Get the warm-bat-degc property */
+ rc = of_property_read_u32(spmi->dev.of_node,
+ "qcom,chg-warm-bat-degc",
+ &chip->warm_bat_degc);
+ if (rc && rc != -EINVAL) {
+ pr_err("Error reading warm-bat-degc property %d\n", rc);
+ goto fail_chg_enable;
+ }
+
+ /* Get the cool-bat-degc property */
+ rc = of_property_read_u32(spmi->dev.of_node,
+ "qcom,chg-cool-bat-degc",
+ &chip->cool_bat_degc);
+ if (rc && rc != -EINVAL) {
+ pr_err("Error reading cool-bat-degc property %d\n", rc);
+ goto fail_chg_enable;
+ }
+
+ if (chip->cool_bat_degc && chip->warm_bat_degc) {
+ rc = qpnp_adc_tm_is_ready();
+ if (rc) {
+ pr_err("tm not ready %d\n", rc);
+ goto fail_chg_enable;
+ }
+
+ /* Get the ibatmax-warm property */
+ rc = of_property_read_u32(spmi->dev.of_node,
+ "qcom,chg-ibatmax-warm-ma",
+ &chip->warm_bat_chg_ma);
+ if (rc) {
+ pr_err("Error reading ibatmax-warm-ma %d\n", rc);
+ goto fail_chg_enable;
+ }
+
+ /* Get the ibatmax-cool property */
+ rc = of_property_read_u32(spmi->dev.of_node,
+ "qcom,chg-ibatmax-cool-ma",
+ &chip->cool_bat_chg_ma);
+ if (rc) {
+ pr_err("Error reading ibatmax-cool-ma %d\n", rc);
+ goto fail_chg_enable;
+ }
+ /* Get the cool-bat-mv property */
+ rc = of_property_read_u32(spmi->dev.of_node,
+ "qcom,chg-cool-bat-mv",
+ &chip->cool_bat_mv);
+ if (rc) {
+ pr_err("Error reading cool-bat-mv property %d\n", rc);
+ goto fail_chg_enable;
+ }
+
+ /* Get the warm-bat-mv property */
+ rc = of_property_read_u32(spmi->dev.of_node,
+ "qcom,chg-warm-bat-mv",
+ &chip->warm_bat_mv);
+ if (rc) {
+ pr_err("Error reading warm-bat-mv property %d\n", rc);
+ goto fail_chg_enable;
+ }
+ }
+
/* Get the fake-batt-values property */
chip->use_default_batt_values = of_property_read_bool(spmi->dev.of_node,
"qcom,chg-use-default-batt-values");
@@ -1701,6 +1983,22 @@
}
}
+ if (chip->cool_bat_degc && chip->warm_bat_degc) {
+ chip->adc_param.low_temp = chip->cool_bat_degc;
+ chip->adc_param.high_temp = chip->warm_bat_degc;
+ chip->adc_param.timer_interval = ADC_MEAS2_INTERVAL_1S;
+ chip->adc_param.state_request = ADC_TM_HIGH_LOW_THR_ENABLE;
+ chip->adc_param.btm_ctx = chip;
+ chip->adc_param.threshold_notification =
+ qpnp_chg_adc_notification;
+
+ rc = qpnp_adc_tm_btm_configure(&chip->adc_param);
+ if (rc) {
+ pr_err("request ADC error %d\n", rc);
+ goto fail_chg_enable;
+ }
+ }
+
qpnp_chg_charge_en(chip, !chip->charging_disabled);
qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 9dd9c40..87a0078 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -516,6 +516,82 @@
/*-------------------------------------------------------------------------*/
/* Supported functions initialization */
+/* ACM */
+static char acm_transports[32]; /*enabled ACM ports - "tty[,sdio]"*/
+static ssize_t acm_transports_store(
+ struct device *device, struct device_attribute *attr,
+ const char *buff, size_t size)
+{
+ strlcpy(acm_transports, buff, sizeof(acm_transports));
+
+ return size;
+}
+
+static DEVICE_ATTR(acm_transports, S_IWUSR, NULL, acm_transports_store);
+static struct device_attribute *acm_function_attributes[] = {
+ &dev_attr_acm_transports,
+ NULL
+};
+
+static void acm_function_cleanup(struct android_usb_function *f)
+{
+ gserial_cleanup();
+}
+
+static int
+acm_function_bind_config(struct android_usb_function *f,
+ struct usb_configuration *c)
+{
+ char *name;
+ char buf[32], *b;
+ int err = -1, i;
+ static int acm_initialized, ports;
+
+ if (acm_initialized)
+ goto bind_config;
+
+ acm_initialized = 1;
+ strlcpy(buf, acm_transports, sizeof(buf));
+ b = strim(buf);
+
+ while (b) {
+ name = strsep(&b, ",");
+
+ if (name) {
+ err = acm_init_port(ports, name);
+ if (err) {
+ pr_err("acm: Cannot open port '%s'", name);
+ goto out;
+ }
+ ports++;
+ }
+ }
+ err = acm_port_setup(c);
+ if (err) {
+ pr_err("acm: Cannot setup transports");
+ goto out;
+ }
+
+bind_config:
+ for (i = 0; i < ports; i++) {
+ err = acm_bind_config(c, i);
+ if (err) {
+ pr_err("acm: bind_config failed for port %d", i);
+ goto out;
+ }
+ }
+
+out:
+ return err;
+}
+
+static struct android_usb_function acm_function = {
+ .name = "acm",
+ .cleanup = acm_function_cleanup,
+ .bind_config = acm_function_bind_config,
+ .attributes = acm_function_attributes,
+};
+
/* RMNET_SMD */
static int rmnet_smd_function_bind_config(struct android_usb_function *f,
struct usb_configuration *c)
@@ -996,78 +1072,6 @@
.attributes = serial_function_attributes,
};
-/* ACM */
-static char acm_transports[32]; /*enabled ACM ports - "tty[,sdio]"*/
-static ssize_t acm_transports_store(
- struct device *device, struct device_attribute *attr,
- const char *buff, size_t size)
-{
- strlcpy(acm_transports, buff, sizeof(acm_transports));
-
- return size;
-}
-
-static DEVICE_ATTR(acm_transports, S_IWUSR, NULL, acm_transports_store);
-static struct device_attribute *acm_function_attributes[] = {
- &dev_attr_acm_transports, NULL };
-
-static void acm_function_cleanup(struct android_usb_function *f)
-{
- gserial_cleanup();
-}
-
-static int acm_function_bind_config(struct android_usb_function *f,
- struct usb_configuration *c)
-{
- char *name;
- char buf[32], *b;
- int err = -1, i;
- static int acm_initialized, ports;
-
- if (acm_initialized)
- goto bind_config;
-
- acm_initialized = 1;
- strlcpy(buf, acm_transports, sizeof(buf));
- b = strim(buf);
-
- while (b) {
- name = strsep(&b, ",");
-
- if (name) {
- err = acm_init_port(ports, name);
- if (err) {
- pr_err("acm: Cannot open port '%s'", name);
- goto out;
- }
- ports++;
- }
- }
- err = acm_port_setup(c);
- if (err) {
- pr_err("acm: Cannot setup transports");
- goto out;
- }
-
-bind_config:
- for (i = 0; i < ports; i++) {
- err = acm_bind_config(c, i);
- if (err) {
- pr_err("acm: bind_config failed for port %d", i);
- goto out;
- }
- }
-
-out:
- return err;
-}
-static struct android_usb_function acm_function = {
- .name = "acm",
- .cleanup = acm_function_cleanup,
- .bind_config = acm_function_bind_config,
- .attributes = acm_function_attributes,
-};
-
/* CCID */
static int ccid_function_init(struct android_usb_function *f,
struct usb_composite_dev *cdev)
@@ -1093,7 +1097,8 @@
.bind_config = ccid_function_bind_config,
};
-static int mtp_function_init(struct android_usb_function *f,
+static int
+mtp_function_init(struct android_usb_function *f,
struct usb_composite_dev *cdev)
{
return mtp_setup();
@@ -1104,13 +1109,16 @@
mtp_cleanup();
}
-static int mtp_function_bind_config(struct android_usb_function *f,
+static int
+mtp_function_bind_config(struct android_usb_function *f,
struct usb_configuration *c)
{
return mtp_bind_config(c, false);
}
-static int ptp_function_init(struct android_usb_function *f, struct usb_composite_dev *cdev)
+static int
+ptp_function_init(struct android_usb_function *f,
+ struct usb_composite_dev *cdev)
{
/* nothing to do - initialization is handled by mtp_function_init */
return 0;
@@ -1121,7 +1129,9 @@
/* nothing to do - cleanup is handled by mtp_function_cleanup */
}
-static int ptp_function_bind_config(struct android_usb_function *f, struct usb_configuration *c)
+static int
+ptp_function_bind_config(struct android_usb_function *f,
+ struct usb_configuration *c)
{
return mtp_bind_config(c, true);
}
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index c02c8e4..81fc1cc 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -1391,9 +1391,6 @@
dev_err(dev, "[%s] EINVAL\n", __func__);
return 0;
}
- dump = kmalloc(2048, GFP_KERNEL);
- if (dump == NULL)
- return -ENOMEM;
dump = kmalloc(sizeof(u32) * DUMP_ENTRIES, GFP_KERNEL);
if (!dump) {
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c
index 0752188..de54714 100644
--- a/drivers/usb/gadget/f_acm.c
+++ b/drivers/usb/gadget/f_acm.c
@@ -18,7 +18,6 @@
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/device.h>
-#include <linux/usb/android_composite.h>
#include <mach/usb_gadget_xport.h>
#include "u_serial.h"
diff --git a/drivers/usb/gadget/f_ccid.c b/drivers/usb/gadget/f_ccid.c
index 4e28d34..6888935 100644
--- a/drivers/usb/gadget/f_ccid.c
+++ b/drivers/usb/gadget/f_ccid.c
@@ -16,7 +16,6 @@
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/device.h>
-#include <linux/usb/android_composite.h>
#include <linux/fs.h>
#include <linux/usb/ccid_desc.h>
#include <linux/miscdevice.h>
diff --git a/drivers/usb/gadget/f_rmnet.c b/drivers/usb/gadget/f_rmnet.c
index 0d8fa0f..af68827 100644
--- a/drivers/usb/gadget/f_rmnet.c
+++ b/drivers/usb/gadget/f_rmnet.c
@@ -14,7 +14,6 @@
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/device.h>
-#include <linux/usb/android_composite.h>
#include <linux/spinlock.h>
#include <mach/usb_gadget_xport.h>
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index bf887a7..8c0894c 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -49,6 +49,7 @@
#include <linux/spinlock.h>
#include <linux/cpu.h>
#include <mach/rpm-regulator.h>
+#include "hbm.c"
#define MSM_USB_BASE (hcd->regs)
#define USB_REG_START_OFFSET 0x90
@@ -105,6 +106,7 @@
int reset_again;
struct pm_qos_request pm_qos_req_dma;
+ unsigned enable_hbm:1;
};
struct msm_hsic_hcd *__mehci;
@@ -1367,6 +1369,18 @@
pm_runtime_set_autosuspend_delay(&dev->dev, 200);
}
+static int ehci_msm_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
+ gfp_t mem_flags)
+{
+ struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
+ struct usb_host_bam_type *usb_host_bam =
+ (struct usb_host_bam_type *)urb->priv_data;
+
+ if (usb_host_bam && mehci && mehci->enable_hbm)
+ return hbm_urb_enqueue(hcd, urb, mem_flags);
+ return ehci_urb_enqueue(hcd, urb, mem_flags);
+}
+
static struct hc_driver msm_hsic_driver = {
.description = hcd_name,
.product_desc = "Qualcomm EHCI Host Controller using HSIC",
@@ -1387,7 +1401,7 @@
/*
* managing i/o requests and associated device resources
*/
- .urb_enqueue = ehci_urb_enqueue,
+ .urb_enqueue = ehci_msm_urb_enqueue,
.urb_dequeue = ehci_urb_dequeue,
.endpoint_disable = ehci_endpoint_disable,
.endpoint_reset = ehci_endpoint_reset,
@@ -1778,6 +1792,8 @@
pdata->pool_64_bit_align = of_property_read_bool(node,
"qcom,pool-64-bit-align");
+ pdata->enable_hbm = of_property_read_bool(node,
+ "qcom,enable-hbm");
return pdata;
}
@@ -1861,6 +1877,7 @@
mehci->ehci.resume_sof_bug = 1;
mehci->ehci.pool_64_bit_align = pdata->pool_64_bit_align;
+ mehci->enable_hbm = pdata->enable_hbm;
if (pdata)
mehci->ehci.log2_irq_thresh = pdata->log2_irq_thresh;
@@ -2011,6 +2028,9 @@
if (pdev->dev.parent)
pm_runtime_put_sync(pdev->dev.parent);
+ if (mehci->enable_hbm)
+ hbm_init(hcd);
+
return 0;
destroy_wq:
@@ -2040,6 +2060,9 @@
pm_runtime_set_suspended(&pdev->dev);
+ if (mehci->enable_hbm)
+ hbm_uninit();
+
/* Remove the HCD prior to releasing our resources. */
usb_remove_hcd(hcd);
diff --git a/drivers/usb/host/hbm.c b/drivers/usb/host/hbm.c
index f516ad8..d48a631 100644
--- a/drivers/usb/host/hbm.c
+++ b/drivers/usb/host/hbm.c
@@ -194,12 +194,6 @@
pr_err("%s: hbm_ctx alloc failed\n", __func__);
return;
}
- hbm_ctx->base = kzalloc(sizeof(u32), GFP_KERNEL);
- if (!hbm_ctx->base) {
- pr_err("%s: hbm_ctx base alloc failed\n", __func__);
- kfree(hbm_ctx);
- return;
- }
hbm_ctx->base = hcd->regs;
hbm_ctx->hcd = hcd;
@@ -214,7 +208,7 @@
void hbm_uninit(void)
{
- kfree(hbm_ctx->base);
+ hbm_config(false);
kfree(hbm_ctx);
}
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 1c7d928..7760d28 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -151,8 +151,8 @@
rc = regulator_set_voltage(hsusb_1p8, USB_PHY_1P8_VOL_MIN,
USB_PHY_1P8_VOL_MAX);
if (rc) {
- dev_err(motg->phy.dev, "unable to set voltage level for"
- "hsusb 1p8\n");
+ dev_err(motg->phy.dev, "unable to set voltage level "
+ "for hsusb 1p8\n");
goto put_1p8;
}
@@ -207,7 +207,7 @@
ret = regulator_set_optimum_mode(hsusb_1p8,
USB_PHY_1P8_HPM_LOAD);
if (ret < 0) {
- pr_err("%s: Unable to set HPM of the regulator:"
+ pr_err("%s: Unable to set HPM of the regulator "
"HSUSB_1p8\n", __func__);
return ret;
}
@@ -223,7 +223,7 @@
ret = regulator_set_optimum_mode(hsusb_3p3,
USB_PHY_3P3_HPM_LOAD);
if (ret < 0) {
- pr_err("%s: Unable to set HPM of the regulator:"
+ pr_err("%s: Unable to set HPM of the regulator "
"HSUSB_3p3\n", __func__);
regulator_set_optimum_mode(hsusb_1p8, 0);
regulator_disable(hsusb_1p8);
@@ -252,7 +252,7 @@
ret = regulator_set_optimum_mode(hsusb_1p8, 0);
if (ret < 0)
- pr_err("%s: Unable to set LPM of the regulator:"
+ pr_err("%s: Unable to set LPM of the regulator "
"HSUSB_1p8\n", __func__);
ret = regulator_disable(hsusb_3p3);
@@ -263,7 +263,7 @@
}
ret = regulator_set_optimum_mode(hsusb_3p3, 0);
if (ret < 0)
- pr_err("%s: Unable to set LPM of the regulator:"
+ pr_err("%s: Unable to set LPM of the regulator "
"HSUSB_3p3\n", __func__);
break;
@@ -1575,7 +1575,7 @@
}
static int msm_otg_set_peripheral(struct usb_otg *otg,
- struct usb_gadget *gadget)
+ struct usb_gadget *gadget)
{
struct msm_otg *motg = container_of(otg->phy, struct msm_otg, phy);
@@ -3017,10 +3017,10 @@
if ((otgsc & OTGSC_IDIS) && (otgsc & OTGSC_IDIE)) {
if (otgsc & OTGSC_ID) {
- pr_debug("Id set\n");
+ dev_dbg(otg->phy->dev, "ID set\n");
set_bit(ID, &motg->inputs);
} else {
- pr_debug("Id clear\n");
+ dev_dbg(otg->phy->dev, "ID clear\n");
/*
* Assert a_bus_req to supply power on
* VBUS when Micro/Mini-A cable is connected
@@ -3049,10 +3049,10 @@
!test_bit(ID_A, &motg->inputs))
return IRQ_HANDLED;
if (otgsc & OTGSC_BSV) {
- pr_debug("BSV set\n");
+ dev_dbg(otg->phy->dev, "BSV set\n");
set_bit(B_SESS_VLD, &motg->inputs);
} else {
- pr_debug("BSV clear\n");
+ dev_dbg(otg->phy->dev, "BSV clear\n");
clear_bit(B_SESS_VLD, &motg->inputs);
clear_bit(A_BUS_SUSPEND, &motg->inputs);
@@ -3245,9 +3245,9 @@
static int msm_otg_mode_show(struct seq_file *s, void *unused)
{
struct msm_otg *motg = s->private;
- struct usb_phy *phy = &motg->phy;
+ struct usb_otg *otg = motg->phy.otg;
- switch (phy->state) {
+ switch (otg->phy->state) {
case OTG_STATE_A_HOST:
seq_printf(s, "host\n");
break;
@@ -4228,10 +4228,10 @@
static int __devexit msm_otg_remove(struct platform_device *pdev)
{
struct msm_otg *motg = platform_get_drvdata(pdev);
- struct usb_otg *otg = motg->phy.otg;
+ struct usb_phy *phy = &motg->phy;
int cnt = 0;
- if (otg->host || otg->gadget)
+ if (phy->otg->host || phy->otg->gadget)
return -EBUSY;
if (pdev->dev.of_node)
@@ -4264,8 +4264,8 @@
/*
* Put PHY in low power mode.
*/
- ulpi_read(otg->phy, 0x14);
- ulpi_write(otg->phy, 0x08, 0x09);
+ ulpi_read(phy, 0x14);
+ ulpi_write(phy, 0x08, 0x09);
writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC);
while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
@@ -4275,7 +4275,7 @@
cnt++;
}
if (cnt >= PHY_SUSPEND_TIMEOUT_USEC)
- dev_err(otg->phy->dev, "Unable to suspend PHY\n");
+ dev_err(phy->dev, "Unable to suspend PHY\n");
clk_disable_unprepare(motg->pclk);
clk_disable_unprepare(motg->core_clk);
diff --git a/drivers/video/msm/mdss/mhl_sii8334.c b/drivers/video/msm/mdss/mhl_sii8334.c
index 30dd471..ccddf44 100644
--- a/drivers/video/msm/mdss/mhl_sii8334.c
+++ b/drivers/video/msm/mdss/mhl_sii8334.c
@@ -1712,18 +1712,18 @@
struct input_dev *input = mhl_ctrl->input;
mhl_ctrl->rcp_key_code_tbl = vmalloc(
- ARRAY_SIZE(support_rcp_key_code_tbl));
+ sizeof(support_rcp_key_code_tbl));
if (!mhl_ctrl->rcp_key_code_tbl) {
pr_err("%s: no alloc mem for rcp keycode tbl\n",
__func__);
return -ENOMEM;
}
+ mhl_ctrl->rcp_key_code_tbl_len = sizeof(
+ support_rcp_key_code_tbl);
memcpy(mhl_ctrl->rcp_key_code_tbl,
&support_rcp_key_code_tbl[0],
- ARRAY_SIZE(support_rcp_key_code_tbl));
- mhl_ctrl->rcp_key_code_tbl_len = ARRAY_SIZE(
- support_rcp_key_code_tbl);
+ mhl_ctrl->rcp_key_code_tbl_len);
input->phys = "cbus/input0";
input->id.bustype = BUS_VIRTUAL;
diff --git a/include/linux/usb/android_composite.h b/include/linux/usb/android_composite.h
deleted file mode 100644
index 438dfa4..0000000
--- a/include/linux/usb/android_composite.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Platform data for Android USB
- *
- * Copyright (C) 2008 Google, Inc.
- * Author: Mike Lockwood <lockwood@android.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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 __LINUX_USB_ANDROID_H
-#define __LINUX_USB_ANDROID_H
-
-#include <linux/usb/composite.h>
-#include <linux/if_ether.h>
-
-struct android_usb_function {
- struct list_head list;
- char *name;
- int (*bind_config)(struct usb_configuration *c);
-};
-
-struct android_usb_product {
- /* Default product ID. */
- __u16 product_id;
-
- /* List of function names associated with this product.
- * This is used to compute the USB product ID dynamically
- * based on which functions are enabled.
- */
- int num_functions;
- char **functions;
-};
-
-struct android_usb_platform_data {
- /* USB device descriptor fields */
- __u16 vendor_id;
-
- /* Default product ID. */
- __u16 product_id;
-
- __u16 version;
-
- char *product_name;
- char *manufacturer_name;
- char *serial_number;
-
- /* List of available USB products.
- * This is used to compute the USB product ID dynamically
- * based on which functions are enabled.
- * if num_products is zero or no match can be found,
- * we use the default product ID
- */
- int num_products;
- struct android_usb_product *products;
-
- /* List of all supported USB functions.
- * This list is used to define the order in which
- * the functions appear in the configuration's list of USB interfaces.
- * This is necessary to avoid depending upon the order in which
- * the individual function drivers are initialized.
- */
- int num_functions;
- char **functions;
-};
-
-/* Platform data for "usb_mass_storage" driver. */
-struct usb_mass_storage_platform_data {
- /* Contains values for the SC_INQUIRY SCSI command. */
- char *vendor;
- char *product;
- int release;
-
- char can_stall;
- /* number of LUNS */
- int nluns;
-};
-
-/* Platform data for USB ethernet driver. */
-struct usb_ether_platform_data {
- u8 ethaddr[ETH_ALEN];
- u32 vendorID;
- const char *vendorDescr;
-};
-
-extern void android_register_function(struct android_usb_function *f);
-
-extern int android_enable_function(struct usb_function *f, int enable);
-
-
-#endif /* __LINUX_USB_ANDROID_H */
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index c7c6b05..c5943c9 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -412,6 +412,7 @@
/*standalone latency is required when HSCI is active*/
u32 standalone_latency;
bool pool_64_bit_align;
+ bool enable_hbm;
};
struct msm_usb_host_platform_data {
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index af268bd..f4ea679 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -83,6 +83,7 @@
AIF2_CAP,
AIF3_PB,
AIF3_CAP,
+ AIF4_VIFEED,
NUM_CODEC_DAIS,
};
@@ -2671,6 +2672,7 @@
{"AIF1 CAP", NULL, "AIF1_CAP Mixer"},
{"AIF2 CAP", NULL, "AIF2_CAP Mixer"},
{"AIF3 CAP", NULL, "AIF3_CAP Mixer"},
+ {"AIF4 VI", NULL, "SPK_OUT"},
/* SLIM_MIXER("AIF1_CAP Mixer"),*/
{"AIF1_CAP Mixer", "SLIM TX1", "SLIM TX1 MUX"},
@@ -3143,6 +3145,7 @@
{"MIC BIAS3 Internal2", NULL, "LDO_H"},
{"MIC BIAS3 External", NULL, "LDO_H"},
{"MIC BIAS4 External", NULL, "LDO_H"},
+
};
static int taiko_readable(struct snd_soc_codec *ssc, unsigned int reg)
@@ -3367,6 +3370,7 @@
unsigned int rx_num, unsigned int *rx_slot)
{
+ struct wcd9xxx_codec_dai_data *dai_data = NULL;
struct taiko_priv *taiko = snd_soc_codec_get_drvdata(dai->codec);
struct wcd9xxx *core = dev_get_drvdata(dai->codec->dev->parent);
if (!tx_slot && !rx_slot) {
@@ -3378,9 +3382,18 @@
__func__, dai->name, dai->id, tx_num, rx_num,
taiko->intf_type);
- if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_SLIMBUS)
+ if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
wcd9xxx_init_slimslave(core, core->slim->laddr,
- tx_num, tx_slot, rx_num, rx_slot);
+ tx_num, tx_slot, rx_num, rx_slot);
+ /*Reserve tx11 and tx12 for VI feedback path*/
+ dai_data = &taiko->dai[AIF4_VIFEED];
+ if (dai_data) {
+ list_add_tail(&core->tx_chs[TAIKO_TX11].list,
+ &dai_data->wcd9xxx_ch_list);
+ list_add_tail(&core->tx_chs[TAIKO_TX12].list,
+ &dai_data->wcd9xxx_ch_list);
+ }
+ }
return 0;
}
@@ -3414,6 +3427,7 @@
case AIF1_CAP:
case AIF2_CAP:
case AIF3_CAP:
+ case AIF4_VIFEED:
if (!tx_slot || !tx_num) {
pr_err("%s: Invalid tx_slot %d or tx_num %d\n",
__func__, (u32) tx_slot, (u32) tx_num);
@@ -3639,12 +3653,14 @@
switch (substream->stream) {
case SNDRV_PCM_STREAM_CAPTURE:
- ret = taiko_set_decimator_rate(dai, tx_fs_rate,
- params_rate(params));
- if (ret < 0) {
- pr_err("%s: set decimator rate failed %d\n", __func__,
- ret);
- return ret;
+ if (dai->id != AIF4_VIFEED) {
+ ret = taiko_set_decimator_rate(dai, tx_fs_rate,
+ params_rate(params));
+ if (ret < 0) {
+ pr_err("%s: set decimator rate failed %d\n",
+ __func__, ret);
+ return ret;
+ }
}
if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
@@ -3828,6 +3844,20 @@
},
.ops = &taiko_dai_ops,
},
+ {
+ .name = "taiko_vifeedback",
+ .id = AIF4_VIFEED,
+ .capture = {
+ .stream_name = "VIfeed",
+ .rates = SNDRV_PCM_RATE_48000,
+ .formats = TAIKO_FORMATS,
+ .rate_max = 48000,
+ .rate_min = 48000,
+ .channels_min = 2,
+ .channels_max = 2,
+ },
+ .ops = &taiko_dai_ops,
+ },
};
static struct snd_soc_dai_driver taiko_i2s_dai[] = {
@@ -3967,6 +3997,89 @@
return ret;
}
+static int taiko_codec_enable_slimvi_feedback(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct wcd9xxx *core = NULL;
+ struct snd_soc_codec *codec = NULL;
+ struct taiko_priv *taiko_p = NULL;
+ u32 ret = 0;
+ struct wcd9xxx_codec_dai_data *dai = NULL;
+
+ if (!w || !w->codec) {
+ pr_err("%s invalid params\n", __func__);
+ return -EINVAL;
+ }
+ codec = w->codec;
+ taiko_p = snd_soc_codec_get_drvdata(codec);
+ core = dev_get_drvdata(codec->dev->parent);
+
+ pr_debug("%s: event called! codec name %s num_dai %d stream name %s\n",
+ __func__, w->codec->name, w->codec->num_dai, w->sname);
+
+ /* Execute the callback only if interface type is slimbus */
+ if (taiko_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
+ pr_err("%s Interface is not correct", __func__);
+ return 0;
+ }
+
+ pr_debug("%s(): w->name %s event %d w->shift %d\n",
+ __func__, w->name, event, w->shift);
+ if (w->shift != AIF4_VIFEED) {
+ pr_err("%s Error in enabling the tx path\n", __func__);
+ ret = -EINVAL;
+ goto out_vi;
+ }
+ dai = &taiko_p->dai[w->shift];
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ /*Enable Clip Detection*/
+ snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_CLIP_DET,
+ 0x8, 0x8);
+ /*Enable V&I sensing*/
+ snd_soc_update_bits(codec, TAIKO_A_SPKR_PROT_EN,
+ 0x88, 0x88);
+ /*Enable spkr VI clocks*/
+ snd_soc_update_bits(codec,
+ TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL, 0xC, 0xC);
+ /*Enable Voltage Decimator*/
+ snd_soc_update_bits(codec,
+ TAIKO_A_CDC_CONN_TX_SB_B9_CTL, 0x1F, 0x12);
+ /*Enable Current Decimator*/
+ snd_soc_update_bits(codec,
+ TAIKO_A_CDC_CONN_TX_SB_B10_CTL, 0x1F, 0x13);
+ ret = wcd9xxx_cfg_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
+ dai->rate, dai->bit_width,
+ &dai->grph);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ ret = wcd9xxx_close_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
+ dai->grph);
+ if (ret)
+ pr_err("%s error in close_slim_sch_tx %d\n",
+ __func__, ret);
+ /*Disable Voltage decimator*/
+ snd_soc_update_bits(codec,
+ TAIKO_A_CDC_CONN_TX_SB_B9_CTL, 0x1F, 0x0);
+ /*Disable Current decimator*/
+ snd_soc_update_bits(codec,
+ TAIKO_A_CDC_CONN_TX_SB_B10_CTL, 0x1F, 0x0);
+ /*Disable spkr VI clocks*/
+ snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL,
+ 0xC, 0x0);
+ /*Disable V&I sensing*/
+ snd_soc_update_bits(codec, TAIKO_A_SPKR_PROT_EN,
+ 0x88, 0x00);
+ /*Disable clip detection*/
+ snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_CLIP_DET,
+ 0x8, 0x0);
+ break;
+ }
+out_vi:
+ return ret;
+}
+
static int taiko_codec_enable_slimtx(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
@@ -4440,6 +4553,10 @@
AIF3_CAP, 0, taiko_codec_enable_slimtx,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_AIF_OUT_E("AIF4 VI", "VIfeed", 0, SND_SOC_NOPM,
+ AIF4_VIFEED, 0, taiko_codec_enable_slimvi_feedback,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
SND_SOC_DAPM_MIXER("AIF1_CAP Mixer", SND_SOC_NOPM, AIF1_CAP, 0,
aif_cap_mixer, ARRAY_SIZE(aif_cap_mixer)),
@@ -4529,7 +4646,6 @@
SND_SOC_DAPM_MIXER("LINEOUT4_PA_MIXER", SND_SOC_NOPM, 0, 0,
lineout4_pa_mix, ARRAY_SIZE(lineout4_pa_mix)),
-
};
static irqreturn_t taiko_slimbus_irq(int irq, void *data)
diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
index 39afb73..4e6cbaa 100644
--- a/sound/soc/msm/msm-compr-q6.c
+++ b/sound/soc/msm/msm-compr-q6.c
@@ -788,7 +788,7 @@
runtime->private_data = compr;
atomic_set(&prtd->eos, 0);
compressed_audio.prtd = &compr->prtd;
- ret = compressed_set_volume(compressed_audio.volume);
+ ret = compressed_set_volume(0);
if (ret < 0)
pr_err("%s : Set Volume failed : %d", __func__, ret);
diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
index d0b5500..f6e571b8 100644
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
@@ -754,7 +754,7 @@
prtd->session_id,
substream->stream);
- ret = compressed_set_volume(compressed_audio.volume);
+ ret = compressed_set_volume(0);
if (ret < 0)
pr_err("%s : Set Volume failed : %d", __func__, ret);
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
index c300a9f..557ec65 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
@@ -485,6 +485,7 @@
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
+ case SNDRV_PCM_FMTBIT_SPECIAL:
dai_data->port_config.i2s.bit_width = 16;
break;
case SNDRV_PCM_FORMAT_S24_LE:
@@ -560,6 +561,7 @@
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
+ case SNDRV_PCM_FMTBIT_SPECIAL:
dai_data->port_config.slim_sch.bit_width = 16;
break;
case SNDRV_PCM_FORMAT_S24_LE:
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index e05e58d..4ca96d7 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -459,19 +459,20 @@
pr_debug("%s\n", __func__);
- dir = IN;
- ret = wait_event_timeout(the_locks.eos_wait,
- prtd->cmd_ack, 5 * HZ);
- if (ret < 0)
- pr_err("%s: CMD_EOS failed\n", __func__);
- q6asm_cmd(prtd->audio_client, CMD_CLOSE);
- q6asm_audio_client_buf_free_contiguous(dir,
- prtd->audio_client);
-
+ if (prtd->audio_client) {
+ dir = IN;
+ ret = wait_event_timeout(the_locks.eos_wait,
+ prtd->cmd_ack, 5 * HZ);
+ if (ret < 0)
+ pr_err("%s: CMD_EOS failed\n", __func__);
+ q6asm_cmd(prtd->audio_client, CMD_CLOSE);
+ q6asm_audio_client_buf_free_contiguous(dir,
+ prtd->audio_client);
+ pcm_audio.prtd = NULL;
+ q6asm_audio_client_free(prtd->audio_client);
+ }
msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id,
SNDRV_PCM_STREAM_PLAYBACK);
- pcm_audio.prtd = NULL;
- q6asm_audio_client_free(prtd->audio_client);
kfree(prtd);
return 0;
}
@@ -678,7 +679,7 @@
if (ret < 0) {
pr_err("%s: q6asm_open_write_v2 failed\n", __func__);
q6asm_audio_client_free(prtd->audio_client);
- kfree(prtd);
+ prtd->audio_client = NULL;
return -ENOMEM;
}
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 4e7455b..0549671 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -2344,7 +2344,7 @@
fmt.fmt_blk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
sizeof(fmt.fmt_blk);
fmt.num_channels = channels;
- fmt.bits_per_sample = 16;
+ fmt.bits_per_sample = bits_per_sample;
fmt.sample_rate = rate;
fmt.is_signed = 1;
diff --git a/sound/soc/msm/qdsp6v2/q6audio-v2.c b/sound/soc/msm/qdsp6v2/q6audio-v2.c
index 99cb6a6..4ed0fb7 100644
--- a/sound/soc/msm/qdsp6v2/q6audio-v2.c
+++ b/sound/soc/msm/qdsp6v2/q6audio-v2.c
@@ -43,6 +43,7 @@
case SLIMBUS_1_TX: return IDX_SLIMBUS_1_TX;
case SLIMBUS_2_RX: return IDX_SLIMBUS_2_RX;
case SLIMBUS_2_TX: return IDX_SLIMBUS_2_TX;
+ case SLIMBUS_4_TX: return IDX_SLIMBUS_4_TX;
case INT_BT_SCO_RX: return IDX_INT_BT_SCO_RX;
case INT_BT_SCO_TX: return IDX_INT_BT_SCO_TX;
case INT_BT_A2DP_RX: return IDX_INT_BT_A2DP_RX;
@@ -89,6 +90,7 @@
case SLIMBUS_1_TX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_1_TX;
case SLIMBUS_2_RX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_2_RX;
case SLIMBUS_2_TX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_2_TX;
+ case SLIMBUS_4_TX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_4_TX;
case INT_BT_SCO_RX: return AFE_PORT_ID_INTERNAL_BT_SCO_RX;
case INT_BT_SCO_TX: return AFE_PORT_ID_INTERNAL_BT_SCO_TX;
case INT_BT_A2DP_RX: return AFE_PORT_ID_INTERNAL_BT_A2DP_RX;
@@ -182,6 +184,7 @@
case SLIMBUS_1_TX:
case SLIMBUS_2_RX:
case SLIMBUS_2_TX:
+ case SLIMBUS_4_TX:
case INT_BT_SCO_RX:
case INT_BT_SCO_TX:
case INT_BT_A2DP_RX: