Merge "msm: kgsl: Add 8974 support for enabling GPU GDHS"
diff --git a/Documentation/devicetree/bindings/arm/msm/dcvs-core-info.txt b/Documentation/devicetree/bindings/arm/msm/dcvs-core-info.txt
index a39356c..b7dd427 100644
--- a/Documentation/devicetree/bindings/arm/msm/dcvs-core-info.txt
+++ b/Documentation/devicetree/bindings/arm/msm/dcvs-core-info.txt
@@ -5,74 +5,139 @@
Required properties:
-- qcom,core-max-time-us: Maximum time limit in micorseconds for switching clock rate.
- Limited to this value if switching time takes longer than this limit. Typical value is 100000.
-- qcom,algo-slack-time-us: Time in microseconds after which the QoS guarantee will kick in
- and the clock rate will increased as necessary. Typical value is about 30000.
-- qcom,algo-disable-pc-threshold: If core frequency (kHz) is higher than this value, power collapse is disallowed. Set to 0 for GPU.
-- qcom,algo-ss-window-size: Steady state window size in microseconds.
-- qcom,algo-ss-util-pct: When determining the steady state level, this percentage value is used to provide headroom
- from the utilized cpu to the selected level.
-- qcom,algo-ee-max-util-pct: When determining the level with the lowest energy, any level that exceeds this busy
- percentage, for the measured work in the last window, is disqualified for performance reasons.
-- qcom,algo-ss-iobusy-conv: Used to convert correlation time into assumed IO Busy time, which is removed
- from measured elapsed time when computing cpu utilization.
+- qcom,core-core-type: indicates whether this core is a CPU(0) or a GPU(1)
+- qcom,num-cores: The number of cores this entry represents
+- qcom,sensors: The vector of sensor ids for the cores
+
+- qcom,algo-disable-pc-threshold: sets highest frequency at which DCVS
+ will allow the CPU to power collapse.
+- qcom,algo-em-win-size-min-us: sets minimum Energy Minimization(EM)
+ window size.
+
+- qcom,algo-em-win-size-max-us: sets maximum EM window size.
+- qcom,algo-em-max-util-pct: sets maximum CPU utilization that will
+ not be exceeded by any core when
+ MP-decision decides the number of
+ online cores.
+- qcom,algo-group-id: specifies a group index of a core.
+- qcom,algo-max-freq-chg-time-us: shows time taken for the most recent
+ frequency change.
+- qcom,algo-slack-mode-dynamic: specifies if dynamic slack mode is
+ enabled or not.
+- qcom,algo-slack-weight-thresh-pct: sets occurrence percentage of CPU
+ activity that will make slack timer
+ triggered.
+- qcom,algo-slack-time-min-us: specifies the slack time that slack
+ timer would be set if the current clock
+ frequency is zero.
+- qcom,algo-slack-time-max-us: sets maximum slack timer value to be
+ used by slack timer.
+- qcom,algo-ss-win-size-min-us: sets minimum steady state window size.
+- qcom,algo-ss-win-size-max-us: sets maximum steady state window size.
+- qcom,algo-ss-util-pct: sets target CPU utilization during
+ steady-state.
+- qcom,algo-ss-iobusy-conv: specifies how wait time (i/o busy time)
+ is incorporated into the steady-state
+ algorithm.
+
+- qcom,energy-active-coeff-a: sets active power equation coefficient a.
+- qcom,energy-active-coeff-b: sets active power equation coefficient b.
+- qcom,energy-active-coeff-c: sets active power equation coefficient c.
+- qcom,energy-leakage-coeff-a: sets leakage power equation coefficient a.
+- qcom,energy-leakage-coeff-b: sets leakage power equation coefficient b.
+- qcom,energy-leakage-coeff-c: sets leakage power equation coefficient c.
+- qcom,energy-leakage-coeff-d: sets leakage power equation coefficient d.
+
+- qcom,power-current-temp: the current temperature in degCelcius.
+- qcom,power-num-freq: the number of freq this core supports.
A number of frequency levels are represented as sub-nodes:
required properties:
- reg: The index of the frequency entry
- qcom,freq The frequency of the DVS entry (in kHZ)
-- qcom,idle-energy: The idle energy cost of the entry (in micro watts)
-- qcom,active-energy: The active energy cost of the entry (in micro watts)
+- qcom,is_trans_level This frequency is transient step for DCVS
+- qcom,active-energy-offset: The active energy cost of the entry
+- qcom,leakage-energy-offset: The leakage energy cost of the entry
Sample:
qcom,kgsl-3d0@fdb00000 {
...
- qcom,dcvs-core-info {
- #address-cells = <1>;
- #size-cells = <0>;
+ qcom,dcvs-core-info {
+ #address-cells = <1>;
+ #size-cells = <0>;
- compatible = "qcom,dcvs-core-info";
+ compatible = "qcom,dcvs-core-info";
- qcom,core-max-time-us = <100000>;
- qcom,algo-slack-time-us = <39000>;
- qcom,algo-disable-pc-threshold = <86000>;
- qcom,algo-ss-window-size = <1000000>;
- qcom,algo-ss-util-pct = <95>;
- qcom,algo-em-max-util-pct = <97>;
- qcom,algo-ss-iobusy-conv = <100>;
+ qcom,num-cores = <1>;
+ qcom,sensors = <0>;
- qcom,dcvs-freq@0 {
- reg = <0>;
- qcom,freq = <0>;
- qcom,idle-energy = <0>;
- qcom,active-energy = <333932>;
+ qcom,core-core-type = <1>;
+
+ qcom,algo-disable-pc-threshold = <0>;
+ qcom,algo-em-win-size-min-us = <100000>;
+ qcom,algo-em-win-size-max-us = <300000>;
+ qcom,algo-em-max-util-pct = <97>;
+ qcom,algo-group-id = <95>;
+ qcom,algo-max-freq-chg-time-us = <100000>;
+ qcom,algo-slack-mode-dynamic = <100000>;
+ qcom,algo-slack-weight-thresh-pct = <0>;
+ qcom,algo-slack-time-min-us = <39000>;
+ qcom,algo-slack-time-max-us = <39000>;
+ qcom,algo-ss-win-size-min-us = <1000000>;
+ qcom,algo-ss-win-size-max-us = <1000000>;
+ qcom,algo-ss-util-pct = <95>;
+ qcom,algo-ss-iobusy-conv = <100>;
+
+ qcom,energy-active-coeff-a = <2492>;
+ qcom,energy-active-coeff-b = <0>;
+ qcom,energy-active-coeff-c = <0>;
+ qcom,energy-leakage-coeff-a = <11>;
+ qcom,energy-leakage-coeff-b = <157150>;
+ qcom,energy-leakage-coeff-c = <0>;
+ qcom,energy-leakage-coeff-d = <0>;
+
+ qcom,power-current-temp = <25>;
+ qcom,power-num-freq = <4>;
+
+ qcom,dcvs-freq@0 {
+ reg = <0>;
+ qcom,freq = <0>;
+ qcom,voltage = <0>;
+ qcom,is_trans_level = <0>;
+ qcom,active-energy-offset = <100>;
+ qcom,leakage-energy-offset = <0>;
+ };
+
+ qcom,dcvs-freq@1 {
+ reg = <1>;
+ qcom,freq = <0>;
+ qcom,voltage = <0>;
+ qcom,is_trans_level = <0>;
+ qcom,active-energy-offset = <100>;
+ qcom,leakage-energy-offset = <0>;
+ };
+
+ qcom,dcvs-freq@2 {
+ reg = <2>;
+ qcom,freq = <0>;
+ qcom,voltage = <0>;
+ qcom,is_trans_level = <0>;
+ qcom,active-energy-offset = <100>;
+ qcom,leakage-energy-offset = <0>;
+ };
+
+ qcom,dcvs-freq@3 {
+ reg = <3>;
+ qcom,freq = <0>;
+ qcom,voltage = <0>;
+ qcom,is_trans_level = <0>;
+ qcom,active-energy-offset = <844545>;
+ qcom,leakage-energy-offset = <0>;
+ };
};
-
- qcom,dcvs-freq@1 {
- reg = <1>;
- qcom,freq = <0>;
- qcom,idle-energy = <0>;
- qcom,active-energy = <497532>;
- };
-
- qcom,dcvs-freq@2 {
- reg = <2>;
- qcom,freq = <0>;
- qcom,idle-energy = <0>;
- qcom,active-energy = <707610>;
- };
-
- qcom,dcvs-freq@3 {
- reg = <3>;
- qcom,freq = <0>;
- qcom,idle-energy = <0>;
- qcom,active-energy = <844545>;
- };
- };
...
};
diff --git a/Documentation/devicetree/bindings/iommu/msm_iommu.txt b/Documentation/devicetree/bindings/iommu/msm_iommu.txt
index f5a2590..7a90cc0 100644
--- a/Documentation/devicetree/bindings/iommu/msm_iommu.txt
+++ b/Documentation/devicetree/bindings/iommu/msm_iommu.txt
@@ -19,6 +19,19 @@
Optional properties:
- qcom,needs-alt-core-clk : boolean to enable the secondary core clock for
access to the IOMMU configuration registers
+- qcom,iommu-bfb-regs : An array of unsigned 32-bit integers corresponding to
+ BFB register addresses that need to be configured for performance tuning
+ purposes. If this property is present, the qcom,iommu-bfb-data must also be
+ present. Register addresses are specified as an offset from the base of the
+ IOMMU hardware block. This property may be omitted if no BFB register
+ configuration needs to be done for a particular IOMMU hardware instance. The
+ registers specified by this property shall fall within the IOMMU
+ implementation-defined register region.
+- qcom,iommu-bfb-data : An array of unsigned 32-bit integers representing the
+ values to be programmed into the corresponding registers given by the
+ qcom,iommu-bfb-regs property. If this property is present, the
+ qcom,iommu-bfb-regs property shall also be present, and the lengths of both
+ properties shall be the same.
Example:
@@ -26,6 +39,8 @@
compatible = "qcom,msm-smmu-v2";
reg = <0xfda64000 0x10000>;
vdd-supply = <&gdsc_iommu>;
+ qcom,iommu-bfb-regs = <0x204c 0x2050>;
+ qcom,iommu-bfb-data = <0xffff 0xffce>;
qcom,iommu-ctx@fda6c000 {
reg = <0xfda6c000 0x1000>;
diff --git a/Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt b/Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt
index 21d376a..adb93b8 100644
--- a/Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt
+++ b/Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt
@@ -11,18 +11,24 @@
- compatible: Must be "qcom,qpnp-power-on"
- reg: Specifies the SPMI address and size for this PON (power-on) peripheral
- interrupts: Specifies the interrupt associated with PON.
+- interrupt-names: Specify the interrupt names associated with interrupts. Must be
+ one of "kpdpwr", "kpdpwr-bark", "resin", "resin-bark", "cblpwr".
+ Bark interrupts are associated with system reset configuration
+ to allow default reset configuration to be activated. If system
+ reset configuration is not supported then bark interrupts are
+ nops.
Optional properties:
-- qcom,pon-dbc-delay The debouce delay for the power-key interrupt
- specifed in us. The value ranges from 2 seconds
+- qcom,pon-dbc-delay The debounce delay for the power-key interrupt
+ specified in us. The value ranges from 2 seconds
to 1/64 of a second. Possible values are -
- 2, 1, 1/2, 1/4, 1/8, 1/16, 1/32, 1/64
- Intermediate value is rounded down to the
nearest valid value.
- qcom,pon_1 ...pon_n These represent the child nodes which describe
the properties (reset, key) for each of the pon
- reset source. All the child nodes are optional,
- if none of them are specified the driver fails
+ reset source. All the child nodes are optional.
+ If none of them is specified, the driver fails
to register.
- qcom,system-reset Specifies that this PON peripheral can be used
to reset the system. This property can only be
@@ -32,32 +38,32 @@
All the below properties are in the sub-node section (properties of the child
node).
+Sub-node required properties:
+- qcom,pon-type The type of PON/RESET source. The driver
+ currently supports KPDPWR(0), RESIN(1) and
+ CBLPWR(2) pon/reset sources.
+
+Sub-node optional properties:
- qcom,pull-up The initial state of the reset pin under
consideration.
0 = No pull-up
1 = pull-up enabled
- This property is optional and is set to '0'
- if not specified.
-- qcom,pon-type The type of PON/RESET source. The driver
- currently supports KPDPWR(0) and RESIN(1)
- pon/reset sources. This property must be
- specified.
+ This property is set to '0' if not specified.
- qcom,support-reset Indicates if this PON source supports
reset functionality.
0 = Not supported
1 = Supported
- This property is optional and is set to '0'
- if not specified.
-- qcom,s1-timer The debouce timer for the BARK interrupt for
+ This property is set to '0' if not specified.
+- qcom,s1-timer The debounce timer for the BARK interrupt for
that reset source. Value is specified in ms.
Supported values are -
- 0, 32, 56, 80, 128, 184, 272, 408, 608, 904
1352, 2048, 3072, 4480, 6720, 10256
This property must be specified only if
'support-reset' is set to 1.
-- qcom,s2-timer The debouce timer for the S2 reset specified
+- qcom,s2-timer The debounce timer for the S2 reset specified
in ms. On the expiry of this timer, the PMIC
- executes the reset sequence. Supoprted values -
+ executes the reset sequence. Supported values -
- 0, 10, 50, 100, 250, 500, 1000, 2000
This property is required only if
'support-reset' is set to 1.
@@ -68,7 +74,7 @@
'support-reset' is set to 1.
- linux,code The input key-code associated with the reset source.
The reset source in its default configuration can be
- used to support standard keys. This property is optional.
+ used to support standard keys.
Example:
qcom,power-on@800 {
diff --git a/arch/arm/boot/dts/msm-pm8019.dtsi b/arch/arm/boot/dts/msm-pm8019.dtsi
index 3b06450..e70eb36 100755
--- a/arch/arm/boot/dts/msm-pm8019.dtsi
+++ b/arch/arm/boot/dts/msm-pm8019.dtsi
@@ -22,6 +22,21 @@
#address-cells = <1>;
#size-cells = <1>;
+ qcom,power_on@800 {
+ compatible = "qcom,qpnp-power-on";
+ reg = <0x800 0x100>;
+ interrupts = <0x0 0x8 0x2>;
+ interrupt-names = "cblpwr";
+ qcom,pon-dbc-delay = <15625>;
+ qcom,system-reset;
+
+ qcom,pon_1 {
+ qcom,pon-type = <2>;
+ qcom,pull-up = <1>;
+ linux,code = <116>;
+ };
+ };
+
clkdiv@5b00 {
reg = <0x5b00 0x100>;
compatible = "qcom,qpnp-clkdiv";
diff --git a/arch/arm/boot/dts/msm-pm8841.dtsi b/arch/arm/boot/dts/msm-pm8841.dtsi
index 069a248..ea83231 100644
--- a/arch/arm/boot/dts/msm-pm8841.dtsi
+++ b/arch/arm/boot/dts/msm-pm8841.dtsi
@@ -22,7 +22,7 @@
#address-cells = <1>;
#size-cells = <1>;
- pm8841_mpps {
+ pm8841_mpps: mpps {
spmi-dev-container;
compatible = "qcom,qpnp-pin";
gpio-controller;
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index d58a71d..f1e18cf 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -203,7 +203,7 @@
};
};
- pm8941_gpios {
+ pm8941_gpios: gpios {
spmi-dev-container;
compatible = "qcom,qpnp-pin";
gpio-controller;
@@ -393,7 +393,7 @@
};
};
- pm8941_mpps {
+ pm8941_mpps: mpps {
spmi-dev-container;
compatible = "qcom,qpnp-pin";
gpio-controller;
diff --git a/arch/arm/boot/dts/msm8974-cdp.dts b/arch/arm/boot/dts/msm8974-cdp.dts
index 7aeb33c..aff0adc 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dts
+++ b/arch/arm/boot/dts/msm8974-cdp.dts
@@ -168,3 +168,196 @@
cd-gpios = <&msmgpio 62 0x1>;
wp-gpios = <&pm8941_gpios 29 0x1>;
};
+
+&pm8941_gpios {
+ gpio@c000 { /* GPIO 1 */
+ };
+
+ gpio@c100 { /* GPIO 2 */
+ };
+
+ gpio@c200 { /* GPIO 3 */
+ qcom,mode = <0>;
+ qcom,pull = <0>;
+ qcom,vin-sel = <2>;
+ qcom,select = <0>;
+ };
+
+ gpio@c300 { /* GPIO 4 */
+ qcom,mode = <0>;
+ qcom,pull = <0>;
+ qcom,vin-sel = <2>;
+ qcom,select = <0>;
+ };
+
+ gpio@c400 { /* GPIO 5 */
+ qcom,mode = <0>;
+ qcom,pull = <0>;
+ qcom,vin-sel = <2>;
+ qcom,select = <0>;
+ };
+
+ gpio@c500 { /* GPIO 6 */
+ };
+
+ gpio@c600 { /* GPIO 7 */
+ };
+
+ gpio@c700 { /* GPIO 8 */
+ };
+
+ gpio@c800 { /* GPIO 9 */
+ };
+
+ gpio@c900 { /* GPIO 10 */
+ };
+
+ gpio@ca00 { /* GPIO 11 */
+ };
+
+ gpio@cb00 { /* GPIO 12 */
+ };
+
+ gpio@cc00 { /* GPIO 13 */
+ };
+
+ gpio@cd00 { /* GPIO 14 */
+ };
+
+ gpio@ce00 { /* GPIO 15 */
+ qcom,mode = <1>;
+ qcom,output-type = <0>;
+ qcom,pull = <5>;
+ qcom,vin-sel = <2>;
+ qcom,out-strength = <3>;
+ qcom,src-select = <2>;
+ qcom,master-en = <1>;
+ };
+
+ gpio@cf00 { /* GPIO 16 */
+ };
+
+ gpio@d000 { /* GPIO 17 */
+ };
+
+ gpio@d100 { /* GPIO 18 */
+ };
+
+ gpio@d200 { /* GPIO 19 */
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,output-type = <0>; /* QPNP_PIN_OUT_BUF_CMOS */
+ qcom,pull = <5>; /* QPNP_PIN_PULL_NO */
+ qcom,vin-sel = <2>; /* QPNP_PIN_VIN2 */
+ qcom,out-strength = <2>; /* QPNP_PIN_OUT_STRENGTH_MED */
+ qcom,src-select = <0>; /* QPNP_PIN_SEL_FUNC_CONSTANT */
+ qcom,master-en = <1>;
+ };
+
+ gpio@d300 { /* GPIO 20 */
+ };
+
+ gpio@d400 { /* GPIO 21 */
+ };
+
+ gpio@d500 { /* GPIO 22 */
+ };
+
+ gpio@d600 { /* GPIO 23 */
+ };
+
+ gpio@d700 { /* GPIO 24 */
+ };
+
+ gpio@d800 { /* GPIO 25 */
+ };
+
+ gpio@d900 { /* GPIO 26 */
+ };
+
+ gpio@da00 { /* GPIO 27 */
+ };
+
+ gpio@db00 { /* GPIO 28 */
+ };
+
+ gpio@dc00 { /* GPIO 29 */
+ qcom,pull = <0>; /* set to default pull */
+ qcom,master-en = <1>;
+ qcom,vin-sel = <2>; /* select 1.8 V source */
+ };
+
+ gpio@dd00 { /* GPIO 30 */
+ };
+
+ gpio@de00 { /* GPIO 31 */
+ };
+
+ gpio@df00 { /* GPIO 32 */
+ };
+
+ gpio@e000 { /* GPIO 33 */
+ };
+
+ gpio@e100 { /* GPIO 34 */
+ };
+
+ gpio@e200 { /* GPIO 35 */
+ };
+
+ gpio@e300 { /* GPIO 36 */
+ };
+};
+
+&pm8941_mpps {
+
+ mpp@a000 { /* MPP 1 */
+ };
+
+ mpp@a100 { /* MPP 2 */
+ };
+
+ mpp@a200 { /* MPP 3 */
+ };
+
+ mpp@a300 { /* MPP 4 */
+ };
+
+ mpp@a400 { /* MPP 5 */
+ /* SPI_ETH config */
+ qcom,mode = <1>; /* DIG_OUT */
+ qcom,output-type = <0>; /* CMOS */
+ qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
+ qcom,src-select = <0>; /* CONSTANT */
+ qcom,master-en = <1>; /* ENABLE MPP */
+ };
+
+ mpp@a500 { /* MPP 6 */
+ /* SPI_ETH_RST config */
+ qcom,mode = <1>; /* DIG_OUT */
+ qcom,output-type = <0>; /* CMOS */
+ qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
+ qcom,src-select = <0>; /* CONSTANT */
+ qcom,master-en = <1>; /* ENABLE MPP */
+ };
+
+ mpp@a600 { /* MPP 7 */
+ };
+
+ mpp@a700 { /* MPP 8 */
+ };
+};
+
+&pm8841_mpps {
+
+ mpp@a000 { /* MPP 1 */
+ };
+
+ mpp@a100 { /* MPP 2 */
+ };
+
+ mpp@a200 { /* MPP 3 */
+ };
+
+ mpp@a300 { /* MPP 4 */
+ };
+};
diff --git a/arch/arm/boot/dts/msm8974-fluid.dts b/arch/arm/boot/dts/msm8974-fluid.dts
new file mode 100644
index 0000000..b1d467e
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-fluid.dts
@@ -0,0 +1,366 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "msm8974.dtsi"
+/include/ "dsi-panel-toshiba-720p-video.dtsi"
+
+/ {
+ model = "Qualcomm MSM 8974 FLUID";
+ compatible = "qcom,msm8974-fluid", "qcom,msm8974";
+ qcom,msm-id = <126 3 0>;
+
+ serial@f991e000 {
+ status = "ok";
+ };
+
+ qcom,mdss_dsi@fd922800 {
+ qcom,mdss_dsi_toshiba_720p_video {
+ status = "ok";
+ };
+ };
+
+ i2c@f9924000 {
+ atmel_mxt_ts@4a {
+ compatible = "atmel,mxt-ts";
+ reg = <0x4a>;
+ interrupt-parent = <&msmgpio>;
+ interrupts = <61 0x2>;
+ vdd_ana-supply = <&pm8941_l18>;
+ vcc_i2c-supply = <&pm8941_lvs1>;
+ atmel,reset-gpio = <&msmgpio 60 0x00>;
+ atmel,irq-gpio = <&msmgpio 61 0x00>;
+ atmel,panel-coords = <0 0 760 1424>;
+ atmel,display-coords = <0 0 720 1280>;
+ atmel,i2c-pull-up = <1>;
+ atmel,cfg_1 {
+ atmel,family-id = <0x82>;
+ atmel,variant-id = <0x19>;
+ atmel,version = <0x10>;
+ atmel,build = <0xaa>;
+ atmel,config = [
+ /* Object 6, Instance = 0 */
+ 00 00 00 00 00 00
+ /* Object 38, Instance = 0 */
+ 15 00 02 10 08 0C 00 00
+ /* Object 7, Instance = 0 */
+ FF FF 32 03
+ /* Object 8, Instance = 0 */
+ 0F 00 0A 0A 00 00 0A 00 00 00
+ /* Object 9, Instance = 0 */
+ 83 00 00 18 0E 00 70 32 02 01
+ 00 03 01 01 05 0A 0A 0A 90 05
+ F8 02 00 00 0F 0F 00 00 48 2D
+ 07 0C 00 00 00 00
+ /* Object 15, Instance = 0 */
+ 00 00 00 00 00 00 00 00 00 00
+ 00
+ /* Object 18, Instance = 0 */
+ 00 00
+ /* Object 19, Instance = 0 */
+ 00 00 00 00 00 00
+ /* Object 23, Instance = 0 */
+ 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00
+ /* Object 25, Instance = 0 */
+ 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00
+ /* Object 40, Instance = 0 */
+ 00 00 00 00 00
+ /* Object 42, Instance = 0 */
+ 00 00 00 00 00 00 00 00 00 00
+ /* Object 46, Instance = 0 */
+ 00 00 10 10 00 00 03 00 00 01
+ /* Object 47, Instance = 0 */
+ 08 0A 28 0A 02 0A 00 8C 00 20
+ 00 00 00
+ /* Object 55, Instance = 0 */
+ 00 00 00 00 00 00
+ /* Object 56, Instance = 0 */
+ 03 00 01 18 05 05 05 05 05 05
+ 05 05 05 05 05 05 05 05 05 05
+ 05 05 05 05 05 05 05 05 00 00
+ 00 00 00 00 00 00 00 00 00 00
+ 00 00
+ /* Object 57, Instance = 0 */
+ 00 00 00
+ /* Object 61, Instance = 0 */
+ 00 00 00 00 00
+ /* Object 61, Instance = 1 */
+ 00 00 00 00 00
+ /* Object 62, Instance = 0 */
+ 7F 03 00 16 00 00 00 00 00 00
+ 04 08 10 18 05 00 0A 05 05 50
+ 14 19 34 1A 64 00 00 04 40 00
+ 00 00 00 00 30 32 02 00 01 00
+ 05 00 00 00 00 00 00 00 00 00
+ 00 00 0C 00
+ ];
+ };
+ };
+ };
+
+ gpio_keys {
+ compatible = "gpio-keys";
+
+ camera_snapshot {
+ label = "camera_snapshot";
+ gpios = <&pm8941_gpios 3 0x1>;
+ linux,input-type = <1>;
+ linux,code = <0x2fe>;
+ gpio-key,wakeup;
+ debounce-interval = <15>;
+ };
+
+ camera_focus {
+ label = "camera_focus";
+ gpios = <&pm8941_gpios 4 0x1>;
+ linux,input-type = <1>;
+ linux,code = <0x210>;
+ gpio-key,wakeup;
+ debounce-interval = <15>;
+ };
+
+ vol_up {
+ label = "volume_up";
+ gpios = <&pm8941_gpios 5 0x1>;
+ linux,input-type = <1>;
+ linux,code = <115>;
+ gpio-key,wakeup;
+ debounce-interval = <15>;
+ };
+ };
+
+ spi@f9923000 {
+ ethernet-switch@2 {
+ compatible = "micrel,ks8851";
+ reg = <2>;
+ interrupt-parent = <&msmgpio>;
+ interrupts = <94 0>;
+ spi-max-frequency = <4800000>;
+ rst-gpio = <&pm8941_mpps 6 0>;
+ vdd-io-supply = <&spi_eth_vreg>;
+ vdd-phy-supply = <&spi_eth_vreg>;
+ };
+ };
+};
+
+&sdcc1 {
+ qcom,sdcc-bus-width = <4>;
+};
+
+&sdcc2 {
+ #address-cells = <0>;
+ interrupt-parent = <&sdcc2>;
+ interrupts = <0 1 2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 125 0
+ 1 &intc 0 220 0
+ 2 &msmgpio 62 0x3>;
+ interrupt-names = "core_irq", "bam_irq", "status_irq";
+ cd-gpios = <&msmgpio 62 0x1>;
+};
+
+&pm8941_gpios {
+ gpio@c000 { /* GPIO 1 */
+ };
+
+ gpio@c100 { /* GPIO 2 */
+ };
+
+ gpio@c200 { /* GPIO 3 */
+ qcom,mode = <0>;
+ qcom,pull = <0>;
+ qcom,vin-sel = <2>;
+ qcom,select = <0>;
+ };
+
+ gpio@c300 { /* GPIO 4 */
+ qcom,mode = <0>;
+ qcom,pull = <0>;
+ qcom,vin-sel = <2>;
+ qcom,select = <0>;
+ };
+
+ gpio@c400 { /* GPIO 5 */
+ qcom,mode = <0>;
+ qcom,pull = <0>;
+ qcom,vin-sel = <2>;
+ qcom,select = <0>;
+ };
+
+ gpio@c500 { /* GPIO 6 */
+ };
+
+ gpio@c600 { /* GPIO 7 */
+ };
+
+ gpio@c700 { /* GPIO 8 */
+ };
+
+ gpio@c800 { /* GPIO 9 */
+ };
+
+ gpio@c900 { /* GPIO 10 */
+ };
+
+ gpio@ca00 { /* GPIO 11 */
+ };
+
+ gpio@cb00 { /* GPIO 12 */
+ };
+
+ gpio@cc00 { /* GPIO 13 */
+ };
+
+ gpio@cd00 { /* GPIO 14 */
+ };
+
+ gpio@ce00 { /* GPIO 15 */
+ qcom,mode = <1>;
+ qcom,output-type = <0>;
+ qcom,pull = <5>;
+ qcom,vin-sel = <2>;
+ qcom,out-strength = <3>;
+ qcom,src-select = <2>;
+ qcom,master-en = <1>;
+ };
+
+ gpio@cf00 { /* GPIO 16 */
+ };
+
+ gpio@d000 { /* GPIO 17 */
+ };
+
+ gpio@d100 { /* GPIO 18 */
+ };
+
+ gpio@d200 { /* GPIO 19 */
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,output-type = <0>; /* QPNP_PIN_OUT_BUF_CMOS */
+ qcom,pull = <5>; /* QPNP_PIN_PULL_NO */
+ qcom,vin-sel = <2>; /* QPNP_PIN_VIN2 */
+ qcom,out-strength = <2>; /* QPNP_PIN_OUT_STRENGTH_MED */
+ qcom,src-select = <0>; /* QPNP_PIN_SEL_FUNC_CONSTANT */
+ qcom,master-en = <1>;
+ };
+
+ gpio@d300 { /* GPIO 20 */
+ };
+
+ gpio@d400 { /* GPIO 21 */
+ };
+
+ gpio@d500 { /* GPIO 22 */
+ };
+
+ gpio@d600 { /* GPIO 23 */
+ };
+
+ gpio@d700 { /* GPIO 24 */
+ };
+
+ gpio@d800 { /* GPIO 25 */
+ };
+
+ gpio@d900 { /* GPIO 26 */
+ };
+
+ gpio@da00 { /* GPIO 27 */
+ };
+
+ gpio@db00 { /* GPIO 28 */
+ };
+
+ gpio@dc00 { /* GPIO 29 */
+ qcom,pull = <0>; /* set to default pull */
+ qcom,master-en = <1>;
+ qcom,vin-sel = <2>; /* select 1.8 V source */
+ };
+
+ gpio@dd00 { /* GPIO 30 */
+ };
+
+ gpio@de00 { /* GPIO 31 */
+ };
+
+ gpio@df00 { /* GPIO 32 */
+ };
+
+ gpio@e000 { /* GPIO 33 */
+ };
+
+ gpio@e100 { /* GPIO 34 */
+ };
+
+ gpio@e200 { /* GPIO 35 */
+ };
+
+ gpio@e300 { /* GPIO 36 */
+ };
+};
+
+&pm8941_mpps {
+
+ mpp@a000 { /* MPP 1 */
+ };
+
+ mpp@a100 { /* MPP 2 */
+ };
+
+ mpp@a200 { /* MPP 3 */
+ };
+
+ mpp@a300 { /* MPP 4 */
+ };
+
+ mpp@a400 { /* MPP 5 */
+ /* SPI_ETH config */
+ qcom,mode = <1>; /* DIG_OUT */
+ qcom,output-type = <0>; /* CMOS */
+ qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
+ qcom,src-select = <0>; /* CONSTANT */
+ qcom,master-en = <1>; /* ENABLE MPP */
+ };
+
+ mpp@a500 { /* MPP 6 */
+ /* SPI_ETH_RST config */
+ qcom,mode = <1>; /* DIG_OUT */
+ qcom,output-type = <0>; /* CMOS */
+ qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
+ qcom,src-select = <0>; /* CONSTANT */
+ qcom,master-en = <1>; /* ENABLE MPP */
+ };
+
+ mpp@a600 { /* MPP 7 */
+ };
+
+ mpp@a700 { /* MPP 8 */
+ };
+};
+
+&pm8841_mpps {
+
+ mpp@a000 { /* MPP 1 */
+ };
+
+ mpp@a100 { /* MPP 2 */
+ };
+
+ mpp@a200 { /* MPP 3 */
+ };
+
+ mpp@a300 { /* MPP 4 */
+ };
+};
diff --git a/arch/arm/boot/dts/msm8974-gpio.dtsi b/arch/arm/boot/dts/msm8974-gpio.dtsi
deleted file mode 100644
index e298340..0000000
--- a/arch/arm/boot/dts/msm8974-gpio.dtsi
+++ /dev/null
@@ -1,214 +0,0 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-&spmi_bus {
-
- qcom,pm8941@0 {
-
- pm8941_gpios: pm8941_gpios {
-
- gpio@c000 {
- };
-
- gpio@c100 {
- };
-
- gpio@c200 {
- qcom,mode = <0>;
- qcom,pull = <0>;
- qcom,vin-sel = <2>;
- qcom,select = <0>;
- };
-
- gpio@c300 {
- qcom,mode = <0>;
- qcom,pull = <0>;
- qcom,vin-sel = <2>;
- qcom,select = <0>;
- };
-
- gpio@c400 {
- qcom,mode = <0>;
- qcom,pull = <0>;
- qcom,vin-sel = <2>;
- qcom,select = <0>;
- };
-
- gpio@c500 {
- };
-
- gpio@c600 {
- };
-
- gpio@c700 {
- };
-
- gpio@c800 {
- };
-
- gpio@c900 {
- };
-
- gpio@ca00 {
- };
-
- gpio@cb00 {
- };
-
- gpio@cc00 {
- };
-
- gpio@cd00 {
- };
-
- gpio@ce00 {
- qcom,mode = <1>;
- qcom,output-type = <0>;
- qcom,pull = <5>;
- qcom,vin-sel = <2>;
- qcom,out-strength = <3>;
- qcom,src-select = <2>;
- qcom,master-en = <1>;
- };
-
- gpio@cf00 {
- };
-
- gpio@d000 {
- };
-
- gpio@d100 {
- };
-
- gpio@d200 {
- qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
- qcom,output-type = <0>; /* QPNP_PIN_OUT_BUF_CMOS */
- qcom,pull = <5>; /* QPNP_PIN_PULL_NO */
- qcom,vin-sel = <2>; /* QPNP_PIN_VIN2 */
- qcom,out-strength = <2>; /* QPNP_PIN_OUT_STRENGTH_MED */
- qcom,src-select = <0>; /* QPNP_PIN_SEL_FUNC_CONSTANT */
- qcom,master-en = <1>;
- };
-
- gpio@d300 {
- };
-
- gpio@d400 {
- };
-
- gpio@d500 {
- };
-
- gpio@d600 {
- };
-
- gpio@d700 {
- };
-
- gpio@d800 {
- };
-
- gpio@d900 {
- };
-
- gpio@da00 {
- };
-
- gpio@db00 {
- };
-
- gpio@dc00 {
- qcom,pull = <0>; /* set to default pull */
- qcom,master-en = <1>;
- qcom,vin-sel = <2>; /* select 1.8 V source */
- };
-
- gpio@dd00 {
- };
-
- gpio@de00 {
- };
-
- gpio@df00 {
- };
-
- gpio@e000 {
- };
-
- gpio@e100 {
- };
-
- gpio@e200 {
- };
-
- gpio@e300 {
- };
- };
-
- pm8941_mpps: pm8941_mpps {
-
- mpp@a000 {
- };
-
- mpp@a100 {
- };
-
- mpp@a200 {
- };
-
- mpp@a300 {
- };
-
- mpp@a400 {
- /* SPI_ETH config */
- qcom,mode = <1>; /* DIG_OUT */
- qcom,output-type = <0>; /* CMOS */
- qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
- qcom,src-select = <0>; /* CONSTANT */
- qcom,master-en = <1>; /* ENABLE MPP */
- };
-
- mpp@a500 {
- /* SPI_ETH_RST config */
- qcom,mode = <1>; /* DIG_OUT */
- qcom,output-type = <0>; /* CMOS */
- qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
- qcom,src-select = <0>; /* CONSTANT */
- qcom,master-en = <1>; /* ENABLE MPP */
- };
-
- mpp@a600 {
- };
-
- mpp@a700 {
- };
- };
- };
-
- qcom,pm8841@4 {
-
- pm8841_mpps: pm8841_mpps {
-
- mpp@a000 {
- };
-
- mpp@a100 {
- };
-
- mpp@a200 {
- };
-
- mpp@a300 {
- };
- };
- };
-};
diff --git a/arch/arm/boot/dts/msm8974-gpu.dtsi b/arch/arm/boot/dts/msm8974-gpu.dtsi
index a4b5584..6d00b01 100644
--- a/arch/arm/boot/dts/msm8974-gpu.dtsi
+++ b/arch/arm/boot/dts/msm8974-gpu.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -86,40 +86,71 @@
compatible = "qcom,dcvs-core-info";
- qcom,core-max-time-us = <100000>;
- qcom,algo-slack-time-us = <39000>;
- qcom,algo-disable-pc-threshold = <86000>;
- qcom,algo-ss-window-size = <1000000>;
- qcom,algo-ss-util-pct = <95>;
+ qcom,num-cores = <1>;
+ qcom,sensors = <0>;
+
+ qcom,core-core-type = <1>;
+
+ qcom,algo-disable-pc-threshold = <0>;
+ qcom,algo-em-win-size-min-us = <100000>;
+ qcom,algo-em-win-size-max-us = <300000>;
qcom,algo-em-max-util-pct = <97>;
+ qcom,algo-group-id = <95>;
+ qcom,algo-max-freq-chg-time-us = <100000>;
+ qcom,algo-slack-mode-dynamic = <100000>;
+ qcom,algo-slack-weight-thresh-pct = <0>;
+ qcom,algo-slack-time-min-us = <39000>;
+ qcom,algo-slack-time-max-us = <39000>;
+ qcom,algo-ss-win-size-min-us = <1000000>;
+ qcom,algo-ss-win-size-max-us = <1000000>;
+ qcom,algo-ss-util-pct = <95>;
qcom,algo-ss-iobusy-conv = <100>;
+ qcom,energy-active-coeff-a = <2492>;
+ qcom,energy-active-coeff-b = <0>;
+ qcom,energy-active-coeff-c = <0>;
+ qcom,energy-leakage-coeff-a = <11>;
+ qcom,energy-leakage-coeff-b = <157150>;
+ qcom,energy-leakage-coeff-c = <0>;
+ qcom,energy-leakage-coeff-d = <0>;
+
+ qcom,power-current-temp = <25>;
+ qcom,power-num-freq = <4>;
+
qcom,dcvs-freq@0 {
reg = <0>;
qcom,freq = <0>;
- qcom,idle-energy = <0>;
- qcom,active-energy = <333932>;
+ qcom,voltage = <0>;
+ qcom,is_trans_level = <0>;
+ qcom,active-energy-offset = <100>;
+ qcom,leakage-energy-offset = <0>;
};
qcom,dcvs-freq@1 {
reg = <1>;
qcom,freq = <0>;
- qcom,idle-energy = <0>;
- qcom,active-energy = <497532>;
+ qcom,voltage = <0>;
+ qcom,is_trans_level = <0>;
+ qcom,active-energy-offset = <100>;
+ qcom,leakage-energy-offset = <0>;
};
qcom,dcvs-freq@2 {
reg = <2>;
qcom,freq = <0>;
- qcom,idle-energy = <0>;
- qcom,active-energy = <707610>;
+ qcom,voltage = <0>;
+ qcom,is_trans_level = <0>;
+ qcom,active-energy-offset = <100>;
+ qcom,leakage-energy-offset = <0>;
};
qcom,dcvs-freq@3 {
reg = <3>;
qcom,freq = <0>;
- qcom,idle-energy = <0>;
- qcom,active-energy = <844545>;
+ qcom,voltage = <0>;
+ qcom,is_trans_level = <0>;
+ qcom,active-energy-offset = <844545>;
+ qcom,leakage-energy-offset = <0>;
};
};
diff --git a/arch/arm/boot/dts/msm8974-ion.dtsi b/arch/arm/boot/dts/msm8974-ion.dtsi
index 1893ae4..9b5aaac 100644
--- a/arch/arm/boot/dts/msm8974-ion.dtsi
+++ b/arch/arm/boot/dts/msm8974-ion.dtsi
@@ -70,7 +70,7 @@
reg = <28>;
qcom,heap-align = <0x1000>;
qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
- qcom,memory-reservation-size = <0x2B4000>;
+ qcom,memory-reservation-size = <0x314000>;
};
};
};
diff --git a/arch/arm/boot/dts/msm8974-liquid.dts b/arch/arm/boot/dts/msm8974-liquid.dts
index 5de2d43..2abc1d5 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dts
+++ b/arch/arm/boot/dts/msm8974-liquid.dts
@@ -24,4 +24,195 @@
};
};
+&pm8941_gpios {
+ gpio@c000 { /* GPIO 1 */
+ };
+ gpio@c100 { /* GPIO 2 */
+ };
+
+ gpio@c200 { /* GPIO 3 */
+ qcom,mode = <0>;
+ qcom,pull = <0>;
+ qcom,vin-sel = <2>;
+ qcom,select = <0>;
+ };
+
+ gpio@c300 { /* GPIO 4 */
+ qcom,mode = <0>;
+ qcom,pull = <0>;
+ qcom,vin-sel = <2>;
+ qcom,select = <0>;
+ };
+
+ gpio@c400 { /* GPIO 5 */
+ qcom,mode = <0>;
+ qcom,pull = <0>;
+ qcom,vin-sel = <2>;
+ qcom,select = <0>;
+ };
+
+ gpio@c500 { /* GPIO 6 */
+ };
+
+ gpio@c600 { /* GPIO 7 */
+ };
+
+ gpio@c700 { /* GPIO 8 */
+ };
+
+ gpio@c800 { /* GPIO 9 */
+ };
+
+ gpio@c900 { /* GPIO 10 */
+ };
+
+ gpio@ca00 { /* GPIO 11 */
+ };
+
+ gpio@cb00 { /* GPIO 12 */
+ };
+
+ gpio@cc00 { /* GPIO 13 */
+ };
+
+ gpio@cd00 { /* GPIO 14 */
+ };
+
+ gpio@ce00 { /* GPIO 15 */
+ qcom,mode = <1>;
+ qcom,output-type = <0>;
+ qcom,pull = <5>;
+ qcom,vin-sel = <2>;
+ qcom,out-strength = <3>;
+ qcom,src-select = <2>;
+ qcom,master-en = <1>;
+ };
+
+ gpio@cf00 { /* GPIO 16 */
+ };
+
+ gpio@d000 { /* GPIO 17 */
+ };
+
+ gpio@d100 { /* GPIO 18 */
+ };
+
+ gpio@d200 { /* GPIO 19 */
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,output-type = <0>; /* QPNP_PIN_OUT_BUF_CMOS */
+ qcom,pull = <5>; /* QPNP_PIN_PULL_NO */
+ qcom,vin-sel = <2>; /* QPNP_PIN_VIN2 */
+ qcom,out-strength = <2>; /* QPNP_PIN_OUT_STRENGTH_MED */
+ qcom,src-select = <0>; /* QPNP_PIN_SEL_FUNC_CONSTANT */
+ qcom,master-en = <1>;
+ };
+
+ gpio@d300 { /* GPIO 20 */
+ };
+
+ gpio@d400 { /* GPIO 21 */
+ };
+
+ gpio@d500 { /* GPIO 22 */
+ };
+
+ gpio@d600 { /* GPIO 23 */
+ };
+
+ gpio@d700 { /* GPIO 24 */
+ };
+
+ gpio@d800 { /* GPIO 25 */
+ };
+
+ gpio@d900 { /* GPIO 26 */
+ };
+
+ gpio@da00 { /* GPIO 27 */
+ };
+
+ gpio@db00 { /* GPIO 28 */
+ };
+
+ gpio@dc00 { /* GPIO 29 */
+ qcom,pull = <0>; /* set to default pull */
+ qcom,master-en = <1>;
+ qcom,vin-sel = <2>; /* select 1.8 V source */
+ };
+
+ gpio@dd00 { /* GPIO 30 */
+ };
+
+ gpio@de00 { /* GPIO 31 */
+ };
+
+ gpio@df00 { /* GPIO 32 */
+ };
+
+ gpio@e000 { /* GPIO 33 */
+ };
+
+ gpio@e100 { /* GPIO 34 */
+ };
+
+ gpio@e200 { /* GPIO 35 */
+ };
+
+ gpio@e300 { /* GPIO 36 */
+ };
+};
+
+&pm8941_mpps {
+
+ mpp@a000 { /* MPP 1 */
+ };
+
+ mpp@a100 { /* MPP 2 */
+ };
+
+ mpp@a200 { /* MPP 3 */
+ };
+
+ mpp@a300 { /* MPP 4 */
+ };
+
+ mpp@a400 { /* MPP 5 */
+ /* SPI_ETH config */
+ qcom,mode = <1>; /* DIG_OUT */
+ qcom,output-type = <0>; /* CMOS */
+ qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
+ qcom,src-select = <0>; /* CONSTANT */
+ qcom,master-en = <1>; /* ENABLE MPP */
+ };
+
+ mpp@a500 { /* MPP 6 */
+ /* SPI_ETH_RST config */
+ qcom,mode = <1>; /* DIG_OUT */
+ qcom,output-type = <0>; /* CMOS */
+ qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
+ qcom,src-select = <0>; /* CONSTANT */
+ qcom,master-en = <1>; /* ENABLE MPP */
+ };
+
+ mpp@a600 { /* MPP 7 */
+ };
+
+ mpp@a700 { /* MPP 8 */
+ };
+};
+
+&pm8841_mpps {
+
+ mpp@a000 { /* MPP 1 */
+ };
+
+ mpp@a100 { /* MPP 2 */
+ };
+
+ mpp@a200 { /* MPP 3 */
+ };
+
+ mpp@a300 { /* MPP 4 */
+ };
+};
diff --git a/arch/arm/boot/dts/msm8974-mdss.dtsi b/arch/arm/boot/dts/msm8974-mdss.dtsi
index ee5836c..ca98706 100644
--- a/arch/arm/boot/dts/msm8974-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8974-mdss.dtsi
@@ -18,6 +18,8 @@
reg-names = "mdp_phys", "vbif_phys";
interrupts = <0 72 0>;
vdd-supply = <&gdsc_mdss>;
+ qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
+ qcom,memory-reservation-size = <0x800000>; /* size 8MB */
};
mdss_dsi: qcom,mdss_dsi@fd922800 {
diff --git a/arch/arm/boot/dts/msm8974-mtp.dts b/arch/arm/boot/dts/msm8974-mtp.dts
index ed89368..00aec9f 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dts
+++ b/arch/arm/boot/dts/msm8974-mtp.dts
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -18,7 +18,7 @@
/ {
model = "Qualcomm MSM 8974 MTP";
compatible = "qcom,msm8974-mtp", "qcom,msm8974";
- qcom,msm-id = <126 8 0>, <126 3 0>;
+ qcom,msm-id = <126 8 0>;
serial@f991e000 {
status = "ok";
@@ -167,3 +167,196 @@
interrupt-names = "core_irq", "bam_irq", "status_irq";
cd-gpios = <&msmgpio 62 0x1>;
};
+
+&pm8941_gpios {
+ gpio@c000 { /* GPIO 1 */
+ };
+
+ gpio@c100 { /* GPIO 2 */
+ };
+
+ gpio@c200 { /* GPIO 3 */
+ qcom,mode = <0>;
+ qcom,pull = <0>;
+ qcom,vin-sel = <2>;
+ qcom,select = <0>;
+ };
+
+ gpio@c300 { /* GPIO 4 */
+ qcom,mode = <0>;
+ qcom,pull = <0>;
+ qcom,vin-sel = <2>;
+ qcom,select = <0>;
+ };
+
+ gpio@c400 { /* GPIO 5 */
+ qcom,mode = <0>;
+ qcom,pull = <0>;
+ qcom,vin-sel = <2>;
+ qcom,select = <0>;
+ };
+
+ gpio@c500 { /* GPIO 6 */
+ };
+
+ gpio@c600 { /* GPIO 7 */
+ };
+
+ gpio@c700 { /* GPIO 8 */
+ };
+
+ gpio@c800 { /* GPIO 9 */
+ };
+
+ gpio@c900 { /* GPIO 10 */
+ };
+
+ gpio@ca00 { /* GPIO 11 */
+ };
+
+ gpio@cb00 { /* GPIO 12 */
+ };
+
+ gpio@cc00 { /* GPIO 13 */
+ };
+
+ gpio@cd00 { /* GPIO 14 */
+ };
+
+ gpio@ce00 { /* GPIO 15 */
+ qcom,mode = <1>;
+ qcom,output-type = <0>;
+ qcom,pull = <5>;
+ qcom,vin-sel = <2>;
+ qcom,out-strength = <3>;
+ qcom,src-select = <2>;
+ qcom,master-en = <1>;
+ };
+
+ gpio@cf00 { /* GPIO 16 */
+ };
+
+ gpio@d000 { /* GPIO 17 */
+ };
+
+ gpio@d100 { /* GPIO 18 */
+ };
+
+ gpio@d200 { /* GPIO 19 */
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,output-type = <0>; /* QPNP_PIN_OUT_BUF_CMOS */
+ qcom,pull = <5>; /* QPNP_PIN_PULL_NO */
+ qcom,vin-sel = <2>; /* QPNP_PIN_VIN2 */
+ qcom,out-strength = <2>; /* QPNP_PIN_OUT_STRENGTH_MED */
+ qcom,src-select = <0>; /* QPNP_PIN_SEL_FUNC_CONSTANT */
+ qcom,master-en = <1>;
+ };
+
+ gpio@d300 { /* GPIO 20 */
+ };
+
+ gpio@d400 { /* GPIO 21 */
+ };
+
+ gpio@d500 { /* GPIO 22 */
+ };
+
+ gpio@d600 { /* GPIO 23 */
+ };
+
+ gpio@d700 { /* GPIO 24 */
+ };
+
+ gpio@d800 { /* GPIO 25 */
+ };
+
+ gpio@d900 { /* GPIO 26 */
+ };
+
+ gpio@da00 { /* GPIO 27 */
+ };
+
+ gpio@db00 { /* GPIO 28 */
+ };
+
+ gpio@dc00 { /* GPIO 29 */
+ qcom,pull = <0>; /* set to default pull */
+ qcom,master-en = <1>;
+ qcom,vin-sel = <2>; /* select 1.8 V source */
+ };
+
+ gpio@dd00 { /* GPIO 30 */
+ };
+
+ gpio@de00 { /* GPIO 31 */
+ };
+
+ gpio@df00 { /* GPIO 32 */
+ };
+
+ gpio@e000 { /* GPIO 33 */
+ };
+
+ gpio@e100 { /* GPIO 34 */
+ };
+
+ gpio@e200 { /* GPIO 35 */
+ };
+
+ gpio@e300 { /* GPIO 36 */
+ };
+};
+
+&pm8941_mpps {
+
+ mpp@a000 { /* MPP 1 */
+ };
+
+ mpp@a100 { /* MPP 2 */
+ };
+
+ mpp@a200 { /* MPP 3 */
+ };
+
+ mpp@a300 { /* MPP 4 */
+ };
+
+ mpp@a400 { /* MPP 5 */
+ /* SPI_ETH config */
+ qcom,mode = <1>; /* DIG_OUT */
+ qcom,output-type = <0>; /* CMOS */
+ qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
+ qcom,src-select = <0>; /* CONSTANT */
+ qcom,master-en = <1>; /* ENABLE MPP */
+ };
+
+ mpp@a500 { /* MPP 6 */
+ /* SPI_ETH_RST config */
+ qcom,mode = <1>; /* DIG_OUT */
+ qcom,output-type = <0>; /* CMOS */
+ qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
+ qcom,src-select = <0>; /* CONSTANT */
+ qcom,master-en = <1>; /* ENABLE MPP */
+ };
+
+ mpp@a600 { /* MPP 7 */
+ };
+
+ mpp@a700 { /* MPP 8 */
+ };
+};
+
+&pm8841_mpps {
+
+ mpp@a000 { /* MPP 1 */
+ };
+
+ mpp@a100 { /* MPP 2 */
+ };
+
+ mpp@a200 { /* MPP 3 */
+ };
+
+ mpp@a300 { /* MPP 4 */
+ };
+};
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index b634f61..b992e86 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -239,6 +239,19 @@
qcom,bam-dma-res-pipes = <6>;
};
+ spi@f9966000 {
+ compatible = "qcom,spi-qup-v2";
+ cell-index = <7>;
+ reg = <0xf9966000 0x1000>;
+ interrupts = <0 104 0>;
+ spi-max-frequency = <19200000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ gpios = <&msmgpio 56 0>, /* CLK */
+ <&msmgpio 54 0>, /* MISO */
+ <&msmgpio 53 0>; /* MOSI */
+ cs-gpios = <&msmgpio 55 0>;
+ };
slim@fe12f000 {
cell-index = <1>;
@@ -1044,5 +1057,4 @@
/include/ "msm-pm8841.dtsi"
/include/ "msm-pm8941.dtsi"
/include/ "msm8974-regulator.dtsi"
-/include/ "msm8974-gpio.dtsi"
/include/ "msm8974-clock.dtsi"
diff --git a/arch/arm/boot/dts/msm8974_pm.dtsi b/arch/arm/boot/dts/msm8974_pm.dtsi
index 77f2532..e39a72a 100644
--- a/arch/arm/boot/dts/msm8974_pm.dtsi
+++ b/arch/arm/boot/dts/msm8974_pm.dtsi
@@ -117,10 +117,9 @@
qcom,vctl-port = <0x0>;
qcom,phase-port = <0x1>;
qcom,saw2-spm-cmd-ret = [00 20 03 22 00 0f];
- qcom,saw2-spm-cmd-gdhs = [00 20 32 0b 42 07 44 22 50 02 32 50
- 0f];
- qcom,saw2-spm-cmd-pc = [00 10 32 b0 11 0b 42 07 01 b0 12 44 a0
- 50 02 32 a0 50 0f];
+ qcom,saw2-spm-cmd-gdhs = [00 20 32 42 07 44 22 50 02 32 50 0f];
+ qcom,saw2-spm-cmd-pc = [00 10 32 b0 11 42 07 01 b0 12 44
+ 50 02 32 50 0f];
};
qcom,lpm-resources {
diff --git a/arch/arm/boot/dts/msm9625-ion.dtsi b/arch/arm/boot/dts/msm9625-ion.dtsi
new file mode 100644
index 0000000..8183264
--- /dev/null
+++ b/arch/arm/boot/dts/msm9625-ion.dtsi
@@ -0,0 +1,35 @@
+/* Copyright (c) 2012, 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.
+ */
+
+/ {
+ qcom,ion {
+ compatible = "qcom,msm-ion";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ qcom,ion-heap@30 { /* SYSTEM HEAP */
+ reg = <30>;
+ };
+
+ qcom,ion-heap@25 { /* IOMMU HEAP */
+ reg = <25>;
+ };
+
+ qcom,ion-heap@28 { /* AUDIO HEAP */
+ compatible = "qcom,msm-ion-reserve";
+ reg = <28>;
+ qcom,heap-align = <0x1000>;
+ qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
+ qcom,memory-reservation-size = <0xAF000>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index f50d14f..a8a2bf1 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -11,6 +11,7 @@
*/
/include/ "skeleton.dtsi"
+/include/ "msm9625-ion.dtsi"
/ {
model = "Qualcomm MSM 9625";
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 9dd4347..6b8a374 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -1167,41 +1167,35 @@
/*
* Configure the GIC after we come out of power collapse.
* This function will configure some of the GIC registers so as to prepare the
- * core1 to receive an SPI(ACSR_MP_CORE_IPC1, (32 + 8)), which will bring
- * core1 out of GDFS.
+ * secondary cores to receive an SPI(ACSR_MP_CORE_IPC1/IPC2/IPC3, 40/92/93),
+ * which will bring cores out of GDFS.
*/
-void core1_gic_configure_and_raise(void)
+void gic_configure_and_raise(unsigned int irq, unsigned int cpu)
{
struct gic_chip_data *gic = &gic_data[0];
+ struct irq_data *d = irq_get_irq_data(irq);
void __iomem *base = gic_data_dist_base(gic);
- unsigned int value = 0;
+ unsigned int value = 0, byte_offset, offset, bit;
unsigned long flags;
+ offset = ((gic_irq(d) / 32) * 4);
+ bit = BIT(gic_irq(d) % 32);
+
raw_spin_lock_irqsave(&irq_controller_lock, flags);
- value = __raw_readl(base + GIC_DIST_ACTIVE_BIT + 0x4);
- value |= BIT(8);
- __raw_writel(value, base + GIC_DIST_ACTIVE_BIT + 0x4);
+ value = __raw_readl(base + GIC_DIST_ACTIVE_BIT + offset);
+ __raw_writel(value | bit, base + GIC_DIST_ACTIVE_BIT + offset);
mb();
- value = __raw_readl(base + GIC_DIST_TARGET + 0x24);
- value |= BIT(13);
- __raw_writel(value, base + GIC_DIST_TARGET + 0x24);
+ value = __raw_readl(base + GIC_DIST_TARGET + (gic_irq(d) / 4) * 4);
+ byte_offset = (gic_irq(d) % 4) * 8;
+ value |= 1 << (cpu + byte_offset);
+ __raw_writel(value, base + GIC_DIST_TARGET + (gic_irq(d) / 4) * 4);
mb();
- value = __raw_readl(base + GIC_DIST_TARGET + 0x28);
- value |= BIT(1);
- __raw_writel(value, base + GIC_DIST_TARGET + 0x28);
+ value = __raw_readl(base + GIC_DIST_ENABLE_SET + offset);
+ __raw_writel(value | bit, base + GIC_DIST_ENABLE_SET + offset);
mb();
- value = __raw_readl(base + GIC_DIST_ENABLE_SET + 0x4);
- value |= BIT(8);
- __raw_writel(value, base + GIC_DIST_ENABLE_SET + 0x4);
- mb();
-
- value = __raw_readl(base + GIC_DIST_PENDING_SET + 0x4);
- value |= BIT(8);
- __raw_writel(value, base + GIC_DIST_PENDING_SET + 0x4);
- mb();
raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
}
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index 3fdc804..45d52e4 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -506,3 +506,4 @@
CONFIG_CRYPTO_DEV_QCEDEV=m
CONFIG_CRC_CCITT=y
CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_CONTROL_TRACE=m
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 4daaa12..465598f 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -524,3 +524,4 @@
CONFIG_CRYPTO_DEV_QCEDEV=m
CONFIG_CRC_CCITT=y
CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_CONTROL_TRACE=m
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index 47f9ba3..2f1833e 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -402,3 +402,4 @@
CONFIG_CRYPTO_DEV_QCE=m
CONFIG_CRYPTO_DEV_QCEDEV=m
CONFIG_CRC_CCITT=y
+CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index f6e51af..1230fbe 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -398,7 +398,6 @@
CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
# CONFIG_DEBUG_PREEMPT is not set
CONFIG_DEBUG_SPINLOCK=y
-CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_ATOMIC_SLEEP=y
CONFIG_DEBUG_STACK_USAGE=y
CONFIG_DEBUG_INFO=y
@@ -422,3 +421,4 @@
CONFIG_CRYPTO_DEV_QCE=m
CONFIG_CRYPTO_DEV_QCEDEV=m
CONFIG_CRC_CCITT=y
+CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index 4cb3f6b..284f5fc 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -113,6 +113,7 @@
CONFIG_USB_BAM=y
CONFIG_SPS_SUPPORT_BAMDMA=y
CONFIG_SPS_SUPPORT_NDP_BAM=y
+CONFIG_QPNP_POWER_ON=y
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
CONFIG_YAFFS_FS=y
@@ -146,11 +147,3 @@
# CONFIG_CRYPTO_HW is not set
CONFIG_CRC_CCITT=y
CONFIG_LIBCRC32C=y
-CONFIG_MMC=y
-CONFIG_MMC_PERF_PROFILING=y
-CONFIG_MMC_CLKGATE=y
-CONFIG_MMC_PARANOID_SD_INIT=y
-CONFIG_MMC_BLOCK_MINORS=32
-CONFIG_MMC_TEST=m
-CONFIG_MMC_MSM=y
-CONFIG_MMC_MSM_SPS_SUPPORT=y
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
index ad12bcd..72c3c27 100644
--- a/arch/arm/include/asm/hardware/gic.h
+++ b/arch/arm/include/asm/hardware/gic.h
@@ -62,7 +62,7 @@
void msm_gic_save(void);
void msm_gic_restore(void);
-void core1_gic_configure_and_raise(void);
+void gic_configure_and_raise(unsigned int irq, unsigned int cpu);
#endif
#endif
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index d7872c3..2020422 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -1903,13 +1903,13 @@
config MSM_PIL_MODEM
tristate "Modem (ARM11) Boot Support"
- depends on MSM_PIL
+ depends on MSM_PIL && MSM_SUBSYSTEM_RESTART
help
Support for booting and shutting down ARM11 Modem processors.
config MSM_PIL_QDSP6V3
tristate "QDSP6v3 (Hexagon) Boot Support"
- depends on MSM_PIL
+ depends on MSM_PIL && MSM_SUBSYSTEM_RESTART
help
Support for booting and shutting down QDSP6v3 processors (hexagon).
The QDSP6 is a low power DSP used in audio software applications.
@@ -1945,7 +1945,7 @@
config MSM_PIL_RIVA
tristate "RIVA (WCNSS) Boot Support"
- depends on MSM_PIL
+ depends on MSM_PIL && MSM_SUBSYSTEM_RESTART
help
Support for booting and shutting down the RIVA processor (WCNSS).
Riva is the wireless subsystem processor used in bluetooth, wireless
@@ -1984,8 +1984,8 @@
Venus is the Video subsystem processor used for video codecs.
config MSM_PIL_GSS
- tristate "GSS (Coretx A5) Boot Support"
- depends on MSM_PIL
+ tristate "GSS (Cortex A5) Boot Support"
+ depends on MSM_PIL && MSM_SUBSYSTEM_RESTART
help
Support for booting and shutting down Cortex A5 processors which run
GPS subsystem firmware.
@@ -2018,22 +2018,6 @@
lpass hardware watchdog interrupt lines and plugs into the subsystem
restart and PIL drivers. For MSM9615, it only supports a full chip reset.
-config MSM_WCNSS_SSR_8960
- tristate "MSM 8960 WCNSS restart module"
- depends on (ARCH_MSM8960)
- help
- This option enables the WCNSS restart module for MSM8960, which
- monitors WCNSS hardware watchdog interrupt lines and plugs WCNSS
- into the subsystem restart framework.
-
-config MSM_GSS_SSR_8064
- bool "MSM 8064 GSS restart driver"
- depends on (ARCH_APQ8064)
- help
- This option enables the gps subsystem restart driver for APQ8064, which monitors
- gss hardware watchdog interrupt lines and plugs into the subsystem
- restart and PIL drivers.
-
config MSM_MODEM_SSR_8974
bool "MSM 8974 Modem restart driver"
depends on (ARCH_MSM8974)
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 4a234a4..7dece76 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -65,6 +65,8 @@
$(obj)/smd_rpc_sym.c: $(src)/smd_rpc_sym $(src)/mkrpcsym.pl
$(call if_changed,mkrpcsym)
+obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o remote_spinlock.o smd_private.o
+
obj-$(CONFIG_MSM_SCM) += scm.o scm-boot.o
obj-$(CONFIG_MSM_SECURE_IO) += scm-io.o
obj-$(CONFIG_MSM_PIL) += peripheral-loader.o
@@ -96,7 +98,6 @@
ifdef CONFIG_DEBUG_FS
obj-$(CONFIG_MSM_IPC_LOGGING) += ipc_logging_debug.o
endif
-obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o remote_spinlock.o smd_private.o
obj-y += socinfo.o
ifndef CONFIG_ARCH_MSM8960
ifndef CONFIG_ARCH_MSM8X60
@@ -194,15 +195,12 @@
obj-y += subsystem_notif.o
obj-y += subsystem_restart.o
obj-y += ramdump.o
- obj-$(CONFIG_ARCH_MSM8X60) += modem-8660.o lpass-8660.o
endif
obj-$(CONFIG_MSM_SYSMON_COMM) += sysmon.o
obj-$(CONFIG_MSM_MODEM_8960) += modem-8960.o
obj-$(CONFIG_MSM_MODEM_SSR_8974) += modem-ssr-8974.o
obj-$(CONFIG_MSM_LPASS_8960) += lpass-8960.o
obj-$(CONFIG_MSM_ADSP_SSR_8974) += adsp-8974.o
-obj-$(CONFIG_MSM_WCNSS_SSR_8960) += wcnss-ssr-8960.o
-obj-$(CONFIG_MSM_GSS_SSR_8064) += gss-8064.o
ifdef CONFIG_CPU_IDLE
obj-$(CONFIG_ARCH_APQ8064) += cpuidle.o
@@ -288,7 +286,6 @@
obj-$(CONFIG_ARCH_MSM8974) += gdsc.o
obj-$(CONFIG_ARCH_MSM8974) += krait-regulator.o
obj-$(CONFIG_ARCH_MSM9625) += board-9625.o board-9625-gpiomux.o
-obj-$(CONFIG_ARCH_MSM9625) += clock-local2.o clock-pll.o clock-9625.o clock-rpm.o clock-voter.o
obj-$(CONFIG_ARCH_MSM8930) += acpuclock-8930.o acpuclock-8627.o acpuclock-8930aa.o
obj-$(CONFIG_ARCH_MPQ8092) += board-8092.o board-8092-gpiomux.o
obj-$(CONFIG_ARCH_MSM8226) += board-8226.o board-8226-gpiomux.o
@@ -351,7 +348,7 @@
obj-$(CONFIG_ARCH_MSM8226) += gpiomux-v2.o gpiomux.o
obj-$(CONFIG_MSM_SLEEP_STATS_DEVICE) += idle_stats_device.o
-obj-$(CONFIG_MSM_DCVS) += msm_dcvs_scm.o msm_dcvs.o msm_dcvs_idle.o
+obj-$(CONFIG_MSM_DCVS) += msm_dcvs_scm.o msm_dcvs.o msm_dcvs_idle.o msm_mpdecision.o
obj-$(CONFIG_MSM_RUN_QUEUE_STATS) += msm_rq_stats.o
obj-$(CONFIG_MSM_SHOW_RESUME_IRQ) += msm_show_resume_irq.o
obj-$(CONFIG_BT_MSM_PINTEST) += btpintest.o
diff --git a/arch/arm/mach-msm/acpuclock-8064.c b/arch/arm/mach-msm/acpuclock-8064.c
index d0de62b..d10211bc 100644
--- a/arch/arm/mach-msm/acpuclock-8064.c
+++ b/arch/arm/mach-msm/acpuclock-8064.c
@@ -18,6 +18,7 @@
#include <mach/msm_bus_board.h>
#include <mach/msm_bus.h>
+#include "mach/socinfo.h"
#include "acpuclock.h"
#include "acpuclock-krait.h"
@@ -94,6 +95,10 @@
},
};
+/*
+ * The correct maximum rate for 8064ab in 600 MHZ.
+ * We rely on the RPM rounding requests up here.
+*/
static struct msm_bus_paths bw_level_tbl[] __initdata = {
[0] = BW_MBPS(640), /* At least 80 MHz on bus. */
[1] = BW_MBPS(1064), /* At least 133 MHz on bus. */
@@ -110,7 +115,7 @@
.name = "acpuclk-8064",
};
-static struct l2_level l2_freq_tbl[] __initdata __initdata = {
+static struct l2_level l2_freq_tbl[] __initdata = {
[0] = { { 384000, PLL_8, 0, 0x00 }, 1050000, 1050000, 1 },
[1] = { { 432000, HFPLL, 2, 0x20 }, 1050000, 1050000, 2 },
[2] = { { 486000, HFPLL, 2, 0x24 }, 1050000, 1050000, 2 },
@@ -127,10 +132,12 @@
[13] = { { 1080000, HFPLL, 1, 0x28 }, 1150000, 1150000, 5 },
[14] = { { 1134000, HFPLL, 1, 0x2A }, 1150000, 1150000, 5 },
[15] = { { 1188000, HFPLL, 1, 0x2C }, 1150000, 1150000, 5 },
+ /* L2 Level 16 is for 8064ab only */
+ [16] = { { 1242000, HFPLL, 1, 0x2E }, 1150000, 1150000, 5 },
{ }
};
-static struct acpu_level acpu_freq_tbl_slow[] __initdata = {
+static struct acpu_level tbl_slow[] __initdata = {
{ 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 950000 },
{ 0, { 432000, HFPLL, 2, 0x20 }, L2(6), 975000 },
{ 1, { 486000, HFPLL, 2, 0x24 }, L2(6), 975000 },
@@ -156,7 +163,7 @@
{ 0, { 0 } }
};
-static struct acpu_level acpu_freq_tbl_nom[] __initdata = {
+static struct acpu_level tbl_nom[] __initdata = {
{ 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 900000 },
{ 0, { 432000, HFPLL, 2, 0x20 }, L2(6), 925000 },
{ 1, { 486000, HFPLL, 2, 0x24 }, L2(6), 925000 },
@@ -182,7 +189,7 @@
{ 0, { 0 } }
};
-static struct acpu_level acpu_freq_tbl_fast[] __initdata = {
+static struct acpu_level tbl_fast[] __initdata = {
{ 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 850000 },
{ 0, { 432000, HFPLL, 2, 0x20 }, L2(6), 875000 },
{ 1, { 486000, HFPLL, 2, 0x24 }, L2(6), 875000 },
@@ -208,12 +215,91 @@
{ 0, { 0 } }
};
-static struct pvs_table pvs_tables[NUM_PVS] __initdata = {
-[PVS_SLOW] = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow), 0 },
-[PVS_NOMINAL] = { acpu_freq_tbl_nom, sizeof(acpu_freq_tbl_nom), 25000 },
-[PVS_FAST] = { acpu_freq_tbl_fast, sizeof(acpu_freq_tbl_fast), 25000 },
-/* TODO: update the faster table when data is available */
-[PVS_FASTER] = { acpu_freq_tbl_fast, sizeof(acpu_freq_tbl_fast), 25000 },
+static struct acpu_level tbl_slow_1p7[] __initdata = {
+ { 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 950000 },
+ { 0, { 432000, HFPLL, 2, 0x20 }, L2(6), 975000 },
+ { 1, { 486000, HFPLL, 2, 0x24 }, L2(6), 975000 },
+ { 0, { 540000, HFPLL, 2, 0x28 }, L2(6), 1000000 },
+ { 1, { 594000, HFPLL, 1, 0x16 }, L2(6), 1000000 },
+ { 0, { 648000, HFPLL, 1, 0x18 }, L2(6), 1025000 },
+ { 1, { 702000, HFPLL, 1, 0x1A }, L2(6), 1025000 },
+ { 0, { 756000, HFPLL, 1, 0x1C }, L2(6), 1075000 },
+ { 1, { 810000, HFPLL, 1, 0x1E }, L2(6), 1075000 },
+ { 0, { 864000, HFPLL, 1, 0x20 }, L2(6), 1100000 },
+ { 1, { 918000, HFPLL, 1, 0x22 }, L2(6), 1100000 },
+ { 0, { 972000, HFPLL, 1, 0x24 }, L2(6), 1125000 },
+ { 1, { 1026000, HFPLL, 1, 0x26 }, L2(6), 1125000 },
+ { 0, { 1080000, HFPLL, 1, 0x28 }, L2(15), 1175000 },
+ { 1, { 1134000, HFPLL, 1, 0x2A }, L2(15), 1175000 },
+ { 0, { 1188000, HFPLL, 1, 0x2C }, L2(15), 1200000 },
+ { 1, { 1242000, HFPLL, 1, 0x2E }, L2(15), 1200000 },
+ { 0, { 1296000, HFPLL, 1, 0x30 }, L2(15), 1225000 },
+ { 1, { 1350000, HFPLL, 1, 0x32 }, L2(15), 1225000 },
+ { 0, { 1404000, HFPLL, 1, 0x34 }, L2(15), 1237500 },
+ { 1, { 1458000, HFPLL, 1, 0x36 }, L2(15), 1237500 },
+ { 1, { 1512000, HFPLL, 1, 0x38 }, L2(15), 1250000 },
+ { 1, { 1566000, HFPLL, 1, 0x3A }, L2(15), 1250000 },
+ { 1, { 1620000, HFPLL, 1, 0x3C }, L2(15), 1250000 },
+ { 1, { 1674000, HFPLL, 1, 0x3E }, L2(15), 1250000 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level tbl_slow_2p0[] __initdata = {
+ { 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 950000 },
+ { 0, { 432000, HFPLL, 2, 0x20 }, L2(6), 975000 },
+ { 1, { 486000, HFPLL, 2, 0x24 }, L2(6), 975000 },
+ { 0, { 540000, HFPLL, 2, 0x28 }, L2(6), 1000000 },
+ { 1, { 594000, HFPLL, 1, 0x16 }, L2(6), 1000000 },
+ { 0, { 648000, HFPLL, 1, 0x18 }, L2(6), 1025000 },
+ { 1, { 702000, HFPLL, 1, 0x1A }, L2(6), 1025000 },
+ { 0, { 756000, HFPLL, 1, 0x1C }, L2(6), 1075000 },
+ { 1, { 810000, HFPLL, 1, 0x1E }, L2(6), 1075000 },
+ { 0, { 864000, HFPLL, 1, 0x20 }, L2(6), 1100000 },
+ { 1, { 918000, HFPLL, 1, 0x22 }, L2(6), 1100000 },
+ { 0, { 972000, HFPLL, 1, 0x24 }, L2(6), 1125000 },
+ { 1, { 1026000, HFPLL, 1, 0x26 }, L2(6), 1125000 },
+ { 0, { 1080000, HFPLL, 1, 0x28 }, L2(15), 1175000 },
+ { 1, { 1134000, HFPLL, 1, 0x2A }, L2(15), 1175000 },
+ { 0, { 1188000, HFPLL, 1, 0x2C }, L2(15), 1200000 },
+ { 1, { 1242000, HFPLL, 1, 0x2E }, L2(15), 1200000 },
+ { 0, { 1296000, HFPLL, 1, 0x30 }, L2(15), 1225000 },
+ { 1, { 1350000, HFPLL, 1, 0x32 }, L2(15), 1225000 },
+ { 0, { 1404000, HFPLL, 1, 0x34 }, L2(15), 1237500 },
+ { 1, { 1458000, HFPLL, 1, 0x36 }, L2(15), 1237500 },
+ { 1, { 1512000, HFPLL, 1, 0x38 }, L2(15), 1250000 },
+ { 1, { 1566000, HFPLL, 1, 0x3A }, L2(15), 1250000 },
+ { 1, { 1620000, HFPLL, 1, 0x3C }, L2(15), 1250000 },
+ { 1, { 1674000, HFPLL, 1, 0x3E }, L2(15), 1250000 },
+ { 1, { 1728000, HFPLL, 1, 0x40 }, L2(15), 1250000 },
+ { 1, { 1782000, HFPLL, 1, 0x42 }, L2(15), 1250000 },
+ { 1, { 1836000, HFPLL, 1, 0x44 }, L2(15), 1250000 },
+ { 1, { 1890000, HFPLL, 1, 0x46 }, L2(15), 1250000 },
+ { 1, { 1944000, HFPLL, 1, 0x48 }, L2(15), 1250000 },
+ { 1, { 1998000, HFPLL, 1, 0x4A }, L2(15), 1250000 },
+ { 0, { 0 } }
+};
+
+static struct pvs_table pvs_tables[NUM_SPEED_BINS][NUM_PVS] __initdata = {
+ [0][PVS_SLOW] = {tbl_slow, sizeof(tbl_slow), 0 },
+ [0][PVS_NOMINAL] = {tbl_nom, sizeof(tbl_nom), 25000 },
+ [0][PVS_FAST] = {tbl_fast, sizeof(tbl_fast), 25000 },
+ [0][PVS_FASTER] = {tbl_fast, sizeof(tbl_fast), 25000 },
+
+ [1][0] = { tbl_slow_1p7, sizeof(tbl_slow_1p7), 0 },
+ [1][1] = { tbl_slow_1p7, sizeof(tbl_slow_1p7), 0 },
+ [1][2] = { tbl_slow_1p7, sizeof(tbl_slow_1p7), 0 },
+ [1][3] = { tbl_slow_1p7, sizeof(tbl_slow_1p7), 0 },
+ [1][4] = { tbl_slow_1p7, sizeof(tbl_slow_1p7), 0 },
+ [1][5] = { tbl_slow_1p7, sizeof(tbl_slow_1p7), 0 },
+ [1][6] = { tbl_slow_1p7, sizeof(tbl_slow_1p7), 0 },
+
+ [2][0] = { tbl_slow_2p0, sizeof(tbl_slow_2p0), 0 },
+ [2][1] = { tbl_slow_2p0, sizeof(tbl_slow_2p0), 0 },
+ [2][2] = { tbl_slow_2p0, sizeof(tbl_slow_2p0), 0 },
+ [2][3] = { tbl_slow_2p0, sizeof(tbl_slow_2p0), 0 },
+ [2][4] = { tbl_slow_2p0, sizeof(tbl_slow_2p0), 0 },
+ [2][5] = { tbl_slow_2p0, sizeof(tbl_slow_2p0), 0 },
+ [2][6] = { tbl_slow_2p0, sizeof(tbl_slow_2p0), 0 },
};
static struct acpuclk_krait_params acpuclk_8064_params __initdata = {
@@ -230,6 +316,12 @@
static int __init acpuclk_8064_probe(struct platform_device *pdev)
{
+ if (cpu_is_apq8064ab() ||
+ SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 2) {
+ acpuclk_8064_params.hfpll_data->low_vdd_l_max = 37;
+ acpuclk_8064_params.hfpll_data->nom_vdd_l_max = 74;
+ }
+
return acpuclk_krait_init(&pdev->dev, &acpuclk_8064_params);
}
diff --git a/arch/arm/mach-msm/acpuclock-8627.c b/arch/arm/mach-msm/acpuclock-8627.c
index da49656..ac29cac 100644
--- a/arch/arm/mach-msm/acpuclock-8627.c
+++ b/arch/arm/mach-msm/acpuclock-8627.c
@@ -127,10 +127,10 @@
{ 0, { 0 } }
};
-static struct pvs_table pvs_tables[NUM_PVS] __initdata = {
- [PVS_SLOW] = { acpu_freq_tbl, sizeof(acpu_freq_tbl), 0 },
- [PVS_NOMINAL] = { acpu_freq_tbl, sizeof(acpu_freq_tbl), 25000 },
- [PVS_FAST] = { acpu_freq_tbl, sizeof(acpu_freq_tbl), 25000 },
+static struct pvs_table pvs_tables[NUM_SPEED_BINS][NUM_PVS] __initdata = {
+ [0][PVS_SLOW] = { acpu_freq_tbl, sizeof(acpu_freq_tbl), 0 },
+ [0][PVS_NOMINAL] = { acpu_freq_tbl, sizeof(acpu_freq_tbl), 25000 },
+ [0][PVS_FAST] = { acpu_freq_tbl, sizeof(acpu_freq_tbl), 25000 },
};
static struct acpuclk_krait_params acpuclk_8627_params __initdata = {
diff --git a/arch/arm/mach-msm/acpuclock-8930.c b/arch/arm/mach-msm/acpuclock-8930.c
index b4f2a1e..e46599a 100644
--- a/arch/arm/mach-msm/acpuclock-8930.c
+++ b/arch/arm/mach-msm/acpuclock-8930.c
@@ -213,10 +213,10 @@
{ 0, { 0 } }
};
-static struct pvs_table pvs_tables[NUM_PVS] __initdata = {
-[PVS_SLOW] = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow), 0 },
-[PVS_NOMINAL] = { acpu_freq_tbl_nom, sizeof(acpu_freq_tbl_nom), 25000 },
-[PVS_FAST] = { acpu_freq_tbl_fast, sizeof(acpu_freq_tbl_fast), 25000 },
+static struct pvs_table pvs_tables[NUM_SPEED_BINS][NUM_PVS] __initdata = {
+[0][PVS_SLOW] = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow), 0 },
+[0][PVS_NOMINAL] = { acpu_freq_tbl_nom, sizeof(acpu_freq_tbl_nom), 25000 },
+[0][PVS_FAST] = { acpu_freq_tbl_fast, sizeof(acpu_freq_tbl_fast), 25000 },
};
static struct acpuclk_krait_params acpuclk_8930_params __initdata = {
diff --git a/arch/arm/mach-msm/acpuclock-8930aa.c b/arch/arm/mach-msm/acpuclock-8930aa.c
index bcb00ea..9d2b6fc 100644
--- a/arch/arm/mach-msm/acpuclock-8930aa.c
+++ b/arch/arm/mach-msm/acpuclock-8930aa.c
@@ -189,10 +189,10 @@
{ 0, { 0 } }
};
-static struct pvs_table pvs_tables[NUM_PVS] __initdata = {
-[PVS_SLOW] = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow), 0 },
-[PVS_NOMINAL] = { acpu_freq_tbl_nom, sizeof(acpu_freq_tbl_nom), 25000 },
-[PVS_FAST] = { acpu_freq_tbl_fast, sizeof(acpu_freq_tbl_fast), 25000 },
+static struct pvs_table pvs_tables[NUM_SPEED_BINS][NUM_PVS] __initdata = {
+[0][PVS_SLOW] = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow), 0 },
+[0][PVS_NOMINAL] = { acpu_freq_tbl_nom, sizeof(acpu_freq_tbl_nom), 25000 },
+[0][PVS_FAST] = { acpu_freq_tbl_fast, sizeof(acpu_freq_tbl_fast), 25000 },
};
static struct acpuclk_krait_params acpuclk_8930aa_params __initdata = {
diff --git a/arch/arm/mach-msm/acpuclock-8960.c b/arch/arm/mach-msm/acpuclock-8960.c
index cf6a6c2..d7d3edd 100644
--- a/arch/arm/mach-msm/acpuclock-8960.c
+++ b/arch/arm/mach-msm/acpuclock-8960.c
@@ -195,10 +195,10 @@
{ 0, { 0 } }
};
-static struct pvs_table pvs_tables[NUM_PVS] __initdata = {
-[PVS_SLOW] = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow), 0 },
-[PVS_NOMINAL] = { acpu_freq_tbl_nom, sizeof(acpu_freq_tbl_nom), 25000 },
-[PVS_FAST] = { acpu_freq_tbl_fast, sizeof(acpu_freq_tbl_fast), 25000 },
+static struct pvs_table pvs_tables[NUM_SPEED_BINS][NUM_PVS] __initdata = {
+[0][PVS_SLOW] = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow), 0 },
+[0][PVS_NOMINAL] = { acpu_freq_tbl_nom, sizeof(acpu_freq_tbl_nom), 25000 },
+[0][PVS_FAST] = { acpu_freq_tbl_fast, sizeof(acpu_freq_tbl_fast), 25000 },
};
static struct acpuclk_krait_params acpuclk_8960_params __initdata = {
diff --git a/arch/arm/mach-msm/acpuclock-8960ab.c b/arch/arm/mach-msm/acpuclock-8960ab.c
index 91ccd37..ae1cd7b 100644
--- a/arch/arm/mach-msm/acpuclock-8960ab.c
+++ b/arch/arm/mach-msm/acpuclock-8960ab.c
@@ -135,10 +135,10 @@
{ 0, { 0 } }
};
-static struct pvs_table pvs_tables[NUM_PVS] __initdata = {
-[PVS_SLOW] = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow), 0 },
-[PVS_NOMINAL] = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow), 0 },
-[PVS_FAST] = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow), 0 },
+static struct pvs_table pvs_tables[NUM_SPEED_BINS][NUM_PVS] __initdata = {
+[0][PVS_SLOW] = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow), 0 },
+[0][PVS_NOMINAL] = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow), 0 },
+[0][PVS_FAST] = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow), 0 },
};
static struct acpuclk_krait_params acpuclk_8960ab_params __initdata = {
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index 4a755bd..098f854 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -170,10 +170,10 @@
{ 0, { 0 } }
};
-static struct pvs_table pvs_tables[NUM_PVS] __initdata = {
- [PVS_SLOW] = { acpu_freq_tbl, sizeof(acpu_freq_tbl) },
- [PVS_NOMINAL] = { acpu_freq_tbl, sizeof(acpu_freq_tbl) },
- [PVS_FAST] = { acpu_freq_tbl, sizeof(acpu_freq_tbl) },
+static struct pvs_table pvs_tables[NUM_SPEED_BINS][NUM_PVS] __initdata = {
+ [0][PVS_SLOW] = { acpu_freq_tbl, sizeof(acpu_freq_tbl) },
+ [0][PVS_NOMINAL] = { acpu_freq_tbl, sizeof(acpu_freq_tbl) },
+ [0][PVS_FAST] = { acpu_freq_tbl, sizeof(acpu_freq_tbl) },
};
static struct acpuclk_krait_params acpuclk_8974_params __initdata = {
diff --git a/arch/arm/mach-msm/acpuclock-krait.c b/arch/arm/mach-msm/acpuclock-krait.c
index 79c01b2..57c4411 100644
--- a/arch/arm/mach-msm/acpuclock-krait.c
+++ b/arch/arm/mach-msm/acpuclock-krait.c
@@ -946,58 +946,68 @@
}
}
-static int __init select_freq_plan(u32 pte_efuse_phys)
+static int __init get_speed_bin(u32 pte_efuse)
+{
+ uint32_t speed_bin;
+
+ speed_bin = pte_efuse & 0xF;
+ if (speed_bin == 0xF)
+ speed_bin = (pte_efuse >> 4) & 0xF;
+
+ if (speed_bin == 0xF) {
+ speed_bin = 0;
+ dev_warn(drv.dev, "SPEED BIN: Defaulting to %d\n", speed_bin);
+ } else {
+ dev_info(drv.dev, "SPEED BIN: %d\n", speed_bin);
+ }
+
+ return speed_bin;
+}
+
+static int __init get_pvs_bin(u32 pte_efuse)
+{
+ uint32_t pvs_bin;
+
+ pvs_bin = (pte_efuse >> 10) & 0x7;
+ if (pvs_bin == 0x7)
+ pvs_bin = (pte_efuse >> 13) & 0x7;
+
+ if (pvs_bin == 0x7) {
+ pvs_bin = 0;
+ dev_warn(drv.dev, "ACPU PVS: Defaulting to %d\n", pvs_bin);
+ } else {
+ dev_info(drv.dev, "ACPU PVS: %d\n", pvs_bin);
+ }
+
+ return pvs_bin;
+}
+
+static struct pvs_table * __init select_freq_plan(u32 pte_efuse_phys,
+ struct pvs_table (*pvs_tables)[NUM_PVS])
{
void __iomem *pte_efuse;
- u32 pte_efuse_val, pvs, tbl_idx;
- char *pvs_names[] = { "Slow", "Nominal", "Fast", "Faster", "Unknown" };
+ u32 pte_efuse_val, tbl_idx, bin_idx;
pte_efuse = ioremap(pte_efuse_phys, 4);
- /* Select frequency tables. */
- if (pte_efuse) {
- pte_efuse_val = readl_relaxed(pte_efuse);
- pvs = (pte_efuse_val >> 10) & 0x7;
- iounmap(pte_efuse);
- if (pvs == 0x7)
- pvs = (pte_efuse_val >> 13) & 0x7;
-
- switch (pvs) {
- case 0x0:
- case 0x7:
- tbl_idx = PVS_SLOW;
- break;
- case 0x1:
- tbl_idx = PVS_NOMINAL;
- break;
- case 0x3:
- tbl_idx = PVS_FAST;
- break;
- case 0x4:
- tbl_idx = PVS_FASTER;
- break;
- default:
- tbl_idx = PVS_UNKNOWN;
- break;
- }
- } else {
- tbl_idx = PVS_UNKNOWN;
+ if (!pte_efuse) {
dev_err(drv.dev, "Unable to map QFPROM base\n");
- }
- if (tbl_idx == PVS_UNKNOWN) {
- tbl_idx = PVS_SLOW;
- dev_warn(drv.dev, "ACPU PVS: Defaulting to %s\n",
- pvs_names[tbl_idx]);
- } else {
- dev_info(drv.dev, "ACPU PVS: %s\n", pvs_names[tbl_idx]);
+ return NULL;
}
- return tbl_idx;
+ pte_efuse_val = readl_relaxed(pte_efuse);
+ iounmap(pte_efuse);
+
+ /* Select frequency tables. */
+ bin_idx = get_speed_bin(pte_efuse_val);
+ tbl_idx = get_pvs_bin(pte_efuse_val);
+
+ return &pvs_tables[bin_idx][tbl_idx];
}
static void __init drv_data_init(struct device *dev,
const struct acpuclk_krait_params *params)
{
- int tbl_idx;
+ struct pvs_table *pvs;
drv.dev = dev;
drv.scalable = kmemdup(params->scalable, params->scalable_size,
@@ -1020,12 +1030,12 @@
GFP_KERNEL);
BUG_ON(!drv.bus_scale->usecase);
- tbl_idx = select_freq_plan(params->pte_efuse_phys);
- drv.acpu_freq_tbl = kmemdup(params->pvs_tables[tbl_idx].table,
- params->pvs_tables[tbl_idx].size,
- GFP_KERNEL);
+ pvs = select_freq_plan(params->pte_efuse_phys, params->pvs_tables);
+ BUG_ON(!pvs->table);
+
+ drv.acpu_freq_tbl = kmemdup(pvs->table, pvs->size, GFP_KERNEL);
BUG_ON(!drv.acpu_freq_tbl);
- drv.boost_uv = params->pvs_tables[tbl_idx].boost_uv;
+ drv.boost_uv = pvs->boost_uv;
acpuclk_krait_data.power_collapse_khz = params->stby_khz;
acpuclk_krait_data.wait_for_irq_khz = params->stby_khz;
diff --git a/arch/arm/mach-msm/acpuclock-krait.h b/arch/arm/mach-msm/acpuclock-krait.h
index 84a5b5e..3fa10e3 100644
--- a/arch/arm/mach-msm/acpuclock-krait.h
+++ b/arch/arm/mach-msm/acpuclock-krait.h
@@ -46,14 +46,18 @@
*/
enum pvs {
PVS_SLOW = 0,
- PVS_NOMINAL,
- PVS_FAST,
- PVS_FASTER,
- PVS_UNKNOWN,
- NUM_PVS
+ PVS_NOMINAL = 1,
+ PVS_FAST = 3,
+ PVS_FASTER = 4,
+ NUM_PVS = 7
};
/**
+ * The maximum number of speed bins.
+ */
+#define NUM_SPEED_BINS (16)
+
+/**
* enum scalables - IDs of frequency scalable hardware blocks.
*/
enum scalables {
@@ -186,8 +190,8 @@
const bool has_droop_ctl;
const u32 droop_offset;
const u32 droop_val;
- const u32 low_vdd_l_max;
- const u32 nom_vdd_l_max;
+ u32 low_vdd_l_max;
+ u32 nom_vdd_l_max;
const u32 low_vco_l_max;
const int vdd[NUM_HFPLL_VDD];
};
@@ -237,7 +241,7 @@
* @scalable: Array of scalables.
* @scalable_size: Size of @scalable.
* @hfpll_data: HFPLL configuration data.
- * @pvs_tables: CPU frequency tables.
+ * @pvs_tables: 2D array of CPU frequency tables.
* @l2_freq_tbl: L2 frequency table.
* @l2_freq_tbl_size: Size of @l2_freq_tbl.
* @pte_efuse_phys: Physical address of PTE EFUSE.
@@ -248,7 +252,7 @@
struct scalable *scalable;
size_t scalable_size;
struct hfpll_data *hfpll_data;
- struct pvs_table *pvs_tables;
+ struct pvs_table (*pvs_tables)[NUM_PVS];
struct l2_level *l2_freq_tbl;
size_t l2_freq_tbl_size;
phys_addr_t pte_efuse_phys;
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index d5e4638..7ba22f4 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -171,7 +171,6 @@
#define A2_NUM_PIPES 6
#define A2_SUMMING_THRESHOLD 4096
-#define A2_DEFAULT_DESCRIPTORS 32
#define A2_PHYS_BASE 0x124C2000
#define A2_PHYS_SIZE 0x2000
#define BUFFER_SIZE 2048
@@ -223,6 +222,7 @@
static void rx_timer_work_func(struct work_struct *work);
static DECLARE_WORK(rx_timer_work, rx_timer_work_func);
+static struct delayed_work queue_rx_work;
static struct workqueue_struct *bam_mux_rx_workqueue;
static struct workqueue_struct *bam_mux_tx_workqueue;
@@ -430,21 +430,27 @@
rx_len_cached = bam_rx_pool_len;
mutex_unlock(&bam_rx_pool_mutexlock);
- while (rx_len_cached < NUM_BUFFERS) {
+ while (bam_connection_is_active && rx_len_cached < NUM_BUFFERS) {
if (in_global_reset)
goto fail;
- info = kmalloc(sizeof(struct rx_pkt_info), GFP_KERNEL);
+ info = kmalloc(sizeof(struct rx_pkt_info),
+ GFP_NOWAIT | __GFP_NOWARN);
if (!info) {
- pr_err("%s: unable to alloc rx_pkt_info\n", __func__);
+ DMUX_LOG_KERR(
+ "%s: unable to alloc rx_pkt_info, will retry later\n",
+ __func__);
goto fail;
}
INIT_WORK(&info->work, handle_bam_mux_cmd);
- info->skb = __dev_alloc_skb(BUFFER_SIZE, GFP_KERNEL);
+ info->skb = __dev_alloc_skb(BUFFER_SIZE,
+ GFP_NOWAIT | __GFP_NOWARN);
if (info->skb == NULL) {
- DMUX_LOG_KERR("%s: unable to alloc skb\n", __func__);
+ DMUX_LOG_KERR(
+ "%s: unable to alloc skb, will retry later\n",
+ __func__);
goto fail_info;
}
ptr = skb_put(info->skb, BUFFER_SIZE);
@@ -488,11 +494,16 @@
fail:
if (rx_len_cached == 0) {
- DMUX_LOG_KERR("%s: RX queue failure\n", __func__);
- in_global_reset = 1;
+ DMUX_LOG_KERR("%s: rescheduling\n", __func__);
+ schedule_delayed_work(&queue_rx_work, msecs_to_jiffies(100));
}
}
+static void queue_rx_work_func(struct work_struct *work)
+{
+ queue_rx();
+}
+
static void bam_mux_process_data(struct sk_buff *rx_skb)
{
unsigned long flags;
@@ -2422,6 +2433,7 @@
init_completion(&bam_connection_completion);
init_completion(&dfab_unvote_completion);
INIT_DELAYED_WORK(&ul_timeout_work, ul_timeout);
+ INIT_DELAYED_WORK(&queue_rx_work, queue_rx_work_func);
wake_lock_init(&bam_wakelock, WAKE_LOCK_SUSPEND, "bam_dmux_wakelock");
rc = smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_A2_POWER_CONTROL,
diff --git a/arch/arm/mach-msm/board-8064-gpiomux.c b/arch/arm/mach-msm/board-8064-gpiomux.c
index a08f45c..cb03d4b 100644
--- a/arch/arm/mach-msm/board-8064-gpiomux.c
+++ b/arch/arm/mach-msm/board-8064-gpiomux.c
@@ -31,6 +31,7 @@
.drv = GPIOMUX_DRV_8MA,
.func = GPIOMUX_FUNC_GPIO,
};
+#endif
/* The SPI configurations apply to GSBI 5*/
static struct gpiomux_setting gpio_spi_config = {
@@ -60,6 +61,7 @@
.pull = GPIOMUX_PULL_UP,
};
+#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
struct msm_gpiomux_config apq8064_ethernet_configs[] = {
{
.gpio = 43,
@@ -361,6 +363,22 @@
.pull = GPIOMUX_PULL_NONE,
};
+static struct gpiomux_setting audio_auxpcm[] = {
+/* Suspended state */
+ {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_NONE,
+ },
+/* Active state */
+ {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_NONE,
+ },
+};
+
+
static struct gpiomux_setting wcnss_5wire_suspend_cfg = {
.func = GPIOMUX_FUNC_GPIO,
.drv = GPIOMUX_DRV_2MA,
@@ -682,7 +700,6 @@
[GPIOMUX_SUSPENDED] = &gsbi1_uart_config,
},
},
-#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
{
.gpio = 51, /* GSBI5 QUP SPI_DATA_MOSI */
.settings = {
@@ -713,7 +730,6 @@
[GPIOMUX_SUSPENDED] = &gpio_spi_config,
},
},
-#endif
{
.gpio = 30, /* FP CS */
.settings = {
@@ -846,6 +862,37 @@
},
};
+static struct msm_gpiomux_config mpq8064_audio_auxpcm_configs[] __initdata = {
+ {
+ .gpio = 43,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &audio_auxpcm[0],
+ [GPIOMUX_ACTIVE] = &audio_auxpcm[1],
+ },
+ },
+ {
+ .gpio = 44,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &audio_auxpcm[0],
+ [GPIOMUX_ACTIVE] = &audio_auxpcm[1],
+ },
+ },
+ {
+ .gpio = 45,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &audio_auxpcm[0],
+ [GPIOMUX_ACTIVE] = &audio_auxpcm[1],
+ },
+ },
+ {
+ .gpio = 46,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &audio_auxpcm[0],
+ [GPIOMUX_ACTIVE] = &audio_auxpcm[1],
+ },
+ },
+};
+
/* External 3.3 V regulator enable */
static struct msm_gpiomux_config apq8064_ext_regulator_configs[] __initdata = {
{
@@ -1527,6 +1574,10 @@
if (machine_is_mpq8064_cdp() || machine_is_mpq8064_hrd() ||
machine_is_mpq8064_dtv()) {
+
+ msm_gpiomux_install(mpq8064_audio_auxpcm_configs,
+ ARRAY_SIZE(mpq8064_audio_auxpcm_configs));
+
msm_gpiomux_install(mpq8064_spkr_i2s_config,
ARRAY_SIZE(mpq8064_spkr_i2s_config));
}
diff --git a/arch/arm/mach-msm/board-8064-gpu.c b/arch/arm/mach-msm/board-8064-gpu.c
index 122505e..c7075bc 100644
--- a/arch/arm/mach-msm/board-8064-gpu.c
+++ b/arch/arm/mach-msm/board-8064-gpu.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -24,26 +24,51 @@
#ifdef CONFIG_MSM_DCVS
static struct msm_dcvs_freq_entry grp3d_freq[] = {
- {0, 0, 333932},
- {0, 0, 497532},
- {0, 0, 707610},
- {0, 0, 844545},
+ {0, 900, 0, 0, 0},
+ {0, 950, 0, 0, 0},
+ {0, 950, 0, 0, 0},
+ {0, 1200, 1, 100, 100},
};
static struct msm_dcvs_core_info grp3d_core_info = {
- .freq_tbl = &grp3d_freq[0],
- .core_param = {
- .max_time_us = 100000,
- .num_freq = ARRAY_SIZE(grp3d_freq),
+ .freq_tbl = &grp3d_freq[0],
+ .num_cores = 1,
+ .sensors = (int[]){0},
+ .core_param = {
+ .core_type = MSM_DCVS_CORE_TYPE_GPU,
},
- .algo_param = {
- .slack_time_us = 39000,
- .disable_pc_threshold = 86000,
- .ss_window_size = 1000000,
- .ss_util_pct = 95,
- .em_max_util_pct = 97,
- .ss_iobusy_conv = 100,
+ .algo_param = {
+ .disable_pc_threshold = 0,
+ .em_win_size_min_us = 100000,
+ .em_win_size_max_us = 300000,
+ .em_max_util_pct = 97,
+ .group_id = 0,
+ .max_freq_chg_time_us = 100000,
+ .slack_mode_dynamic = 0,
+ .slack_time_min_us = 39000,
+ .slack_time_max_us = 39000,
+ .ss_win_size_min_us = 1000000,
+ .ss_win_size_max_us = 1000000,
+ .ss_util_pct = 95,
+ .ss_iobusy_conv = 100,
},
+
+
+ .energy_coeffs = {
+ .leakage_coeff_a = -17720,
+ .leakage_coeff_b = 37,
+ .leakage_coeff_c = 3329,
+ .leakage_coeff_d = -277,
+
+ .active_coeff_a = 2492,
+ .active_coeff_b = 0,
+ .active_coeff_c = 0
+ },
+
+ .power_param = {
+ .current_temp = 25,
+ .num_freq = ARRAY_SIZE(grp3d_freq),
+ }
};
#endif /* CONFIG_MSM_DCVS */
@@ -251,11 +276,17 @@
{
unsigned int version = socinfo_get_version();
- if ((SOCINFO_VERSION_MAJOR(version) == 1) &&
- (SOCINFO_VERSION_MINOR(version) == 1))
- kgsl_3d0_pdata.chipid = ADRENO_CHIPID(3, 2, 0, 1);
- else
- kgsl_3d0_pdata.chipid = ADRENO_CHIPID(3, 2, 0, 0);
+ if (cpu_is_apq8064ab())
+ kgsl_3d0_pdata.pwrlevel[0].gpu_freq = 450000000;
+ if (SOCINFO_VERSION_MAJOR(version) == 2) {
+ kgsl_3d0_pdata.chipid = ADRENO_CHIPID(3, 2, 0, 2);
+ } else {
+ if ((SOCINFO_VERSION_MAJOR(version) == 1) &&
+ (SOCINFO_VERSION_MINOR(version) == 1))
+ kgsl_3d0_pdata.chipid = ADRENO_CHIPID(3, 2, 0, 1);
+ else
+ kgsl_3d0_pdata.chipid = ADRENO_CHIPID(3, 2, 0, 0);
+ }
platform_device_register(&device_kgsl_3d0);
}
diff --git a/arch/arm/mach-msm/board-8064-pmic.c b/arch/arm/mach-msm/board-8064-pmic.c
index 3b47d2e..f6423c8 100644
--- a/arch/arm/mach-msm/board-8064-pmic.c
+++ b/arch/arm/mach-msm/board-8064-pmic.c
@@ -115,7 +115,6 @@
/* Initial PM8921 GPIO configurations */
static struct pm8xxx_gpio_init pm8921_gpios[] __initdata = {
PM8921_GPIO_OUTPUT(14, 1, HIGH), /* HDMI Mux Selector */
- PM8921_GPIO_OUTPUT(23, 0, HIGH), /* touchscreen power FET */
PM8921_GPIO_OUTPUT_BUFCONF(25, 0, LOW, CMOS), /* DISP_RESET_N */
PM8921_GPIO_OUTPUT_FUNC(26, 0, PM_GPIO_FUNC_2), /* Bl: Off, PWM mode */
PM8921_GPIO_OUTPUT_VIN(30, 1, PM_GPIO_VIN_VPH), /* SMB349 susp line */
@@ -146,10 +145,13 @@
PM8921_GPIO_OUTPUT(37, 0, LOW), /* MUX1_SEL */
};
+static struct pm8xxx_gpio_init touchscreen_gpios[] __initdata = {
+ PM8921_GPIO_OUTPUT(23, 0, HIGH), /* touchscreen power FET */
+};
+
/* Initial PM8917 GPIO configurations */
static struct pm8xxx_gpio_init pm8917_gpios[] __initdata = {
PM8921_GPIO_OUTPUT(14, 1, HIGH), /* HDMI Mux Selector */
- PM8921_GPIO_OUTPUT(23, 0, HIGH), /* touchscreen power FET */
PM8921_GPIO_OUTPUT_BUFCONF(25, 0, LOW, CMOS), /* DISP_RESET_N */
PM8921_GPIO_OUTPUT(26, 1, HIGH), /* Backlight: on */
PM8921_GPIO_OUTPUT_BUFCONF(36, 1, LOW, OPEN_DRAIN),
@@ -210,6 +212,8 @@
apq8064_configure_gpios(pm8917_gpios, ARRAY_SIZE(pm8917_gpios));
if (machine_is_apq8064_cdp() || machine_is_apq8064_liquid()) {
+ apq8064_configure_gpios(touchscreen_gpios,
+ ARRAY_SIZE(touchscreen_gpios));
if (socinfo_get_pmic_model() != PMIC_MODEL_PM8917)
apq8064_configure_gpios(pm8921_cdp_kp_gpios,
ARRAY_SIZE(pm8921_cdp_kp_gpios));
@@ -395,6 +399,8 @@
.max_voltage = MAX_VOLTAGE_MV,
.min_voltage = 3200,
.uvd_thresh_voltage = 4050,
+ .alarm_low_mv = 3400,
+ .alarm_high_mv = 4000,
.resume_voltage_delta = 100,
.term_current = CHG_TERM_MA,
.cool_temp = 10,
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index 6cdafbc..ef3c81d 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -771,4 +771,10 @@
= ARRAY_SIZE(vreg_consumers_8917_S1);
}
}
+
+ /*
+ * Switch to 8960_PM8917 rpm-regulator version so that TCXO workaround
+ * is applied to PM8917 regulators L25, L26, L27, and L28.
+ */
+ apq8064_rpm_regulator_pdata.version = RPM_VREG_VERSION_8960_PM8917;
}
diff --git a/arch/arm/mach-msm/board-8064-storage.c b/arch/arm/mach-msm/board-8064-storage.c
index c81a637..379d7ae 100644
--- a/arch/arm/mach-msm/board-8064-storage.c
+++ b/arch/arm/mach-msm/board-8064-storage.c
@@ -338,6 +338,11 @@
apq8064_add_sdcc(2, apq8064_sdc2_pdata);
if (apq8064_sdc3_pdata) {
+ if (machine_is_mpq8064_hrd() || machine_is_mpq8064_dtv()) {
+ apq8064_sdc3_pdata->uhs_caps &= ~(MMC_CAP_UHS_SDR12 |
+ MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_DDR50 |
+ MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104);
+ }
if (!machine_is_apq8064_cdp()) {
apq8064_sdc3_pdata->wpswitch_gpio = 0;
apq8064_sdc3_pdata->is_wpswitch_active_low = false;
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 1efc64b..cc9dcbb 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -927,7 +927,8 @@
static void __init apq8064_ehci_host_init(void)
{
if (machine_is_apq8064_liquid() || machine_is_mpq8064_cdp() ||
- machine_is_mpq8064_hrd() || machine_is_mpq8064_dtv()) {
+ machine_is_mpq8064_hrd() || machine_is_mpq8064_dtv() ||
+ machine_is_apq8064_cdp()) {
if (machine_is_apq8064_liquid())
msm_ehci_host_pdata3.dock_connect_irq =
PM8921_MPP_IRQ(PM8921_IRQ_BASE, 9);
@@ -1769,6 +1770,27 @@
},
};
+static struct msm_bus_vectors qseecom_enable_dfab_sfpb_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_ADM_PORT0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 70000000UL,
+ .ib = 70000000UL,
+ },
+ {
+ .src = MSM_BUS_MASTER_ADM_PORT1,
+ .dst = MSM_BUS_SLAVE_GSBI1_UART,
+ .ab = 2480000000UL,
+ .ib = 2480000000UL,
+ },
+ {
+ .src = MSM_BUS_MASTER_SPDM,
+ .dst = MSM_BUS_SLAVE_SPDM,
+ .ib = (64 * 8) * 1000000UL,
+ .ab = (64 * 8) * 100000UL,
+ },
+};
+
static struct msm_bus_paths qseecom_hw_bus_scale_usecases[] = {
{
ARRAY_SIZE(qseecom_clks_init_vectors),
@@ -1782,6 +1804,10 @@
ARRAY_SIZE(qseecom_enable_sfpb_vectors),
qseecom_enable_sfpb_vectors,
},
+ {
+ ARRAY_SIZE(qseecom_enable_dfab_sfpb_vectors),
+ qseecom_enable_dfab_sfpb_vectors,
+ },
};
static struct msm_bus_scale_pdata qseecom_bus_pdata = {
@@ -2442,7 +2468,6 @@
&apq8064_device_ext_3p3v_vreg,
&apq8064_device_ssbi_pmic1,
&apq8064_device_ssbi_pmic2,
- &apq8064_device_ext_ts_sw_vreg,
};
static struct platform_device *pm8917_common_devices[] __initdata = {
@@ -2450,7 +2475,6 @@
&apq8064_device_ext_3p3v_vreg,
&apq8064_device_ssbi_pmic1,
&apq8064_device_ssbi_pmic2,
- &apq8064_device_ext_ts_sw_vreg,
};
static struct platform_device *common_devices[] __initdata = {
@@ -2545,6 +2569,7 @@
&msm_gss,
&apq8064_rtb_device,
&apq8064_cpu_idle_device,
+ &apq8064_msm_gov_device,
&apq8064_device_cache_erp,
&msm8960_device_ebi1_ch0_erp,
&msm8960_device_ebi1_ch1_erp,
@@ -2568,6 +2593,7 @@
#ifdef CONFIG_BATTERY_BCL
&battery_bcl_device,
#endif
+ &apq8064_msm_mpd_device,
};
static struct platform_device *cdp_devices[] __initdata = {
@@ -3347,6 +3373,8 @@
else
platform_add_devices(pm8917_common_devices,
ARRAY_SIZE(pm8917_common_devices));
+ if (machine_is_apq8064_cdp() || machine_is_apq8064_liquid())
+ platform_device_register(&apq8064_device_ext_ts_sw_vreg);
platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
if (!(machine_is_mpq8064_cdp() || machine_is_mpq8064_hrd() ||
machine_is_mpq8064_dtv()))
diff --git a/arch/arm/mach-msm/board-8930-pmic.c b/arch/arm/mach-msm/board-8930-pmic.c
index 59e4ba1..402aec4 100644
--- a/arch/arm/mach-msm/board-8930-pmic.c
+++ b/arch/arm/mach-msm/board-8930-pmic.c
@@ -320,6 +320,8 @@
.max_voltage = MAX_VOLTAGE_MV,
.min_voltage = 3200,
.uvd_thresh_voltage = 4050,
+ .alarm_low_mv = 3400,
+ .alarm_high_mv = 4000,
.resume_voltage_delta = 100,
.term_current = CHG_TERM_MA,
.cool_temp = 10,
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index b84e66e..a6a90a7 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1048,6 +1048,27 @@
},
};
+static struct msm_bus_vectors qseecom_enable_dfab_sfpb_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_SPS,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ib = (492 * 8) * 1000000UL,
+ .ab = (492 * 8) * 100000UL,
+ },
+ {
+ .src = MSM_BUS_MASTER_SPS,
+ .dst = MSM_BUS_SLAVE_SPS,
+ .ib = (492 * 8) * 1000000UL,
+ .ab = (492 * 8) * 100000UL,
+ },
+ {
+ .src = MSM_BUS_MASTER_SPDM,
+ .dst = MSM_BUS_SLAVE_SPDM,
+ .ib = (64 * 8) * 1000000UL,
+ .ab = (64 * 8) * 100000UL,
+ },
+};
+
static struct msm_bus_paths qseecom_hw_bus_scale_usecases[] = {
{
ARRAY_SIZE(qseecom_clks_init_vectors),
@@ -1061,6 +1082,10 @@
ARRAY_SIZE(qseecom_enable_sfpb_vectors),
qseecom_enable_sfpb_vectors,
},
+ {
+ ARRAY_SIZE(qseecom_enable_dfab_sfpb_vectors),
+ qseecom_enable_dfab_sfpb_vectors,
+ },
};
static struct msm_bus_scale_pdata qseecom_bus_pdata = {
@@ -2389,7 +2414,6 @@
#endif
&msm8930_rtb_device,
&msm8930_cpu_idle_device,
- &msm8930_msm_gov_device,
&msm_bus_8930_apps_fabric,
&msm_bus_8930_sys_fabric,
&msm_bus_8930_mm_fabric,
diff --git a/arch/arm/mach-msm/board-8960-pmic.c b/arch/arm/mach-msm/board-8960-pmic.c
index ae74285..f6c3653 100644
--- a/arch/arm/mach-msm/board-8960-pmic.c
+++ b/arch/arm/mach-msm/board-8960-pmic.c
@@ -401,6 +401,8 @@
.max_voltage = MAX_VOLTAGE_MV,
.min_voltage = 3200,
.uvd_thresh_voltage = 4050,
+ .alarm_low_mv = 3400,
+ .alarm_high_mv = 4000,
.resume_voltage_delta = 100,
.term_current = CHG_TERM_MA,
.cool_temp = 10,
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index d93a4fa..7115e40 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1113,6 +1113,27 @@
},
};
+static struct msm_bus_vectors qseecom_enable_dfab_sfpb_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_SPS,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ib = (492 * 8) * 1000000UL,
+ .ab = (492 * 8) * 100000UL,
+ },
+ {
+ .src = MSM_BUS_MASTER_SPS,
+ .dst = MSM_BUS_SLAVE_SPS,
+ .ib = (492 * 8) * 1000000UL,
+ .ab = (492 * 8) * 100000UL,
+ },
+ {
+ .src = MSM_BUS_MASTER_SPDM,
+ .dst = MSM_BUS_SLAVE_SPDM,
+ .ib = (64 * 8) * 1000000UL,
+ .ab = (64 * 8) * 100000UL,
+ },
+};
+
static struct msm_bus_paths qseecom_hw_bus_scale_usecases[] = {
{
ARRAY_SIZE(qseecom_clks_init_vectors),
@@ -1126,6 +1147,10 @@
ARRAY_SIZE(qseecom_enable_sfpb_vectors),
qseecom_enable_sfpb_vectors,
},
+ {
+ ARRAY_SIZE(qseecom_enable_dfab_sfpb_vectors),
+ qseecom_enable_dfab_sfpb_vectors,
+ },
};
static struct msm_bus_scale_pdata qseecom_bus_pdata = {
@@ -2738,7 +2763,6 @@
&msm8960_device_watchdog,
&msm8960_rtb_device,
&msm8960_cpu_idle_device,
- &msm8960_msm_gov_device,
&msm8960_device_cache_erp,
&msm8960_device_ebi1_ch0_erp,
&msm8960_device_ebi1_ch1_erp,
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index 1577a2b..8568340 100644
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -271,6 +271,30 @@
[GPIOMUX_SUSPENDED] = &gpio_uart_config,
},
},
+ {
+ .gpio = 53, /* BLSP2 QUP4 SPI_DATA_MOSI */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_spi_config,
+ },
+ },
+ {
+ .gpio = 54, /* BLSP2 QUP4 SPI_DATA_MISO */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_spi_config,
+ },
+ },
+ {
+ .gpio = 56, /* BLSP2 QUP4 SPI_CLK */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_spi_config,
+ },
+ },
+ {
+ .gpio = 55, /* BLSP2 QUP4 SPI_CS0_N */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_spi_config,
+ },
+ },
};
static struct msm_gpiomux_config msm8974_slimbus_config[] __initdata = {
diff --git a/arch/arm/mach-msm/board-9625.c b/arch/arm/mach-msm/board-9625.c
index 5f556fb..37e93b6 100644
--- a/arch/arm/mach-msm/board-9625.c
+++ b/arch/arm/mach-msm/board-9625.c
@@ -31,8 +31,39 @@
#include <mach/gpio.h>
#include <mach/clk-provider.h>
#include <mach/qpnp-int.h>
+#include <mach/msm_memtypes.h>
#include "clock.h"
+#define MSM_KERNEL_EBI_SIZE 0x51000
+
+static struct memtype_reserve msm9625_reserve_table[] __initdata = {
+ [MEMTYPE_SMI] = {
+ },
+ [MEMTYPE_EBI0] = {
+ .flags = MEMTYPE_FLAGS_1M_ALIGN,
+ },
+ [MEMTYPE_EBI1] = {
+ .flags = MEMTYPE_FLAGS_1M_ALIGN,
+ },
+};
+
+static int msm9625_paddr_to_memtype(unsigned int paddr)
+{
+ return MEMTYPE_EBI1;
+}
+
+static void __init msm9625_calculate_reserve_sizes(void)
+{
+ msm9625_reserve_table[MEMTYPE_EBI1].size += MSM_KERNEL_EBI_SIZE;
+}
+
+static struct reserve_info msm9625_reserve_info __initdata = {
+ .memtype_reserve_table = msm9625_reserve_table,
+ .calculate_reserve_sizes = msm9625_calculate_reserve_sizes,
+ .paddr_to_memtype = msm9625_paddr_to_memtype,
+};
+
+
#define L2CC_AUX_CTRL ((0x1 << L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT) | \
(0x2 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT) | \
(0x1 << L2X0_AUX_CTRL_EVNT_MON_BUS_EN_SHIFT))
@@ -97,13 +128,20 @@
.init = msm_dt_timer_init
};
+static void __init msm9625_reserve(void)
+{
+ reserve_info = &msm9625_reserve_info;
+ msm_reserve();
+}
+
+
void __init msm9625_init(void)
{
if (socinfo_init() < 0)
pr_err("%s: socinfo_init() failed\n", __func__);
msm9625_init_gpiomux();
- msm_clock_init(&msm9625_clock_init_data);
+ msm_clock_init(&msm_dummy_clock_init_data);
of_platform_populate(NULL, of_default_bus_match_table,
msm9625_auxdata_lookup, NULL);
}
@@ -115,4 +153,5 @@
.handle_irq = gic_handle_irq,
.timer = &msm_dt_timer,
.dt_compat = msm9625_dt_match,
+ .reserve = msm9625_reserve,
MACHINE_END
diff --git a/arch/arm/mach-msm/board-fsm9xxx.c b/arch/arm/mach-msm/board-fsm9xxx.c
index b4f6968..1d6eb01 100644
--- a/arch/arm/mach-msm/board-fsm9xxx.c
+++ b/arch/arm/mach-msm/board-fsm9xxx.c
@@ -941,6 +941,8 @@
static void __init fsm9xxx_init(void)
{
+ msm_clock_init(&fsm9xxx_clock_init_data);
+
regulator_has_full_constraints();
#if defined(CONFIG_I2C_SSBI) || defined(CONFIG_MSM_SSBI)
@@ -977,7 +979,6 @@
{
msm_shared_ram_phys = 0x00100000;
msm_map_fsm9xxx_io();
- msm_clock_init(&fsm9xxx_clock_init_data);
if (socinfo_init() < 0)
pr_err("%s: socinfo_init() failed!\n",
__func__);
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index 2a51e66..13c4be2 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -841,7 +841,7 @@
static void __init msm8625_reserve(void)
{
msm7x27a_reserve();
- memblock_remove(MSM8625_SECONDARY_PHYS, SZ_8);
+ memblock_remove(MSM8625_CPU_PHYS, SZ_8);
memblock_remove(MSM8625_WARM_BOOT_PHYS, SZ_32);
}
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index 205db58..ee13e04 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -5190,7 +5190,7 @@
int bahama_not_marimba = bahama_present();
- if (bahama_not_marimba == -1) {
+ if (bahama_not_marimba < 0) {
printk(KERN_WARNING "%s: bahama_present: %d\n",
__func__, bahama_not_marimba);
return -ENODEV;
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index ed1fafc..ec8e438 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -812,7 +812,7 @@
static void __init msm8625_reserve(void)
{
- memblock_remove(MSM8625_SECONDARY_PHYS, SZ_8);
+ memblock_remove(MSM8625_CPU_PHYS, SZ_8);
msm7627a_reserve();
}
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index b60f693..2cd2cd4 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -1534,6 +1534,11 @@
static CLK_SDC(sdc4_clk, 4, 3, 33000000, 67000000);
static CLK_SDC(sdc5_clk, 5, 2, 33000000, 67000000);
+static unsigned long fmax_sdc1_8064v2[MAX_VDD_LEVELS] __initdata = {
+ [VDD_DIG_LOW] = 100000000,
+ [VDD_DIG_NOMINAL] = 200000000,
+};
+
#define F_TSIF_REF(f, s, d, m, n) \
{ \
.freq_hz = f, \
@@ -1907,6 +1912,7 @@
F_CE3( 0, gnd, 1),
F_CE3( 48000000, pll8, 8),
F_CE3(100000000, pll3, 12),
+ F_CE3(120000000, pll3, 10),
F_END
};
@@ -1929,6 +1935,11 @@
},
};
+static unsigned long fmax_ce3_8064v2[MAX_VDD_LEVELS] __initdata = {
+ [VDD_DIG_LOW] = 57000000,
+ [VDD_DIG_NOMINAL] = 120000000,
+};
+
static struct branch_clk ce3_core_clk = {
.b = {
.ctl_reg = CE3_CORE_CLK_CTL_REG,
@@ -3540,11 +3551,12 @@
F_GFX3D(145455000, pll2, 2, 11),
F_GFX3D(160000000, pll2, 1, 5),
F_GFX3D(177778000, pll2, 2, 9),
+ F_GFX3D(192000000, pll8, 1, 2),
F_GFX3D(200000000, pll2, 1, 4),
F_GFX3D(228571000, pll2, 2, 7),
F_GFX3D(266667000, pll2, 1, 3),
- F_GFX3D(325000000, pll15, 1, 3),
F_GFX3D(400000000, pll2, 1, 2),
+ F_GFX3D(450000000, pll15, 1, 2),
F_END
};
@@ -3570,6 +3582,12 @@
F_END
};
+static unsigned long fmax_gfx3d_8064ab[MAX_VDD_LEVELS] __initdata = {
+ [VDD_DIG_LOW] = 128000000,
+ [VDD_DIG_NOMINAL] = 325000000,
+ [VDD_DIG_HIGH] = 450000000
+};
+
static unsigned long fmax_gfx3d_8064[MAX_VDD_LEVELS] __initdata = {
[VDD_DIG_LOW] = 128000000,
[VDD_DIG_NOMINAL] = 325000000,
@@ -4295,6 +4313,7 @@
F_VCODEC(133330000, pll2, 1, 6),
F_VCODEC(200000000, pll2, 1, 4),
F_VCODEC(228570000, pll2, 2, 7),
+ F_VCODEC(266670000, pll2, 1, 3),
F_END
};
@@ -4325,6 +4344,12 @@
},
};
+static unsigned long fmax_vcodec_8064v2[MAX_VDD_LEVELS] __initdata = {
+ [VDD_DIG_LOW] = 100000000,
+ [VDD_DIG_NOMINAL] = 200000000,
+ [VDD_DIG_HIGH] = 266670000,
+};
+
#define F_VPE(f, s, d) \
{ \
.freq_hz = f, \
@@ -5065,6 +5090,8 @@
writel_relaxed(0x80|BVAL(5, 3, clk_sel), GCC_APCS_CLK_DIAG);
measure->sample_ticks = 0x4000;
measure->multiplier = 2;
+ if (cpu_is_krait_v3())
+ measure->multiplier = 8;
break;
default:
ret = -EPERM;
@@ -6302,7 +6329,7 @@
writel_relaxed(0x3C7097F9, AHB_EN2_REG);
}
- if (cpu_is_apq8064())
+ if (cpu_is_apq8064() || cpu_is_apq8064ab())
rmwreg(0x00000001, AHB_EN3_REG, 0x00000001);
/* Deassert all locally-owned MM AHB resets. */
@@ -6325,7 +6352,7 @@
rmwreg(0x0027FCFF, MAXI_EN3_REG, 0x003FFFFF);
rmwreg(0x0027FCFF, MAXI_EN4_REG, 0x017FFFFF);
- if (cpu_is_apq8064())
+ if (cpu_is_apq8064() || cpu_is_apq8064ab())
rmwreg(0x019FECFF, MAXI_EN5_REG, 0x01FFEFFF);
if (cpu_is_msm8930() || cpu_is_msm8930aa() || cpu_is_msm8627())
rmwreg(0x000004FF, MAXI_EN5_REG, 0x00000FFF);
@@ -6363,7 +6390,8 @@
rmwreg(0x80FF0000, VFE_CC_REG, 0xE0FF4010);
rmwreg(0x800000FF, VFE_CC2_REG, 0xE00000FF);
rmwreg(0x80FF0000, VPE_CC_REG, 0xE0FF0010);
- if (cpu_is_msm8960ab() || cpu_is_msm8960() || cpu_is_apq8064()) {
+ if (cpu_is_msm8960ab() || cpu_is_msm8960() || cpu_is_apq8064()
+ || cpu_is_apq8064ab()) {
rmwreg(0x80FF0000, DSI2_BYTE_CC_REG, 0xE0FF0010);
rmwreg(0x80FF0000, DSI2_PIXEL_CC_REG, 0xE0FF0010);
rmwreg(0x80FF0000, JPEGD_CC_REG, 0xE0FF0010);
@@ -6381,7 +6409,7 @@
rmwreg(0x80FF0000, GFX2D0_CC_REG, 0xE0FF0010);
rmwreg(0x80FF0000, GFX2D1_CC_REG, 0xE0FF0010);
}
- if (cpu_is_apq8064()) {
+ if (cpu_is_apq8064() || cpu_is_apq8064ab()) {
rmwreg(0x00000000, TV_CC_REG, 0x00004010);
rmwreg(0x80FF0000, VCAP_CC_REG, 0xE0FF1010);
}
@@ -6392,7 +6420,7 @@
* and wake-up value to max.
*/
rmwreg(0x0000004F, USB_HS1_HCLK_FS_REG, 0x0000007F);
- if (cpu_is_apq8064()) {
+ if (cpu_is_apq8064() || cpu_is_apq8064ab()) {
rmwreg(0x0000004F, USB_HS3_HCLK_FS_REG, 0x0000007F);
rmwreg(0x0000004F, USB_HS4_HCLK_FS_REG, 0x0000007F);
}
@@ -6414,7 +6442,8 @@
/* Source the dsi_byte_clks from the DSI PHY PLLs */
rmwreg(0x1, DSI1_BYTE_NS_REG, 0x7);
- if (cpu_is_msm8960ab() || cpu_is_msm8960() || cpu_is_apq8064())
+ if (cpu_is_msm8960ab() || cpu_is_msm8960() || cpu_is_apq8064()
+ || cpu_is_apq8064ab())
rmwreg(0x2, DSI2_BYTE_NS_REG, 0x7);
/* Source the dsi1_esc_clk from the DSI1 PHY PLLs */
@@ -6424,7 +6453,7 @@
* Source the sata_phy_ref_clk from PXO and set predivider of
* sata_pmalive_clk to 1.
*/
- if (cpu_is_apq8064()) {
+ if (cpu_is_apq8064() || cpu_is_apq8064ab()) {
rmwreg(0, SATA_PHY_REF_CLK_CTL_REG, 0x1);
rmwreg(0, SATA_PMALIVE_CLK_CTL_REG, 0x3);
}
@@ -6433,7 +6462,7 @@
* TODO: Programming below PLLs and prng_clk is temporary and
* needs to be removed after bootloaders program them.
*/
- if (cpu_is_apq8064()) {
+ if (cpu_is_apq8064() || cpu_is_apq8064ab()) {
u32 is_pll_enabled;
/* Program pxo_src_clk to source from PXO */
@@ -6445,9 +6474,6 @@
/* Ref clk = 27MHz and program pll14 to 480MHz */
configure_sr_pll(&pll14_config, &pll14_regs, 1);
- /* Program PLL15 to 975MHz with ref clk = 27MHz */
- configure_sr_pll(&pll15_config, &pll15_regs, 0);
-
/* Check if PLL4 is active */
is_pll_enabled = readl_relaxed(LCC_PLL0_STATUS_REG) & BIT(16);
if (!is_pll_enabled)
@@ -6462,6 +6488,17 @@
writel_relaxed(0x2B, PRNG_CLK_NS_REG);
}
+ if (cpu_is_apq8064()) {
+ /* Program PLL15 to 975MHz with ref clk = 27MHz */
+ configure_sr_pll(&pll15_config, &pll15_regs, 0);
+ } else if (cpu_is_apq8064ab()) {
+ /* Program PLL15 to 900MHZ */
+ pll15_config.l = 0x21 | BVAL(31, 7, 0x620);
+ pll15_config.m = 0x1;
+ pll15_config.n = 0x3;
+ configure_sr_pll(&pll15_config, &pll15_regs, 0);
+ }
+
/*
* Program PLL15 to 900MHz with ref clk = 27MHz and
* only enable PLL main output.
@@ -6482,7 +6519,7 @@
/* Initialize clock registers. */
reg_init();
- if (cpu_is_apq8064())
+ if (cpu_is_apq8064() || cpu_is_apq8064ab())
vdd_sr2_hdmi_pll.set_vdd = set_vdd_sr2_hdmi_pll_8064;
/* Detect PLL4 programmed for alternate 491.52MHz clock plan. */
@@ -6524,13 +6561,32 @@
}
/*
* Change the freq tables for and voltage requirements for
- * clocks which differ between 8960 and 8064.
+ * clocks which differ between chips.
*/
if (cpu_is_apq8064()) {
gfx3d_clk.freq_tbl = clk_tbl_gfx3d_8064;
memcpy(gfx3d_clk.c.fmax, fmax_gfx3d_8064,
sizeof(gfx3d_clk.c.fmax));
+ }
+ if (cpu_is_apq8064ab()) {
+ gfx3d_clk.freq_tbl = clk_tbl_gfx3d_8064;
+
+ memcpy(gfx3d_clk.c.fmax, fmax_gfx3d_8064ab,
+ sizeof(gfx3d_clk.c.fmax));
+ }
+ if ((cpu_is_apq8064() &&
+ SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 2) ||
+ cpu_is_apq8064ab()) {
+
+ memcpy(vcodec_clk.c.fmax, fmax_vcodec_8064v2,
+ sizeof(vcodec_clk.c.fmax));
+ memcpy(ce3_src_clk.c.fmax, fmax_ce3_8064v2,
+ sizeof(ce3_src_clk.c.fmax));
+ memcpy(sdc1_clk.c.fmax, fmax_sdc1_8064v2,
+ sizeof(sdc1_clk.c.fmax));
+ }
+ if (cpu_is_apq8064() || cpu_is_apq8064ab()) {
memcpy(ijpeg_clk.c.fmax, fmax_ijpeg_8064,
sizeof(ijpeg_clk.c.fmax));
memcpy(mdp_clk.c.fmax, fmax_mdp_8064,
@@ -6606,7 +6662,7 @@
clk_set_rate(&tsif_ref_clk.c, 105000);
clk_set_rate(&tssc_clk.c, 27000000);
clk_set_rate(&usb_hs1_xcvr_clk.c, 60000000);
- if (cpu_is_apq8064()) {
+ if (cpu_is_apq8064() || cpu_is_apq8064ab()) {
clk_set_rate(&usb_hs3_xcvr_clk.c, 60000000);
clk_set_rate(&usb_hs4_xcvr_clk.c, 60000000);
}
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index a64e6a5..10de231 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -2183,6 +2183,18 @@
},
};
+struct branch_clk gcc_sys_noc_usb3_axi_clk = {
+ .cbcr_reg = SYS_NOC_USB3_AXI_CBCR,
+ .parent = &usb30_master_clk_src.c,
+ .has_sibling = 1,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "gcc_sys_noc_usb3_axi_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_sys_noc_usb3_axi_clk.c),
+ },
+};
+
static struct branch_clk gcc_usb30_master_clk = {
.cbcr_reg = USB30_MASTER_CBCR,
.bcr_reg = USB_30_BCR,
@@ -2193,6 +2205,7 @@
.dbg_name = "gcc_usb30_master_clk",
.ops = &clk_ops_branch,
CLK_INIT(gcc_usb30_master_clk.c),
+ .depends = &gcc_sys_noc_usb3_axi_clk.c,
},
};
@@ -2207,18 +2220,6 @@
},
};
-struct branch_clk gcc_sys_noc_usb3_axi_clk = {
- .cbcr_reg = SYS_NOC_USB3_AXI_CBCR,
- .parent = &usb30_master_clk_src.c,
- .has_sibling = 1,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_sys_noc_usb3_axi_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_sys_noc_usb3_axi_clk.c),
- },
-};
-
struct branch_clk gcc_usb30_sleep_clk = {
.cbcr_reg = USB30_SLEEP_CBCR,
.has_sibling = 1,
@@ -5039,6 +5040,7 @@
CLK_LOOKUP("core_clk", gcc_blsp1_uart6_apps_clk.c, ""),
CLK_LOOKUP("iface_clk", gcc_blsp2_ahb_clk.c, "f9967000.i2c"),
+ CLK_LOOKUP("iface_clk", gcc_blsp2_ahb_clk.c, "f9966000.spi"),
CLK_LOOKUP("iface_clk", gcc_blsp2_ahb_clk.c, "f995e000.serial"),
CLK_LOOKUP("core_clk", gcc_blsp2_qup1_i2c_apps_clk.c, ""),
CLK_LOOKUP("core_clk", gcc_blsp2_qup1_spi_apps_clk.c, ""),
@@ -5047,8 +5049,8 @@
CLK_LOOKUP("core_clk", gcc_blsp2_qup3_i2c_apps_clk.c, ""),
CLK_LOOKUP("core_clk", gcc_blsp2_qup3_spi_apps_clk.c, ""),
CLK_LOOKUP("core_clk", gcc_blsp2_qup4_i2c_apps_clk.c, ""),
- CLK_LOOKUP("core_clk", gcc_blsp2_qup4_spi_apps_clk.c, ""),
CLK_LOOKUP("core_clk", gcc_blsp2_qup5_i2c_apps_clk.c, "f9967000.i2c"),
+ CLK_LOOKUP("core_clk", gcc_blsp2_qup4_spi_apps_clk.c, "f9966000.spi"),
CLK_LOOKUP("core_clk", gcc_blsp2_qup5_spi_apps_clk.c, ""),
CLK_LOOKUP("core_clk", gcc_blsp2_qup6_i2c_apps_clk.c, ""),
CLK_LOOKUP("core_clk", gcc_blsp2_qup6_spi_apps_clk.c, ""),
diff --git a/arch/arm/mach-msm/clock-9625.c b/arch/arm/mach-msm/clock-9625.c
deleted file mode 100644
index a07eebb..0000000
--- a/arch/arm/mach-msm/clock-9625.c
+++ /dev/null
@@ -1,2278 +0,0 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/ctype.h>
-#include <linux/io.h>
-#include <linux/spinlock.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-
-#include <mach/clk.h>
-#include <mach/rpm-regulator-smd.h>
-#include <mach/socinfo.h>
-
-#include "clock-local2.h"
-#include "clock-pll.h"
-#include "clock-rpm.h"
-#include "clock-voter.h"
-#include "clock.h"
-
-enum {
- GCC_BASE,
- LPASS_BASE,
- APCS_BASE,
- APCS_PLL_BASE,
- N_BASES,
-};
-
-static void __iomem *virt_bases[N_BASES];
-
-#define GCC_REG_BASE(x) (void __iomem *)(virt_bases[GCC_BASE] + (x))
-#define LPASS_REG_BASE(x) (void __iomem *)(virt_bases[LPASS_BASE] + (x))
-#define APCS_REG_BASE(x) (void __iomem *)(virt_bases[APCS_BASE] + (x))
-#define APCS_PLL_REG_BASE(x) (void __iomem *)(virt_bases[APCS_PLL_BASE] + (x))
-
-/* GCC registers */
-#define GPLL0_MODE_REG 0x0000
-#define GPLL0_L_REG 0x0004
-#define GPLL0_M_REG 0x0008
-#define GPLL0_N_REG 0x000C
-#define GPLL0_USER_CTL_REG 0x0010
-#define GPLL0_CONFIG_CTL_REG 0x0014
-#define GPLL0_TEST_CTL_REG 0x0018
-#define GPLL0_STATUS_REG 0x001C
-
-#define GPLL1_MODE_REG 0x0040
-#define GPLL1_L_REG 0x0044
-#define GPLL1_M_REG 0x0048
-#define GPLL1_N_REG 0x004C
-#define GPLL1_USER_CTL_REG 0x0050
-#define GPLL1_CONFIG_CTL_REG 0x0054
-#define GPLL1_TEST_CTL_REG 0x0058
-#define GPLL1_STATUS_REG 0x005C
-
-#define GCC_DEBUG_CLK_CTL_REG 0x1880
-#define CLOCK_FRQ_MEASURE_CTL_REG 0x1884
-#define CLOCK_FRQ_MEASURE_STATUS_REG 0x1888
-#define GCC_PLLTEST_PAD_CFG_REG 0x188C
-#define GCC_XO_DIV4_CBCR_REG 0x10C8
-#define APCS_GPLL_ENA_VOTE_REG 0x1480
-#define APCS_CLOCK_BRANCH_ENA_VOTE 0x1484
-#define APCS_CLOCK_SLEEP_ENA_VOTE 0x1488
-
-#define APCS_CLK_DIAG_REG 0x001C
-
-#define APCS_CPU_PLL_MODE_REG 0x0000
-#define APCS_CPU_PLL_L_REG 0x0004
-#define APCS_CPU_PLL_M_REG 0x0008
-#define APCS_CPU_PLL_N_REG 0x000C
-#define APCS_CPU_PLL_USER_CTL_REG 0x0010
-#define APCS_CPU_PLL_CONFIG_CTL_REG 0x0014
-#define APCS_CPU_PLL_TEST_CTL_REG 0x0018
-#define APCS_CPU_PLL_STATUS_REG 0x001C
-
-#define USB_HSIC_SYSTEM_CMD_RCGR 0x041C
-#define USB_HSIC_XCVR_FS_CMD_RCGR 0x0424
-#define USB_HSIC_CMD_RCGR 0x0440
-#define USB_HSIC_IO_CAL_CMD_RCGR 0x0458
-#define USB_HS_SYSTEM_CMD_RCGR 0x0490
-#define SDCC2_APPS_CMD_RCGR 0x0510
-#define SDCC3_APPS_CMD_RCGR 0x0550
-#define BLSP1_QUP1_SPI_APPS_CMD_RCGR 0x064C
-#define BLSP1_UART1_APPS_CMD_RCGR 0x068C
-#define BLSP1_QUP2_SPI_APPS_CMD_RCGR 0x06CC
-#define BLSP1_UART2_APPS_CMD_RCGR 0x070C
-#define BLSP1_QUP3_SPI_APPS_CMD_RCGR 0x074C
-#define BLSP1_UART3_APPS_CMD_RCGR 0x078C
-#define BLSP1_QUP4_SPI_APPS_CMD_RCGR 0x07CC
-#define BLSP1_UART4_APPS_CMD_RCGR 0x080C
-#define BLSP1_QUP5_SPI_APPS_CMD_RCGR 0x084C
-#define BLSP1_UART5_APPS_CMD_RCGR 0x088C
-#define BLSP1_QUP6_SPI_APPS_CMD_RCGR 0x08CC
-#define BLSP1_UART6_APPS_CMD_RCGR 0x090C
-#define PDM2_CMD_RCGR 0x0CD0
-#define CE1_CMD_RCGR 0x1050
-#define GP1_CMD_RCGR 0x1904
-#define GP2_CMD_RCGR 0x1944
-#define GP3_CMD_RCGR 0x1984
-#define QPIC_CMD_RCGR 0x1A50
-#define IPA_CMD_RCGR 0x1A90
-
-#define USB_HS_HSIC_BCR 0x0400
-#define USB_HS_BCR 0x0480
-#define SDCC2_BCR 0x0500
-#define SDCC3_BCR 0x0540
-#define BLSP1_BCR 0x05C0
-#define BLSP1_QUP1_BCR 0x0640
-#define BLSP1_UART1_BCR 0x0680
-#define BLSP1_QUP2_BCR 0x06C0
-#define BLSP1_UART2_BCR 0x0700
-#define BLSP1_QUP3_BCR 0x0740
-#define BLSP1_UART3_BCR 0x0780
-#define BLSP1_QUP4_BCR 0x07C0
-#define BLSP1_UART4_BCR 0x0800
-#define BLSP1_QUP5_BCR 0x0840
-#define BLSP1_UART5_BCR 0x0880
-#define BLSP1_QUP6_BCR 0x08C0
-#define BLSP1_UART6_BCR 0x0900
-#define PDM_BCR 0x0CC0
-#define PRNG_BCR 0x0D00
-#define BAM_DMA_BCR 0x0D40
-#define BOOT_ROM_BCR 0x0E00
-#define CE1_BCR 0x1040
-#define QPIC_BCR 0x1040
-#define IPA_BCR 0x1A80
-
-
-#define SYS_NOC_IPA_AXI_CBCR 0x0128
-#define USB_HSIC_AHB_CBCR 0x0408
-#define USB_HSIC_SYSTEM_CBCR 0x040C
-#define USB_HSIC_CBCR 0x0410
-#define USB_HSIC_IO_CAL_CBCR 0x0414
-#define USB_HSIC_XCVR_FS_CBCR 0x042C
-#define USB_HS_SYSTEM_CBCR 0x0484
-#define USB_HS_AHB_CBCR 0x0488
-#define SDCC2_APPS_CBCR 0x0504
-#define SDCC2_AHB_CBCR 0x0508
-#define SDCC3_APPS_CBCR 0x0544
-#define SDCC3_AHB_CBCR 0x0548
-#define BLSP1_AHB_CBCR 0x05C4
-#define BLSP1_QUP1_SPI_APPS_CBCR 0x0644
-#define BLSP1_QUP1_I2C_APPS_CBCR 0x0648
-#define BLSP1_UART1_APPS_CBCR 0x0684
-#define BLSP1_UART1_SIM_CBCR 0x0688
-#define BLSP1_QUP2_SPI_APPS_CBCR 0x06C4
-#define BLSP1_QUP2_I2C_APPS_CBCR 0x06C8
-#define BLSP1_UART2_APPS_CBCR 0x0704
-#define BLSP1_UART2_SIM_CBCR 0x0708
-#define BLSP1_QUP3_SPI_APPS_CBCR 0x0744
-#define BLSP1_QUP3_I2C_APPS_CBCR 0x0748
-#define BLSP1_UART3_APPS_CBCR 0x0784
-#define BLSP1_UART3_SIM_CBCR 0x0788
-#define BLSP1_QUP4_SPI_APPS_CBCR 0x07C4
-#define BLSP1_QUP4_I2C_APPS_CBCR 0x07C8
-#define BLSP1_UART4_APPS_CBCR 0x0804
-#define BLSP1_UART4_SIM_CBCR 0x0808
-#define BLSP1_QUP5_SPI_APPS_CBCR 0x0844
-#define BLSP1_QUP5_I2C_APPS_CBCR 0x0848
-#define BLSP1_UART5_APPS_CBCR 0x0884
-#define BLSP1_UART5_SIM_CBCR 0x0888
-#define BLSP1_QUP6_SPI_APPS_CBCR 0x08C4
-#define BLSP1_QUP6_I2C_APPS_CBCR 0x08C8
-#define BLSP1_UART6_APPS_CBCR 0x0904
-#define BLSP1_UART6_SIM_CBCR 0x0908
-#define BOOT_ROM_AHB_CBCR 0x0E04
-#define PDM_AHB_CBCR 0x0CC4
-#define PDM_XO4_CBCR 0x0CC8
-#define PDM_AHB_CBCR 0x0CC4
-#define PDM_XO4_CBCR 0x0CC8
-#define PDM2_CBCR 0x0CCC
-#define PRNG_AHB_CBCR 0x0D04
-#define BAM_DMA_AHB_CBCR 0x0D44
-#define MSG_RAM_AHB_CBCR 0x0E44
-#define CE1_CBCR 0x1044
-#define CE1_AXI_CBCR 0x1048
-#define CE1_AHB_CBCR 0x104C
-#define GCC_AHB_CBCR 0x10C0
-#define GP1_CBCR 0x1900
-#define GP2_CBCR 0x1940
-#define GP3_CBCR 0x1980
-#define QPIC_CBCR 0x1A44
-#define QPIC_AHB_CBCR 0x1A48
-#define IPA_CBCR 0x1A84
-#define IPA_CNOC_CBCR 0x1A88
-#define IPA_SLEEP_CBCR 0x1A8C
-
-/* LPASS registers */
-/* TODO: Needs to double check lpass regiserts after get the SWI for hw */
-#define LPAPLL_MODE_REG 0x0000
-#define LPAPLL_L_REG 0x0004
-#define LPAPLL_M_REG 0x0008
-#define LPAPLL_N_REG 0x000C
-#define LPAPLL_USER_CTL_REG 0x0010
-#define LPAPLL_CONFIG_CTL_REG 0x0014
-#define LPAPLL_TEST_CTL_REG 0x0018
-#define LPAPLL_STATUS_REG 0x001C
-
-#define LPASS_DEBUG_CLK_CTL_REG 0x29000
-#define LPASS_LPA_PLL_VOTE_APPS_REG 0x2000
-
-#define LPAIF_PRI_CMD_RCGR 0xB000
-#define LPAIF_SEC_CMD_RCGR 0xC000
-#define LPAIF_PCM0_CMD_RCGR 0xF000
-#define LPAIF_PCM1_CMD_RCGR 0x10000
-#define SLIMBUS_CMD_RCGR 0x12000
-#define LPAIF_PCMOE_CMD_RCGR 0x13000
-
-#define AUDIO_CORE_BCR 0x4000
-
-#define AUDIO_CORE_LPAIF_PRI_OSR_CBCR 0xB014
-#define AUDIO_CORE_LPAIF_PRI_IBIT_CBCR 0xB018
-#define AUDIO_CORE_LPAIF_PRI_EBIT_CBCR 0xB01C
-#define AUDIO_CORE_LPAIF_SEC_OSR_CBCR 0xC014
-#define AUDIO_CORE_LPAIF_SEC_IBIT_CBCR 0xC018
-#define AUDIO_CORE_LPAIF_SEC_EBIT_CBCR 0xC01C
-#define AUDIO_CORE_LPAIF_PCM0_IBIT_CBCR 0xF014
-#define AUDIO_CORE_LPAIF_PCM0_EBIT_CBCR 0xF018
-#define AUDIO_CORE_LPAIF_PCM1_IBIT_CBCR 0x10014
-#define AUDIO_CORE_LPAIF_PCM1_EBIT_CBCR 0x10018
-#define AUDIO_CORE_RESAMPLER_CORE_CBCR 0x11014
-#define AUDIO_CORE_RESAMPLER_LFABIF_CBCR 0x11018
-#define AUDIO_CORE_SLIMBUS_CORE_CBCR 0x12014
-#define AUDIO_CORE_SLIMBUS_LFABIF_CBCR 0x12018
-#define AUDIO_CORE_LPAIF_PCM_DATA_OE_CBCR 0x13014
-
-/* Mux source select values */
-#define cxo_source_val 0
-#define gpll0_source_val 1
-#define gpll1_hsic_source_val 4
-#define gnd_source_val 5
-#define cxo_lpass_source_val 0
-#define lpapll0_lpass_source_val 1
-#define gpll0_lpass_source_val 5
-
-#define F(f, s, div, m, n) \
- { \
- .freq_hz = (f), \
- .src_clk = &s##_clk_src.c, \
- .m_val = (m), \
- .n_val = ~((n)-(m)) * !!(n), \
- .d_val = ~(n),\
- .div_src_val = BVAL(4, 0, (int)(2*(div) - 1)) \
- | BVAL(10, 8, s##_source_val), \
- }
-
-#define F_HSIC(f, s, div, m, n) \
- { \
- .freq_hz = (f), \
- .src_clk = &s##_clk_src.c, \
- .m_val = (m), \
- .n_val = ~((n)-(m)) * !!(n), \
- .d_val = ~(n),\
- .div_src_val = BVAL(4, 0, (int)(2*(div) - 1)) \
- | BVAL(10, 8, s##_hsic_source_val), \
- }
-
-#define F_LPASS(f, s, div, m, n) \
- { \
- .freq_hz = (f), \
- .src_clk = &s##_clk_src.c, \
- .m_val = (m), \
- .n_val = ~((n)-(m)) * !!(n), \
- .d_val = ~(n),\
- .div_src_val = BVAL(4, 0, (int)(2*(div) - 1)) \
- | BVAL(10, 8, s##_lpass_source_val), \
- }
-
-
-#define VDD_DIG_FMAX_MAP1(l1, f1) \
- .vdd_class = &vdd_dig, \
- .fmax[VDD_DIG_##l1] = (f1)
-#define VDD_DIG_FMAX_MAP2(l1, f1, l2, f2) \
- .vdd_class = &vdd_dig, \
- .fmax[VDD_DIG_##l1] = (f1), \
- .fmax[VDD_DIG_##l2] = (f2)
-#define VDD_DIG_FMAX_MAP3(l1, f1, l2, f2, l3, f3) \
- .vdd_class = &vdd_dig, \
- .fmax[VDD_DIG_##l1] = (f1), \
- .fmax[VDD_DIG_##l2] = (f2), \
- .fmax[VDD_DIG_##l3] = (f3)
-
-enum vdd_dig_levels {
- VDD_DIG_NONE,
- VDD_DIG_LOW,
- VDD_DIG_NOMINAL,
- VDD_DIG_HIGH
-};
-
-/* TODO: Add regulator set voltage APIs when support is available */
-static int set_vdd_dig(struct clk_vdd_class *vdd_class, int level)
-{
- return 0;
-}
-
-static DEFINE_VDD_CLASS(vdd_dig, set_vdd_dig);
-
-/* TODO: Needs to confirm the below values */
-#define RPM_MISC_CLK_TYPE 0x306b6c63
-#define RPM_BUS_CLK_TYPE 0x316b6c63
-#define RPM_MEM_CLK_TYPE 0x326b6c63
-
-#define RPM_SMD_KEY_ENABLE 0x62616E45
-
-#define CXO_ID 0x0
-#define QDSS_ID 0x1
-#define RPM_SCALING_ENABLE_ID 0x2
-
-#define PNOC_ID 0x0
-#define SNOC_ID 0x1
-#define CNOC_ID 0x2
-
-#define BIMC_ID 0x0
-
-#define D0_ID 1
-#define D1_ID 2
-#define A0_ID 3
-#define A1_ID 4
-#define A2_ID 5
-
-DEFINE_CLK_RPM_SMD_BRANCH(cxo_clk_src, cxo_a_clk_src,
- RPM_MISC_CLK_TYPE, CXO_ID, 19200000);
-
-DEFINE_CLK_RPM_SMD(cnoc_clk, cnoc_a_clk, RPM_BUS_CLK_TYPE, CNOC_ID, NULL);
-DEFINE_CLK_RPM_SMD(pnoc_clk, pnoc_a_clk, RPM_BUS_CLK_TYPE, PNOC_ID, NULL);
-DEFINE_CLK_RPM_SMD(snoc_clk, snoc_a_clk, RPM_BUS_CLK_TYPE, SNOC_ID, NULL);
-
-DEFINE_CLK_RPM_SMD(bimc_clk, bimc_a_clk, RPM_MEM_CLK_TYPE, BIMC_ID, NULL);
-
-DEFINE_CLK_RPM_SMD_QDSS(qdss_clk, qdss_a_clk, RPM_MISC_CLK_TYPE, QDSS_ID);
-
-DEFINE_CLK_RPM_SMD_XO_BUFFER(cxo_d0, cxo_d0_a, D0_ID);
-DEFINE_CLK_RPM_SMD_XO_BUFFER(cxo_d1, cxo_d1_a, D1_ID);
-DEFINE_CLK_RPM_SMD_XO_BUFFER(cxo_a0, cxo_a0_a, A0_ID);
-DEFINE_CLK_RPM_SMD_XO_BUFFER(cxo_a1, cxo_a1_a, A1_ID);
-DEFINE_CLK_RPM_SMD_XO_BUFFER(cxo_a2, cxo_a2_a, A2_ID);
-
-DEFINE_CLK_RPM_SMD_XO_BUFFER_PINCTRL(cxo_d0_pin, cxo_d0_a_pin, D0_ID);
-DEFINE_CLK_RPM_SMD_XO_BUFFER_PINCTRL(cxo_d1_pin, cxo_d1_a_pin, D1_ID);
-DEFINE_CLK_RPM_SMD_XO_BUFFER_PINCTRL(cxo_a0_pin, cxo_a0_a_pin, A0_ID);
-DEFINE_CLK_RPM_SMD_XO_BUFFER_PINCTRL(cxo_a1_pin, cxo_a1_a_pin, A1_ID);
-DEFINE_CLK_RPM_SMD_XO_BUFFER_PINCTRL(cxo_a2_pin, cxo_a2_a_pin, A2_ID);
-
-static struct pll_vote_clk gpll0_clk_src = {
- .en_reg = (void __iomem *)APCS_GPLL_ENA_VOTE_REG,
- .status_reg = (void __iomem *)GPLL0_STATUS_REG,
- .status_mask = BIT(17),
- .parent = &cxo_clk_src.c,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .rate = 600000000,
- .dbg_name = "gpll0_clk_src",
- .ops = &clk_ops_pll_vote,
- CLK_INIT(gpll0_clk_src.c),
- },
-};
-
-static struct pll_vote_clk lpapll0_clk_src = {
- .en_reg = (void __iomem *)LPASS_LPA_PLL_VOTE_APPS_REG,
- .en_mask = BIT(0),
- .status_reg = (void __iomem *)LPAPLL_STATUS_REG,
- .status_mask = BIT(17),
- .parent = &cxo_clk_src.c,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .rate = 393216000,
- .dbg_name = "lpapll0_clk_src",
- .ops = &clk_ops_pll_vote,
- CLK_INIT(lpapll0_clk_src.c),
- },
-};
-
-static struct pll_vote_clk gpll1_clk_src = {
- .en_reg = (void __iomem *)APCS_GPLL_ENA_VOTE_REG,
- .en_mask = BIT(1),
- .status_reg = (void __iomem *)GPLL1_STATUS_REG,
- .status_mask = BIT(17),
- .parent = &cxo_clk_src.c,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .rate = 480000000,
- .dbg_name = "gpll1_clk_src",
- .ops = &clk_ops_pll_vote,
- CLK_INIT(gpll1_clk_src.c),
- },
-};
-
-static struct pll_clk apcspll_clk_src = {
- .mode_reg = (void __iomem *)APCS_CPU_PLL_MODE_REG,
- .status_reg = (void __iomem *)APCS_CPU_PLL_STATUS_REG,
- .parent = &cxo_clk_src.c,
- .base = &virt_bases[APCS_PLL_BASE],
- .c = {
- .rate = 748800000,
- .dbg_name = "apcspll_clk_src",
- .ops = &clk_ops_local_pll,
- CLK_INIT(apcspll_clk_src.c),
- },
-};
-
-static DEFINE_CLK_VOTER(pnoc_msmbus_clk, &pnoc_clk.c, LONG_MAX);
-static DEFINE_CLK_VOTER(snoc_msmbus_clk, &snoc_clk.c, LONG_MAX);
-static DEFINE_CLK_VOTER(cnoc_msmbus_clk, &cnoc_clk.c, LONG_MAX);
-static DEFINE_CLK_VOTER(pnoc_msmbus_a_clk, &pnoc_a_clk.c, LONG_MAX);
-static DEFINE_CLK_VOTER(snoc_msmbus_a_clk, &snoc_a_clk.c, LONG_MAX);
-static DEFINE_CLK_VOTER(cnoc_msmbus_a_clk, &cnoc_a_clk.c, LONG_MAX);
-
-static DEFINE_CLK_VOTER(bimc_msmbus_clk, &bimc_clk.c, LONG_MAX);
-static DEFINE_CLK_VOTER(bimc_msmbus_a_clk, &bimc_a_clk.c, LONG_MAX);
-
-static DEFINE_CLK_VOTER(pnoc_sdcc2_clk, &pnoc_clk.c, LONG_MAX);
-static DEFINE_CLK_VOTER(pnoc_sdcc3_clk, &pnoc_clk.c, LONG_MAX);
-
-static DEFINE_CLK_VOTER(pnoc_sps_clk, &pnoc_clk.c, LONG_MAX);
-
-static struct clk_freq_tbl ftbl_gcc_ipa_clk[] = {
- F( 50000000, gpll0, 12, 0, 0),
- F( 92310000, gpll0, 6.5, 0, 0),
- F(100000000, gpll0, 6, 0, 0),
- F_END
-};
-
-static struct rcg_clk ipa_clk_src = {
- .cmd_rcgr_reg = IPA_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_gcc_ipa_clk,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "ipa_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 50000000, NOMINAL, 100000000),
- CLK_INIT(ipa_clk_src.c)
- },
-};
-
-static struct clk_freq_tbl ftbl_gcc_blsp1_qup1_6_spi_apps_clk[] = {
- F(960000, cxo, 10, 1, 2),
- F(4800000, cxo, 4, 0, 0),
- F(9600000, cxo, 2, 0, 0),
- F(15000000, gpll0, 10, 1, 4),
- F(19200000, cxo, 1, 0, 0),
- F(25000000, gpll0, 12, 1, 2),
- F(50000000, gpll0, 12, 0, 0),
- F_END
-};
-
-static struct rcg_clk blsp1_qup1_spi_apps_clk_src = {
- .cmd_rcgr_reg = BLSP1_QUP1_SPI_APPS_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "blsp1_qup1_spi_apps_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000),
- CLK_INIT(blsp1_qup1_spi_apps_clk_src.c)
- },
-};
-
-static struct rcg_clk blsp1_qup2_spi_apps_clk_src = {
- .cmd_rcgr_reg = BLSP1_QUP2_SPI_APPS_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "blsp1_qup2_spi_apps_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000),
- CLK_INIT(blsp1_qup2_spi_apps_clk_src.c)
- },
-};
-
-static struct rcg_clk blsp1_qup3_spi_apps_clk_src = {
- .cmd_rcgr_reg = BLSP1_QUP3_SPI_APPS_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "blsp1_qup3_spi_apps_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000),
- CLK_INIT(blsp1_qup3_spi_apps_clk_src.c)
- },
-};
-
-static struct rcg_clk blsp1_qup4_spi_apps_clk_src = {
- .cmd_rcgr_reg = BLSP1_QUP4_SPI_APPS_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "blsp1_qup4_spi_apps_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000),
- CLK_INIT(blsp1_qup4_spi_apps_clk_src.c)
- },
-};
-
-static struct rcg_clk blsp1_qup5_spi_apps_clk_src = {
- .cmd_rcgr_reg = BLSP1_QUP5_SPI_APPS_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "blsp1_qup5_spi_apps_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000),
- CLK_INIT(blsp1_qup5_spi_apps_clk_src.c)
- },
-};
-
-static struct rcg_clk blsp1_qup6_spi_apps_clk_src = {
- .cmd_rcgr_reg = BLSP1_QUP6_SPI_APPS_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "blsp1_qup6_spi_apps_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000),
- CLK_INIT(blsp1_qup6_spi_apps_clk_src.c)
- },
-};
-
-static struct clk_freq_tbl ftbl_gcc_blsp1_uart1_6_apps_clk[] = {
- F(3686400, gpll0, 1, 96, 15625),
- F(7372800, gpll0, 1, 192, 15625),
- F(14745600, gpll0, 1, 384, 15625),
- F(16000000, gpll0, 5, 2, 15),
- F(19200000, cxo, 1, 0, 0),
- F(24000000, gpll0, 5, 1, 5),
- F(32000000, gpll0, 1, 4, 75),
- F(40000000, gpll0, 15, 0, 0),
- F(46400000, gpll0, 1, 29, 375),
- F(48000000, gpll0, 12.5, 0, 0),
- F(51200000, gpll0, 1, 32, 375),
- F(56000000, gpll0, 1, 7, 75),
- F(58982400, gpll0, 1, 1536, 15625),
- F(60000000, gpll0, 10, 0, 0),
- F_END
-};
-
-static struct rcg_clk blsp1_uart1_apps_clk_src = {
- .cmd_rcgr_reg = BLSP1_UART1_APPS_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "blsp1_uart1_apps_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 31580000, NOMINAL, 63160000),
- CLK_INIT(blsp1_uart1_apps_clk_src.c)
- },
-};
-
-static struct rcg_clk blsp1_uart2_apps_clk_src = {
- .cmd_rcgr_reg = BLSP1_UART2_APPS_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "blsp1_uart2_apps_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 31580000, NOMINAL, 63160000),
- CLK_INIT(blsp1_uart2_apps_clk_src.c)
- },
-};
-
-static struct rcg_clk blsp1_uart3_apps_clk_src = {
- .cmd_rcgr_reg = BLSP1_UART3_APPS_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "blsp1_uart3_apps_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 31580000, NOMINAL, 63160000),
- CLK_INIT(blsp1_uart3_apps_clk_src.c)
- },
-};
-
-static struct rcg_clk blsp1_uart4_apps_clk_src = {
- .cmd_rcgr_reg = BLSP1_UART4_APPS_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "blsp1_uart4_apps_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 31580000, NOMINAL, 63160000),
- CLK_INIT(blsp1_uart4_apps_clk_src.c)
- },
-};
-
-static struct rcg_clk blsp1_uart5_apps_clk_src = {
- .cmd_rcgr_reg = BLSP1_UART5_APPS_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "blsp1_uart5_apps_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 31580000, NOMINAL, 63160000),
- CLK_INIT(blsp1_uart5_apps_clk_src.c)
- },
-};
-
-static struct rcg_clk blsp1_uart6_apps_clk_src = {
- .cmd_rcgr_reg = BLSP1_UART6_APPS_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "blsp1_uart6_apps_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 31580000, NOMINAL, 63160000),
- CLK_INIT(blsp1_uart6_apps_clk_src.c)
- },
-};
-
-static struct clk_freq_tbl ftbl_gcc_ce1_clk[] = {
- F(50000000, gpll0, 12, 0, 0),
- F(100000000, gpll0, 6, 0, 0),
- F_END
-};
-
-static struct rcg_clk ce1_clk_src = {
- .cmd_rcgr_reg = CE1_CMD_RCGR,
- .set_rate = set_rate_hid,
- .freq_tbl = ftbl_gcc_ce1_clk,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "ce1_clk_src",
- .ops = &clk_ops_rcg,
- VDD_DIG_FMAX_MAP2(LOW, 50000000, NOMINAL, 100000000),
- CLK_INIT(ce1_clk_src.c),
- },
-};
-
-static struct clk_freq_tbl ftbl_gcc_gp_clk[] = {
- F(19200000, cxo, 1, 0, 0),
- F_END
-};
-
-static struct rcg_clk gp1_clk_src = {
- .cmd_rcgr_reg = GP1_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_gcc_gp_clk,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gp1_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
- CLK_INIT(gp1_clk_src.c)
- },
-};
-
-static struct rcg_clk gp2_clk_src = {
- .cmd_rcgr_reg = GP2_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_gcc_gp_clk,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gp2_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
- CLK_INIT(gp2_clk_src.c)
- },
-};
-
-static struct rcg_clk gp3_clk_src = {
- .cmd_rcgr_reg = GP3_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_gcc_gp_clk,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gp3_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
- CLK_INIT(gp3_clk_src.c)
- },
-};
-
-static struct clk_freq_tbl ftbl_gcc_pdm2_clk[] = {
- F(60000000, gpll0, 10, 0, 0),
- F_END
-};
-
-static struct rcg_clk pdm2_clk_src = {
- .cmd_rcgr_reg = PDM2_CMD_RCGR,
- .set_rate = set_rate_hid,
- .freq_tbl = ftbl_gcc_pdm2_clk,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "pdm2_clk_src",
- .ops = &clk_ops_rcg,
- VDD_DIG_FMAX_MAP1(LOW, 60000000),
- CLK_INIT(pdm2_clk_src.c),
- },
-};
-
-static struct clk_freq_tbl ftbl_gcc_qpic_clk[] = {
- F(50000000, gpll0, 12, 0, 0),
- F(100000000, gpll0, 6, 0, 0),
- F_END
-};
-
-static struct rcg_clk qpic_clk_src = {
- .cmd_rcgr_reg = QPIC_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_gcc_qpic_clk,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "qpic_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 50000000, NOMINAL, 100000000),
- CLK_INIT(qpic_clk_src.c)
- },
-};
-
-static struct clk_freq_tbl ftbl_gcc_sdcc2_apps_clk[] = {
- F(144000, cxo, 16, 3, 25),
- F(400000, cxo, 12, 1, 4),
- F(20000000, gpll0, 15, 1, 2),
- F(25000000, gpll0, 12, 1, 2),
- F(50000000, gpll0, 12, 0, 0),
- F(100000000, gpll0, 6, 0, 0),
- F(200000000, gpll0, 3, 0, 0),
- F_END
-};
-
-static struct clk_freq_tbl ftbl_gcc_sdcc3_apps_clk[] = {
- F(144000, cxo, 16, 3, 25),
- F(400000, cxo, 12, 1, 4),
- F(20000000, gpll0, 15, 1, 2),
- F(25000000, gpll0, 12, 1, 2),
- F(50000000, gpll0, 12, 0, 0),
- F(100000000, gpll0, 6, 0, 0),
- F_END
-};
-
-static struct rcg_clk sdcc2_apps_clk_src = {
- .cmd_rcgr_reg = SDCC2_APPS_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_gcc_sdcc2_apps_clk,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "sdcc2_apps_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
- CLK_INIT(sdcc2_apps_clk_src.c)
- },
-};
-
-static struct rcg_clk sdcc3_apps_clk_src = {
- .cmd_rcgr_reg = SDCC3_APPS_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_gcc_sdcc3_apps_clk,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "sdcc3_apps_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 50000000, NOMINAL, 100000000),
- CLK_INIT(sdcc3_apps_clk_src.c)
- },
-};
-
-static struct clk_freq_tbl ftbl_gcc_usb_hs_system_clk[] = {
- F(75000000, gpll0, 8, 0, 0),
- F_END
-};
-
-static struct rcg_clk usb_hs_system_clk_src = {
- .cmd_rcgr_reg = USB_HS_SYSTEM_CMD_RCGR,
- .set_rate = set_rate_hid,
- .freq_tbl = ftbl_gcc_usb_hs_system_clk,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "usb_hs_system_clk_src",
- .ops = &clk_ops_rcg,
- VDD_DIG_FMAX_MAP2(LOW, 37500000, NOMINAL, 75000000),
- CLK_INIT(usb_hs_system_clk_src.c),
- },
-};
-
-static struct clk_freq_tbl ftbl_gcc_usb_hsic_clk[] = {
- F_HSIC(480000000, gpll1, 1, 0, 0),
- F_END
-};
-
-static struct rcg_clk usb_hsic_clk_src = {
- .cmd_rcgr_reg = USB_HSIC_CMD_RCGR,
- .set_rate = set_rate_hid,
- .freq_tbl = ftbl_gcc_usb_hsic_clk,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "usb_hsic_clk_src",
- .ops = &clk_ops_rcg,
- VDD_DIG_FMAX_MAP1(LOW, 480000000),
- CLK_INIT(usb_hsic_clk_src.c),
- },
-};
-
-static struct clk_freq_tbl ftbl_gcc_usb_hsic_io_cal_clk[] = {
- F(9600000, cxo, 2, 0, 0),
- F_END
-};
-
-static struct rcg_clk usb_hsic_io_cal_clk_src = {
- .cmd_rcgr_reg = USB_HSIC_IO_CAL_CMD_RCGR,
- .set_rate = set_rate_hid,
- .freq_tbl = ftbl_gcc_usb_hsic_io_cal_clk,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "usb_hsic_io_cal_clk_src",
- .ops = &clk_ops_rcg,
- VDD_DIG_FMAX_MAP1(LOW, 9600000),
- CLK_INIT(usb_hsic_io_cal_clk_src.c),
- },
-};
-
-static struct clk_freq_tbl ftbl_gcc_usb_hsic_system_clk[] = {
- F(75000000, gpll0, 8, 0, 0),
- F_END
-};
-
-static struct rcg_clk usb_hsic_system_clk_src = {
- .cmd_rcgr_reg = USB_HSIC_SYSTEM_CMD_RCGR,
- .set_rate = set_rate_hid,
- .freq_tbl = ftbl_gcc_usb_hsic_system_clk,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "usb_hsic_system_clk_src",
- .ops = &clk_ops_rcg,
- VDD_DIG_FMAX_MAP2(LOW, 60000000, NOMINAL, 75000000),
- CLK_INIT(usb_hsic_system_clk_src.c),
- },
-};
-
-static struct clk_freq_tbl ftbl_gcc_usb_hsic_xcvr_fs_clk[] = {
- F(60000000, gpll0, 10, 0, 0),
- F_END
-};
-
-static struct rcg_clk usb_hsic_xcvr_fs_clk_src = {
- .cmd_rcgr_reg = USB_HSIC_XCVR_FS_CMD_RCGR,
- .set_rate = set_rate_hid,
- .freq_tbl = ftbl_gcc_usb_hsic_xcvr_fs_clk,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "usb_hsic_xcvr_fs_clk_src",
- .ops = &clk_ops_rcg,
- VDD_DIG_FMAX_MAP1(LOW, 60000000),
- CLK_INIT(usb_hsic_xcvr_fs_clk_src.c),
- },
-};
-
-static struct local_vote_clk gcc_bam_dma_ahb_clk = {
- .cbcr_reg = BAM_DMA_AHB_CBCR,
- .vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
- .en_mask = BIT(12),
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_bam_dma_ahb_clk",
- .ops = &clk_ops_vote,
- CLK_INIT(gcc_bam_dma_ahb_clk.c),
- },
-};
-
-static struct local_vote_clk gcc_blsp1_ahb_clk = {
- .cbcr_reg = BLSP1_AHB_CBCR,
- .vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
- .en_mask = BIT(17),
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_blsp1_ahb_clk",
- .ops = &clk_ops_vote,
- CLK_INIT(gcc_blsp1_ahb_clk.c),
- },
-};
-
-static struct branch_clk gcc_blsp1_qup1_i2c_apps_clk = {
- .cbcr_reg = BLSP1_QUP1_I2C_APPS_CBCR,
- .parent = &cxo_clk_src.c,
- .has_sibling = 1,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_blsp1_qup1_i2c_apps_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_blsp1_qup1_i2c_apps_clk.c),
- },
-};
-
-static struct branch_clk gcc_blsp1_qup1_spi_apps_clk = {
- .cbcr_reg = BLSP1_QUP1_SPI_APPS_CBCR,
- .parent = &blsp1_qup1_spi_apps_clk_src.c,
- .has_sibling = 0,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_blsp1_qup1_spi_apps_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_blsp1_qup1_spi_apps_clk.c),
- },
-};
-
-static struct branch_clk gcc_blsp1_qup2_i2c_apps_clk = {
- .cbcr_reg = BLSP1_QUP2_I2C_APPS_CBCR,
- .parent = &cxo_clk_src.c,
- .has_sibling = 1,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_blsp1_qup2_i2c_apps_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_blsp1_qup2_i2c_apps_clk.c),
- },
-};
-
-static struct branch_clk gcc_blsp1_qup2_spi_apps_clk = {
- .cbcr_reg = BLSP1_QUP2_SPI_APPS_CBCR,
- .parent = &blsp1_qup2_spi_apps_clk_src.c,
- .has_sibling = 0,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_blsp1_qup2_spi_apps_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_blsp1_qup2_spi_apps_clk.c),
- },
-};
-
-static struct branch_clk gcc_blsp1_qup3_i2c_apps_clk = {
- .cbcr_reg = BLSP1_QUP3_I2C_APPS_CBCR,
- .parent = &cxo_clk_src.c,
- .has_sibling = 1,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_blsp1_qup3_i2c_apps_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_blsp1_qup3_i2c_apps_clk.c),
- },
-};
-
-static struct branch_clk gcc_blsp1_qup3_spi_apps_clk = {
- .cbcr_reg = BLSP1_QUP3_SPI_APPS_CBCR,
- .parent = &blsp1_qup3_spi_apps_clk_src.c,
- .has_sibling = 0,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_blsp1_qup3_spi_apps_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_blsp1_qup3_spi_apps_clk.c),
- },
-};
-
-static struct branch_clk gcc_blsp1_qup4_i2c_apps_clk = {
- .cbcr_reg = BLSP1_QUP4_I2C_APPS_CBCR,
- .parent = &cxo_clk_src.c,
- .has_sibling = 1,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_blsp1_qup4_i2c_apps_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_blsp1_qup4_i2c_apps_clk.c),
- },
-};
-
-static struct branch_clk gcc_blsp1_qup4_spi_apps_clk = {
- .cbcr_reg = BLSP1_QUP4_SPI_APPS_CBCR,
- .parent = &blsp1_qup4_spi_apps_clk_src.c,
- .has_sibling = 0,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_blsp1_qup4_spi_apps_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_blsp1_qup4_spi_apps_clk.c),
- },
-};
-
-static struct branch_clk gcc_blsp1_qup5_i2c_apps_clk = {
- .cbcr_reg = BLSP1_QUP5_I2C_APPS_CBCR,
- .parent = &cxo_clk_src.c,
- .has_sibling = 1,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_blsp1_qup5_i2c_apps_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_blsp1_qup5_i2c_apps_clk.c),
- },
-};
-
-static struct branch_clk gcc_blsp1_qup5_spi_apps_clk = {
- .cbcr_reg = BLSP1_QUP5_SPI_APPS_CBCR,
- .parent = &blsp1_qup5_spi_apps_clk_src.c,
- .has_sibling = 0,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_blsp1_qup5_spi_apps_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_blsp1_qup5_spi_apps_clk.c),
- },
-};
-
-static struct branch_clk gcc_blsp1_qup6_i2c_apps_clk = {
- .cbcr_reg = BLSP1_QUP6_I2C_APPS_CBCR,
- .parent = &cxo_clk_src.c,
- .has_sibling = 1,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_blsp1_qup6_i2c_apps_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_blsp1_qup6_i2c_apps_clk.c),
- },
-};
-
-static struct branch_clk gcc_blsp1_qup6_spi_apps_clk = {
- .cbcr_reg = BLSP1_QUP6_SPI_APPS_CBCR,
- .parent = &blsp1_qup6_spi_apps_clk_src.c,
- .has_sibling = 0,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_blsp1_qup6_spi_apps_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_blsp1_qup6_spi_apps_clk.c),
- },
-};
-
-static struct branch_clk gcc_blsp1_uart1_apps_clk = {
- .cbcr_reg = BLSP1_UART1_APPS_CBCR,
- .parent = &blsp1_uart1_apps_clk_src.c,
- .has_sibling = 0,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_blsp1_uart1_apps_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_blsp1_uart1_apps_clk.c),
- },
-};
-
-static struct branch_clk gcc_blsp1_uart2_apps_clk = {
- .cbcr_reg = BLSP1_UART2_APPS_CBCR,
- .parent = &blsp1_uart2_apps_clk_src.c,
- .has_sibling = 0,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_blsp1_uart2_apps_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_blsp1_uart2_apps_clk.c),
- },
-};
-
-static struct branch_clk gcc_blsp1_uart3_apps_clk = {
- .cbcr_reg = BLSP1_UART3_APPS_CBCR,
- .parent = &blsp1_uart3_apps_clk_src.c,
- .has_sibling = 0,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_blsp1_uart3_apps_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_blsp1_uart3_apps_clk.c),
- },
-};
-
-static struct branch_clk gcc_blsp1_uart4_apps_clk = {
- .cbcr_reg = BLSP1_UART4_APPS_CBCR,
- .parent = &blsp1_uart4_apps_clk_src.c,
- .has_sibling = 0,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_blsp1_uart4_apps_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_blsp1_uart4_apps_clk.c),
- },
-};
-
-static struct branch_clk gcc_blsp1_uart5_apps_clk = {
- .cbcr_reg = BLSP1_UART5_APPS_CBCR,
- .parent = &blsp1_uart5_apps_clk_src.c,
- .has_sibling = 0,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_blsp1_uart5_apps_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_blsp1_uart5_apps_clk.c),
- },
-};
-
-static struct branch_clk gcc_blsp1_uart6_apps_clk = {
- .cbcr_reg = BLSP1_UART6_APPS_CBCR,
- .parent = &blsp1_uart6_apps_clk_src.c,
- .has_sibling = 0,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_blsp1_uart6_apps_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_blsp1_uart6_apps_clk.c),
- },
-};
-
-static struct local_vote_clk gcc_boot_rom_ahb_clk = {
- .cbcr_reg = BOOT_ROM_AHB_CBCR,
- .vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
- .en_mask = BIT(10),
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_boot_rom_ahb_clk",
- .ops = &clk_ops_vote,
- CLK_INIT(gcc_boot_rom_ahb_clk.c),
- },
-};
-
-static struct local_vote_clk gcc_ce1_ahb_clk = {
- .cbcr_reg = CE1_AHB_CBCR,
- .vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
- .en_mask = BIT(3),
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_ce1_ahb_clk",
- .ops = &clk_ops_vote,
- CLK_INIT(gcc_ce1_ahb_clk.c),
- },
-};
-
-static struct local_vote_clk gcc_ce1_axi_clk = {
- .cbcr_reg = CE1_AXI_CBCR,
- .vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
- .en_mask = BIT(4),
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_ce1_axi_clk",
- .ops = &clk_ops_vote,
- CLK_INIT(gcc_ce1_axi_clk.c),
- },
-};
-
-static struct local_vote_clk gcc_ce1_clk = {
- .cbcr_reg = CE1_CBCR,
- .vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
- .en_mask = BIT(5),
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_ce1_clk",
- .ops = &clk_ops_vote,
- CLK_INIT(gcc_ce1_clk.c),
- },
-};
-
-static struct branch_clk gcc_gp1_clk = {
- .cbcr_reg = GP1_CBCR,
- .parent = &gp1_clk_src.c,
- .has_sibling = 0,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_gp1_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_gp1_clk.c),
- },
-};
-
-static struct branch_clk gcc_gp2_clk = {
- .cbcr_reg = GP2_CBCR,
- .parent = &gp2_clk_src.c,
- .has_sibling = 0,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_gp2_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_gp2_clk.c),
- },
-};
-
-static struct branch_clk gcc_gp3_clk = {
- .cbcr_reg = GP3_CBCR,
- .parent = &gp3_clk_src.c,
- .has_sibling = 0,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_gp3_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_gp3_clk.c),
- },
-};
-
-static struct branch_clk gcc_ipa_clk = {
- .cbcr_reg = IPA_CBCR,
- .parent = &ipa_clk_src.c,
- .has_sibling = 1,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_ipa_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_ipa_clk.c),
- },
-};
-
-static struct branch_clk gcc_ipa_cnoc_clk = {
- .cbcr_reg = IPA_CNOC_CBCR,
- .has_sibling = 1,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_ipa_cnoc_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_ipa_cnoc_clk.c),
- },
-};
-
-static struct branch_clk gcc_pdm2_clk = {
- .cbcr_reg = PDM2_CBCR,
- .parent = &pdm2_clk_src.c,
- .has_sibling = 0,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_pdm2_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_pdm2_clk.c),
- },
-};
-
-static struct branch_clk gcc_pdm_ahb_clk = {
- .cbcr_reg = PDM_AHB_CBCR,
- .has_sibling = 1,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_pdm_ahb_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_pdm_ahb_clk.c),
- },
-};
-
-static struct local_vote_clk gcc_prng_ahb_clk = {
- .cbcr_reg = PRNG_AHB_CBCR,
- .vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
- .en_mask = BIT(13),
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_prng_ahb_clk",
- .ops = &clk_ops_vote,
- CLK_INIT(gcc_prng_ahb_clk.c),
- },
-};
-
-static struct branch_clk gcc_qpic_ahb_clk = {
- .cbcr_reg = QPIC_AHB_CBCR,
- .has_sibling = 1,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_qpic_ahb_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_qpic_ahb_clk.c),
- },
-};
-
-static struct branch_clk gcc_qpic_clk = {
- .cbcr_reg = QPIC_CBCR,
- .parent = &qpic_clk_src.c,
- .has_sibling = 0,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_qpic_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_qpic_clk.c),
- },
-};
-
-static struct branch_clk gcc_sdcc2_ahb_clk = {
- .cbcr_reg = SDCC2_AHB_CBCR,
- .has_sibling = 1,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_sdcc2_ahb_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_sdcc2_ahb_clk.c),
- },
-};
-
-static struct branch_clk gcc_sdcc2_apps_clk = {
- .cbcr_reg = SDCC2_APPS_CBCR,
- .parent = &sdcc2_apps_clk_src.c,
- .has_sibling = 0,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_sdcc2_apps_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_sdcc2_apps_clk.c),
- },
-};
-
-static struct branch_clk gcc_sdcc3_ahb_clk = {
- .cbcr_reg = SDCC3_AHB_CBCR,
- .has_sibling = 1,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_sdcc3_ahb_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_sdcc3_ahb_clk.c),
- },
-};
-
-static struct branch_clk gcc_sdcc3_apps_clk = {
- .cbcr_reg = SDCC3_APPS_CBCR,
- .parent = &sdcc3_apps_clk_src.c,
- .has_sibling = 0,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_sdcc3_apps_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_sdcc3_apps_clk.c),
- },
-};
-
-static struct branch_clk gcc_sys_noc_ipa_axi_clk = {
- .cbcr_reg = SYS_NOC_IPA_AXI_CBCR,
- .parent = &ipa_clk_src.c,
- .has_sibling = 1,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_sys_noc_ipa_axi_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_sys_noc_ipa_axi_clk.c),
- },
-};
-
-static struct branch_clk gcc_usb_hs_ahb_clk = {
- .cbcr_reg = USB_HS_AHB_CBCR,
- .has_sibling = 1,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_usb_hs_ahb_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_usb_hs_ahb_clk.c),
- },
-};
-
-static struct branch_clk gcc_usb_hs_system_clk = {
- .cbcr_reg = USB_HS_SYSTEM_CBCR,
- .bcr_reg = USB_HS_BCR,
- .parent = &usb_hs_system_clk_src.c,
- .has_sibling = 0,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_usb_hs_system_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_usb_hs_system_clk.c),
- },
-};
-
-static struct branch_clk gcc_usb_hsic_ahb_clk = {
- .cbcr_reg = USB_HSIC_AHB_CBCR,
- .has_sibling = 1,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_usb_hsic_ahb_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_usb_hsic_ahb_clk.c),
- },
-};
-
-static struct branch_clk gcc_usb_hsic_clk = {
- .cbcr_reg = USB_HSIC_CBCR,
- .parent = &usb_hsic_clk_src.c,
- .has_sibling = 0,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_usb_hsic_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_usb_hsic_clk.c),
- },
-};
-
-static struct branch_clk gcc_usb_hsic_io_cal_clk = {
- .cbcr_reg = USB_HSIC_IO_CAL_CBCR,
- .parent = &usb_hsic_io_cal_clk_src.c,
- .has_sibling = 0,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_usb_hsic_io_cal_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_usb_hsic_io_cal_clk.c),
- },
-};
-
-static struct branch_clk gcc_usb_hsic_system_clk = {
- .cbcr_reg = USB_HSIC_SYSTEM_CBCR,
- .bcr_reg = USB_HS_HSIC_BCR,
- .parent = &usb_hsic_system_clk_src.c,
- .has_sibling = 0,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_usb_hsic_system_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_usb_hsic_system_clk.c),
- },
-};
-
-static struct branch_clk gcc_usb_hsic_xcvr_fs_clk = {
- .cbcr_reg = USB_HSIC_XCVR_FS_CBCR,
- .parent = &usb_hsic_xcvr_fs_clk_src.c,
- .has_sibling = 0,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_usb_hsic_xcvr_fs_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_usb_hsic_xcvr_fs_clk.c),
- },
-};
-
-/* LPASS clock data */
-static struct clk_freq_tbl ftbl_audio_core_lpaif_clock[] = {
- F_LPASS( 512000, lpapll0, 16, 1, 48),
- F_LPASS( 768000, lpapll0, 16, 1, 32),
- F_LPASS( 1024000, lpapll0, 16, 1, 24),
- F_LPASS( 1536000, lpapll0, 16, 1, 16),
- F_LPASS( 2048000, lpapll0, 16, 1, 12),
- F_LPASS( 3072000, lpapll0, 16, 1, 8),
- F_LPASS( 4096000, lpapll0, 16, 1, 6),
- F_LPASS( 6144000, lpapll0, 16, 1, 4),
- F_LPASS( 8192000, lpapll0, 16, 1, 3),
- F_LPASS(12288000, lpapll0, 16, 1, 2),
- F_END
-};
-
-static struct rcg_clk audio_core_lpaif_pcmoe_clk_src = {
- .cmd_rcgr_reg = LPAIF_PCMOE_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_audio_core_lpaif_clock,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_lpaif_pcmoe_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP1(LOW, 12290000),
- CLK_INIT(audio_core_lpaif_pcmoe_clk_src.c)
- },
-};
-
-static struct rcg_clk audio_core_lpaif_pri_clk_src = {
- .cmd_rcgr_reg = LPAIF_PRI_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_audio_core_lpaif_clock,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_lpaif_pri_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 9220000, NOMINAL, 18440000),
- CLK_INIT(audio_core_lpaif_pri_clk_src.c)
- },
-};
-
-static struct rcg_clk audio_core_lpaif_sec_clk_src = {
- .cmd_rcgr_reg = LPAIF_SEC_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_audio_core_lpaif_clock,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_lpaif_sec_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 6140000, NOMINAL, 12290000),
- CLK_INIT(audio_core_lpaif_sec_clk_src.c)
- },
-};
-
-static struct clk_freq_tbl ftbl_audio_core_slimbus_core_clock[] = {
- F_LPASS(26041000, lpapll0, 1, 10, 151),
- F_END
-};
-
-static struct rcg_clk audio_core_slimbus_core_clk_src = {
- .cmd_rcgr_reg = SLIMBUS_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_audio_core_slimbus_core_clock,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_slimbus_core_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 13110000, NOMINAL, 26210000),
- CLK_INIT(audio_core_slimbus_core_clk_src.c)
- },
-};
-
-static struct rcg_clk audio_core_lpaif_pcm0_clk_src = {
- .cmd_rcgr_reg = LPAIF_PCM0_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_audio_core_lpaif_clock,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_lpaif_pcm0_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 4100000, NOMINAL, 8190000),
- CLK_INIT(audio_core_lpaif_pcm0_clk_src.c)
- },
-};
-
-static struct rcg_clk audio_core_lpaif_pcm1_clk_src = {
- .cmd_rcgr_reg = LPAIF_PCM1_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_audio_core_lpaif_clock,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_lpaif_pcm1_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 4100000, NOMINAL, 8190000),
- CLK_INIT(audio_core_lpaif_pcm1_clk_src.c)
- },
-};
-
-static struct branch_clk audio_core_slimbus_lfabif_clk = {
- .cbcr_reg = AUDIO_CORE_SLIMBUS_LFABIF_CBCR,
- .has_sibling = 1,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_slimbus_lfabif_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_slimbus_lfabif_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_pcm_data_oe_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_PCM_DATA_OE_CBCR,
- .parent = &audio_core_lpaif_pcmoe_clk_src.c,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_lpaif_pcm_data_oe_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_pcm_data_oe_clk.c),
- },
-};
-
-static struct branch_clk audio_core_slimbus_core_clk = {
- .cbcr_reg = AUDIO_CORE_SLIMBUS_CORE_CBCR,
- .parent = &audio_core_slimbus_core_clk_src.c,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_slimbus_core_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_slimbus_core_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_pri_ebit_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_PRI_EBIT_CBCR,
- .has_sibling = 0,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_lpaif_pri_ebit_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_pri_ebit_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_pri_ibit_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_PRI_IBIT_CBCR,
- .parent = &audio_core_lpaif_pri_clk_src.c,
- .has_sibling = 1,
- .max_div = 15,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_lpaif_pri_ibit_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_pri_ibit_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_pri_osr_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_PRI_OSR_CBCR,
- .parent = &audio_core_lpaif_pri_clk_src.c,
- .has_sibling = 1,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_lpaif_pri_osr_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_pri_osr_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_pcm0_ebit_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_PCM0_EBIT_CBCR,
- .has_sibling = 0,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_lpaif_pcm0_ebit_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_pcm0_ebit_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_pcm0_ibit_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_PCM0_IBIT_CBCR,
- .parent = &audio_core_lpaif_pcm0_clk_src.c,
- .has_sibling = 0,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_lpaif_pcm0_ibit_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_pcm0_ibit_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_sec_ebit_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_SEC_EBIT_CBCR,
- .has_sibling = 0,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_lpaif_sec_ebit_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_sec_ebit_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_sec_ibit_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_SEC_IBIT_CBCR,
- .parent = &audio_core_lpaif_sec_clk_src.c,
- .has_sibling = 1,
- .max_div = 15,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_lpaif_sec_ibit_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_sec_ibit_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_sec_osr_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_SEC_OSR_CBCR,
- .parent = &audio_core_lpaif_sec_clk_src.c,
- .has_sibling = 1,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_lpaif_sec_osr_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_sec_osr_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_pcm1_ebit_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_PCM1_EBIT_CBCR,
- .has_sibling = 0,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_lpaif_pcm1_ebit_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_pcm1_ebit_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_pcm1_ibit_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_PCM1_IBIT_CBCR,
- .parent = &audio_core_lpaif_pcm1_clk_src.c,
- .has_sibling = 0,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_lpaif_pcm1_ibit_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_pcm1_ibit_clk.c),
- },
-};
-
-static DEFINE_CLK_MEASURE(a5_m_clk);
-
-#ifdef CONFIG_DEBUG_FS
-
-struct measure_mux_entry {
- struct clk *c;
- int base;
- u32 debug_mux;
-};
-
-struct measure_mux_entry measure_mux[] = {
- {&gcc_pdm_ahb_clk.c, GCC_BASE, 0x00d0},
- {&gcc_usb_hsic_xcvr_fs_clk.c, GCC_BASE, 0x005d},
- {&gcc_usb_hsic_system_clk.c, GCC_BASE, 0x0059},
- {&gcc_usb_hsic_io_cal_clk.c, GCC_BASE, 0x005b},
- {&gcc_sdcc3_ahb_clk.c, GCC_BASE, 0x0079},
- {&gcc_blsp1_qup5_i2c_apps_clk.c, GCC_BASE, 0x009d},
- {&gcc_blsp1_qup1_spi_apps_clk.c, GCC_BASE, 0x008a},
- {&gcc_blsp1_uart2_apps_clk.c, GCC_BASE, 0x0091},
- {&gcc_blsp1_qup4_spi_apps_clk.c, GCC_BASE, 0x0098},
- {&gcc_blsp1_qup3_spi_apps_clk.c, GCC_BASE, 0x0093},
- {&gcc_blsp1_qup6_i2c_apps_clk.c, GCC_BASE, 0x00a2},
- {&gcc_bam_dma_ahb_clk.c, GCC_BASE, 0x00e0},
- {&gcc_sdcc3_apps_clk.c, GCC_BASE, 0x0078},
- {&gcc_usb_hs_system_clk.c, GCC_BASE, 0x0060},
- {&gcc_blsp1_ahb_clk.c, GCC_BASE, 0x0088},
- {&gcc_blsp1_uart4_apps_clk.c, GCC_BASE, 0x009a},
- {&gcc_blsp1_qup2_spi_apps_clk.c, GCC_BASE, 0x008e},
- {&gcc_usb_hsic_ahb_clk.c, GCC_BASE, 0x0058},
- {&gcc_blsp1_uart3_apps_clk.c, GCC_BASE, 0x0095},
- {&gcc_ce1_axi_clk.c, GCC_BASE, 0x0139},
- {&gcc_blsp1_qup5_spi_apps_clk.c, GCC_BASE, 0x009c},
- {&gcc_usb_hs_ahb_clk.c, GCC_BASE, 0x0061},
- {&gcc_blsp1_qup6_spi_apps_clk.c, GCC_BASE, 0x00a1},
- {&gcc_prng_ahb_clk.c, GCC_BASE, 0x00d8},
- {&gcc_blsp1_qup3_i2c_apps_clk.c, GCC_BASE, 0x0094},
- {&gcc_usb_hsic_clk.c, GCC_BASE, 0x005a},
- {&gcc_blsp1_uart6_apps_clk.c, GCC_BASE, 0x00a3},
- {&gcc_sdcc2_apps_clk.c, GCC_BASE, 0x0070},
- {&gcc_blsp1_uart1_apps_clk.c, GCC_BASE, 0x008c},
- {&gcc_blsp1_qup4_i2c_apps_clk.c, GCC_BASE, 0x0099},
- {&gcc_boot_rom_ahb_clk.c, GCC_BASE, 0x00f8},
- {&gcc_ce1_ahb_clk.c, GCC_BASE, 0x013a},
- {&gcc_pdm2_clk.c, GCC_BASE, 0x00d2},
- {&gcc_blsp1_uart5_apps_clk.c, GCC_BASE, 0x009e},
- {&gcc_blsp1_qup2_i2c_apps_clk.c, GCC_BASE, 0x0090},
- {&gcc_blsp1_qup1_i2c_apps_clk.c, GCC_BASE, 0x008b},
- {&gcc_sdcc2_ahb_clk.c, GCC_BASE, 0x0071},
- {&gcc_ce1_clk.c, GCC_BASE, 0x0138},
- {&gcc_sys_noc_ipa_axi_clk.c, GCC_BASE, 0x0007},
-
- {&audio_core_lpaif_pcm_data_oe_clk.c, LPASS_BASE, 0x0030},
- {&audio_core_slimbus_core_clk.c, LPASS_BASE, 0x003d},
- {&audio_core_lpaif_pri_clk_src.c, LPASS_BASE, 0x0017},
- {&audio_core_lpaif_sec_clk_src.c, LPASS_BASE, 0x0016},
- {&audio_core_slimbus_core_clk_src.c, LPASS_BASE, 0x0011},
- {&audio_core_lpaif_pcm1_clk_src.c, LPASS_BASE, 0x0012},
- {&audio_core_lpaif_pcm0_clk_src.c, LPASS_BASE, 0x0013},
- {&audio_core_lpaif_pcmoe_clk_src.c, LPASS_BASE, 0x000f},
- {&audio_core_slimbus_lfabif_clk.c, LPASS_BASE, 0x003e},
-
- {&a5_m_clk, APCS_BASE, 0x3},
-
- {&dummy_clk, N_BASES, 0x0000},
-};
-
-static int measure_clk_set_parent(struct clk *c, struct clk *parent)
-{
- struct measure_clk *clk = to_measure_clk(c);
- unsigned long flags;
- u32 regval, clk_sel, i;
-
- if (!parent)
- return -EINVAL;
-
- for (i = 0; i < (ARRAY_SIZE(measure_mux) - 1); i++)
- if (measure_mux[i].c == parent)
- break;
-
- if (measure_mux[i].c == &dummy_clk)
- return -EINVAL;
-
- spin_lock_irqsave(&local_clock_reg_lock, flags);
- /*
- * Program the test vector, measurement period (sample_ticks)
- * and scaling multiplier.
- */
- clk->sample_ticks = 0x10000;
- clk->multiplier = 1;
-
- writel_relaxed(0, LPASS_REG_BASE(LPASS_DEBUG_CLK_CTL_REG));
- writel_relaxed(0, GCC_REG_BASE(GCC_DEBUG_CLK_CTL_REG));
-
- switch (measure_mux[i].base) {
-
- case GCC_BASE:
- clk_sel = measure_mux[i].debug_mux;
- break;
-
- case LPASS_BASE:
- clk_sel = 0x161;
- regval = BVAL(15, 0, measure_mux[i].debug_mux);
- writel_relaxed(regval, LPASS_REG_BASE(LPASS_DEBUG_CLK_CTL_REG));
-
- /* Activate debug clock output */
- regval |= BIT(20);
- writel_relaxed(regval, LPASS_REG_BASE(LPASS_DEBUG_CLK_CTL_REG));
- break;
-
- case APCS_BASE:
- clk_sel = 0x16A;
- regval = BVAL(5, 3, measure_mux[i].debug_mux);
- writel_relaxed(regval, APCS_REG_BASE(APCS_CLK_DIAG_REG));
-
- /* Activate debug clock output */
- regval |= BIT(7);
- writel_relaxed(regval, APCS_REG_BASE(APCS_CLK_DIAG_REG));
- break;
-
- default:
- return -EINVAL;
- }
-
- /* Set debug mux clock index */
- regval = BVAL(8, 0, clk_sel);
- writel_relaxed(regval, GCC_REG_BASE(GCC_DEBUG_CLK_CTL_REG));
-
- /* Activate debug clock output */
- regval |= BIT(16);
- writel_relaxed(regval, GCC_REG_BASE(GCC_DEBUG_CLK_CTL_REG));
-
- /* Make sure test vector is set before starting measurements. */
- mb();
- spin_unlock_irqrestore(&local_clock_reg_lock, flags);
-
- return 0;
-}
-
-/* Sample clock for 'ticks' reference clock ticks. */
-static u32 run_measurement(unsigned ticks)
-{
- /* Stop counters and set the XO4 counter start value. */
- writel_relaxed(ticks, GCC_REG_BASE(CLOCK_FRQ_MEASURE_CTL_REG));
-
- /* Wait for timer to become ready. */
- while ((readl_relaxed(GCC_REG_BASE(CLOCK_FRQ_MEASURE_STATUS_REG)) &
- BIT(25)) != 0)
- cpu_relax();
-
- /* Run measurement and wait for completion. */
- writel_relaxed(BIT(20)|ticks, GCC_REG_BASE(CLOCK_FRQ_MEASURE_CTL_REG));
- while ((readl_relaxed(GCC_REG_BASE(CLOCK_FRQ_MEASURE_STATUS_REG)) &
- BIT(25)) == 0)
- cpu_relax();
-
- /* Return measured ticks. */
- return readl_relaxed(GCC_REG_BASE(CLOCK_FRQ_MEASURE_STATUS_REG)) &
- BM(24, 0);
-}
-
-/*
- * Perform a hardware rate measurement for a given clock.
- * FOR DEBUG USE ONLY: Measurements take ~15 ms!
- */
-static unsigned long measure_clk_get_rate(struct clk *c)
-{
- unsigned long flags;
- u32 gcc_xo4_reg_backup;
- u64 raw_count_short, raw_count_full;
- struct measure_clk *clk = to_measure_clk(c);
- unsigned ret;
-
- ret = clk_prepare_enable(&cxo_clk_src.c);
- if (ret) {
- pr_warning("CXO clock failed to enable. Can't measure\n");
- return 0;
- }
-
- spin_lock_irqsave(&local_clock_reg_lock, flags);
-
- /* Enable CXO/4 and RINGOSC branch. */
- gcc_xo4_reg_backup = readl_relaxed(GCC_REG_BASE(GCC_XO_DIV4_CBCR_REG));
- writel_relaxed(0x1, GCC_REG_BASE(GCC_XO_DIV4_CBCR_REG));
-
- /*
- * The ring oscillator counter will not reset if the measured clock
- * is not running. To detect this, run a short measurement before
- * the full measurement. If the raw results of the two are the same
- * then the clock must be off.
- */
-
- /* Run a short measurement. (~1 ms) */
- raw_count_short = run_measurement(0x1000);
- /* Run a full measurement. (~14 ms) */
- raw_count_full = run_measurement(clk->sample_ticks);
-
- writel_relaxed(gcc_xo4_reg_backup, GCC_REG_BASE(GCC_XO_DIV4_CBCR_REG));
-
- /* Return 0 if the clock is off. */
- if (raw_count_full == raw_count_short) {
- ret = 0;
- } else {
- /* Compute rate in Hz. */
- raw_count_full = ((raw_count_full * 10) + 15) * 4800000;
- do_div(raw_count_full, ((clk->sample_ticks * 10) + 35));
- ret = (raw_count_full * clk->multiplier);
- }
- /*TODO: Confirm this is value is correct */
- writel_relaxed(0x51A00, GCC_REG_BASE(GCC_PLLTEST_PAD_CFG_REG));
- spin_unlock_irqrestore(&local_clock_reg_lock, flags);
-
- clk_disable_unprepare(&cxo_clk_src.c);
-
- return ret;
-}
-#else /* !CONFIG_DEBUG_FS */
-static int measure_clk_set_parent(struct clk *clk, struct clk *parent)
-{
- return -EINVAL;
-}
-
-static unsigned long measure_clk_get_rate(struct clk *clk)
-{
- return 0;
-}
-#endif /* CONFIG_DEBUG_FS */
-
-static struct clk_ops clk_ops_measure = {
- .set_parent = measure_clk_set_parent,
- .get_rate = measure_clk_get_rate,
-};
-
-static struct measure_clk measure_clk = {
- .c = {
- .dbg_name = "measure_clk",
- .ops = &clk_ops_measure,
- CLK_INIT(measure_clk.c),
- },
- .multiplier = 1,
-};
-
-static struct clk_lookup msm_clocks_9625[] = {
- CLK_LOOKUP("xo", cxo_clk_src.c, ""),
- CLK_LOOKUP("measure", measure_clk.c, "debug"),
-
- CLK_LOOKUP("pll0", gpll0_clk_src.c, "f9010000.qcom,acpuclk"),
- CLK_LOOKUP("pll14", apcspll_clk_src.c, "f9010000.qcom,acpuclk"),
-
- CLK_LOOKUP("dma_bam_pclk", gcc_bam_dma_ahb_clk.c, ""),
- CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, "msm_serial_hsl.0"),
- CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, "spi_qsd.1"),
- CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, "f9966000.i2c"),
- CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, ""),
- CLK_LOOKUP("core_clk", gcc_blsp1_qup1_i2c_apps_clk.c, ""),
- CLK_LOOKUP("core_clk", gcc_blsp1_qup1_spi_apps_clk.c, "spi_qsd.1"),
- CLK_LOOKUP("core_clk", gcc_blsp1_qup2_i2c_apps_clk.c, "f9966000.i2c"),
- CLK_LOOKUP("core_clk", gcc_blsp1_qup2_spi_apps_clk.c, ""),
- CLK_LOOKUP("core_clk", gcc_blsp1_qup3_i2c_apps_clk.c, ""),
- CLK_LOOKUP("core_clk", gcc_blsp1_qup3_spi_apps_clk.c, ""),
- CLK_LOOKUP("core_clk", gcc_blsp1_qup4_i2c_apps_clk.c, ""),
- CLK_LOOKUP("core_clk", gcc_blsp1_qup4_spi_apps_clk.c, ""),
- CLK_LOOKUP("core_clk", gcc_blsp1_qup5_i2c_apps_clk.c, ""),
- CLK_LOOKUP("core_clk", gcc_blsp1_qup5_spi_apps_clk.c, ""),
- CLK_LOOKUP("core_clk", gcc_blsp1_qup6_i2c_apps_clk.c, ""),
- CLK_LOOKUP("core_clk", gcc_blsp1_qup6_spi_apps_clk.c, ""),
- CLK_LOOKUP("core_clk", gcc_blsp1_uart1_apps_clk.c, ""),
- CLK_LOOKUP("core_clk", gcc_blsp1_uart2_apps_clk.c, ""),
- CLK_LOOKUP("core_clk", gcc_blsp1_uart3_apps_clk.c, "msm_serial_hsl.0"),
- CLK_LOOKUP("core_clk", gcc_blsp1_uart4_apps_clk.c, ""),
- CLK_LOOKUP("core_clk", gcc_blsp1_uart5_apps_clk.c, ""),
- CLK_LOOKUP("core_clk", gcc_blsp1_uart6_apps_clk.c, ""),
-
- CLK_LOOKUP("core_clk", gcc_ce1_clk.c, ""),
- CLK_LOOKUP("iface_clk", gcc_ce1_ahb_clk.c, ""),
- CLK_LOOKUP("bus_clk", gcc_ce1_axi_clk.c, ""),
-
- CLK_LOOKUP("core_clk", gcc_gp1_clk.c, ""),
- CLK_LOOKUP("core_clk", gcc_gp2_clk.c, ""),
- CLK_LOOKUP("core_clk", gcc_gp3_clk.c, ""),
-
- CLK_LOOKUP("core_src_clk", ipa_clk_src.c, ""),
- CLK_LOOKUP("core_clk", gcc_ipa_clk.c, ""),
- CLK_LOOKUP("bus_clk", gcc_sys_noc_ipa_axi_clk.c, ""),
- CLK_LOOKUP("iface_clk", gcc_ipa_cnoc_clk.c, ""),
-
- CLK_LOOKUP("core_clk", gcc_pdm2_clk.c, ""),
- CLK_LOOKUP("iface_clk", gcc_pdm_ahb_clk.c, ""),
-
- CLK_LOOKUP("core_clk", gcc_qpic_clk.c, ""),
- CLK_LOOKUP("iface_clk", gcc_qpic_ahb_clk.c, ""),
-
- CLK_LOOKUP("iface_clk", gcc_sdcc2_ahb_clk.c, "f98a4000.qcom,sdcc"),
- CLK_LOOKUP("core_clk", gcc_sdcc2_apps_clk.c, "f98a4000.qcom,sdcc"),
- CLK_LOOKUP("bus_clk", pnoc_sdcc2_clk.c, "f98a4000.qcom,sdcc"),
- CLK_LOOKUP("iface_clk", gcc_sdcc3_ahb_clk.c, ""),
- CLK_LOOKUP("core_clk", gcc_sdcc3_apps_clk.c, ""),
- CLK_LOOKUP("bus_clk", pnoc_sdcc3_clk.c, ""),
-
- CLK_LOOKUP("iface_clk", gcc_usb_hs_ahb_clk.c, "f9a55000.usb"),
- CLK_LOOKUP("core_clk", gcc_usb_hs_system_clk.c, "f9a55000.usb"),
- CLK_LOOKUP("iface_clk", gcc_usb_hsic_ahb_clk.c, "f9a15000.hsic"),
- CLK_LOOKUP("phy_clk", gcc_usb_hsic_clk.c, "f9a15000.hsic"),
- CLK_LOOKUP("cal_clk", gcc_usb_hsic_io_cal_clk.c, "f9a15000.hsic"),
- CLK_LOOKUP("core_clk", gcc_usb_hsic_system_clk.c, "f9a15000.hsic"),
- CLK_LOOKUP("alt_core_clk", gcc_usb_hsic_xcvr_fs_clk.c,
- "f9a15000.hsic"),
-
- /* LPASS clocks */
- CLK_LOOKUP("core_clk", audio_core_slimbus_core_clk.c, "fe12f000.slim"),
- CLK_LOOKUP("iface_clk", audio_core_slimbus_lfabif_clk.c, ""),
- CLK_LOOKUP("core_clk", audio_core_lpaif_pri_clk_src.c, ""),
- CLK_LOOKUP("osr_clk", audio_core_lpaif_pri_osr_clk.c, ""),
- CLK_LOOKUP("ebit_clk", audio_core_lpaif_pri_ebit_clk.c, ""),
- CLK_LOOKUP("ibit_clk", audio_core_lpaif_pri_ibit_clk.c, ""),
- CLK_LOOKUP("core_clk", audio_core_lpaif_sec_clk_src.c, ""),
- CLK_LOOKUP("osr_clk", audio_core_lpaif_sec_osr_clk.c, ""),
- CLK_LOOKUP("ebit_clk", audio_core_lpaif_sec_ebit_clk.c, ""),
- CLK_LOOKUP("ibit_clk", audio_core_lpaif_sec_ibit_clk.c, ""),
- CLK_LOOKUP("core_clk", audio_core_lpaif_pcm0_clk_src.c, ""),
- CLK_LOOKUP("ebit_clk", audio_core_lpaif_pcm0_ebit_clk.c, ""),
- CLK_LOOKUP("ibit_clk", audio_core_lpaif_pcm0_ibit_clk.c, ""),
- CLK_LOOKUP("core_clk", audio_core_lpaif_pcm1_clk_src.c, ""),
- CLK_LOOKUP("ebit_clk", audio_core_lpaif_pcm1_ebit_clk.c, ""),
- CLK_LOOKUP("ibit_clk", audio_core_lpaif_pcm1_ibit_clk.c, ""),
- CLK_LOOKUP("core_oe_src_clk", audio_core_lpaif_pcmoe_clk_src.c, ""),
- CLK_LOOKUP("core_oe_clk", audio_core_lpaif_pcm_data_oe_clk.c, ""),
-
- /* RPM and voter clocks */
- CLK_LOOKUP("bus_clk", snoc_clk.c, ""),
- CLK_LOOKUP("bus_clk", pnoc_clk.c, ""),
- CLK_LOOKUP("bus_clk", cnoc_clk.c, ""),
- CLK_LOOKUP("mem_clk", bimc_clk.c, ""),
- CLK_LOOKUP("bus_clk", snoc_a_clk.c, ""),
- CLK_LOOKUP("bus_clk", pnoc_a_clk.c, ""),
- CLK_LOOKUP("bus_clk", cnoc_a_clk.c, ""),
- CLK_LOOKUP("mem_clk", bimc_a_clk.c, ""),
-
- CLK_LOOKUP("bus_clk", cnoc_msmbus_clk.c, ""),
- CLK_LOOKUP("bus_a_clk", cnoc_msmbus_a_clk.c, ""),
- CLK_LOOKUP("bus_clk", snoc_msmbus_clk.c, ""),
- CLK_LOOKUP("bus_a_clk", snoc_msmbus_a_clk.c, ""),
- CLK_LOOKUP("bus_clk", pnoc_msmbus_clk.c, ""),
- CLK_LOOKUP("bus_a_clk", pnoc_msmbus_a_clk.c, ""),
- CLK_LOOKUP("mem_clk", bimc_msmbus_clk.c, ""),
- CLK_LOOKUP("mem_a_clk", bimc_msmbus_a_clk.c, ""),
-
- CLK_LOOKUP("dfab_clk", pnoc_sps_clk.c, "msm_sps"),
-
- CLK_LOOKUP("a5_m_clk", a5_m_clk, ""),
-};
-
-static struct pll_config_regs gpll0_regs __initdata = {
- .l_reg = (void __iomem *)GPLL0_L_REG,
- .m_reg = (void __iomem *)GPLL0_M_REG,
- .n_reg = (void __iomem *)GPLL0_N_REG,
- .config_reg = (void __iomem *)GPLL0_USER_CTL_REG,
- .mode_reg = (void __iomem *)GPLL0_MODE_REG,
- .base = &virt_bases[GCC_BASE],
-};
-
-/* GPLL0 at 600 MHz, main output enabled. */
-static struct pll_config gpll0_config __initdata = {
- .l = 0x1f,
- .m = 0x1,
- .n = 0x4,
- .vco_val = 0x0,
- .vco_mask = BM(21, 20),
- .pre_div_val = 0x0,
- .pre_div_mask = BM(14, 12),
- .post_div_val = 0x0,
- .post_div_mask = BM(9, 8),
- .mn_ena_val = BIT(24),
- .mn_ena_mask = BIT(24),
- .main_output_val = BIT(0),
- .main_output_mask = BIT(0),
-};
-
-static struct pll_config_regs gpll1_regs __initdata = {
- .l_reg = (void __iomem *)GPLL1_L_REG,
- .m_reg = (void __iomem *)GPLL1_M_REG,
- .n_reg = (void __iomem *)GPLL1_N_REG,
- .config_reg = (void __iomem *)GPLL1_USER_CTL_REG,
- .mode_reg = (void __iomem *)GPLL1_MODE_REG,
- .base = &virt_bases[GCC_BASE],
-};
-
-/* GPLL1 at 480 MHz, main output enabled. */
-static struct pll_config gpll1_config __initdata = {
- .l = 0x19,
- .m = 0x0,
- .n = 0x1,
- .vco_val = 0x0,
- .vco_mask = BM(21, 20),
- .pre_div_val = 0x0,
- .pre_div_mask = BM(14, 12),
- .post_div_val = 0x0,
- .post_div_mask = BM(9, 8),
- .main_output_val = BIT(0),
- .main_output_mask = BIT(0),
-};
-
-static struct pll_config_regs lpapll0_regs __initdata = {
- .l_reg = (void __iomem *)LPAPLL_L_REG,
- .m_reg = (void __iomem *)LPAPLL_M_REG,
- .n_reg = (void __iomem *)LPAPLL_N_REG,
- .config_reg = (void __iomem *)LPAPLL_USER_CTL_REG,
- .mode_reg = (void __iomem *)LPAPLL_MODE_REG,
- .base = &virt_bases[LPASS_BASE],
-};
-
-/* LPAPLL0 at 393.216 MHz, main output enabled. */
-static struct pll_config lpapll0_config __initdata = {
- .l = 0x28,
- .m = 0x18,
- .n = 0x19,
- .vco_val = 0x0,
- .vco_mask = BM(21, 20),
- .pre_div_val = 0x0,
- .pre_div_mask = BM(14, 12),
- .post_div_val = BVAL(9, 8, 0x1),
- .post_div_mask = BM(9, 8),
- .mn_ena_val = BIT(24),
- .mn_ena_mask = BIT(24),
- .main_output_val = BIT(0),
- .main_output_mask = BIT(0),
-};
-
-static struct pll_config_regs apcspll_regs __initdata = {
- .l_reg = (void __iomem *)APCS_CPU_PLL_L_REG,
- .m_reg = (void __iomem *)APCS_CPU_PLL_M_REG,
- .n_reg = (void __iomem *)APCS_CPU_PLL_N_REG,
- .config_reg = (void __iomem *)APCS_CPU_PLL_USER_CTL_REG,
- .mode_reg = (void __iomem *)APCS_CPU_PLL_MODE_REG,
- .base = &virt_bases[APCS_PLL_BASE],
-};
-
-/* A5PLL with 998.4MHz */
-static struct pll_config apcspll_config __initdata = {
- .l = 0x34,
- .m = 0x0,
- .n = 0x1,
- .vco_val = 0x0,
- .vco_mask = BM(21, 20),
- .pre_div_val = 0x0,
- .pre_div_mask = BM(14, 12),
- .post_div_val = BVAL(9, 8, 0x0),
- .post_div_mask = BM(9, 8),
- .mn_ena_val = BIT(24),
- .mn_ena_mask = BIT(24),
- .main_output_val = BIT(0),
- .main_output_mask = BIT(0),
-};
-
-#define PLL_AUX_OUTPUT_BIT 1
-#define PLL_AUX2_OUTPUT_BIT 2
-
-static void __init configure_apcs_pll(void)
-{
- u32 regval;
-
- configure_sr_hpm_lp_pll(&apcspll_config, &apcspll_regs, 0);
- writel_relaxed(0x00141200,
- APCS_PLL_REG_BASE(APCS_CPU_PLL_CONFIG_CTL_REG));
- regval = readl_relaxed(APCS_PLL_REG_BASE(APCS_CPU_PLL_USER_CTL_REG));
- regval |= BIT(PLL_AUX_OUTPUT_BIT) | BIT(PLL_AUX2_OUTPUT_BIT);
- writel_relaxed(regval, APCS_PLL_REG_BASE(APCS_CPU_PLL_USER_CTL_REG));
-}
-
-static void __init reg_init(void)
-{
- u32 regval;
-
- if (!(readl_relaxed(GCC_REG_BASE(GPLL0_STATUS_REG))
- & gpll0_clk_src.status_mask))
- configure_sr_hpm_lp_pll(&gpll0_config, &gpll0_regs, 1);
-
- if (!(readl_relaxed(GCC_REG_BASE(GPLL1_STATUS_REG))
- & gpll1_clk_src.status_mask))
- configure_sr_hpm_lp_pll(&gpll1_config, &gpll1_regs, 1);
-
- configure_sr_hpm_lp_pll(&lpapll0_config, &lpapll0_regs, 1);
-
- /* TODO: Remove A5 pll configuration once the bootloader is avaiable */
- regval = readl_relaxed(APCS_PLL_REG_BASE(APCS_CPU_PLL_MODE_REG));
- if ((regval & BM(2, 0)) != 0x7)
- configure_apcs_pll();
-
- /* TODO:
- * 1) do we need to turn on AUX2 output too?
- * 2) if need to vote off all sleep clocks
- */
-
- /* Enable GPLL0's aux outputs. */
- regval = readl_relaxed(GCC_REG_BASE(GPLL0_USER_CTL_REG));
- regval |= BIT(PLL_AUX_OUTPUT_BIT) | BIT(PLL_AUX2_OUTPUT_BIT);
- writel_relaxed(regval, GCC_REG_BASE(GPLL0_USER_CTL_REG));
-
- /* Vote for GPLL0 to turn on. Needed by acpuclock. */
- regval = readl_relaxed(GCC_REG_BASE(APCS_GPLL_ENA_VOTE_REG));
- regval |= BIT(0);
- writel_relaxed(regval, GCC_REG_BASE(APCS_GPLL_ENA_VOTE_REG));
-
- /*
- * TODO: Confirm that no clocks need to be voted on in this sleep vote
- * register.
- */
- writel_relaxed(0x0, GCC_REG_BASE(APCS_CLOCK_SLEEP_ENA_VOTE));
-}
-
-static void __init msm9625_clock_post_init(void)
-{
- /*
- * Hold an active set vote for CXO; this is because CXO is expected
- * to remain on whenever CPUs aren't power collapsed.
- */
- clk_prepare_enable(&cxo_a_clk_src.c);
-
- /* TODO :FIXME */
- clk_prepare_enable(&gcc_qpic_ahb_clk.c);
-
- /* Set rates for single-rate clocks. */
- clk_set_rate(&usb_hs_system_clk_src.c,
- usb_hs_system_clk_src.freq_tbl[0].freq_hz);
- clk_set_rate(&usb_hsic_clk_src.c,
- usb_hsic_clk_src.freq_tbl[0].freq_hz);
- clk_set_rate(&usb_hsic_io_cal_clk_src.c,
- usb_hsic_io_cal_clk_src.freq_tbl[0].freq_hz);
- clk_set_rate(&usb_hsic_system_clk_src.c,
- usb_hsic_system_clk_src.freq_tbl[0].freq_hz);
- clk_set_rate(&usb_hsic_xcvr_fs_clk_src.c,
- usb_hsic_xcvr_fs_clk_src.freq_tbl[0].freq_hz);
- clk_set_rate(&pdm2_clk_src.c, pdm2_clk_src.freq_tbl[0].freq_hz);
- clk_set_rate(&audio_core_slimbus_core_clk_src.c,
- audio_core_slimbus_core_clk_src.freq_tbl[0].freq_hz);
-}
-
-#define GCC_CC_PHYS 0xFC400000
-#define GCC_CC_SIZE SZ_16K
-
-#define LPASS_CC_PHYS 0xFE000000
-#define LPASS_CC_SIZE SZ_256K
-
-#define APCS_GCC_CC_PHYS 0xF9011000
-#define APCS_GCC_CC_SIZE SZ_4K
-
-#define APCS_PLL_PHYS 0xF9008018
-#define APCS_PLL_SIZE 0x18
-
-static void __init msm9625_clock_pre_init(void)
-{
- virt_bases[GCC_BASE] = ioremap(GCC_CC_PHYS, GCC_CC_SIZE);
- if (!virt_bases[GCC_BASE])
- panic("clock-9625: Unable to ioremap GCC memory!");
-
- virt_bases[LPASS_BASE] = ioremap(LPASS_CC_PHYS, LPASS_CC_SIZE);
- if (!virt_bases[LPASS_BASE])
- panic("clock-9625: Unable to ioremap LPASS_CC memory!");
-
- virt_bases[APCS_BASE] = ioremap(APCS_GCC_CC_PHYS, APCS_GCC_CC_SIZE);
- if (!virt_bases[APCS_BASE])
- panic("clock-9625: Unable to ioremap APCS_GCC_CC memory!");
-
- virt_bases[APCS_PLL_BASE] = ioremap(APCS_PLL_PHYS, APCS_PLL_SIZE);
- if (!virt_bases[APCS_PLL_BASE])
- panic("clock-9625: Unable to ioremap APCS_PLL memory!");
-
- clk_ops_local_pll.enable = sr_hpm_lp_pll_clk_enable;
-
- reg_init();
-}
-
-/* TODO: Add vdd level unvote */
-static int __init msm9625_clock_late_init(void)
-{
- return 0;
-}
-
-struct clock_init_data msm9625_clock_init_data __initdata = {
- .table = msm_clocks_9625,
- .size = ARRAY_SIZE(msm_clocks_9625),
- .pre_init = msm9625_clock_pre_init,
- .post_init = msm9625_clock_post_init,
- .late_init = msm9625_clock_late_init,
-};
diff --git a/arch/arm/mach-msm/clock-debug.c b/arch/arm/mach-msm/clock-debug.c
index e942173..8bd4433 100644
--- a/arch/arm/mach-msm/clock-debug.c
+++ b/arch/arm/mach-msm/clock-debug.c
@@ -218,6 +218,28 @@
.release = seq_release,
};
+static int clock_parent_show(struct seq_file *m, void *unused)
+{
+ struct clk *clock = m->private;
+ struct clk *parent = clk_get_parent(clock);
+
+ seq_printf(m, "%s\n", (parent ? parent->dbg_name : "None"));
+
+ return 0;
+}
+
+static int clock_parent_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, clock_parent_show, inode->i_private);
+}
+
+static const struct file_operations clock_parent_fops = {
+ .open = clock_parent_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
static struct dentry *debugfs_base;
static u32 debug_suspend;
@@ -274,6 +296,10 @@
S_IRUGO, clk_dir, clock, &fmax_rates_fops))
goto error;
+ if (!debugfs_create_file("parent", S_IRUGO, clk_dir, clock,
+ &clock_parent_fops))
+ goto error;
+
return 0;
error:
debugfs_remove_recursive(clk_dir);
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index eead627..c30bd79 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -133,6 +133,18 @@
unvote_vdd_level(clk->vdd_class, level);
}
+/* Returns true if the rate is valid without voting for it */
+static bool is_rate_valid(struct clk *clk, unsigned long rate)
+{
+ int level;
+
+ if (!clk->vdd_class)
+ return true;
+
+ level = find_vdd_level(clk, rate);
+ return level >= 0;
+}
+
int clk_prepare(struct clk *clk)
{
int ret = 0;
@@ -331,14 +343,16 @@
/* Enforce vdd requirements for target frequency. */
rc = vote_rate_vdd(clk, rate);
if (rc)
- goto err_vote_vdd;
+ goto out;
rc = clk->ops->set_rate(clk, rate);
if (rc)
goto err_set_rate;
/* Release vdd requirements for starting frequency. */
unvote_rate_vdd(clk, start_rate);
- } else {
+ } else if (is_rate_valid(clk, rate)) {
rc = clk->ops->set_rate(clk, rate);
+ } else {
+ rc = -EINVAL;
}
if (!rc)
@@ -349,7 +363,6 @@
err_set_rate:
unvote_rate_vdd(clk, rate);
-err_vote_vdd:
goto out;
}
EXPORT_SYMBOL(clk_set_rate);
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index 8a75d390..48f897b 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -34,7 +34,6 @@
};
extern struct clock_init_data msm9615_clock_init_data;
-extern struct clock_init_data msm9625_clock_init_data;
extern struct clock_init_data apq8064_clock_init_data;
extern struct clock_init_data fsm9xxx_clock_init_data;
extern struct clock_init_data msm7x01a_clock_init_data;
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index c0461e1..3cd4b2f 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1962,6 +1962,11 @@
.end = 0x10008000 + SZ_256 - 1,
.flags = IORESOURCE_MEM,
},
+ {
+ .start = GSS_A5_WDOG_EXPIRED,
+ .end = GSS_A5_WDOG_EXPIRED,
+ .flags = IORESOURCE_IRQ,
+ },
};
struct platform_device msm_gss = {
@@ -2655,32 +2660,52 @@
};
static struct msm_dcvs_freq_entry apq8064_freq[] = {
- { 384000, 166981, 345600},
- { 702000, 213049, 632502},
- {1026000, 285712, 925613},
- {1242000, 383945, 1176550},
- {1458000, 419729, 1465478},
- {1512000, 434116, 1546674},
-
+ { 384000, 900, 0, 0, 0},
+ { 594000, 950, 0, 0, 0},
+ { 702000, 975, 0, 0, 0},
+ {1026000, 1075, 0, 0, 0},
+ {1242000, 1150, 0, 100, 100},
+ {1458000, 1188, 0, 100, 100},
+ {1512000, 1200, 1, 100, 100},
};
static struct msm_dcvs_core_info apq8064_core_info = {
- .freq_tbl = &apq8064_freq[0],
- .core_param = {
- .max_time_us = 100000,
- .num_freq = ARRAY_SIZE(apq8064_freq),
+ .freq_tbl = &apq8064_freq[0],
+ .num_cores = 4,
+ .sensors = (int[]){7, 8, 9, 10},
+ .core_param = {
+ .core_type = MSM_DCVS_CORE_TYPE_CPU,
},
- .algo_param = {
- .slack_time_us = 58000,
- .scale_slack_time = 0,
- .scale_slack_time_pct = 0,
- .disable_pc_threshold = 1458000,
- .em_window_size = 100000,
- .em_max_util_pct = 97,
- .ss_window_size = 1000000,
- .ss_util_pct = 95,
- .ss_iobusy_conv = 100,
+ .algo_param = {
+ .disable_pc_threshold = 1458000,
+ .em_win_size_min_us = 100000,
+ .em_win_size_max_us = 300000,
+ .em_max_util_pct = 97,
+ .group_id = 1,
+ .max_freq_chg_time_us = 100000,
+ .slack_mode_dynamic = 0,
+ .slack_weight_thresh_pct = 3,
+ .slack_time_min_us = 45000,
+ .slack_time_max_us = 45000,
+ .ss_iobusy_conv = 100,
+ .ss_win_size_min_us = 1000000,
+ .ss_win_size_max_us = 1000000,
+ .ss_util_pct = 95,
},
+ .energy_coeffs = {
+ .active_coeff_a = 336,
+ .active_coeff_b = 0,
+ .active_coeff_c = 0,
+
+ .leakage_coeff_a = -17720,
+ .leakage_coeff_b = 37,
+ .leakage_coeff_c = 3329,
+ .leakage_coeff_d = -277,
+ },
+ .power_param = {
+ .current_temp = 25,
+ .num_freq = ARRAY_SIZE(apq8064_freq),
+ }
};
struct platform_device apq8064_msm_gov_device = {
@@ -2691,6 +2716,23 @@
},
};
+static struct msm_mpd_algo_param apq8064_mpd_algo_param = {
+ .em_win_size_min_us = 10000,
+ .em_win_size_max_us = 100000,
+ .em_max_util_pct = 90,
+ .online_util_pct_min = 60,
+ .slack_time_min_us = 50000,
+ .slack_time_max_us = 100000,
+};
+
+struct platform_device apq8064_msm_mpd_device = {
+ .name = "msm_mpdecision",
+ .id = -1,
+ .dev = {
+ .platform_data = &apq8064_mpd_algo_param,
+ },
+};
+
#ifdef CONFIG_MSM_VCAP
#define VCAP_HW_BASE 0x05900000
diff --git a/arch/arm/mach-msm/devices-8930.c b/arch/arm/mach-msm/devices-8930.c
index f52ee18..d062ff4 100644
--- a/arch/arm/mach-msm/devices-8930.c
+++ b/arch/arm/mach-msm/devices-8930.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -18,7 +18,6 @@
#include <mach/msm_iomap.h>
#include <mach/irqs-8930.h>
#include <mach/rpm.h>
-#include <mach/msm_dcvs.h>
#include <mach/msm_bus.h>
#include <mach/msm_bus_board.h>
#include <mach/board.h>
@@ -594,43 +593,6 @@
},
};
-static struct msm_dcvs_freq_entry msm8930_freq[] = {
- { 384000, 166981, 345600},
- { 702000, 213049, 632502},
- {1026000, 285712, 925613},
- {1242000, 383945, 1176550},
- {1458000, 419729, 1465478},
- {1512000, 434116, 1546674},
-
-};
-
-static struct msm_dcvs_core_info msm8930_core_info = {
- .freq_tbl = &msm8930_freq[0],
- .core_param = {
- .max_time_us = 100000,
- .num_freq = ARRAY_SIZE(msm8930_freq),
- },
- .algo_param = {
- .slack_time_us = 58000,
- .scale_slack_time = 0,
- .scale_slack_time_pct = 0,
- .disable_pc_threshold = 1458000,
- .em_window_size = 100000,
- .em_max_util_pct = 97,
- .ss_window_size = 1000000,
- .ss_util_pct = 95,
- .ss_iobusy_conv = 100,
- },
-};
-
-struct platform_device msm8930_msm_gov_device = {
- .name = "msm_dcvs_gov",
- .id = -1,
- .dev = {
- .platform_data = &msm8930_core_info,
- },
-};
-
struct platform_device msm_bus_8930_sys_fabric = {
.name = "msm_bus_fabric",
.id = MSM_BUS_FAB_SYSTEM,
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 5cbfb5b..72da3d8 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1444,6 +1444,11 @@
.end = 0x03204000 + SZ_256 - 1,
.flags = IORESOURCE_MEM,
},
+ {
+ .start = RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ,
+ .end = RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
};
struct platform_device msm_8960_riva = {
@@ -2935,46 +2940,89 @@
};
static struct msm_dcvs_freq_entry grp3d_freq[] = {
- {0, 0, 333932},
- {0, 0, 497532},
- {0, 0, 707610},
- {0, 0, 844545},
+ {0, 900, 0, 0, 0},
+ {0, 950, 0, 0, 0},
+ {0, 950, 0, 0, 0},
+ {0, 1200, 1, 100, 100},
};
static struct msm_dcvs_freq_entry grp2d_freq[] = {
- {0, 0, 86000},
- {0, 0, 200000},
+ {0, 900, 0, 0, 0},
+ {0, 950, 1, 100, 100},
};
static struct msm_dcvs_core_info grp3d_core_info = {
- .freq_tbl = &grp3d_freq[0],
- .core_param = {
- .max_time_us = 100000,
- .num_freq = ARRAY_SIZE(grp3d_freq),
+ .freq_tbl = &grp3d_freq[0],
+ .core_param = {
+ .core_type = MSM_DCVS_CORE_TYPE_GPU,
},
- .algo_param = {
- .slack_time_us = 39000,
- .disable_pc_threshold = 86000,
- .ss_window_size = 1000000,
- .ss_util_pct = 95,
- .em_max_util_pct = 97,
- .ss_iobusy_conv = 100,
+ .algo_param = {
+ .disable_pc_threshold = 0,
+ .em_win_size_min_us = 100000,
+ .em_win_size_max_us = 300000,
+ .em_max_util_pct = 97,
+ .group_id = 0,
+ .max_freq_chg_time_us = 100000,
+ .slack_mode_dynamic = 0,
+ .slack_weight_thresh_pct = 0,
+ .slack_time_min_us = 39000,
+ .slack_time_max_us = 39000,
+ .ss_win_size_min_us = 1000000,
+ .ss_win_size_max_us = 1000000,
+ .ss_util_pct = 95,
+ .ss_iobusy_conv = 100,
},
+ .energy_coeffs = {
+ .active_coeff_a = 2492,
+ .active_coeff_b = 0,
+ .active_coeff_c = 0,
+
+ .leakage_coeff_a = -17720,
+ .leakage_coeff_b = 37,
+ .leakage_coeff_c = 2729,
+ .leakage_coeff_d = -277,
+ },
+ .power_param = {
+ .current_temp = 25,
+ .num_freq = ARRAY_SIZE(grp3d_freq),
+ }
};
static struct msm_dcvs_core_info grp2d_core_info = {
- .freq_tbl = &grp2d_freq[0],
- .core_param = {
- .max_time_us = 100000,
- .num_freq = ARRAY_SIZE(grp2d_freq),
+ .freq_tbl = &grp2d_freq[0],
+ .core_param = {
+ .core_type = MSM_DCVS_CORE_TYPE_GPU,
},
- .algo_param = {
- .slack_time_us = 39000,
- .disable_pc_threshold = 90000,
- .ss_window_size = 1000000,
- .ss_util_pct = 90,
- .em_max_util_pct = 95,
+ .algo_param = {
+ .disable_pc_threshold = 0,
+ .em_win_size_min_us = 100000,
+ .em_win_size_max_us = 300000,
+ .em_max_util_pct = 97,
+ .group_id = 0,
+ .max_freq_chg_time_us = 100000,
+ .slack_mode_dynamic = 0,
+ .slack_weight_thresh_pct = 0,
+ .slack_time_min_us = 39000,
+ .slack_time_max_us = 39000,
+ .ss_win_size_min_us = 1000000,
+ .ss_win_size_max_us = 1000000,
+ .ss_util_pct = 95,
+ .ss_iobusy_conv = 100,
},
+ .energy_coeffs = {
+ .active_coeff_a = 2492,
+ .active_coeff_b = 0,
+ .active_coeff_c = 0,
+
+ .leakage_coeff_a = -17720,
+ .leakage_coeff_b = 37,
+ .leakage_coeff_c = 2729,
+ .leakage_coeff_d = -277,
+ },
+ .power_param = {
+ .current_temp = 25,
+ .num_freq = ARRAY_SIZE(grp2d_freq),
+ }
};
#ifdef CONFIG_MSM_BUS_SCALING
@@ -4033,43 +4081,6 @@
},
};
-static struct msm_dcvs_freq_entry msm8960_freq[] = {
- { 384000, 166981, 345600},
- { 702000, 213049, 632502},
- {1026000, 285712, 925613},
- {1242000, 383945, 1176550},
- {1458000, 419729, 1465478},
- {1512000, 434116, 1546674},
-
-};
-
-static struct msm_dcvs_core_info msm8960_core_info = {
- .freq_tbl = &msm8960_freq[0],
- .core_param = {
- .max_time_us = 100000,
- .num_freq = ARRAY_SIZE(msm8960_freq),
- },
- .algo_param = {
- .slack_time_us = 58000,
- .scale_slack_time = 0,
- .scale_slack_time_pct = 0,
- .disable_pc_threshold = 1458000,
- .em_window_size = 100000,
- .em_max_util_pct = 97,
- .ss_window_size = 1000000,
- .ss_util_pct = 95,
- .ss_iobusy_conv = 100,
- },
-};
-
-struct platform_device msm8960_msm_gov_device = {
- .name = "msm_dcvs_gov",
- .id = -1,
- .dev = {
- .platform_data = &msm8960_core_info,
- },
-};
-
static struct resource msm_cache_erp_resources[] = {
{
.name = "l1_irq",
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index 0a9bbf6..46853ac 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -1316,8 +1316,8 @@
};
static struct msm_rpmstats_platform_data msm_rpm_stat_pdata = {
- .phys_addr_base = 0x0010D204,
- .phys_size = SZ_8K,
+ .phys_addr_base = 0x0010DD04,
+ .phys_size = SZ_256,
};
struct platform_device msm9615_rpm_stat_device = {
diff --git a/arch/arm/mach-msm/devices-iommu.c b/arch/arm/mach-msm/devices-iommu.c
index acf577e..6434a63 100644
--- a/arch/arm/mach-msm/devices-iommu.c
+++ b/arch/arm/mach-msm/devices-iommu.c
@@ -1017,13 +1017,13 @@
ARRAY_SIZE(msm_iommu_gfx2d_devs));
}
- if (cpu_is_apq8064() || cpu_is_msm8960ab()) {
+ if (cpu_is_apq8064() || cpu_is_msm8960ab() || cpu_is_apq8064ab()) {
platform_add_devices(msm_iommu_jpegd_devs,
ARRAY_SIZE(msm_iommu_jpegd_devs));
platform_add_devices(msm_iommu_adreno3xx_gfx_devs,
ARRAY_SIZE(msm_iommu_adreno3xx_gfx_devs));
}
- if (cpu_is_apq8064())
+ if (cpu_is_apq8064() || cpu_is_apq8064ab())
platform_add_devices(msm_iommu_vcap_devs,
ARRAY_SIZE(msm_iommu_vcap_devs));
@@ -1039,14 +1039,14 @@
ARRAY_SIZE(msm_iommu_gfx2d_ctx_devs));
}
- if (cpu_is_apq8064() || cpu_is_msm8960ab()) {
+ if (cpu_is_apq8064() || cpu_is_msm8960ab() || cpu_is_apq8064ab()) {
platform_add_devices(msm_iommu_jpegd_ctx_devs,
ARRAY_SIZE(msm_iommu_jpegd_ctx_devs));
platform_add_devices(msm_iommu_adreno3xx_ctx_devs,
ARRAY_SIZE(msm_iommu_adreno3xx_ctx_devs));
}
- if (cpu_is_apq8064())
+ if (cpu_is_apq8064() || cpu_is_apq8064ab())
platform_add_devices(msm_iommu_vcap_ctx_devs,
ARRAY_SIZE(msm_iommu_vcap_ctx_devs));
@@ -1081,12 +1081,12 @@
for (i = 0; i < ARRAY_SIZE(msm_iommu_jpegd_devs); i++)
platform_device_unregister(msm_iommu_jpegd_devs[i]);
}
- if (cpu_is_apq8064()) {
+ if (cpu_is_apq8064() || cpu_is_apq8064ab()) {
for (i = 0; i < ARRAY_SIZE(msm_iommu_vcap_ctx_devs); i++)
platform_device_unregister(msm_iommu_vcap_ctx_devs[i]);
}
- if (cpu_is_apq8064() || cpu_is_msm8960ab()) {
+ if (cpu_is_apq8064() || cpu_is_msm8960ab() || cpu_is_apq8064ab()) {
for (i = 0; i < ARRAY_SIZE(msm_iommu_adreno3xx_ctx_devs);
i++)
platform_device_unregister(
@@ -1097,7 +1097,7 @@
platform_device_unregister(
msm_iommu_jpegd_ctx_devs[i]);
- if (cpu_is_apq8064()) {
+ if (cpu_is_apq8064() || cpu_is_apq8064ab()) {
for (i = 0; i < ARRAY_SIZE(msm_iommu_vcap_devs);
i++)
platform_device_unregister(
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index 01c4a9c..50ab26f 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -1664,12 +1664,13 @@
* These are various Vdd levels supported by PMIC
*/
static uint32_t msm_c2_pmic_mv[] __initdata = {
- 1300000, 1287500, 1275000, 1262500, 1250000,
- 1237500, 1225000, 1212500, 1200000, 1187500,
- 1175000, 1162500, 1150000, 1137500, 1125000,
- 1112500, 1100000, 1087500, 1075000, 1062500,
- 1050000, 1037500, 1025000, 1012500, 0, 0, 0,
- 0, 0, 0, 0, 1000,
+ 1350000, 1337500, 1325000, 1312500, 1300000,
+ 1287500, 1275000, 1262500, 1250000, 1237500,
+ 1225000, 1212500, 1200000, 1187500, 1175000,
+ 1162500, 1150000, 1137500, 1125000, 1112500,
+ 1100000, 1087500, 1075000, 1062500, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1050000,
};
/**
@@ -1709,9 +1710,9 @@
.step_quot = ~0,
.tgt_volt_offset = 0,
.turbo_Vmax = 1350000,
- .turbo_Vmin = 1200000,
+ .turbo_Vmin = 1100000,
.nom_Vmax = 1350000,
- .nom_Vmin = 1050000,
+ .nom_Vmin = 1100000,
.calibrated_uV = 1300000,
},
};
@@ -1749,7 +1750,7 @@
static struct msm_cpr_config msm_cpr_pdata = {
.ref_clk_khz = 19200,
- .delay_us = 25000,
+ .delay_us = 1000,
.irq_line = 0,
.cpr_mode_data = msm_cpr_mode_data,
.tgt_count_div_N = 1,
@@ -1757,7 +1758,7 @@
.ceiling = 40,
.sw_vlevel = 20,
.up_threshold = 1,
- .dn_threshold = 3,
+ .dn_threshold = 4,
.up_margin = 0,
.dn_margin = 0,
.max_nom_freq = 700800,
@@ -1819,6 +1820,22 @@
* enough to represent the value of maximum quot
*/
msm_cpr_pdata.max_quot = cpr_info->turbo_quot * 10 + 600;
+ /**
+ * Fused Quot value for 1.2GHz on a 1.2GHz part is lower than
+ * the quot value calculated using the scaling factor formula for
+ * 1.2GHz when running on a 1.4GHz part. So, prop up the Quot for
+ * a 1.2GHz part by a chip characterization recommended value.
+ * Ditto for a 1.0GHz part.
+ */
+ if (msm8625_cpu_id() == MSM8625A) {
+ msm_cpr_pdata.max_quot += 100;
+ if (msm_cpr_pdata.max_quot > 1400)
+ msm_cpr_pdata.max_quot = 1400;
+ } else if (msm8625_cpu_id() == MSM8625) {
+ msm_cpr_pdata.max_quot += 120;
+ if (msm_cpr_pdata.max_quot > 1350)
+ msm_cpr_pdata.max_quot = 1350;
+ }
/**
* Bits 4:0 of pvs_fuse provide mapping to the safe boot up voltage.
diff --git a/arch/arm/mach-msm/devices-msm7x2xa.h b/arch/arm/mach-msm/devices-msm7x2xa.h
index 8b59b14..614037c 100644
--- a/arch/arm/mach-msm/devices-msm7x2xa.h
+++ b/arch/arm/mach-msm/devices-msm7x2xa.h
@@ -33,6 +33,6 @@
void __init msm8x25_spm_device_init(void);
void __init msm_pm_register_cpr_ops(void);
void __init msm8x25_kgsl_3d0_init(void);
-void __iomem *core1_reset_base(void);
+void __iomem *core_reset_base(unsigned int);
extern void setup_mm_for_reboot(void);
#endif
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index 7bffd9b..37cdc98 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -192,7 +192,9 @@
gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE, (void *)MSM_QGIC_CPU_BASE);
}
-#define MSM_LPASS_QDSP6SS_PHYS 0x28800000
+#define MSM_LPASS_QDSP6SS_PHYS 0x28800000
+#define MSM_LPASS_QDSP6SS_WDOG_PHYS 0x28882000
+#define MSM_LPASS_QDSP6SS_IM_PHYS 0x288A0000
static struct resource msm_8660_q6_resources[] = {
{
@@ -200,6 +202,21 @@
.end = MSM_LPASS_QDSP6SS_PHYS + SZ_256 - 1,
.flags = IORESOURCE_MEM,
},
+ {
+ .start = MSM_LPASS_QDSP6SS_IM_PHYS,
+ .end = MSM_LPASS_QDSP6SS_IM_PHYS + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MSM_LPASS_QDSP6SS_WDOG_PHYS,
+ .end = MSM_LPASS_QDSP6SS_WDOG_PHYS + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = LPASS_Q6SS_WDOG_EXPIRED,
+ .end = LPASS_Q6SS_WDOG_EXPIRED,
+ .flags = IORESOURCE_IRQ,
+ },
};
struct platform_device msm_pil_q6v3 = {
@@ -210,6 +227,7 @@
};
#define MSM_MSS_REGS_PHYS 0x10200000
+#define MSM_MSS_WDOG_PHYS 0x10020000
static struct resource msm_8660_modem_resources[] = {
{
@@ -217,6 +235,16 @@
.end = MSM_MSS_REGS_PHYS + SZ_256 - 1,
.flags = IORESOURCE_MEM,
},
+ {
+ .start = MSM_MSS_WDOG_PHYS,
+ .end = MSM_MSS_WDOG_PHYS + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MARM_WDOG_EXPIRED,
+ .end = MARM_WDOG_EXPIRED,
+ .flags = IORESOURCE_IRQ,
+ },
};
struct platform_device msm_pil_modem = {
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 0506217..6f3dda3 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -1,7 +1,7 @@
/* linux/arch/arm/mach-msm/devices.h
*
* Copyright (C) 2008 Google, Inc.
- * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -398,8 +398,6 @@
extern struct platform_device msm8930_cpu_idle_device;
extern struct platform_device apq8064_cpu_idle_device;
-extern struct platform_device msm8960_msm_gov_device;
-extern struct platform_device msm8930_msm_gov_device;
extern struct platform_device apq8064_msm_gov_device;
extern struct platform_device msm_bus_8930_apps_fabric;
@@ -447,6 +445,8 @@
extern struct platform_device msm8960ab_device_acpuclk;
extern struct platform_device msm9615_device_acpuclk;
+extern struct platform_device apq8064_msm_mpd_device;
+
extern struct platform_device msm_gpio_device;
extern struct platform_device apq_cpudai_mi2s;
diff --git a/arch/arm/mach-msm/gss-8064.c b/arch/arm/mach-msm/gss-8064.c
deleted file mode 100644
index e528650..0000000
--- a/arch/arm/mach-msm/gss-8064.c
+++ /dev/null
@@ -1,265 +0,0 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/reboot.h>
-#include <linux/workqueue.h>
-#include <linux/io.h>
-#include <linux/jiffies.h>
-#include <linux/stringify.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/miscdevice.h>
-#include <linux/fs.h>
-
-#include <mach/irqs.h>
-#include <mach/msm_smsm.h>
-#include <mach/scm.h>
-#include <mach/peripheral-loader.h>
-#include <mach/subsystem_restart.h>
-#include <mach/subsystem_notif.h>
-#include <mach/socinfo.h>
-
-#include "smd_private.h"
-#include "modem_notifier.h"
-#include "ramdump.h"
-
-static struct gss_8064_data {
- struct miscdevice gss_dev;
- void *pil_handle;
- void *gss_ramdump_dev;
- void *smem_ramdump_dev;
-} gss_data;
-
-static int crash_shutdown;
-
-static struct subsys_device *gss_8064_dev;
-
-#define MAX_SSR_REASON_LEN 81U
-
-static void log_gss_sfr(void)
-{
- u32 size;
- char *smem_reason, reason[MAX_SSR_REASON_LEN];
-
- smem_reason = smem_get_entry(SMEM_SSR_REASON_MSS0, &size);
- if (!smem_reason || !size) {
- pr_err("GSS subsystem failure reason: (unknown, smem_get_entry failed).\n");
- return;
- }
- if (!smem_reason[0]) {
- pr_err("GSS subsystem failure reason: (unknown, init string found).\n");
- return;
- }
-
- size = min(size, MAX_SSR_REASON_LEN-1);
- memcpy(reason, smem_reason, size);
- reason[size] = '\0';
- pr_err("GSS subsystem failure reason: %s.\n", reason);
-
- smem_reason[0] = '\0';
- wmb();
-}
-
-static void restart_gss(void)
-{
- log_gss_sfr();
- subsystem_restart_dev(gss_8064_dev);
-}
-
-static void smsm_state_cb(void *data, uint32_t old_state, uint32_t new_state)
-{
- /* Ignore if we're the one that set SMSM_RESET */
- if (crash_shutdown)
- return;
-
- if (new_state & SMSM_RESET) {
- pr_err("GSS SMSM state changed to SMSM_RESET.\n"
- "Probable err_fatal on the GSS. "
- "Calling subsystem restart...\n");
- restart_gss();
- }
-}
-
-#define Q6_FW_WDOG_ENABLE 0x08882024
-#define Q6_SW_WDOG_ENABLE 0x08982024
-static int gss_shutdown(const struct subsys_desc *desc)
-{
- pil_force_shutdown("gss");
- disable_irq_nosync(GSS_A5_WDOG_EXPIRED);
-
- return 0;
-}
-
-static int gss_powerup(const struct subsys_desc *desc)
-{
- pil_force_boot("gss");
- enable_irq(GSS_A5_WDOG_EXPIRED);
- return 0;
-}
-
-void gss_crash_shutdown(const struct subsys_desc *desc)
-{
- crash_shutdown = 1;
- smsm_reset_modem(SMSM_RESET);
-}
-
-/* FIXME: Get address, size from PIL */
-static struct ramdump_segment gss_segments[] = {
- {0x89000000, 0x00D00000}
-};
-
-static struct ramdump_segment smem_segments[] = {
- {0x80000000, 0x00200000},
-};
-
-static int gss_ramdump(int enable,
- const struct subsys_desc *crashed_subsys)
-{
- int ret = 0;
-
- if (enable) {
- ret = do_ramdump(gss_data.gss_ramdump_dev, gss_segments,
- ARRAY_SIZE(gss_segments));
-
- if (ret < 0) {
- pr_err("Unable to dump gss memory (rc = %d).\n",
- ret);
- goto out;
- }
-
- ret = do_ramdump(gss_data.smem_ramdump_dev, smem_segments,
- ARRAY_SIZE(smem_segments));
-
- if (ret < 0) {
- pr_err("Unable to dump smem memory (rc = %d).\n", ret);
- goto out;
- }
- }
-
-out:
- return ret;
-}
-
-static irqreturn_t gss_wdog_bite_irq(int irq, void *dev_id)
-{
- pr_err("Watchdog bite received from GSS!\n");
- restart_gss();
-
- return IRQ_HANDLED;
-}
-
-static struct subsys_desc gss_8064 = {
- .name = "gss",
- .shutdown = gss_shutdown,
- .powerup = gss_powerup,
- .ramdump = gss_ramdump,
- .crash_shutdown = gss_crash_shutdown
-};
-
-static int gss_subsystem_restart_init(void)
-{
- gss_8064_dev = subsys_register(&gss_8064);
- if (IS_ERR(gss_8064_dev))
- return PTR_ERR(gss_8064_dev);
- return 0;
-}
-
-static int gss_open(struct inode *inode, struct file *filep)
-{
- void *ret;
- gss_data.pil_handle = ret = pil_get("gss");
- if (!ret)
- pr_debug("%s - pil_get returned NULL\n", __func__);
- return 0;
-}
-
-static int gss_release(struct inode *inode, struct file *filep)
-{
- pil_put(gss_data.pil_handle);
- pr_debug("%s pil_put called on GSS\n", __func__);
- return 0;
-}
-
-const struct file_operations gss_file_ops = {
- .open = gss_open,
- .release = gss_release,
-};
-
-static int __init gss_8064_init(void)
-{
- int ret;
-
- if (!cpu_is_apq8064())
- return -ENODEV;
-
- ret = smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_RESET,
- smsm_state_cb, 0);
-
- if (ret < 0)
- pr_err("%s: Unable to register SMSM callback! (%d)\n",
- __func__, ret);
-
- ret = request_irq(GSS_A5_WDOG_EXPIRED, gss_wdog_bite_irq,
- IRQF_TRIGGER_RISING, "gss_a5_wdog", NULL);
-
- if (ret < 0) {
- pr_err("%s: Unable to request gss watchdog IRQ. (%d)\n",
- __func__, ret);
- disable_irq_nosync(GSS_A5_WDOG_EXPIRED);
- goto out;
- }
-
- ret = gss_subsystem_restart_init();
-
- if (ret < 0) {
- pr_err("%s: Unable to reg with subsystem restart. (%d)\n",
- __func__, ret);
- goto out;
- }
-
- gss_data.gss_dev.minor = MISC_DYNAMIC_MINOR;
- gss_data.gss_dev.name = "gss";
- gss_data.gss_dev.fops = &gss_file_ops;
- ret = misc_register(&gss_data.gss_dev);
-
- if (ret) {
- pr_err("%s: misc_registers failed for %s (%d)", __func__,
- gss_data.gss_dev.name, ret);
- goto out;
- }
-
- gss_data.gss_ramdump_dev = create_ramdump_device("gss");
-
- if (!gss_data.gss_ramdump_dev) {
- pr_err("%s: Unable to create gss ramdump device. (%d)\n",
- __func__, -ENOMEM);
- ret = -ENOMEM;
- goto out;
- }
-
- gss_data.smem_ramdump_dev = create_ramdump_device("smem-gss");
-
- if (!gss_data.smem_ramdump_dev) {
- pr_err("%s: Unable to create smem ramdump device. (%d)\n",
- __func__, -ENOMEM);
- ret = -ENOMEM;
- goto out;
- }
-
- pr_info("%s: gss fatal driver init'ed.\n", __func__);
-out:
- return ret;
-}
-
-module_init(gss_8064_init);
diff --git a/arch/arm/mach-msm/headsmp.S b/arch/arm/mach-msm/headsmp.S
index e5ad312..0537421 100644
--- a/arch/arm/mach-msm/headsmp.S
+++ b/arch/arm/mach-msm/headsmp.S
@@ -35,8 +35,6 @@
* we've been released from the holding pen: secondary_stack
* should now contain the SVC stack for this core
*/
- mvn r7, #0 @ -1 to registers
- str r7,[r6] @ back to the pen for ack
b secondary_startup
ENDPROC(msm_secondary_startup)
diff --git a/arch/arm/mach-msm/hotplug.c b/arch/arm/mach-msm/hotplug.c
index d1d9f4b..f296aae 100644
--- a/arch/arm/mach-msm/hotplug.c
+++ b/arch/arm/mach-msm/hotplug.c
@@ -43,7 +43,7 @@
{
}
-static inline void platform_do_lowpower(unsigned int cpu)
+static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
{
/* Just enter wfi for now. TODO: Properly shut off the cpu. */
for (;;) {
@@ -53,9 +53,6 @@
/*
* OK, proper wakeup, we're done
*/
- pen_release = -1;
- dmac_flush_range((char *)&pen_release,
- (char *)&pen_release + sizeof(pen_release));
break;
}
@@ -67,9 +64,7 @@
* possible, since we are currently running incoherently, and
* therefore cannot safely call printk() or anything else
*/
- dmac_inv_range((char *)&pen_release,
- (char *)&pen_release + sizeof(pen_release));
- pr_debug("CPU%u: spurious wakeup call\n", cpu);
+ (*spurious)++;
}
}
@@ -85,6 +80,8 @@
*/
void platform_cpu_die(unsigned int cpu)
{
+ int spurious = 0;
+
if (unlikely(cpu != smp_processor_id())) {
pr_crit("%s: running on %u, should be %u\n",
__func__, smp_processor_id(), cpu);
@@ -95,10 +92,13 @@
* we're ready for shutdown now, so do it
*/
cpu_enter_lowpower();
- platform_do_lowpower(cpu);
+ platform_do_lowpower(cpu, &spurious);
pr_debug("CPU%u: %s: normal wakeup\n", cpu, __func__);
cpu_leave_lowpower();
+
+ if (spurious)
+ pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
}
int platform_cpu_disable(unsigned int cpu)
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index b14f145..f63af64 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -38,6 +38,8 @@
/* Maximum number of SMT entries allowed by the system */
#define MAX_NUM_SMR 128
+#define MAX_NUM_BFB_REGS 32
+
/**
* struct msm_iommu_dev - a single IOMMU hardware instance
* name Human-readable name given to this IOMMU HW instance
@@ -64,6 +66,17 @@
int mids[MAX_NUM_MIDS];
};
+/**
+ * struct msm_iommu_bfb_settings - a set of IOMMU BFB tuning parameters
+ * regs An array of register offsets to configure
+ * data Values to write to corresponding registers
+ * length Number of valid entries in the offset/val arrays
+ */
+struct msm_iommu_bfb_settings {
+ unsigned int regs[MAX_NUM_BFB_REGS];
+ unsigned int data[MAX_NUM_BFB_REGS];
+ int length;
+};
/**
* struct msm_iommu_drvdata - A single IOMMU hardware instance
@@ -76,6 +89,7 @@
* @name: Human-readable name of this IOMMU device
* @gdsc: Regulator needed to power this HW block (v2 only)
* @nsmr: Size of the SMT on this HW block (v2 only)
+ * @bfb_settings: Optional BFB performance tuning parameters
*
* A msm_iommu_drvdata holds the global driver data about a single piece
* of an IOMMU hardware instance.
@@ -90,6 +104,7 @@
const char *name;
struct regulator *gdsc;
unsigned int nsmr;
+ struct msm_iommu_bfb_settings *bfb_settings;
};
/**
diff --git a/arch/arm/mach-msm/include/mach/iommu_hw-v2.h b/arch/arm/mach-msm/include/mach/iommu_hw-v2.h
index b01dbd8..c4991bf 100644
--- a/arch/arm/mach-msm/include/mach/iommu_hw-v2.h
+++ b/arch/arm/mach-msm/include/mach/iommu_hw-v2.h
@@ -15,6 +15,8 @@
#define CTX_SHIFT 12
#define CTX_OFFSET 0x8000
+#define IMPLDEF_OFFSET 0x2000
+#define IMPLDEF_LENGTH 0xDFF
#define GET_GLOBAL_REG(reg, base) (readl_relaxed((base) + (reg)))
#define GET_CTX_REG(reg, base, ctx) \
diff --git a/arch/arm/mach-msm/include/mach/irqs-8625.h b/arch/arm/mach-msm/include/mach/irqs-8625.h
index 413a778..2ec0e21 100644
--- a/arch/arm/mach-msm/include/mach/irqs-8625.h
+++ b/arch/arm/mach-msm/include/mach/irqs-8625.h
@@ -87,6 +87,8 @@
#define MSM8625_INT_CPR_IRQ0 (GIC_SPI_START + 32 + 25)
#define MSM8625_INT_CPR_IRQ1 (GIC_SPI_START + 32 + 26)
#define MSM8625_INT_CPR_IRQ2 (GIC_SPI_START + 32 + 27)
+#define MSM8625_INT_ACSR_MP_CORE_IPC2 (GIC_SPI_START + 32 + 28)
+#define MSM8625_INT_ACSR_MP_CORE_IPC3 (GIC_SPI_START + 32 + 29)
#define MSM8625_INT_ADSP_A11_SMSM MSM8625_INT_ADSP_A11
#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_dcvs.h b/arch/arm/mach-msm/include/mach/msm_dcvs.h
index fa7e6f0..e8908e8 100644
--- a/arch/arm/mach-msm/include/mach/msm_dcvs.h
+++ b/arch/arm/mach-msm/include/mach/msm_dcvs.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -18,6 +18,8 @@
#define CORE_NAME_MAX (32)
#define CORES_MAX (10)
+#define CPU_OFFSET 1 /* used to notify TZ the core number */
+
enum msm_core_idle_state {
MSM_DCVS_IDLE_ENTER,
MSM_DCVS_IDLE_EXIT,
@@ -88,16 +90,20 @@
* before the sink driver can be registered.
*/
struct msm_dcvs_core_info {
- struct msm_dcvs_freq_entry *freq_tbl;
- struct msm_dcvs_core_param core_param;
- struct msm_dcvs_algo_param algo_param;
+ int num_cores;
+ int *sensors;
+ struct msm_dcvs_freq_entry *freq_tbl;
+ struct msm_dcvs_core_param core_param;
+ struct msm_dcvs_algo_param algo_param;
+ struct msm_dcvs_energy_curve_coeffs energy_coeffs;
+ struct msm_dcvs_power_params power_param;
};
/**
* msm_dcvs_register_core
* @core_name: Unique name identifier for the core.
- * @group_id: Cores that are to be grouped for synchronized frequency scaling
* @info: The core specific algorithm parameters.
+ * @sensor: The thermal sensor number of the core in question
* @return :
* 0 on success,
* -ENOSYS,
@@ -106,10 +112,9 @@
* Register the core with msm_dcvs driver. Done once at init before calling
* msm_dcvs_freq_sink_register
* Cores that need to run synchronously must share the same group id.
- * If a core doesnt care to be in any group, the group_id should be 0.
*/
-extern int msm_dcvs_register_core(const char *core_name, uint32_t group_id,
- struct msm_dcvs_core_info *info);
+extern int msm_dcvs_register_core(const char *core_name,
+ struct msm_dcvs_core_info *info, int sensor);
/**
* struct msm_dcvs_freq
diff --git a/arch/arm/mach-msm/include/mach/msm_dcvs_scm.h b/arch/arm/mach-msm/include/mach/msm_dcvs_scm.h
index 3cc2595..597fdc0 100644
--- a/arch/arm/mach-msm/include/mach/msm_dcvs_scm.h
+++ b/arch/arm/mach-msm/include/mach/msm_dcvs_scm.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -13,38 +13,87 @@
#ifndef _ARCH_ARM_MACH_MSM_MSM_DCVS_SCM_H
#define _ARCH_ARM_MACH_MSM_MSM_DCVS_SCM_H
+enum msm_dcvs_core_type {
+ MSM_DCVS_CORE_TYPE_CPU = 0,
+ MSM_DCVS_CORE_TYPE_GPU = 1,
+};
+
+enum msm_dcvs_algo_param_type {
+ MSM_DCVS_ALGO_DCVS_PARAM = 0,
+ MSM_DCVS_ALGO_MPD_PARAM = 1,
+};
+
enum msm_dcvs_scm_event {
- MSM_DCVS_SCM_IDLE_ENTER,
- MSM_DCVS_SCM_IDLE_EXIT,
- MSM_DCVS_SCM_QOS_TIMER_EXPIRED,
- MSM_DCVS_SCM_CLOCK_FREQ_UPDATE,
- MSM_DCVS_SCM_ENABLE_CORE,
- MSM_DCVS_SCM_RESET_CORE,
+ MSM_DCVS_SCM_IDLE_ENTER = 0, /* Core enters idle */
+ MSM_DCVS_SCM_IDLE_EXIT = 1, /* Core exits idle */
+ MSM_DCVS_SCM_QOS_TIMER_EXPIRED = 2, /* Core slack timer expired */
+ MSM_DCVS_SCM_CLOCK_FREQ_UPDATE = 3, /* Core freq change complete */
+ MSM_DCVS_SCM_CORE_ONLINE = 4, /* Core is online */
+ MSM_DCVS_SCM_CORE_OFFLINE = 5, /* Core is offline */
+ MSM_DCVS_SCM_CORE_UNAVAILABLE = 6, /* Core is offline + unavailable */
+ MSM_DCVS_SCM_DCVS_ENABLE = 7, /* DCVS is enabled/disabled for core */
+ MSM_DCVS_SCM_MPD_ENABLE = 8, /* Enable/disable MP Decision */
+ MSM_DCVS_SCM_RUNQ_UPDATE = 9, /* Update running threads */
+ MSM_DCVS_SCM_MPD_QOS_TIMER_EXPIRED = 10, /* MPDecision slack timer */
};
struct msm_dcvs_algo_param {
- uint32_t slack_time_us;
- uint32_t scale_slack_time;
- uint32_t scale_slack_time_pct;
uint32_t disable_pc_threshold;
- uint32_t em_window_size;
+ uint32_t em_win_size_min_us;
+ uint32_t em_win_size_max_us;
uint32_t em_max_util_pct;
- uint32_t ss_window_size;
- uint32_t ss_util_pct;
+ uint32_t group_id;
+ uint32_t max_freq_chg_time_us;
+ uint32_t slack_mode_dynamic;
+ uint32_t slack_time_min_us;
+ uint32_t slack_time_max_us;
+ uint32_t slack_weight_thresh_pct;
uint32_t ss_iobusy_conv;
+ uint32_t ss_win_size_min_us;
+ uint32_t ss_win_size_max_us;
+ uint32_t ss_util_pct;
};
struct msm_dcvs_freq_entry {
- uint32_t freq; /* Core freq in MHz */
- uint32_t idle_energy;
- uint32_t active_energy;
+ uint32_t freq;
+ uint32_t voltage;
+ uint32_t is_trans_level;
+ uint32_t active_energy_offset;
+ uint32_t leakage_energy_offset;
};
-struct msm_dcvs_core_param {
- uint32_t max_time_us;
+struct msm_dcvs_energy_curve_coeffs {
+ int32_t active_coeff_a;
+ int32_t active_coeff_b;
+ int32_t active_coeff_c;
+
+ int32_t leakage_coeff_a;
+ int32_t leakage_coeff_b;
+ int32_t leakage_coeff_c;
+ int32_t leakage_coeff_d;
+};
+
+struct msm_dcvs_power_params {
+ uint32_t current_temp;
uint32_t num_freq; /* number of msm_dcvs_freq_entry passed */
};
+struct msm_dcvs_core_param {
+ uint32_t core_type;
+ uint32_t core_bitmask_id;
+};
+
+struct msm_mpd_algo_param {
+ uint32_t em_win_size_min_us;
+ uint32_t em_win_size_max_us;
+ uint32_t em_max_util_pct;
+ uint32_t mp_em_rounding_point_min;
+ uint32_t mp_em_rounding_point_max;
+ uint32_t online_util_pct_min;
+ uint32_t online_util_pct_max;
+ uint32_t slack_time_min_us;
+ uint32_t slack_time_max_us;
+};
#ifdef CONFIG_MSM_DCVS
/**
@@ -61,20 +110,9 @@
extern int msm_dcvs_scm_init(size_t size);
/**
- * Create an empty core group
- *
- * @return:
- * 0 on success.
- * -ENOMEM: Insufficient memory.
- * -EINVAL: Invalid args.
- */
-extern int msm_dcvs_scm_create_group(uint32_t id);
-
-/**
- * Registers cores as part of a group
+ * Registers cores with the DCVS algo.
*
* @core_id: The core identifier that will be used for communication with DCVS
- * @group_id: The group to which this core will be added to.
* @param: The core parameters
* @freq: Array of frequency and energy values
*
@@ -83,9 +121,8 @@
* -ENOMEM: Insufficient memory.
* -EINVAL: Invalid args.
*/
-extern int msm_dcvs_scm_register_core(uint32_t core_id, uint32_t group_id,
- struct msm_dcvs_core_param *param,
- struct msm_dcvs_freq_entry *freq);
+extern int msm_dcvs_scm_register_core(uint32_t core_id,
+ struct msm_dcvs_core_param *param);
/**
* Set DCVS algorithm parameters
@@ -101,6 +138,33 @@
struct msm_dcvs_algo_param *param);
/**
+ * Set MPDecision algorithm parameters
+ *
+ * @param: The param data structure
+ * 0 on success.
+ * -EINVAL: Invalid args.
+ */
+extern int msm_mpd_scm_set_algo_params(struct msm_mpd_algo_param *param);
+
+/**
+ * Set frequency and power characteristics for the core.
+ *
+ * @param core_id: The core identifier that will be used to interace with the
+ * DCVS algo.
+ * @param pwr_param: power params
+ * @param freq_entry: frequency characteristics desired
+ * @param coeffs: Coefficients that will describe the power curve
+ *
+ * @return int
+ * 0 on success.
+ * -EINVAL: Invalid args.
+ */
+extern int msm_dcvs_scm_set_power_params(uint32_t core_id,
+ struct msm_dcvs_power_params *pwr_param,
+ struct msm_dcvs_freq_entry *freq_entry,
+ struct msm_dcvs_energy_curve_coeffs *coeffs);
+
+/**
* Do an SCM call.
*
* @core_id: The core identifier.
@@ -126,19 +190,44 @@
* @param1: time taken in usec to switch to the frequency
* @ret0: New QoS timer value for the core in usec
* @ret1: unused
- * MSM_DCVS_SCM_ENABLE_CORE
- * @param0: enable(1) or disable(0) core
- * @param1: active clock frequency of the core in KHz
- * @ret0: New clock frequency for the core in KHz
- * @ret1: unused
- * MSM_DCVS_SCM_RESET_CORE
+ * MSM_DCVS_SCM_CORE_ONLINE
* @param0: active clock frequency of the core in KHz
+ * @param1: time taken to online the core
+ * @ret0: unused
+ * @ret1: unused
+ * MSM_DCVS_SCM_CORE_OFFLINE
+ * @param0: time taken to offline the core
+ * @param1: unused
+ * @ret0: unused
+ * @ret1: unused
+ * MSM_DCVS_SCM_CORE_UNAVAILABLE
+ * @param0: TODO:bitmask
+ * @param1: unused
+ * @ret0: Bitmask of cores to bring online/offline.
+ * @ret1: Mp Decision slack time. Common to all cores.
+ * MSM_DCVS_SCM_DCVS_ENABLE
+ * @param0: 1 to enable; 0 to disable DCVS
* @param1: unused
* @ret0: New clock frequency for the core in KHz
* @ret1: unused
- * @return:
- * 0 on success,
- * SCM return values
+ * MSM_DCVS_SCM_MPD_ENABLE
+ * @param0: 1 to enable; 0 to disable MP Decision
+ * @param1: unused
+ * @ret0: unused
+ * @ret1: unused
+ * MSM_DCVS_SCM_RUNQ_UPDATE
+ * @param0: run q value
+ * @param1: unused
+ * @ret0: Bitmask of cores online
+ * @ret1: New QoS timer for MP Decision (usec)
+ * MSM_DCVS_SCM_MPD_QOS_TIMER_EXPIRED
+ * @param0: unused
+ * @param1: unused
+ * @ret0: Bitmask of cores online
+ * @ret1: New QoS timer for MP Decision (usec)
+ * @return:
+ * 0 on success,
+ * SCM return values
*/
extern int msm_dcvs_scm_event(uint32_t core_id,
enum msm_dcvs_scm_event event_id,
@@ -148,16 +237,21 @@
#else
static inline int msm_dcvs_scm_init(uint32_t phy, size_t bytes)
{ return -ENOSYS; }
-static inline int msm_dcvs_scm_create_group(uint32_t id)
-{ return -ENOSYS; }
static inline int msm_dcvs_scm_register_core(uint32_t core_id,
- uint32_t group_id,
struct msm_dcvs_core_param *param,
struct msm_dcvs_freq_entry *freq)
{ return -ENOSYS; }
static inline int msm_dcvs_scm_set_algo_params(uint32_t core_id,
struct msm_dcvs_algo_param *param)
{ return -ENOSYS; }
+static inline int msm_mpd_scm_set_algo_params(
+ struct msm_mpd_algo_param *param)
+{ return -ENOSYS; }
+static inline int msm_dcvs_set_power_params(uint32_t core_id,
+ struct msm_dcvs_power_params *pwr_param,
+ struct msm_dcvs_freq_entry *freq_entry,
+ struct msm_dcvs_energy_curve_coeffs *coeffs)
+{ return -ENOSYS; }
static inline int msm_dcvs_scm_event(uint32_t core_id,
enum msm_dcvs_scm_event event_id,
uint32_t param0, uint32_t param1,
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-9625.h b/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
index eecdd67..765de13 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
@@ -34,9 +34,27 @@
#define MSM9625_TLMM_PHYS 0xFD510000
#define MSM9625_TLMM_SIZE SZ_16K
+/*
+ * TODO: Revert IMEM_PHYS back to actual
+ * address 0xfe807800
+ * after IMEM issues resolved.
+ *
+ */
+#define MSM9625_IMEM_PHYS 0xFC42B000
+#define MSM9625_IMEM_SIZE SZ_2K
+
#ifdef CONFIG_DEBUG_MSM9625_UART
#define MSM_DEBUG_UART_BASE IOMEM(0xFA71E000)
#define MSM_DEBUG_UART_PHYS 0xF991E000
#endif
+/*
+ * IMEM is retained for secure watchdog reset
+ * Debug Image looks at actual IMEM to
+ * do memory dumping.
+ */
+
+#define MSM9625_DBG_IMEM_PHYS 0xFE807800
+#define MSM9625_DBG_IMEM_SIZE SZ_4K
+
#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index 6f925d4..8dbd29c 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -101,7 +101,7 @@
#define MSM_DBG_IMEM_BASE IOMEM(0xFB600000) /* 4K */
#define MSM_STRONGLY_ORDERED_PAGE 0xFA0F0000
-#define MSM8625_SECONDARY_PHYS 0x0FE00000
+#define MSM8625_CPU_PHYS 0x0FE00000
#if defined(CONFIG_ARCH_MSM9615) || defined(CONFIG_ARCH_MSM7X27) \
diff --git a/arch/arm/mach-msm/include/mach/msm_smsm.h b/arch/arm/mach-msm/include/mach/msm_smsm.h
index be8f6c1..44b52b6 100644
--- a/arch/arm/mach-msm/include/mach/msm_smsm.h
+++ b/arch/arm/mach-msm/include/mach/msm_smsm.h
@@ -57,8 +57,7 @@
#define SMSM_PWRC 0x00000200
#define SMSM_TIMEWAIT 0x00000400
#define SMSM_TIMEINIT 0x00000800
-#define SMSM_PWRC_EARLY_EXIT 0x00001000
-#define SMSM_LTE_COEX_AWAKE 0x00001000
+#define SMSM_PROC_AWAKE 0x00001000
#define SMSM_WFPI 0x00002000
#define SMSM_SLEEP 0x00004000
#define SMSM_SLEEPEXIT 0x00008000
diff --git a/arch/arm/mach-msm/include/mach/rpm-regulator.h b/arch/arm/mach-msm/include/mach/rpm-regulator.h
index f6e082d..075d20f 100644
--- a/arch/arm/mach-msm/include/mach/rpm-regulator.h
+++ b/arch/arm/mach-msm/include/mach/rpm-regulator.h
@@ -32,7 +32,8 @@
RPM_VREG_VERSION_9615,
RPM_VREG_VERSION_8930,
RPM_VREG_VERSION_8930_PM8917,
- RPM_VREG_VERSION_MAX = RPM_VREG_VERSION_8930_PM8917,
+ RPM_VREG_VERSION_8960_PM8917,
+ RPM_VREG_VERSION_MAX = RPM_VREG_VERSION_8960_PM8917,
};
#define RPM_VREG_PIN_CTRL_NONE 0x00
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index 546cbaf..225440c 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -89,6 +89,7 @@
MSM_CPU_7X25AA,
MSM_CPU_7X25AB,
MSM_CPU_8064,
+ MSM_CPU_8064AB,
MSM_CPU_8930,
MSM_CPU_8930AA,
MSM_CPU_7X27AA,
@@ -304,6 +305,15 @@
#endif
}
+static inline int cpu_is_apq8064ab(void)
+{
+#ifdef CONFIG_ARCH_APQ8064
+ return read_msm_cpu_type() == MSM_CPU_8064AB;
+#else
+ return 0;
+#endif
+}
+
static inline int cpu_is_msm8930(void)
{
#ifdef CONFIG_ARCH_MSM8930
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index 5ee7068..39ac253 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -462,6 +462,7 @@
MSM_CHIP_DEVICE(APCS_GCC, MSM9625),
MSM_CHIP_DEVICE(TLMM, MSM9625),
MSM_CHIP_DEVICE(TMR, MSM9625),
+ MSM_CHIP_DEVICE(IMEM, MSM9625),
{
.virtual = (unsigned long) MSM_SHARED_RAM_BASE,
.length = MSM_SHARED_RAM_SIZE,
@@ -470,6 +471,7 @@
#ifdef CONFIG_DEBUG_MSM9625_UART
MSM_DEVICE(DEBUG_UART),
#endif
+ MSM_CHIP_DEVICE(DBG_IMEM, MSM9625),
};
void __init msm_map_msm9625_io(void)
diff --git a/arch/arm/mach-msm/lpass-8660.c b/arch/arm/mach-msm/lpass-8660.c
deleted file mode 100644
index be18b68..0000000
--- a/arch/arm/mach-msm/lpass-8660.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * 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/interrupt.h>
-#include <linux/reboot.h>
-#include <linux/workqueue.h>
-#include <linux/io.h>
-#include <linux/jiffies.h>
-#include <linux/stringify.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/err.h>
-
-#include <mach/irqs.h>
-#include <mach/scm.h>
-#include <mach/peripheral-loader.h>
-#include <mach/subsystem_restart.h>
-#include <mach/subsystem_notif.h>
-
-#include "smd_private.h"
-#include "modem_notifier.h"
-#include "ramdump.h"
-
-#define Q6SS_WDOG_ENABLE 0x28882024
-#define Q6SS_SOFT_INTR_WAKEUP 0x288A001C
-#define MODULE_NAME "lpass_8x60"
-#define SCM_Q6_NMI_CMD 0x1
-
-static struct subsys_device *subsys_8x60_q6_dev;
-
-/* Subsystem restart: QDSP6 data, functions */
-static void *q6_ramdump_dev;
-static void q6_fatal_fn(struct work_struct *);
-static DECLARE_WORK(q6_fatal_work, q6_fatal_fn);
-static void __iomem *q6_wakeup_intr;
-
-static void q6_fatal_fn(struct work_struct *work)
-{
- pr_err("%s: Watchdog bite received from Q6!\n", MODULE_NAME);
- subsystem_restart_dev(subsys_8x60_q6_dev);
- enable_irq(LPASS_Q6SS_WDOG_EXPIRED);
-}
-
-static void send_q6_nmi(void)
-{
- /* Send NMI to QDSP6 via an SCM call. */
- scm_call_atomic1(SCM_SVC_UTIL, SCM_Q6_NMI_CMD, 0x1);
-
- /* Wakeup the Q6 */
- if (q6_wakeup_intr)
- writel_relaxed(0x2000, q6_wakeup_intr);
- else
- pr_warn("lpass-8660: Unable to send wakeup interrupt to Q6.\n");
-
- /* Q6 requires atleast 100ms to dump caches etc.*/
- mdelay(100);
-
- pr_info("subsystem-fatal-8x60: Q6 NMI was sent.\n");
-}
-
-int subsys_q6_shutdown(const struct subsys_desc *crashed_subsys)
-{
- void __iomem *q6_wdog_addr =
- ioremap_nocache(Q6SS_WDOG_ENABLE, 8);
-
- send_q6_nmi();
- writel_relaxed(0x0, q6_wdog_addr);
- /* The write needs to go through before the q6 is shutdown. */
- mb();
- iounmap(q6_wdog_addr);
-
- pil_force_shutdown("q6");
- disable_irq_nosync(LPASS_Q6SS_WDOG_EXPIRED);
-
- return 0;
-}
-
-int subsys_q6_powerup(const struct subsys_desc *crashed_subsys)
-{
- int ret = pil_force_boot("q6");
- enable_irq(LPASS_Q6SS_WDOG_EXPIRED);
- return ret;
-}
-
-/* FIXME: Get address, size from PIL */
-static struct ramdump_segment q6_segments[] = { {0x46700000, 0x47F00000 -
- 0x46700000}, {0x28400000, 0x12800} };
-static int subsys_q6_ramdump(int enable,
- const struct subsys_desc *crashed_subsys)
-{
- if (enable)
- return do_ramdump(q6_ramdump_dev, q6_segments,
- ARRAY_SIZE(q6_segments));
- else
- return 0;
-}
-
-void subsys_q6_crash_shutdown(const struct subsys_desc *crashed_subsys)
-{
- send_q6_nmi();
-}
-
-static irqreturn_t lpass_wdog_bite_irq(int irq, void *dev_id)
-{
- int ret;
-
- ret = schedule_work(&q6_fatal_work);
- disable_irq_nosync(LPASS_Q6SS_WDOG_EXPIRED);
-
- return IRQ_HANDLED;
-}
-
-static struct subsys_desc subsys_8x60_q6 = {
- .name = "lpass",
- .shutdown = subsys_q6_shutdown,
- .powerup = subsys_q6_powerup,
- .ramdump = subsys_q6_ramdump,
- .crash_shutdown = subsys_q6_crash_shutdown
-};
-
-static void __exit lpass_fatal_exit(void)
-{
- subsys_unregister(subsys_8x60_q6_dev);
- iounmap(q6_wakeup_intr);
- free_irq(LPASS_Q6SS_WDOG_EXPIRED, NULL);
-}
-
-static int __init lpass_fatal_init(void)
-{
- int ret;
-
- ret = request_irq(LPASS_Q6SS_WDOG_EXPIRED, lpass_wdog_bite_irq,
- IRQF_TRIGGER_RISING, "q6_wdog", NULL);
-
- if (ret < 0) {
- pr_err("%s: Unable to request LPASS_Q6SS_WDOG_EXPIRED irq.",
- __func__);
- goto out;
- }
-
- q6_ramdump_dev = create_ramdump_device("lpass");
-
- if (!q6_ramdump_dev) {
- ret = -ENOMEM;
- goto out;
- }
-
- q6_wakeup_intr = ioremap_nocache(Q6SS_SOFT_INTR_WAKEUP, 8);
-
- if (!q6_wakeup_intr)
- pr_warn("lpass-8660: Unable to ioremap q6 wakeup address.");
-
- subsys_8x60_q6_dev = subsys_register(&subsys_8x60_q6);
- if (IS_ERR(subsys_8x60_q6_dev))
- ret = PTR_ERR(subsys_8x60_q6_dev);
-out:
- return ret;
-}
-
-module_init(lpass_fatal_init);
-module_exit(lpass_fatal_exit);
-
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index 74c1c4a..a785389 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -173,63 +173,29 @@
struct reserve_info *reserve_info;
-static unsigned long stable_size(struct membank *mb,
- unsigned long unstable_limit)
-{
- unsigned long upper_limit = mb->start + mb->size;
-
- if (!unstable_limit)
- return mb->size;
-
- /* Check for 32 bit roll-over */
- if (upper_limit >= mb->start) {
- /* If we didn't roll over we can safely make the check below */
- if (upper_limit <= unstable_limit)
- return mb->size;
- }
-
- if (mb->start >= unstable_limit)
- return 0;
- return unstable_limit - mb->start;
-}
-
-/* stable size of all memory banks contiguous to and below this one */
-static unsigned long total_stable_size(unsigned long bank)
-{
- int i;
- struct membank *mb = &meminfo.bank[bank];
- int memtype = reserve_info->paddr_to_memtype(mb->start);
- unsigned long size;
-
- size = stable_size(mb, reserve_info->low_unstable_address);
- for (i = bank - 1, mb = &meminfo.bank[bank - 1]; i >= 0; i--, mb--) {
- if (mb->start + mb->size != (mb + 1)->start)
- break;
- if (reserve_info->paddr_to_memtype(mb->start) != memtype)
- break;
- size += stable_size(mb, reserve_info->low_unstable_address);
- }
- return size;
-}
-
+/**
+ * calculate_reserve_limits() - calculate reserve limits for all
+ * memtypes
+ *
+ * for each memtype in the reserve_info->memtype_reserve_table, sets
+ * the `limit' field to the largest size of any memblock of that
+ * memtype.
+ */
static void __init calculate_reserve_limits(void)
{
- int i;
- struct membank *mb;
+ struct memblock_region *mr;
int memtype;
struct memtype_reserve *mt;
- unsigned long size;
- for (i = 0, mb = &meminfo.bank[0]; i < meminfo.nr_banks; i++, mb++) {
- memtype = reserve_info->paddr_to_memtype(mb->start);
+ for_each_memblock(memory, mr) {
+ memtype = reserve_info->paddr_to_memtype(mr->base);
if (memtype == MEMTYPE_NONE) {
- pr_warning("unknown memory type for bank at %lx\n",
- (long unsigned int)mb->start);
+ pr_warning("unknown memory type for region at %lx\n",
+ (long unsigned int)mr->base);
continue;
}
mt = &reserve_info->memtype_reserve_table[memtype];
- size = total_stable_size(i);
- mt->limit = max(mt->limit, size);
+ mt->limit = max_t(unsigned long, mt->limit, mr->size);
}
}
@@ -252,50 +218,38 @@
static void __init reserve_memory_for_mempools(void)
{
- int i, memtype, membank_type;
+ int memtype, memreg_type;
struct memtype_reserve *mt;
- struct membank *mb;
+ struct memblock_region *mr, *mr_candidate = NULL;
int ret;
- unsigned long size;
mt = &reserve_info->memtype_reserve_table[0];
for (memtype = 0; memtype < MEMTYPE_MAX; memtype++, mt++) {
if (mt->flags & MEMTYPE_FLAGS_FIXED || !mt->size)
continue;
- /* We know we will find memory bank(s) of the proper size
- * as we have limited the size of the memory pool for
- * each memory type to the largest total size of the memory
- * banks which are contiguous and of the correct memory type.
- * Choose the memory bank with the highest physical
+ /* Choose the memory block with the highest physical
* address which is large enough, so that we will not
* take memory from the lowest memory bank which the kernel
* is in (and cause boot problems) and so that we might
* be able to steal memory that would otherwise become
- * highmem. However, do not use unstable memory.
+ * highmem.
*/
- for (i = meminfo.nr_banks - 1; i >= 0; i--) {
- mb = &meminfo.bank[i];
- membank_type =
- reserve_info->paddr_to_memtype(mb->start);
- if (memtype != membank_type)
+ for_each_memblock(memory, mr) {
+ memreg_type =
+ reserve_info->paddr_to_memtype(mr->base);
+ if (memtype != memreg_type)
continue;
- size = total_stable_size(i);
- if (size >= mt->size) {
- size = stable_size(mb,
- reserve_info->low_unstable_address);
- if (!size)
- continue;
- /* mt->size may be larger than size, all this
- * means is that we are carving the memory pool
- * out of multiple contiguous memory banks.
- */
- mt->start = mb->start + (size - mt->size);
- ret = memblock_remove(mt->start, mt->size);
- BUG_ON(ret);
- break;
- }
+ if (mr->size >= mt->size
+ && (mr_candidate == NULL
+ || mr->base > mr_candidate->base))
+ mr_candidate = mr;
}
+ BUG_ON(mr_candidate == NULL);
+ /* bump mt up against the top of the region */
+ mt->start = mr_candidate->base + mr_candidate->size - mt->size;
+ ret = memblock_remove(mt->start, mt->size);
+ BUG_ON(ret);
}
}
diff --git a/arch/arm/mach-msm/modem-8660.c b/arch/arm/mach-msm/modem-8660.c
deleted file mode 100644
index 096ed9c..0000000
--- a/arch/arm/mach-msm/modem-8660.c
+++ /dev/null
@@ -1,290 +0,0 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * 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/interrupt.h>
-#include <linux/reboot.h>
-#include <linux/workqueue.h>
-#include <linux/io.h>
-#include <linux/jiffies.h>
-#include <linux/stringify.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/err.h>
-
-#include <mach/irqs.h>
-#include <mach/scm.h>
-#include <mach/peripheral-loader.h>
-#include <mach/subsystem_restart.h>
-#include <mach/subsystem_notif.h>
-
-#include "smd_private.h"
-#include "modem_notifier.h"
-#include "ramdump.h"
-
-#define MODEM_HWIO_MSS_RESET_ADDR 0x00902C48
-#define MODULE_NAME "modem_8660"
-#define MODEM_WDOG_ENABLE 0x10020008
-#define MODEM_CLEANUP_DELAY_MS 20
-
-#define SUBSYS_FATAL_DEBUG
-
-#if defined(SUBSYS_FATAL_DEBUG)
-static void debug_crash_modem_fn(struct work_struct *);
-static int reset_modem;
-static int ignore_smsm_ack;
-
-static DECLARE_DELAYED_WORK(debug_crash_modem_work,
- debug_crash_modem_fn);
-
-module_param(reset_modem, int, 0644);
-#endif
-
-static struct subsys_device *modem_8660_dev;
-
-/* Subsystem restart: Modem data, functions */
-static void *modem_ramdump_dev;
-static void modem_fatal_fn(struct work_struct *);
-static void modem_unlock_timeout(struct work_struct *work);
-static int modem_notif_handler(struct notifier_block *this,
- unsigned long code,
- void *_cmd);
-static DECLARE_WORK(modem_fatal_work, modem_fatal_fn);
-static DECLARE_DELAYED_WORK(modem_unlock_timeout_work,
- modem_unlock_timeout);
-
-static struct notifier_block modem_notif_nb = {
- .notifier_call = modem_notif_handler,
-};
-
-static void modem_unlock_timeout(struct work_struct *work)
-{
- void __iomem *hwio_modem_reset_addr =
- ioremap_nocache(MODEM_HWIO_MSS_RESET_ADDR, 8);
- pr_crit("%s: Timeout waiting for modem to unlock.\n", MODULE_NAME);
-
- /* Set MSS_MODEM_RESET to 0x0 since the unlock didn't work */
- writel_relaxed(0x0, hwio_modem_reset_addr);
- /* Write needs to go through before the modem is restarted. */
- mb();
- iounmap(hwio_modem_reset_addr);
-
- subsystem_restart_dev(modem_8660_dev);
- enable_irq(MARM_WDOG_EXPIRED);
-}
-
-static void modem_fatal_fn(struct work_struct *work)
-{
- uint32_t modem_state;
- uint32_t panic_smsm_states = SMSM_RESET | SMSM_SYSTEM_DOWNLOAD;
- uint32_t reset_smsm_states = SMSM_SYSTEM_REBOOT_USR |
- SMSM_SYSTEM_PWRDWN_USR;
-
- pr_err("%s: Watchdog bite received from modem!\n", MODULE_NAME);
-
- modem_state = smsm_get_state(SMSM_MODEM_STATE);
- pr_err("%s: Modem SMSM state = 0x%x!", MODULE_NAME, modem_state);
-
- if (modem_state == 0 || modem_state & panic_smsm_states) {
-
- subsystem_restart_dev(modem_8660_dev);
- enable_irq(MARM_WDOG_EXPIRED);
-
- } else if (modem_state & reset_smsm_states) {
-
- pr_err("%s: User-invoked system reset/powerdown.",
- MODULE_NAME);
- kernel_restart(NULL);
-
- } else {
-
- int ret;
- void *hwio_modem_reset_addr =
- ioremap_nocache(MODEM_HWIO_MSS_RESET_ADDR, 8);
-
- pr_err("%s: Modem AHB locked up.\n", MODULE_NAME);
- pr_err("%s: Trying to free up modem!\n", MODULE_NAME);
-
- writel_relaxed(0x3, hwio_modem_reset_addr);
-
- /* If we are still alive after 6 seconds (allowing for
- * the 5-second-delayed-panic-reboot), modem is either
- * still wedged or SMSM didn't come through. Force panic
- * in that case.
- */
- ret = schedule_delayed_work(&modem_unlock_timeout_work,
- msecs_to_jiffies(6000));
-
- iounmap(hwio_modem_reset_addr);
- }
-}
-
-static int modem_notif_handler(struct notifier_block *this,
- unsigned long code,
- void *_cmd)
-{
- if (code == MODEM_NOTIFIER_START_RESET) {
- if (ignore_smsm_ack) {
- ignore_smsm_ack = 0;
- goto out;
- }
- pr_err("%s: Modem error fatal'ed.", MODULE_NAME);
- subsystem_restart_dev(modem_8660_dev);
- }
-out:
- return NOTIFY_DONE;
-}
-
-static int modem_shutdown(const struct subsys_desc *crashed_subsys)
-{
- void __iomem *modem_wdog_addr;
-
- /* If the modem didn't already crash, setting SMSM_RESET
- * here will help flush caches etc. The ignore_smsm_ack
- * flag is set to ignore the SMSM_RESET notification
- * that is generated due to the modem settings its own
- * SMSM_RESET bit in response to the apps setting the
- * apps SMSM_RESET bit.
- */
- if (!(smsm_get_state(SMSM_MODEM_STATE) & SMSM_RESET)) {
- ignore_smsm_ack = 1;
- smsm_reset_modem(SMSM_RESET);
- }
-
- /* Disable the modem watchdog to allow clean modem bootup */
- modem_wdog_addr = ioremap_nocache(MODEM_WDOG_ENABLE, 8);
- writel_relaxed(0x0, modem_wdog_addr);
-
- /*
- * The write above needs to go through before the modem is
- * powered up again (subsystem restart).
- */
- mb();
- iounmap(modem_wdog_addr);
-
- /* Wait here to allow the modem to clean up caches etc. */
- msleep(MODEM_CLEANUP_DELAY_MS);
- pil_force_shutdown("modem");
- disable_irq_nosync(MARM_WDOG_EXPIRED);
-
-
-
- return 0;
-}
-
-static int modem_powerup(const struct subsys_desc *crashed_subsys)
-{
- int ret;
-
- ret = pil_force_boot("modem");
- enable_irq(MARM_WDOG_EXPIRED);
-
- return ret;
-}
-
-/* FIXME: Get address, size from PIL */
-static struct ramdump_segment modem_segments[] = {
- {0x42F00000, 0x46000000 - 0x42F00000} };
-
-static int modem_ramdump(int enable, const struct subsys_desc *crashed_subsys)
-{
- if (enable)
- return do_ramdump(modem_ramdump_dev, modem_segments,
- ARRAY_SIZE(modem_segments));
- else
- return 0;
-}
-
-static void modem_crash_shutdown(const struct subsys_desc *crashed_subsys)
-{
- /* If modem hasn't already crashed, send SMSM_RESET. */
- if (!(smsm_get_state(SMSM_MODEM_STATE) & SMSM_RESET)) {
- modem_unregister_notifier(&modem_notif_nb);
- smsm_reset_modem(SMSM_RESET);
- }
-
- /* Wait to allow the modem to clean up caches etc. */
- mdelay(5);
-}
-
-static irqreturn_t modem_wdog_bite_irq(int irq, void *dev_id)
-{
- int ret;
-
- ret = schedule_work(&modem_fatal_work);
- disable_irq_nosync(MARM_WDOG_EXPIRED);
-
- return IRQ_HANDLED;
-}
-
-static struct subsys_desc subsys_8660_modem = {
- .name = "modem",
- .shutdown = modem_shutdown,
- .powerup = modem_powerup,
- .ramdump = modem_ramdump,
- .crash_shutdown = modem_crash_shutdown
-};
-
-static int __init modem_8660_init(void)
-{
- int ret;
-
- /* Need to listen for SMSM_RESET always */
- modem_register_notifier(&modem_notif_nb);
-
-#if defined(SUBSYS_FATAL_DEBUG)
- schedule_delayed_work(&debug_crash_modem_work, msecs_to_jiffies(5000));
-#endif
-
- ret = request_irq(MARM_WDOG_EXPIRED, modem_wdog_bite_irq,
- IRQF_TRIGGER_RISING, "modem_wdog", NULL);
-
- if (ret < 0) {
- pr_err("%s: Unable to request MARM_WDOG_EXPIRED irq.",
- __func__);
- goto out;
- }
-
- modem_ramdump_dev = create_ramdump_device("modem");
-
- if (!modem_ramdump_dev) {
- ret = -ENOMEM;
- goto out;
- }
-
- modem_8660_dev = subsys_register(&subsys_8660_modem);
- if (IS_ERR(modem_8660_dev))
- ret = PTR_ERR(modem_8660_dev);
-out:
- return ret;
-}
-
-static void __exit modem_8660_exit(void)
-{
- subsys_unregister(modem_8660_dev);
- free_irq(MARM_WDOG_EXPIRED, NULL);
-}
-
-#ifdef SUBSYS_FATAL_DEBUG
-static void debug_crash_modem_fn(struct work_struct *work)
-{
- if (reset_modem == 1)
- smsm_reset_modem(SMSM_RESET);
-
- reset_modem = 0;
- schedule_delayed_work(&debug_crash_modem_work, msecs_to_jiffies(1000));
-}
-#endif
-
-module_init(modem_8660_init);
-module_exit(modem_8660_exit);
-
diff --git a/arch/arm/mach-msm/modem-8960.c b/arch/arm/mach-msm/modem-8960.c
index f0a123b..83b3bc4 100644
--- a/arch/arm/mach-msm/modem-8960.c
+++ b/arch/arm/mach-msm/modem-8960.c
@@ -258,7 +258,7 @@
{
int ret;
- if (cpu_is_apq8064())
+ if (cpu_is_apq8064() || cpu_is_apq8064ab())
return -ENODEV;
ret = smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_RESET,
diff --git a/arch/arm/mach-msm/msm_cpr.c b/arch/arm/mach-msm/msm_cpr.c
index 54f900d..c00352d 100644
--- a/arch/arm/mach-msm/msm_cpr.c
+++ b/arch/arm/mach-msm/msm_cpr.c
@@ -525,6 +525,10 @@
*/
error_step -= 2;
+ /* Keep down step upto two per interrupt to avoid any spike */
+ if (error_step > 2)
+ error_step = 2;
+
/* Calculte new PMIC voltage */
new_volt = curr_volt - (error_step * cpr->vp->step_size);
msm_cpr_debug(MSM_CPR_DEBUG_STEPS,
@@ -642,6 +646,11 @@
cpr->config->delay_us);
cpr_write_reg(cpr, RBCPR_TIMER_INTERVAL, delay_count);
+ /* Use Consecutive Down to avoid any interrupt due to spike */
+ cpr_write_reg(cpr, RBIF_TIMER_ADJUST, (0x2 << RBIF_CONS_DN_SHIFT));
+ msm_cpr_debug(MSM_CPR_DEBUG_CONFIG, "RBIF_TIMER_ADJUST: 0x%x\n",
+ readl_relaxed(cpr->base + RBIF_TIMER_ADJUST));
+
/* Enable the Timer */
cpr_modify_reg(cpr, RBCPR_CTL, TIMER_M, ENABLE_TIMER);
@@ -743,12 +752,15 @@
"RBIF_IRQ_STATUS: 0x%x\n",
cpr_read_reg(cpr, RBIF_IRQ_STATUS));
+ /* Clear all the interrupts */
+ cpr_write_reg(cpr, RBIF_IRQ_CLEAR, ALL_CPR_IRQ);
+
cpr_enable(cpr);
break;
default:
break;
}
- return 0;
+ return NOTIFY_OK;
}
#ifdef CONFIG_PM
@@ -776,6 +788,9 @@
cpr_write_reg(cpr, RBCPR_CTL,
cpr_save_state.rbcpr_ctl);
+ /* Clear all the interrupts */
+ cpr_write_reg(cpr, RBIF_IRQ_CLEAR, ALL_CPR_IRQ);
+
enable_irq(cpr->irq);
cpr_enable(cpr);
@@ -792,6 +807,9 @@
cpr_disable(cpr);
disable_irq(cpr->irq);
+ /* Clear all the interrupts */
+ cpr_write_reg(cpr, RBIF_IRQ_CLEAR, ALL_CPR_IRQ);
+
cpr_save_state.rbif_timer_interval =
cpr_read_reg(cpr, RBCPR_TIMER_INTERVAL);
cpr_save_state.rbif_int_en =
@@ -814,12 +832,18 @@
void msm_cpr_pm_resume(void)
{
+ if (!enable)
+ return;
+
msm_cpr_resume(&cpr_pdev->dev);
}
EXPORT_SYMBOL(msm_cpr_pm_resume);
void msm_cpr_pm_suspend(void)
{
+ if (!enable)
+ return;
+
msm_cpr_suspend(&cpr_pdev->dev);
}
EXPORT_SYMBOL(msm_cpr_pm_suspend);
@@ -827,14 +851,26 @@
void msm_cpr_disable(void)
{
- struct msm_cpr *cpr = platform_get_drvdata(cpr_pdev);
+ struct msm_cpr *cpr;
+
+ if (!enable)
+ return;
+
+ cpr = platform_get_drvdata(cpr_pdev);
+
cpr_disable(cpr);
}
EXPORT_SYMBOL(msm_cpr_disable);
void msm_cpr_enable(void)
{
- struct msm_cpr *cpr = platform_get_drvdata(cpr_pdev);
+ struct msm_cpr *cpr;
+
+ if (!enable)
+ return;
+
+ cpr = platform_get_drvdata(cpr_pdev);
+
cpr_enable(cpr);
}
EXPORT_SYMBOL(msm_cpr_enable);
@@ -853,12 +889,15 @@
if (!pdata) {
pr_err("CPR: Platform data is not available\n");
+ enable = false;
return -EIO;
}
cpr = devm_kzalloc(&pdev->dev, sizeof(struct msm_cpr), GFP_KERNEL);
- if (!cpr)
+ if (!cpr) {
+ enable = false;
return -ENOMEM;
+ }
/* Initialize platform_data */
cpr->config = pdata;
@@ -973,6 +1012,7 @@
err_ioremap:
iounmap(base);
out:
+ enable = false;
return res;
}
diff --git a/arch/arm/mach-msm/msm_cpr.h b/arch/arm/mach-msm/msm_cpr.h
index e690c63..005d9b1 100644
--- a/arch/arm/mach-msm/msm_cpr.h
+++ b/arch/arm/mach-msm/msm_cpr.h
@@ -72,6 +72,9 @@
#define SW_AUTO_CONT_ACK_EN BIT(5)
#define SW_AUTO_CONT_NACK_DN_EN BIT(6)
+/* Shift Values */
+#define RBIF_CONS_DN_SHIFT (0x4)
+
/* Test values for RBCPR RUMI Testing */
#define GNT_CNT 0xC0
#define TARGET 0xEFF
diff --git a/arch/arm/mach-msm/msm_dcvs.c b/arch/arm/mach-msm/msm_dcvs.c
index 0c158de..f761bf9 100644
--- a/arch/arm/mach-msm/msm_dcvs.c
+++ b/arch/arm/mach-msm/msm_dcvs.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -23,6 +23,7 @@
#include <linux/spinlock.h>
#include <linux/stringify.h>
#include <linux/debugfs.h>
+#include <linux/msm_tsens.h>
#include <asm/atomic.h>
#include <asm/page.h>
#include <mach/msm_dcvs.h>
@@ -39,35 +40,47 @@
};
struct core_attribs {
+ struct kobj_attribute core_id;
struct kobj_attribute idle_enabled;
struct kobj_attribute freq_change_enabled;
struct kobj_attribute actual_freq;
struct kobj_attribute freq_change_us;
- struct kobj_attribute max_time_us;
-
- struct kobj_attribute slack_time_us;
- struct kobj_attribute scale_slack_time;
- struct kobj_attribute scale_slack_time_pct;
struct kobj_attribute disable_pc_threshold;
- struct kobj_attribute em_window_size;
+ struct kobj_attribute em_win_size_min_us;
+ struct kobj_attribute em_win_size_max_us;
struct kobj_attribute em_max_util_pct;
- struct kobj_attribute ss_window_size;
- struct kobj_attribute ss_util_pct;
+ struct kobj_attribute group_id;
+ struct kobj_attribute max_freq_chg_time_us;
+ struct kobj_attribute slack_mode_dynamic;
+ struct kobj_attribute slack_time_min_us;
+ struct kobj_attribute slack_time_max_us;
+ struct kobj_attribute slack_weight_thresh_pct;
struct kobj_attribute ss_iobusy_conv;
+ struct kobj_attribute ss_win_size_min_us;
+ struct kobj_attribute ss_win_size_max_us;
+ struct kobj_attribute ss_util_pct;
+
+ struct kobj_attribute active_coeff_a;
+ struct kobj_attribute active_coeff_b;
+ struct kobj_attribute active_coeff_c;
+ struct kobj_attribute leakage_coeff_a;
+ struct kobj_attribute leakage_coeff_b;
+ struct kobj_attribute leakage_coeff_c;
+ struct kobj_attribute leakage_coeff_d;
struct attribute_group attrib_group;
};
struct dcvs_core {
char core_name[CORE_NAME_MAX];
- uint32_t new_freq[MAX_PENDING];
uint32_t actual_freq;
uint32_t freq_change_us;
uint32_t max_time_us; /* core param */
struct msm_dcvs_algo_param algo_param;
+ struct msm_dcvs_energy_curve_coeffs coeffs;
struct msm_dcvs_idle *idle_driver;
struct msm_dcvs_freq *freq_driver;
@@ -78,19 +91,19 @@
struct task_struct *task;
struct core_attribs attrib;
uint32_t handle;
- uint32_t group_id;
- uint32_t freq_pending;
struct hrtimer timer;
int32_t timer_disabled;
- /* track if kthread for change_freq is active */
- int32_t change_freq_activated;
+ struct msm_dcvs_core_info *info;
+ int sensor;
+ int pending_freq;
+ wait_queue_head_t wait_q;
};
static int msm_dcvs_debug;
static int msm_dcvs_enabled = 1;
module_param_named(enable, msm_dcvs_enabled, int, S_IRUGO | S_IWUSR | S_IWGRP);
-static struct dentry *debugfs_base;
+static struct dentry *debugfs_base;
static struct dcvs_core core_list[CORES_MAX];
static DEFINE_MUTEX(core_list_lock);
@@ -114,24 +127,12 @@
/* Core may have unregistered or hotplugged */
return -ENODEV;
}
-repeat:
spin_lock_irqsave(&core->cpu_lock, flags);
- if (unlikely(!core->freq_pending)) {
- spin_unlock_irqrestore(&core->cpu_lock, flags);
- return ret;
- }
- requested_freq = core->new_freq[core->freq_pending - 1];
- if (unlikely(core->freq_pending > 1) &&
- (msm_dcvs_debug & MSM_DCVS_DEBUG_FREQ_CHANGE)) {
- int i;
- for (i = 0; i < core->freq_pending - 1; i++) {
- __info("Core %s missing freq %u\n",
- core->core_name, core->new_freq[i]);
- }
- }
+repeat:
+
+ requested_freq = core->pending_freq;
time_start = core->time_start;
core->time_start = 0;
- core->freq_pending = 0;
/**
* Cancel the timers, we dont want the timer firing as we are
* changing the clock rate. Dont let idle_exit and others setup
@@ -139,10 +140,11 @@
*/
hrtimer_cancel(&core->timer);
core->timer_disabled = 1;
+ if (requested_freq == core->actual_freq)
+ goto out;
+
spin_unlock_irqrestore(&core->cpu_lock, flags);
- if (requested_freq == core->actual_freq)
- return ret;
/**
* Call the frequency sink driver to change the frequency
@@ -216,14 +218,40 @@
core->actual_freq, prev_freq,
core->freq_change_us, slack_us);
+ spin_lock_irqsave(&core->cpu_lock, flags);
/**
* By the time we are done with freq changes, we could be asked to
* change again. Check before exiting.
*/
- if (core->freq_pending)
+ if (core->pending_freq)
goto repeat;
- core->change_freq_activated = 0;
+
+out: /* should always be jumped to with the spin_lock held */
+ core->pending_freq = 0;
+ spin_unlock_irqrestore(&core->cpu_lock, flags);
+
+ return ret;
+}
+
+static int __msm_dcvs_report_temp(struct dcvs_core *core)
+{
+ struct msm_dcvs_core_info *info = core->info;
+ struct tsens_device tsens_dev;
+ int ret;
+ unsigned long temp = 0;
+
+ tsens_dev.sensor_num = core->sensor;
+ ret = tsens_get_temp(&tsens_dev, &temp);
+ if (!ret) {
+ tsens_dev.sensor_num = 0;
+ ret = tsens_get_temp(&tsens_dev, &temp);
+ if (!ret)
+ return -ENODEV;
+ }
+
+ ret = msm_dcvs_scm_set_power_params(core->handle, &info->power_param,
+ &info->freq_tbl[0], &core->coeffs);
return ret;
}
@@ -233,23 +261,21 @@
static struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1};
sched_setscheduler(current, SCHED_FIFO, ¶m);
- set_current_state(TASK_UNINTERRUPTIBLE);
while (!kthread_should_stop()) {
- mutex_lock(&core->lock);
- __msm_dcvs_change_freq(core);
- mutex_unlock(&core->lock);
-
- schedule();
+ wait_event(core->wait_q, !(core->pending_freq == 0 ||
+ core->pending_freq == -1) ||
+ kthread_should_stop());
if (kthread_should_stop())
break;
- set_current_state(TASK_UNINTERRUPTIBLE);
+ mutex_lock(&core->lock);
+ __msm_dcvs_change_freq(core);
+ __msm_dcvs_report_temp(core);
+ mutex_unlock(&core->lock);
}
- __set_current_state(TASK_RUNNING);
-
return 0;
}
@@ -265,33 +291,25 @@
ret = msm_dcvs_scm_event(core->handle, event, param0,
core->actual_freq, &new_freq, ret1);
if (ret) {
- __err("Error (%d) sending SCM event %d for core %s\n",
+ if (ret == -13)
+ ret = 0;
+ else
+ __err("Error (%d) sending SCM event %d for core %s\n",
ret, event, core->core_name);
- goto freq_done;
+ goto out;
}
- if ((core->actual_freq != new_freq) &&
- (core->new_freq[core->freq_pending] != new_freq)) {
- if (core->freq_pending >= MAX_PENDING - 1)
- core->freq_pending = MAX_PENDING - 1;
- core->new_freq[core->freq_pending++] = new_freq;
+ if (core->actual_freq != new_freq && core->pending_freq != new_freq) {
+ core->pending_freq = new_freq;
core->time_start = ktime_to_ns(ktime_get());
- /* Schedule the frequency change */
- if (!core->task)
- __err("Uninitialized task for core %s\n",
- core->core_name);
- else {
- if (freq_changed)
- *freq_changed = 1;
- core->change_freq_activated = 1;
- wake_up_process(core->task);
- }
+ if (core->task)
+ wake_up(&core->wait_q);
} else {
if (freq_changed)
*freq_changed = 0;
}
-freq_done:
+out:
spin_unlock_irqrestore(&core->cpu_lock, flags);
return ret;
@@ -365,6 +383,39 @@
return count; \
}
+#define DCVS_ENERGY_PARAM(_name) \
+static ssize_t msm_dcvs_attr_##_name##_show(struct kobject *kobj,\
+ struct kobj_attribute *attr, char *buf) \
+{ \
+ struct dcvs_core *core = CORE_FROM_ATTRIBS(attr, _name); \
+ return snprintf(buf, PAGE_SIZE, "%d\n", core->coeffs._name); \
+} \
+static ssize_t msm_dcvs_attr_##_name##_store(struct kobject *kobj, \
+ struct kobj_attribute *attr, const char *buf, size_t count) \
+{ \
+ int ret = 0; \
+ int32_t val = 0; \
+ struct dcvs_core *core = CORE_FROM_ATTRIBS(attr, _name); \
+ mutex_lock(&core->lock); \
+ ret = kstrtoint(buf, 10, &val); \
+ if (ret) { \
+ __err("Invalid input %s for %s\n", buf, __stringify(_name));\
+ } else { \
+ int32_t old_val = core->coeffs._name; \
+ core->coeffs._name = val; \
+ ret = msm_dcvs_scm_set_power_params(core->handle, \
+ &core->info->power_param, &core->info->freq_tbl[0], \
+ &core->coeffs); \
+ if (ret) { \
+ core->coeffs._name = old_val; \
+ __err("Error(%d) in setting %d for coeffs param %s\n",\
+ ret, val, __stringify(_name)); \
+ } \
+ } \
+ mutex_unlock(&core->lock); \
+ return count; \
+}
+
#define DCVS_RO_ATTRIB(i, _name) \
core->attrib._name.attr.name = __stringify(_name); \
core->attrib._name.attr.mode = S_IRUGO; \
@@ -383,27 +434,40 @@
* Function declarations for different attributes.
* Gets used when setting the attribute show and store parameters.
*/
+DCVS_PARAM_SHOW(core_id, core->handle)
DCVS_PARAM_SHOW(idle_enabled, (core->idle_driver != NULL))
DCVS_PARAM_SHOW(freq_change_enabled, (core->freq_driver != NULL))
DCVS_PARAM_SHOW(actual_freq, (core->actual_freq))
DCVS_PARAM_SHOW(freq_change_us, (core->freq_change_us))
-DCVS_PARAM_SHOW(max_time_us, (core->max_time_us))
-DCVS_ALGO_PARAM(slack_time_us)
-DCVS_ALGO_PARAM(scale_slack_time)
-DCVS_ALGO_PARAM(scale_slack_time_pct)
DCVS_ALGO_PARAM(disable_pc_threshold)
-DCVS_ALGO_PARAM(em_window_size)
+DCVS_ALGO_PARAM(em_win_size_min_us)
+DCVS_ALGO_PARAM(em_win_size_max_us)
DCVS_ALGO_PARAM(em_max_util_pct)
-DCVS_ALGO_PARAM(ss_window_size)
-DCVS_ALGO_PARAM(ss_util_pct)
+DCVS_ALGO_PARAM(group_id)
+DCVS_ALGO_PARAM(max_freq_chg_time_us)
+DCVS_ALGO_PARAM(slack_mode_dynamic)
+DCVS_ALGO_PARAM(slack_time_min_us)
+DCVS_ALGO_PARAM(slack_time_max_us)
+DCVS_ALGO_PARAM(slack_weight_thresh_pct)
DCVS_ALGO_PARAM(ss_iobusy_conv)
+DCVS_ALGO_PARAM(ss_win_size_min_us)
+DCVS_ALGO_PARAM(ss_win_size_max_us)
+DCVS_ALGO_PARAM(ss_util_pct)
+
+DCVS_ENERGY_PARAM(active_coeff_a)
+DCVS_ENERGY_PARAM(active_coeff_b)
+DCVS_ENERGY_PARAM(active_coeff_c)
+DCVS_ENERGY_PARAM(leakage_coeff_a)
+DCVS_ENERGY_PARAM(leakage_coeff_b)
+DCVS_ENERGY_PARAM(leakage_coeff_c)
+DCVS_ENERGY_PARAM(leakage_coeff_d)
static int msm_dcvs_setup_core_sysfs(struct dcvs_core *core)
{
int ret = 0;
struct kobject *core_kobj = NULL;
- const int attr_count = 15;
+ const int attr_count = 27;
BUG_ON(!cores_kobj);
@@ -415,23 +479,37 @@
goto done;
}
- DCVS_RO_ATTRIB(0, idle_enabled);
- DCVS_RO_ATTRIB(1, freq_change_enabled);
- DCVS_RO_ATTRIB(2, actual_freq);
- DCVS_RO_ATTRIB(3, freq_change_us);
- DCVS_RO_ATTRIB(4, max_time_us);
- DCVS_RW_ATTRIB(5, slack_time_us);
- DCVS_RW_ATTRIB(6, scale_slack_time);
- DCVS_RW_ATTRIB(7, scale_slack_time_pct);
- DCVS_RW_ATTRIB(8, disable_pc_threshold);
- DCVS_RW_ATTRIB(9, em_window_size);
- DCVS_RW_ATTRIB(10, em_max_util_pct);
- DCVS_RW_ATTRIB(11, ss_window_size);
- DCVS_RW_ATTRIB(12, ss_util_pct);
- DCVS_RW_ATTRIB(13, ss_iobusy_conv);
+ DCVS_RO_ATTRIB(0, core_id);
+ DCVS_RO_ATTRIB(1, idle_enabled);
+ DCVS_RO_ATTRIB(2, freq_change_enabled);
+ DCVS_RO_ATTRIB(3, actual_freq);
+ DCVS_RO_ATTRIB(4, freq_change_us);
- core->attrib.attrib_group.attrs[14] = NULL;
+ DCVS_RW_ATTRIB(5, disable_pc_threshold);
+ DCVS_RW_ATTRIB(6, em_win_size_min_us);
+ DCVS_RW_ATTRIB(7, em_win_size_max_us);
+ DCVS_RW_ATTRIB(8, em_max_util_pct);
+ DCVS_RW_ATTRIB(9, group_id);
+ DCVS_RW_ATTRIB(10, max_freq_chg_time_us);
+ DCVS_RW_ATTRIB(11, slack_mode_dynamic);
+ DCVS_RW_ATTRIB(12, slack_time_min_us);
+ DCVS_RW_ATTRIB(13, slack_time_max_us);
+ DCVS_RW_ATTRIB(14, slack_weight_thresh_pct);
+ DCVS_RW_ATTRIB(15, ss_iobusy_conv);
+ DCVS_RW_ATTRIB(16, ss_win_size_min_us);
+ DCVS_RW_ATTRIB(17, ss_win_size_max_us);
+ DCVS_RW_ATTRIB(18, ss_util_pct);
+
+ DCVS_RW_ATTRIB(19, active_coeff_a);
+ DCVS_RW_ATTRIB(20, active_coeff_b);
+ DCVS_RW_ATTRIB(21, active_coeff_c);
+ DCVS_RW_ATTRIB(22, leakage_coeff_a);
+ DCVS_RW_ATTRIB(23, leakage_coeff_b);
+ DCVS_RW_ATTRIB(24, leakage_coeff_c);
+ DCVS_RW_ATTRIB(25, leakage_coeff_d);
+
+ core->attrib.attrib_group.attrs[26] = NULL;
core_kobj = kobject_create_and_add(core->core_name, cores_kobj);
if (!core_kobj) {
@@ -497,11 +575,13 @@
return core;
}
-int msm_dcvs_register_core(const char *core_name, uint32_t group_id,
- struct msm_dcvs_core_info *info)
+int msm_dcvs_register_core(const char *core_name,
+ struct msm_dcvs_core_info *info, int sensor)
{
int ret = -EINVAL;
struct dcvs_core *core = NULL;
+ uint32_t ret1;
+ uint32_t ret2;
if (!core_name || !core_name[0])
return ret;
@@ -511,25 +591,18 @@
return ret;
mutex_lock(&core->lock);
- if (group_id) {
- /**
- * Create a group for cores, if this core is part of a group
- * if the group_id is 0, the core is not part of a group.
- * If the group_id already exits, it will through an error
- * which we will ignore.
- */
- ret = msm_dcvs_scm_create_group(group_id);
- if (ret == -ENOMEM)
- goto bail;
- }
- core->group_id = group_id;
- core->max_time_us = info->core_param.max_time_us;
+ core->info = info;
memcpy(&core->algo_param, &info->algo_param,
sizeof(struct msm_dcvs_algo_param));
- ret = msm_dcvs_scm_register_core(core->handle, group_id,
- &info->core_param, info->freq_tbl);
+ memcpy(&core->coeffs, &info->energy_coeffs,
+ sizeof(struct msm_dcvs_energy_curve_coeffs));
+
+ pr_debug("registering core with sensor %d\n", sensor);
+ core->sensor = sensor;
+ ret = msm_dcvs_scm_register_core(core->handle,
+ &info->core_param);
if (ret)
goto bail;
@@ -537,13 +610,25 @@
if (ret)
goto bail;
+ ret = msm_dcvs_scm_set_power_params(core->handle, &info->power_param,
+ &info->freq_tbl[0], &core->coeffs);
+ if (ret)
+ goto bail;
+
+ ret = msm_dcvs_scm_event(core->handle, MSM_DCVS_SCM_CORE_ONLINE,
+ core->actual_freq, 0, &ret1, &ret2);
+ if (ret)
+ goto bail;
+
ret = msm_dcvs_setup_core_sysfs(core);
if (ret) {
__err("Unable to setup core %s sysfs\n", core->core_name);
core_handles[core->handle - CORE_HANDLE_OFFSET] = NULL;
goto bail;
}
-
+ init_waitqueue_head(&core->wait_q);
+ core->task = kthread_run(msm_dcvs_do_freq, (void *)core,
+ "msm_dcvs/%d", core->handle);
bail:
mutex_unlock(&core->lock);
return ret;
@@ -569,8 +654,6 @@
__info("Frequency notifier for %s being replaced\n",
core->core_name);
core->freq_driver = drv;
- core->task = kthread_create(msm_dcvs_do_freq, (void *)core,
- "msm_dcvs/%d", core->handle);
if (IS_ERR(core->task)) {
mutex_unlock(&core->lock);
return -EFAULT;
@@ -582,7 +665,7 @@
if (core->idle_driver) {
core->actual_freq = core->freq_driver->get_frequency(drv);
/* Notify TZ to start receiving idle info for the core */
- ret = msm_dcvs_update_freq(core, MSM_DCVS_SCM_ENABLE_CORE, 1,
+ ret = msm_dcvs_update_freq(core, MSM_DCVS_SCM_DCVS_ENABLE, 1,
&ret1, &ret2);
core->idle_driver->enable(core->idle_driver,
MSM_DCVS_ENABLE_IDLE_PULSE);
@@ -615,7 +698,7 @@
core->idle_driver->enable(core->idle_driver,
MSM_DCVS_DISABLE_IDLE_PULSE);
/* Notify TZ to stop receiving idle info for the core */
- ret = msm_dcvs_update_freq(core, MSM_DCVS_SCM_ENABLE_CORE, 0,
+ ret = msm_dcvs_update_freq(core, MSM_DCVS_SCM_DCVS_ENABLE, 0,
&ret1, &ret2);
hrtimer_cancel(&core->timer);
core->idle_driver->enable(core->idle_driver,
@@ -623,10 +706,8 @@
if (msm_dcvs_debug & MSM_DCVS_DEBUG_IDLE_PULSE)
__info("Enabling LPM for %s\n", core->core_name);
}
- core->freq_pending = 0;
core->freq_driver = NULL;
mutex_unlock(&core->lock);
- kthread_stop(core->task);
return 0;
}
@@ -710,7 +791,7 @@
__err("Error (%d) sending idle exit for %s\n",
ret, core->core_name);
/* only start slack timer if change_freq won't */
- if (freq_changed || core->change_freq_activated)
+ if (freq_changed)
break;
if (timer_interval_us && !core->timer_disabled) {
ret = hrtimer_start(&core->timer,
diff --git a/arch/arm/mach-msm/msm_dcvs_scm.c b/arch/arm/mach-msm/msm_dcvs_scm.c
index 6095e0813..df6c44f 100644
--- a/arch/arm/mach-msm/msm_dcvs_scm.c
+++ b/arch/arm/mach-msm/msm_dcvs_scm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -21,17 +21,15 @@
#include <mach/scm.h>
#include <mach/msm_dcvs_scm.h>
-#define DCVS_CMD_CREATE_GROUP 1
#define DCVS_CMD_REGISTER_CORE 2
#define DCVS_CMD_SET_ALGO_PARAM 3
#define DCVS_CMD_EVENT 4
#define DCVS_CMD_INIT 5
+#define DCVS_CMD_SET_POWER_PARAM 6
struct scm_register_core {
uint32_t core_id;
- uint32_t group_id;
phys_addr_t core_param_phy;
- phys_addr_t freq_phy;
};
struct scm_algo {
@@ -44,6 +42,21 @@
uint32_t size;
};
+struct scm_pwr_param {
+ uint32_t core_id;
+ phys_addr_t pwr_param_phy;
+ phys_addr_t freq_phy;
+ phys_addr_t coeffs_phy;
+};
+
+struct msm_algo_param {
+ enum msm_dcvs_algo_param_type type;
+ union {
+ struct msm_dcvs_algo_param dcvs_param;
+ struct msm_mpd_algo_param mpd_param;
+ } u;
+};
+
int msm_dcvs_scm_init(size_t size)
{
int ret = 0;
@@ -69,49 +82,25 @@
}
EXPORT_SYMBOL(msm_dcvs_scm_init);
-int msm_dcvs_scm_create_group(uint32_t id)
-{
- int ret = 0;
-
- ret = scm_call(SCM_SVC_DCVS, DCVS_CMD_CREATE_GROUP,
- &id, sizeof(uint32_t), NULL, 0);
-
- return ret;
-}
-EXPORT_SYMBOL(msm_dcvs_scm_create_group);
-
-int msm_dcvs_scm_register_core(uint32_t core_id, uint32_t group_id,
- struct msm_dcvs_core_param *param,
- struct msm_dcvs_freq_entry *freq)
+int msm_dcvs_scm_register_core(uint32_t core_id,
+ struct msm_dcvs_core_param *param)
{
int ret = 0;
struct scm_register_core reg_data;
struct msm_dcvs_core_param *p = NULL;
- struct msm_dcvs_freq_entry *f = NULL;
p = kzalloc(PAGE_ALIGN(sizeof(struct msm_dcvs_core_param)), GFP_KERNEL);
if (!p)
return -ENOMEM;
- f = kzalloc(PAGE_ALIGN(sizeof(struct msm_dcvs_freq_entry) *
- param->num_freq), GFP_KERNEL);
- if (!f) {
- kfree(p);
- return -ENOMEM;
- }
-
memcpy(p, param, sizeof(struct msm_dcvs_core_param));
- memcpy(f, freq, sizeof(struct msm_dcvs_freq_entry) * param->num_freq);
reg_data.core_id = core_id;
- reg_data.group_id = group_id;
reg_data.core_param_phy = virt_to_phys(p);
- reg_data.freq_phy = virt_to_phys(f);
ret = scm_call(SCM_SVC_DCVS, DCVS_CMD_REGISTER_CORE,
®_data, sizeof(reg_data), NULL, 0);
- kfree(f);
kfree(p);
return ret;
@@ -123,13 +112,14 @@
{
int ret = 0;
struct scm_algo algo;
- struct msm_dcvs_algo_param *p = NULL;
+ struct msm_algo_param *p = NULL;
- p = kzalloc(PAGE_ALIGN(sizeof(struct msm_dcvs_algo_param)), GFP_KERNEL);
+ p = kzalloc(PAGE_ALIGN(sizeof(struct msm_algo_param)), GFP_KERNEL);
if (!p)
return -ENOMEM;
- memcpy(p, param, sizeof(struct msm_dcvs_algo_param));
+ p->type = MSM_DCVS_ALGO_DCVS_PARAM;
+ memcpy(&p->u.dcvs_param, param, sizeof(struct msm_dcvs_algo_param));
algo.core_id = core_id;
algo.algo_phy = virt_to_phys(p);
@@ -143,6 +133,85 @@
}
EXPORT_SYMBOL(msm_dcvs_scm_set_algo_params);
+int msm_mpd_scm_set_algo_params(struct msm_mpd_algo_param *param)
+{
+ int ret = 0;
+ struct scm_algo algo;
+ struct msm_algo_param *p = NULL;
+
+ p = kzalloc(PAGE_ALIGN(sizeof(struct msm_algo_param)), GFP_KERNEL);
+ if (!p)
+ return -ENOMEM;
+
+ p->type = MSM_DCVS_ALGO_MPD_PARAM;
+ memcpy(&p->u.mpd_param, param, sizeof(struct msm_mpd_algo_param));
+
+ algo.core_id = 0;
+ algo.algo_phy = virt_to_phys(p);
+
+ ret = scm_call(SCM_SVC_DCVS, DCVS_CMD_SET_ALGO_PARAM,
+ &algo, sizeof(algo), NULL, 0);
+
+ kfree(p);
+
+ return ret;
+}
+EXPORT_SYMBOL(msm_mpd_scm_set_algo_params);
+
+int msm_dcvs_scm_set_power_params(uint32_t core_id,
+ struct msm_dcvs_power_params *pwr_param,
+ struct msm_dcvs_freq_entry *freq_entry,
+ struct msm_dcvs_energy_curve_coeffs *coeffs)
+{
+ int ret = 0;
+ struct scm_pwr_param pwr;
+ struct msm_dcvs_power_params *pwrt = NULL;
+ struct msm_dcvs_freq_entry *freqt = NULL;
+ struct msm_dcvs_energy_curve_coeffs *coefft = NULL;
+
+ pwrt = kzalloc(PAGE_ALIGN(sizeof(struct msm_dcvs_power_params)),
+ GFP_KERNEL);
+ if (!pwrt)
+ return -ENOMEM;
+
+ freqt = kzalloc(PAGE_ALIGN(sizeof(struct msm_dcvs_freq_entry)
+ * pwr_param->num_freq),
+ GFP_KERNEL);
+ if (!freqt) {
+ kfree(pwrt);
+ return -ENOMEM;
+ }
+
+ coefft = kzalloc(PAGE_ALIGN(
+ sizeof(struct msm_dcvs_energy_curve_coeffs)),
+ GFP_KERNEL);
+ if (!coefft) {
+ kfree(pwrt);
+ kfree(freqt);
+ return -ENOMEM;
+ }
+
+ memcpy(pwrt, pwr_param, sizeof(struct msm_dcvs_power_params));
+ memcpy(freqt, freq_entry,
+ sizeof(struct msm_dcvs_freq_entry)*pwr_param->num_freq);
+ memcpy(coefft, coeffs, sizeof(struct msm_dcvs_energy_curve_coeffs));
+
+ pwr.core_id = core_id;
+ pwr.pwr_param_phy = virt_to_phys(pwrt);
+ pwr.freq_phy = virt_to_phys(freqt);
+ pwr.coeffs_phy = virt_to_phys(coefft);
+
+ ret = scm_call(SCM_SVC_DCVS, DCVS_CMD_SET_POWER_PARAM,
+ &pwr, sizeof(pwr), NULL, 0);
+
+ kfree(pwrt);
+ kfree(freqt);
+ kfree(coefft);
+
+ return ret;
+}
+EXPORT_SYMBOL(msm_dcvs_scm_set_power_params);
+
int msm_dcvs_scm_event(uint32_t core_id,
enum msm_dcvs_scm_event event_id,
uint32_t param0, uint32_t param1,
diff --git a/arch/arm/mach-msm/msm_mpdecision.c b/arch/arm/mach-msm/msm_mpdecision.c
new file mode 100644
index 0000000..056e4eb
--- /dev/null
+++ b/arch/arm/mach-msm/msm_mpdecision.c
@@ -0,0 +1,707 @@
+ /* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "mpd %s: " fmt, __func__
+
+#include <linux/cpumask.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/kthread.h>
+#include <linux/kobject.h>
+#include <linux/ktime.h>
+#include <linux/hrtimer.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/cpu.h>
+#include <linux/stringify.h>
+#include <linux/sched.h>
+#include <linux/platform_device.h>
+#include <linux/debugfs.h>
+#include <linux/cpu_pm.h>
+#include <linux/cpu.h>
+#include <linux/cpufreq.h>
+#include <linux/sched.h>
+#include <linux/rq_stats.h>
+#include <asm/atomic.h>
+#include <asm/page.h>
+#include <mach/msm_dcvs.h>
+#include <mach/msm_dcvs_scm.h>
+
+#define DEFAULT_RQ_AVG_POLL_MS (1)
+
+struct mpd_attrib {
+ struct kobj_attribute enabled;
+ struct kobj_attribute rq_avg_poll_ms;
+ struct kobj_attribute iowait_threshold_pct;
+
+ struct kobj_attribute em_win_size_min_us;
+ struct kobj_attribute em_win_size_max_us;
+ struct kobj_attribute em_max_util_pct;
+ struct kobj_attribute mp_em_rounding_point_min;
+ struct kobj_attribute mp_em_rounding_point_max;
+ struct kobj_attribute online_util_pct_min;
+ struct kobj_attribute online_util_pct_max;
+ struct kobj_attribute slack_time_min_us;
+ struct kobj_attribute slack_time_max_us;
+ struct kobj_attribute hp_up_max_ms;
+ struct kobj_attribute hp_up_ms;
+ struct kobj_attribute hp_up_count;
+ struct kobj_attribute hp_dw_max_ms;
+ struct kobj_attribute hp_dw_ms;
+ struct kobj_attribute hp_dw_count;
+ struct attribute_group attrib_group;
+};
+
+struct msm_mpd_scm_data {
+ enum msm_dcvs_scm_event event;
+ int nr;
+};
+
+struct mpdecision {
+ uint32_t enabled;
+ atomic_t algo_cpu_mask;
+ uint32_t rq_avg_poll_ms;
+ uint32_t iowait_threshold_pct;
+ ktime_t next_update;
+ uint32_t slack_us;
+ struct msm_mpd_algo_param mp_param;
+ struct mpd_attrib attrib;
+ struct mutex lock;
+ struct task_struct *task;
+ struct task_struct *hptask;
+ struct hrtimer slack_timer;
+ struct msm_mpd_scm_data data;
+ int hpupdate;
+ wait_queue_head_t wait_q;
+ wait_queue_head_t wait_hpq;
+};
+
+struct hp_latency {
+ int hp_up_max_ms;
+ int hp_up_ms;
+ int hp_up_count;
+ int hp_dw_max_ms;
+ int hp_dw_ms;
+ int hp_dw_count;
+};
+
+static DEFINE_PER_CPU(struct hrtimer, rq_avg_poll_timer);
+static DEFINE_SPINLOCK(rq_avg_lock);
+
+enum {
+ MSM_MPD_DEBUG_NOTIFIER = BIT(0),
+ MSM_MPD_CORE_STATUS = BIT(1),
+ MSM_MPD_SLACK_TIMER = BIT(2),
+};
+
+enum {
+ HPUPDATE_WAITING = 0, /* we are waiting for cpumask update */
+ HPUPDATE_SCHEDULED = 1, /* we are in the process of hotplugging */
+ HPUPDATE_IN_PROGRESS = 2, /* we are in the process of hotplugging */
+};
+
+static int msm_mpd_enabled = 1;
+module_param_named(enabled, msm_mpd_enabled, int, S_IRUGO | S_IWUSR | S_IWGRP);
+
+static struct dentry *debugfs_base;
+static struct mpdecision msm_mpd;
+
+static struct hp_latency hp_latencies;
+
+static unsigned long last_nr;
+static int num_present_hundreds;
+
+#define RQ_AVG_INSIGNIFICANT_BITS 3
+static bool ok_to_update_tz(int nr, int last_nr)
+{
+ /*
+ * Exclude unnecessary TZ reports if run queue haven't changed much from
+ * the last reported value. The left shift by INSIGNIFICANT_BITS is to
+ * filter out small changes in the run queue average which won't cause
+ * a online cpu mask change. Also if the cpu online count does not match
+ * the count requested by TZ and we are not in the process of bringing
+ * cpus online as indicated by a HPUPDATE_IN_PROGRESS in msm_mpd.hpdata
+ */
+ return
+ (((nr >> RQ_AVG_INSIGNIFICANT_BITS)
+ != (last_nr >> RQ_AVG_INSIGNIFICANT_BITS))
+ || ((hweight32(atomic_read(&msm_mpd.algo_cpu_mask))
+ != num_online_cpus())
+ && (msm_mpd.hpupdate != HPUPDATE_IN_PROGRESS)));
+}
+
+static enum hrtimer_restart msm_mpd_rq_avg_poll_timer(struct hrtimer *timer)
+{
+ int nr, nr_iowait;
+ ktime_t curr_time = ktime_get();
+ unsigned long flags;
+ int cpu = smp_processor_id();
+ enum hrtimer_restart restart = HRTIMER_RESTART;
+
+ spin_lock_irqsave(&rq_avg_lock, flags);
+ /* If running on the wrong cpu, don't restart */
+ if (&per_cpu(rq_avg_poll_timer, cpu) != timer)
+ restart = HRTIMER_NORESTART;
+
+ if (ktime_to_ns(ktime_sub(curr_time, msm_mpd.next_update)) < 0)
+ goto out;
+
+ msm_mpd.next_update = ktime_add_ns(curr_time,
+ (msm_mpd.rq_avg_poll_ms * NSEC_PER_MSEC));
+
+ sched_get_nr_running_avg(&nr, &nr_iowait);
+
+ if ((nr_iowait >= msm_mpd.iowait_threshold_pct) && (nr < last_nr))
+ nr = last_nr;
+
+ if (nr > num_present_hundreds)
+ nr = num_present_hundreds;
+
+ if (ok_to_update_tz(nr, last_nr)) {
+ hrtimer_try_to_cancel(&msm_mpd.slack_timer);
+ msm_mpd.data.nr = nr;
+ msm_mpd.data.event = MSM_DCVS_SCM_RUNQ_UPDATE;
+ wake_up(&msm_mpd.wait_q);
+ last_nr = nr;
+ }
+
+out:
+ hrtimer_set_expires(timer, msm_mpd.next_update);
+ spin_unlock_irqrestore(&rq_avg_lock, flags);
+ /* set next expiration */
+ return restart;
+}
+
+static void bring_up_cpu(int cpu)
+{
+ int cpu_action_time_ms;
+ int time_taken_ms;
+ int ret, ret1, ret2;
+
+ cpu_action_time_ms = ktime_to_ms(ktime_get());
+ ret = cpu_up(cpu);
+ if (ret) {
+ pr_debug("Error %d online core %d\n", ret, cpu);
+ } else {
+ time_taken_ms = ktime_to_ms(ktime_get()) - cpu_action_time_ms;
+ if (time_taken_ms > hp_latencies.hp_up_max_ms)
+ hp_latencies.hp_up_max_ms = time_taken_ms;
+ if (time_taken_ms > 5)
+ pr_warn("cpu_up for cpu%d exceeded 5ms (%d)\n",
+ cpu, time_taken_ms);
+ hp_latencies.hp_up_ms += time_taken_ms;
+ hp_latencies.hp_up_count++;
+ ret = msm_dcvs_scm_event(
+ CPU_OFFSET + cpu,
+ MSM_DCVS_SCM_CORE_ONLINE,
+ cpufreq_get(cpu),
+ (uint32_t) time_taken_ms * USEC_PER_MSEC,
+ &ret1, &ret2);
+ if (ret)
+ pr_err("Error sending hotplug scm event err=%d\n", ret);
+ }
+}
+
+static void bring_down_cpu(int cpu)
+{
+ int cpu_action_time_ms;
+ int time_taken_ms;
+ int ret, ret1, ret2;
+
+ BUG_ON(cpu == 0);
+ cpu_action_time_ms = ktime_to_ms(ktime_get());
+ ret = cpu_down(cpu);
+ if (ret) {
+ pr_debug("Error %d offline" "core %d\n", ret, cpu);
+ } else {
+ time_taken_ms = ktime_to_ms(ktime_get()) - cpu_action_time_ms;
+ if (time_taken_ms > hp_latencies.hp_dw_max_ms)
+ hp_latencies.hp_dw_max_ms = time_taken_ms;
+ if (time_taken_ms > 5)
+ pr_warn("cpu_down for cpu%d exceeded 5ms (%d)\n",
+ cpu, time_taken_ms);
+ hp_latencies.hp_dw_ms += time_taken_ms;
+ hp_latencies.hp_dw_count++;
+ ret = msm_dcvs_scm_event(
+ CPU_OFFSET + cpu,
+ MSM_DCVS_SCM_CORE_OFFLINE,
+ (uint32_t) time_taken_ms * USEC_PER_MSEC,
+ 0,
+ &ret1, &ret2);
+ if (ret)
+ pr_err("Error sending hotplug scm event err=%d\n", ret);
+ }
+}
+
+static int __ref msm_mpd_update_scm(enum msm_dcvs_scm_event event, int nr)
+{
+ int ret = 0;
+ uint32_t req_cpu_mask = 0;
+ uint32_t slack_us = 0;
+ uint32_t param0 = 0;
+
+ if (event == MSM_DCVS_SCM_RUNQ_UPDATE)
+ param0 = nr;
+
+ ret = msm_dcvs_scm_event(0, event, param0, 0,
+ &req_cpu_mask, &slack_us);
+
+ if (ret) {
+ pr_err("Error (%d) sending event %d, param %d\n", ret, event,
+ param0);
+ return ret;
+ }
+
+ msm_mpd.slack_us = slack_us;
+ atomic_set(&msm_mpd.algo_cpu_mask, req_cpu_mask);
+ msm_mpd.hpupdate = HPUPDATE_SCHEDULED;
+ wake_up(&msm_mpd.wait_hpq);
+
+ /* Start MP Decision slack timer */
+ if (slack_us) {
+ hrtimer_cancel(&msm_mpd.slack_timer);
+ ret = hrtimer_start(&msm_mpd.slack_timer,
+ ktime_set(0, slack_us * NSEC_PER_USEC),
+ HRTIMER_MODE_REL_PINNED);
+ if (ret)
+ pr_err("Failed to register slack timer (%d) %d\n",
+ slack_us, ret);
+ }
+
+ return ret;
+}
+
+static enum hrtimer_restart msm_mpd_slack_timer(struct hrtimer *timer)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&rq_avg_lock, flags);
+ if (msm_mpd.data.event == MSM_DCVS_SCM_RUNQ_UPDATE)
+ goto out;
+
+ msm_mpd.data.nr = 0;
+ msm_mpd.data.event = MSM_DCVS_SCM_MPD_QOS_TIMER_EXPIRED;
+ wake_up(&msm_mpd.wait_q);
+out:
+ spin_unlock_irqrestore(&rq_avg_lock, flags);
+ return HRTIMER_NORESTART;
+}
+
+static int msm_mpd_idle_notifier(struct notifier_block *self,
+ unsigned long cmd, void *v)
+{
+ int cpu = smp_processor_id();
+ unsigned long flags;
+
+ switch (cmd) {
+ case CPU_PM_EXIT:
+ spin_lock_irqsave(&rq_avg_lock, flags);
+ hrtimer_start(&per_cpu(rq_avg_poll_timer, cpu),
+ msm_mpd.next_update,
+ HRTIMER_MODE_ABS_PINNED);
+ spin_unlock_irqrestore(&rq_avg_lock, flags);
+ break;
+ case CPU_PM_ENTER:
+ hrtimer_cancel(&per_cpu(rq_avg_poll_timer, cpu));
+ break;
+ default:
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static int msm_mpd_hotplug_notifier(struct notifier_block *self,
+ unsigned long action, void *hcpu)
+{
+ int cpu = (int)hcpu;
+ unsigned long flags;
+
+ switch (action & (~CPU_TASKS_FROZEN)) {
+ case CPU_STARTING:
+ spin_lock_irqsave(&rq_avg_lock, flags);
+ hrtimer_start(&per_cpu(rq_avg_poll_timer, cpu),
+ msm_mpd.next_update,
+ HRTIMER_MODE_ABS_PINNED);
+ spin_unlock_irqrestore(&rq_avg_lock, flags);
+ break;
+ default:
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block msm_mpd_idle_nb = {
+ .notifier_call = msm_mpd_idle_notifier,
+};
+
+static struct notifier_block msm_mpd_hotplug_nb = {
+ .notifier_call = msm_mpd_hotplug_notifier,
+};
+
+static int __cpuinit msm_mpd_do_hotplug(void *data)
+{
+ int *event = (int *)data;
+ static struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1};
+ int cpu;
+
+ sched_setscheduler(current, SCHED_FIFO, ¶m);
+
+ while (1) {
+ wait_event(msm_mpd.wait_hpq, *event || kthread_should_stop());
+ if (kthread_should_stop())
+ break;
+
+ msm_mpd.hpupdate = HPUPDATE_IN_PROGRESS;
+ /*
+ * Bring online any offline cores, then offline any online
+ * cores. Whenever a core is off/onlined restart the procedure
+ * in case a new core is desired to be brought online in the
+ * mean time.
+ */
+restart:
+ for_each_possible_cpu(cpu) {
+ if ((atomic_read(&msm_mpd.algo_cpu_mask) & (1 << cpu))
+ && !cpu_online(cpu)) {
+ bring_up_cpu(cpu);
+ if (cpu_online(cpu))
+ goto restart;
+ }
+ }
+
+ for_each_possible_cpu(cpu) {
+ if (!(atomic_read(&msm_mpd.algo_cpu_mask) & (1 << cpu))
+ && cpu_online(cpu)) {
+ bring_down_cpu(cpu);
+ if (!cpu_online(cpu))
+ goto restart;
+ }
+ }
+ msm_mpd.hpupdate = HPUPDATE_WAITING;
+ }
+
+ return 0;
+}
+
+static int msm_mpd_do_update_scm(void *data)
+{
+ struct msm_mpd_scm_data *scm_data = (struct msm_mpd_scm_data *)data;
+ static struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1};
+ unsigned long flags;
+ enum msm_dcvs_scm_event event;
+ int nr;
+
+ sched_setscheduler(current, SCHED_FIFO, ¶m);
+
+ while (1) {
+ wait_event(msm_mpd.wait_q,
+ msm_mpd.data.event == MSM_DCVS_SCM_MPD_QOS_TIMER_EXPIRED
+ || msm_mpd.data.event == MSM_DCVS_SCM_RUNQ_UPDATE
+ || kthread_should_stop());
+
+ if (kthread_should_stop())
+ break;
+
+ spin_lock_irqsave(&rq_avg_lock, flags);
+ event = scm_data->event;
+ nr = scm_data->nr;
+ scm_data->event = 0;
+ scm_data->nr = 0;
+ spin_unlock_irqrestore(&rq_avg_lock, flags);
+
+ msm_mpd_update_scm(event, nr);
+ }
+ return 0;
+}
+
+static int __ref msm_mpd_set_enabled(uint32_t enable)
+{
+ int ret = 0;
+ int ret0 = 0;
+ int ret1 = 0;
+ int cpu;
+ static uint32_t last_enable;
+
+ enable = (enable > 0) ? 1 : 0;
+ if (last_enable == enable)
+ return ret;
+
+ if (enable) {
+ ret = msm_mpd_scm_set_algo_params(&msm_mpd.mp_param);
+ if (ret) {
+ pr_err("Error(%d): msm_mpd_scm_set_algo_params failed\n",
+ ret);
+ return ret;
+ }
+ }
+
+ ret = msm_dcvs_scm_event(0, MSM_DCVS_SCM_MPD_ENABLE, enable, 0,
+ &ret0, &ret1);
+ if (ret) {
+ pr_err("Error(%d) %s MP Decision\n",
+ ret, (enable ? "enabling" : "disabling"));
+ } else {
+ last_enable = enable;
+ last_nr = 0;
+ }
+ if (enable) {
+ msm_mpd.next_update = ktime_add_ns(ktime_get(),
+ (msm_mpd.rq_avg_poll_ms * NSEC_PER_MSEC));
+ msm_mpd.task = kthread_run(msm_mpd_do_update_scm,
+ &msm_mpd.data, "msm_mpdecision");
+ if (IS_ERR(msm_mpd.task))
+ return -EFAULT;
+
+ msm_mpd.hptask = kthread_run(msm_mpd_do_hotplug,
+ &msm_mpd.hpupdate, "msm_hp");
+ if (IS_ERR(msm_mpd.hptask))
+ return -EFAULT;
+
+ for_each_online_cpu(cpu)
+ hrtimer_start(&per_cpu(rq_avg_poll_timer, cpu),
+ msm_mpd.next_update,
+ HRTIMER_MODE_ABS_PINNED);
+ cpu_pm_register_notifier(&msm_mpd_idle_nb);
+ register_cpu_notifier(&msm_mpd_hotplug_nb);
+ msm_mpd.enabled = 1;
+ } else {
+ for_each_online_cpu(cpu)
+ hrtimer_cancel(&per_cpu(rq_avg_poll_timer, cpu));
+ kthread_stop(msm_mpd.hptask);
+ kthread_stop(msm_mpd.task);
+ cpu_pm_unregister_notifier(&msm_mpd_idle_nb);
+ unregister_cpu_notifier(&msm_mpd_hotplug_nb);
+ msm_mpd.enabled = 0;
+ }
+
+ return ret;
+}
+
+static int msm_mpd_set_rq_avg_poll_ms(uint32_t val)
+{
+ /*
+ * No need to do anything. Just let the timer set its own next poll
+ * interval when it next fires.
+ */
+ msm_mpd.rq_avg_poll_ms = val;
+ return 0;
+}
+
+static int msm_mpd_set_iowait_threshold_pct(uint32_t val)
+{
+ /*
+ * No need to do anything. Just let the timer set its own next poll
+ * interval when it next fires.
+ */
+ msm_mpd.iowait_threshold_pct = val;
+ return 0;
+}
+
+#define MPD_ALGO_PARAM(_name, _param) \
+static ssize_t msm_mpd_attr_##_name##_show(struct kobject *kobj, \
+ struct kobj_attribute *attr, char *buf) \
+{ \
+ return snprintf(buf, PAGE_SIZE, "%d\n", _param); \
+} \
+static ssize_t msm_mpd_attr_##_name##_store(struct kobject *kobj, \
+ struct kobj_attribute *attr, const char *buf, size_t count) \
+{ \
+ int ret = 0; \
+ uint32_t val; \
+ uint32_t old_val; \
+ mutex_lock(&msm_mpd.lock); \
+ ret = kstrtouint(buf, 10, &val); \
+ if (ret) { \
+ pr_err("Invalid input %s for %s %d\n", \
+ buf, __stringify(_name), ret);\
+ return 0; \
+ } \
+ old_val = _param; \
+ _param = val; \
+ ret = msm_mpd_scm_set_algo_params(&msm_mpd.mp_param); \
+ if (ret) { \
+ pr_err("Error %d returned when setting algo param %s to %d\n",\
+ ret, __stringify(_name), val); \
+ _param = old_val; \
+ } \
+ mutex_unlock(&msm_mpd.lock); \
+ return count; \
+}
+
+#define MPD_PARAM(_name, _param) \
+static ssize_t msm_mpd_attr_##_name##_show(struct kobject *kobj, \
+ struct kobj_attribute *attr, char *buf) \
+{ \
+ return snprintf(buf, PAGE_SIZE, "%d\n", _param); \
+} \
+static ssize_t msm_mpd_attr_##_name##_store(struct kobject *kobj, \
+ struct kobj_attribute *attr, const char *buf, size_t count) \
+{ \
+ int ret = 0; \
+ uint32_t val; \
+ uint32_t old_val; \
+ mutex_lock(&msm_mpd.lock); \
+ ret = kstrtouint(buf, 10, &val); \
+ if (ret) { \
+ pr_err("Invalid input %s for %s %d\n", \
+ buf, __stringify(_name), ret);\
+ return 0; \
+ } \
+ old_val = _param; \
+ ret = msm_mpd_set_##_name(val); \
+ if (ret) { \
+ pr_err("Error %d returned when setting algo param %s to %d\n",\
+ ret, __stringify(_name), val); \
+ _param = old_val; \
+ } \
+ mutex_unlock(&msm_mpd.lock); \
+ return count; \
+}
+
+#define MPD_RW_ATTRIB(i, _name) \
+ msm_mpd.attrib._name.attr.name = __stringify(_name); \
+ msm_mpd.attrib._name.attr.mode = S_IRUGO | S_IWUSR; \
+ msm_mpd.attrib._name.show = msm_mpd_attr_##_name##_show; \
+ msm_mpd.attrib._name.store = msm_mpd_attr_##_name##_store; \
+ msm_mpd.attrib.attrib_group.attrs[i] = &msm_mpd.attrib._name.attr;
+
+MPD_PARAM(enabled, msm_mpd.enabled);
+MPD_PARAM(rq_avg_poll_ms, msm_mpd.rq_avg_poll_ms);
+MPD_PARAM(iowait_threshold_pct, msm_mpd.iowait_threshold_pct);
+MPD_ALGO_PARAM(em_win_size_min_us, msm_mpd.mp_param.em_win_size_min_us);
+MPD_ALGO_PARAM(em_win_size_max_us, msm_mpd.mp_param.em_win_size_max_us);
+MPD_ALGO_PARAM(em_max_util_pct, msm_mpd.mp_param.em_max_util_pct);
+MPD_ALGO_PARAM(mp_em_rounding_point_min,
+ msm_mpd.mp_param.mp_em_rounding_point_min);
+MPD_ALGO_PARAM(mp_em_rounding_point_max,
+ msm_mpd.mp_param.mp_em_rounding_point_max);
+MPD_ALGO_PARAM(online_util_pct_min, msm_mpd.mp_param.online_util_pct_min);
+MPD_ALGO_PARAM(online_util_pct_max, msm_mpd.mp_param.online_util_pct_max);
+MPD_ALGO_PARAM(slack_time_min_us, msm_mpd.mp_param.slack_time_min_us);
+MPD_ALGO_PARAM(slack_time_max_us, msm_mpd.mp_param.slack_time_max_us);
+MPD_ALGO_PARAM(hp_up_max_ms, hp_latencies.hp_up_max_ms);
+MPD_ALGO_PARAM(hp_up_ms, hp_latencies.hp_up_ms);
+MPD_ALGO_PARAM(hp_up_count, hp_latencies.hp_up_count);
+MPD_ALGO_PARAM(hp_dw_max_ms, hp_latencies.hp_dw_max_ms);
+MPD_ALGO_PARAM(hp_dw_ms, hp_latencies.hp_dw_ms);
+MPD_ALGO_PARAM(hp_dw_count, hp_latencies.hp_dw_count);
+
+static int __devinit msm_mpd_probe(struct platform_device *pdev)
+{
+ struct kobject *module_kobj = NULL;
+ int ret = 0;
+ const int attr_count = 19;
+ struct msm_mpd_algo_param *param = NULL;
+
+ param = pdev->dev.platform_data;
+
+ module_kobj = kset_find_obj(module_kset, KBUILD_MODNAME);
+ if (!module_kobj) {
+ pr_err("Cannot find kobject for module %s\n", KBUILD_MODNAME);
+ ret = -ENOENT;
+ goto done;
+ }
+
+ msm_mpd.attrib.attrib_group.attrs =
+ kzalloc(attr_count * sizeof(struct attribute *), GFP_KERNEL);
+ if (!msm_mpd.attrib.attrib_group.attrs) {
+ ret = -ENOMEM;
+ goto done;
+ }
+
+ MPD_RW_ATTRIB(0, enabled);
+ MPD_RW_ATTRIB(1, rq_avg_poll_ms);
+ MPD_RW_ATTRIB(2, iowait_threshold_pct);
+ MPD_RW_ATTRIB(3, em_win_size_min_us);
+ MPD_RW_ATTRIB(4, em_win_size_max_us);
+ MPD_RW_ATTRIB(5, em_max_util_pct);
+ MPD_RW_ATTRIB(6, mp_em_rounding_point_min);
+ MPD_RW_ATTRIB(7, mp_em_rounding_point_max);
+ MPD_RW_ATTRIB(8, online_util_pct_min);
+ MPD_RW_ATTRIB(9, online_util_pct_max);
+ MPD_RW_ATTRIB(10, slack_time_min_us);
+ MPD_RW_ATTRIB(11, slack_time_max_us);
+ MPD_RW_ATTRIB(12, hp_up_max_ms);
+ MPD_RW_ATTRIB(13, hp_up_ms);
+ MPD_RW_ATTRIB(14, hp_up_count);
+ MPD_RW_ATTRIB(15, hp_dw_max_ms);
+ MPD_RW_ATTRIB(16, hp_dw_ms);
+ MPD_RW_ATTRIB(17, hp_dw_count);
+
+ msm_mpd.attrib.attrib_group.attrs[18] = NULL;
+ ret = sysfs_create_group(module_kobj, &msm_mpd.attrib.attrib_group);
+ if (ret)
+ pr_err("Unable to create sysfs objects :%d\n", ret);
+
+ msm_mpd.rq_avg_poll_ms = DEFAULT_RQ_AVG_POLL_MS;
+
+ memcpy(&msm_mpd.mp_param, param, sizeof(struct msm_mpd_algo_param));
+
+ debugfs_base = debugfs_create_dir("msm_mpdecision", NULL);
+ if (!debugfs_base) {
+ pr_err("Cannot create debugfs base msm_mpdecision\n");
+ ret = -ENOENT;
+ goto done;
+ }
+
+done:
+ if (ret && debugfs_base)
+ debugfs_remove(debugfs_base);
+
+ return ret;
+}
+
+static int __devexit msm_mpd_remove(struct platform_device *pdev)
+{
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+static struct platform_driver msm_mpd_driver = {
+ .probe = msm_mpd_probe,
+ .remove = __devexit_p(msm_mpd_remove),
+ .driver = {
+ .name = "msm_mpdecision",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init msm_mpdecision_init(void)
+{
+ int cpu;
+ if (!msm_mpd_enabled) {
+ pr_info("Not enabled\n");
+ return 0;
+ }
+
+ num_present_hundreds = 100 * num_present_cpus();
+
+ hrtimer_init(&msm_mpd.slack_timer, CLOCK_MONOTONIC,
+ HRTIMER_MODE_REL_PINNED);
+ msm_mpd.slack_timer.function = msm_mpd_slack_timer;
+
+ for_each_possible_cpu(cpu) {
+ hrtimer_init(&per_cpu(rq_avg_poll_timer, cpu),
+ CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED);
+ per_cpu(rq_avg_poll_timer, cpu).function
+ = msm_mpd_rq_avg_poll_timer;
+ }
+ mutex_init(&msm_mpd.lock);
+ init_waitqueue_head(&msm_mpd.wait_q);
+ init_waitqueue_head(&msm_mpd.wait_hpq);
+ return platform_driver_register(&msm_mpd_driver);
+}
+late_initcall(msm_mpdecision_init);
diff --git a/arch/arm/mach-msm/msm_xo.c b/arch/arm/mach-msm/msm_xo.c
index 2d61504..404b350 100644
--- a/arch/arm/mach-msm/msm_xo.c
+++ b/arch/arm/mach-msm/msm_xo.c
@@ -236,7 +236,7 @@
int needs_workaround = cpu_is_msm8960() || cpu_is_apq8064() ||
cpu_is_msm8930() || cpu_is_msm8930aa() ||
cpu_is_msm9615() || cpu_is_msm8627() ||
- cpu_is_msm8960ab();
+ cpu_is_msm8960ab() || cpu_is_apq8064ab();
if (xo_voter->mode == mode)
return 0;
diff --git a/arch/arm/mach-msm/peripheral-loader.h b/arch/arm/mach-msm/peripheral-loader.h
index e3b250b..405b73f 100644
--- a/arch/arm/mach-msm/peripheral-loader.h
+++ b/arch/arm/mach-msm/peripheral-loader.h
@@ -55,7 +55,15 @@
struct pil_device;
+#ifdef CONFIG_MSM_PIL
extern struct pil_device *msm_pil_register(struct pil_desc *desc);
extern void msm_pil_unregister(struct pil_device *pil);
+#else
+static inline struct pil_device *msm_pil_register(struct pil_desc *desc)
+{
+ return NULL;
+}
+static inline void msm_pil_unregister(struct pil_device *pil) { }
+#endif
#endif
diff --git a/arch/arm/mach-msm/pil-gss.c b/arch/arm/mach-msm/pil-gss.c
index 73248db..bccbce2 100644
--- a/arch/arm/mach-msm/pil-gss.c
+++ b/arch/arm/mach-msm/pil-gss.c
@@ -21,15 +21,22 @@
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/smp.h>
+#include <linux/miscdevice.h>
+#include <linux/reboot.h>
+#include <linux/interrupt.h>
#include <mach/msm_iomap.h>
#include <mach/msm_xo.h>
#include <mach/socinfo.h>
#include <mach/msm_bus_board.h>
#include <mach/msm_bus.h>
+#include <mach/subsystem_restart.h>
+#include <mach/peripheral-loader.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
+#include "smd_private.h"
+#include "ramdump.h"
#define GSS_CSR_AHB_CLK_SEL 0x0
#define GSS_CSR_RESET 0x4
@@ -63,6 +70,14 @@
unsigned long start_addr;
struct clk *xo;
struct pil_device *pil;
+ struct miscdevice misc_dev;
+ struct subsys_device *subsys;
+ struct subsys_desc subsys_desc;
+ int crash_shutdown;
+ int irq;
+ void *pil_handle;
+ struct ramdump_device *ramdump_dev;
+ struct ramdump_device *smem_ramdump_dev;
};
static int pil_gss_init_image(struct pil_desc *pil, const u8 *metadata,
@@ -308,11 +323,160 @@
.proxy_unvote = remove_gss_proxy_votes,
};
+#define MAX_SSR_REASON_LEN 81U
+
+static void log_gss_sfr(void)
+{
+ u32 size;
+ char *smem_reason, reason[MAX_SSR_REASON_LEN];
+
+ smem_reason = smem_get_entry(SMEM_SSR_REASON_MSS0, &size);
+ if (!smem_reason || !size) {
+ pr_err("GSS subsystem failure reason: (unknown, smem_get_entry failed).\n");
+ return;
+ }
+ if (!smem_reason[0]) {
+ pr_err("GSS subsystem failure reason: (unknown, init string found).\n");
+ return;
+ }
+
+ size = min(size, MAX_SSR_REASON_LEN-1);
+ memcpy(reason, smem_reason, size);
+ reason[size] = '\0';
+ pr_err("GSS subsystem failure reason: %s.\n", reason);
+
+ smem_reason[0] = '\0';
+ wmb();
+}
+
+static void restart_gss(struct gss_data *drv)
+{
+ log_gss_sfr();
+ subsystem_restart_dev(drv->subsys);
+}
+
+static void smsm_state_cb(void *data, uint32_t old_state, uint32_t new_state)
+{
+ struct gss_data *drv = data;
+
+ /* Ignore if we're the one that set SMSM_RESET */
+ if (drv->crash_shutdown)
+ return;
+
+ if (new_state & SMSM_RESET) {
+ pr_err("GSS SMSM state changed to SMSM_RESET.\n"
+ "Probable err_fatal on the GSS. "
+ "Calling subsystem restart...\n");
+ restart_gss(drv);
+ }
+}
+
+static int gss_shutdown(const struct subsys_desc *desc)
+{
+ struct gss_data *drv = container_of(desc, struct gss_data, subsys_desc);
+
+ pil_force_shutdown("gss");
+ disable_irq_nosync(drv->irq);
+
+ return 0;
+}
+
+static int gss_powerup(const struct subsys_desc *desc)
+{
+ struct gss_data *drv = container_of(desc, struct gss_data, subsys_desc);
+
+ pil_force_boot("gss");
+ enable_irq(drv->irq);
+ return 0;
+}
+
+void gss_crash_shutdown(const struct subsys_desc *desc)
+{
+ struct gss_data *drv = container_of(desc, struct gss_data, subsys_desc);
+
+ drv->crash_shutdown = 1;
+ smsm_reset_modem(SMSM_RESET);
+}
+
+/* FIXME: Get address, size from PIL */
+static struct ramdump_segment gss_segments[] = {
+ {0x89000000, 0x00D00000}
+};
+
+static struct ramdump_segment smem_segments[] = {
+ {0x80000000, 0x00200000},
+};
+
+static int gss_ramdump(int enable, const struct subsys_desc *desc)
+{
+ int ret;
+ struct gss_data *drv = container_of(desc, struct gss_data, subsys_desc);
+
+ if (enable) {
+ ret = do_ramdump(drv->ramdump_dev, gss_segments,
+ ARRAY_SIZE(gss_segments));
+ if (ret < 0) {
+ pr_err("Unable to dump gss memory\n");
+ return ret;
+ }
+
+ ret = do_ramdump(drv->smem_ramdump_dev, smem_segments,
+ ARRAY_SIZE(smem_segments));
+ if (ret < 0) {
+ pr_err("Unable to dump smem memory (rc = %d).\n", ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static irqreturn_t gss_wdog_bite_irq(int irq, void *dev_id)
+{
+ struct gss_data *drv = dev_id;
+
+ pr_err("Watchdog bite received from GSS!\n");
+ restart_gss(drv);
+
+ return IRQ_HANDLED;
+}
+
+static int gss_open(struct inode *inode, struct file *filp)
+{
+ void *ret;
+ struct miscdevice *c = filp->private_data;
+ struct gss_data *drv = container_of(c, struct gss_data, misc_dev);
+
+ drv->pil_handle = ret = pil_get("gss");
+ if (!ret)
+ pr_debug("%s - pil_get returned NULL\n", __func__);
+
+ return 0;
+}
+
+static int gss_release(struct inode *inode, struct file *filp)
+{
+ struct miscdevice *c = filp->private_data;
+ struct gss_data *drv = container_of(c, struct gss_data, misc_dev);
+
+ pil_put(drv->pil_handle);
+ pr_debug("%s pil_put called on GSS\n", __func__);
+
+ return 0;
+}
+
+const struct file_operations gss_file_ops = {
+ .open = gss_open,
+ .release = gss_release,
+ .owner = THIS_MODULE,
+};
+
static int __devinit pil_gss_probe(struct platform_device *pdev)
{
struct gss_data *drv;
struct resource *res;
struct pil_desc *desc;
+ int ret;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
@@ -344,6 +508,10 @@
if (IS_ERR(drv->xo))
return PTR_ERR(drv->xo);
+ drv->irq = platform_get_irq(pdev, 0);
+ if (drv->irq < 0)
+ return drv->irq;
+
desc->name = "gss";
desc->dev = &pdev->dev;
desc->owner = THIS_MODULE;
@@ -363,13 +531,71 @@
if (IS_ERR(drv->pil)) {
return PTR_ERR(drv->pil);
}
+
+ ret = smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_RESET,
+ smsm_state_cb, drv);
+ if (ret < 0)
+ dev_warn(&pdev->dev, "Unable to register SMSM callback\n");
+
+ drv->subsys_desc.name = "gss";
+ drv->subsys_desc.shutdown = gss_shutdown;
+ drv->subsys_desc.powerup = gss_powerup;
+ drv->subsys_desc.ramdump = gss_ramdump;
+ drv->subsys_desc.crash_shutdown = gss_crash_shutdown;
+
+ drv->subsys = subsys_register(&drv->subsys_desc);
+ if (IS_ERR(drv->subsys)) {
+ ret = PTR_ERR(drv->subsys);
+ goto err_subsys;
+ }
+
+ drv->misc_dev.minor = MISC_DYNAMIC_MINOR;
+ drv->misc_dev.name = "gss";
+ drv->misc_dev.fops = &gss_file_ops;
+ ret = misc_register(&drv->misc_dev);
+ if (ret)
+ goto err_misc;
+
+ drv->ramdump_dev = create_ramdump_device("gss");
+ if (!drv->ramdump_dev) {
+ ret = -ENOMEM;
+ goto err_ramdump;
+ }
+
+ drv->smem_ramdump_dev = create_ramdump_device("smem-gss");
+ if (!drv->smem_ramdump_dev) {
+ ret = -ENOMEM;
+ goto err_smem;
+ }
+
+ ret = devm_request_irq(&pdev->dev, drv->irq, gss_wdog_bite_irq,
+ IRQF_TRIGGER_RISING, "gss_a5_wdog", drv);
+ if (ret < 0)
+ goto err;
return 0;
+err:
+ destroy_ramdump_device(drv->smem_ramdump_dev);
+err_smem:
+ destroy_ramdump_device(drv->ramdump_dev);
+err_ramdump:
+ misc_deregister(&drv->misc_dev);
+err_misc:
+ subsys_unregister(drv->subsys);
+err_subsys:
+ msm_pil_unregister(drv->pil);
+ return ret;
}
static int __devexit pil_gss_remove(struct platform_device *pdev)
{
struct gss_data *drv = platform_get_drvdata(pdev);
+
+ destroy_ramdump_device(drv->smem_ramdump_dev);
+ destroy_ramdump_device(drv->ramdump_dev);
+ misc_deregister(&drv->misc_dev);
+ subsys_unregister(drv->subsys);
msm_pil_unregister(drv->pil);
+
return 0;
}
diff --git a/arch/arm/mach-msm/pil-modem.c b/arch/arm/mach-msm/pil-modem.c
index 8344496..ecb3800 100644
--- a/arch/arm/mach-msm/pil-modem.c
+++ b/arch/arm/mach-msm/pil-modem.c
@@ -19,11 +19,19 @@
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/clk.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/reboot.h>
#include <mach/msm_iomap.h>
+#include <mach/subsystem_restart.h>
+#include <mach/msm_smsm.h>
+#include <mach/peripheral-loader.h>
+#include "modem_notifier.h"
#include "peripheral-loader.h"
#include "scm-pas.h"
+#include "ramdump.h"
#define MARM_BOOT_CONTROL 0x0010
#define MARM_RESET (MSM_CLK_CTL_BASE + 0x2BD4)
@@ -46,12 +54,22 @@
#define PLL_ENA_MARM (MSM_CLK_CTL_BASE + 0x3500)
#define PLL8_STATUS (MSM_CLK_CTL_BASE + 0x3158)
#define CLK_HALT_MSS_SMPSS_MISC_STATE (MSM_CLK_CTL_BASE + 0x2FDC)
+#define MSS_MODEM_RESET (MSM_CLK_CTL_BASE + 0x2C48)
struct modem_data {
void __iomem *base;
+ void __iomem *wdog;
unsigned long start_addr;
struct pil_device *pil;
struct clk *xo;
+ struct notifier_block notifier;
+ int ignore_smsm_ack;
+ int irq;
+ struct subsys_device *subsys;
+ struct subsys_desc subsys_desc;
+ struct delayed_work unlock_work;
+ struct work_struct fatal_work;
+ struct ramdump_device *ramdump_dev;
};
static int make_modem_proxy_votes(struct pil_desc *pil)
@@ -161,7 +179,7 @@
return 0;
}
-static int modem_shutdown(struct pil_desc *pil)
+static int modem_pil_shutdown(struct pil_desc *pil)
{
u32 reg;
@@ -203,7 +221,7 @@
static struct pil_reset_ops pil_modem_ops = {
.init_image = modem_init_image,
.auth_and_reset = modem_reset,
- .shutdown = modem_shutdown,
+ .shutdown = modem_pil_shutdown,
.proxy_vote = make_modem_proxy_votes,
.proxy_unvote = remove_modem_proxy_votes,
};
@@ -232,11 +250,166 @@
.proxy_unvote = remove_modem_proxy_votes,
};
+static void modem_crash_shutdown(const struct subsys_desc *subsys)
+{
+ struct modem_data *drv;
+
+ /* If modem hasn't already crashed, send SMSM_RESET. */
+ drv = container_of(subsys, struct modem_data, subsys_desc);
+ if (!(smsm_get_state(SMSM_MODEM_STATE) & SMSM_RESET)) {
+ modem_unregister_notifier(&drv->notifier);
+ smsm_reset_modem(SMSM_RESET);
+ }
+
+ /* Wait to allow the modem to clean up caches etc. */
+ mdelay(5);
+}
+
+static irqreturn_t modem_wdog_bite_irq(int irq, void *dev_id)
+{
+ struct modem_data *drv = dev_id;
+
+ schedule_work(&drv->fatal_work);
+ disable_irq_nosync(drv->irq);
+
+ return IRQ_HANDLED;
+}
+
+static void modem_unlock_timeout(struct work_struct *work)
+{
+ struct modem_data *drv;
+ struct delayed_work *dwork = to_delayed_work(work);
+
+ pr_crit("Timeout waiting for modem to unlock.\n");
+
+ drv = container_of(dwork, struct modem_data, unlock_work);
+ /* The unlock didn't work, clear the reset */
+ writel_relaxed(0x0, MSS_MODEM_RESET);
+ mb();
+
+ subsystem_restart_dev(drv->subsys);
+ enable_irq(drv->irq);
+}
+
+static void modem_fatal_fn(struct work_struct *work)
+{
+ u32 modem_state;
+ u32 panic_smsm_states = SMSM_RESET | SMSM_SYSTEM_DOWNLOAD;
+ u32 reset_smsm_states = SMSM_SYSTEM_REBOOT_USR | SMSM_SYSTEM_PWRDWN_USR;
+ struct modem_data *drv;
+
+ drv = container_of(work, struct modem_data, fatal_work);
+
+ pr_err("Watchdog bite received from modem!\n");
+
+ modem_state = smsm_get_state(SMSM_MODEM_STATE);
+ pr_err("Modem SMSM state = 0x%x!\n", modem_state);
+
+ if (modem_state == 0 || modem_state & panic_smsm_states) {
+ subsystem_restart_dev(drv->subsys);
+ enable_irq(drv->irq);
+ } else if (modem_state & reset_smsm_states) {
+ pr_err("User-invoked system reset/powerdown.");
+ kernel_restart(NULL);
+ } else {
+ unsigned long timeout = msecs_to_jiffies(6000);
+
+ pr_err("Modem AHB locked up. Trying to free up modem!\n");
+
+ writel_relaxed(0x3, MSS_MODEM_RESET);
+ /*
+ * If we are still alive (allowing for the 5 second
+ * delayed-panic-reboot), the modem is either still wedged or
+ * SMSM didn't come through. Force panic in that case.
+ */
+ schedule_delayed_work(&drv->unlock_work, timeout);
+ }
+}
+
+static int modem_notif_handler(struct notifier_block *nb, unsigned long code,
+ void *p)
+{
+ struct modem_data *drv = container_of(nb, struct modem_data, notifier);
+
+ if (code == MODEM_NOTIFIER_START_RESET) {
+ if (drv->ignore_smsm_ack) {
+ drv->ignore_smsm_ack = 0;
+ } else {
+ pr_err("Modem error fatal'ed.");
+ subsystem_restart_dev(drv->subsys);
+ }
+ }
+ return NOTIFY_DONE;
+}
+
+static int modem_shutdown(const struct subsys_desc *subsys)
+{
+ struct modem_data *drv;
+
+ drv = container_of(subsys, struct modem_data, subsys_desc);
+ /*
+ * If the modem didn't already crash, setting SMSM_RESET here will help
+ * flush caches etc. The ignore_smsm_ack flag is set to ignore the
+ * SMSM_RESET notification that is generated due to the modem settings
+ * its own SMSM_RESET bit in response to the apps setting the apps
+ * SMSM_RESET bit.
+ */
+ if (!(smsm_get_state(SMSM_MODEM_STATE) & SMSM_RESET)) {
+ drv->ignore_smsm_ack = 1;
+ smsm_reset_modem(SMSM_RESET);
+ }
+
+ /* Disable the modem watchdog to allow clean modem bootup */
+ writel_relaxed(0x0, drv->wdog + 0x8);
+ /*
+ * The write above needs to go through before the modem is powered up
+ * again.
+ */
+ mb();
+ /* Wait here to allow the modem to clean up caches, etc. */
+ msleep(20);
+
+ pil_force_shutdown("modem");
+ disable_irq_nosync(drv->irq);
+
+ return 0;
+}
+
+static int modem_powerup(const struct subsys_desc *subsys)
+{
+ struct modem_data *drv;
+ int ret;
+
+ drv = container_of(subsys, struct modem_data, subsys_desc);
+ ret = pil_force_boot("modem");
+ enable_irq(drv->irq);
+
+ return ret;
+}
+
+/* FIXME: Get address, size from PIL */
+static struct ramdump_segment modem_segments[] = {
+ { 0x42F00000, 0x46000000 - 0x42F00000 },
+};
+
+static int modem_ramdump(int enable, const struct subsys_desc *subsys)
+{
+ struct modem_data *drv;
+
+ drv = container_of(subsys, struct modem_data, subsys_desc);
+ if (enable)
+ return do_ramdump(drv->ramdump_dev, modem_segments,
+ ARRAY_SIZE(modem_segments));
+ else
+ return 0;
+}
+
static int __devinit pil_modem_driver_probe(struct platform_device *pdev)
{
struct modem_data *drv;
struct resource *res;
struct pil_desc *desc;
+ int ret;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
@@ -247,6 +420,10 @@
return -ENOMEM;
platform_set_drvdata(pdev, drv);
+ drv->irq = platform_get_irq(pdev, 0);
+ if (drv->irq < 0)
+ return drv->irq;
+
drv->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
if (!drv->base)
return -ENOMEM;
@@ -259,6 +436,14 @@
if (!desc)
return -ENOMEM;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!res)
+ return -EINVAL;
+
+ drv->wdog = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ if (!drv->wdog)
+ return -ENOMEM;
+
desc->name = "modem";
desc->depends_on = "q6";
desc->dev = &pdev->dev;
@@ -273,16 +458,61 @@
dev_info(&pdev->dev, "using non-secure boot\n");
}
drv->pil = msm_pil_register(desc);
- if (IS_ERR(drv->pil)) {
+ if (IS_ERR(drv->pil))
return PTR_ERR(drv->pil);
+
+ drv->notifier.notifier_call = modem_notif_handler,
+ ret = modem_register_notifier(&drv->notifier);
+ if (ret)
+ goto err_notify;
+
+ drv->subsys_desc.name = "modem";
+ drv->subsys_desc.shutdown = modem_shutdown;
+ drv->subsys_desc.powerup = modem_powerup;
+ drv->subsys_desc.ramdump = modem_ramdump;
+ drv->subsys_desc.crash_shutdown = modem_crash_shutdown;
+
+ INIT_WORK(&drv->fatal_work, modem_fatal_fn);
+ INIT_DELAYED_WORK(&drv->unlock_work, modem_unlock_timeout);
+
+ drv->subsys = subsys_register(&drv->subsys_desc);
+ if (IS_ERR(drv->subsys)) {
+ ret = PTR_ERR(drv->subsys);
+ goto err_subsys;
}
+
+ drv->ramdump_dev = create_ramdump_device("modem");
+ if (!drv->ramdump_dev) {
+ ret = -ENOMEM;
+ goto err_ramdump;
+ }
+
+ ret = devm_request_irq(&pdev->dev, drv->irq, modem_wdog_bite_irq,
+ IRQF_TRIGGER_RISING, "modem_watchdog", drv);
+ if (ret)
+ goto err_irq;
return 0;
+
+err_irq:
+ destroy_ramdump_device(drv->ramdump_dev);
+err_ramdump:
+ subsys_unregister(drv->subsys);
+err_subsys:
+ modem_unregister_notifier(&drv->notifier);
+err_notify:
+ msm_pil_unregister(drv->pil);
+ return ret;
}
static int __devexit pil_modem_driver_exit(struct platform_device *pdev)
{
struct modem_data *drv = platform_get_drvdata(pdev);
+
+ destroy_ramdump_device(drv->ramdump_dev);
+ subsys_unregister(drv->subsys);
+ modem_unregister_notifier(&drv->notifier);
msm_pil_unregister(drv->pil);
+
return 0;
}
diff --git a/arch/arm/mach-msm/pil-q6v3.c b/arch/arm/mach-msm/pil-q6v3.c
index 28b9dee..1a226de 100644
--- a/arch/arm/mach-msm/pil-q6v3.c
+++ b/arch/arm/mach-msm/pil-q6v3.c
@@ -19,9 +19,15 @@
#include <linux/elf.h>
#include <linux/err.h>
#include <linux/clk.h>
+#include <linux/workqueue.h>
+#include <linux/interrupt.h>
#include <mach/msm_iomap.h>
+#include <mach/subsystem_restart.h>
+#include <mach/scm.h>
+#include <mach/peripheral-loader.h>
+#include "ramdump.h"
#include "peripheral-loader.h"
#include "scm-pas.h"
@@ -60,11 +66,34 @@
#define Q6_STRAP_TCM_BASE (0x28C << 15)
#define Q6_STRAP_TCM_CONFIG 0x28B
+#define SCM_Q6_NMI_CMD 0x1
+
+/**
+ * struct q6v3_data - LPASS driver data
+ * @base: register base
+ * @wk_base: wakeup register base
+ * @wd_base: watchdog register base
+ * @start_addr: address that processor starts running at
+ * @irq: watchdog irq
+ * @pil: peripheral handle
+ * @subsys: subsystem restart handle
+ * @subsys_desc: subsystem restart descriptor
+ * @fatal_wrk: fatal error workqueue
+ * @pll: pll clock handle
+ * @ramdump_dev: ramdump device
+ */
struct q6v3_data {
void __iomem *base;
+ void __iomem *wk_base;
+ void __iomem *wd_base;
unsigned long start_addr;
+ int irq;
struct pil_device *pil;
+ struct subsys_device *subsys;
+ struct subsys_desc subsys_desc;
+ struct work_struct fatal_wrk;
struct clk *pll;
+ struct ramdump_device *ramdump_dev;
};
static int pil_q6v3_init_image(struct pil_desc *pil, const u8 *metadata,
@@ -198,11 +227,96 @@
.proxy_unvote = pil_q6v3_remove_proxy_votes,
};
+static void q6_fatal_fn(struct work_struct *work)
+{
+ struct q6v3_data *drv = container_of(work, struct q6v3_data, fatal_wrk);
+
+ pr_err("Watchdog bite received from Q6!\n");
+ subsystem_restart_dev(drv->subsys);
+ enable_irq(drv->irq);
+}
+
+static void send_q6_nmi(struct q6v3_data *drv)
+{
+ /* Send NMI to QDSP6 via an SCM call. */
+ scm_call_atomic1(SCM_SVC_UTIL, SCM_Q6_NMI_CMD, 0x1);
+
+ /* Wakeup the Q6 */
+ writel_relaxed(0x2000, drv->wk_base + 0x1c);
+ /* Q6 requires atleast 100ms to dump caches etc.*/
+ mdelay(100);
+ pr_info("Q6 NMI was sent.\n");
+}
+
+static int lpass_q6_shutdown(const struct subsys_desc *subsys)
+{
+ struct q6v3_data *drv;
+
+ drv = container_of(subsys, struct q6v3_data, subsys_desc);
+ send_q6_nmi(drv);
+ writel_relaxed(0x0, drv->wd_base + 0x24);
+ mb();
+
+ pil_force_shutdown("q6");
+ disable_irq_nosync(drv->irq);
+
+ return 0;
+}
+
+static int lpass_q6_powerup(const struct subsys_desc *subsys)
+{
+ struct q6v3_data *drv;
+ int ret;
+
+ drv = container_of(subsys, struct q6v3_data, subsys_desc);
+ ret = pil_force_boot("q6");
+ enable_irq(drv->irq);
+ return ret;
+}
+
+/* FIXME: Get address, size from PIL */
+static struct ramdump_segment q6_segments[] = {
+ { 0x46700000, 0x47f00000 - 0x46700000 },
+ { 0x28400000, 0x12800 }
+};
+
+static int lpass_q6_ramdump(int enable, const struct subsys_desc *subsys)
+{
+ struct q6v3_data *drv;
+
+ drv = container_of(subsys, struct q6v3_data, subsys_desc);
+ if (enable)
+ return do_ramdump(drv->ramdump_dev, q6_segments,
+ ARRAY_SIZE(q6_segments));
+ else
+ return 0;
+}
+
+static void lpass_q6_crash_shutdown(const struct subsys_desc *subsys)
+{
+ struct q6v3_data *drv;
+
+ drv = container_of(subsys, struct q6v3_data, subsys_desc);
+ send_q6_nmi(drv);
+}
+
+static irqreturn_t lpass_wdog_bite_irq(int irq, void *dev_id)
+{
+ int ret;
+ struct q6v3_data *drv = dev_id;
+
+ ret = schedule_work(&drv->fatal_wrk);
+ disable_irq_nosync(drv->irq);
+
+ return IRQ_HANDLED;
+}
+
static int __devinit pil_q6v3_driver_probe(struct platform_device *pdev)
{
struct q6v3_data *drv;
struct resource *res;
struct pil_desc *desc;
+ int ret;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
@@ -217,14 +331,34 @@
if (!drv->base)
return -ENOMEM;
- desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL);
- if (!drv)
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!res)
+ return -EINVAL;
+
+ drv->wk_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ if (!drv->wk_base)
return -ENOMEM;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+ if (!res)
+ return -EINVAL;
+
+ drv->wd_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ if (!drv->wd_base)
+ return -ENOMEM;
+
+ drv->irq = platform_get_irq(pdev, 0);
+ if (drv->irq < 0)
+ return drv->irq;
+
drv->pll = devm_clk_get(&pdev->dev, "pll4");
if (IS_ERR(drv->pll))
return PTR_ERR(drv->pll);
+ desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL);
+ if (!drv)
+ return -ENOMEM;
+
desc->name = "q6";
desc->dev = &pdev->dev;
desc->owner = THIS_MODULE;
@@ -239,15 +373,51 @@
}
drv->pil = msm_pil_register(desc);
- if (IS_ERR(drv->pil)) {
+ if (IS_ERR(drv->pil))
return PTR_ERR(drv->pil);
+
+ drv->subsys_desc.name = "lpass";
+ drv->subsys_desc.shutdown = lpass_q6_shutdown;
+ drv->subsys_desc.powerup = lpass_q6_powerup;
+ drv->subsys_desc.ramdump = lpass_q6_ramdump;
+ drv->subsys_desc.crash_shutdown = lpass_q6_crash_shutdown;
+
+ INIT_WORK(&drv->fatal_wrk, q6_fatal_fn);
+
+ drv->ramdump_dev = create_ramdump_device("lpass");
+ if (!drv->ramdump_dev) {
+ ret = -ENOMEM;
+ goto err_ramdump;
}
+
+ drv->subsys = subsys_register(&drv->subsys_desc);
+ if (IS_ERR(drv->subsys)) {
+ ret = PTR_ERR(drv->subsys);
+ goto err_subsys;
+ }
+
+ ret = devm_request_irq(&pdev->dev, drv->irq, lpass_wdog_bite_irq,
+ IRQF_TRIGGER_RISING, "lpass_wdog", drv);
+ if (ret) {
+ dev_err(&pdev->dev, "Unable to request wdog irq.\n");
+ goto err_irq;
+ }
+
return 0;
+err_irq:
+ subsys_unregister(drv->subsys);
+err_subsys:
+ destroy_ramdump_device(drv->ramdump_dev);
+err_ramdump:
+ msm_pil_unregister(drv->pil);
+ return ret;
}
static int __devexit pil_q6v3_driver_exit(struct platform_device *pdev)
{
struct q6v3_data *drv = platform_get_drvdata(pdev);
+ subsys_unregister(drv->subsys);
+ destroy_ramdump_device(drv->ramdump_dev);
msm_pil_unregister(drv->pil);
return 0;
}
diff --git a/arch/arm/mach-msm/pil-riva.c b/arch/arm/mach-msm/pil-riva.c
index 3040a31..dbb4408 100644
--- a/arch/arm/mach-msm/pil-riva.c
+++ b/arch/arm/mach-msm/pil-riva.c
@@ -20,11 +20,17 @@
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/wcnss_wlan.h>
#include <mach/msm_iomap.h>
+#include <mach/subsystem_restart.h>
+#include <mach/peripheral-loader.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
+#include "ramdump.h"
+#include "smd_private.h"
#define RIVA_PMU_A2XB_CFG 0xB8
#define RIVA_PMU_A2XB_CFG_EN BIT(0)
@@ -82,6 +88,13 @@
struct clk *xo;
struct regulator *pll_supply;
struct pil_device *pil;
+ int irq;
+ int crash;
+ int rst_in_progress;
+ struct subsys_device *subsys;
+ struct subsys_desc subsys_desc;
+ struct delayed_work cancel_work;
+ struct ramdump_device *ramdump_dev;
};
static bool cxo_is_needed(struct riva_data *drv)
@@ -272,6 +285,160 @@
.proxy_unvote = pil_riva_remove_proxy_vote,
};
+static int enable_riva_ssr;
+
+static int enable_riva_ssr_set(const char *val, struct kernel_param *kp)
+{
+ int ret;
+
+ ret = param_set_int(val, kp);
+ if (ret)
+ return ret;
+
+ if (enable_riva_ssr)
+ pr_info("Subsystem restart activated for riva.\n");
+
+ return 0;
+}
+module_param_call(enable_riva_ssr, enable_riva_ssr_set, param_get_int,
+ &enable_riva_ssr, S_IRUGO | S_IWUSR);
+
+static void smsm_state_cb_hdlr(void *data, uint32_t old_state,
+ uint32_t new_state)
+{
+ struct riva_data *drv = data;
+ char *smem_reset_reason;
+ char buffer[81];
+ unsigned smem_reset_size;
+ unsigned size;
+
+ drv->crash = true;
+ if (!(new_state & SMSM_RESET))
+ return;
+
+ if (drv->rst_in_progress) {
+ pr_err("riva: Ignoring smsm reset req, restart in progress\n");
+ return;
+ }
+
+ pr_err("riva: smsm state changed to smsm reset\n");
+
+ smem_reset_reason = smem_get_entry(SMEM_SSR_REASON_WCNSS0,
+ &smem_reset_size);
+
+ if (!smem_reset_reason || !smem_reset_size) {
+ pr_err("wcnss subsystem failure reason:\n"
+ "(unknown, smem_get_entry failed)");
+ } else if (!smem_reset_reason[0]) {
+ pr_err("wcnss subsystem failure reason:\n"
+ "(unknown, init string found)");
+ } else {
+ size = smem_reset_size < sizeof(buffer) ? smem_reset_size :
+ (sizeof(buffer) - 1);
+ memcpy(buffer, smem_reset_reason, size);
+ buffer[size] = '\0';
+ pr_err("wcnss subsystem failure reason: %s\n", buffer);
+ memset(smem_reset_reason, 0, smem_reset_size);
+ wmb();
+ }
+
+ drv->rst_in_progress = 1;
+ subsystem_restart_dev(drv->subsys);
+}
+
+static irqreturn_t riva_wdog_bite_irq_hdlr(int irq, void *dev_id)
+{
+ struct riva_data *drv = dev_id;
+
+ drv->crash = true;
+ if (drv->rst_in_progress) {
+ pr_err("Ignoring riva bite irq, restart in progress\n");
+ return IRQ_HANDLED;
+ }
+ if (!enable_riva_ssr)
+ panic("Watchdog bite received from Riva");
+
+ drv->rst_in_progress = 1;
+ subsystem_restart_dev(drv->subsys);
+
+ return IRQ_HANDLED;
+}
+
+static void riva_post_bootup(struct work_struct *work)
+{
+ struct platform_device *pdev = wcnss_get_platform_device();
+ struct wcnss_wlan_config *pwlanconfig = wcnss_get_wlan_config();
+
+ wcnss_wlan_power(&pdev->dev, pwlanconfig, WCNSS_WLAN_SWITCH_OFF);
+}
+
+static int riva_shutdown(const struct subsys_desc *desc)
+{
+ struct riva_data *drv;
+
+ drv = container_of(desc, struct riva_data, subsys_desc);
+ pil_force_shutdown("wcnss");
+ flush_delayed_work(&drv->cancel_work);
+ wcnss_flush_delayed_boot_votes();
+ disable_irq_nosync(drv->irq);
+
+ return 0;
+}
+
+static int riva_powerup(const struct subsys_desc *desc)
+{
+ struct riva_data *drv;
+ struct platform_device *pdev = wcnss_get_platform_device();
+ struct wcnss_wlan_config *pwlanconfig = wcnss_get_wlan_config();
+ int ret = 0;
+
+ drv = container_of(desc, struct riva_data, subsys_desc);
+ if (pdev && pwlanconfig) {
+ ret = wcnss_wlan_power(&pdev->dev, pwlanconfig,
+ WCNSS_WLAN_SWITCH_ON);
+ if (!ret)
+ pil_force_boot("wcnss");
+ }
+ drv->rst_in_progress = 0;
+ enable_irq(drv->irq);
+ schedule_delayed_work(&drv->cancel_work, msecs_to_jiffies(5000));
+
+ return ret;
+}
+
+/*
+ * 7MB RAM segments for Riva SS;
+ * Riva 1.1 0x8f000000 - 0x8f700000
+ * Riva 1.0 0x8f200000 - 0x8f700000
+ */
+static struct ramdump_segment riva_segments[] = {
+ {0x8f000000, 0x8f700000 - 0x8f000000}
+};
+
+static int riva_ramdump(int enable, const struct subsys_desc *desc)
+{
+ struct riva_data *drv;
+
+ drv = container_of(desc, struct riva_data, subsys_desc);
+
+ if (enable)
+ return do_ramdump(drv->ramdump_dev, riva_segments,
+ ARRAY_SIZE(riva_segments));
+ else
+ return 0;
+}
+
+/* Riva crash handler */
+static void riva_crash_shutdown(const struct subsys_desc *desc)
+{
+ struct riva_data *drv;
+
+ drv = container_of(desc, struct riva_data, subsys_desc);
+ pr_err("riva crash shutdown %d\n", drv->crash);
+ if (drv->crash != true)
+ smsm_change_state(SMSM_APPS_STATE, SMSM_RESET, SMSM_RESET);
+}
+
static int __devinit pil_riva_probe(struct platform_device *pdev)
{
struct riva_data *drv;
@@ -317,6 +484,10 @@
}
}
+ drv->irq = platform_get_irq(pdev, 0);
+ if (drv->irq < 0)
+ return drv->irq;
+
desc->name = "wcnss";
desc->dev = &pdev->dev;
desc->owner = THIS_MODULE;
@@ -337,13 +508,60 @@
drv->pil = msm_pil_register(desc);
if (IS_ERR(drv->pil))
return PTR_ERR(drv->pil);
+
+ ret = smsm_state_cb_register(SMSM_WCNSS_STATE, SMSM_RESET,
+ smsm_state_cb_hdlr, drv);
+ if (ret < 0)
+ goto err_smsm;
+
+ drv->subsys_desc.name = "wcnss";
+ drv->subsys_desc.shutdown = riva_shutdown;
+ drv->subsys_desc.powerup = riva_powerup;
+ drv->subsys_desc.ramdump = riva_ramdump;
+ drv->subsys_desc.crash_shutdown = riva_crash_shutdown;
+
+ INIT_DELAYED_WORK(&drv->cancel_work, riva_post_bootup);
+
+ drv->ramdump_dev = create_ramdump_device("riva");
+ if (!drv->ramdump_dev) {
+ ret = -ENOMEM;
+ goto err_ramdump;
+ }
+
+ drv->subsys = subsys_register(&drv->subsys_desc);
+ if (IS_ERR(drv->subsys)) {
+ ret = PTR_ERR(drv->subsys);
+ goto err_subsys;
+ }
+
+ ret = devm_request_irq(&pdev->dev, drv->irq, riva_wdog_bite_irq_hdlr,
+ IRQF_TRIGGER_HIGH, "riva_wdog", drv);
+ if (ret < 0)
+ goto err;
+
return 0;
+err:
+ subsys_unregister(drv->subsys);
+err_subsys:
+ destroy_ramdump_device(drv->ramdump_dev);
+err_ramdump:
+ smsm_state_cb_deregister(SMSM_WCNSS_STATE, SMSM_RESET,
+ smsm_state_cb_hdlr, drv);
+err_smsm:
+ msm_pil_unregister(drv->pil);
+ return ret;
}
static int __devexit pil_riva_remove(struct platform_device *pdev)
{
struct riva_data *drv = platform_get_drvdata(pdev);
+
+ subsys_unregister(drv->subsys);
+ destroy_ramdump_device(drv->ramdump_dev);
+ smsm_state_cb_deregister(SMSM_WCNSS_STATE, SMSM_RESET,
+ smsm_state_cb_hdlr, drv);
msm_pil_unregister(drv->pil);
+
return 0;
}
diff --git a/arch/arm/mach-msm/platsmp-8625.c b/arch/arm/mach-msm/platsmp-8625.c
index 700f966..3b31b9f 100644
--- a/arch/arm/mach-msm/platsmp-8625.c
+++ b/arch/arm/mach-msm/platsmp-8625.c
@@ -28,19 +28,28 @@
#include <mach/msm_iomap.h>
#include "pm.h"
-#define MSM_CORE1_RESET 0xA8600590
-#define MSM_CORE1_STATUS_MSK 0x02800000
+#define CORE_RESET_BASE 0xA8600590
+#define MSM_CORE_STATUS_MSK 0x02800000
/*
* control for which core is the next to come out of the secondary
* boot "holding pen"
*/
-int pen_release = -1;
+volatile int pen_release = -1;
-static bool cold_boot_done;
+static DEFINE_PER_CPU(bool, cold_boot_done);
+
+struct per_cpu_data {
+ unsigned int reset_off;
+ unsigned int offset;
+ unsigned int ipc_irq;
+ void __iomem *reset_core_base;
+};
static uint32_t *msm8625_boot_vector;
-static void __iomem *reset_core1_base;
+
+
+static struct per_cpu_data cpu_data[CONFIG_NR_CPUS];
/*
* Write pen_release in a way that is guaranteed to be visible to all
@@ -65,7 +74,8 @@
/*
* MP_CORE_IPC will be used to generate interrupt and can be used by either
* of core.
- * To bring core1 out of GDFS we need to raise the SPI using the MP_CORE_IPC.
+ * To bring secondary cores out of GDFS we need to raise the SPI using the
+ * MP_CORE_IPC.
*/
static void raise_clear_spi(unsigned int cpu, bool set)
{
@@ -110,10 +120,10 @@
*/
write_pen_release(-1);
- /* clear the IPC1(SPI-8) pending SPI */
+ /* clear the IPC pending SPI */
if (power_collapsed) {
- raise_clear_spi(1, false);
- clear_pending_spi(MSM8625_INT_ACSR_MP_CORE_IPC1);
+ raise_clear_spi(cpu, false);
+ clear_pending_spi(cpu_data[cpu].ipc_irq);
power_collapsed = 0;
}
@@ -124,7 +134,7 @@
spin_unlock(&boot_lock);
}
-static int __cpuinit msm8625_release_secondary(void)
+static int __cpuinit msm8625_release_secondary(unsigned int cpu)
{
void __iomem *base_ptr;
int value = 0;
@@ -137,33 +147,35 @@
*/
timeout = jiffies + usecs_to_jiffies(20);
while (time_before(jiffies, timeout)) {
- value = __raw_readl(MSM_CFG_CTL_BASE + 0x3c);
- if ((value & MSM_CORE1_STATUS_MSK) ==
- MSM_CORE1_STATUS_MSK)
+ value = __raw_readl(MSM_CFG_CTL_BASE + cpu_data[cpu].offset);
+ if ((value & MSM_CORE_STATUS_MSK) ==
+ MSM_CORE_STATUS_MSK)
break;
udelay(1);
}
if (!value) {
- pr_err("Core 1 cannot be brought out of Reset!!!\n");
+ pr_err("Core %u cannot be brought out of Reset!!!\n", cpu);
return -ENODEV;
}
- base_ptr = ioremap_nocache(MSM_CORE1_RESET, SZ_4);
+ base_ptr = ioremap_nocache(CORE_RESET_BASE +
+ cpu_data[cpu].reset_off, SZ_4);
if (!base_ptr)
return -ENODEV;
- /* Reset core 1 out of reset */
+
+ /* Reset core out of reset */
__raw_writel(0x0, base_ptr);
mb();
- reset_core1_base = base_ptr;
+ cpu_data[cpu].reset_core_base = base_ptr;
return 0;
}
-void __iomem *core1_reset_base(void)
+void __iomem *core_reset_base(unsigned int cpu)
{
- return reset_core1_base;
+ return cpu_data[cpu].reset_core_base;
}
int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
@@ -172,12 +184,12 @@
preset_lpj = loops_per_jiffy;
- if (cold_boot_done == false) {
- if (msm8625_release_secondary()) {
- pr_err("Failed to release secondary core\n");
+ if (per_cpu(cold_boot_done, cpu) == false) {
+ if (msm8625_release_secondary(cpu)) {
+ pr_err("Failed to release core %u\n", cpu);
return -ENODEV;
}
- cold_boot_done = true;
+ per_cpu(cold_boot_done, cpu) = true;
}
/*
@@ -200,13 +212,13 @@
* and branch to the address found there.
*
* power_collapsed is the flag which will be updated for Powercollapse.
- * Once we are out of PC, as Core1 will be in the state of GDFS which
- * needs to be brought out by raising an SPI.
+ * Once we are out of PC, as secondary cores will be in the state of
+ * GDFS which needs to be brought out by raising an SPI.
*/
if (power_collapsed) {
- core1_gic_configure_and_raise();
- raise_clear_spi(1, true);
+ gic_configure_and_raise(cpu_data[cpu].ipc_irq, cpu);
+ raise_clear_spi(cpu, true);
} else {
gic_raise_softirq(cpumask_of(cpu), 1);
}
@@ -247,6 +259,34 @@
set_smp_cross_call(gic_raise_softirq);
}
+static void per_cpu_data(unsigned int cpu, unsigned int off,
+ unsigned int off1, unsigned int irq)
+{
+ cpu_data[cpu].reset_off = off;
+ cpu_data[cpu].offset = off1;
+ cpu_data[cpu].ipc_irq = irq;
+}
+
+static void enable_boot_remapper(unsigned long bit, unsigned int off)
+{
+ int value;
+
+ /* Enable boot remapper address */
+ value = __raw_readl(MSM_CFG_CTL_BASE + off);
+ __raw_writel(value | bit, MSM_CFG_CTL_BASE + off) ;
+ mb();
+}
+
+static void remapper_address(unsigned long phys, unsigned int off)
+{
+ /*
+ * Write the address of secondary startup into the
+ * boot remapper register. The secondary CPU branches to this address.
+ */
+ __raw_writel(phys, (MSM_CFG_CTL_BASE + off));
+ mb();
+}
+
static void __init msm8625_boot_vector_init(uint32_t *boot_vector,
unsigned long entry)
{
@@ -260,8 +300,8 @@
void __init platform_smp_prepare_cpus(unsigned int max_cpus)
{
- int i, value;
- void __iomem *second_ptr;
+ int i, cpu, value;
+ void __iomem *cpu_ptr;
/*
* Initialise the present map, which describes the set of CPUs
@@ -272,25 +312,41 @@
scu_enable(scu_base_addr());
- /*
- * Write the address of secondary startup into the
- * boot remapper register. The secondary CPU branches to this address.
- */
- __raw_writel(MSM8625_SECONDARY_PHYS, (MSM_CFG_CTL_BASE + 0x34));
- mb();
-
- second_ptr = ioremap_nocache(MSM8625_SECONDARY_PHYS, SZ_8);
- if (!second_ptr) {
- pr_err("failed to ioremap for secondary core\n");
+ cpu_ptr = ioremap_nocache(MSM8625_CPU_PHYS, SZ_8);
+ if (!cpu_ptr) {
+ pr_err("failed to ioremap for secondary cores\n");
return;
}
- msm8625_boot_vector_init(second_ptr,
+ msm8625_boot_vector_init(cpu_ptr,
virt_to_phys(msm_secondary_startup));
- iounmap(second_ptr);
- /* Enable boot remapper address: bit 26 for core1 */
- value = __raw_readl(MSM_CFG_CTL_BASE + 0x30);
- __raw_writel(value | (0x4 << 24), MSM_CFG_CTL_BASE + 0x30) ;
- mb();
+ iounmap(cpu_ptr);
+
+ for_each_possible_cpu(cpu) {
+ switch (cpu) {
+ case 0:
+ break;
+ case 1:
+ remapper_address(MSM8625_CPU_PHYS, 0x34);
+ per_cpu_data(cpu, 0x0, 0x3c,
+ MSM8625_INT_ACSR_MP_CORE_IPC1);
+ enable_boot_remapper(BIT(26), 0x30);
+ break;
+ case 2:
+ remapper_address((MSM8625_CPU_PHYS >> 16), 0x4C);
+ per_cpu_data(cpu, 0x8, 0x50,
+ MSM8625_INT_ACSR_MP_CORE_IPC2);
+ enable_boot_remapper(BIT(25), 0x48);
+ break;
+ case 3:
+ value = __raw_readl(MSM_CFG_CTL_BASE + 0x4C);
+ remapper_address(value | MSM8625_CPU_PHYS, 0x4C);
+ per_cpu_data(cpu, 0xC, 0x50,
+ MSM8625_INT_ACSR_MP_CORE_IPC3);
+ enable_boot_remapper(BIT(26), 0x48);
+ break;
+ }
+
+ }
}
diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c
index f6ed1ea..89003cf 100644
--- a/arch/arm/mach-msm/platsmp.c
+++ b/arch/arm/mach-msm/platsmp.c
@@ -42,6 +42,19 @@
*/
volatile int pen_release = -1;
+/*
+ * Write pen_release in a way that is guaranteed to be visible to all
+ * observers, irrespective of whether they're taking part in coherency
+ * or not. This is necessary for the hotplug code to work reliably.
+ */
+static void __cpuinit write_pen_release(int val)
+{
+ pen_release = val;
+ smp_wmb();
+ __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
+ outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
+}
+
static DEFINE_SPINLOCK(boot_lock);
void __cpuinit platform_secondary_init(unsigned int cpu)
@@ -56,6 +69,12 @@
gic_secondary_init(0);
/*
+ * let the primary processor know we're out of the
+ * pen, then head off into the C entry point
+ */
+ write_pen_release(-1);
+
+ /*
* Synchronise with the boot thread.
*/
spin_lock(&boot_lock);
@@ -165,7 +184,8 @@
return krait_release_secondary_sim(0xf9088000, cpu);
if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm8930aa() ||
- cpu_is_apq8064() || cpu_is_msm8627() || cpu_is_msm8960ab())
+ cpu_is_apq8064() || cpu_is_msm8627() || cpu_is_msm8960ab() ||
+ cpu_is_apq8064ab())
return krait_release_secondary(0x02088000, cpu);
if (cpu_is_msm8974())
@@ -176,17 +196,9 @@
}
DEFINE_PER_CPU(int, cold_boot_done);
-static int cold_boot_flags[] = {
- 0,
- SCM_FLAG_COLDBOOT_CPU1,
- SCM_FLAG_COLDBOOT_CPU2,
- SCM_FLAG_COLDBOOT_CPU3,
-};
int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
{
- int ret;
- unsigned int flag = 0;
unsigned long timeout;
pr_debug("Starting secondary CPU %d\n", cpu);
@@ -194,19 +206,8 @@
/* Set preset_lpj to avoid subsequent lpj recalculations */
preset_lpj = loops_per_jiffy;
- if (cpu > 0 && cpu < ARRAY_SIZE(cold_boot_flags))
- flag = cold_boot_flags[cpu];
- else
- __WARN();
-
if (per_cpu(cold_boot_done, cpu) == false) {
- ret = scm_set_boot_addr(virt_to_phys(msm_secondary_startup),
- flag);
- if (ret == 0)
- release_secondary(cpu);
- else
- printk(KERN_DEBUG "Failed to set secondary core boot "
- "address\n");
+ release_secondary(cpu);
per_cpu(cold_boot_done, cpu) = true;
}
@@ -224,9 +225,7 @@
* Note that "pen_release" is the hardware CPU ID, whereas
* "cpu" is Linux's internal ID.
*/
- pen_release = cpu_logical_map(cpu);
- __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
- outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
+ write_pen_release(cpu_logical_map(cpu));
/*
* Send the secondary CPU a soft interrupt, thereby causing
@@ -241,8 +240,6 @@
if (pen_release == -1)
break;
- dmac_inv_range((char *)&pen_release,
- (char *)&pen_release + sizeof(pen_release));
udelay(10);
}
@@ -274,6 +271,28 @@
set_smp_cross_call(gic_raise_softirq);
}
+static int cold_boot_flags[] __initdata = {
+ 0,
+ SCM_FLAG_COLDBOOT_CPU1,
+ SCM_FLAG_COLDBOOT_CPU2,
+ SCM_FLAG_COLDBOOT_CPU3,
+};
+
void __init platform_smp_prepare_cpus(unsigned int max_cpus)
{
+ int cpu, map;
+ unsigned int flags = 0;
+
+ for_each_present_cpu(cpu) {
+ map = cpu_logical_map(cpu);
+ if (map > ARRAY_SIZE(cold_boot_flags)) {
+ set_cpu_present(cpu, false);
+ __WARN();
+ continue;
+ }
+ flags |= cold_boot_flags[map];
+ }
+
+ if (scm_set_boot_addr(virt_to_phys(msm_secondary_startup), flags))
+ pr_warn("Failed to set CPU boot address\n");
}
diff --git a/arch/arm/mach-msm/pm2.c b/arch/arm/mach-msm/pm2.c
index 10c5445..427e39f 100644
--- a/arch/arm/mach-msm/pm2.c
+++ b/arch/arm/mach-msm/pm2.c
@@ -487,7 +487,7 @@
void __iomem *base_ptr;
unsigned int value = 0;
- base_ptr = core1_reset_base();
+ base_ptr = core_reset_base(1);
if (!base_ptr)
return;
diff --git a/arch/arm/mach-msm/restart.c b/arch/arm/mach-msm/restart.c
index 5883b0c..2189747 100644
--- a/arch/arm/mach-msm/restart.c
+++ b/arch/arm/mach-msm/restart.c
@@ -36,6 +36,7 @@
#include <mach/scm.h>
#include "msm_watchdog.h"
#include "timer.h"
+#include "wdog_debug.h"
#define WDT0_RST 0x38
#define WDT0_EN 0x40
@@ -250,8 +251,11 @@
__raw_writel(5*0x31F3, msm_tmr0_base + WDT0_BARK_TIME);
__raw_writel(0x31F3, msm_tmr0_base + WDT0_BITE_TIME);
__raw_writel(1, msm_tmr0_base + WDT0_EN);
- } else
+ } else {
+ /* Needed for 8974: Reset GCC_WDOG_DEBUG register */
+ msm_disable_wdog_debug();
__raw_writel(0, MSM_MPM2_PSHOLD_BASE);
+ }
mdelay(10000);
printk(KERN_ERR "Restarting has failed\n");
diff --git a/arch/arm/mach-msm/rpm-regulator-8960.c b/arch/arm/mach-msm/rpm-regulator-8960.c
index 8fe3571..c5c01c2 100644
--- a/arch/arm/mach-msm/rpm-regulator-8960.c
+++ b/arch/arm/mach-msm/rpm-regulator-8960.c
@@ -325,3 +325,32 @@
{
return &config;
}
+
+struct vreg_config *get_config_8960_pm8917(void)
+{
+ int i;
+
+ /*
+ * PM8917 regulators L24, L25, L26, L27, and L28 require CXO to be ON
+ * while they are enabled. These same regulators on PM8921 do not
+ * require CXO to be ON. Therefore, set the require_cxo flag for these
+ * regulators only when using PM8917.
+ *
+ * Do not apply the workaround to L24 (VDD_MX) because it is always on
+ * and using the TCXO workaround with it would result in additional
+ * latency during every Krait upscaling event.
+ */
+ for (i = 0; i < ARRAY_SIZE(vregs); i++) {
+ switch (vregs[i].id) {
+ case RPM_VREG_ID_PM8921_L25:
+ case RPM_VREG_ID_PM8921_L26:
+ case RPM_VREG_ID_PM8921_L27:
+ case RPM_VREG_ID_PM8921_L28:
+ vregs[i].requires_cxo = true;
+ default:
+ break;
+ }
+ }
+
+ return &config;
+}
diff --git a/arch/arm/mach-msm/rpm-regulator-private.h b/arch/arm/mach-msm/rpm-regulator-private.h
index d55bd73..703335f 100644
--- a/arch/arm/mach-msm/rpm-regulator-private.h
+++ b/arch/arm/mach-msm/rpm-regulator-private.h
@@ -158,11 +158,16 @@
#if defined(CONFIG_MSM_RPM_REGULATOR) && \
(defined(CONFIG_ARCH_MSM8960) || defined(CONFIG_ARCH_APQ8064))
struct vreg_config *get_config_8960(void);
+struct vreg_config *get_config_8960_pm8917(void);
#else
static inline struct vreg_config *get_config_8960(void)
{
return NULL;
}
+static inline struct vreg_config *get_config_8960_pm8917(void)
+{
+ return NULL;
+}
#endif
#if defined(CONFIG_MSM_RPM_REGULATOR) && defined(CONFIG_ARCH_MSM9615)
diff --git a/arch/arm/mach-msm/rpm-regulator-smd.c b/arch/arm/mach-msm/rpm-regulator-smd.c
index a8af9e7..d1c61fe 100644
--- a/arch/arm/mach-msm/rpm-regulator-smd.c
+++ b/arch/arm/mach-msm/rpm-regulator-smd.c
@@ -112,7 +112,7 @@
PARAM(HEAD_ROOM, 1, 0, 0, 1, "hr", 0, 0x7FFFFFFF, "qcom,init-head-room"),
PARAM(QUIET_MODE, 0, 1, 0, 0, "qm", 0, 2, "qcom,init-quiet-mode"),
PARAM(FREQ_REASON, 0, 1, 0, 1, "resn", 0, 8, "qcom,init-freq-reason"),
- PARAM(CORNER, 0, 1, 0, 0, "corn", 0, 6, "qcom,init-voltage-corner"),
+ PARAM(CORNER, 1, 1, 0, 0, "corn", 0, 6, "qcom,init-voltage-corner"),
PARAM(BYPASS, 1, 0, 0, 0, "bypa", 0, 1, "qcom,init-disallow-bypass"),
};
@@ -1037,6 +1037,19 @@
.enable_time = rpm_vreg_enable_time,
};
+static struct regulator_ops ldo_corner_ops = {
+ .enable = rpm_vreg_enable,
+ .disable = rpm_vreg_disable,
+ .is_enabled = rpm_vreg_is_enabled,
+ .set_voltage = rpm_vreg_set_voltage_corner,
+ .get_voltage = rpm_vreg_get_voltage_corner,
+ .list_voltage = rpm_vreg_list_voltage,
+ .set_mode = rpm_vreg_set_mode,
+ .get_mode = rpm_vreg_get_mode,
+ .get_optimum_mode = rpm_vreg_get_optimum_mode,
+ .enable_time = rpm_vreg_enable_time,
+};
+
static struct regulator_ops smps_ops = {
.enable = rpm_vreg_enable,
.disable = rpm_vreg_disable,
@@ -1194,11 +1207,14 @@
/*
* Switch to voltage corner regulator ops if qcom,use-voltage-corner
- * is specified in the device node (SMPS only).
+ * is specified in the device node (SMPS and LDO only).
*/
- if (of_find_property(node, "qcom,use-voltage-corner", NULL)
- && regulator_type == RPM_REGULATOR_SMD_TYPE_SMPS)
- reg->rdesc.ops = &smps_corner_ops;
+ if (of_property_read_bool(node, "qcom,use-voltage-corner")) {
+ if (regulator_type == RPM_REGULATOR_SMD_TYPE_SMPS)
+ reg->rdesc.ops = &smps_corner_ops;
+ else if (regulator_type == RPM_REGULATOR_SMD_TYPE_LDO)
+ reg->rdesc.ops = &ldo_corner_ops;
+ }
if (regulator_type == RPM_REGULATOR_SMD_TYPE_VS)
reg->rdesc.n_voltages = 0;
@@ -1286,7 +1302,7 @@
}
}
- of_property_read_u32(node, "qcom,system_load", ®->system_load);
+ of_property_read_u32(node, "qcom,system-load", ®->system_load);
rpm_vreg_lock(rpm_vreg);
list_add(®->list, &rpm_vreg->reg_list);
diff --git a/arch/arm/mach-msm/rpm-regulator.c b/arch/arm/mach-msm/rpm-regulator.c
index 424a4fe..01543a2 100644
--- a/arch/arm/mach-msm/rpm-regulator.c
+++ b/arch/arm/mach-msm/rpm-regulator.c
@@ -63,6 +63,7 @@
[RPM_VREG_VERSION_9615] = get_config_9615,
[RPM_VREG_VERSION_8930] = get_config_8930,
[RPM_VREG_VERSION_8930_PM8917] = get_config_8930_pm8917,
+ [RPM_VREG_VERSION_8960_PM8917] = get_config_8960_pm8917,
};
static struct rpm_regulator_consumer_mapping *consumer_map;
diff --git a/arch/arm/mach-msm/rpm-smd.c b/arch/arm/mach-msm/rpm-smd.c
index a9d1ed8..7c31e76 100644
--- a/arch/arm/mach-msm/rpm-smd.c
+++ b/arch/arm/mach-msm/rpm-smd.c
@@ -149,8 +149,6 @@
uint32_t id_ack;
};
-static int irq_process;
-
LIST_HEAD(msm_rpm_ack_list);
static void msm_rpm_notify_sleep_chain(struct rpm_message_header *hdr,
@@ -518,20 +516,18 @@
uint32_t msg_id;
int errno;
char buf[MAX_ERR_BUFFER_SIZE] = {0};
- unsigned long flags;
- while (smd_is_pkt_avail(msm_rpm_data.ch_info) && !irq_process) {
- spin_lock_irqsave(&msm_rpm_data.smd_lock_read, flags);
+ if (!spin_trylock(&msm_rpm_data.smd_lock_read))
+ return;
+ while (smd_is_pkt_avail(msm_rpm_data.ch_info)) {
if (msm_rpm_read_smd_data(buf)) {
- spin_unlock_irqrestore(&msm_rpm_data.smd_lock_read,
- flags);
break;
}
msg_id = msm_rpm_get_msg_id_from_ack(buf);
errno = msm_rpm_get_error_from_ack(buf);
msm_rpm_process_ack(msg_id, errno);
- spin_unlock_irqrestore(&msm_rpm_data.smd_lock_read, flags);
}
+ spin_unlock(&msm_rpm_data.smd_lock_read);
}
#define DEBUG_PRINT_BUFFER_SIZE 512
@@ -783,7 +779,14 @@
int msm_rpm_send_request(struct msm_rpm_request *handle)
{
- return msm_rpm_send_data(handle, MSM_RPM_MSG_REQUEST_TYPE, false);
+ int ret;
+ static DEFINE_MUTEX(send_mtx);
+
+ mutex_lock(&send_mtx);
+ ret = msm_rpm_send_data(handle, MSM_RPM_MSG_REQUEST_TYPE, false);
+ mutex_unlock(&send_mtx);
+
+ return ret;
}
EXPORT_SYMBOL(msm_rpm_send_request);
@@ -837,7 +840,6 @@
return 0;
spin_lock_irqsave(&msm_rpm_data.smd_lock_read, flags);
- irq_process = true;
elem = msm_rpm_get_entry_from_msg_id(msg_id);
@@ -868,7 +870,6 @@
rc = elem->errno;
msm_rpm_free_list_entry(elem);
wait_ack_cleanup:
- irq_process = false;
spin_unlock_irqrestore(&msm_rpm_data.smd_lock_read, flags);
return rc;
}
diff --git a/arch/arm/mach-msm/rpm_resources.c b/arch/arm/mach-msm/rpm_resources.c
index 3ab5a98..dfed3aa 100644
--- a/arch/arm/mach-msm/rpm_resources.c
+++ b/arch/arm/mach-msm/rpm_resources.c
@@ -1132,7 +1132,8 @@
static int __init msm_rpmrs_l2_init(void)
{
if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm8930aa() ||
- cpu_is_apq8064() || cpu_is_msm8627() || cpu_is_msm8960ab()) {
+ cpu_is_apq8064() || cpu_is_msm8627() || cpu_is_msm8960ab() ||
+ cpu_is_apq8064ab()) {
msm_pm_set_l2_flush_flag(0);
diff --git a/arch/arm/mach-msm/scm-pas.h b/arch/arm/mach-msm/scm-pas.h
index dd24e20..8da1d75 100644
--- a/arch/arm/mach-msm/scm-pas.h
+++ b/arch/arm/mach-msm/scm-pas.h
@@ -25,8 +25,29 @@
PAS_VIDC,
};
+#ifdef CONFIG_MSM_PIL
extern int pas_init_image(enum pas_id id, const u8 *metadata, size_t size);
extern int pas_auth_and_reset(enum pas_id id);
extern int pas_shutdown(enum pas_id id);
extern int pas_supported(enum pas_id id);
+#else
+static inline int pas_init_image(enum pas_id id, const u8 *metadata,
+ size_t size)
+{
+ return 0;
+}
+static inline int pas_auth_and_reset(enum pas_id id)
+{
+ return 0;
+}
+static inline int pas_shutdown(enum pas_id id)
+{
+ return 0;
+}
+static inline int pas_supported(enum pas_id id)
+{
+ return 0;
+}
+#endif
+
#endif
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index b228147..c1e2421 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -35,6 +35,7 @@
#include <linux/wakelock.h>
#include <linux/notifier.h>
#include <linux/sort.h>
+#include <linux/suspend.h>
#include <mach/msm_smd.h>
#include <mach/msm_iomap.h>
#include <mach/system.h>
@@ -553,6 +554,26 @@
}
}
+static int smsm_pm_notifier(struct notifier_block *nb,
+ unsigned long event, void *unused)
+{
+ switch (event) {
+ case PM_SUSPEND_PREPARE:
+ smsm_change_state(SMSM_APPS_STATE, SMSM_PROC_AWAKE, 0);
+ break;
+
+ case PM_POST_SUSPEND:
+ smsm_change_state(SMSM_APPS_STATE, 0, SMSM_PROC_AWAKE);
+ break;
+ }
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block smsm_pm_nb = {
+ .notifier_call = smsm_pm_notifier,
+ .priority = 0,
+};
+
void smd_diag(void)
{
char *x;
@@ -2545,6 +2566,12 @@
return i;
wmb();
+
+ smsm_pm_notifier(&smsm_pm_nb, PM_POST_SUSPEND, NULL);
+ i = register_pm_notifier(&smsm_pm_nb);
+ if (i)
+ pr_err("%s: power state notif error %d\n", __func__, i);
+
return 0;
}
@@ -3513,7 +3540,7 @@
static struct restart_notifier_block restart_notifiers[] = {
{SMD_MODEM, "modem", .nb.notifier_call = restart_notifier_cb},
{SMD_Q6, "lpass", .nb.notifier_call = restart_notifier_cb},
- {SMD_WCNSS, "riva", .nb.notifier_call = restart_notifier_cb},
+ {SMD_WCNSS, "wcnss", .nb.notifier_call = restart_notifier_cb},
{SMD_DSPS, "dsps", .nb.notifier_call = restart_notifier_cb},
{SMD_MODEM, "gss", .nb.notifier_call = restart_notifier_cb},
{SMD_Q6, "adsp", .nb.notifier_call = restart_notifier_cb},
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 86de130..ac077e9 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -286,6 +286,9 @@
/* 8092 IDs */
[146] = MSM_CPU_8092,
+ /* 8064AB IDs */
+ [153] = MSM_CPU_8064AB,
+
/* Uninitialized IDs are not known to run Linux.
MSM_CPU_UNKNOWN is set to 0 to ensure these IDs are
considered as unknown CPU. */
diff --git a/arch/arm/mach-msm/spm-v2.c b/arch/arm/mach-msm/spm-v2.c
index 1eab9bf..f0d3d06 100644
--- a/arch/arm/mach-msm/spm-v2.c
+++ b/arch/arm/mach-msm/spm-v2.c
@@ -179,7 +179,7 @@
}
}
-static inline uint32_t msm_spm_drv_get_sts_curr_pmic_data(
+uint32_t msm_spm_drv_get_sts_curr_pmic_data(
struct msm_spm_driver_data *dev)
{
if (dev->major == SAW2_MAJOR_2) {
diff --git a/arch/arm/mach-msm/spm.h b/arch/arm/mach-msm/spm.h
index e81e335..09ee26a 100644
--- a/arch/arm/mach-msm/spm.h
+++ b/arch/arm/mach-msm/spm.h
@@ -141,6 +141,13 @@
int msm_spm_set_vdd(unsigned int cpu, unsigned int vlevel);
/**
+ * msm_spm_get_vdd(): Get core voltage
+ * @cpu: core id
+ * @return: Returns encoded PMIC data.
+ */
+unsigned int msm_spm_get_vdd(unsigned int cpu);
+
+/**
* msm_spm_turn_on_cpu_rail(): Power on cpu rail before turning on core
* @cpu: core id
*/
@@ -239,6 +246,11 @@
return -ENOSYS;
}
+static inline unsigned int msm_spm_get_vdd(unsigned int cpu)
+{
+ return 0;
+}
+
static inline void msm_spm_reinit(void)
{
/* empty */
diff --git a/arch/arm/mach-msm/spm_devices.c b/arch/arm/mach-msm/spm_devices.c
index b87b0f1..2cbed94 100644
--- a/arch/arm/mach-msm/spm_devices.c
+++ b/arch/arm/mach-msm/spm_devices.c
@@ -75,6 +75,15 @@
}
EXPORT_SYMBOL(msm_spm_set_vdd);
+unsigned int msm_spm_get_vdd(unsigned int cpu)
+{
+ struct msm_spm_device *dev;
+
+ dev = &per_cpu(msm_cpu_spm_device, cpu);
+ return msm_spm_drv_get_sts_curr_pmic_data(&dev->reg_data);
+}
+EXPORT_SYMBOL(msm_spm_get_vdd);
+
static int msm_spm_dev_set_low_power_mode(struct msm_spm_device *dev,
unsigned int mode, bool notify_rpm)
{
@@ -159,7 +168,8 @@
reg = saw_bases[cpu];
if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm8930aa() ||
- cpu_is_apq8064() || cpu_is_msm8627() || cpu_is_msm8960ab()) {
+ cpu_is_apq8064() || cpu_is_msm8627() || cpu_is_msm8960ab() ||
+ cpu_is_apq8064ab()) {
val = 0xA4;
reg += 0x14;
timeout = 512;
diff --git a/arch/arm/mach-msm/spm_driver.h b/arch/arm/mach-msm/spm_driver.h
index f272adb0..4cdfd33 100644
--- a/arch/arm/mach-msm/spm_driver.h
+++ b/arch/arm/mach-msm/spm_driver.h
@@ -35,6 +35,8 @@
uint32_t addr);
int msm_spm_drv_set_vdd(struct msm_spm_driver_data *dev,
unsigned int vlevel);
+uint32_t msm_spm_drv_get_sts_curr_pmic_data(
+ struct msm_spm_driver_data *dev);
int msm_spm_drv_write_seq_data(struct msm_spm_driver_data *dev,
uint8_t *cmd, uint32_t *offset);
void msm_spm_drv_flush_seq_entry(struct msm_spm_driver_data *dev);
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index 668f4cc..b361d9d 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -966,7 +966,7 @@
if (cpu_is_msm8x60() || cpu_is_msm8960() || cpu_is_apq8064() ||
cpu_is_msm8930() || cpu_is_msm8930aa() || cpu_is_msm8627() ||
- cpu_is_msm8960ab())
+ cpu_is_msm8960ab() || cpu_is_apq8064ab())
__raw_writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL);
if (__get_cpu_var(first_boot)) {
@@ -1064,7 +1064,7 @@
dgt->flags |= MSM_CLOCK_FLAGS_UNSTABLE_COUNT;
} else if (cpu_is_msm8960() || cpu_is_apq8064() || cpu_is_msm8930() ||
cpu_is_msm8930aa() || cpu_is_msm8627() ||
- cpu_is_msm8960ab()) {
+ cpu_is_msm8960ab() || cpu_is_apq8064ab()) {
global_timer_offset = MSM_TMR0_BASE - MSM_TMR_BASE;
dgt->freq = 6750000;
__raw_writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL);
@@ -1127,7 +1127,7 @@
if (cpu_is_msm8x60() || cpu_is_msm8960() || cpu_is_apq8064() ||
cpu_is_msm8930() || cpu_is_msm9615() || cpu_is_msm8625() ||
cpu_is_msm8627() || cpu_is_msm8930aa() ||
- cpu_is_msm8960ab()) {
+ cpu_is_msm8960ab() || cpu_is_apq8064ab()) {
clock->percpu_evt = alloc_percpu(struct clock_event_device *);
if (!clock->percpu_evt) {
pr_err("msm_timer_init: memory allocation "
diff --git a/arch/arm/mach-msm/wcnss-ssr-8960.c b/arch/arm/mach-msm/wcnss-ssr-8960.c
deleted file mode 100644
index f014df9..0000000
--- a/arch/arm/mach-msm/wcnss-ssr-8960.c
+++ /dev/null
@@ -1,277 +0,0 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * 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/interrupt.h>
-#include <linux/reboot.h>
-#include <linux/workqueue.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/wcnss_wlan.h>
-#include <linux/err.h>
-#include <asm/mach-types.h>
-#include <mach/irqs.h>
-#include <mach/scm.h>
-#include <mach/subsystem_restart.h>
-#include <mach/subsystem_notif.h>
-#include <mach/peripheral-loader.h>
-#include "smd_private.h"
-#include "ramdump.h"
-
-#define MODULE_NAME "wcnss_8960"
-#define MAX_BUF_SIZE 0x51
-
-
-
-static struct delayed_work cancel_vote_work;
-static void *riva_ramdump_dev;
-static int riva_crash;
-static int ss_restart_inprogress;
-static int enable_riva_ssr;
-static struct subsys_device *riva_8960_dev;
-
-static void smsm_state_cb_hdlr(void *data, uint32_t old_state,
- uint32_t new_state)
-{
- char *smem_reset_reason;
- char buffer[MAX_BUF_SIZE];
- unsigned smem_reset_size;
- unsigned size;
-
- riva_crash = true;
-
- pr_err("%s: smsm state changed\n", MODULE_NAME);
-
- if (!(new_state & SMSM_RESET))
- return;
-
- if (ss_restart_inprogress) {
- pr_err("%s: Ignoring smsm reset req, restart in progress\n",
- MODULE_NAME);
- return;
- }
-
- if (!enable_riva_ssr)
- panic(MODULE_NAME ": SMSM reset request received from Riva");
-
- smem_reset_reason = smem_get_entry(SMEM_SSR_REASON_WCNSS0,
- &smem_reset_size);
-
- if (!smem_reset_reason || !smem_reset_size) {
- pr_err("%s: wcnss subsystem failure reason: %s\n",
- __func__, "(unknown, smem_get_entry failed)");
- } else if (!smem_reset_reason[0]) {
- pr_err("%s: wcnss subsystem failure reason: %s\n",
- __func__, "(unknown, init string found)");
- } else {
- size = smem_reset_size < MAX_BUF_SIZE ? smem_reset_size :
- (MAX_BUF_SIZE - 1);
- memcpy(buffer, smem_reset_reason, size);
- buffer[size] = '\0';
- pr_err("%s: wcnss subsystem failure reason: %s\n",
- __func__, buffer);
- memset(smem_reset_reason, 0, smem_reset_size);
- wmb();
- }
-
- ss_restart_inprogress = true;
- subsystem_restart_dev(riva_8960_dev);
-}
-
-static irqreturn_t riva_wdog_bite_irq_hdlr(int irq, void *dev_id)
-{
- riva_crash = true;
-
- if (ss_restart_inprogress) {
- pr_err("%s: Ignoring riva bite irq, restart in progress\n",
- MODULE_NAME);
- return IRQ_HANDLED;
- }
-
- if (!enable_riva_ssr)
- panic(MODULE_NAME ": Watchdog bite received from Riva");
-
- ss_restart_inprogress = true;
- subsystem_restart_dev(riva_8960_dev);
-
- return IRQ_HANDLED;
-}
-
-/* SMSM reset Riva */
-static void smsm_riva_reset(void)
-{
- /* per SS reset request bit is not available now,
- * all SS host modules are setting this bit
- * This is still under discussion*/
- smsm_change_state(SMSM_APPS_STATE, SMSM_RESET, SMSM_RESET);
-}
-
-static void riva_post_bootup(struct work_struct *work)
-{
- struct platform_device *pdev = wcnss_get_platform_device();
- struct wcnss_wlan_config *pwlanconfig = wcnss_get_wlan_config();
-
- pr_debug(MODULE_NAME ": Cancel APPS vote for Iris & Riva\n");
-
- wcnss_wlan_power(&pdev->dev, pwlanconfig,
- WCNSS_WLAN_SWITCH_OFF);
-}
-
-/* Subsystem handlers */
-static int riva_shutdown(const struct subsys_desc *subsys)
-{
- pil_force_shutdown("wcnss");
- flush_delayed_work(&cancel_vote_work);
- wcnss_flush_delayed_boot_votes();
- disable_irq_nosync(RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ);
-
- return 0;
-}
-
-static int riva_powerup(const struct subsys_desc *subsys)
-{
- struct platform_device *pdev = wcnss_get_platform_device();
- struct wcnss_wlan_config *pwlanconfig = wcnss_get_wlan_config();
- int ret = -1;
-
- if (pdev && pwlanconfig)
- ret = wcnss_wlan_power(&pdev->dev, pwlanconfig,
- WCNSS_WLAN_SWITCH_ON);
- /* delay PIL operation, this SSR may be happening soon after kernel
- * resumes because of a SMSM RESET by Riva when APPS was suspended.
- * PIL fails to locate the images without this delay */
- if (!ret) {
- msleep(1000);
- pil_force_boot("wcnss");
- }
- ss_restart_inprogress = false;
- enable_irq(RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ);
- schedule_delayed_work(&cancel_vote_work, msecs_to_jiffies(5000));
-
- return ret;
-}
-
-/* 5MB RAM segments for Riva SS */
-static struct ramdump_segment riva_segments[] = {{0x8f200000,
- 0x8f700000 - 0x8f200000} };
-
-static int riva_ramdump(int enable, const struct subsys_desc *subsys)
-{
- pr_debug("%s: enable[%d]\n", MODULE_NAME, enable);
- if (enable)
- return do_ramdump(riva_ramdump_dev,
- riva_segments,
- ARRAY_SIZE(riva_segments));
- else
- return 0;
-}
-
-/* Riva crash handler */
-static void riva_crash_shutdown(const struct subsys_desc *subsys)
-{
- pr_err("%s: crash shutdown : %d\n", MODULE_NAME, riva_crash);
- if (riva_crash != true)
- smsm_riva_reset();
-}
-
-static struct subsys_desc riva_8960 = {
- .name = "riva",
- .shutdown = riva_shutdown,
- .powerup = riva_powerup,
- .ramdump = riva_ramdump,
- .crash_shutdown = riva_crash_shutdown
-};
-
-static int enable_riva_ssr_set(const char *val, struct kernel_param *kp)
-{
- int ret;
-
- ret = param_set_int(val, kp);
- if (ret)
- return ret;
-
- if (enable_riva_ssr)
- pr_info(MODULE_NAME ": Subsystem restart activated for riva.\n");
-
- return 0;
-}
-
-module_param_call(enable_riva_ssr, enable_riva_ssr_set, param_get_int,
- &enable_riva_ssr, S_IRUGO | S_IWUSR);
-
-static int __init riva_restart_init(void)
-{
- riva_8960_dev = subsys_register(&riva_8960);
- if (IS_ERR(riva_8960_dev))
- return PTR_ERR(riva_8960_dev);
- return 0;
-}
-
-static int __init riva_ssr_module_init(void)
-{
- int ret;
-
- if (machine_is_mpq8064_hrd()) {
- pr_err("Riva not supported on this target\n");
- return 0;
- }
-
- ret = smsm_state_cb_register(SMSM_WCNSS_STATE, SMSM_RESET,
- smsm_state_cb_hdlr, 0);
- if (ret < 0) {
- pr_err("%s: Unable to register smsm callback for Riva Reset! %d\n",
- MODULE_NAME, ret);
- goto out;
- }
- ret = request_irq(RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ,
- riva_wdog_bite_irq_hdlr, IRQF_TRIGGER_HIGH,
- "riva_wdog", NULL);
-
- if (ret < 0) {
- pr_err("%s: Unable to register for Riva bite interrupt (%d)\n",
- MODULE_NAME, ret);
- goto out;
- }
- ret = riva_restart_init();
- if (ret < 0) {
- pr_err("%s: Unable to register with ssr. (%d)\n",
- MODULE_NAME, ret);
- goto out;
- }
- riva_ramdump_dev = create_ramdump_device("riva");
- if (!riva_ramdump_dev) {
- pr_err("%s: Unable to create ramdump device.\n",
- MODULE_NAME);
- ret = -ENOMEM;
- goto out;
- }
- INIT_DELAYED_WORK(&cancel_vote_work, riva_post_bootup);
-
- pr_info("%s: module initialized\n", MODULE_NAME);
-out:
- return ret;
-}
-
-static void __exit riva_ssr_module_exit(void)
-{
- if (machine_is_mpq8064_hrd())
- return;
- subsys_unregister(riva_8960_dev);
- free_irq(RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ, NULL);
-}
-
-module_init(riva_ssr_module_init);
-module_exit(riva_ssr_module_exit);
-
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/bluetooth/hci_ibs.c b/drivers/bluetooth/hci_ibs.c
index 6253605..acff5a5 100644
--- a/drivers/bluetooth/hci_ibs.c
+++ b/drivers/bluetooth/hci_ibs.c
@@ -254,13 +254,14 @@
struct ibs_struct *ibs = container_of(work, struct ibs_struct,
ws_awake_device);
struct hci_uart *hu = (struct hci_uart *)ibs->ibs_hu;
+ unsigned long flags;
BT_DBG(" %p ", hu);
/* Vote for serial clock */
ibs_msm_serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_ON, hu);
- spin_lock(&ibs->hci_ibs_lock);
+ spin_lock_irqsave(&ibs->hci_ibs_lock, flags);
/* send wake indication to device */
if (send_hci_ibs_cmd(HCI_IBS_WAKE_IND, hu) < 0)
@@ -271,7 +272,8 @@
/* start retransmit timer */
mod_timer(&ibs->wake_retrans_timer, jiffies + wake_retrans);
- spin_unlock(&ibs->hci_ibs_lock);
+ spin_unlock_irqrestore(&ibs->hci_ibs_lock, flags);
+
}
static void ibs_wq_awake_rx(struct work_struct *work)
@@ -279,12 +281,14 @@
struct ibs_struct *ibs = container_of(work, struct ibs_struct,
ws_awake_rx);
struct hci_uart *hu = (struct hci_uart *)ibs->ibs_hu;
+ unsigned long flags;
BT_DBG(" %p ", hu);
ibs_msm_serial_clock_vote(HCI_IBS_RX_VOTE_CLOCK_ON, hu);
- spin_lock(&ibs->hci_ibs_lock);
+ spin_lock_irqsave(&ibs->hci_ibs_lock, flags);
+
ibs->rx_ibs_state = HCI_IBS_RX_AWAKE;
/* Always acknowledge device wake up,
* sending IBS message doesn't count as TX ON
@@ -294,7 +298,8 @@
ibs->ibs_sent_wacks++; /* debug */
- spin_unlock(&ibs->hci_ibs_lock);
+ spin_unlock_irqrestore(&ibs->hci_ibs_lock, flags);
+
/* actually send the packets */
hci_uart_tx_wakeup(hu);
diff --git a/drivers/char/diag/Makefile b/drivers/char/diag/Makefile
index ea75ffd..6ecc970 100644
--- a/drivers/char/diag/Makefile
+++ b/drivers/char/diag/Makefile
@@ -2,4 +2,4 @@
obj-$(CONFIG_DIAG_SDIO_PIPE) += diagfwd_sdio.o
obj-$(CONFIG_DIAG_BRIDGE_CODE) += diagfwd_hsic.o
obj-$(CONFIG_DIAG_BRIDGE_CODE) += diagfwd_smux.o
-diagchar-objs := diagchar_core.o diagchar_hdlc.o diagfwd.o diagmem.o diagfwd_cntl.o diag_dci.o
+diagchar-objs := diagchar_core.o diagchar_hdlc.o diagfwd.o diagmem.o diagfwd_cntl.o diag_dci.o diag_masks.o diag_debugfs.o
diff --git a/drivers/char/diag/diag_debugfs.c b/drivers/char/diag/diag_debugfs.c
new file mode 100644
index 0000000..ed0f08e
--- /dev/null
+++ b/drivers/char/diag/diag_debugfs.c
@@ -0,0 +1,305 @@
+/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * 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.
+ */
+
+#ifdef CONFIG_DEBUG_FS
+
+#include <linux/slab.h>
+#include <linux/debugfs.h>
+#include "diagchar.h"
+#include "diagfwd.h"
+
+#define DEBUG_BUF_SIZE 4096
+static struct dentry *diag_dbgfs_dent;
+static int diag_dbgfs_table_index;
+
+static ssize_t diag_dbgfs_read_status(struct file *file, char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ char *buf;
+ int ret;
+
+ buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
+ if (!buf) {
+ pr_err("diag: %s, Error allocating memory\n", __func__);
+ return -ENOMEM;
+ }
+
+ ret = scnprintf(buf, DEBUG_BUF_SIZE,
+ "modem ch: 0x%x\n"
+ "lpass ch: 0x%x\n"
+ "riva ch: 0x%x\n"
+ "dci ch: 0x%x\n"
+ "modem cntl_ch: 0x%x\n"
+ "lpass cntl_ch: 0x%x\n"
+ "riva cntl_ch: 0x%x\n"
+ "CPU Tools id: %d\n"
+ "Apps only: %d\n"
+ "Apps master: %d\n"
+ "Check Polling Response: %d\n"
+ "polling_reg_flag: %d\n"
+ "uses device tree: %d\n"
+ "in_busy_1: %d\n"
+ "in_busy_2: %d\n"
+ "in_busy_lpass_1: %d\n"
+ "in_busy_lpass_2: %d\n"
+ "in_busy_wcnss_1: %d\n"
+ "in_busy_wcnss_2: %d\n"
+ "in_busy_dci: %d\n"
+ "logging_mode: %d\n",
+ (unsigned int)driver->ch,
+ (unsigned int)driver->chlpass,
+ (unsigned int)driver->ch_wcnss,
+ (unsigned int)driver->ch_dci,
+ (unsigned int)driver->ch_cntl,
+ (unsigned int)driver->chlpass_cntl,
+ (unsigned int)driver->ch_wcnss_cntl,
+ chk_config_get_id(),
+ chk_apps_only(),
+ chk_apps_master(),
+ chk_polling_response(),
+ driver->polling_reg_flag,
+ driver->use_device_tree,
+ driver->in_busy_1,
+ driver->in_busy_2,
+ driver->in_busy_lpass_1,
+ driver->in_busy_lpass_2,
+ driver->in_busy_wcnss_1,
+ driver->in_busy_wcnss_2,
+ driver->in_busy_dci,
+ driver->logging_mode);
+
+#ifdef CONFIG_DIAG_OVER_USB
+ ret += scnprintf(buf+ret, DEBUG_BUF_SIZE,
+ "usb_connected: %d\n",
+ driver->usb_connected);
+#endif
+ ret = simple_read_from_buffer(ubuf, count, ppos, buf, ret);
+
+ kfree(buf);
+ return ret;
+}
+
+static ssize_t diag_dbgfs_read_workpending(struct file *file,
+ char __user *ubuf, size_t count, loff_t *ppos)
+{
+ char *buf;
+ int ret;
+
+ buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
+ if (!buf) {
+ pr_err("diag: %s, Error allocating memory\n", __func__);
+ return -ENOMEM;
+ }
+
+ ret = scnprintf(buf, DEBUG_BUF_SIZE,
+ "Pending status for work_stucts:\n"
+ "diag_drain_work: %d\n"
+ "diag_read_smd_work: %d\n"
+ "diag_read_smd_cntl_work: %d\n"
+ "diag_read_smd_lpass_work: %d\n"
+ "diag_read_smd_lpass_cntl_work: %d\n"
+ "diag_read_smd_wcnss_work: %d\n"
+ "diag_read_smd_wcnss_cntl_work: %d\n"
+ "diag_modem_mask_update_work: %d\n"
+ "diag_lpass_mask_update_work: %d\n"
+ "diag_wcnss_mask_update_work: %d\n"
+ "diag_read_smd_dci_work: %d\n",
+ work_pending(&(driver->diag_drain_work)),
+ work_pending(&(driver->diag_read_smd_work)),
+ work_pending(&(driver->diag_read_smd_cntl_work)),
+ work_pending(&(driver->diag_read_smd_lpass_work)),
+ work_pending(&(driver->diag_read_smd_lpass_cntl_work)),
+ work_pending(&(driver->diag_read_smd_wcnss_work)),
+ work_pending(&(driver->diag_read_smd_wcnss_cntl_work)),
+ work_pending(&(driver->diag_modem_mask_update_work)),
+ work_pending(&(driver->diag_lpass_mask_update_work)),
+ work_pending(&(driver->diag_wcnss_mask_update_work)),
+ work_pending(&(driver->diag_read_smd_dci_work)));
+
+#ifdef CONFIG_DIAG_OVER_USB
+ ret += scnprintf(buf+ret, DEBUG_BUF_SIZE,
+ "diag_proc_hdlc_work: %d\n"
+ "diag_read_work: %d\n",
+ work_pending(&(driver->diag_proc_hdlc_work)),
+ work_pending(&(driver->diag_read_work)));
+#endif
+ ret = simple_read_from_buffer(ubuf, count, ppos, buf, ret);
+
+ kfree(buf);
+ return ret;
+}
+
+static ssize_t diag_dbgfs_read_table(struct file *file, char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ char *buf;
+ int ret = 0;
+ int i;
+ int bytes_remaining;
+ int bytes_in_buffer = 0;
+ int bytes_written;
+ int buf_size = (DEBUG_BUF_SIZE < count) ? DEBUG_BUF_SIZE : count;
+
+ if (diag_dbgfs_table_index >= diag_max_reg) {
+ /* Done. Reset to prepare for future requests */
+ diag_dbgfs_table_index = 0;
+ return 0;
+ }
+
+ buf = kzalloc(sizeof(char) * buf_size, GFP_KERNEL);
+ if (!buf) {
+ pr_err("diag: %s, Error allocating memory\n", __func__);
+ return -ENOMEM;
+ }
+
+ bytes_remaining = buf_size;
+ for (i = diag_dbgfs_table_index; i < diag_max_reg; i++) {
+ /* Do not process empty entries in the table */
+ if (driver->table[i].process_id == 0)
+ continue;
+
+ bytes_written = scnprintf(buf+bytes_in_buffer, bytes_remaining,
+ "i: %3d, cmd_code: %4x, subsys_id: %4x, "
+ "client: %2d, cmd_code_lo: %4x, "
+ "cmd_code_hi: %4x, process_id: %5d\n",
+ i,
+ driver->table[i].cmd_code,
+ driver->table[i].subsys_id,
+ driver->table[i].client_id,
+ driver->table[i].cmd_code_lo,
+ driver->table[i].cmd_code_hi,
+ driver->table[i].process_id);
+
+ bytes_in_buffer += bytes_written;
+
+ /* Check if there is room to add another table entry */
+ bytes_remaining = buf_size - bytes_in_buffer;
+ if (bytes_remaining < bytes_written)
+ break;
+ }
+ diag_dbgfs_table_index = i;
+
+ *ppos = 0;
+ ret = simple_read_from_buffer(ubuf, count, ppos, buf, bytes_in_buffer);
+
+ kfree(buf);
+ return ret;
+}
+
+#ifdef CONFIG_DIAG_BRIDGE_CODE
+static ssize_t diag_dbgfs_read_hsic(struct file *file, char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ char *buf;
+ int ret;
+
+ buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
+ if (!buf) {
+ pr_err("diag: %s, Error allocating memory\n", __func__);
+ return -ENOMEM;
+ }
+
+ ret = scnprintf(buf, DEBUG_BUF_SIZE,
+ "hsic ch: %d\n"
+ "hsic_inited: %d\n"
+ "hsic enabled: %d\n"
+ "hsic_opened: %d\n"
+ "hsic_suspend: %d\n"
+ "in_busy_hsic_read_on_device: %d\n"
+ "in_busy_hsic_write: %d\n"
+ "count_hsic_pool: %d\n"
+ "count_hsic_write_pool: %d\n"
+ "diag_hsic_pool: %x\n"
+ "diag_hsic_write_pool: %x\n"
+ "write_len_mdm: %d\n"
+ "num_hsic_buf_tbl_entries: %d\n"
+ "usb_mdm_connected: %d\n"
+ "diag_read_mdm_work: %d\n"
+ "diag_read_hsic_work: %d\n"
+ "diag_disconnect_work: %d\n"
+ "diag_usb_read_complete_work: %d\n",
+ driver->hsic_ch,
+ driver->hsic_inited,
+ driver->hsic_device_enabled,
+ driver->hsic_device_opened,
+ driver->hsic_suspend,
+ driver->in_busy_hsic_read_on_device,
+ driver->in_busy_hsic_write,
+ driver->count_hsic_pool,
+ driver->count_hsic_write_pool,
+ (unsigned int)driver->diag_hsic_pool,
+ (unsigned int)driver->diag_hsic_write_pool,
+ driver->write_len_mdm,
+ driver->num_hsic_buf_tbl_entries,
+ driver->usb_mdm_connected,
+ work_pending(&(driver->diag_read_mdm_work)),
+ work_pending(&(driver->diag_read_hsic_work)),
+ work_pending(&(driver->diag_disconnect_work)),
+ work_pending(&(driver->diag_usb_read_complete_work)));
+
+ ret = simple_read_from_buffer(ubuf, count, ppos, buf, ret);
+
+ kfree(buf);
+ return ret;
+}
+
+const struct file_operations diag_dbgfs_hsic_ops = {
+ .read = diag_dbgfs_read_hsic,
+};
+#endif
+
+const struct file_operations diag_dbgfs_status_ops = {
+ .read = diag_dbgfs_read_status,
+};
+
+const struct file_operations diag_dbgfs_table_ops = {
+ .read = diag_dbgfs_read_table,
+};
+
+const struct file_operations diag_dbgfs_workpending_ops = {
+ .read = diag_dbgfs_read_workpending,
+};
+
+void diag_debugfs_init(void)
+{
+ diag_dbgfs_dent = debugfs_create_dir("diag", 0);
+ if (IS_ERR(diag_dbgfs_dent))
+ return;
+
+ debugfs_create_file("status", 0444, diag_dbgfs_dent, 0,
+ &diag_dbgfs_status_ops);
+
+ debugfs_create_file("table", 0444, diag_dbgfs_dent, 0,
+ &diag_dbgfs_table_ops);
+
+ debugfs_create_file("work_pending", 0444, diag_dbgfs_dent, 0,
+ &diag_dbgfs_workpending_ops);
+
+#ifdef CONFIG_DIAG_BRIDGE_CODE
+ debugfs_create_file("hsic", 0444, diag_dbgfs_dent, 0,
+ &diag_dbgfs_hsic_ops);
+#endif
+
+ diag_dbgfs_table_index = 0;
+}
+
+void diag_debugfs_cleanup(void)
+{
+ if (diag_dbgfs_dent) {
+ debugfs_remove_recursive(diag_dbgfs_dent);
+ diag_dbgfs_dent = NULL;
+ }
+}
+#else
+void diag_debugfs_init(void) { }
+void diag_debugfs_cleanup(void) { }
+#endif
diff --git a/drivers/char/diag/diag_debugfs.h b/drivers/char/diag/diag_debugfs.h
new file mode 100644
index 0000000..4bc8b0f
--- /dev/null
+++ b/drivers/char/diag/diag_debugfs.h
@@ -0,0 +1,19 @@
+/* Copyright (c)2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef DIAG_DEBUGFS_H
+#define DIAG_DEBUGFS_H
+
+void diag_debugfs_init(void);
+void diag_debugfs_cleanup(void);
+
+#endif
diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c
new file mode 100644
index 0000000..5316548
--- /dev/null
+++ b/drivers/char/diag/diag_masks.c
@@ -0,0 +1,790 @@
+/* Copyright (c) 2008-2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/diagchar.h>
+#include <linux/kmemleak.h>
+#include <linux/workqueue.h>
+#include "diagchar.h"
+#include "diagfwd_cntl.h"
+#include "diag_masks.h"
+
+int diag_event_config;
+int diag_event_num_bytes;
+
+#define ALL_EQUIP_ID 100
+#define ALL_SSID -1
+#define MAX_SSID_PER_RANGE 100
+
+struct mask_info {
+ int equip_id;
+ int num_items;
+ int index;
+};
+
+#define CREATE_MSG_MASK_TBL_ROW(XX) \
+do { \
+ *(int *)(msg_mask_tbl_ptr) = MSG_SSID_ ## XX; \
+ msg_mask_tbl_ptr += 4; \
+ *(int *)(msg_mask_tbl_ptr) = MSG_SSID_ ## XX ## _LAST; \
+ msg_mask_tbl_ptr += 4; \
+ /* mimic the last entry as actual_last while creation */ \
+ *(int *)(msg_mask_tbl_ptr) = MSG_SSID_ ## XX ## _LAST; \
+ msg_mask_tbl_ptr += 4; \
+ /* increment by MAX_SSID_PER_RANGE cells */ \
+ msg_mask_tbl_ptr += MAX_SSID_PER_RANGE * sizeof(int); \
+} while (0)
+
+#define WAIT_FOR_SMD(num_delays, delay_time) \
+do { \
+ int count; \
+ for (count = 0; count < (num_delays); count++) \
+ udelay((delay_time)); \
+} while (0)
+
+static void diag_print_mask_table(void)
+{
+/* Enable this to print mask table when updated */
+#ifdef MASK_DEBUG
+ int first, last, actual_last;
+ uint8_t *ptr = driver->msg_masks;
+ int i = 0;
+ pr_info("diag: F3 message mask table\n");
+ while (*(uint32_t *)(ptr + 4)) {
+ first = *(uint32_t *)ptr;
+ ptr += 4;
+ last = *(uint32_t *)ptr;
+ ptr += 4;
+ actual_last = *(uint32_t *)ptr;
+ ptr += 4;
+ pr_info("diag: SSID %d, %d - %d\n", first, last, actual_last);
+ for (i = 0 ; i <= actual_last - first ; i++)
+ pr_info("diag: MASK:%x\n", *((uint32_t *)ptr + i));
+ ptr += MAX_SSID_PER_RANGE*4;
+ }
+#endif
+}
+
+void diag_create_msg_mask_table(void)
+{
+ uint8_t *msg_mask_tbl_ptr = driver->msg_masks;
+
+ CREATE_MSG_MASK_TBL_ROW(0);
+ CREATE_MSG_MASK_TBL_ROW(1);
+ CREATE_MSG_MASK_TBL_ROW(2);
+ CREATE_MSG_MASK_TBL_ROW(3);
+ CREATE_MSG_MASK_TBL_ROW(4);
+ CREATE_MSG_MASK_TBL_ROW(5);
+ CREATE_MSG_MASK_TBL_ROW(6);
+ CREATE_MSG_MASK_TBL_ROW(7);
+ CREATE_MSG_MASK_TBL_ROW(8);
+ CREATE_MSG_MASK_TBL_ROW(9);
+ CREATE_MSG_MASK_TBL_ROW(10);
+ CREATE_MSG_MASK_TBL_ROW(11);
+ CREATE_MSG_MASK_TBL_ROW(12);
+ CREATE_MSG_MASK_TBL_ROW(13);
+ CREATE_MSG_MASK_TBL_ROW(14);
+ CREATE_MSG_MASK_TBL_ROW(15);
+ CREATE_MSG_MASK_TBL_ROW(16);
+ CREATE_MSG_MASK_TBL_ROW(17);
+ CREATE_MSG_MASK_TBL_ROW(18);
+ CREATE_MSG_MASK_TBL_ROW(19);
+ CREATE_MSG_MASK_TBL_ROW(20);
+ CREATE_MSG_MASK_TBL_ROW(21);
+ CREATE_MSG_MASK_TBL_ROW(22);
+ CREATE_MSG_MASK_TBL_ROW(23);
+}
+
+static void diag_set_msg_mask(int rt_mask)
+{
+ int first_ssid, last_ssid, i;
+ uint8_t *parse_ptr, *ptr = driver->msg_masks;
+
+ mutex_lock(&driver->diagchar_mutex);
+ while (*(uint32_t *)(ptr + 4)) {
+ first_ssid = *(uint32_t *)ptr;
+ ptr += 8; /* increment by 8 to skip 'last' */
+ last_ssid = *(uint32_t *)ptr;
+ ptr += 4;
+ parse_ptr = ptr;
+ pr_debug("diag: updating range %d %d\n", first_ssid, last_ssid);
+ for (i = 0; i < last_ssid - first_ssid + 1; i++) {
+ *(int *)parse_ptr = rt_mask;
+ parse_ptr += 4;
+ }
+ ptr += MAX_SSID_PER_RANGE * 4;
+ }
+ mutex_unlock(&driver->diagchar_mutex);
+}
+
+static void diag_update_msg_mask(int start, int end , uint8_t *buf)
+{
+ int found = 0, first, last, actual_last;
+ uint8_t *actual_last_ptr;
+ uint8_t *ptr = driver->msg_masks;
+ uint8_t *ptr_buffer_start = &(*(driver->msg_masks));
+ uint8_t *ptr_buffer_end = &(*(driver->msg_masks)) + MSG_MASK_SIZE;
+
+ mutex_lock(&driver->diagchar_mutex);
+
+ /* First SSID can be zero : So check that last is non-zero */
+ while (*(uint32_t *)(ptr + 4)) {
+ first = *(uint32_t *)ptr;
+ ptr += 4;
+ last = *(uint32_t *)ptr;
+ ptr += 4;
+ actual_last = *(uint32_t *)ptr;
+ actual_last_ptr = ptr;
+ ptr += 4;
+ if (start >= first && start <= actual_last) {
+ ptr += (start - first)*4;
+ if (end > actual_last) {
+ pr_info("diag: ssid range mismatch\n");
+ actual_last = end;
+ *(uint32_t *)(actual_last_ptr) = end;
+ }
+ if (CHK_OVERFLOW(ptr_buffer_start, ptr, ptr_buffer_end,
+ (((end - start)+1)*4))) {
+ pr_debug("diag: update ssid start %d, end %d\n",
+ start, end);
+ memcpy(ptr, buf , ((end - start)+1)*4);
+ } else
+ pr_alert("diag: Not enough space MSG_MASK\n");
+ found = 1;
+ break;
+ } else {
+ ptr += MAX_SSID_PER_RANGE*4;
+ }
+ }
+ /* Entry was not found - add new table */
+ if (!found) {
+ if (CHK_OVERFLOW(ptr_buffer_start, ptr, ptr_buffer_end,
+ 8 + ((end - start) + 1)*4)) {
+ memcpy(ptr, &(start) , 4);
+ ptr += 4;
+ memcpy(ptr, &(end), 4);
+ ptr += 4;
+ memcpy(ptr, &(end), 4); /* create actual_last entry */
+ ptr += 4;
+ pr_debug("diag: adding NEW ssid start %d, end %d\n",
+ start, end);
+ memcpy(ptr, buf , ((end - start) + 1)*4);
+ } else
+ pr_alert("diag: Not enough buffer space for MSG_MASK\n");
+ }
+ mutex_unlock(&driver->diagchar_mutex);
+ diag_print_mask_table();
+}
+
+void diag_toggle_event_mask(int toggle)
+{
+ uint8_t *ptr = driver->event_masks;
+
+ mutex_lock(&driver->diagchar_mutex);
+ if (toggle)
+ memset(ptr, 0xFF, EVENT_MASK_SIZE);
+ else
+ memset(ptr, 0, EVENT_MASK_SIZE);
+ mutex_unlock(&driver->diagchar_mutex);
+}
+
+
+static void diag_update_event_mask(uint8_t *buf, int toggle, int num_bytes)
+{
+ uint8_t *ptr = driver->event_masks;
+ uint8_t *temp = buf + 2;
+
+ mutex_lock(&driver->diagchar_mutex);
+ if (!toggle)
+ memset(ptr, 0 , EVENT_MASK_SIZE);
+ else
+ if (CHK_OVERFLOW(ptr, ptr,
+ ptr+EVENT_MASK_SIZE, num_bytes))
+ memcpy(ptr, temp , num_bytes);
+ else
+ printk(KERN_CRIT "Not enough buffer space for EVENT_MASK\n");
+ mutex_unlock(&driver->diagchar_mutex);
+}
+
+static void diag_disable_log_mask(void)
+{
+ int i = 0;
+ struct mask_info *parse_ptr = (struct mask_info *)(driver->log_masks);
+
+ pr_debug("diag: disable log masks\n");
+ mutex_lock(&driver->diagchar_mutex);
+ for (i = 0; i < MAX_EQUIP_ID; i++) {
+ pr_debug("diag: equip id %d\n", parse_ptr->equip_id);
+ if (!(parse_ptr->equip_id)) /* Reached a null entry */
+ break;
+ memset(driver->log_masks + parse_ptr->index, 0,
+ (parse_ptr->num_items + 7)/8);
+ parse_ptr++;
+ }
+ mutex_unlock(&driver->diagchar_mutex);
+}
+
+int chk_equip_id_and_mask(int equip_id, uint8_t *buf)
+{
+ int i = 0, flag = 0, num_items, offset;
+ unsigned char *ptr_data;
+ struct mask_info *ptr = (struct mask_info *)(driver->log_masks);
+
+ pr_debug("diag: received equip id = %d\n", equip_id);
+ /* Check if this is valid equipment ID */
+ for (i = 0; i < MAX_EQUIP_ID; i++) {
+ if ((ptr->equip_id == equip_id) && (ptr->index != 0)) {
+ offset = ptr->index;
+ num_items = ptr->num_items;
+ flag = 1;
+ break;
+ }
+ ptr++;
+ }
+ if (!flag)
+ return -EPERM;
+ ptr_data = driver->log_masks + offset;
+ memcpy(buf, ptr_data, (num_items+7)/8);
+ return 0;
+}
+
+static void diag_update_log_mask(int equip_id, uint8_t *buf, int num_items)
+{
+ uint8_t *temp = buf;
+ int i = 0;
+ unsigned char *ptr_data;
+ int offset = (sizeof(struct mask_info))*MAX_EQUIP_ID;
+ struct mask_info *ptr = (struct mask_info *)(driver->log_masks);
+
+ pr_debug("diag: received equip id = %d\n", equip_id);
+ mutex_lock(&driver->diagchar_mutex);
+ /* Check if we already know index of this equipment ID */
+ for (i = 0; i < MAX_EQUIP_ID; i++) {
+ if ((ptr->equip_id == equip_id) && (ptr->index != 0)) {
+ offset = ptr->index;
+ break;
+ }
+ if ((ptr->equip_id == 0) && (ptr->index == 0)) {
+ /* Reached a null entry */
+ ptr->equip_id = equip_id;
+ ptr->num_items = num_items;
+ ptr->index = driver->log_masks_length;
+ offset = driver->log_masks_length;
+ driver->log_masks_length += ((num_items+7)/8);
+ break;
+ }
+ ptr++;
+ }
+ ptr_data = driver->log_masks + offset;
+ if (CHK_OVERFLOW(driver->log_masks, ptr_data, driver->log_masks
+ + LOG_MASK_SIZE, (num_items+7)/8))
+ memcpy(ptr_data, temp , (num_items+7)/8);
+ else
+ pr_err("diag: Not enough buffer space for LOG_MASK\n");
+ mutex_unlock(&driver->diagchar_mutex);
+}
+
+void diag_modem_mask_update_fn(struct work_struct *work)
+{
+ diag_send_msg_mask_update(driver->ch_cntl, ALL_SSID,
+ ALL_SSID, MODEM_PROC);
+ diag_send_log_mask_update(driver->ch_cntl, ALL_EQUIP_ID);
+ diag_send_event_mask_update(driver->ch_cntl, diag_event_num_bytes);
+}
+
+void diag_lpass_mask_update_fn(struct work_struct *work)
+{
+ diag_send_msg_mask_update(driver->chlpass_cntl, ALL_SSID,
+ ALL_SSID, LPASS_PROC);
+ diag_send_log_mask_update(driver->chlpass_cntl, ALL_EQUIP_ID);
+ diag_send_event_mask_update(driver->chlpass_cntl, diag_event_num_bytes);
+}
+
+void diag_wcnss_mask_update_fn(struct work_struct *work)
+{
+ diag_send_msg_mask_update(driver->ch_wcnss_cntl, ALL_SSID,
+ ALL_SSID, WCNSS_PROC);
+ diag_send_log_mask_update(driver->ch_wcnss_cntl, ALL_EQUIP_ID);
+ diag_send_event_mask_update(driver->ch_wcnss_cntl,
+ diag_event_num_bytes);
+}
+
+void diag_send_log_mask_update(smd_channel_t *ch, int equip_id)
+{
+ void *buf = driver->buf_log_mask_update;
+ int header_size = sizeof(struct diag_ctrl_log_mask);
+ struct mask_info *ptr = (struct mask_info *)driver->log_masks;
+ int i, size, wr_size = -ENOMEM, retry_count = 0;
+
+ mutex_lock(&driver->diag_cntl_mutex);
+ for (i = 0; i < MAX_EQUIP_ID; i++) {
+ size = (ptr->num_items+7)/8;
+ /* reached null entry */
+ if ((ptr->equip_id == 0) && (ptr->index == 0))
+ break;
+ driver->log_mask->cmd_type = DIAG_CTRL_MSG_LOG_MASK;
+ driver->log_mask->num_items = ptr->num_items;
+ driver->log_mask->data_len = 11 + size;
+ driver->log_mask->stream_id = 1; /* 2, if dual stream */
+ driver->log_mask->status = 3; /* status for valid mask */
+ driver->log_mask->equip_id = ptr->equip_id;
+ driver->log_mask->log_mask_size = size;
+ /* send only desired update, NOT ALL */
+ if (equip_id == ALL_EQUIP_ID || equip_id ==
+ driver->log_mask->equip_id) {
+ memcpy(buf, driver->log_mask, header_size);
+ memcpy(buf+header_size, driver->log_masks+ptr->index,
+ size);
+ if (ch) {
+ while (retry_count < 3) {
+ wr_size = smd_write(ch, buf,
+ header_size + size);
+ if (wr_size == -ENOMEM) {
+ retry_count++;
+ WAIT_FOR_SMD(5, 2000);
+ } else
+ break;
+ }
+ if (wr_size != header_size + size)
+ pr_err("diag: log mask update failed %d, tried %d",
+ wr_size, header_size + size);
+ else
+ pr_debug("diag: updated log equip ID %d,len %d\n",
+ driver->log_mask->equip_id,
+ driver->log_mask->log_mask_size);
+ } else
+ pr_err("diag: ch not valid for log update\n");
+ }
+ ptr++;
+ }
+ mutex_unlock(&driver->diag_cntl_mutex);
+}
+
+void diag_send_event_mask_update(smd_channel_t *ch, int num_bytes)
+{
+ void *buf = driver->buf_event_mask_update;
+ int header_size = sizeof(struct diag_ctrl_event_mask);
+ int wr_size = -ENOMEM, retry_count = 0;
+
+ mutex_lock(&driver->diag_cntl_mutex);
+ if (num_bytes == 0) {
+ pr_debug("diag: event mask not set yet, so no update\n");
+ mutex_unlock(&driver->diag_cntl_mutex);
+ return;
+ }
+ /* send event mask update */
+ driver->event_mask->cmd_type = DIAG_CTRL_MSG_EVENT_MASK;
+ driver->event_mask->data_len = 7 + num_bytes;
+ driver->event_mask->stream_id = 1; /* 2, if dual stream */
+ driver->event_mask->status = 3; /* status for valid mask */
+ driver->event_mask->event_config = diag_event_config; /* event config */
+ driver->event_mask->event_mask_size = num_bytes;
+ memcpy(buf, driver->event_mask, header_size);
+ memcpy(buf+header_size, driver->event_masks, num_bytes);
+ if (ch) {
+ while (retry_count < 3) {
+ wr_size = smd_write(ch, buf, header_size + num_bytes);
+ if (wr_size == -ENOMEM) {
+ retry_count++;
+ WAIT_FOR_SMD(5, 2000);
+ } else
+ break;
+ }
+ if (wr_size != header_size + num_bytes)
+ pr_err("diag: error writing event mask %d, tried %d\n",
+ wr_size, header_size + num_bytes);
+ } else
+ pr_err("diag: ch not valid for event update\n");
+ mutex_unlock(&driver->diag_cntl_mutex);
+}
+
+void diag_send_msg_mask_update(smd_channel_t *ch, int updated_ssid_first,
+ int updated_ssid_last, int proc)
+{
+ void *buf = driver->buf_msg_mask_update;
+ int first, last, actual_last, size = -ENOMEM, retry_count = 0;
+ int header_size = sizeof(struct diag_ctrl_msg_mask);
+ uint8_t *ptr = driver->msg_masks;
+
+ mutex_lock(&driver->diag_cntl_mutex);
+ while (*(uint32_t *)(ptr + 4)) {
+ first = *(uint32_t *)ptr;
+ ptr += 4;
+ last = *(uint32_t *)ptr;
+ ptr += 4;
+ actual_last = *(uint32_t *)ptr;
+ ptr += 4;
+ if ((updated_ssid_first >= first && updated_ssid_last <=
+ actual_last) || (updated_ssid_first == ALL_SSID)) {
+ /* send f3 mask update */
+ driver->msg_mask->cmd_type = DIAG_CTRL_MSG_F3_MASK;
+ driver->msg_mask->msg_mask_size = actual_last -
+ first + 1;
+ driver->msg_mask->data_len = 11 +
+ 4 * (driver->msg_mask->msg_mask_size);
+ driver->msg_mask->stream_id = 1; /* 2, if dual stream */
+ driver->msg_mask->status = 3; /* status valid mask */
+ driver->msg_mask->msg_mode = 0; /* Legcay mode */
+ driver->msg_mask->ssid_first = first;
+ driver->msg_mask->ssid_last = actual_last;
+ memcpy(buf, driver->msg_mask, header_size);
+ memcpy(buf+header_size, ptr,
+ 4 * (driver->msg_mask->msg_mask_size));
+ if (ch) {
+ while (retry_count < 3) {
+ size = smd_write(ch, buf, header_size +
+ 4*(driver->msg_mask->msg_mask_size));
+ if (size == -ENOMEM) {
+ retry_count++;
+ WAIT_FOR_SMD(5, 2000);
+ } else
+ break;
+ }
+ if (size != header_size +
+ 4*(driver->msg_mask->msg_mask_size))
+ pr_err("diag: proc %d, msg mask update fail %d, tried %d\n",
+ proc, size, (header_size +
+ 4*(driver->msg_mask->msg_mask_size)));
+ else
+ pr_debug("diag: sending mask update for ssid first %d, last %d on PROC %d\n",
+ first, actual_last, proc);
+ } else
+ pr_err("diag: proc %d, ch invalid msg mask update\n",
+ proc);
+ }
+ ptr += MAX_SSID_PER_RANGE*4;
+ }
+ mutex_unlock(&driver->diag_cntl_mutex);
+}
+
+int diag_process_apps_masks(unsigned char *buf, int len)
+{
+ int packet_type = 1;
+ int i;
+ int ssid_first, ssid_last, ssid_range;
+ int rt_mask, rt_first_ssid, rt_last_ssid, rt_mask_size;
+ uint8_t *rt_mask_ptr;
+ int equip_id, num_items;
+#if defined(CONFIG_DIAG_OVER_USB)
+ int payload_length;
+#endif
+
+ /* Set log masks */
+ if (*buf == 0x73 && *(int *)(buf+4) == 3) {
+ buf += 8;
+ /* Read Equip ID and pass as first param below*/
+ diag_update_log_mask(*(int *)buf, buf+8, *(int *)(buf+4));
+ diag_update_userspace_clients(LOG_MASKS_TYPE);
+#if defined(CONFIG_DIAG_OVER_USB)
+ if (chk_apps_only()) {
+ driver->apps_rsp_buf[0] = 0x73;
+ *(int *)(driver->apps_rsp_buf + 4) = 0x3; /* op. ID */
+ *(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success */
+ payload_length = 8 + ((*(int *)(buf + 4)) + 7)/8;
+ for (i = 0; i < payload_length; i++)
+ *(int *)(driver->apps_rsp_buf+12+i) = *(buf+i);
+ if (driver->ch_cntl)
+ diag_send_log_mask_update(driver->ch_cntl,
+ *(int *)buf);
+ if (driver->chlpass_cntl)
+ diag_send_log_mask_update(driver->chlpass_cntl,
+ *(int *)buf);
+ if (driver->ch_wcnss_cntl)
+ diag_send_log_mask_update(driver->ch_wcnss_cntl,
+ *(int *)buf);
+ encode_rsp_and_send(12 + payload_length - 1);
+ return 0;
+ }
+#endif
+ } /* Get log masks */
+ else if (*buf == 0x73 && *(int *)(buf+4) == 4) {
+#if defined(CONFIG_DIAG_OVER_USB)
+ if (!(driver->ch) && chk_apps_only()) {
+ equip_id = *(int *)(buf + 8);
+ num_items = *(int *)(buf + 12);
+ driver->apps_rsp_buf[0] = 0x73;
+ driver->apps_rsp_buf[1] = 0x0;
+ driver->apps_rsp_buf[2] = 0x0;
+ driver->apps_rsp_buf[3] = 0x0;
+ *(int *)(driver->apps_rsp_buf + 4) = 0x4;
+ if (!chk_equip_id_and_mask(equip_id,
+ driver->apps_rsp_buf+20))
+ *(int *)(driver->apps_rsp_buf + 8) = 0x0;
+ else
+ *(int *)(driver->apps_rsp_buf + 8) = 0x1;
+ *(int *)(driver->apps_rsp_buf + 12) = equip_id;
+ *(int *)(driver->apps_rsp_buf + 16) = num_items;
+ encode_rsp_and_send(20+(num_items+7)/8-1);
+ return 0;
+ }
+#endif
+ } /* Disable log masks */
+ else if (*buf == 0x73 && *(int *)(buf+4) == 0) {
+ /* Disable mask for each log code */
+ diag_disable_log_mask();
+ diag_update_userspace_clients(LOG_MASKS_TYPE);
+#if defined(CONFIG_DIAG_OVER_USB)
+ if (chk_apps_only()) {
+ driver->apps_rsp_buf[0] = 0x73;
+ driver->apps_rsp_buf[1] = 0x0;
+ driver->apps_rsp_buf[2] = 0x0;
+ driver->apps_rsp_buf[3] = 0x0;
+ *(int *)(driver->apps_rsp_buf + 4) = 0x0;
+ *(int *)(driver->apps_rsp_buf + 8) = 0x0; /* status */
+ if (driver->ch_cntl)
+ diag_send_log_mask_update(driver->ch_cntl,
+ ALL_EQUIP_ID);
+ if (driver->chlpass_cntl)
+ diag_send_log_mask_update(driver->chlpass_cntl,
+ ALL_EQUIP_ID);
+ if (driver->ch_wcnss_cntl)
+ diag_send_log_mask_update(driver->ch_wcnss_cntl,
+ ALL_EQUIP_ID);
+ encode_rsp_and_send(11);
+ return 0;
+ }
+#endif
+ } /* Get runtime message mask */
+ else if ((*buf == 0x7d) && (*(buf+1) == 0x3)) {
+ ssid_first = *(uint16_t *)(buf + 2);
+ ssid_last = *(uint16_t *)(buf + 4);
+#if defined(CONFIG_DIAG_OVER_USB)
+ if (!(driver->ch) && chk_apps_only()) {
+ driver->apps_rsp_buf[0] = 0x7d;
+ driver->apps_rsp_buf[1] = 0x3;
+ *(uint16_t *)(driver->apps_rsp_buf+2) = ssid_first;
+ *(uint16_t *)(driver->apps_rsp_buf+4) = ssid_last;
+ driver->apps_rsp_buf[6] = 0x1; /* Success Status */
+ driver->apps_rsp_buf[7] = 0x0;
+ rt_mask_ptr = driver->msg_masks;
+ while (*(uint32_t *)(rt_mask_ptr + 4)) {
+ rt_first_ssid = *(uint32_t *)rt_mask_ptr;
+ rt_mask_ptr += 8; /* +8 to skip 'last' */
+ rt_last_ssid = *(uint32_t *)rt_mask_ptr;
+ rt_mask_ptr += 4;
+ if (ssid_first == rt_first_ssid && ssid_last ==
+ rt_last_ssid) {
+ rt_mask_size = 4 * (rt_last_ssid -
+ rt_first_ssid + 1);
+ memcpy(driver->apps_rsp_buf+8,
+ rt_mask_ptr, rt_mask_size);
+ encode_rsp_and_send(8+rt_mask_size-1);
+ return 0;
+ }
+ rt_mask_ptr += MAX_SSID_PER_RANGE*4;
+ }
+ }
+#endif
+ } /* Set runtime message mask */
+ else if ((*buf == 0x7d) && (*(buf+1) == 0x4)) {
+ ssid_first = *(uint16_t *)(buf + 2);
+ ssid_last = *(uint16_t *)(buf + 4);
+ ssid_range = 4 * (ssid_last - ssid_first + 1);
+ pr_debug("diag: received mask update for ssid_first = %d, ssid_last = %d",
+ ssid_first, ssid_last);
+ diag_update_msg_mask(ssid_first, ssid_last , buf + 8);
+ diag_update_userspace_clients(MSG_MASKS_TYPE);
+#if defined(CONFIG_DIAG_OVER_USB)
+ if (chk_apps_only()) {
+ for (i = 0; i < 8 + ssid_range; i++)
+ *(driver->apps_rsp_buf + i) = *(buf+i);
+ *(driver->apps_rsp_buf + 6) = 0x1;
+ if (driver->ch_cntl)
+ diag_send_msg_mask_update(driver->ch_cntl,
+ ssid_first, ssid_last, MODEM_PROC);
+ if (driver->chlpass_cntl)
+ diag_send_msg_mask_update(driver->chlpass_cntl,
+ ssid_first, ssid_last, LPASS_PROC);
+ if (driver->ch_wcnss_cntl)
+ diag_send_msg_mask_update(driver->ch_wcnss_cntl,
+ ssid_first, ssid_last, WCNSS_PROC);
+ encode_rsp_and_send(8 + ssid_range - 1);
+ return 0;
+ }
+#endif
+ } /* Set ALL runtime message mask */
+ else if ((*buf == 0x7d) && (*(buf+1) == 0x5)) {
+ rt_mask = *(int *)(buf + 4);
+ diag_set_msg_mask(rt_mask);
+ diag_update_userspace_clients(MSG_MASKS_TYPE);
+#if defined(CONFIG_DIAG_OVER_USB)
+ if (chk_apps_only()) {
+ driver->apps_rsp_buf[0] = 0x7d; /* cmd_code */
+ driver->apps_rsp_buf[1] = 0x5; /* set subcommand */
+ driver->apps_rsp_buf[2] = 1; /* success */
+ driver->apps_rsp_buf[3] = 0; /* rsvd */
+ *(int *)(driver->apps_rsp_buf + 4) = rt_mask;
+ /* send msg mask update to peripheral */
+ if (driver->ch_cntl)
+ diag_send_msg_mask_update(driver->ch_cntl,
+ ALL_SSID, ALL_SSID, MODEM_PROC);
+ if (driver->chlpass_cntl)
+ diag_send_msg_mask_update(driver->chlpass_cntl,
+ ALL_SSID, ALL_SSID, LPASS_PROC);
+ if (driver->ch_wcnss_cntl)
+ diag_send_msg_mask_update(driver->ch_wcnss_cntl,
+ ALL_SSID, ALL_SSID, WCNSS_PROC);
+ encode_rsp_and_send(7);
+ return 0;
+ }
+#endif
+ } else if (*buf == 0x82) { /* event mask change */
+ buf += 4;
+ diag_event_num_bytes = (*(uint16_t *)buf)/8+1;
+ diag_update_event_mask(buf, 1, (*(uint16_t *)buf)/8+1);
+ diag_update_userspace_clients(EVENT_MASKS_TYPE);
+#if defined(CONFIG_DIAG_OVER_USB)
+ if (chk_apps_only()) {
+ driver->apps_rsp_buf[0] = 0x82;
+ driver->apps_rsp_buf[1] = 0x0;
+ *(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
+ *(uint16_t *)(driver->apps_rsp_buf + 4) =
+ EVENT_LAST_ID + 1;
+ memcpy(driver->apps_rsp_buf+6, driver->event_masks,
+ EVENT_LAST_ID/8+1);
+ if (driver->ch_cntl)
+ diag_send_event_mask_update(driver->ch_cntl,
+ diag_event_num_bytes);
+ if (driver->chlpass_cntl)
+ diag_send_event_mask_update(
+ driver->chlpass_cntl,
+ diag_event_num_bytes);
+ if (driver->ch_wcnss_cntl)
+ diag_send_event_mask_update(
+ driver->ch_wcnss_cntl, diag_event_num_bytes);
+ encode_rsp_and_send(6 + EVENT_LAST_ID/8);
+ return 0;
+ }
+#endif
+ } else if (*buf == 0x60) {
+ diag_event_config = *(buf+1);
+ diag_toggle_event_mask(*(buf+1));
+ diag_update_userspace_clients(EVENT_MASKS_TYPE);
+#if defined(CONFIG_DIAG_OVER_USB)
+ if (chk_apps_only()) {
+ driver->apps_rsp_buf[0] = 0x60;
+ driver->apps_rsp_buf[1] = 0x0;
+ driver->apps_rsp_buf[2] = 0x0;
+ if (driver->ch_cntl)
+ diag_send_event_mask_update(driver->ch_cntl,
+ diag_event_num_bytes);
+ if (driver->chlpass_cntl)
+ diag_send_event_mask_update(
+ driver->chlpass_cntl,
+ diag_event_num_bytes);
+ if (driver->ch_wcnss_cntl)
+ diag_send_event_mask_update(
+ driver->ch_wcnss_cntl, diag_event_num_bytes);
+ encode_rsp_and_send(2);
+ return 0;
+ }
+#endif
+ }
+
+ return packet_type;
+}
+
+void diag_masks_init(void)
+{
+ if (driver->event_mask == NULL) {
+ driver->event_mask = kzalloc(sizeof(
+ struct diag_ctrl_event_mask), GFP_KERNEL);
+ if (driver->event_mask == NULL)
+ goto err;
+ kmemleak_not_leak(driver->event_mask);
+ }
+ if (driver->msg_mask == NULL) {
+ driver->msg_mask = kzalloc(sizeof(
+ struct diag_ctrl_msg_mask), GFP_KERNEL);
+ if (driver->msg_mask == NULL)
+ goto err;
+ kmemleak_not_leak(driver->msg_mask);
+ }
+ if (driver->log_mask == NULL) {
+ driver->log_mask = kzalloc(sizeof(
+ struct diag_ctrl_log_mask), GFP_KERNEL);
+ if (driver->log_mask == NULL)
+ goto err;
+ kmemleak_not_leak(driver->log_mask);
+ }
+
+ if (driver->buf_msg_mask_update == NULL) {
+ driver->buf_msg_mask_update = kzalloc(APPS_BUF_SIZE,
+ GFP_KERNEL);
+ if (driver->buf_msg_mask_update == NULL)
+ goto err;
+ kmemleak_not_leak(driver->buf_msg_mask_update);
+ }
+ if (driver->buf_log_mask_update == NULL) {
+ driver->buf_log_mask_update = kzalloc(APPS_BUF_SIZE,
+ GFP_KERNEL);
+ if (driver->buf_log_mask_update == NULL)
+ goto err;
+ kmemleak_not_leak(driver->buf_log_mask_update);
+ }
+ if (driver->buf_event_mask_update == NULL) {
+ driver->buf_event_mask_update = kzalloc(APPS_BUF_SIZE,
+ GFP_KERNEL);
+ if (driver->buf_event_mask_update == NULL)
+ goto err;
+ kmemleak_not_leak(driver->buf_event_mask_update);
+ }
+ if (driver->msg_masks == NULL) {
+ driver->msg_masks = kzalloc(MSG_MASK_SIZE, GFP_KERNEL);
+ if (driver->msg_masks == NULL)
+ goto err;
+ kmemleak_not_leak(driver->msg_masks);
+ }
+ diag_create_msg_mask_table();
+ diag_event_num_bytes = 0;
+ if (driver->log_masks == NULL) {
+ driver->log_masks = kzalloc(LOG_MASK_SIZE, GFP_KERNEL);
+ if (driver->log_masks == NULL)
+ goto err;
+ kmemleak_not_leak(driver->log_masks);
+ }
+ driver->log_masks_length = (sizeof(struct mask_info))*MAX_EQUIP_ID;
+ if (driver->event_masks == NULL) {
+ driver->event_masks = kzalloc(EVENT_MASK_SIZE, GFP_KERNEL);
+ if (driver->event_masks == NULL)
+ goto err;
+ kmemleak_not_leak(driver->event_masks);
+ }
+#ifdef CONFIG_DIAG_OVER_USB
+ INIT_WORK(&(driver->diag_modem_mask_update_work),
+ diag_modem_mask_update_fn);
+ INIT_WORK(&(driver->diag_lpass_mask_update_work),
+ diag_lpass_mask_update_fn);
+ INIT_WORK(&(driver->diag_wcnss_mask_update_work),
+ diag_wcnss_mask_update_fn);
+#endif
+ return;
+err:
+ pr_err("diag: Could not initialize diag mask buffers");
+ kfree(driver->event_mask);
+ kfree(driver->log_mask);
+ kfree(driver->msg_mask);
+ kfree(driver->msg_masks);
+ kfree(driver->log_masks);
+ kfree(driver->event_masks);
+}
+
+void diag_masks_exit(void)
+{
+ kfree(driver->event_mask);
+ kfree(driver->log_mask);
+ kfree(driver->msg_mask);
+ kfree(driver->msg_masks);
+ kfree(driver->log_masks);
+ kfree(driver->event_masks);
+}
diff --git a/drivers/char/diag/diag_masks.h b/drivers/char/diag/diag_masks.h
new file mode 100644
index 0000000..bcf5bc2
--- /dev/null
+++ b/drivers/char/diag/diag_masks.h
@@ -0,0 +1,27 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef DIAG_MASKS_H
+#define DIAG_MASKS_H
+
+#include "diagfwd.h"
+
+int chk_equip_id_and_mask(int equip_id, uint8_t *buf);
+void diag_send_event_mask_update(smd_channel_t *, int num_bytes);
+void diag_send_msg_mask_update(smd_channel_t *, int ssid_first,
+ int ssid_last, int proc);
+void diag_send_log_mask_update(smd_channel_t *, int);
+int diag_process_apps_masks(unsigned char *buf, int len);
+void diag_masks_init(void);
+void diag_masks_exit(void);
+extern int diag_event_num_bytes;
+#endif
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 814fe64..5c6cdc6 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -37,6 +37,8 @@
#include "diagfwd_smux.h"
#endif
#include <linux/timer.h>
+#include "diag_debugfs.h"
+#include "diag_masks.h"
MODULE_DESCRIPTION("Diag Char Driver");
MODULE_LICENSE("GPL v2");
@@ -1420,6 +1422,7 @@
INIT_WORK(&(driver->diag_clean_wcnss_reg_work),
diag_clean_wcnss_reg_fn);
diag_debugfs_init();
+ diag_masks_init();
diagfwd_init();
diagfwd_cntl_init();
driver->dci_state = diag_dci_init();
@@ -1457,6 +1460,7 @@
diagchar_cleanup();
diagfwd_exit();
diagfwd_cntl_exit();
+ diag_masks_exit();
diag_sdio_fn(EXIT);
diag_bridge_fn(EXIT);
return -1;
@@ -1470,6 +1474,7 @@
diagmem_exit(driver, POOL_TYPE_ALL);
diagfwd_exit();
diagfwd_cntl_exit();
+ diag_masks_exit();
diag_sdio_fn(EXIT);
diag_bridge_fn(EXIT);
diag_debugfs_cleanup();
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 737edbf..a537bb3 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -39,63 +39,38 @@
#include "diagfwd_sdio.h"
#endif
#include "diag_dci.h"
+#include "diag_masks.h"
#define MODE_CMD 41
#define RESET_ID 2
-#define ALL_EQUIP_ID 100
-#define ALL_SSID -1
-#define MAX_SSID_PER_RANGE 100
int diag_debug_buf_idx;
unsigned char diag_debug_buf[1024];
static unsigned int buf_tbl_size = 8; /*Number of entries in table of buffers */
struct diag_master_table entry;
smd_channel_t *ch_temp = NULL, *chlpass_temp = NULL, *ch_wcnss_temp = NULL;
-int diag_event_num_bytes;
-int diag_event_config;
struct diag_send_desc_type send = { NULL, NULL, DIAG_STATE_START, 0 };
struct diag_hdlc_dest_type enc = { NULL, NULL, 0 };
-struct mask_info {
- int equip_id;
- int num_items;
- int index;
-};
-#define CREATE_MSG_MASK_TBL_ROW(XX) \
-do { \
- *(int *)(msg_mask_tbl_ptr) = MSG_SSID_ ## XX; \
- msg_mask_tbl_ptr += 4; \
- *(int *)(msg_mask_tbl_ptr) = MSG_SSID_ ## XX ## _LAST; \
- msg_mask_tbl_ptr += 4; \
- /* mimic the last entry as actual_last while creation */ \
- *(int *)(msg_mask_tbl_ptr) = MSG_SSID_ ## XX ## _LAST; \
- msg_mask_tbl_ptr += 4; \
- /* increment by MAX_SSID_PER_RANGE cells */ \
- msg_mask_tbl_ptr += MAX_SSID_PER_RANGE * sizeof(int); \
-} while (0)
-
-#define ENCODE_RSP_AND_SEND(buf_length) \
-do { \
- send.state = DIAG_STATE_START; \
- send.pkt = driver->apps_rsp_buf; \
- send.last = (void *)(driver->apps_rsp_buf + buf_length); \
- send.terminate = 1; \
- if (!driver->in_busy_1) { \
- enc.dest = driver->buf_in_1; \
- enc.dest_last = (void *)(driver->buf_in_1 + APPS_BUF_SIZE - 1);\
- diag_hdlc_encode(&send, &enc); \
- driver->write_ptr_1->buf = driver->buf_in_1; \
- driver->write_ptr_1->length = (int)(enc.dest - \
- (void *)(driver->buf_in_1)); \
- driver->in_busy_1 = 1; \
- diag_device_write(driver->buf_in_1, MODEM_DATA, \
- driver->write_ptr_1); \
- memset(driver->apps_rsp_buf, '\0', APPS_BUF_SIZE); \
- } \
-} while (0)
-
-#define CHK_OVERFLOW(bufStart, start, end, length) \
-((bufStart <= start) && (end - start >= length)) ? 1 : 0
+void encode_rsp_and_send(int buf_length)
+{
+ send.state = DIAG_STATE_START;
+ send.pkt = driver->apps_rsp_buf;
+ send.last = (void *)(driver->apps_rsp_buf + buf_length);
+ send.terminate = 1;
+ if (!driver->in_busy_1) {
+ enc.dest = driver->buf_in_1;
+ enc.dest_last = (void *)(driver->buf_in_1 + APPS_BUF_SIZE - 1);
+ diag_hdlc_encode(&send, &enc);
+ driver->write_ptr_1->buf = driver->buf_in_1;
+ driver->write_ptr_1->length = (int)(enc.dest -
+ (void *)(driver->buf_in_1));
+ driver->in_busy_1 = 1;
+ diag_device_write(driver->buf_in_1, MODEM_DATA,
+ driver->write_ptr_1);
+ memset(driver->apps_rsp_buf, '\0', APPS_BUF_SIZE);
+ }
+}
/* Determine if this device uses a device tree */
#ifdef CONFIG_OF
@@ -136,6 +111,7 @@
case MSM_CPU_8960AB:
return AO8960_TOOLS_ID;
case MSM_CPU_8064:
+ case MSM_CPU_8064AB:
return APQ8064_TOOLS_ID;
case MSM_CPU_8930:
case MSM_CPU_8930AA:
@@ -163,6 +139,7 @@
case MSM_CPU_8960:
case MSM_CPU_8960AB:
case MSM_CPU_8064:
+ case MSM_CPU_8064AB:
case MSM_CPU_8930:
case MSM_CPU_8930AA:
case MSM_CPU_8627:
@@ -185,7 +162,7 @@
return 1;
else if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm8930aa() ||
cpu_is_msm9615() || cpu_is_apq8064() || cpu_is_msm8627() ||
- cpu_is_msm8960ab())
+ cpu_is_msm8960ab() || cpu_is_apq8064ab())
return 1;
else
return 0;
@@ -559,248 +536,6 @@
}
}
-static void diag_print_mask_table(void)
-{
-/* Enable this to print mask table when updated */
-#ifdef MASK_DEBUG
- int first, last, actual_last;
- uint8_t *ptr = driver->msg_masks;
- int i = 0;
- pr_info("diag: F3 message mask table\n");
- while (*(uint32_t *)(ptr + 4)) {
- first = *(uint32_t *)ptr;
- ptr += 4;
- last = *(uint32_t *)ptr;
- ptr += 4;
- actual_last = *(uint32_t *)ptr;
- ptr += 4;
- pr_info("diag: SSID %d, %d - %d\n", first, last, actual_last);
- for (i = 0 ; i <= actual_last - first ; i++)
- pr_info("diag: MASK:%x\n", *((uint32_t *)ptr + i));
- ptr += MAX_SSID_PER_RANGE*4;
- }
-#endif
-}
-
-void diag_create_msg_mask_table(void)
-{
- uint8_t *msg_mask_tbl_ptr = driver->msg_masks;
-
- CREATE_MSG_MASK_TBL_ROW(0);
- CREATE_MSG_MASK_TBL_ROW(1);
- CREATE_MSG_MASK_TBL_ROW(2);
- CREATE_MSG_MASK_TBL_ROW(3);
- CREATE_MSG_MASK_TBL_ROW(4);
- CREATE_MSG_MASK_TBL_ROW(5);
- CREATE_MSG_MASK_TBL_ROW(6);
- CREATE_MSG_MASK_TBL_ROW(7);
- CREATE_MSG_MASK_TBL_ROW(8);
- CREATE_MSG_MASK_TBL_ROW(9);
- CREATE_MSG_MASK_TBL_ROW(10);
- CREATE_MSG_MASK_TBL_ROW(11);
- CREATE_MSG_MASK_TBL_ROW(12);
- CREATE_MSG_MASK_TBL_ROW(13);
- CREATE_MSG_MASK_TBL_ROW(14);
- CREATE_MSG_MASK_TBL_ROW(15);
- CREATE_MSG_MASK_TBL_ROW(16);
- CREATE_MSG_MASK_TBL_ROW(17);
- CREATE_MSG_MASK_TBL_ROW(18);
- CREATE_MSG_MASK_TBL_ROW(19);
- CREATE_MSG_MASK_TBL_ROW(20);
- CREATE_MSG_MASK_TBL_ROW(21);
- CREATE_MSG_MASK_TBL_ROW(22);
- CREATE_MSG_MASK_TBL_ROW(23);
-}
-
-static void diag_set_msg_mask(int rt_mask)
-{
- int first_ssid, last_ssid, i;
- uint8_t *parse_ptr, *ptr = driver->msg_masks;
-
- mutex_lock(&driver->diagchar_mutex);
- while (*(uint32_t *)(ptr + 4)) {
- first_ssid = *(uint32_t *)ptr;
- ptr += 8; /* increment by 8 to skip 'last' */
- last_ssid = *(uint32_t *)ptr;
- ptr += 4;
- parse_ptr = ptr;
- pr_debug("diag: updating range %d %d\n", first_ssid, last_ssid);
- for (i = 0; i < last_ssid - first_ssid + 1; i++) {
- *(int *)parse_ptr = rt_mask;
- parse_ptr += 4;
- }
- ptr += MAX_SSID_PER_RANGE * 4;
- }
- mutex_unlock(&driver->diagchar_mutex);
-}
-
-static void diag_update_msg_mask(int start, int end , uint8_t *buf)
-{
- int found = 0, first, last, actual_last;
- uint8_t *actual_last_ptr;
- uint8_t *ptr = driver->msg_masks;
- uint8_t *ptr_buffer_start = &(*(driver->msg_masks));
- uint8_t *ptr_buffer_end = &(*(driver->msg_masks)) + MSG_MASK_SIZE;
-
- mutex_lock(&driver->diagchar_mutex);
-
- /* First SSID can be zero : So check that last is non-zero */
- while (*(uint32_t *)(ptr + 4)) {
- first = *(uint32_t *)ptr;
- ptr += 4;
- last = *(uint32_t *)ptr;
- ptr += 4;
- actual_last = *(uint32_t *)ptr;
- actual_last_ptr = ptr;
- ptr += 4;
- if (start >= first && start <= actual_last) {
- ptr += (start - first)*4;
- if (end > actual_last) {
- pr_info("diag: ssid range mismatch\n");
- actual_last = end;
- *(uint32_t *)(actual_last_ptr) = end;
- }
- if (CHK_OVERFLOW(ptr_buffer_start, ptr, ptr_buffer_end,
- (((end - start)+1)*4))) {
- pr_debug("diag: update ssid start %d, end %d\n",
- start, end);
- memcpy(ptr, buf , ((end - start)+1)*4);
- } else
- pr_alert("diag: Not enough space MSG_MASK\n");
- found = 1;
- break;
- } else {
- ptr += MAX_SSID_PER_RANGE*4;
- }
- }
- /* Entry was not found - add new table */
- if (!found) {
- if (CHK_OVERFLOW(ptr_buffer_start, ptr, ptr_buffer_end,
- 8 + ((end - start) + 1)*4)) {
- memcpy(ptr, &(start) , 4);
- ptr += 4;
- memcpy(ptr, &(end), 4);
- ptr += 4;
- memcpy(ptr, &(end), 4); /* create actual_last entry */
- ptr += 4;
- pr_debug("diag: adding NEW ssid start %d, end %d\n",
- start, end);
- memcpy(ptr, buf , ((end - start) + 1)*4);
- } else
- pr_alert("diag: Not enough buffer space for MSG_MASK\n");
- }
- mutex_unlock(&driver->diagchar_mutex);
- diag_print_mask_table();
-}
-
-void diag_toggle_event_mask(int toggle)
-{
- uint8_t *ptr = driver->event_masks;
-
- mutex_lock(&driver->diagchar_mutex);
- if (toggle)
- memset(ptr, 0xFF, EVENT_MASK_SIZE);
- else
- memset(ptr, 0, EVENT_MASK_SIZE);
- mutex_unlock(&driver->diagchar_mutex);
-}
-
-static void diag_update_event_mask(uint8_t *buf, int toggle, int num_bytes)
-{
- uint8_t *ptr = driver->event_masks;
- uint8_t *temp = buf + 2;
-
- mutex_lock(&driver->diagchar_mutex);
- if (!toggle)
- memset(ptr, 0 , EVENT_MASK_SIZE);
- else
- if (CHK_OVERFLOW(ptr, ptr,
- ptr+EVENT_MASK_SIZE, num_bytes))
- memcpy(ptr, temp , num_bytes);
- else
- printk(KERN_CRIT "Not enough buffer space "
- "for EVENT_MASK\n");
- mutex_unlock(&driver->diagchar_mutex);
-}
-
-static void diag_disable_log_mask(void)
-{
- int i = 0;
- struct mask_info *parse_ptr = (struct mask_info *)(driver->log_masks);
-
- pr_debug("diag: disable log masks\n");
- mutex_lock(&driver->diagchar_mutex);
- for (i = 0; i < MAX_EQUIP_ID; i++) {
- pr_debug("diag: equip id %d\n", parse_ptr->equip_id);
- if (!(parse_ptr->equip_id)) /* Reached a null entry */
- break;
- memset(driver->log_masks + parse_ptr->index, 0,
- (parse_ptr->num_items + 7)/8);
- parse_ptr++;
- }
- mutex_unlock(&driver->diagchar_mutex);
-}
-
-int chk_equip_id_and_mask(int equip_id, uint8_t *buf)
-{
- int i = 0, flag = 0, num_items, offset;
- unsigned char *ptr_data;
- struct mask_info *ptr = (struct mask_info *)(driver->log_masks);
-
- pr_debug("diag: received equip id = %d\n", equip_id);
- /* Check if this is valid equipment ID */
- for (i = 0; i < MAX_EQUIP_ID; i++) {
- if ((ptr->equip_id == equip_id) && (ptr->index != 0)) {
- offset = ptr->index;
- num_items = ptr->num_items;
- flag = 1;
- break;
- }
- ptr++;
- }
- if (!flag)
- return -EPERM;
- ptr_data = driver->log_masks + offset;
- memcpy(buf, ptr_data, (num_items+7)/8);
- return 0;
-}
-
-static void diag_update_log_mask(int equip_id, uint8_t *buf, int num_items)
-{
- uint8_t *temp = buf;
- int i = 0;
- unsigned char *ptr_data;
- int offset = (sizeof(struct mask_info))*MAX_EQUIP_ID;
- struct mask_info *ptr = (struct mask_info *)(driver->log_masks);
-
- pr_debug("diag: received equip id = %d\n", equip_id);
- mutex_lock(&driver->diagchar_mutex);
- /* Check if we already know index of this equipment ID */
- for (i = 0; i < MAX_EQUIP_ID; i++) {
- if ((ptr->equip_id == equip_id) && (ptr->index != 0)) {
- offset = ptr->index;
- break;
- }
- if ((ptr->equip_id == 0) && (ptr->index == 0)) {
- /* Reached a null entry */
- ptr->equip_id = equip_id;
- ptr->num_items = num_items;
- ptr->index = driver->log_masks_length;
- offset = driver->log_masks_length;
- driver->log_masks_length += ((num_items+7)/8);
- break;
- }
- ptr++;
- }
- ptr_data = driver->log_masks + offset;
- if (CHK_OVERFLOW(driver->log_masks, ptr_data, driver->log_masks
- + LOG_MASK_SIZE, (num_items+7)/8))
- memcpy(ptr_data, temp , (num_items+7)/8);
- else
- pr_err("diag: Not enough buffer space for LOG_MASK\n");
- mutex_unlock(&driver->diagchar_mutex);
-}
-
static void diag_update_pkt_buffer(unsigned char *buf)
{
unsigned char *ptr = driver->pkt_buf;
@@ -869,415 +604,21 @@
}
}
-void diag_modem_mask_update_fn(struct work_struct *work)
-{
- diag_send_msg_mask_update(driver->ch_cntl, ALL_SSID,
- ALL_SSID, MODEM_PROC);
- diag_send_log_mask_update(driver->ch_cntl, ALL_EQUIP_ID);
- diag_send_event_mask_update(driver->ch_cntl, diag_event_num_bytes);
-}
-
-void diag_lpass_mask_update_fn(struct work_struct *work)
-{
- diag_send_msg_mask_update(driver->chlpass_cntl, ALL_SSID,
- ALL_SSID, LPASS_PROC);
- diag_send_log_mask_update(driver->chlpass_cntl, ALL_EQUIP_ID);
- diag_send_event_mask_update(driver->chlpass_cntl, diag_event_num_bytes);
-}
-
-void diag_wcnss_mask_update_fn(struct work_struct *work)
-{
- diag_send_msg_mask_update(driver->ch_wcnss_cntl, ALL_SSID,
- ALL_SSID, WCNSS_PROC);
- diag_send_log_mask_update(driver->ch_wcnss_cntl, ALL_EQUIP_ID);
- diag_send_event_mask_update(driver->ch_wcnss_cntl,
- diag_event_num_bytes);
-}
-
-void diag_send_log_mask_update(smd_channel_t *ch, int equip_id)
-{
- void *buf = driver->buf_log_mask_update;
- int header_size = sizeof(struct diag_ctrl_log_mask);
- struct mask_info *ptr = (struct mask_info *)driver->log_masks;
- int i, size, wr_size = -ENOMEM, retry_count = 0, timer;
-
- mutex_lock(&driver->diag_cntl_mutex);
- for (i = 0; i < MAX_EQUIP_ID; i++) {
- size = (ptr->num_items+7)/8;
- /* reached null entry */
- if ((ptr->equip_id == 0) && (ptr->index == 0))
- break;
- driver->log_mask->cmd_type = DIAG_CTRL_MSG_LOG_MASK;
- driver->log_mask->num_items = ptr->num_items;
- driver->log_mask->data_len = 11 + size;
- driver->log_mask->stream_id = 1; /* 2, if dual stream */
- driver->log_mask->status = 3; /* status for valid mask */
- driver->log_mask->equip_id = ptr->equip_id;
- driver->log_mask->log_mask_size = size;
- /* send only desired update, NOT ALL */
- if (equip_id == ALL_EQUIP_ID || equip_id ==
- driver->log_mask->equip_id) {
- memcpy(buf, driver->log_mask, header_size);
- memcpy(buf+header_size, driver->log_masks+ptr->index,
- size);
- if (ch) {
- while (retry_count < 3) {
- wr_size = smd_write(ch, buf,
- header_size + size);
- if (wr_size == -ENOMEM) {
- retry_count++;
- for (timer = 0; timer < 5;
- timer++)
- udelay(2000);
- } else
- break;
- }
- if (wr_size != header_size + size)
- pr_err("diag: log mask update failed"
- " %d, tried %d", wr_size, header_size + size);
- else
- pr_debug("diag: updated log equip ID %d"
- ",len %d\n", driver->log_mask->equip_id,
- driver->log_mask->log_mask_size);
- } else
- pr_err("diag: ch not valid for log update\n");
- }
- ptr++;
- }
- mutex_unlock(&driver->diag_cntl_mutex);
-}
-
-void diag_send_event_mask_update(smd_channel_t *ch, int num_bytes)
-{
- void *buf = driver->buf_event_mask_update;
- int header_size = sizeof(struct diag_ctrl_event_mask);
- int wr_size = -ENOMEM, retry_count = 0, timer;
-
- mutex_lock(&driver->diag_cntl_mutex);
- if (num_bytes == 0) {
- pr_debug("diag: event mask not set yet, so no update\n");
- mutex_unlock(&driver->diag_cntl_mutex);
- return;
- }
- /* send event mask update */
- driver->event_mask->cmd_type = DIAG_CTRL_MSG_EVENT_MASK;
- driver->event_mask->data_len = 7 + num_bytes;
- driver->event_mask->stream_id = 1; /* 2, if dual stream */
- driver->event_mask->status = 3; /* status for valid mask */
- driver->event_mask->event_config = diag_event_config; /* event config */
- driver->event_mask->event_mask_size = num_bytes;
- memcpy(buf, driver->event_mask, header_size);
- memcpy(buf+header_size, driver->event_masks, num_bytes);
- if (ch) {
- while (retry_count < 3) {
- wr_size = smd_write(ch, buf, header_size + num_bytes);
- if (wr_size == -ENOMEM) {
- retry_count++;
- for (timer = 0; timer < 5; timer++)
- udelay(2000);
- } else
- break;
- }
- if (wr_size != header_size + num_bytes)
- pr_err("diag: error writing event mask %d, tried %d\n",
- wr_size, header_size + num_bytes);
- } else
- pr_err("diag: ch not valid for event update\n");
- mutex_unlock(&driver->diag_cntl_mutex);
-}
-
-void diag_send_msg_mask_update(smd_channel_t *ch, int updated_ssid_first,
- int updated_ssid_last, int proc)
-{
- void *buf = driver->buf_msg_mask_update;
- int first, last, actual_last, size = -ENOMEM, retry_count = 0, timer;
- int header_size = sizeof(struct diag_ctrl_msg_mask);
- uint8_t *ptr = driver->msg_masks;
-
- mutex_lock(&driver->diag_cntl_mutex);
- while (*(uint32_t *)(ptr + 4)) {
- first = *(uint32_t *)ptr;
- ptr += 4;
- last = *(uint32_t *)ptr;
- ptr += 4;
- actual_last = *(uint32_t *)ptr;
- ptr += 4;
- if ((updated_ssid_first >= first && updated_ssid_last <=
- actual_last) || (updated_ssid_first == ALL_SSID)) {
- /* send f3 mask update */
- driver->msg_mask->cmd_type = DIAG_CTRL_MSG_F3_MASK;
- driver->msg_mask->msg_mask_size = actual_last -
- first + 1;
- driver->msg_mask->data_len = 11 +
- 4 * (driver->msg_mask->msg_mask_size);
- driver->msg_mask->stream_id = 1; /* 2, if dual stream */
- driver->msg_mask->status = 3; /* status valid mask */
- driver->msg_mask->msg_mode = 0; /* Legcay mode */
- driver->msg_mask->ssid_first = first;
- driver->msg_mask->ssid_last = actual_last;
- memcpy(buf, driver->msg_mask, header_size);
- memcpy(buf+header_size, ptr,
- 4 * (driver->msg_mask->msg_mask_size));
- if (ch) {
- while (retry_count < 3) {
- size = smd_write(ch, buf, header_size +
- 4*(driver->msg_mask->msg_mask_size));
- if (size == -ENOMEM) {
- retry_count++;
- for (timer = 0; timer < 5;
- timer++)
- udelay(2000);
- } else
- break;
- }
- if (size != header_size +
- 4*(driver->msg_mask->msg_mask_size))
- pr_err("diag: proc %d, msg mask update "
- "fail %d, tried %d\n", proc, size,
- header_size + 4*(driver->msg_mask->msg_mask_size));
- else
- pr_debug("diag: sending mask update for ssid first %d, last %d on PROC %d\n",
- first, actual_last, proc);
- } else
- pr_err("diag: proc %d, ch invalid msg mask"
- "update\n", proc);
- }
- ptr += MAX_SSID_PER_RANGE*4;
- }
- mutex_unlock(&driver->diag_cntl_mutex);
-}
-
static int diag_process_apps_pkt(unsigned char *buf, int len)
{
uint16_t subsys_cmd_code;
int subsys_id, ssid_first, ssid_last, ssid_range;
int packet_type = 1, i, cmd_code;
- int rt_mask, rt_first_ssid, rt_last_ssid, rt_mask_size;
unsigned char *temp = buf;
- uint8_t *rt_mask_ptr;
- int data_type, equip_id, num_items;
+ int data_type;
#if defined(CONFIG_DIAG_OVER_USB)
- int payload_length;
unsigned char *ptr;
#endif
- /* Set log masks */
- if (*buf == 0x73 && *(int *)(buf+4) == 3) {
- buf += 8;
- /* Read Equip ID and pass as first param below*/
- diag_update_log_mask(*(int *)buf, buf+8, *(int *)(buf+4));
- diag_update_userspace_clients(LOG_MASKS_TYPE);
-#if defined(CONFIG_DIAG_OVER_USB)
- if (chk_apps_only()) {
- driver->apps_rsp_buf[0] = 0x73;
- *(int *)(driver->apps_rsp_buf + 4) = 0x3; /* op. ID */
- *(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success */
- payload_length = 8 + ((*(int *)(buf + 4)) + 7)/8;
- for (i = 0; i < payload_length; i++)
- *(int *)(driver->apps_rsp_buf+12+i) = *(buf+i);
- if (driver->ch_cntl)
- diag_send_log_mask_update(driver->ch_cntl,
- *(int *)buf);
- if (driver->chlpass_cntl)
- diag_send_log_mask_update(driver->chlpass_cntl,
- *(int *)buf);
- if (driver->ch_wcnss_cntl)
- diag_send_log_mask_update(driver->ch_wcnss_cntl,
- *(int *)buf);
- ENCODE_RSP_AND_SEND(12 + payload_length - 1);
- return 0;
- } else
- buf = temp;
-#endif
- } /* Get log masks */
- else if (*buf == 0x73 && *(int *)(buf+4) == 4) {
-#if defined(CONFIG_DIAG_OVER_USB)
- if (!(driver->ch) && chk_apps_only()) {
- equip_id = *(int *)(buf + 8);
- num_items = *(int *)(buf + 12);
- driver->apps_rsp_buf[0] = 0x73;
- driver->apps_rsp_buf[1] = 0x0;
- driver->apps_rsp_buf[2] = 0x0;
- driver->apps_rsp_buf[3] = 0x0;
- *(int *)(driver->apps_rsp_buf + 4) = 0x4;
- if (!chk_equip_id_and_mask(equip_id,
- driver->apps_rsp_buf+20))
- *(int *)(driver->apps_rsp_buf + 8) = 0x0;
- else
- *(int *)(driver->apps_rsp_buf + 8) = 0x1;
- *(int *)(driver->apps_rsp_buf + 12) = equip_id;
- *(int *)(driver->apps_rsp_buf + 16) = num_items;
- ENCODE_RSP_AND_SEND(20+(num_items+7)/8-1);
- return 0;
- } else
- buf = temp;
-#endif
- } /* Disable log masks */
- else if (*buf == 0x73 && *(int *)(buf+4) == 0) {
- /* Disable mask for each log code */
- diag_disable_log_mask();
- diag_update_userspace_clients(LOG_MASKS_TYPE);
-#if defined(CONFIG_DIAG_OVER_USB)
- if (chk_apps_only()) {
- driver->apps_rsp_buf[0] = 0x73;
- driver->apps_rsp_buf[1] = 0x0;
- driver->apps_rsp_buf[2] = 0x0;
- driver->apps_rsp_buf[3] = 0x0;
- *(int *)(driver->apps_rsp_buf + 4) = 0x0;
- *(int *)(driver->apps_rsp_buf + 8) = 0x0; /* status */
- if (driver->ch_cntl)
- diag_send_log_mask_update(driver->ch_cntl,
- ALL_EQUIP_ID);
- if (driver->chlpass_cntl)
- diag_send_log_mask_update(driver->chlpass_cntl,
- ALL_EQUIP_ID);
- if (driver->ch_wcnss_cntl)
- diag_send_log_mask_update(driver->ch_wcnss_cntl,
- ALL_EQUIP_ID);
- ENCODE_RSP_AND_SEND(11);
- return 0;
- }
-#endif
- } /* Get runtime message mask */
- else if ((*buf == 0x7d) && (*(buf+1) == 0x3)) {
- ssid_first = *(uint16_t *)(buf + 2);
- ssid_last = *(uint16_t *)(buf + 4);
-#if defined(CONFIG_DIAG_OVER_USB)
- if (!(driver->ch) && chk_apps_only()) {
- driver->apps_rsp_buf[0] = 0x7d;
- driver->apps_rsp_buf[1] = 0x3;
- *(uint16_t *)(driver->apps_rsp_buf+2) = ssid_first;
- *(uint16_t *)(driver->apps_rsp_buf+4) = ssid_last;
- driver->apps_rsp_buf[6] = 0x1; /* Success Status */
- driver->apps_rsp_buf[7] = 0x0;
- rt_mask_ptr = driver->msg_masks;
- while (*(uint32_t *)(rt_mask_ptr + 4)) {
- rt_first_ssid = *(uint32_t *)rt_mask_ptr;
- rt_mask_ptr += 8; /* +8 to skip 'last' */
- rt_last_ssid = *(uint32_t *)rt_mask_ptr;
- rt_mask_ptr += 4;
- if (ssid_first == rt_first_ssid && ssid_last ==
- rt_last_ssid) {
- rt_mask_size = 4 * (rt_last_ssid -
- rt_first_ssid + 1);
- memcpy(driver->apps_rsp_buf+8,
- rt_mask_ptr, rt_mask_size);
- ENCODE_RSP_AND_SEND(8+rt_mask_size-1);
- return 0;
- }
- rt_mask_ptr += MAX_SSID_PER_RANGE*4;
- }
- } else
- buf = temp;
-#endif
- } /* Set runtime message mask */
- else if ((*buf == 0x7d) && (*(buf+1) == 0x4)) {
- ssid_first = *(uint16_t *)(buf + 2);
- ssid_last = *(uint16_t *)(buf + 4);
- ssid_range = 4 * (ssid_last - ssid_first + 1);
- pr_debug("diag: received mask update for ssid_first = %d,"
- " ssid_last = %d", ssid_first, ssid_last);
- diag_update_msg_mask(ssid_first, ssid_last , buf + 8);
- diag_update_userspace_clients(MSG_MASKS_TYPE);
-#if defined(CONFIG_DIAG_OVER_USB)
- if (chk_apps_only()) {
- for (i = 0; i < 8 + ssid_range; i++)
- *(driver->apps_rsp_buf + i) = *(buf+i);
- *(driver->apps_rsp_buf + 6) = 0x1;
- if (driver->ch_cntl)
- diag_send_msg_mask_update(driver->ch_cntl,
- ssid_first, ssid_last, MODEM_PROC);
- if (driver->chlpass_cntl)
- diag_send_msg_mask_update(driver->chlpass_cntl,
- ssid_first, ssid_last, LPASS_PROC);
- if (driver->ch_wcnss_cntl)
- diag_send_msg_mask_update(driver->ch_wcnss_cntl,
- ssid_first, ssid_last, WCNSS_PROC);
- ENCODE_RSP_AND_SEND(8 + ssid_range - 1);
- return 0;
- } else
- buf = temp;
-#endif
- } /* Set ALL runtime message mask */
- else if ((*buf == 0x7d) && (*(buf+1) == 0x5)) {
- rt_mask = *(int *)(buf + 4);
- diag_set_msg_mask(rt_mask);
- diag_update_userspace_clients(MSG_MASKS_TYPE);
-#if defined(CONFIG_DIAG_OVER_USB)
- if (chk_apps_only()) {
- driver->apps_rsp_buf[0] = 0x7d; /* cmd_code */
- driver->apps_rsp_buf[1] = 0x5; /* set subcommand */
- driver->apps_rsp_buf[2] = 1; /* success */
- driver->apps_rsp_buf[3] = 0; /* rsvd */
- *(int *)(driver->apps_rsp_buf + 4) = rt_mask;
- /* send msg mask update to peripheral */
- if (driver->ch_cntl)
- diag_send_msg_mask_update(driver->ch_cntl,
- ALL_SSID, ALL_SSID, MODEM_PROC);
- if (driver->chlpass_cntl)
- diag_send_msg_mask_update(driver->chlpass_cntl,
- ALL_SSID, ALL_SSID, LPASS_PROC);
- if (driver->ch_wcnss_cntl)
- diag_send_msg_mask_update(driver->ch_wcnss_cntl,
- ALL_SSID, ALL_SSID, WCNSS_PROC);
- ENCODE_RSP_AND_SEND(7);
- return 0;
- } else
- buf = temp;
-#endif
- } else if (*buf == 0x82) { /* event mask change */
- buf += 4;
- diag_event_num_bytes = (*(uint16_t *)buf)/8+1;
- diag_update_event_mask(buf, 1, (*(uint16_t *)buf)/8+1);
- diag_update_userspace_clients(EVENT_MASKS_TYPE);
-#if defined(CONFIG_DIAG_OVER_USB)
- if (chk_apps_only()) {
- driver->apps_rsp_buf[0] = 0x82;
- driver->apps_rsp_buf[1] = 0x0;
- *(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
- *(uint16_t *)(driver->apps_rsp_buf + 4) =
- EVENT_LAST_ID + 1;
- memcpy(driver->apps_rsp_buf+6, driver->event_masks,
- EVENT_LAST_ID/8+1);
- if (driver->ch_cntl)
- diag_send_event_mask_update(driver->ch_cntl,
- diag_event_num_bytes);
- if (driver->chlpass_cntl)
- diag_send_event_mask_update(
- driver->chlpass_cntl,
- diag_event_num_bytes);
- if (driver->ch_wcnss_cntl)
- diag_send_event_mask_update(
- driver->ch_wcnss_cntl, diag_event_num_bytes);
- ENCODE_RSP_AND_SEND(6 + EVENT_LAST_ID/8);
- return 0;
- } else
- buf = temp;
-#endif
- } else if (*buf == 0x60) {
- diag_event_config = *(buf+1);
- diag_toggle_event_mask(*(buf+1));
- diag_update_userspace_clients(EVENT_MASKS_TYPE);
-#if defined(CONFIG_DIAG_OVER_USB)
- if (chk_apps_only()) {
- driver->apps_rsp_buf[0] = 0x60;
- driver->apps_rsp_buf[1] = 0x0;
- driver->apps_rsp_buf[2] = 0x0;
- if (driver->ch_cntl)
- diag_send_event_mask_update(driver->ch_cntl,
- diag_event_num_bytes);
- if (driver->chlpass_cntl)
- diag_send_event_mask_update(
- driver->chlpass_cntl,
- diag_event_num_bytes);
- if (driver->ch_wcnss_cntl)
- diag_send_event_mask_update(
- driver->ch_wcnss_cntl, diag_event_num_bytes);
- ENCODE_RSP_AND_SEND(2);
- return 0;
- }
-#endif
- }
+ /* Check if the command is a supported mask command */
+ if (diag_process_apps_masks(buf, len) == 0)
+ return 0;
+
/* Check for registered clients and forward packet to apropriate proc */
cmd_code = (int)(*(char *)buf);
temp++;
@@ -1334,7 +675,7 @@
for (i = 0; i < 4; i++)
*(driver->apps_rsp_buf+i) = *(buf+i);
*(uint32_t *)(driver->apps_rsp_buf+4) = PKT_SIZE;
- ENCODE_RSP_AND_SEND(7);
+ encode_rsp_and_send(7);
return 0;
}
/* Check for Apps Only & get event mask request */
@@ -1345,7 +686,7 @@
*(uint16_t *)(driver->apps_rsp_buf + 4) = EVENT_LAST_ID + 1;
for (i = 0; i < EVENT_LAST_ID/8 + 1; i++)
*(unsigned char *)(driver->apps_rsp_buf + 6 + i) = 0x0;
- ENCODE_RSP_AND_SEND(6 + EVENT_LAST_ID/8);
+ encode_rsp_and_send(6 + EVENT_LAST_ID/8);
return 0;
}
/* Get log ID range & Check for Apps Only */
@@ -1370,7 +711,7 @@
*(int *)(driver->apps_rsp_buf + 64) = LOG_GET_ITEM_NUM(LOG_13);
*(int *)(driver->apps_rsp_buf + 68) = LOG_GET_ITEM_NUM(LOG_14);
*(int *)(driver->apps_rsp_buf + 72) = LOG_GET_ITEM_NUM(LOG_15);
- ENCODE_RSP_AND_SEND(75);
+ encode_rsp_and_send(75);
return 0;
}
/* Respond to Get SSID Range request message */
@@ -1428,7 +769,7 @@
*(uint16_t *)(driver->apps_rsp_buf + 94) = MSG_SSID_21_LAST;
*(uint16_t *)(driver->apps_rsp_buf + 96) = MSG_SSID_22;
*(uint16_t *)(driver->apps_rsp_buf + 98) = MSG_SSID_22_LAST;
- ENCODE_RSP_AND_SEND(99);
+ encode_rsp_and_send(99);
return 0;
}
/* Check for Apps Only Respond to Get Subsys Build mask */
@@ -1540,14 +881,14 @@
*(int *)(ptr + i) = msg_bld_masks_22[i/4];
break;
}
- ENCODE_RSP_AND_SEND(8 + ssid_range - 1);
+ encode_rsp_and_send(8 + ssid_range - 1);
return 0;
}
/* Check for download command */
else if ((cpu_is_msm8x60() || chk_apps_master()) && (*buf == 0x3A)) {
/* send response back */
driver->apps_rsp_buf[0] = *buf;
- ENCODE_RSP_AND_SEND(0);
+ encode_rsp_and_send(0);
msleep(5000);
/* call download API */
msm_set_restart_mode(RESTART_DLOAD);
@@ -1567,7 +908,7 @@
for (i = 0; i < 13; i++)
driver->apps_rsp_buf[i+3] = 0;
- ENCODE_RSP_AND_SEND(15);
+ encode_rsp_and_send(15);
return 0;
}
}
@@ -1578,7 +919,7 @@
for (i = 0; i < 55; i++)
driver->apps_rsp_buf[i] = 0;
- ENCODE_RSP_AND_SEND(54);
+ encode_rsp_and_send(54);
return 0;
}
/* respond to 0x7c command */
@@ -1591,12 +932,12 @@
chk_config_get_id();
*(unsigned char *)(driver->apps_rsp_buf + 12) = '\0';
*(unsigned char *)(driver->apps_rsp_buf + 13) = '\0';
- ENCODE_RSP_AND_SEND(13);
+ encode_rsp_and_send(13);
return 0;
}
}
#endif
- return packet_type;
+ return packet_type;
}
#ifdef CONFIG_DIAG_OVER_USB
@@ -1611,7 +952,7 @@
driver->apps_rsp_buf[0] = 0x13; /* error code 13 */
for (i = 0; i < index; i++)
driver->apps_rsp_buf[i+1] = *(driver->hdlc_buf+i);
- ENCODE_RSP_AND_SEND(index - 3);
+ encode_rsp_and_send(index - 3);
}
#else
static inline void diag_send_error_rsp(int index) {}
@@ -1994,27 +1335,6 @@
driver->use_device_tree = has_device_tree();
mutex_init(&driver->diag_cntl_mutex);
- if (driver->event_mask == NULL) {
- driver->event_mask = kzalloc(sizeof(
- struct diag_ctrl_event_mask), GFP_KERNEL);
- if (driver->event_mask == NULL)
- goto err;
- kmemleak_not_leak(driver->event_mask);
- }
- if (driver->msg_mask == NULL) {
- driver->msg_mask = kzalloc(sizeof(
- struct diag_ctrl_msg_mask), GFP_KERNEL);
- if (driver->msg_mask == NULL)
- goto err;
- kmemleak_not_leak(driver->msg_mask);
- }
- if (driver->log_mask == NULL) {
- driver->log_mask = kzalloc(sizeof(
- struct diag_ctrl_log_mask), GFP_KERNEL);
- if (driver->log_mask == NULL)
- goto err;
- kmemleak_not_leak(driver->log_mask);
- }
if (driver->buf_in_1 == NULL) {
driver->buf_in_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
if (driver->buf_in_1 == NULL)
@@ -2051,28 +1371,6 @@
goto err;
kmemleak_not_leak(driver->buf_in_wcnss_2);
}
-
- if (driver->buf_msg_mask_update == NULL) {
- driver->buf_msg_mask_update = kzalloc(APPS_BUF_SIZE,
- GFP_KERNEL);
- if (driver->buf_msg_mask_update == NULL)
- goto err;
- kmemleak_not_leak(driver->buf_msg_mask_update);
- }
- if (driver->buf_log_mask_update == NULL) {
- driver->buf_log_mask_update = kzalloc(APPS_BUF_SIZE,
- GFP_KERNEL);
- if (driver->buf_log_mask_update == NULL)
- goto err;
- kmemleak_not_leak(driver->buf_log_mask_update);
- }
- if (driver->buf_event_mask_update == NULL) {
- driver->buf_event_mask_update = kzalloc(APPS_BUF_SIZE,
- GFP_KERNEL);
- if (driver->buf_event_mask_update == NULL)
- goto err;
- kmemleak_not_leak(driver->buf_event_mask_update);
- }
if (driver->usb_buf_out == NULL &&
(driver->usb_buf_out = kzalloc(USB_MAX_OUT_BUF,
GFP_KERNEL)) == NULL)
@@ -2087,23 +1385,6 @@
if (driver->user_space_data == NULL)
goto err;
kmemleak_not_leak(driver->user_space_data);
- if (driver->msg_masks == NULL
- && (driver->msg_masks = kzalloc(MSG_MASK_SIZE,
- GFP_KERNEL)) == NULL)
- goto err;
- kmemleak_not_leak(driver->msg_masks);
- diag_create_msg_mask_table();
- diag_event_num_bytes = 0;
- if (driver->log_masks == NULL &&
- (driver->log_masks = kzalloc(LOG_MASK_SIZE, GFP_KERNEL)) == NULL)
- goto err;
- kmemleak_not_leak(driver->log_masks);
- driver->log_masks_length = (sizeof(struct mask_info))*MAX_EQUIP_ID;
- if (driver->event_masks == NULL &&
- (driver->event_masks = kzalloc(EVENT_MASK_SIZE,
- GFP_KERNEL)) == NULL)
- goto err;
- kmemleak_not_leak(driver->event_masks);
if (driver->client_map == NULL &&
(driver->client_map = kzalloc
((driver->num_clients) * sizeof(struct diag_client_map),
@@ -2192,12 +1473,6 @@
#ifdef CONFIG_DIAG_OVER_USB
INIT_WORK(&(driver->diag_proc_hdlc_work), diag_process_hdlc_fn);
INIT_WORK(&(driver->diag_read_work), diag_read_work_fn);
- INIT_WORK(&(driver->diag_modem_mask_update_work),
- diag_modem_mask_update_fn);
- INIT_WORK(&(driver->diag_lpass_mask_update_work),
- diag_lpass_mask_update_fn);
- INIT_WORK(&(driver->diag_wcnss_mask_update_work),
- diag_wcnss_mask_update_fn);
driver->legacy_ch = usb_diag_open(DIAG_LEGACY, driver,
diag_usb_legacy_notifier);
if (IS_ERR(driver->legacy_ch)) {
@@ -2210,40 +1485,34 @@
return;
err:
- pr_err("diag: Could not initialize diag buffers");
- kfree(driver->event_mask);
- kfree(driver->log_mask);
- kfree(driver->msg_mask);
- kfree(driver->buf_in_1);
- kfree(driver->buf_in_2);
- kfree(driver->buf_in_lpass_1);
- kfree(driver->buf_in_lpass_2);
- kfree(driver->buf_in_wcnss_1);
- kfree(driver->buf_in_wcnss_2);
- kfree(driver->buf_msg_mask_update);
- kfree(driver->buf_log_mask_update);
- kfree(driver->buf_event_mask_update);
- kfree(driver->usb_buf_out);
- kfree(driver->hdlc_buf);
- kfree(driver->msg_masks);
- kfree(driver->log_masks);
- kfree(driver->event_masks);
- kfree(driver->client_map);
- kfree(driver->buf_tbl);
- kfree(driver->data_ready);
- kfree(driver->table);
- kfree(driver->pkt_buf);
- kfree(driver->write_ptr_1);
- kfree(driver->write_ptr_2);
- kfree(driver->write_ptr_lpass_1);
- kfree(driver->write_ptr_lpass_2);
- kfree(driver->write_ptr_wcnss_1);
- kfree(driver->write_ptr_wcnss_2);
- kfree(driver->usb_read_ptr);
- kfree(driver->apps_rsp_buf);
- kfree(driver->user_space_data);
- if (driver->diag_wq)
- destroy_workqueue(driver->diag_wq);
+ pr_err("diag: Could not initialize diag buffers");
+ kfree(driver->buf_in_1);
+ kfree(driver->buf_in_2);
+ kfree(driver->buf_in_lpass_1);
+ kfree(driver->buf_in_lpass_2);
+ kfree(driver->buf_in_wcnss_1);
+ kfree(driver->buf_in_wcnss_2);
+ kfree(driver->buf_msg_mask_update);
+ kfree(driver->buf_log_mask_update);
+ kfree(driver->buf_event_mask_update);
+ kfree(driver->usb_buf_out);
+ kfree(driver->hdlc_buf);
+ kfree(driver->client_map);
+ kfree(driver->buf_tbl);
+ kfree(driver->data_ready);
+ kfree(driver->table);
+ kfree(driver->pkt_buf);
+ kfree(driver->write_ptr_1);
+ kfree(driver->write_ptr_2);
+ kfree(driver->write_ptr_lpass_1);
+ kfree(driver->write_ptr_lpass_2);
+ kfree(driver->write_ptr_wcnss_1);
+ kfree(driver->write_ptr_wcnss_2);
+ kfree(driver->usb_read_ptr);
+ kfree(driver->apps_rsp_buf);
+ kfree(driver->user_space_data);
+ if (driver->diag_wq)
+ destroy_workqueue(driver->diag_wq);
}
void diagfwd_exit(void)
@@ -2262,9 +1531,6 @@
platform_driver_unregister(&msm_smd_ch1_driver);
platform_driver_unregister(&msm_diag_dci_driver);
platform_driver_unregister(&diag_smd_lite_driver);
- kfree(driver->event_mask);
- kfree(driver->log_mask);
- kfree(driver->msg_mask);
kfree(driver->buf_in_1);
kfree(driver->buf_in_2);
kfree(driver->buf_in_lpass_1);
@@ -2276,9 +1542,6 @@
kfree(driver->buf_event_mask_update);
kfree(driver->usb_buf_out);
kfree(driver->hdlc_buf);
- kfree(driver->msg_masks);
- kfree(driver->log_masks);
- kfree(driver->event_masks);
kfree(driver->client_map);
kfree(driver->buf_tbl);
kfree(driver->data_ready);
diff --git a/drivers/char/diag/diagfwd.h b/drivers/char/diag/diagfwd.h
index cf7fda6..a0631d6 100644
--- a/drivers/char/diag/diagfwd.h
+++ b/drivers/char/diag/diagfwd.h
@@ -16,6 +16,9 @@
#define NO_PROCESS 0
#define NON_APPS_PROC -1
+#define CHK_OVERFLOW(bufStart, start, end, length) \
+ ((((bufStart) <= (start)) && ((end) - (start) >= (length))) ? 1 : 0)
+
void diagfwd_init(void);
void diagfwd_exit(void);
void diag_process_hdlc(void *data, unsigned len);
@@ -31,11 +34,9 @@
int chk_apps_only(void);
int chk_apps_master(void);
int chk_polling_response(void);
-void diag_send_event_mask_update(smd_channel_t *, int num_bytes);
-void diag_send_msg_mask_update(smd_channel_t *, int ssid_first,
- int ssid_last, int proc);
-void diag_send_log_mask_update(smd_channel_t *, int);
+void diag_update_userspace_clients(unsigned int type);
void diag_update_sleeping_process(int process_id, int data_type);
+void encode_rsp_and_send(int buf_length);
/* State for diag forwarding */
#ifdef CONFIG_DIAG_OVER_USB
int diagfwd_connect(void);
@@ -43,6 +44,5 @@
#endif
extern int diag_debug_buf_idx;
extern unsigned char diag_debug_buf[1024];
-extern int diag_event_num_bytes;
extern struct platform_driver msm_diag_dci_driver;
#endif
diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index 3bbd3fb..4848a1d 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.c
@@ -17,9 +17,6 @@
#include "diagchar.h"
#include "diagfwd.h"
#include "diagfwd_cntl.h"
-#ifdef CONFIG_DEBUG_FS
-#include <linux/debugfs.h>
-#endif
/* tracks which peripheral is undergoing SSR */
static uint16_t reg_dirty;
#define HDR_SIZ 8
@@ -365,291 +362,3 @@
kfree(driver->buf_in_lpass_cntl);
kfree(driver->buf_in_wcnss_cntl);
}
-
-#ifdef CONFIG_DEBUG_FS
-#define DEBUG_BUF_SIZE 4096
-static struct dentry *diag_dbgfs_dent;
-static int diag_dbgfs_table_index;
-
-static ssize_t diag_dbgfs_read_status(struct file *file, char __user *ubuf,
- size_t count, loff_t *ppos)
-{
- char *buf;
- int ret;
-
- buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
- if (!buf) {
- pr_err("diag: %s, Error allocating memory\n", __func__);
- return -ENOMEM;
- }
-
- ret = scnprintf(buf, DEBUG_BUF_SIZE,
- "modem ch: 0x%x\n"
- "lpass ch: 0x%x\n"
- "riva ch: 0x%x\n"
- "dci ch: 0x%x\n"
- "modem cntl_ch: 0x%x\n"
- "lpass cntl_ch: 0x%x\n"
- "riva cntl_ch: 0x%x\n"
- "CPU Tools id: %d\n"
- "Apps only: %d\n"
- "Apps master: %d\n"
- "Check Polling Response: %d\n"
- "polling_reg_flag: %d\n"
- "uses device tree: %d\n"
- "in_busy_1: %d\n"
- "in_busy_2: %d\n"
- "in_busy_lpass_1: %d\n"
- "in_busy_lpass_2: %d\n"
- "in_busy_wcnss_1: %d\n"
- "in_busy_wcnss_2: %d\n"
- "in_busy_dci: %d\n"
- "logging_mode: %d\n",
- (unsigned int)driver->ch,
- (unsigned int)driver->chlpass,
- (unsigned int)driver->ch_wcnss,
- (unsigned int)driver->ch_dci,
- (unsigned int)driver->ch_cntl,
- (unsigned int)driver->chlpass_cntl,
- (unsigned int)driver->ch_wcnss_cntl,
- chk_config_get_id(),
- chk_apps_only(),
- chk_apps_master(),
- chk_polling_response(),
- driver->polling_reg_flag,
- driver->use_device_tree,
- driver->in_busy_1,
- driver->in_busy_2,
- driver->in_busy_lpass_1,
- driver->in_busy_lpass_2,
- driver->in_busy_wcnss_1,
- driver->in_busy_wcnss_2,
- driver->in_busy_dci,
- driver->logging_mode);
-
-#ifdef CONFIG_DIAG_OVER_USB
- ret += scnprintf(buf+ret, DEBUG_BUF_SIZE,
- "usb_connected: %d\n",
- driver->usb_connected);
-#endif
- ret = simple_read_from_buffer(ubuf, count, ppos, buf, ret);
-
- kfree(buf);
- return ret;
-}
-
-static ssize_t diag_dbgfs_read_workpending(struct file *file,
- char __user *ubuf, size_t count, loff_t *ppos)
-{
- char *buf;
- int ret;
-
- buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
- if (!buf) {
- pr_err("diag: %s, Error allocating memory\n", __func__);
- return -ENOMEM;
- }
-
- ret = scnprintf(buf, DEBUG_BUF_SIZE,
- "Pending status for work_stucts:\n"
- "diag_drain_work: %d\n"
- "diag_read_smd_work: %d\n"
- "diag_read_smd_cntl_work: %d\n"
- "diag_read_smd_lpass_work: %d\n"
- "diag_read_smd_lpass_cntl_work: %d\n"
- "diag_read_smd_wcnss_work: %d\n"
- "diag_read_smd_wcnss_cntl_work: %d\n"
- "diag_modem_mask_update_work: %d\n"
- "diag_lpass_mask_update_work: %d\n"
- "diag_wcnss_mask_update_work: %d\n"
- "diag_read_smd_dci_work: %d\n",
- work_pending(&(driver->diag_drain_work)),
- work_pending(&(driver->diag_read_smd_work)),
- work_pending(&(driver->diag_read_smd_cntl_work)),
- work_pending(&(driver->diag_read_smd_lpass_work)),
- work_pending(&(driver->diag_read_smd_lpass_cntl_work)),
- work_pending(&(driver->diag_read_smd_wcnss_work)),
- work_pending(&(driver->diag_read_smd_wcnss_cntl_work)),
- work_pending(&(driver->diag_modem_mask_update_work)),
- work_pending(&(driver->diag_lpass_mask_update_work)),
- work_pending(&(driver->diag_wcnss_mask_update_work)),
- work_pending(&(driver->diag_read_smd_dci_work)));
-
-#ifdef CONFIG_DIAG_OVER_USB
- ret += scnprintf(buf+ret, DEBUG_BUF_SIZE,
- "diag_proc_hdlc_work: %d\n"
- "diag_read_work: %d\n",
- work_pending(&(driver->diag_proc_hdlc_work)),
- work_pending(&(driver->diag_read_work)));
-#endif
- ret = simple_read_from_buffer(ubuf, count, ppos, buf, ret);
-
- kfree(buf);
- return ret;
-}
-
-static ssize_t diag_dbgfs_read_table(struct file *file, char __user *ubuf,
- size_t count, loff_t *ppos)
-{
- char *buf;
- int ret = 0;
- int i;
- int bytes_remaining;
- int bytes_in_buffer = 0;
- int bytes_written;
- int buf_size = (DEBUG_BUF_SIZE < count) ? DEBUG_BUF_SIZE : count;
-
- if (diag_dbgfs_table_index >= diag_max_reg) {
- /* Done. Reset to prepare for future requests */
- diag_dbgfs_table_index = 0;
- return 0;
- }
-
- buf = kzalloc(sizeof(char) * buf_size, GFP_KERNEL);
- if (!buf) {
- pr_err("diag: %s, Error allocating memory\n", __func__);
- return -ENOMEM;
- }
-
- bytes_remaining = buf_size;
- for (i = diag_dbgfs_table_index; i < diag_max_reg; i++) {
- /* Do not process empty entries in the table */
- if (driver->table[i].process_id == 0)
- continue;
-
- bytes_written = scnprintf(buf+bytes_in_buffer, bytes_remaining,
- "i: %3d, cmd_code: %4x, subsys_id: %4x, "
- "client: %2d, cmd_code_lo: %4x, "
- "cmd_code_hi: %4x, process_id: %5d\n",
- i,
- driver->table[i].cmd_code,
- driver->table[i].subsys_id,
- driver->table[i].client_id,
- driver->table[i].cmd_code_lo,
- driver->table[i].cmd_code_hi,
- driver->table[i].process_id);
-
- bytes_in_buffer += bytes_written;
-
- /* Check if there is room to add another table entry */
- bytes_remaining = buf_size - bytes_in_buffer;
- if (bytes_remaining < bytes_written)
- break;
- }
- diag_dbgfs_table_index = i;
-
- *ppos = 0;
- ret = simple_read_from_buffer(ubuf, count, ppos, buf, bytes_in_buffer);
-
- kfree(buf);
- return ret;
-}
-
-#ifdef CONFIG_DIAG_BRIDGE_CODE
-static ssize_t diag_dbgfs_read_hsic(struct file *file, char __user *ubuf,
- size_t count, loff_t *ppos)
-{
- char *buf;
- int ret;
-
- buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
- if (!buf) {
- pr_err("diag: %s, Error allocating memory\n", __func__);
- return -ENOMEM;
- }
-
- ret = scnprintf(buf, DEBUG_BUF_SIZE,
- "hsic ch: %d\n"
- "hsic_inited: %d\n"
- "hsic enabled: %d\n"
- "hsic_opened: %d\n"
- "hsic_suspend: %d\n"
- "in_busy_hsic_read_on_device: %d\n"
- "in_busy_hsic_write: %d\n"
- "count_hsic_pool: %d\n"
- "count_hsic_write_pool: %d\n"
- "diag_hsic_pool: %x\n"
- "diag_hsic_write_pool: %x\n"
- "write_len_mdm: %d\n"
- "num_hsic_buf_tbl_entries: %d\n"
- "usb_mdm_connected: %d\n"
- "diag_read_mdm_work: %d\n"
- "diag_read_hsic_work: %d\n"
- "diag_disconnect_work: %d\n"
- "diag_usb_read_complete_work: %d\n",
- driver->hsic_ch,
- driver->hsic_inited,
- driver->hsic_device_enabled,
- driver->hsic_device_opened,
- driver->hsic_suspend,
- driver->in_busy_hsic_read_on_device,
- driver->in_busy_hsic_write,
- driver->count_hsic_pool,
- driver->count_hsic_write_pool,
- (unsigned int)driver->diag_hsic_pool,
- (unsigned int)driver->diag_hsic_write_pool,
- driver->write_len_mdm,
- driver->num_hsic_buf_tbl_entries,
- driver->usb_mdm_connected,
- work_pending(&(driver->diag_read_mdm_work)),
- work_pending(&(driver->diag_read_hsic_work)),
- work_pending(&(driver->diag_disconnect_work)),
- work_pending(&(driver->diag_usb_read_complete_work)));
-
- ret = simple_read_from_buffer(ubuf, count, ppos, buf, ret);
-
- kfree(buf);
- return ret;
-}
-
-const struct file_operations diag_dbgfs_hsic_ops = {
- .read = diag_dbgfs_read_hsic,
-};
-#endif
-
-const struct file_operations diag_dbgfs_status_ops = {
- .read = diag_dbgfs_read_status,
-};
-
-const struct file_operations diag_dbgfs_table_ops = {
- .read = diag_dbgfs_read_table,
-};
-
-const struct file_operations diag_dbgfs_workpending_ops = {
- .read = diag_dbgfs_read_workpending,
-};
-
-void diag_debugfs_init(void)
-{
- diag_dbgfs_dent = debugfs_create_dir("diag", 0);
- if (IS_ERR(diag_dbgfs_dent))
- return;
-
- debugfs_create_file("status", 0444, diag_dbgfs_dent, 0,
- &diag_dbgfs_status_ops);
-
- debugfs_create_file("table", 0444, diag_dbgfs_dent, 0,
- &diag_dbgfs_table_ops);
-
- debugfs_create_file("work_pending", 0444, diag_dbgfs_dent, 0,
- &diag_dbgfs_workpending_ops);
-
-#ifdef CONFIG_DIAG_BRIDGE_CODE
- debugfs_create_file("hsic", 0444, diag_dbgfs_dent, 0,
- &diag_dbgfs_hsic_ops);
-#endif
-
- diag_dbgfs_table_index = 0;
-}
-
-void diag_debugfs_cleanup(void)
-{
- if (diag_dbgfs_dent) {
- debugfs_remove_recursive(diag_dbgfs_dent);
- diag_dbgfs_dent = NULL;
- }
-}
-#else
-void diag_debugfs_init(void) { }
-void diag_debugfs_cleanup(void) { }
-#endif
diff --git a/drivers/char/diag/diagfwd_cntl.h b/drivers/char/diag/diagfwd_cntl.h
index e6f5352..8a0ec3f 100644
--- a/drivers/char/diag/diagfwd_cntl.h
+++ b/drivers/char/diag/diagfwd_cntl.h
@@ -88,7 +88,5 @@
void diag_clean_modem_reg_fn(struct work_struct *);
void diag_clean_lpass_reg_fn(struct work_struct *);
void diag_clean_wcnss_reg_fn(struct work_struct *);
-void diag_debugfs_init(void);
-void diag_debugfs_cleanup(void);
#endif
diff --git a/drivers/cpufreq/cpufreq_gov_msm.c b/drivers/cpufreq/cpufreq_gov_msm.c
index 9c49f80..11eb9f5 100644
--- a/drivers/cpufreq/cpufreq_gov_msm.c
+++ b/drivers/cpufreq/cpufreq_gov_msm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -66,13 +66,17 @@
if (freq > gov->max_freq)
freq = gov->max_freq;
- ret = __cpufreq_driver_target(gov->policy, freq, CPUFREQ_RELATION_L);
- gov->cur_freq = gov->policy->cur;
-
mutex_unlock(&per_cpu(gov_mutex, gov->cpu));
- if (!ret)
- return gov->cur_freq;
+ ret = cpufreq_driver_target(gov->policy, freq, CPUFREQ_RELATION_L);
+
+ if (!ret) {
+ gov->cur_freq = cpufreq_quick_get(gov->cpu);
+ if (freq != gov->cur_freq)
+ pr_err("cpu %d freq %u gov->cur_freq %u didn't match",
+ gov->cpu, freq, gov->cur_freq);
+ }
+ ret = gov->cur_freq;
return ret;
}
@@ -82,6 +86,11 @@
struct msm_gov *gov =
container_of(self, struct msm_gov, gov_notifier);
+ /*
+ * the rw_sem in cpufreq is always held when this is called.
+ * The policy->cur won't be updated in this case - so it is safe to
+ * access policy->cur
+ */
return gov->cur_freq;
}
@@ -113,9 +122,7 @@
break;
case CPUFREQ_GOV_STOP:
- mutex_lock(&per_cpu(gov_mutex, cpu));
msm_dcvs_freq_sink_unregister(dcvs_notifier);
- mutex_unlock(&per_cpu(gov_mutex, cpu));
break;
case CPUFREQ_GOV_LIMITS:
@@ -138,15 +145,17 @@
{
int ret = 0;
int cpu;
- uint32_t group_id = 0x43505530; /* CPU0 */
struct msm_dcvs_core_info *core = NULL;
+ int sensor = 0;
core = pdev->dev.platform_data;
for_each_possible_cpu(cpu) {
mutex_init(&per_cpu(gov_mutex, cpu));
snprintf(core_name[cpu], 10, "cpu%d", cpu);
- ret = msm_dcvs_register_core(core_name[cpu], group_id, core);
+ if (cpu < core->num_cores)
+ sensor = core->sensors[cpu];
+ ret = msm_dcvs_register_core(core_name[cpu], core, sensor);
if (ret)
pr_err("Unable to register core for %d\n", cpu);
}
diff --git a/drivers/gpu/msm/a3xx_reg.h b/drivers/gpu/msm/a3xx_reg.h
index 05c7967..6a010a9 100644
--- a/drivers/gpu/msm/a3xx_reg.h
+++ b/drivers/gpu/msm/a3xx_reg.h
@@ -65,13 +65,17 @@
#define A3XX_RBBM_INT_CLEAR_CMD 0x061
#define A3XX_RBBM_INT_0_MASK 0x063
#define A3XX_RBBM_INT_0_STATUS 0x064
+#define A3XX_RBBM_PERFCTR_CTL 0x80
#define A3XX_RBBM_GPU_BUSY_MASKED 0x88
+#define A3XX_RBBM_PERFCTR_SP_7_LO 0xE0
+#define A3XX_RBBM_PERFCTR_SP_7_HI 0xE1
#define A3XX_RBBM_RBBM_CTL 0x100
#define A3XX_RBBM_RBBM_CTL 0x100
#define A3XX_RBBM_PERFCTR_PWR_1_LO 0x0EC
#define A3XX_RBBM_PERFCTR_PWR_1_HI 0x0ED
#define A3XX_RBBM_DEBUG_BUS_CTL 0x111
#define A3XX_RBBM_DEBUG_BUS_DATA_STATUS 0x112
+
/* Following two are same as on A2XX, just in a different place */
#define A3XX_CP_PFP_UCODE_ADDR 0x1C9
#define A3XX_CP_PFP_UCODE_DATA 0x1CA
@@ -160,6 +164,7 @@
#define A3XX_VPC_VPC_DEBUG_RAM_READ 0xE62
#define A3XX_UCHE_CACHE_MODE_CONTROL_REG 0xE82
#define A3XX_UCHE_CACHE_INVALIDATE0_REG 0xEA0
+#define A3XX_SP_PERFCOUNTER7_SELECT 0xECB
#define A3XX_GRAS_CL_CLIP_CNTL 0x2040
#define A3XX_GRAS_CL_GB_CLIP_ADJ 0x2044
#define A3XX_GRAS_CL_VPORT_XOFFSET 0x2048
@@ -528,4 +533,7 @@
/* RBBM_CLOCK_CTL default value */
#define A3XX_RBBM_CLOCK_CTL_DEFAULT 0xBFFFFFFF
+/* COUNTABLE FOR SP PERFCOUNTER */
+#define SP_FS_FULL_ALU_INSTRUCTIONS 0x0E
+
#endif
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 13230ab..97711e2 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2002,2007-2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -127,6 +127,8 @@
REG_CP_IB1_BUFSZ,
REG_CP_IB2_BASE,
REG_CP_IB2_BUFSZ,
+ 0,
+ 0
};
const unsigned int hang_detect_regs_count = ARRAY_SIZE(hang_detect_regs);
@@ -847,15 +849,15 @@
for_each_child_of_node(node, child)
count++;
- info->core_param.num_freq = count;
+ info->power_param.num_freq = count;
- info->freq_tbl = kzalloc(info->core_param.num_freq *
+ info->freq_tbl = kzalloc(info->power_param.num_freq *
sizeof(struct msm_dcvs_freq_entry),
GFP_KERNEL);
if (info->freq_tbl == NULL) {
KGSL_CORE_ERR("kzalloc(%d) failed\n",
- info->core_param.num_freq *
+ info->power_param.num_freq *
sizeof(struct msm_dcvs_freq_entry));
ret = -ENOMEM;
goto err;
@@ -867,7 +869,7 @@
if (adreno_of_read_property(child, "reg", &index))
goto err;
- if (index >= info->core_param.num_freq) {
+ if (index >= info->power_param.num_freq) {
KGSL_CORE_ERR("DCVS freq entry %d is out of range\n",
index);
continue;
@@ -877,43 +879,109 @@
&info->freq_tbl[index].freq))
goto err;
- if (adreno_of_read_property(child, "qcom,idle-energy",
- &info->freq_tbl[index].idle_energy))
- info->freq_tbl[index].idle_energy = 0;
+ if (adreno_of_read_property(child, "qcom,voltage",
+ &info->freq_tbl[index].voltage))
+ info->freq_tbl[index].voltage = 0;
- if (adreno_of_read_property(child, "qcom,active-energy",
- &info->freq_tbl[index].active_energy))
- info->freq_tbl[index].active_energy = 0;
+ if (adreno_of_read_property(child, "qcom,is_trans_level",
+ &info->freq_tbl[index].is_trans_level))
+ info->freq_tbl[index].is_trans_level = 0;
+
+ if (adreno_of_read_property(child, "qcom,active-energy-offset",
+ &info->freq_tbl[index].active_energy_offset))
+ info->freq_tbl[index].active_energy_offset = 0;
+
+ if (adreno_of_read_property(child, "qcom,leakage-energy-offset",
+ &info->freq_tbl[index].leakage_energy_offset))
+ info->freq_tbl[index].leakage_energy_offset = 0;
}
- if (adreno_of_read_property(node, "qcom,core-max-time-us",
- &info->core_param.max_time_us))
+ if (adreno_of_read_property(node, "qcom,num-cores", &info->num_cores))
goto err;
- if (adreno_of_read_property(node, "qcom,algo-slack-time-us",
- &info->algo_param.slack_time_us))
+ info->sensors = kzalloc(info->num_cores *
+ sizeof(int),
+ GFP_KERNEL);
+
+ for (count = 0; count < info->num_cores; count++) {
+ if (adreno_of_read_property(node, "qcom,sensors",
+ &(info->sensors[count])))
+ goto err;
+ }
+
+ if (adreno_of_read_property(node, "qcom,core-core-type",
+ &info->core_param.core_type))
goto err;
if (adreno_of_read_property(node, "qcom,algo-disable-pc-threshold",
&info->algo_param.disable_pc_threshold))
goto err;
-
- if (adreno_of_read_property(node, "qcom,algo-ss-window-size",
- &info->algo_param.ss_window_size))
+ if (adreno_of_read_property(node, "qcom,algo-em-win-size-min-us",
+ &info->algo_param.em_win_size_min_us))
goto err;
-
- if (adreno_of_read_property(node, "qcom,algo-ss-util-pct",
- &info->algo_param.ss_util_pct))
+ if (adreno_of_read_property(node, "qcom,algo-em-win-size-max-us",
+ &info->algo_param.em_win_size_max_us))
goto err;
-
if (adreno_of_read_property(node, "qcom,algo-em-max-util-pct",
&info->algo_param.em_max_util_pct))
goto err;
-
+ if (adreno_of_read_property(node, "qcom,algo-group-id",
+ &info->algo_param.group_id))
+ goto err;
+ if (adreno_of_read_property(node, "qcom,algo-max-freq-chg-time-us",
+ &info->algo_param.max_freq_chg_time_us))
+ goto err;
+ if (adreno_of_read_property(node, "qcom,algo-slack-mode-dynamic",
+ &info->algo_param.slack_mode_dynamic))
+ goto err;
+ if (adreno_of_read_property(node, "qcom,algo-slack-weight-thresh-pct",
+ &info->algo_param.slack_weight_thresh_pct))
+ goto err;
+ if (adreno_of_read_property(node, "qcom,algo-slack-time-min-us",
+ &info->algo_param.slack_time_min_us))
+ goto err;
+ if (adreno_of_read_property(node, "qcom,algo-slack-time-max-us",
+ &info->algo_param.slack_time_max_us))
+ goto err;
+ if (adreno_of_read_property(node, "qcom,algo-ss-win-size-min-us",
+ &info->algo_param.ss_win_size_min_us))
+ goto err;
+ if (adreno_of_read_property(node, "qcom,algo-ss-win-size-max-us",
+ &info->algo_param.ss_win_size_max_us))
+ goto err;
+ if (adreno_of_read_property(node, "qcom,algo-ss-util-pct",
+ &info->algo_param.ss_util_pct))
+ goto err;
if (adreno_of_read_property(node, "qcom,algo-ss-iobusy-conv",
&info->algo_param.ss_iobusy_conv))
goto err;
+ if (adreno_of_read_property(node, "qcom,energy-active-coeff-a",
+ &info->energy_coeffs.active_coeff_a))
+ goto err;
+ if (adreno_of_read_property(node, "qcom,energy-active-coeff-b",
+ &info->energy_coeffs.active_coeff_b))
+ goto err;
+ if (adreno_of_read_property(node, "qcom,energy-active-coeff-c",
+ &info->energy_coeffs.active_coeff_c))
+ goto err;
+ if (adreno_of_read_property(node, "qcom,energy-leakage-coeff-a",
+ &info->energy_coeffs.leakage_coeff_a))
+ goto err;
+ if (adreno_of_read_property(node, "qcom,energy-leakage-coeff-b",
+ &info->energy_coeffs.leakage_coeff_b))
+ goto err;
+ if (adreno_of_read_property(node, "qcom,energy-leakage-coeff-c",
+ &info->energy_coeffs.leakage_coeff_c))
+ goto err;
+ if (adreno_of_read_property(node, "qcom,energy-leakage-coeff-d",
+ &info->energy_coeffs.leakage_coeff_d))
+ goto err;
+
+ if (adreno_of_read_property(node, "qcom,power-current-temp",
+ &info->power_param.current_temp))
+ goto err;
+
return info;
err:
@@ -1236,6 +1304,12 @@
*/
hang_detect_regs[0] = adreno_dev->gpudev->reg_rbbm_status;
+ /* Add A3XX specific registers for hang detection */
+ if (adreno_is_a3xx(adreno_dev)) {
+ hang_detect_regs[6] = A3XX_RBBM_PERFCTR_SP_7_LO;
+ hang_detect_regs[7] = A3XX_RBBM_PERFCTR_SP_7_HI;
+ }
+
status = kgsl_mmu_start(device);
if (status)
goto error_clk_off;
@@ -2158,7 +2232,14 @@
if (!adreno_dev->fast_hang_detect)
return 0;
+ if (device->ftbl->isidle(device))
+ return 0;
+
for (i = 0; i < hang_detect_regs_count; i++) {
+
+ if (hang_detect_regs[i] == 0)
+ continue;
+
adreno_regread(device, hang_detect_regs[i],
&curr_reg_val[i]);
if (curr_reg_val[i] != prev_reg_val[i]) {
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index 2388fff..8de2c70 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -1749,9 +1749,6 @@
if (status & (CP_INT_CNTL__IB1_INT_MASK | CP_INT_CNTL__RB_INT_MASK)) {
queue_work(device->work_queue, &device->ts_expired_ws);
wake_up_interruptible_all(&device->wait_queue);
- atomic_notifier_call_chain(&(device->ts_notifier_list),
- device->id,
- NULL);
}
}
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 7bf928f..104baf8 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -2587,9 +2587,6 @@
/* Schedule work to free mem and issue ibs */
queue_work(device->work_queue, &device->ts_expired_ws);
-
- atomic_notifier_call_chain(&device->ts_notifier_list,
- device->id, NULL);
}
#define A3XX_IRQ_CALLBACK(_c) { .func = _c }
@@ -2836,6 +2833,17 @@
adreno_regwrite(device, A3XX_RB_GMEM_BASE_ADDR,
(unsigned int)(adreno_dev->ocmem_base >> 14));
}
+
+ /* Turn on performance counters */
+ adreno_regwrite(device, A3XX_RBBM_PERFCTR_CTL, 0x01);
+
+ /*
+ * Set SP perfcounter 7 to count SP_FS_FULL_ALU_INSTRUCTIONS
+ * we will use this to augment our hang detection
+ */
+
+ adreno_regwrite(device, A3XX_SP_PERFCOUNTER7_SELECT,
+ SP_FS_FULL_ALU_INSTRUCTIONS);
}
/* Defined in adreno_a3xx_snapshot.c */
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 1ff219b..0dd140b 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -503,7 +503,7 @@
* support, we must use the global timestamp since issueibcmds
* will be returning that one.
*/
- if (context->flags & CTXT_FLAGS_PER_CONTEXT_TS)
+ if (context && context->flags & CTXT_FLAGS_PER_CONTEXT_TS)
context_id = context->id;
/* reserve space to temporarily turn off protected mode
@@ -518,7 +518,7 @@
total_sizedwords += 7;
total_sizedwords += 2; /* scratchpad ts for recovery */
- if (context->flags & CTXT_FLAGS_PER_CONTEXT_TS) {
+ if (context && context->flags & CTXT_FLAGS_PER_CONTEXT_TS) {
total_sizedwords += 3; /* sop timestamp */
total_sizedwords += 4; /* eop timestamp */
total_sizedwords += 3; /* global timestamp without cache
@@ -591,7 +591,7 @@
GSL_RB_WRITE(ringcmds, rcmd_gpu, 0x00);
}
- if (context->flags & CTXT_FLAGS_PER_CONTEXT_TS) {
+ if (context && context->flags & CTXT_FLAGS_PER_CONTEXT_TS) {
/* start-of-pipeline timestamp */
GSL_RB_WRITE(ringcmds, rcmd_gpu,
cp_type3_packet(CP_MEM_WRITE, 2));
@@ -902,6 +902,7 @@
unsigned int i;
struct adreno_context *drawctxt;
unsigned int start_index = 0;
+ int ret;
if (device->state & KGSL_STATE_HUNG)
return -EBUSY;
@@ -948,9 +949,15 @@
if (unlikely(adreno_dev->ib_check_level >= 1 &&
!_parse_ibs(dev_priv, ibdesc[i].gpuaddr,
ibdesc[i].sizedwords))) {
- kfree(link);
- return -EINVAL;
+ ret = -EINVAL;
+ goto done;
}
+
+ if (ibdesc[i].sizedwords == 0) {
+ ret = -EINVAL;
+ goto done;
+ }
+
*cmds++ = CP_HDR_INDIRECT_BUFFER_PFD;
*cmds++ = ibdesc[i].gpuaddr;
*cmds++ = ibdesc[i].sizedwords;
@@ -972,7 +979,6 @@
KGSL_CMD_INFO(device, "<%d:0x%x> g %08x numibs %d\n",
context->id, *timestamp, (unsigned int)ibdesc, numibs);
- kfree(link);
#ifdef CONFIG_MSM_KGSL_CFF_DUMP
/*
@@ -982,13 +988,16 @@
*/
adreno_idle(device);
#endif
+
/* If context hung and recovered then return error so that the
* application may handle it */
- if (drawctxt->flags & CTXT_FLAGS_GPU_HANG_RECOVERED)
- return -EDEADLK;
- else
- return 0;
+ ret = (drawctxt->flags & CTXT_FLAGS_GPU_HANG_RECOVERED) ?
+ -EDEADLK : 0;
+
+done:
+ kfree(link);
+ return ret;
}
static int _find_start_of_cmd_seq(struct adreno_ringbuffer *rb,
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index ccc6119..5ba844a 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -507,24 +507,6 @@
return ret;
}
-int kgsl_register_ts_notifier(struct kgsl_device *device,
- struct notifier_block *nb)
-{
- BUG_ON(device == NULL);
- return atomic_notifier_chain_register(&device->ts_notifier_list,
- nb);
-}
-EXPORT_SYMBOL(kgsl_register_ts_notifier);
-
-int kgsl_unregister_ts_notifier(struct kgsl_device *device,
- struct notifier_block *nb)
-{
- BUG_ON(device == NULL);
- return atomic_notifier_chain_unregister(&device->ts_notifier_list,
- nb);
-}
-EXPORT_SYMBOL(kgsl_unregister_ts_notifier);
-
int kgsl_check_timestamp(struct kgsl_device *device,
struct kgsl_context *context, unsigned int timestamp)
{
@@ -1770,6 +1752,8 @@
if (result)
goto error;
+ entry->memdesc.priv |= param->flags & KGSL_MEMTYPE_MASK;
+
result = kgsl_mmu_map(private->pagetable,
&entry->memdesc,
GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 2ca3a4f..dc597f5 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -155,7 +155,6 @@
struct kgsl_pwrctrl pwrctrl;
int open_count;
- struct atomic_notifier_head ts_notifier_list;
struct mutex mutex;
uint32_t state;
uint32_t requested_state;
@@ -210,7 +209,6 @@
.hwaccess_gate = COMPLETION_INITIALIZER((_dev).hwaccess_gate),\
.suspend_gate = COMPLETION_INITIALIZER((_dev).suspend_gate),\
.recovery_gate = COMPLETION_INITIALIZER((_dev).recovery_gate),\
- .ts_notifier_list = ATOMIC_NOTIFIER_INIT((_dev).ts_notifier_list),\
.idle_check_ws = __WORK_INITIALIZER((_dev).idle_check_ws,\
kgsl_idle_check),\
.ts_expired_ws = __WORK_INITIALIZER((_dev).ts_expired_ws,\
@@ -374,12 +372,6 @@
int kgsl_check_timestamp(struct kgsl_device *device,
struct kgsl_context *context, unsigned int timestamp);
-int kgsl_register_ts_notifier(struct kgsl_device *device,
- struct notifier_block *nb);
-
-int kgsl_unregister_ts_notifier(struct kgsl_device *device,
- struct notifier_block *nb);
-
int kgsl_device_platform_probe(struct kgsl_device *device);
void kgsl_device_platform_remove(struct kgsl_device *device);
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 0e1e100..54ba5ad 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -729,7 +729,8 @@
return 0;
gpuaddr = memdesc->gpuaddr;
- memdesc->priv |= KGSL_MEMFLAGS_GLOBAL;
+ memdesc->priv |= KGSL_MEMFLAGS_GLOBAL
+ | (KGSL_MEMTYPE_KERNEL << KGSL_MEMTYPE_SHIFT);
result = kgsl_mmu_map(pagetable, memdesc, protflags);
if (result)
diff --git a/drivers/gpu/msm/kgsl_pwrscale_msm.c b/drivers/gpu/msm/kgsl_pwrscale_msm.c
index 879b381..5b66e70 100644
--- a/drivers/gpu/msm/kgsl_pwrscale_msm.c
+++ b/drivers/gpu/msm/kgsl_pwrscale_msm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -170,9 +170,9 @@
/* Fill in frequency table from low to high, reversing order. */
low_level = pwr->num_pwrlevels - KGSL_PWRLEVEL_LAST_OFFSET;
for (i = 0; i <= low_level; i++)
- tbl[i].freq =
- pwr->pwrlevels[low_level - i].gpu_freq / 1000;
- ret = msm_dcvs_register_core(device->name, 0, priv->core_info);
+ tbl[i].freq = pwr->pwrlevels[low_level - i].gpu_freq / 1000;
+ ret = msm_dcvs_register_core(device->name, priv->core_info,
+ priv->core_info->sensors[0]);
if (ret) {
KGSL_PWR_ERR(device, "msm_dcvs_register_core failed");
goto err;
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index c2ce5c7..bdc5686 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.c
@@ -540,7 +540,6 @@
memdesc->size = size;
memdesc->pagetable = pagetable;
- memdesc->priv = KGSL_MEMFLAGS_CACHED;
memdesc->ops = &kgsl_page_alloc_ops;
memdesc->sg = kgsl_sg_alloc(sglen);
diff --git a/drivers/gpu/msm/kgsl_sharedmem.h b/drivers/gpu/msm/kgsl_sharedmem.h
index de89ac1..5a6c4c2 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.h
+++ b/drivers/gpu/msm/kgsl_sharedmem.h
@@ -27,8 +27,6 @@
#define KGSL_CACHE_OP_FLUSH 0x02
#define KGSL_CACHE_OP_CLEAN 0x03
-/** Set if the memdesc describes cached memory */
-#define KGSL_MEMFLAGS_CACHED 0x00000001
/** Set if the memdesc is mapped into all pagetables */
#define KGSL_MEMFLAGS_GLOBAL 0x00000002
@@ -136,6 +134,7 @@
{
if (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_NONE)
return kgsl_sharedmem_ebimem(memdesc, pagetable, size);
+ memdesc->priv |= (KGSL_MEMTYPE_KERNEL << KGSL_MEMTYPE_SHIFT);
return kgsl_sharedmem_page_alloc(memdesc, pagetable, size);
}
@@ -144,10 +143,17 @@
struct kgsl_pagetable *pagetable,
size_t size, unsigned int flags)
{
+ int ret;
+ unsigned int mask = (KGSL_MEMTYPE_MASK | KGSL_MEMFLAGS_GPUREADONLY);
if (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_NONE)
- return kgsl_sharedmem_ebimem_user(memdesc, pagetable, size,
+ ret = kgsl_sharedmem_ebimem_user(memdesc, pagetable, size,
flags);
- return kgsl_sharedmem_page_alloc_user(memdesc, pagetable, size, flags);
+ else
+ ret = kgsl_sharedmem_page_alloc_user(memdesc, pagetable, size,
+ flags);
+ if (ret == 0)
+ memdesc->priv |= flags & mask;
+ return ret;
}
static inline int
diff --git a/drivers/gpu/msm/kgsl_trace.h b/drivers/gpu/msm/kgsl_trace.h
index 81ab3fb..bba06bc 100644
--- a/drivers/gpu/msm/kgsl_trace.h
+++ b/drivers/gpu/msm/kgsl_trace.h
@@ -315,16 +315,18 @@
TP_STRUCT__entry(
__field(unsigned int, gpuaddr)
__field(unsigned int, size)
+ __field(unsigned int, tgid)
),
TP_fast_assign(
__entry->gpuaddr = mem_entry->memdesc.gpuaddr;
__entry->size = mem_entry->memdesc.size;
+ __entry->tgid = mem_entry->priv->pid;
),
TP_printk(
- "gpuaddr=0x%08x size=%d",
- __entry->gpuaddr, __entry->size
+ "gpuaddr=0x%08x size=%d tgid=%d",
+ __entry->gpuaddr, __entry->size, __entry->tgid
)
);
@@ -339,6 +341,7 @@
__field(unsigned int, size)
__field(int, fd)
__field(int, type)
+ __field(unsigned int, tgid)
),
TP_fast_assign(
@@ -346,12 +349,13 @@
__entry->size = mem_entry->memdesc.size;
__entry->fd = fd;
__entry->type = mem_entry->memtype;
+ __entry->tgid = mem_entry->priv->pid;
),
TP_printk(
- "gpuaddr=0x%08x size=%d type=%d fd=%d",
+ "gpuaddr=0x%08x size=%d type=%d fd=%d tgid=%d",
__entry->gpuaddr, __entry->size,
- __entry->type, __entry->fd
+ __entry->type, __entry->fd, __entry->tgid
)
);
@@ -366,17 +370,20 @@
__field(unsigned int, size)
__field(int, type)
__field(int, fd)
+ __field(unsigned int, tgid)
),
TP_fast_assign(
__entry->gpuaddr = mem_entry->memdesc.gpuaddr;
__entry->size = mem_entry->memdesc.size;
__entry->type = mem_entry->memtype;
+ __entry->tgid = mem_entry->priv->pid;
),
TP_printk(
- "gpuaddr=0x%08x size=%d type=%d",
- __entry->gpuaddr, __entry->size, __entry->type
+ "gpuaddr=0x%08x size=%d type=%d tgid=%d",
+ __entry->gpuaddr, __entry->size, __entry->type,
+ __entry->tgid
)
);
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index 8ddc991..712bc60 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -212,10 +212,6 @@
queue_work(device->work_queue, &device->ts_expired_ws);
wake_up_interruptible(&device->wait_queue);
-
- atomic_notifier_call_chain(
- &(device->ts_notifier_list),
- device->id, NULL);
}
}
diff --git a/drivers/input/misc/pmic8xxx-pwrkey.c b/drivers/input/misc/pmic8xxx-pwrkey.c
index 9f64cec..abd66f4 100644
--- a/drivers/input/misc/pmic8xxx-pwrkey.c
+++ b/drivers/input/misc/pmic8xxx-pwrkey.c
@@ -104,14 +104,75 @@
static SIMPLE_DEV_PM_OPS(pm8xxx_pwr_key_pm_ops,
pmic8xxx_pwrkey_suspend, pmic8xxx_pwrkey_resume);
+static int pmic8xxx_set_pon1(struct device *dev, u32 debounce_us, bool pull_up)
+{
+ int err;
+ u32 delay;
+ u8 pon_cntl;
+
+ /* Valid range of pwr key trigger delay is 1/64 sec to 2 seconds. */
+ if (debounce_us > USEC_PER_SEC * 2 ||
+ debounce_us < USEC_PER_SEC / 64) {
+ dev_err(dev, "invalid power key trigger delay\n");
+ return -EINVAL;
+ }
+
+ delay = (debounce_us << 6) / USEC_PER_SEC;
+ delay = ilog2(delay);
+
+ err = pm8xxx_readb(dev->parent, PON_CNTL_1, &pon_cntl);
+ if (err < 0) {
+ dev_err(dev, "failed reading PON_CNTL_1 err=%d\n", err);
+ return err;
+ }
+
+ pon_cntl &= ~PON_CNTL_TRIG_DELAY_MASK;
+ pon_cntl |= (delay & PON_CNTL_TRIG_DELAY_MASK);
+
+ if (pull_up)
+ pon_cntl |= PON_CNTL_PULL_UP;
+ else
+ pon_cntl &= ~PON_CNTL_PULL_UP;
+
+ err = pm8xxx_writeb(dev->parent, PON_CNTL_1, pon_cntl);
+ if (err < 0) {
+ dev_err(dev, "failed writing PON_CNTL_1 err=%d\n", err);
+ return err;
+ }
+
+ return 0;
+}
+
+static ssize_t pmic8xxx_debounce_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct pmic8xxx_pwrkey *pwrkey = dev_get_drvdata(dev);
+ int err;
+ unsigned long val;
+
+ if (size > 8)
+ return -EINVAL;
+
+ err = kstrtoul(buf, 10, &val);
+ if (err < 0)
+ return err;
+
+ err = pmic8xxx_set_pon1(dev, val, pwrkey->pdata->pull_up);
+ if (err < 0)
+ return err;
+
+ return size;
+}
+
+static DEVICE_ATTR(debounce_us, 0664, NULL, pmic8xxx_debounce_store);
+
static int __devinit pmic8xxx_pwrkey_probe(struct platform_device *pdev)
{
struct input_dev *pwr;
int key_release_irq = platform_get_irq(pdev, 0);
int key_press_irq = platform_get_irq(pdev, 1);
int err;
- unsigned int delay;
- u8 pon_cntl;
struct pmic8xxx_pwrkey *pwrkey;
const struct pm8xxx_pwrkey_platform_data *pdata =
dev_get_platdata(&pdev->dev);
@@ -121,13 +182,6 @@
return -EINVAL;
}
- /* Valid range of pwr key trigger delay is 1/64 sec to 2 seconds. */
- if (pdata->kpd_trigger_delay_us > USEC_PER_SEC * 2 ||
- pdata->kpd_trigger_delay_us < USEC_PER_SEC / 64) {
- dev_err(&pdev->dev, "invalid power key trigger delay\n");
- return -EINVAL;
- }
-
pwrkey = kzalloc(sizeof(*pwrkey), GFP_KERNEL);
if (!pwrkey)
return -ENOMEM;
@@ -147,25 +201,10 @@
pwr->phys = "pmic8xxx_pwrkey/input0";
pwr->dev.parent = &pdev->dev;
- delay = (pdata->kpd_trigger_delay_us << 6) / USEC_PER_SEC;
- delay = ilog2(delay);
-
- err = pm8xxx_readb(pdev->dev.parent, PON_CNTL_1, &pon_cntl);
- if (err < 0) {
- dev_err(&pdev->dev, "failed reading PON_CNTL_1 err=%d\n", err);
- goto free_input_dev;
- }
-
- pon_cntl &= ~PON_CNTL_TRIG_DELAY_MASK;
- pon_cntl |= (delay & PON_CNTL_TRIG_DELAY_MASK);
- if (pdata->pull_up)
- pon_cntl |= PON_CNTL_PULL_UP;
- else
- pon_cntl &= ~PON_CNTL_PULL_UP;
-
- err = pm8xxx_writeb(pdev->dev.parent, PON_CNTL_1, pon_cntl);
- if (err < 0) {
- dev_err(&pdev->dev, "failed writing PON_CNTL_1 err=%d\n", err);
+ err = pmic8xxx_set_pon1(&pdev->dev,
+ pdata->kpd_trigger_delay_us, pdata->pull_up);
+ if (err) {
+ dev_dbg(&pdev->dev, "Can't set PON CTRL1 register: %d\n", err);
goto free_input_dev;
}
@@ -178,10 +217,22 @@
pwrkey->key_press_irq = key_press_irq;
pwrkey->key_release_irq = key_release_irq;
pwrkey->pwr = pwr;
- pwrkey->press = false;
platform_set_drvdata(pdev, pwrkey);
+ /* check power key status during boot */
+ err = pm8xxx_read_irq_stat(pdev->dev.parent, key_press_irq);
+ if (err < 0) {
+ dev_err(&pdev->dev, "reading irq status failed\n");
+ goto unreg_input_dev;
+ }
+ pwrkey->press = !!err;
+
+ if (pwrkey->press) {
+ input_report_key(pwrkey->pwr, KEY_POWER, 1);
+ input_sync(pwrkey->pwr);
+ }
+
err = request_any_context_irq(key_press_irq, pwrkey_press_irq,
IRQF_TRIGGER_RISING, "pmic8xxx_pwrkey_press", pwrkey);
if (err < 0) {
@@ -199,12 +250,22 @@
goto free_press_irq;
}
+ err = device_create_file(&pdev->dev, &dev_attr_debounce_us);
+ if (err < 0) {
+ dev_err(&pdev->dev,
+ "dev file creation for debounce failed: %d\n",
+ err);
+ goto free_rel_irq;
+ }
+
device_init_wakeup(&pdev->dev, pdata->wakeup);
return 0;
+free_rel_irq:
+ free_irq(key_release_irq, pwrkey);
free_press_irq:
- free_irq(key_press_irq, NULL);
+ free_irq(key_press_irq, pwrkey);
unreg_input_dev:
platform_set_drvdata(pdev, NULL);
input_unregister_device(pwr);
@@ -224,6 +285,7 @@
device_init_wakeup(&pdev->dev, 0);
+ device_remove_file(&pdev->dev, &dev_attr_debounce_us);
free_irq(key_press_irq, pwrkey);
free_irq(key_release_irq, pwrkey);
input_unregister_device(pwrkey->pwr);
diff --git a/drivers/iommu/msm_iommu-v2.c b/drivers/iommu/msm_iommu-v2.c
index c7f6b82..f49d009 100644
--- a/drivers/iommu/msm_iommu-v2.c
+++ b/drivers/iommu/msm_iommu-v2.c
@@ -169,8 +169,10 @@
mb();
}
-static void __program_iommu(void __iomem *base, int smt_size)
+static void __program_iommu(void __iomem *base, int smt_size,
+ struct msm_iommu_bfb_settings *bfb_settings)
{
+ int i;
__reset_iommu(base, smt_size);
SET_CR0_SMCFCFG(base, 1);
@@ -181,6 +183,12 @@
SET_CR0_GFIE(base, 1);
SET_CR0_GFRE(base, 1);
SET_CR0_CLIENTPD(base, 0);
+
+ if (bfb_settings)
+ for (i = 0; i < bfb_settings->length; i++)
+ SET_GLOBAL_REG(base, bfb_settings->regs[i],
+ bfb_settings->data[i]);
+
mb(); /* Make sure writes complete before returning */
}
@@ -200,6 +208,17 @@
mb();
}
+static void __release_smg(void __iomem *base, int ctx, int smt_size)
+{
+ int i;
+
+ /* Invalidate any SMGs associated with this context */
+ for (i = 0; i < smt_size; i++)
+ if (GET_SMR_VALID(base, i) &&
+ GET_S2CR_CBNDX(base, i) == ctx)
+ SET_SMR_VALID(base, i, 0);
+}
+
static void __program_context(void __iomem *base, int ctx, int ncb,
phys_addr_t pgtable, int redirect,
u32 *sids, int len, int smt_size)
@@ -416,7 +435,8 @@
}
if (!msm_iommu_ctx_attached(dev->parent))
- __program_iommu(iommu_drvdata->base, iommu_drvdata->nsmr);
+ __program_iommu(iommu_drvdata->base, iommu_drvdata->nsmr,
+ iommu_drvdata->bfb_settings);
__program_context(iommu_drvdata->base, ctx_drvdata->num,
iommu_drvdata->ncb, __pa(priv->pt.fl_table),
@@ -458,6 +478,9 @@
GET_CB_CONTEXTIDR_ASID(iommu_drvdata->base, ctx_drvdata->num));
__reset_context(iommu_drvdata->base, ctx_drvdata->num);
+ __release_smg(iommu_drvdata->base, ctx_drvdata->num,
+ iommu_drvdata->nsmr);
+
__disable_clocks(iommu_drvdata);
regulator_disable(iommu_drvdata->gdsc);
diff --git a/drivers/iommu/msm_iommu_dev-v2.c b/drivers/iommu/msm_iommu_dev-v2.c
index 8c26f95..237d601 100644
--- a/drivers/iommu/msm_iommu_dev-v2.c
+++ b/drivers/iommu/msm_iommu_dev-v2.c
@@ -29,6 +29,66 @@
#include <mach/iommu_hw-v2.h>
#include <mach/iommu.h>
+static int msm_iommu_parse_bfb_settings(struct platform_device *pdev,
+ struct msm_iommu_drvdata *drvdata)
+{
+ struct msm_iommu_bfb_settings *bfb_settings;
+ u32 nreg, nval;
+ int ret, i;
+
+ /*
+ * It is not valid for a device to have the qcom,iommu-bfb-regs
+ * property but not the qcom,iommu-bfb-data property, and vice versa.
+ */
+ if (!of_get_property(pdev->dev.of_node, "qcom,iommu-bfb-regs", &nreg)) {
+ if (of_get_property(pdev->dev.of_node, "qcom,iommu-bfb-data",
+ &nval))
+ return -EINVAL;
+ return 0;
+ }
+
+ if (!of_get_property(pdev->dev.of_node, "qcom,iommu-bfb-data", &nval))
+ return -EINVAL;
+
+ if (nreg >= sizeof(bfb_settings->regs))
+ return -EINVAL;
+
+ if (nval >= sizeof(bfb_settings->data))
+ return -EINVAL;
+
+ if (nval != nreg)
+ return -EINVAL;
+
+ bfb_settings = devm_kzalloc(&pdev->dev, sizeof(*bfb_settings),
+ GFP_KERNEL);
+ if (!bfb_settings)
+ return -ENOMEM;
+
+ ret = of_property_read_u32_array(pdev->dev.of_node,
+ "qcom,iommu-bfb-regs",
+ bfb_settings->regs,
+ nreg / sizeof(*bfb_settings->regs));
+ if (ret)
+ return ret;
+
+ ret = of_property_read_u32_array(pdev->dev.of_node,
+ "qcom,iommu-bfb-data",
+ bfb_settings->data,
+ nval / sizeof(*bfb_settings->data));
+ if (ret)
+ return ret;
+
+ bfb_settings->length = nreg / sizeof(*bfb_settings->regs);
+
+ for (i = 0; i < bfb_settings->length; i++)
+ if (bfb_settings->regs[i] < IMPLDEF_OFFSET ||
+ bfb_settings->regs[i] >= IMPLDEF_OFFSET + IMPLDEF_LENGTH)
+ return -EINVAL;
+
+ drvdata->bfb_settings = bfb_settings;
+ return 0;
+}
+
static int msm_iommu_parse_dt(struct platform_device *pdev,
struct msm_iommu_drvdata *drvdata)
{
@@ -40,6 +100,10 @@
if (ret)
goto fail;
+ ret = msm_iommu_parse_bfb_settings(pdev, drvdata);
+ if (ret)
+ goto fail;
+
ret = of_property_read_u32(pdev->dev.of_node, "qcom,iommu-smt-size",
&nsmr);
if (ret)
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index 2d9296c..17303dd 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -210,11 +210,13 @@
int dirty;
int node_type;
struct timeval timestamp;
+ uint32_t frame_id;
};
struct msm_cam_timestamp {
uint8_t present;
struct timeval timestamp;
+ uint32_t frame_id;
};
struct msm_cam_buf_map_info {
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index 2c95ef5..77922e2 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -711,8 +711,12 @@
int rc = -EINVAL;
void __user *argp = (void __user *)arg;
- struct v4l2_subdev *sd = pmctl->vfe_sdev;
-
+ struct v4l2_subdev *sd;
+ if (!pmctl->vfe_sdev) {
+ pr_err("%s vfe subdev is NULL\n", __func__);
+ return -ENXIO;
+ }
+ sd = pmctl->vfe_sdev;
D("%s: cmd %d\n", __func__, _IOC_NR(cmd));
switch (cmd) {
case MSM_CAM_IOCTL_CONFIG_VFE:
diff --git a/drivers/media/video/msm/msm_mctl_buf.c b/drivers/media/video/msm/msm_mctl_buf.c
index a3c7243..2919d23 100644
--- a/drivers/media/video/msm/msm_mctl_buf.c
+++ b/drivers/media/video/msm/msm_mctl_buf.c
@@ -434,7 +434,11 @@
D("%s Copying timestamp as %ld.%ld", __func__,
cam_ts->timestamp.tv_sec, cam_ts->timestamp.tv_usec);
buf->vidbuf.v4l2_buf.timestamp = cam_ts->timestamp;
+ buf->vidbuf.v4l2_buf.sequence = cam_ts->frame_id;
}
+ D("%s Notify user about buffer %d image_mode %d frame_id %d", __func__,
+ buf->vidbuf.v4l2_buf.index, pcam_inst->image_mode,
+ buf->vidbuf.v4l2_buf.sequence);
vb2_buffer_done(&buf->vidbuf, VB2_BUF_STATE_DONE);
return 0;
}
@@ -821,6 +825,7 @@
__func__, pcam_inst, frame->ch_paddr[0], ret_frame->dirty);
cam_ts.present = 1;
cam_ts.timestamp = ret_frame->timestamp;
+ cam_ts.frame_id = ret_frame->frame_id;
if (ret_frame->dirty)
/* the frame is dirty, not going to disptach to app */
rc = msm_mctl_release_free_buf(pmctl, pcam_inst, frame);
diff --git a/drivers/media/video/msm/msm_mctl_pp.c b/drivers/media/video/msm/msm_mctl_pp.c
index a114b37..105426e 100644
--- a/drivers/media/video/msm/msm_mctl_pp.c
+++ b/drivers/media/video/msm/msm_mctl_pp.c
@@ -636,6 +636,9 @@
ret_frame.dirty = dirty;
ret_frame.node_type = 0;
ret_frame.timestamp = frame.timestamp;
+ ret_frame.frame_id = frame.frame_id;
+ D("%s frame_id: %d buffer idx %d\n", __func__,
+ frame.frame_id, frame.buf_idx);
rc = msm_mctl_buf_done_pp(p_mctl, &buf_handle, &buf, &ret_frame);
return rc;
}
diff --git a/drivers/media/video/msm/vfe/msm_vfe32.c b/drivers/media/video/msm/vfe/msm_vfe32.c
index 6e22388..db0db36 100644
--- a/drivers/media/video/msm/vfe/msm_vfe32.c
+++ b/drivers/media/video/msm/vfe/msm_vfe32.c
@@ -587,6 +587,25 @@
atomic_set(&share_ctrl->handle_common_irq, 1);
}
+static void axi_clear_all_interrupts(struct vfe_share_ctrl_t *share_ctrl)
+{
+ atomic_set(&share_ctrl->handle_common_irq, 0);
+ msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
+ share_ctrl->vfebase + VFE_IRQ_MASK_0);
+ msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
+ share_ctrl->vfebase + VFE_IRQ_MASK_1);
+
+ /* clear all pending interrupts*/
+ msm_camera_io_w(VFE_CLEAR_ALL_IRQS,
+ share_ctrl->vfebase + VFE_IRQ_CLEAR_0);
+ msm_camera_io_w(VFE_CLEAR_ALL_IRQS,
+ share_ctrl->vfebase + VFE_IRQ_CLEAR_1);
+ /* Ensure the write order while writing
+ *to the command register using the barrier */
+ msm_camera_io_w_mb(1,
+ share_ctrl->vfebase + VFE_IRQ_CMD);
+}
+
static void axi_disable_irq(struct vfe_share_ctrl_t *share_ctrl,
uint32_t mode)
{
@@ -632,24 +651,6 @@
msm_camera_io_w(irq_mask, share_ctrl->vfebase +
VFE_IRQ_MASK_0);
}
- /*Dont Disable for concurrent*/
- if (share_ctrl->axi_ref_cnt == 1) {
- atomic_set(&share_ctrl->handle_common_irq, 0);
- msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
- share_ctrl->vfebase + VFE_IRQ_MASK_0);
- msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
- share_ctrl->vfebase + VFE_IRQ_MASK_1);
-
- /* clear all pending interrupts*/
- msm_camera_io_w(VFE_CLEAR_ALL_IRQS,
- share_ctrl->vfebase + VFE_IRQ_CLEAR_0);
- msm_camera_io_w(VFE_CLEAR_ALL_IRQS,
- share_ctrl->vfebase + VFE_IRQ_CLEAR_1);
- /* Ensure the write order while writing
- *to the command register using the barrier */
- msm_camera_io_w_mb(1,
- share_ctrl->vfebase + VFE_IRQ_CMD);
- }
}
static void vfe32_stop(struct vfe32_ctrl_type *vfe32_ctrl)
@@ -5554,6 +5555,8 @@
axi_ctrl->share_ctrl->axi_ref_cnt--;
if (axi_ctrl->share_ctrl->axi_ref_cnt > 0)
return;
+
+ axi_clear_all_interrupts(axi_ctrl->share_ctrl);
axi_ctrl->share_ctrl->dual_enabled = 0;
disable_irq(axi_ctrl->vfeirq->start);
tasklet_kill(&axi_ctrl->vfe32_tasklet);
diff --git a/drivers/media/video/msm_vidc/vidc_hal_api.h b/drivers/media/video/msm_vidc/vidc_hal_api.h
index 659cf7e..879418d 100644
--- a/drivers/media/video/msm_vidc/vidc_hal_api.h
+++ b/drivers/media/video/msm_vidc/vidc_hal_api.h
@@ -210,7 +210,7 @@
enum hal_mpeg4_profile {
HAL_MPEG4_PROFILE_SIMPLE = 0x00000001,
- HAL_MPEG4_PROFILE_SIMPLESCALABLE = 0x00000002,
+ HAL_MPEG4_PROFILE_ADVANCEDSIMPLE = 0x00000002,
HAL_MPEG4_PROFILE_CORE = 0x00000004,
HAL_MPEG4_PROFILE_MAIN = 0x00000008,
HAL_MPEG4_PROFILE_NBIT = 0x00000010,
@@ -224,7 +224,7 @@
HAL_MPEG4_PROFILE_ADVANCEDCODING = 0x00001000,
HAL_MPEG4_PROFILE_ADVANCEDCORE = 0x00002000,
HAL_MPEG4_PROFILE_ADVANCEDSCALABLE = 0x00004000,
- HAL_MPEG4_PROFILE_ADVANCEDSIMPLE = 0x00008000,
+ HAL_MPEG4_PROFILE_SIMPLESCALABLE = 0x00008000,
HAL_UNUSED_MPEG4_PROFILE = 0x10000000,
};
diff --git a/drivers/media/video/msm_wfd/enc-mfc-subdev.c b/drivers/media/video/msm_wfd/enc-mfc-subdev.c
index 3292d78..09a5e32 100644
--- a/drivers/media/video/msm_wfd/enc-mfc-subdev.c
+++ b/drivers/media/video/msm_wfd/enc-mfc-subdev.c
@@ -2199,7 +2199,7 @@
if (rc)
WFD_MSG_ERR("Failed to free recon buffer\n");
- if (IS_ERR_OR_NULL(
+ if (!IS_ERR_OR_NULL(
client_ctx->recon_buffer_ion_handle[i])) {
if (!inst->secure) {
ion_unmap_iommu(
diff --git a/drivers/media/video/vcap_v4l2.c b/drivers/media/video/vcap_v4l2.c
index 7ac78cb..753171c 100644
--- a/drivers/media/video/vcap_v4l2.c
+++ b/drivers/media/video/vcap_v4l2.c
@@ -1957,8 +1957,10 @@
/* init video device*/
vfd = video_device_alloc();
- if (!vfd)
+ if (!vfd) {
+ ret = -ENOMEM;
goto deinit_vc;
+ }
*vfd = vcap_template;
vfd->v4l2_dev = &dev->v4l2_dev;
@@ -1972,6 +1974,7 @@
dev->vcap_wq = create_workqueue("vcap");
if (!dev->vcap_wq) {
+ ret = -ENOMEM;
pr_err("Could not create workqueue");
goto rel_vdev;
}
@@ -1979,6 +1982,8 @@
dev->ion_client = msm_ion_client_create(-1, "vcap");
if (IS_ERR((void *)dev->ion_client)) {
pr_err("could not get ion client");
+ ret = PTR_ERR(dev->ion_client);
+ dev->ion_client = NULL;
goto rel_vcap_wq;
}
diff --git a/drivers/media/video/vcap_vp.c b/drivers/media/video/vcap_vp.c
index aa39aad..a017cf2 100644
--- a/drivers/media/video/vcap_vp.c
+++ b/drivers/media/video/vcap_vp.c
@@ -304,7 +304,7 @@
}
if (irq & 0x01000000) {
v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
- VCAP_VC_LINE_ERR_EVENT;
+ VCAP_VP_REG_W_ERR_EVENT;
v4l2_event_queue(dev->vfd, &v4l2_evt);
}
if (irq & 0x00020000) {
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 4840e64..bc8eccf 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -142,7 +142,6 @@
static DEFINE_MUTEX(pil_access_lock);
static DEFINE_MUTEX(qsee_bw_mutex);
-static DEFINE_MUTEX(qsee_sfpb_bw_mutex);
static DEFINE_MUTEX(app_access_lock);
static int qsee_bw_count;
@@ -1198,28 +1197,41 @@
case CLK_DFAB:
mutex_lock(&qsee_bw_mutex);
if (!qsee_bw_count) {
- ret = msm_bus_scale_client_update_request(
- qsee_perf_client, 1);
+ if (qsee_sfpb_bw_count > 0)
+ ret = msm_bus_scale_client_update_request(
+ qsee_perf_client, 3);
+ else
+ ret = msm_bus_scale_client_update_request(
+ qsee_perf_client, 1);
if (ret)
pr_err("DFAB Bandwidth req failed (%d)\n",
ret);
else
qsee_bw_count++;
+ } else {
+ qsee_bw_count++;
}
mutex_unlock(&qsee_bw_mutex);
break;
case CLK_SFPB:
- mutex_lock(&qsee_sfpb_bw_mutex);
+ mutex_lock(&qsee_bw_mutex);
if (!qsee_sfpb_bw_count) {
- ret = msm_bus_scale_client_update_request(
- qsee_perf_client, 2);
+ if (qsee_bw_count > 0)
+ ret = msm_bus_scale_client_update_request(
+ qsee_perf_client, 3);
+ else
+ ret = msm_bus_scale_client_update_request(
+ qsee_perf_client, 2);
+
if (ret)
pr_err("SFPB Bandwidth req failed (%d)\n",
ret);
else
qsee_sfpb_bw_count++;
+ } else {
+ qsee_sfpb_bw_count++;
}
- mutex_unlock(&qsee_sfpb_bw_mutex);
+ mutex_unlock(&qsee_bw_mutex);
break;
default:
pr_err("Clock type not defined\n");
@@ -1238,29 +1250,44 @@
switch (clk_type) {
case CLK_DFAB:
mutex_lock(&qsee_bw_mutex);
- if (qsee_bw_count > 0) {
- if (qsee_bw_count-- == 1) {
+ if (qsee_bw_count == 0) {
+ pr_err("Client error.Extra call to disable DFAB clk\n");
+ mutex_unlock(&qsee_bw_mutex);
+ return;
+ }
+
+ if ((qsee_bw_count > 0) && (qsee_bw_count-- == 1)) {
+ if (qsee_sfpb_bw_count > 0)
+ ret = msm_bus_scale_client_update_request(
+ qsee_perf_client, 2);
+ else
ret = msm_bus_scale_client_update_request(
qsee_perf_client, 0);
- if (ret)
- pr_err("SFPB Bandwidth req fail (%d)\n",
+ if (ret)
+ pr_err("SFPB Bandwidth req fail (%d)\n",
ret);
- }
}
mutex_unlock(&qsee_bw_mutex);
break;
case CLK_SFPB:
- mutex_lock(&qsee_sfpb_bw_mutex);
- if (qsee_sfpb_bw_count > 0) {
- if (qsee_sfpb_bw_count-- == 1) {
+ mutex_lock(&qsee_bw_mutex);
+ if (qsee_sfpb_bw_count == 0) {
+ pr_err("Client error.Extra call to disable SFPB clk\n");
+ mutex_unlock(&qsee_bw_mutex);
+ return;
+ }
+ if ((qsee_sfpb_bw_count > 0) && (qsee_sfpb_bw_count-- == 1)) {
+ if (qsee_bw_count > 0)
+ ret = msm_bus_scale_client_update_request(
+ qsee_perf_client, 1);
+ else
ret = msm_bus_scale_client_update_request(
qsee_perf_client, 0);
- if (ret)
- pr_err("SFPB Bandwidth req fail (%d)\n",
+ if (ret)
+ pr_err("SFPB Bandwidth req fail (%d)\n",
ret);
- }
}
- mutex_unlock(&qsee_sfpb_bw_mutex);
+ mutex_unlock(&qsee_bw_mutex);
break;
default:
pr_err("Clock type not defined\n");
@@ -1697,7 +1724,6 @@
mutex_unlock(&pil_access_lock);
}
kfree(data);
- qsee_disable_clock_vote(CLK_DFAB);
return ret;
}
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 2c98816..357d290 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -1779,6 +1779,7 @@
msmsdcc_irq(int irq, void *dev_id)
{
struct msmsdcc_host *host = dev_id;
+ struct mmc_host *mmc = host->mmc;
u32 status;
int ret = 0;
int timer = 0;
@@ -1820,6 +1821,12 @@
*/
wake_lock(&host->sdio_wlock);
} else {
+ if (!mmc->card || !mmc_card_sdio(mmc->card)) {
+ WARN(1, "%s: SDCC core interrupt received for non-SDIO cards when SDCC clocks are off\n",
+ mmc_hostname(mmc));
+ ret = 1;
+ break;
+ }
spin_unlock(&host->lock);
mmc_signal_sdio_irq(host->mmc);
spin_lock(&host->lock);
@@ -1848,6 +1855,12 @@
#endif
if (status & MCI_SDIOINTROPE) {
+ if (!mmc->card || mmc_card_sdio(mmc->card)) {
+ WARN(1, "%s: SDIO interrupt received for non-SDIO card\n",
+ mmc_hostname(mmc));
+ ret = 1;
+ break;
+ }
if (host->sdcc_suspending)
wake_lock(&host->sdio_suspend_wlock);
spin_unlock(&host->lock);
@@ -2397,7 +2410,8 @@
curr_slot = host->plat->vreg_data;
if (!curr_slot) {
- rc = -EINVAL;
+ pr_debug("%s: vreg info unavailable, assuming the slot is powered by always on domain\n",
+ mmc_hostname(host->mmc));
goto out;
}
@@ -2825,6 +2839,14 @@
msmsdcc_set_vdd_io_vol(host, VDD_IO_LOW, 0);
msmsdcc_update_io_pad_pwr_switch(host);
msmsdcc_setup_pins(host, false);
+ /*
+ * Reset the mask to prevent hitting any pending interrupts
+ * after powering up the card again.
+ */
+ if (atomic_read(&host->clks_on)) {
+ writel_relaxed(0, host->base + MMCIMASK0);
+ mb();
+ }
break;
case MMC_POWER_UP:
/* writing PWR_UP bit is redundant */
@@ -5802,6 +5824,7 @@
mmc->caps |= (MMC_CAP_SET_XPC_330 | MMC_CAP_SET_XPC_300 |
MMC_CAP_SET_XPC_180);
+ mmc->caps2 |= MMC_CAP2_PACKED_WR;
mmc->caps2 |= (MMC_CAP2_BOOTPART_NOACC | MMC_CAP2_DETECT_ON_ERR);
mmc->caps2 |= MMC_CAP2_SANITIZE;
mmc->caps2 |= MMC_CAP2_CACHE_CTRL;
diff --git a/drivers/net/ethernet/msm/msm_rmnet.c b/drivers/net/ethernet/msm/msm_rmnet.c
index 61df241..41ad8af 100644
--- a/drivers/net/ethernet/msm/msm_rmnet.c
+++ b/drivers/net/ethernet/msm/msm_rmnet.c
@@ -501,16 +501,10 @@
static int __rmnet_close(struct net_device *dev)
{
struct rmnet_private *p = netdev_priv(dev);
- int rc;
- unsigned long flags;
- if (p->ch) {
- rc = smd_close(p->ch);
- spin_lock_irqsave(&p->lock, flags);
- p->ch = 0;
- spin_unlock_irqrestore(&p->lock, flags);
- return rc;
- } else
+ if (p->ch)
+ return 0;
+ else
return -EBADF;
}
@@ -529,12 +523,9 @@
static int rmnet_stop(struct net_device *dev)
{
- struct rmnet_private *p = netdev_priv(dev);
-
DBG0("[%s] rmnet_stop()\n", dev->name);
netif_stop_queue(dev);
- tasklet_kill(&p->tsklt);
/* TODO: unload modem safely,
currently, this causes unnecessary unloads */
diff --git a/drivers/platform/msm/qpnp-power-on.c b/drivers/platform/msm/qpnp-power-on.c
index 33b12ae..76a758b 100644
--- a/drivers/platform/msm/qpnp-power-on.c
+++ b/drivers/platform/msm/qpnp-power-on.c
@@ -39,8 +39,10 @@
#define QPNP_PON_RESIN_PULL_UP BIT(0)
#define QPNP_PON_KPDPWR_PULL_UP BIT(1)
+#define QPNP_PON_CBLPWR_PULL_UP BIT(2)
#define QPNP_PON_S2_CNTL_EN BIT(7)
#define QPNP_PON_S2_RESET_ENABLE BIT(7)
+#define QPNP_PON_DELAY_BIT_SHIFT 6
#define QPNP_PON_S1_TIMER_MASK (0xF)
#define QPNP_PON_S2_TIMER_MASK (0x7)
@@ -49,6 +51,7 @@
#define QPNP_PON_DBC_DELAY_MASK (0x7)
#define QPNP_PON_KPDPWR_N_SET BIT(0)
#define QPNP_PON_RESIN_N_SET BIT(1)
+#define QPNP_PON_CBLPWR_N_SET BIT(2)
#define QPNP_PON_RESIN_BARK_N_SET BIT(4)
#define QPNP_PON_RESET_EN BIT(7)
@@ -66,6 +69,7 @@
enum pon_type {
PON_KPDPWR,
PON_RESIN,
+ PON_CBLPWR,
};
struct qpnp_pon_config {
@@ -214,6 +218,9 @@
case PON_RESIN:
pon_rt_bit = QPNP_PON_RESIN_N_SET;
break;
+ case PON_CBLPWR:
+ pon_rt_bit = QPNP_PON_CBLPWR_N_SET;
+ break;
default:
return -EINVAL;
}
@@ -253,6 +260,18 @@
return IRQ_HANDLED;
}
+static irqreturn_t qpnp_cblpwr_irq(int irq, void *_pon)
+{
+ int rc;
+ struct qpnp_pon *pon = _pon;
+
+ rc = qpnp_pon_input_dispatch(pon, PON_CBLPWR);
+ if (rc)
+ dev_err(&pon->spmi->dev, "Unable to send input event\n");
+
+ return IRQ_HANDLED;
+}
+
static void bark_work_func(struct work_struct *work)
{
int rc;
@@ -351,6 +370,9 @@
case PON_RESIN:
pull_bit = QPNP_PON_RESIN_PULL_UP;
break;
+ case PON_CBLPWR:
+ pull_bit = QPNP_PON_CBLPWR_PULL_UP;
+ break;
default:
return -EINVAL;
}
@@ -489,6 +511,17 @@
}
}
break;
+ case PON_CBLPWR:
+ rc = devm_request_irq(&pon->spmi->dev, cfg->state_irq,
+ qpnp_cblpwr_irq,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ "qpnp_cblpwr_status", pon);
+ if (rc < 0) {
+ dev_err(&pon->spmi->dev, "Can't request %d IRQ\n",
+ cfg->state_irq);
+ return rc;
+ }
+ break;
default:
return -EINVAL;
}
@@ -595,6 +628,15 @@
}
}
break;
+ case PON_CBLPWR:
+ cfg->state_irq = spmi_get_irq_byname(pon->spmi,
+ NULL, "cblpwr");
+ if (cfg->state_irq < 0) {
+ dev_err(&pon->spmi->dev,
+ "Unable to get cblpwr irq\n");
+ return rc;
+ }
+ break;
default:
dev_err(&pon->spmi->dev, "PON RESET %d not supported",
cfg->pon_type);
@@ -763,11 +805,13 @@
rc = of_property_read_u32(pon->spmi->dev.of_node,
"qcom,pon-dbc-delay", &delay);
- if (rc && rc != -EINVAL) {
- dev_err(&spmi->dev, "Unable to read debounce delay\n");
- return rc;
+ if (rc) {
+ if (rc != -EINVAL) {
+ dev_err(&spmi->dev, "Unable to read debounce delay\n");
+ return rc;
+ }
} else {
- delay = (delay << 6) / USEC_PER_SEC;
+ delay = (delay << QPNP_PON_DELAY_BIT_SHIFT) / USEC_PER_SEC;
delay = ilog2(delay);
rc = qpnp_pon_masked_write(pon, QPNP_PON_DBC_CTL(pon->base),
QPNP_PON_DBC_DELAY_MASK, delay);
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index b107040..e6e2f30 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -148,8 +148,9 @@
int ibat_at_cv_ua;
int soc_at_cv;
int prev_chg_soc;
-
struct power_supply *batt_psy;
+ bool low_voltage_wake_lock_held;
+ struct wake_lock low_voltage_wake_lock;
};
/*
@@ -1319,6 +1320,28 @@
return chip->prev_chg_soc;
}
+static void very_low_voltage_check(struct pm8921_bms_chip *chip,
+ int ibat_ua, int vbat_uv)
+{
+ /*
+ * if battery is very low (v_cutoff voltage + 20mv) hold
+ * a wakelock untill soc = 0%
+ */
+ if (vbat_uv <= (chip->v_cutoff + 20) * 1000
+ && !chip->low_voltage_wake_lock_held) {
+ pr_debug("voltage = %d low holding wakelock\n", vbat_uv);
+ wake_lock(&chip->low_voltage_wake_lock);
+ chip->low_voltage_wake_lock_held = 1;
+ }
+
+ if (vbat_uv > (chip->v_cutoff + 20) * 1000
+ && chip->low_voltage_wake_lock_held) {
+ pr_debug("voltage = %d releasing wakelock\n", vbat_uv);
+ chip->low_voltage_wake_lock_held = 0;
+ wake_unlock(&chip->low_voltage_wake_lock);
+ }
+}
+
static int last_soc_est = -EINVAL;
static int adjust_soc(struct pm8921_bms_chip *chip, int soc,
int batt_temp, int chargecycles,
@@ -1343,6 +1366,7 @@
goto out;
}
+ very_low_voltage_check(chip, ibat_ua, vbat_uv);
delta_ocv_uv_limit = DIV_ROUND_CLOSEST(ibat_ua, 1000);
@@ -2897,6 +2921,9 @@
goto free_chip;
}
+ wake_lock_init(&chip->low_voltage_wake_lock,
+ WAKE_LOCK_SUSPEND, "pm8921_bms_low");
+
rc = pm8921_bms_hw_init(chip);
if (rc) {
pr_err("couldn't init hardware rc = %d\n", rc);
@@ -2954,12 +2981,33 @@
return 0;
}
+static int pm8921_bms_resume(struct device *dev)
+{
+ int rc, ibat_ua, vbat_uv;
+
+ rc = pm8921_bms_get_simultaneous_battery_voltage_and_current(
+ &ibat_ua,
+ &vbat_uv);
+ if (rc < 0) {
+ pr_err("simultaneous vbat ibat failed err = %d\n", rc);
+ return 0;
+ }
+
+ very_low_voltage_check(the_chip, ibat_ua, vbat_uv);
+ return 0;
+}
+
+static const struct dev_pm_ops pm8921_bms_pm_ops = {
+ .resume = pm8921_bms_resume,
+};
+
static struct platform_driver pm8921_bms_driver = {
.probe = pm8921_bms_probe,
.remove = __devexit_p(pm8921_bms_remove),
.driver = {
.name = PM8921_BMS_DEV_NAME,
.owner = THIS_MODULE,
+ .pm = &pm8921_bms_pm_ops,
},
};
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index e983081..19454ca 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -27,6 +27,7 @@
#include <linux/workqueue.h>
#include <linux/debugfs.h>
#include <linux/slab.h>
+#include <linux/mfd/pm8xxx/batt-alarm.h>
#include <mach/msm_xo.h>
#include <mach/msm_hsusb.h>
@@ -115,6 +116,13 @@
int batt_state;
};
+static int pm8921_battery_gauge_alarm_notify(struct notifier_block *nb,
+ unsigned long status, void *unused);
+
+static struct notifier_block alarm_notifier = {
+ .notifier_call = pm8921_battery_gauge_alarm_notify,
+};
+
static struct fsm_state_to_batt_status map[] = {
{FSM_STATE_OFF_0, POWER_SUPPLY_STATUS_UNKNOWN},
{FSM_STATE_BATFETDET_START_12, POWER_SUPPLY_STATUS_UNKNOWN},
@@ -205,6 +213,8 @@
* @max_voltage_mv: the max volts the batt should be charged up to
* @min_voltage_mv: the min battery voltage before turning the FETon
* @uvd_voltage_mv: (PM8917 only) the falling UVD threshold voltage
+ * @alarm_low_mv: the battery alarm voltage low
+ * @alarm_high_mv: the battery alarm voltage high
* @cool_temp_dc: the cool temp threshold in deciCelcius
* @warm_temp_dc: the warm temp threshold in deciCelcius
* @resume_voltage_delta: the voltage delta from vdd max at which the
@@ -225,6 +235,8 @@
unsigned int max_voltage_mv;
unsigned int min_voltage_mv;
unsigned int uvd_voltage_mv;
+ unsigned int alarm_low_mv;
+ unsigned int alarm_high_mv;
int cool_temp_dc;
int warm_temp_dc;
unsigned int temp_check_period;
@@ -250,6 +262,7 @@
bool ext_charge_done;
bool iusb_fine_res;
bool dc_unplug_check;
+ bool disable_hw_clock_switching;
DECLARE_BITMAP(enabled_irqs, PM_CHG_MAX_INTS);
struct work_struct battery_id_valid_work;
int64_t batt_id_min;
@@ -2003,6 +2016,73 @@
return get_prop_batt_temp(the_chip);
}
+static int pm8921_charger_enable_batt_alarm(struct pm8921_chg_chip *chip)
+{
+ int rc = 0;
+
+ rc = pm8xxx_batt_alarm_disable(PM8XXX_BATT_ALARM_UPPER_COMPARATOR);
+ if (!rc)
+ rc = pm8xxx_batt_alarm_enable(
+ PM8XXX_BATT_ALARM_LOWER_COMPARATOR);
+ if (rc) {
+ pr_err("unable to set batt alarm state rc=%d\n", rc);
+ return rc;
+ }
+
+ return rc;
+}
+static int pm8921_charger_configure_batt_alarm(struct pm8921_chg_chip *chip)
+{
+ int rc = 0;
+
+ rc = pm8xxx_batt_alarm_disable(PM8XXX_BATT_ALARM_UPPER_COMPARATOR);
+ if (!rc)
+ rc = pm8xxx_batt_alarm_disable(
+ PM8XXX_BATT_ALARM_LOWER_COMPARATOR);
+ if (rc) {
+ pr_err("unable to set batt alarm state rc=%d\n", rc);
+ return rc;
+ }
+
+ /*
+ * The batt-alarm driver requires sane values for both min / max,
+ * regardless of whether they're both activated.
+ */
+ rc = pm8xxx_batt_alarm_threshold_set(
+ PM8XXX_BATT_ALARM_LOWER_COMPARATOR,
+ chip->alarm_low_mv);
+ if (!rc)
+ rc = pm8xxx_batt_alarm_threshold_set(
+ PM8XXX_BATT_ALARM_UPPER_COMPARATOR,
+ chip->alarm_high_mv);
+ if (rc) {
+ pr_err("unable to set batt alarm threshold rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = pm8xxx_batt_alarm_hold_time_set(
+ PM8XXX_BATT_ALARM_HOLD_TIME_16_MS);
+ if (rc) {
+ pr_err("unable to set batt alarm hold time rc=%d\n", rc);
+ return rc;
+ }
+
+ /* PWM enabled at 2Hz */
+ rc = pm8xxx_batt_alarm_pwm_rate_set(1, 7, 4);
+ if (rc) {
+ pr_err("unable to set batt alarm pwm rate rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = pm8xxx_batt_alarm_register_notifier(&alarm_notifier);
+ if (rc) {
+ pr_err("unable to register alarm notifier rc=%d\n", rc);
+ return rc;
+ }
+
+ return rc;
+}
+
static void handle_usb_insertion_removal(struct pm8921_chg_chip *chip)
{
int usb_present;
@@ -2138,6 +2218,61 @@
}
}
+static int pm8921_battery_gauge_alarm_notify(struct notifier_block *nb,
+ unsigned long status, void *unused)
+{
+ int rc;
+
+ pr_info("status: %lu\n", status);
+
+ /* Check if called before init */
+
+ switch (status) {
+ case 0:
+ pr_err("spurious interrupt\n");
+ break;
+ /* expected case - trip of low threshold */
+ case 1:
+ if (!the_chip) {
+ pr_err("not initialized\n");
+ return -EINVAL;
+ }
+
+ the_chip->disable_hw_clock_switching = 1;
+
+ rc = pm8xxx_batt_alarm_disable(
+ PM8XXX_BATT_ALARM_LOWER_COMPARATOR);
+ if (!rc)
+ rc = pm8xxx_batt_alarm_enable(
+ PM8XXX_BATT_ALARM_UPPER_COMPARATOR);
+ if (rc)
+ pr_err("unable to set alarm state rc=%d\n", rc);
+ break;
+ case 2:
+ if (!the_chip) {
+ pr_err("not initialized\n");
+ return -EINVAL;
+ }
+
+ the_chip->disable_hw_clock_switching = 0;
+
+ rc = pm8xxx_batt_alarm_disable(
+ PM8XXX_BATT_ALARM_UPPER_COMPARATOR);
+ if (!rc)
+ rc = pm8xxx_batt_alarm_enable(
+ PM8XXX_BATT_ALARM_LOWER_COMPARATOR);
+ if (rc)
+ pr_err("unable to set alarm state rc=%d\n", rc);
+
+ pr_err("trip of high threshold\n");
+ break;
+ default:
+ pr_err("error received\n");
+ };
+
+ return 0;
+}
+
static void turn_on_ovp_fet(struct pm8921_chg_chip *chip, u16 ovptestreg)
{
u8 temp;
@@ -3038,6 +3173,18 @@
return;
}
+ /* If the disable hw clock switching
+ * flag was set it can now be unset. Also, re-enable
+ * the battery alarm to set the flag again when needed
+ */
+ if (chip->disable_hw_clock_switching) {
+ /* Unset the hw clock switching flag */
+ chip->disable_hw_clock_switching = 0;
+
+ if (pm8921_charger_enable_batt_alarm(chip))
+ pr_err("couldn't set up batt alarm!\n");
+ }
+
if (end == CHG_FINISHED) {
count++;
} else {
@@ -3297,6 +3444,7 @@
{
unsigned long flags;
int fsm_state;
+ int is_fast_chg;
chip->dc_present = !!is_dc_chg_plugged_in(chip);
chip->usb_present = !!is_usb_chg_plugged_in(chip);
@@ -3324,9 +3472,17 @@
if (usb_chg_current) {
/* reissue a vbus draw call */
__pm8921_charger_vbus_draw(usb_chg_current);
- fastchg_irq_handler(chip->pmic_chg_irq[FASTCHG_IRQ], chip);
}
spin_unlock_irqrestore(&vbus_lock, flags);
+ /*
+ * The bootloader could have started charging, a fastchg interrupt
+ * might not happen. Check the real time status and if it is fast
+ * charging invoke the handler so that the eoc worker could be
+ * started
+ */
+ is_fast_chg = pm_chg_get_rt_status(chip, FASTCHG_IRQ);
+ if (is_fast_chg)
+ fastchg_irq_handler(chip->pmic_chg_irq[FASTCHG_IRQ], chip);
fsm_state = pm_chg_get_fsm_state(chip);
if (is_battery_charging(fsm_state)) {
@@ -3944,7 +4100,8 @@
rc = pm_chg_masked_write(chip, CHG_CNTRL, VREF_BATT_THERM_FORCE_ON, 0);
if (rc)
pr_err("Failed to Force Vref therm off rc=%d\n", rc);
- pm8921_chg_set_hw_clk_switching(chip);
+ if (!(chip->disable_hw_clock_switching))
+ pm8921_chg_set_hw_clk_switching(chip);
return 0;
}
@@ -4027,6 +4184,8 @@
chip->ttrkl_time = pdata->ttrkl_time;
chip->update_time = pdata->update_time;
chip->max_voltage_mv = pdata->max_voltage;
+ chip->alarm_low_mv = pdata->alarm_low_mv;
+ chip->alarm_high_mv = pdata->alarm_high_mv;
chip->min_voltage_mv = pdata->min_voltage;
chip->uvd_voltage_mv = pdata->uvd_thresh_voltage;
chip->resume_voltage_delta = pdata->resume_voltage_delta;
@@ -4147,6 +4306,17 @@
}
}
+ rc = pm8921_charger_configure_batt_alarm(chip);
+ if (rc) {
+ pr_err("Couldn't configure battery alarm! rc=%d\n", rc);
+ goto free_irq;
+ }
+
+ rc = pm8921_charger_enable_batt_alarm(chip);
+ if (rc) {
+ pr_err("Couldn't enable battery alarm! rc=%d\n", rc);
+ goto free_irq;
+ }
create_debugfs_entries(chip);
INIT_WORK(&chip->bms_notify.work, bms_notify);
diff --git a/drivers/thermal/msm8974-tsens.c b/drivers/thermal/msm8974-tsens.c
index 7169dc0..77cc1f9 100644
--- a/drivers/thermal/msm8974-tsens.c
+++ b/drivers/thermal/msm8974-tsens.c
@@ -10,6 +10,9 @@
* GNU General Public License for more details.
*
*/
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/thermal.h>
@@ -743,8 +746,7 @@
IORESOURCE_MEM, "tsens_physical");
if (!tmdev->res_tsens_mem) {
pr_err("Could not get tsens physical address resource\n");
- rc = -EINVAL;
- goto fail_free_irq;
+ return -EINVAL;
}
tmdev->tsens_len = tmdev->res_tsens_mem->end -
@@ -754,8 +756,7 @@
tmdev->tsens_len, tmdev->res_tsens_mem->name);
if (!res_mem) {
pr_err("Request tsens physical memory region failed\n");
- rc = -EINVAL;
- goto fail_free_irq;
+ return -EINVAL;
}
tmdev->tsens_addr = ioremap(res_mem->start, tmdev->tsens_len);
@@ -805,9 +806,6 @@
if (tmdev->res_tsens_mem)
release_mem_region(tmdev->res_tsens_mem->start,
tmdev->tsens_len);
-fail_free_irq:
- free_irq(tmdev->tsens_irq, tmdev);
-
return rc;
}
@@ -827,8 +825,10 @@
tmdev->pdev = pdev;
rc = tsens_calib_sensors();
- if (rc < 0)
+ if (rc < 0) {
+ pr_err("Calibration failed\n");
goto fail;
+ }
tsens_hw_init();
@@ -848,8 +848,7 @@
if (tmdev->res_tsens_mem)
release_mem_region(tmdev->res_tsens_mem->start,
tmdev->tsens_len);
- free_irq(tmdev->tsens_irq, tmdev);
- kfree(tmdev);
+ tmdev = NULL;
return rc;
}
@@ -930,7 +929,6 @@
tmdev->tsens_len);
free_irq(tmdev->tsens_irq, tmdev);
platform_set_drvdata(pdev, NULL);
- kfree(tmdev);
return 0;
}
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index b8b7f68..0ace679 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -2661,6 +2661,7 @@
mEp->desc = NULL;
mEp->ep.desc = NULL;
+ mEp->ep.maxpacket = USHRT_MAX;
spin_unlock_irqrestore(mEp->lock, flags);
return retval;
@@ -3135,7 +3136,8 @@
mEp->ep.name = mEp->name;
mEp->ep.ops = &usb_ep_ops;
- mEp->ep.maxpacket = CTRL_PAYLOAD_MAX;
+ mEp->ep.maxpacket =
+ k ? USHRT_MAX : CTRL_PAYLOAD_MAX;
INIT_LIST_HEAD(&mEp->qh.queue);
spin_unlock_irqrestore(udc->lock, flags);
diff --git a/drivers/usb/gadget/f_rmnet_smd.c b/drivers/usb/gadget/f_rmnet_smd.c
index b71f646..5e2c6ed 100644
--- a/drivers/usb/gadget/f_rmnet_smd.c
+++ b/drivers/usb/gadget/f_rmnet_smd.c
@@ -907,13 +907,14 @@
* Register platform driver to be notified in case SMD channels
* later becomes ready to be opened.
*/
- ret = platform_driver_register(&dev->pdrv);
- if (ret)
- ERROR(cdev, "Platform driver %s register failed %d\n",
- dev->pdrv.driver.name, ret);
- else
- dev->is_pdrv_used = 1;
-
+ if (!dev->is_pdrv_used) {
+ ret = platform_driver_register(&dev->pdrv);
+ if (ret)
+ ERROR(cdev, "pdrv %s register failed %d\n",
+ dev->pdrv.driver.name, ret);
+ else
+ dev->is_pdrv_used = 1;
+ }
return;
}
wait_event(dev->smd_ctl.wait, test_bit(CH_OPENED,
diff --git a/drivers/usb/gadget/u_bam.c b/drivers/usb/gadget/u_bam.c
index 45dfb87..f092329 100644
--- a/drivers/usb/gadget/u_bam.c
+++ b/drivers/usb/gadget/u_bam.c
@@ -50,7 +50,7 @@
#define BAM_MUX_RX_Q_SIZE 16
#define BAM_MUX_TX_Q_SIZE 200
-#define BAM_MUX_RX_REQ_SIZE (2048 - BAM_MUX_HDR)
+#define BAM_MUX_RX_REQ_SIZE 2048 /* Must be 1KB aligned */
#define DL_INTR_THRESHOLD 20
diff --git a/drivers/usb/otg/msm72k_otg.c b/drivers/usb/otg/msm72k_otg.c
index f62ae76..ca1b155 100644
--- a/drivers/usb/otg/msm72k_otg.c
+++ b/drivers/usb/otg/msm72k_otg.c
@@ -1229,7 +1229,7 @@
static irqreturn_t msm_otg_irq(int irq, void *data)
{
struct msm_otg *dev = data;
- u32 otgsc, sts, pc, sts_mask;
+ u32 otgsc, sts, pc;
irqreturn_t ret = IRQ_HANDLED;
int work = 0;
enum usb_otg_state state;
@@ -1250,12 +1250,16 @@
otgsc = readl(USB_OTGSC);
sts = readl(USB_USBSTS);
- sts_mask = (otgsc & OTGSC_INTR_MASK) >> 8;
-
- if (!((otgsc & sts_mask) || (sts & STS_PCI))) {
+ /* At times during USB disconnect, hardware generates 1MSIS interrupt
+ * during PHY reset, which leads to irq not handled error as IRQ_NONE
+ * is notified. To workaround this issue, check for all the
+ * OTG_INTR_STS_MASK bits and if set, clear them and notify IRQ_HANDLED.
+ */
+ if (!((otgsc & OTGSC_INTR_STS_MASK) || (sts & STS_PCI))) {
ret = IRQ_NONE;
goto out;
}
+ writel_relaxed(otgsc, USB_OTGSC);
spin_lock_irqsave(&dev->lock, flags);
state = dev->phy.state;
@@ -1277,10 +1281,8 @@
set_bit(A_BUS_REQ, &dev->inputs);
clear_bit(ID, &dev->inputs);
}
- writel(otgsc, USB_OTGSC);
work = 1;
} else if (otgsc & OTGSC_BSVIS) {
- writel(otgsc, USB_OTGSC);
/* BSV interrupt comes when operating as an A-device
* (VBUS on/off).
* But, handle BSV when charger is removed from ACA in ID_A
@@ -1298,7 +1300,6 @@
work = 1;
} else if (otgsc & OTGSC_DPIS) {
pr_debug("DPIS detected\n");
- writel(otgsc, USB_OTGSC);
set_bit(A_SRP_DET, &dev->inputs);
set_bit(A_BUS_REQ, &dev->inputs);
work = 1;
diff --git a/drivers/video/msm/Kconfig b/drivers/video/msm/Kconfig
index 54d7090..ed4c25d 100644
--- a/drivers/video/msm/Kconfig
+++ b/drivers/video/msm/Kconfig
@@ -820,14 +820,6 @@
---help---
Support for DVI mode for MSM HDMI 1080p Panel
-config FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
- depends on FB_MSM_HDMI_MSM_PANEL
- bool "Use HDCP mode"
- default y
- ---help---
- Support for HDCP mode for MSM HDMI 1080p Panel
- Choose to enable HDCP
-
config FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
depends on FB_MSM_HDMI_MSM_PANEL
bool "Enable CEC"
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
index 3b1610a..deef4ab 100644
--- a/drivers/video/msm/hdmi_msm.c
+++ b/drivers/video/msm/hdmi_msm.c
@@ -69,12 +69,7 @@
static void hdmi_msm_dump_regs(const char *prefix);
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
static void hdmi_msm_hdcp_enable(void);
-#else
-static inline void hdmi_msm_hdcp_enable(void) {}
-#endif
-
static void hdmi_msm_turn_on(void);
static int hdmi_msm_audio_off(void);
static int hdmi_msm_read_edid(void);
@@ -678,7 +673,6 @@
case 0x00D8: return "ACR_48_1";
case 0x00E4: return "AUDIO_INFO0";
case 0x00E8: return "AUDIO_INFO1";
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
case 0x0110: return "HDCP_CTRL";
case 0x0114: return "HDCP_DEBUG_CTRL";
case 0x0118: return "HDCP_INT_CTRL";
@@ -693,7 +687,6 @@
case 0x014C: return "HDCP_RCVPORT_DATA5";
case 0x0150: return "HDCP_RCVPORT_DATA6";
case 0x0168: return "HDCP_RCVPORT_DATA12";
-#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
case 0x01D0: return "AUDIO_CFG";
case 0x0208: return "USEC_REFTIMER";
case 0x020C: return "DDC_CTRL";
@@ -708,14 +701,10 @@
case 0x0250: return "HPD_INT_STATUS";
case 0x0254: return "HPD_INT_CTRL";
case 0x0258: return "HPD_CTRL";
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
case 0x025C: return "HDCP_ENTROPY_CTRL1";
-#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
case 0x027C: return "DDC_REF";
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
case 0x0284: return "HDCP_SW_UPPER_AKSV";
case 0x0288: return "HDCP_SW_LOWER_AKSV";
-#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
case 0x02B4: return "ACTIVE_H";
case 0x02B8: return "ACTIVE_V";
case 0x02BC: return "ACTIVE_V_F2";
@@ -784,7 +773,7 @@
DEV_INFO("HDMI HPD: CONNECTED: send ONLINE\n");
kobject_uevent(external_common_state->uevent_kobj, KOBJ_ONLINE);
- if (!external_common_state->present_hdcp) {
+ if (!hdmi_msm_state->hdcp_enable) {
/* Send Audio for HDMI Compliance Cases*/
envp[0] = "HDCP_STATE=PASS";
envp[1] = NULL;
@@ -873,10 +862,13 @@
}
#endif
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
static void hdcp_deauthenticate(void);
static void hdmi_msm_hdcp_reauth_work(struct work_struct *work)
{
+ if (!hdmi_msm_state->hdcp_enable) {
+ DEV_DBG("%s: HDCP not enabled\n", __func__);
+ return;
+ }
/* Don't process recursive actions */
mutex_lock(&hdmi_msm_state_mutex);
@@ -894,17 +886,20 @@
* Therefore, as surprising as it may sound do reauth
* only if the device is HDCP-capable
*/
- if (external_common_state->present_hdcp) {
- hdcp_deauthenticate();
- mutex_lock(&hdcp_auth_state_mutex);
- hdmi_msm_state->reauth = TRUE;
- mutex_unlock(&hdcp_auth_state_mutex);
- mod_timer(&hdmi_msm_state->hdcp_timer, jiffies + HZ/2);
- }
+ hdcp_deauthenticate();
+ mutex_lock(&hdcp_auth_state_mutex);
+ hdmi_msm_state->reauth = TRUE;
+ mutex_unlock(&hdcp_auth_state_mutex);
+ mod_timer(&hdmi_msm_state->hdcp_timer, jiffies + HZ/2);
}
static void hdmi_msm_hdcp_work(struct work_struct *work)
{
+ if (!hdmi_msm_state->hdcp_enable) {
+ DEV_DBG("%s: HDCP not enabled\n", __func__);
+ return;
+ }
+
/* Only re-enable if cable still connected */
mutex_lock(&external_common_state_hpd_mutex);
if (external_common_state->hpd_state &&
@@ -925,7 +920,111 @@
hdmi_msm_state->reauth = FALSE;
}
}
-#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
+
+int hdmi_msm_process_hdcp_interrupts(void)
+{
+ int rc = -1;
+ uint32 hdcp_int_val;
+ char *envp[2];
+
+ if (!hdmi_msm_state->hdcp_enable) {
+ DEV_DBG("%s: HDCP not enabled\n", __func__);
+ return -EINVAL;
+ }
+
+ /* HDCP_INT_CTRL[0x0118]
+ * [0] AUTH_SUCCESS_INT [R] HDCP Authentication Success
+ * interrupt status
+ * [1] AUTH_SUCCESS_ACK [W] Acknowledge bit for HDCP
+ * Authentication Success bit - write 1 to clear
+ * [2] AUTH_SUCCESS_MASK [R/W] Mask bit for HDCP Authentication
+ * Success interrupt - set to 1 to enable interrupt */
+ hdcp_int_val = HDMI_INP_ND(0x0118);
+ if ((hdcp_int_val & (1 << 2)) && (hdcp_int_val & (1 << 0))) {
+ /* AUTH_SUCCESS_INT */
+ HDMI_OUTP(0x0118, (hdcp_int_val | (1 << 1)) & ~(1 << 0));
+ DEV_INFO("HDCP: AUTH_SUCCESS_INT received\n");
+ complete_all(&hdmi_msm_state->hdcp_success_done);
+ return 0;
+ }
+
+ /* [4] AUTH_FAIL_INT [R] HDCP Authentication Lost
+ * interrupt Status
+ * [5] AUTH_FAIL_ACK [W] Acknowledge bit for HDCP
+ * Authentication Lost bit - write 1 to clear
+ * [6] AUTH_FAIL_MASK [R/W] Mask bit fo HDCP Authentication
+ * Lost interrupt set to 1 to enable interrupt
+ * [7] AUTH_FAIL_INFO_ACK [W] Acknowledge bit for HDCP
+ * Authentication Failure Info field - write 1 to clear */
+ if ((hdcp_int_val & (1 << 6)) && (hdcp_int_val & (1 << 4))) {
+ /* AUTH_FAIL_INT */
+ /* Clear and Disable */
+ uint32 link_status = HDMI_INP_ND(0x011C);
+ HDMI_OUTP(0x0118, (hdcp_int_val | (1 << 5))
+ & ~((1 << 6) | (1 << 4)));
+ DEV_INFO("HDCP: AUTH_FAIL_INT received, LINK0_STATUS=0x%08x\n",
+ link_status);
+ if (hdmi_msm_state->full_auth_done) {
+ switch_set_state(&external_common_state->sdev, 0);
+ DEV_INFO("Hdmi state switched to %d: %s\n",
+ external_common_state->sdev.state, __func__);
+
+ envp[0] = "HDCP_STATE=FAIL";
+ envp[1] = NULL;
+ DEV_INFO("HDMI HPD:QDSP OFF\n");
+ kobject_uevent_env(external_common_state->uevent_kobj,
+ KOBJ_CHANGE, envp);
+
+ mutex_lock(&hdcp_auth_state_mutex);
+ hdmi_msm_state->full_auth_done = FALSE;
+ mutex_unlock(&hdcp_auth_state_mutex);
+ /* Calling reauth only when authentication
+ * is sucessful or else we always go into
+ * the reauth loop. Also, No need to reauthenticate
+ * if authentication failed because of cable disconnect
+ */
+ if (((link_status & 0xF0) >> 4) != 0x7) {
+ DEV_DBG("Reauthenticate From %s HDCP FAIL INT ",
+ __func__);
+ queue_work(hdmi_work_queue,
+ &hdmi_msm_state->hdcp_reauth_work);
+ } else {
+ DEV_INFO("HDCP: HDMI cable disconnected\n");
+ }
+ }
+
+ /* Clear AUTH_FAIL_INFO as well */
+ HDMI_OUTP(0x0118, (hdcp_int_val | (1 << 7)));
+ return 0;
+ }
+
+ /* [8] DDC_XFER_REQ_INT [R] HDCP DDC Transfer Request
+ * interrupt status
+ * [9] DDC_XFER_REQ_ACK [W] Acknowledge bit for HDCP DDC
+ * Transfer Request bit - write 1 to clear
+ * [10] DDC_XFER_REQ_MASK [R/W] Mask bit for HDCP DDC Transfer
+ * Request interrupt - set to 1 to enable interrupt */
+ if ((hdcp_int_val & (1 << 10)) && (hdcp_int_val & (1 << 8))) {
+ /* DDC_XFER_REQ_INT */
+ HDMI_OUTP_ND(0x0118, (hdcp_int_val | (1 << 9)) & ~(1 << 8));
+ if (!(hdcp_int_val & (1 << 12)))
+ return 0;
+ }
+ /* [12] DDC_XFER_DONE_INT [R] HDCP DDC Transfer done interrupt
+ * status
+ * [13] DDC_XFER_DONE_ACK [W] Acknowledge bit for HDCP DDC
+ * Transfer done bit - write 1 to clear
+ * [14] DDC_XFER_DONE_MASK [R/W] Mask bit for HDCP DDC Transfer
+ * done interrupt - set to 1 to enable interrupt */
+ if ((hdcp_int_val & (1 << 14)) && (hdcp_int_val & (1 << 12))) {
+ /* DDC_XFER_DONE_INT */
+ HDMI_OUTP_ND(0x0118, (hdcp_int_val | (1 << 13)) & ~(1 << 12));
+ DEV_INFO("HDCP: DDC_XFER_DONE received\n");
+ return 0;
+ }
+
+ return rc;
+}
static irqreturn_t hdmi_msm_isr(int irq, void *dev_id)
{
@@ -936,10 +1035,6 @@
#endif
uint32 ddc_int_ctrl;
uint32 audio_int_val;
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
- uint32 hdcp_int_val;
- char *envp[2];
-#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
static uint32 fifo_urun_int_occurred;
static uint32 sample_drop_int_occurred;
const uint32 occurrence_limit = 5;
@@ -1057,96 +1152,8 @@
return IRQ_HANDLED;
}
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
- /* HDCP_INT_CTRL[0x0118]
- * [0] AUTH_SUCCESS_INT [R] HDCP Authentication Success
- * interrupt status
- * [1] AUTH_SUCCESS_ACK [W] Acknowledge bit for HDCP
- * Authentication Success bit - write 1 to clear
- * [2] AUTH_SUCCESS_MASK [R/W] Mask bit for HDCP Authentication
- * Success interrupt - set to 1 to enable interrupt */
- hdcp_int_val = HDMI_INP_ND(0x0118);
- if ((hdcp_int_val & (1 << 2)) && (hdcp_int_val & (1 << 0))) {
- /* AUTH_SUCCESS_INT */
- HDMI_OUTP(0x0118, (hdcp_int_val | (1 << 1)) & ~(1 << 0));
- DEV_INFO("HDCP: AUTH_SUCCESS_INT received\n");
- complete_all(&hdmi_msm_state->hdcp_success_done);
+ if (!hdmi_msm_process_hdcp_interrupts())
return IRQ_HANDLED;
- }
- /* [4] AUTH_FAIL_INT [R] HDCP Authentication Lost
- * interrupt Status
- * [5] AUTH_FAIL_ACK [W] Acknowledge bit for HDCP
- * Authentication Lost bit - write 1 to clear
- * [6] AUTH_FAIL_MASK [R/W] Mask bit fo HDCP Authentication
- * Lost interrupt set to 1 to enable interrupt
- * [7] AUTH_FAIL_INFO_ACK [W] Acknowledge bit for HDCP
- * Authentication Failure Info field - write 1 to clear */
- if ((hdcp_int_val & (1 << 6)) && (hdcp_int_val & (1 << 4))) {
- /* AUTH_FAIL_INT */
- /* Clear and Disable */
- uint32 link_status = HDMI_INP_ND(0x011C);
- HDMI_OUTP(0x0118, (hdcp_int_val | (1 << 5))
- & ~((1 << 6) | (1 << 4)));
- DEV_INFO("HDCP: AUTH_FAIL_INT received, LINK0_STATUS=0x%08x\n",
- link_status);
- if (hdmi_msm_state->full_auth_done) {
- switch_set_state(&external_common_state->sdev, 0);
- DEV_INFO("Hdmi state switched to %d: %s\n",
- external_common_state->sdev.state, __func__);
-
- envp[0] = "HDCP_STATE=FAIL";
- envp[1] = NULL;
- DEV_INFO("HDMI HPD:QDSP OFF\n");
- kobject_uevent_env(external_common_state->uevent_kobj,
- KOBJ_CHANGE, envp);
-
- mutex_lock(&hdcp_auth_state_mutex);
- hdmi_msm_state->full_auth_done = FALSE;
- mutex_unlock(&hdcp_auth_state_mutex);
- /* Calling reauth only when authentication
- * is sucessful or else we always go into
- * the reauth loop. Also, No need to reauthenticate
- * if authentication failed because of cable disconnect
- */
- if (((link_status & 0xF0) >> 4) != 0x7) {
- DEV_DBG("Reauthenticate From %s HDCP FAIL INT ",
- __func__);
- queue_work(hdmi_work_queue,
- &hdmi_msm_state->hdcp_reauth_work);
- } else {
- DEV_INFO("HDCP: HDMI cable disconnected\n");
- }
- }
-
- /* Clear AUTH_FAIL_INFO as well */
- HDMI_OUTP(0x0118, (hdcp_int_val | (1 << 7)));
- return IRQ_HANDLED;
- }
- /* [8] DDC_XFER_REQ_INT [R] HDCP DDC Transfer Request
- * interrupt status
- * [9] DDC_XFER_REQ_ACK [W] Acknowledge bit for HDCP DDC
- * Transfer Request bit - write 1 to clear
- * [10] DDC_XFER_REQ_MASK [R/W] Mask bit for HDCP DDC Transfer
- * Request interrupt - set to 1 to enable interrupt */
- if ((hdcp_int_val & (1 << 10)) && (hdcp_int_val & (1 << 8))) {
- /* DDC_XFER_REQ_INT */
- HDMI_OUTP_ND(0x0118, (hdcp_int_val | (1 << 9)) & ~(1 << 8));
- if (!(hdcp_int_val & (1 << 12)))
- return IRQ_HANDLED;
- }
- /* [12] DDC_XFER_DONE_INT [R] HDCP DDC Transfer done interrupt
- * status
- * [13] DDC_XFER_DONE_ACK [W] Acknowledge bit for HDCP DDC
- * Transfer done bit - write 1 to clear
- * [14] DDC_XFER_DONE_MASK [R/W] Mask bit for HDCP DDC Transfer
- * done interrupt - set to 1 to enable interrupt */
- if ((hdcp_int_val & (1 << 14)) && (hdcp_int_val & (1 << 12))) {
- /* DDC_XFER_DONE_INT */
- HDMI_OUTP_ND(0x0118, (hdcp_int_val | (1 << 13)) & ~(1 << 12));
- DEV_INFO("HDCP: DDC_XFER_DONE received\n");
- return IRQ_HANDLED;
- }
-#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
/* Process CEC Interrupt */
@@ -1305,7 +1312,7 @@
if (external_common_state->hdmi_sink == 0) {
/* HDMI_DVI_SEL */
reg_val |= 0x00000002;
- if (external_common_state->present_hdcp)
+ if (hdmi_msm_state->hdcp_enable)
/* HDMI Encryption */
reg_val |= 0x00000004;
/* HDMI_CTRL */
@@ -1313,7 +1320,7 @@
/* HDMI_DVI_SEL */
reg_val &= ~0x00000002;
} else {
- if (external_common_state->present_hdcp)
+ if (hdmi_msm_state->hdcp_enable)
/* HDMI_Encryption_ON */
reg_val |= 0x00000006;
else
@@ -1393,7 +1400,6 @@
return 0;
}
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
static int hdmi_msm_ddc_write(uint32 dev_addr, uint32 offset,
const uint8 *data_buf, uint32 data_len, const char *what)
{
@@ -1589,7 +1595,6 @@
error:
return status;
}
-#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
static int hdmi_msm_ddc_read_retry(uint32 dev_addr, uint32 offset,
uint8 *data_buf, uint32 data_len, uint32 request_len, int retry,
@@ -2150,9 +2155,13 @@
return status;
}
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
static void hdcp_auth_info(uint32 auth_info)
{
+ if (!hdmi_msm_state->hdcp_enable) {
+ DEV_DBG("%s: HDCP not enabled\n", __func__);
+ return;
+ }
+
switch (auth_info) {
case 0:
DEV_INFO("%s: None", __func__);
@@ -2187,6 +2196,11 @@
static void hdcp_key_state(uint32 key_state)
{
+ if (!hdmi_msm_state->hdcp_enable) {
+ DEV_DBG("%s: HDCP not enabled\n", __func__);
+ return;
+ }
+
switch (key_state) {
case 0:
DEV_WARN("%s: No HDCP Keys", __func__);
@@ -2230,6 +2244,11 @@
{
int hdcp_link_status = HDMI_INP(0x011C);
+ if (!hdmi_msm_state->hdcp_enable) {
+ DEV_DBG("%s: HDCP not enabled\n", __func__);
+ return;
+ }
+
/* Disable HDCP interrupts */
HDMI_OUTP(0x0118, 0x0);
@@ -2257,6 +2276,11 @@
int failure;
int nack0;
+ if (!hdmi_msm_state->hdcp_enable) {
+ DEV_DBG("%s: HDCP not enabled\n", __func__);
+ return;
+ }
+
/*
* Check for any DDC transfer failures
* 0x0128 HDCP_DDC_STATUS
@@ -2367,6 +2391,11 @@
static uint8 buf[0xFF];
memset(buf, 0, sizeof(buf));
+ if (!hdmi_msm_state->hdcp_enable) {
+ DEV_DBG("%s: HDCP not enabled\n", __func__);
+ return 0;
+ }
+
if (!is_part1_done) {
is_part1_done = TRUE;
@@ -2654,6 +2683,11 @@
int ret;
uint8 buf[4];
+ if (!hdmi_msm_state->hdcp_enable) {
+ DEV_DBG("%s: HDCP not enabled\n", __func__);
+ return 0;
+ }
+
snprintf(what, sizeof(what), "V' H0");
ret = hdmi_msm_ddc_read(0x74, 0x20, buf, 4, 5, what, TRUE);
if (ret) {
@@ -2746,6 +2780,11 @@
boolean ksv_done = FALSE;
+ if (!hdmi_msm_state->hdcp_enable) {
+ DEV_DBG("%s: HDCP not enabled\n", __func__);
+ return 0;
+ }
+
memset(buf, 0, sizeof(buf));
memset(kvs_fifo, 0, sizeof(kvs_fifo));
@@ -2938,6 +2977,12 @@
{
int ret = 0;
int poll = 3000;
+
+ if (!hdmi_msm_state->hdcp_enable) {
+ DEV_DBG("%s: HDCP not enabled\n", __func__);
+ return 0;
+ }
+
while (poll) {
/* 0x011C HDCP_LINK0_STATUS
[30:28] KEYS_STATE = 3 = "Valid"
@@ -2968,7 +3013,7 @@
uint32 found_repeater = 0x0;
char *envp[2];
- if (!hdmi_msm_has_hdcp()) {
+ if (!hdmi_msm_state->hdcp_enable) {
DEV_INFO("%s: HDCP NOT ENABLED\n", __func__);
return;
}
@@ -3069,7 +3114,6 @@
DEV_INFO("Hdmi state switched to %d: %s\n",
external_common_state->sdev.state, __func__);
}
-#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
static void hdmi_msm_video_setup(int video_format)
{
@@ -3587,11 +3631,9 @@
{
msm_hdmi_sample_rate = rate;
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
- if (hdmi_msm_has_hdcp())
+ if (hdmi_msm_state->hdcp_enable)
hdcp_deauthenticate();
else
-#endif
hdmi_msm_turn_on();
}
EXPORT_SYMBOL(hdmi_msm_audio_sample_rate_reset);
@@ -4161,12 +4203,10 @@
#endif
hdmi_msm_spd_infoframe_packetsetup();
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
- if (hdmi_msm_state->reauth) {
+ if (hdmi_msm_state->hdcp_enable && hdmi_msm_state->reauth) {
hdmi_msm_hdcp_enable();
hdmi_msm_state->reauth = FALSE ;
}
-#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
/* re-initialize CEC if enabled */
@@ -4211,12 +4251,15 @@
}
}
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
static void hdmi_msm_hdcp_timer(unsigned long data)
{
+ if (!hdmi_msm_state->hdcp_enable) {
+ DEV_DBG("%s: HDCP not enabled\n", __func__);
+ return;
+ }
+
queue_work(hdmi_work_queue, &hdmi_msm_state->hdcp_work);
}
-#endif
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
static void hdmi_msm_cec_read_timer_func(unsigned long data)
@@ -4381,12 +4424,14 @@
mutex_unlock(&external_common_state_hpd_mutex);
hdmi_msm_turn_on();
- /* Kick off HDCP Authentication */
- mutex_lock(&hdcp_auth_state_mutex);
- hdmi_msm_state->reauth = FALSE;
- hdmi_msm_state->full_auth_done = FALSE;
- mutex_unlock(&hdcp_auth_state_mutex);
- mod_timer(&hdmi_msm_state->hdcp_timer, jiffies + HZ/2);
+ if (hdmi_msm_state->hdcp_enable) {
+ /* Kick off HDCP Authentication */
+ mutex_lock(&hdcp_auth_state_mutex);
+ hdmi_msm_state->reauth = FALSE;
+ hdmi_msm_state->full_auth_done = FALSE;
+ mutex_unlock(&hdcp_auth_state_mutex);
+ mod_timer(&hdmi_msm_state->hdcp_timer, jiffies + HZ/2);
+ }
} else
mutex_unlock(&external_common_state_hpd_mutex);
@@ -4410,16 +4455,14 @@
external_common_state->sdev.state, __func__);
if (on) {
hdmi_msm_read_edid();
- if (hdmi_msm_has_hdcp())
- hdmi_msm_state->reauth = FALSE ;
+ hdmi_msm_state->reauth = FALSE ;
/* Build EDID table */
hdmi_msm_turn_on();
DEV_INFO("HDMI HPD: CONNECTED: send ONLINE\n");
kobject_uevent(external_common_state->uevent_kobj,
KOBJ_ONLINE);
- hdmi_msm_hdcp_enable();
envp[0] = 0;
- if (!hdmi_msm_has_hdcp()) {
+ if (!hdmi_msm_state->hdcp_enable) {
/* Send Audio for HDMI Compliance Cases*/
envp[0] = "HDCP_STATE=PASS";
envp[1] = NULL;
@@ -4429,6 +4472,8 @@
switch_set_state(&external_common_state->sdev, 1);
DEV_INFO("Hdmi state switched to %d: %s\n",
external_common_state->sdev.state, __func__);
+ } else {
+ hdmi_msm_hdcp_enable();
}
} else {
DEV_INFO("HDMI HPD: DISCONNECTED: send OFFLINE\n");
@@ -4452,7 +4497,6 @@
if (!hdmi_msm_state->hdmi_app_clk)
return -ENODEV;
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
mutex_lock(&hdmi_msm_state_mutex);
if (hdmi_msm_state->hdcp_activating) {
hdmi_msm_state->panel_power_on = FALSE;
@@ -4461,13 +4505,10 @@
return 0;
}
mutex_unlock(&hdmi_msm_state_mutex);
-#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
DEV_INFO("power: OFF (audio off, Reset Core)\n");
hdmi_msm_audio_off();
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
hdcp_deauthenticate();
-#endif
hdmi_msm_powerdown_phy();
hdmi_msm_state->panel_power_on = FALSE;
@@ -4479,6 +4520,28 @@
return hdmi_msm_state->is_mhl_enabled;
}
+void hdmi_msm_config_hdcp_feature(void)
+{
+ if (hdcp_feature_on && hdmi_msm_has_hdcp()) {
+ init_timer(&hdmi_msm_state->hdcp_timer);
+ hdmi_msm_state->hdcp_timer.function = hdmi_msm_hdcp_timer;
+ hdmi_msm_state->hdcp_timer.data = (uint32)NULL;
+ hdmi_msm_state->hdcp_timer.expires = 0xffffffffL;
+
+ init_completion(&hdmi_msm_state->hdcp_success_done);
+ INIT_WORK(&hdmi_msm_state->hdcp_reauth_work,
+ hdmi_msm_hdcp_reauth_work);
+ INIT_WORK(&hdmi_msm_state->hdcp_work, hdmi_msm_hdcp_work);
+ hdmi_msm_state->hdcp_enable = TRUE;
+ } else {
+ del_timer(&hdmi_msm_state->hdcp_timer);
+ hdmi_msm_state->hdcp_enable = FALSE;
+ }
+ external_common_state->present_hdcp = hdmi_msm_state->hdcp_enable;
+ DEV_INFO("%s: HDCP Feature: %s\n", __func__,
+ hdmi_msm_state->hdcp_enable ? "Enabled" : "Disabled");
+}
+
static int __devinit hdmi_msm_probe(struct platform_device *pdev)
{
int rc;
@@ -4591,15 +4654,6 @@
hdmi_msm_state->hpd_state_timer.expires = 0xffffffffL;
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
- init_timer(&hdmi_msm_state->hdcp_timer);
- hdmi_msm_state->hdcp_timer.function =
- hdmi_msm_hdcp_timer;
- hdmi_msm_state->hdcp_timer.data = (uint32)NULL;
-
- hdmi_msm_state->hdcp_timer.expires = 0xffffffffL;
-#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
-
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
init_timer(&hdmi_msm_state->cec_read_timer);
hdmi_msm_state->cec_read_timer.function =
@@ -4626,22 +4680,7 @@
goto error;
}
- if (hdmi_msm_has_hdcp()) {
- /* Don't Set Encryption in case of non HDCP builds */
- external_common_state->present_hdcp = FALSE;
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
- external_common_state->present_hdcp = TRUE;
-#endif
- } else {
- external_common_state->present_hdcp = FALSE;
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
- /*
- * If the device is not hdcp capable do
- * not start hdcp timer.
- */
- del_timer(&hdmi_msm_state->hdcp_timer);
-#endif
- }
+ hdmi_msm_config_hdcp_feature();
/* Initialize hdmi node and register with switch driver */
if (hdmi_prim_display)
@@ -4825,11 +4864,6 @@
hdmi_common_init_panel_info(&hdmi_msm_panel_data.panel_info);
init_completion(&hdmi_msm_state->ddc_sw_done);
INIT_WORK(&hdmi_msm_state->hpd_state_work, hdmi_msm_hpd_state_work);
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
- init_completion(&hdmi_msm_state->hdcp_success_done);
- INIT_WORK(&hdmi_msm_state->hdcp_reauth_work, hdmi_msm_hdcp_reauth_work);
- INIT_WORK(&hdmi_msm_state->hdcp_work, hdmi_msm_hdcp_work);
-#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
INIT_WORK(&hdmi_msm_state->cec_latch_detect_work,
@@ -4853,9 +4887,6 @@
" RELEASE"
#endif
" AUDIO EDID HPD HDCP"
-#ifndef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
- ":0"
-#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
" DVI"
#ifndef CONFIG_FB_MSM_HDMI_MSM_PANEL_DVI_SUPPORT
":0"
@@ -4885,6 +4916,15 @@
return rv;
pr_debug("%s: HDCP feature = %d\n", __func__, hdcp_feature_on);
+ if (hdmi_msm_state) {
+ if ((HDMI_INP(0x0250) & 0x2)) {
+ pr_err("%s: Unable to set HDCP feature", __func__);
+ pr_err("%s: HDMI panel is currently turned on",
+ __func__);
+ } else if (hdcp_feature_on != hdmi_msm_state->hdcp_enable) {
+ hdmi_msm_config_hdcp_feature();
+ }
+ }
return 0;
}
diff --git a/drivers/video/msm/hdmi_msm.h b/drivers/video/msm/hdmi_msm.h
index 5d27412..20bd492 100644
--- a/drivers/video/msm/hdmi_msm.h
+++ b/drivers/video/msm/hdmi_msm.h
@@ -64,13 +64,12 @@
struct timer_list hpd_state_timer;
struct completion ddc_sw_done;
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
+ bool hdcp_enable;
boolean hdcp_activating;
boolean reauth ;
struct work_struct hdcp_reauth_work, hdcp_work;
struct completion hdcp_success_done;
struct timer_list hdcp_timer;
-#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
boolean cec_enabled;
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index 005e87c..180a18a 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -306,10 +306,16 @@
uint32 is_fg; /* control alpha & color key */
uint32 srcp0_addr; /* interleave, luma */
uint32 srcp0_ystride;
+ struct file *srcp0_file;
+ int put0_need;
uint32 srcp1_addr; /* pseudoplanar, chroma plane */
uint32 srcp1_ystride;
+ struct file *srcp1_file;
+ int put1_need;
uint32 srcp2_addr; /* planar color 2*/
uint32 srcp2_ystride;
+ struct file *srcp2_file;
+ int put2_need;
uint32 srcp3_addr; /* alpha/color 3 */
uint32 srcp3_ystride;
uint32 fetch_plane;
@@ -349,7 +355,7 @@
uint32 ov_cnt;
uint32 dmap_cnt;
uint32 dmae_cnt;
- uint32 blt_end;
+ uint32 blt_end; /* used by mddi only */
uint32 blt_ov_koff;
uint32 blt_ov_done;
uint32 blt_dmap_koff;
@@ -543,12 +549,9 @@
void mdp4_overlay0_done_dsi_cmd(int cndx);
void mdp4_primary_rdptr(void);
void mdp4_dsi_cmd_overlay(struct msm_fb_data_type *mfd);
-int mdp4_overlay_commit(struct fb_info *info, int mixer);
-int mdp4_dsi_video_pipe_commit(void);
-int mdp4_dsi_cmd_pipe_commit(void);
+int mdp4_lcdc_pipe_commit(int cndx, int wait);
+int mdp4_dtv_pipe_commit(int cndx, int wait);
int mdp4_dsi_cmd_update_cnt(int cndx);
-int mdp4_lcdc_pipe_commit(void);
-int mdp4_dtv_pipe_commit(void);
void mdp4_dsi_rdptr_init(int cndx);
void mdp4_dsi_vsync_init(int cndx);
void mdp4_lcdc_vsync_init(int cndx);
@@ -577,6 +580,7 @@
int mdp4_overlay_play_wait(struct fb_info *info,
struct msmfb_overlay_data *req);
int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req);
+int mdp4_overlay_commit(struct fb_info *info, int mixer);
struct mdp4_overlay_pipe *mdp4_overlay_pipe_alloc(int ptype, int mixer);
void mdp4_overlay_dma_commit(int mixer);
void mdp4_overlay_vsync_commit(struct mdp4_overlay_pipe *pipe);
@@ -763,6 +767,8 @@
void mdp4_dsi_video_wait4vsync(int cndx, long long *vtime);
void mdp4_dsi_cmd_pipe_queue(int cndx, struct mdp4_overlay_pipe *pipe);
void mdp4_dsi_video_pipe_queue(int cndx, struct mdp4_overlay_pipe *pipe);
+int mdp4_dsi_video_pipe_commit(int cndx, int wait);
+int mdp4_dsi_cmd_pipe_commit(int cndx, int wait);
void mdp4_dsi_cmd_vsync_ctrl(struct fb_info *info, int enable);
void mdp4_dsi_video_vsync_ctrl(struct fb_info *info, int enable);
#ifdef CONFIG_FB_MSM_MDP303
@@ -812,6 +818,14 @@
struct mdp4_overlay_pipe *pipe)
{
}
+static inline int mdp4_dsi_video_pipe_commit(int cndx, int wait)
+{
+ return 0;
+}
+static inline int mdp4_dsi_cmd_pipe_commit(int cndx, int wait)
+{
+ return 0;
+}
static inline void mdp4_dsi_cmd_vsync_ctrl(struct fb_info *info,
int enable)
{
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index b154a3b..8499e3e 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -191,6 +191,19 @@
if (pipe == NULL)
return;
+ if (pipe->flags & MDP_MEMORY_ID_TYPE_FB) {
+ if (pipe->put0_need)
+ fput_light(pipe->srcp0_file, pipe->put0_need);
+ if (pipe->put1_need)
+ fput_light(pipe->srcp1_file, pipe->put1_need);
+ if (pipe->put2_need)
+ fput_light(pipe->srcp2_file, pipe->put2_need);
+
+ pr_debug("%s: ndx=%d flags=%x put=%d\n", __func__,
+ pipe->pipe_ndx, pipe->flags, pipe->put0_need);
+ return;
+ }
+
mutex_lock(&iommu_mutex);
mixer = pipe->mixer_num;
iom = &pipe->iommu;
@@ -1946,7 +1959,7 @@
struct mdp4_overlay_pipe *d_pipe;
struct mdp4_overlay_pipe *s_pipe;
struct blend_cfg *blend;
- int i, off, ptype, alpha_drop = 0;
+ int i, off, alpha_drop = 0;
int d_alpha, s_alpha;
unsigned char *overlay_base;
uint32 c0, c1, c2, base_premulti;
@@ -1992,7 +2005,8 @@
blend->bg_alpha = 0x0ff - s_pipe->alpha;
blend->fg_alpha = s_pipe->alpha;
blend->co3_sel = 1; /* use fg alpha */
-
+ pr_debug("%s: bg alpha %d, fg alpha %d\n",
+ __func__, blend->bg_alpha, blend->fg_alpha);
if (s_pipe->is_fg) {
if (s_pipe->alpha == 0xff) {
blend->solidfill = 1;
@@ -2008,30 +2022,21 @@
MDP4_BLEND_FG_ALPHA_FG_PIXEL;
else
blend->fg_alpha = 0xff;
+ blend->op |= MDP4_BLEND_BG_INV_ALPHA;
} else
blend->op = MDP4_BLEND_BG_ALPHA_FG_CONST;
-
- blend->op |= MDP4_BLEND_BG_INV_ALPHA;
} else if (d_alpha) {
- ptype = mdp4_overlay_format2type(s_pipe->src_format);
- if (ptype == OVERLAY_TYPE_VIDEO) {
- blend->op = (MDP4_BLEND_FG_ALPHA_BG_PIXEL |
- MDP4_BLEND_FG_INV_ALPHA);
- if ((!(s_pipe->flags & MDP_BLEND_FG_PREMULT)) &&
- ((i != MDP4_MIXER_STAGE0) ||
- (!base_premulti)))
- blend->op |=
- MDP4_BLEND_BG_ALPHA_BG_PIXEL;
- else
- blend->fg_alpha = 0xff;
+ blend->op = (MDP4_BLEND_FG_ALPHA_BG_PIXEL |
+ MDP4_BLEND_FG_INV_ALPHA);
+ if ((!(d_pipe->flags & MDP_BLEND_FG_PREMULT)) &&
+ ((i != MDP4_MIXER_STAGE0) ||
+ (!base_premulti)))
+ blend->op |=
+ MDP4_BLEND_BG_ALPHA_BG_PIXEL;
+ else
+ blend->fg_alpha = 0xff;
- blend->co3_sel = 0; /* use bg alpha */
- } else {
- /* s_pipe is rgb without alpha */
- blend->op = (MDP4_BLEND_FG_ALPHA_FG_CONST |
- MDP4_BLEND_BG_ALPHA_BG_CONST);
- blend->bg_alpha = 0;
- }
+ blend->co3_sel = 0; /* use bg alpha */
}
if (s_pipe->transp != MDP_TRANSP_NOP) {
@@ -2955,14 +2960,13 @@
if (file == NULL)
return -EINVAL;
+ pipe->flags |= MDP_MEMORY_ID_TYPE_FB;
if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
fb_num = MINOR(file->f_dentry->d_inode->i_rdev);
if (get_fb_phys_info(start, len, fb_num,
DISPLAY_SUBSYSTEM_ID)) {
ret = -1;
} else {
- pr_warn("%s: mdp4_overlay play with FB memory\n",
- __func__);
*srcp_file = file;
*p_need = put_needed;
}
@@ -3320,11 +3324,8 @@
struct mdp4_overlay_pipe *pipe;
ulong start, addr;
ulong len = 0;
- struct file *srcp0_file = NULL;
- struct file *srcp1_file = NULL, *srcp2_file = NULL;
struct ion_handle *srcp0_ihdl = NULL;
struct ion_handle *srcp1_ihdl = NULL, *srcp2_ihdl = NULL;
- int ps0_need, p_need;
uint32_t overlay_version = 0;
int ret = 0;
@@ -3349,8 +3350,8 @@
mutex_lock(&mfd->dma->ov_mutex);
img = &req->data;
- get_img(img, info, pipe, 0, &start, &len, &srcp0_file,
- &ps0_need, &srcp0_ihdl);
+ get_img(img, info, pipe, 0, &start, &len, &pipe->srcp0_file,
+ &pipe->put0_need, &srcp0_ihdl);
if (len == 0) {
pr_err("%s: pmem Error\n", __func__);
ret = -1;
@@ -3372,8 +3373,9 @@
if (pipe->fetch_plane == OVERLAY_PLANE_PSEUDO_PLANAR) {
if (overlay_version > 0) {
img = &req->plane1_data;
- get_img(img, info, pipe, 1, &start, &len, &srcp1_file,
- &p_need, &srcp1_ihdl);
+ get_img(img, info, pipe, 1, &start, &len,
+ &pipe->srcp1_file, &pipe->put1_need,
+ &srcp1_ihdl);
if (len == 0) {
pr_err("%s: Error to get plane1\n", __func__);
ret = -EINVAL;
@@ -3404,8 +3406,9 @@
} else if (pipe->fetch_plane == OVERLAY_PLANE_PLANAR) {
if (overlay_version > 0) {
img = &req->plane1_data;
- get_img(img, info, pipe, 1, &start, &len, &srcp1_file,
- &p_need, &srcp1_ihdl);
+ get_img(img, info, pipe, 1, &start, &len,
+ &pipe->srcp1_file, &pipe->put1_need,
+ &srcp1_ihdl);
if (len == 0) {
pr_err("%s: Error to get plane1\n", __func__);
ret = -EINVAL;
@@ -3414,8 +3417,9 @@
pipe->srcp1_addr = start + img->offset;
img = &req->plane2_data;
- get_img(img, info, pipe, 2, &start, &len, &srcp2_file,
- &p_need, &srcp2_ihdl);
+ get_img(img, info, pipe, 2, &start, &len,
+ &pipe->srcp2_file, &pipe->put2_need,
+ &srcp2_ihdl);
if (len == 0) {
pr_err("%s: Error to get plane2\n", __func__);
ret = -EINVAL;
@@ -3464,8 +3468,7 @@
if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) {
/* cndx = 0 */
mdp4_dsi_cmd_pipe_queue(0, pipe);
- }
- if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO) {
+ } else if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO) {
/* cndx = 0 */
mdp4_dsi_video_pipe_queue(0, pipe);
} else if (ctrl->panel_mode & MDP4_PANEL_LCDC) {
@@ -3513,20 +3516,49 @@
end:
mutex_unlock(&mfd->dma->ov_mutex);
-#ifdef CONFIG_ANDROID_PMEM
- if (srcp0_file)
- put_pmem_file(srcp0_file);
- if (srcp1_file)
- put_pmem_file(srcp1_file);
- if (srcp2_file)
- put_pmem_file(srcp2_file);
-#endif
- /* only source may use frame buffer */
- if (img->flags & MDP_MEMORY_ID_TYPE_FB)
- fput_light(srcp0_file, ps0_need);
return ret;
}
+int mdp4_overlay_commit(struct fb_info *info, int mixer)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+ if (mfd == NULL)
+ return -ENODEV;
+
+ if (!mfd->panel_power_on) /* suspended */
+ return -EINVAL;
+
+ if (mixer >= MDP4_MIXER_MAX)
+ return -EPERM;
+
+ mutex_lock(&mfd->dma->ov_mutex);
+
+ mdp4_overlay_mdp_perf_upd(mfd, 1);
+
+ if (mixer == MDP4_MIXER0) {
+ if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) {
+ /* cndx = 0 */
+ mdp4_dsi_cmd_pipe_commit(0, 1);
+ } else if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO) {
+ /* cndx = 0 */
+ mdp4_dsi_video_pipe_commit(0, 1);
+ } else if (ctrl->panel_mode & MDP4_PANEL_LCDC) {
+ /* cndx = 0 */
+ mdp4_lcdc_pipe_commit(0, 1);
+ }
+ } else if (mixer == MDP4_MIXER1) {
+ if (ctrl->panel_mode & MDP4_PANEL_DTV)
+ mdp4_dtv_pipe_commit(0, 1);
+ }
+
+ mdp4_overlay_mdp_perf_upd(mfd, 0);
+
+ mutex_unlock(&mfd->dma->ov_mutex);
+
+ return 0;
+}
+
struct msm_iommu_ctx {
char *name;
int domain;
diff --git a/drivers/video/msm/mdp4_overlay_dsi_cmd.c b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
index 488f2af..ecdd567 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_cmd.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
@@ -250,7 +250,7 @@
static void mdp4_dsi_cmd_blt_ov_update(struct mdp4_overlay_pipe *pipe);
-int mdp4_dsi_cmd_pipe_commit(void)
+int mdp4_dsi_cmd_pipe_commit(int cndx, int wait)
{
int i, undx;
int mixer = 0;
@@ -377,6 +377,12 @@
mdp4_stat.overlay_commit[pipe->mixer_num]++;
+ if (wait) {
+ long long tick;
+
+ mdp4_dsi_cmd_wait4vsync(cndx, &tick);
+ }
+
return cnt;
}
@@ -533,6 +539,8 @@
vctrl = &vsync_ctrl_db[cndx];
pipe = vctrl->base_pipe;
+ if (pipe == NULL)
+ return;
/* blt enabled */
spin_lock(&vctrl->spin_lock);
@@ -572,6 +580,8 @@
vctrl = &vsync_ctrl_db[cndx];
pipe = vctrl->base_pipe;
+ if (pipe == NULL)
+ return;
spin_lock(&vctrl->spin_lock);
vsync_irq_disable(INTR_OVERLAY0_DONE, MDP_OVERLAY0_TERM);
@@ -1016,6 +1026,8 @@
struct msm_fb_data_type *mfd;
struct vsycn_ctrl *vctrl;
struct mdp4_overlay_pipe *pipe;
+ struct vsync_update *vp;
+ int undx;
pr_debug("%s+:\n", __func__);
@@ -1048,6 +1060,16 @@
mdp_clk_ctrl(0);
}
+ undx = vctrl->update_ndx;
+ vp = &vctrl->vlist[undx];
+ if (vp->update_cnt) {
+ /*
+ * pipe's iommu will be freed at next overlay play
+ * and iommu_drop statistic will be increased by one
+ */
+ vp->update_cnt = 0; /* empty queue */
+ }
+
vctrl->clk_enabled = 0;
vctrl->vsync_enabled = 0;
vctrl->clk_control = 0;
@@ -1099,6 +1121,7 @@
struct vsycn_ctrl *vctrl;
struct mdp4_overlay_pipe *pipe;
unsigned long flags;
+ long long tick;
vctrl = &vsync_ctrl_db[cndx];
@@ -1139,8 +1162,10 @@
mdp4_overlay_mdp_perf_upd(mfd, 1);
mutex_lock(&mfd->dma->ov_mutex);
- mdp4_dsi_cmd_pipe_commit();
+ mdp4_dsi_cmd_pipe_commit(cndx, 0);
mutex_unlock(&mfd->dma->ov_mutex);
+ mdp4_dsi_cmd_wait4vsync(cndx, &tick);
+
mdp4_overlay_mdp_perf_upd(mfd, 0);
}
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index 6c9edb5..6aa101f 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -147,7 +147,7 @@
static void mdp4_dsi_video_wait4dmap(int cndx);
static void mdp4_dsi_video_wait4ov(int cndx);
-int mdp4_dsi_video_pipe_commit(void)
+int mdp4_dsi_video_pipe_commit(int cndx, int wait)
{
int i, undx;
@@ -159,7 +159,7 @@
unsigned long flags;
int cnt = 0;
- vctrl = &vsync_ctrl_db[0];
+ vctrl = &vsync_ctrl_db[cndx];
mutex_lock(&vctrl->update_lock);
undx = vctrl->update_ndx;
@@ -253,6 +253,13 @@
mdp4_stat.overlay_commit[pipe->mixer_num]++;
+ if (wait) {
+ if (pipe->ov_blt_addr)
+ mdp4_dsi_video_wait4ov(cndx);
+ else
+ mdp4_dsi_video_wait4dmap(cndx);
+ }
+
return cnt;
}
@@ -682,8 +689,9 @@
struct msm_fb_data_type *mfd;
struct vsycn_ctrl *vctrl;
struct mdp4_overlay_pipe *pipe;
+ struct vsync_update *vp;
unsigned long flags;
- int need_wait = 0;
+ int undx, need_wait = 0;
mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
vctrl = &vsync_ctrl_db[cndx];
@@ -716,6 +724,16 @@
vsync_irq_disable(INTR_PRIMARY_VSYNC, MDP_PRIM_VSYNC_TERM);
}
+ undx = vctrl->update_ndx;
+ vp = &vctrl->vlist[undx];
+ if (vp->update_cnt) {
+ /*
+ * pipe's iommu will be freed at next overlay play
+ * and iommu_drop statistic will be increased by one
+ */
+ vp->update_cnt = 0; /* empty queue */
+ }
+
if (pipe) {
/* sanity check, free pipes besides base layer */
mdp4_overlay_unset_mixer(pipe->mixer_num);
@@ -924,6 +942,8 @@
}
vctrl = &vsync_ctrl_db[cndx];
pipe = vctrl->base_pipe;
+ if (pipe == NULL)
+ return;
spin_lock(&vctrl->spin_lock);
vsync_irq_disable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
@@ -959,6 +979,8 @@
vctrl = &vsync_ctrl_db[cndx];
pipe = vctrl->base_pipe;
+ if (pipe == NULL)
+ return;
spin_lock(&vctrl->spin_lock);
vsync_irq_disable(INTR_OVERLAY0_DONE, MDP_OVERLAY0_TERM);
@@ -1075,13 +1097,13 @@
mdp4_overlay_mdp_perf_upd(mfd, 1);
mutex_lock(&mfd->dma->ov_mutex);
- mdp4_dsi_video_pipe_commit();
+ mdp4_dsi_video_pipe_commit(cndx, 0);
mutex_unlock(&mfd->dma->ov_mutex);
if (pipe->ov_blt_addr)
- mdp4_dsi_video_wait4ov(0);
+ mdp4_dsi_video_wait4ov(cndx);
else
- mdp4_dsi_video_wait4dmap(0);
+ mdp4_dsi_video_wait4dmap(cndx);
mdp4_overlay_mdp_perf_upd(mfd, 0);
}
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index a89b5be..21e5d1d 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -165,7 +165,7 @@
static void mdp4_dtv_blt_ov_update(struct mdp4_overlay_pipe *pipe);
static void mdp4_dtv_wait4dmae(int cndx);
-int mdp4_dtv_pipe_commit(void)
+int mdp4_dtv_pipe_commit(int cndx, int wait)
{
int i, undx;
@@ -177,7 +177,7 @@
unsigned long flags;
int cnt = 0;
- vctrl = &vsync_ctrl_db[0];
+ vctrl = &vsync_ctrl_db[cndx];
mutex_lock(&vctrl->update_lock);
undx = vctrl->update_ndx;
vp = &vctrl->vlist[undx];
@@ -236,6 +236,9 @@
spin_unlock_irqrestore(&vctrl->spin_lock, flags);
mdp4_stat.overlay_commit[pipe->mixer_num]++;
+ if (wait)
+ mdp4_dtv_wait4dmae(cndx);
+
return cnt;
}
@@ -594,8 +597,10 @@
struct msm_fb_data_type *mfd;
int ret = 0;
int cndx = 0;
+ int undx;
struct vsycn_ctrl *vctrl;
struct mdp4_overlay_pipe *pipe;
+ struct vsync_update *vp;
mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
@@ -641,6 +646,16 @@
vsync_irq_disable(INTR_PRIMARY_VSYNC, MDP_PRIM_VSYNC_TERM);
}
+ undx = vctrl->update_ndx;
+ vp = &vctrl->vlist[undx];
+ if (vp->update_cnt) {
+ /*
+ * pipe's iommu will be freed at next overlay play
+ * and iommu_drop statistic will be increased by one
+ */
+ vp->update_cnt = 0; /* empty queue */
+ }
+
ret = panel_next_off(pdev);
mdp_footswitch_ctrl(FALSE);
@@ -867,6 +882,8 @@
vctrl = &vsync_ctrl_db[cndx];
pipe = vctrl->base_pipe;
+ if (pipe == NULL)
+ return;
pr_debug("%s: cpu=%d\n", __func__, smp_processor_id());
spin_lock(&vctrl->spin_lock);
@@ -907,6 +924,8 @@
vctrl = &vsync_ctrl_db[cndx];
pipe = vctrl->base_pipe;
+ if (pipe == NULL)
+ return;
spin_lock(&vctrl->spin_lock);
if (pipe->ov_blt_addr == 0) {
@@ -1060,7 +1079,7 @@
mutex_lock(&mfd->dma->ov_mutex);
mdp4_overlay_mdp_perf_upd(mfd, 1);
- mdp4_dtv_pipe_commit();
+ mdp4_dtv_pipe_commit(cndx, 0);
mdp4_overlay_mdp_perf_upd(mfd, 0);
mutex_unlock(&mfd->dma->ov_mutex);
}
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index 78c69b8..1f5136f 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -152,7 +152,7 @@
static void mdp4_lcdc_wait4dmap(int cndx);
static void mdp4_lcdc_wait4ov(int cndx);
-int mdp4_lcdc_pipe_commit(void)
+int mdp4_lcdc_pipe_commit(int cndx, int wait)
{
int i, undx;
@@ -164,7 +164,7 @@
unsigned long flags;
int cnt = 0;
- vctrl = &vsync_ctrl_db[0];
+ vctrl = &vsync_ctrl_db[cndx];
mutex_lock(&vctrl->update_lock);
undx = vctrl->update_ndx;
@@ -257,6 +257,13 @@
mdp4_stat.overlay_commit[pipe->mixer_num]++;
+ if (wait) {
+ if (pipe->ov_blt_addr)
+ mdp4_lcdc_wait4ov(cndx);
+ else
+ mdp4_lcdc_wait4dmap(cndx);
+ }
+
return cnt;
}
@@ -666,8 +673,9 @@
struct msm_fb_data_type *mfd;
struct vsycn_ctrl *vctrl;
struct mdp4_overlay_pipe *pipe;
+ struct vsync_update *vp;
unsigned long flags;
- int need_wait = 0;
+ int undx, need_wait = 0;
mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
vctrl = &vsync_ctrl_db[cndx];
@@ -700,6 +708,16 @@
vsync_irq_disable(INTR_PRIMARY_VSYNC, MDP_PRIM_VSYNC_TERM);
}
+ undx = vctrl->update_ndx;
+ vp = &vctrl->vlist[undx];
+ if (vp->update_cnt) {
+ /*
+ * pipe's iommu will be freed at next overlay play
+ * and iommu_drop statistic will be increased by one
+ */
+ vp->update_cnt = 0; /* empty queue */
+ }
+
if (pipe) {
/* sanity check, free pipes besides base layer */
mdp4_overlay_unset_mixer(pipe->mixer_num);
@@ -811,6 +829,8 @@
}
vctrl = &vsync_ctrl_db[cndx];
pipe = vctrl->base_pipe;
+ if (pipe == NULL)
+ return;
spin_lock(&vctrl->spin_lock);
vsync_irq_disable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
@@ -849,6 +869,8 @@
vctrl = &vsync_ctrl_db[cndx];
pipe = vctrl->base_pipe;
+ if (pipe == NULL)
+ return;
spin_lock(&vctrl->spin_lock);
vsync_irq_disable(INTR_OVERLAY0_DONE, MDP_OVERLAY0_TERM);
@@ -962,13 +984,13 @@
mdp4_overlay_mdp_perf_upd(mfd, 1);
mutex_lock(&mfd->dma->ov_mutex);
- mdp4_lcdc_pipe_commit();
+ mdp4_lcdc_pipe_commit(cndx, 0);
mutex_unlock(&mfd->dma->ov_mutex);
if (pipe->ov_blt_addr)
- mdp4_lcdc_wait4ov(0);
+ mdp4_lcdc_wait4ov(cndx);
else
- mdp4_lcdc_wait4dmap(0);
+ mdp4_lcdc_wait4dmap(cndx);
mdp4_overlay_mdp_perf_upd(mfd, 0);
}
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index efb4da6..9f29887 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -42,6 +42,9 @@
#include <linux/vmalloc.h>
#include <mach/board.h>
+#include <mach/memory.h>
+#include <mach/msm_memtypes.h>
+#include <mach/iommu_domains.h>
#include "mdss_fb.h"
#include "mdss_mdp.h"
@@ -596,37 +599,17 @@
size *= mfd->fb_page;
if (mfd->index == 0) {
- struct ion_client *iclient = mdss_get_ionclient();
-
- if (iclient) {
- mfd->ihdl = ion_alloc(iclient, size, SZ_4K,
- ION_HEAP(ION_CP_MM_HEAP_ID) |
- ION_HEAP(ION_SF_HEAP_ID), 0);
- if (IS_ERR_OR_NULL(mfd->ihdl)) {
- pr_err("unable to alloc fbmem from ion (%p)\n",
- mfd->ihdl);
- return -ENOMEM;
- }
-
- virt = ion_map_kernel(iclient, mfd->ihdl);
- ion_phys(iclient, mfd->ihdl, &phys, &size);
-
- if (is_mdss_iommu_attached()) {
- ion_map_iommu(iclient, mfd->ihdl,
- mdss_get_iommu_domain(),
- 0, SZ_4K, 0, &mfd->iova,
- (unsigned long *) &size,
- 0, 0);
- }
- } else {
- virt = dma_alloc_coherent(NULL, size,
- (dma_addr_t *) &phys, GFP_KERNEL);
- if (!virt) {
- pr_err("unable to alloc fbmem size=%u\n", size);
- return -ENOMEM;
- }
+ virt = allocate_contiguous_memory(size, MEMTYPE_EBI1, SZ_1M, 0);
+ if (!virt) {
+ pr_err("unable to alloc fbmem size=%u\n", size);
+ return -ENOMEM;
}
-
+ phys = memory_pool_node_paddr(virt);
+ if (is_mdss_iommu_attached()) {
+ msm_iommu_map_contig_buffer(phys,
+ mdss_get_iommu_domain(), 0, size, SZ_4K, 0,
+ &(mfd->iova));
+ }
pr_info("allocating %u bytes at %p (%lx phys) for fb %d\n",
size, virt, phys, mfd->index);
} else {
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index 4f641cc..0f6cfe9 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -1081,8 +1081,10 @@
static const struct of_device_id mdss_mdp_dt_match[] = {
{ .compatible = "qcom,mdss_mdp",},
+ {}
};
MODULE_DEVICE_TABLE(of, mdss_mdp_dt_match);
+EXPORT_COMPAT("qcom,mdss_mdp");
static struct platform_driver mdss_mdp_driver = {
.probe = mdss_mdp_probe,
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index 161f54a..5966989 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -351,6 +351,7 @@
{
struct mdss_mdp_ctl *ctl;
u32 width, height;
+ int ret = 0;
if (!mfd)
return -ENODEV;
@@ -363,23 +364,30 @@
return -EINVAL;
}
- ctl = mdss_mdp_ctl_alloc();
-
- if (!ctl) {
- pr_err("unable to allocate ctl\n");
- return -ENOMEM;
+ if (!mfd->ctl) {
+ ctl = mdss_mdp_ctl_alloc();
+ if (!ctl) {
+ pr_err("unable to allocate ctl\n");
+ return -ENOMEM;
+ }
+ ctl->mfd = mfd;
+ mfd->ctl = ctl;
+ } else {
+ ctl = mfd->ctl;
}
- ctl->mfd = mfd;
ctl->width = width;
ctl->height = height;
ctl->dst_format = mfd->panel_info.out_format;
- ctl->mixer_left = mdss_mdp_mixer_alloc(MDSS_MDP_MIXER_TYPE_INTF);
if (!ctl->mixer_left) {
- pr_err("unable to allocate layer mixer\n");
- mdss_mdp_ctl_free(ctl);
- return -ENOMEM;
+ ctl->mixer_left =
+ mdss_mdp_mixer_alloc(MDSS_MDP_MIXER_TYPE_INTF);
+ if (!ctl->mixer_left) {
+ pr_err("unable to allocate layer mixer\n");
+ ret = -ENOMEM;
+ goto ctl_init_fail;
+ }
}
if (width > MAX_MIXER_WIDTH)
@@ -390,17 +398,20 @@
ctl->mixer_left->ctl = ctl;
if (width < ctl->width) {
- ctl->mixer_right =
- mdss_mdp_mixer_alloc(MDSS_MDP_MIXER_TYPE_INTF);
- if (!ctl->mixer_right) {
- pr_err("unable to allocate right layer mixer\n");
- mdss_mdp_mixer_free(ctl->mixer_left);
- mdss_mdp_ctl_free(ctl);
- return -ENOMEM;
+ if (ctl->mixer_right == NULL) {
+ ctl->mixer_right =
+ mdss_mdp_mixer_alloc(MDSS_MDP_MIXER_TYPE_INTF);
+ if (!ctl->mixer_right) {
+ pr_err("unable to allocate right mixer\n");
+ ret = -ENOMEM;
+ goto ctl_init_fail;
+ }
}
ctl->mixer_right->width = width;
ctl->mixer_right->height = height;
ctl->mixer_right->ctl = ctl;
+ } else if (ctl->mixer_right) {
+ mdss_mdp_mixer_free(ctl->mixer_right);
}
switch (mfd->panel_info.type) {
@@ -432,9 +443,8 @@
break;
default:
pr_err("unsupported panel type (%d)\n", mfd->panel_info.type);
- mdss_mdp_ctl_free(ctl);
- return -EINVAL;
-
+ ret = -EINVAL;
+ goto ctl_init_fail;
}
ctl->opmode |= (ctl->intf_num << 4);
@@ -444,9 +454,17 @@
MDSS_MDP_CTL_OP_PACK_3D_H_ROW_INT;
}
- mfd->ctl = ctl;
+ctl_init_fail:
+ if (IS_ERR_VALUE(ret)) {
+ if (ctl->mixer_left)
+ mdss_mdp_mixer_free(ctl->mixer_left);
+ if (ctl->mixer_right)
+ mdss_mdp_mixer_free(ctl->mixer_right);
+ mdss_mdp_ctl_free(ctl);
+ mfd->ctl = NULL;
+ }
- return 0;
+ return ret;
}
static int mdss_mdp_ctl_destroy(struct msm_fb_data_type *mfd)
@@ -487,12 +505,11 @@
return -ENODEV;
}
- if (!mfd->ctl) {
- if (mdss_mdp_ctl_init(mfd)) {
- pr_err("unable to initialize ctl\n");
- return -ENODEV;
- }
+ if (mdss_mdp_ctl_init(mfd)) {
+ pr_err("unable to initialize ctl\n");
+ return -ENODEV;
}
+
ctl = mfd->ctl;
if (ctl->power_on) {
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index ee1b350..f76b508 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -703,7 +703,6 @@
fbi = mfd->fbi;
if (fbi->fix.smem_len == 0) {
- pr_warn("fb memory not allocated\n");
mdss_mdp_overlay_kickoff(mfd->ctl);
return;
}
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 9f05a6a..1994b1b 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -2961,6 +2961,19 @@
return ret;
}
+static int msmfb_overlay_commit(struct fb_info *info, unsigned long *argp)
+{
+ int ret, ndx;
+
+ ret = copy_from_user(&ndx, argp, sizeof(ndx));
+ if (ret) {
+ pr_err("%s: ioctl failed\n", __func__);
+ return ret;
+ }
+
+ return mdp4_overlay_commit(info, ndx);
+}
+
static int msmfb_overlay_play(struct fb_info *info, unsigned long *argp)
{
int ret;
@@ -3388,6 +3401,11 @@
case MSMFB_OVERLAY_UNSET:
ret = msmfb_overlay_unset(info, argp);
break;
+ case MSMFB_OVERLAY_COMMIT:
+ down(&msm_fb_ioctl_ppp_sem);
+ ret = msmfb_overlay_commit(info, argp);
+ up(&msm_fb_ioctl_ppp_sem);
+ break;
case MSMFB_OVERLAY_PLAY:
ret = msmfb_overlay_play(info, argp);
break;
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 31a152d..5b07403 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -444,3 +444,4 @@
header-y += idle_stats_device.h
header-y += genlock.h
header-y += msm_audio_amrwb.h
+header-y += coresight-stm.h
diff --git a/include/linux/coresight-stm.h b/include/linux/coresight-stm.h
index 754f2f3..7c7c26e 100644
--- a/include/linux/coresight-stm.h
+++ b/include/linux/coresight-stm.h
@@ -28,6 +28,7 @@
STM_OPTION_GUARANTEED = 0x80,
};
+#ifdef __KERNEL__
#define stm_log_inv(entity_id, proto_id, data, size) \
stm_trace(STM_OPTION_NONE, entity_id, proto_id, data, size)
@@ -56,5 +57,6 @@
return 0;
}
#endif
+#endif /* __KERNEL__ */
#endif
diff --git a/include/linux/mfd/pm8xxx/pm8921-charger.h b/include/linux/mfd/pm8xxx/pm8921-charger.h
index 7b389c5..0e86f2a 100644
--- a/include/linux/mfd/pm8xxx/pm8921-charger.h
+++ b/include/linux/mfd/pm8xxx/pm8921-charger.h
@@ -63,6 +63,8 @@
* @ttrkl_time: max trckl charging time in minutes
* valid range 1 to 64 mins. PON default 15 min
* @update_time: how often the userland be updated of the charging (msec)
+ * @alarm_low_mv: the voltage (mV) when low battery alarm is triggered
+ * @alarm_high_mv: the voltage (mV) when high battery alarm is triggered
* @max_voltage: the max voltage (mV) the battery should be charged up to
* @min_voltage: the voltage (mV) where charging method switches from
* trickle to fast. This is also the minimum voltage the
@@ -128,6 +130,8 @@
unsigned int max_voltage;
unsigned int min_voltage;
unsigned int uvd_thresh_voltage;
+ unsigned int alarm_low_mv;
+ unsigned int alarm_high_mv;
unsigned int resume_voltage_delta;
unsigned int term_current;
int cool_temp;
diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h
index 71ff639..5e1395e 100644
--- a/include/linux/msm_kgsl.h
+++ b/include/linux/msm_kgsl.h
@@ -2,7 +2,7 @@
#define _MSM_KGSL_H
#define KGSL_VERSION_MAJOR 3
-#define KGSL_VERSION_MINOR 12
+#define KGSL_VERSION_MINOR 13
/*context flags */
#define KGSL_CONTEXT_SAVE_GMEM 0x00000001
@@ -18,6 +18,33 @@
/* Memory allocayion flags */
#define KGSL_MEMFLAGS_GPUREADONLY 0x01000000
+#define KGSL_MEMTYPE_MASK 0x0000FF00
+#define KGSL_MEMTYPE_SHIFT 8
+
+/* Memory types for which allocations are made */
+#define KGSL_MEMTYPE_OBJECTANY 0
+#define KGSL_MEMTYPE_FRAMEBUFFER 1
+#define KGSL_MEMTYPE_RENDERBUFFER 2
+#define KGSL_MEMTYPE_ARRAYBUFFER 3
+#define KGSL_MEMTYPE_ELEMENTARRAYBUFFER 4
+#define KGSL_MEMTYPE_VERTEXARRAYBUFFER 5
+#define KGSL_MEMTYPE_TEXTURE 6
+#define KGSL_MEMTYPE_SURFACE 7
+#define KGSL_MEMTYPE_EGL_SURFACE 8
+#define KGSL_MEMTYPE_GL 9
+#define KGSL_MEMTYPE_CL 10
+#define KGSL_MEMTYPE_CL_BUFFER_MAP 11
+#define KGSL_MEMTYPE_CL_BUFFER_NOMAP 12
+#define KGSL_MEMTYPE_CL_IMAGE_MAP 13
+#define KGSL_MEMTYPE_CL_IMAGE_NOMAP 14
+#define KGSL_MEMTYPE_CL_KERNEL_STACK 15
+#define KGSL_MEMTYPE_COMMAND 16
+#define KGSL_MEMTYPE_2D 17
+#define KGSL_MEMTYPE_EGL_IMAGE 18
+#define KGSL_MEMTYPE_EGL_SHADOW 19
+#define KGSL_MEMTYPE_MULTISAMPLE 20
+#define KGSL_MEMTYPE_KERNEL 255
+
/* generic flag values */
#define KGSL_FLAGS_NORMALMODE 0x00000000
#define KGSL_FLAGS_SAFEMODE 0x00000001
@@ -278,8 +305,7 @@
unsigned int offset;
unsigned int hostptr; /*input param */
enum kgsl_user_mem_type memtype;
- unsigned int reserved; /* May be required to add
- params for another mem type */
+ unsigned int flags;
};
#define IOCTL_KGSL_MAP_USER_MEM \
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 861084a..1cdc434 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -71,6 +71,8 @@
#define MSMFB_OVERLAY_VSYNC_CTRL _IOW(MSMFB_IOCTL_MAGIC, 160, unsigned int)
#define MSMFB_VSYNC_CTRL _IOW(MSMFB_IOCTL_MAGIC, 161, unsigned int)
#define MSMFB_METADATA_SET _IOW(MSMFB_IOCTL_MAGIC, 162, struct msmfb_metadata)
+#define MSMFB_OVERLAY_COMMIT _IOW(MSMFB_IOCTL_MAGIC, 163, unsigned int)
+
#define FB_TYPE_3D_PANEL 0x10101010
#define MDP_IMGTYPE2_START 0x10000
#define MSMFB_DRIVER_VERSION 0xF9E8D701
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 2c9509d..1f13da3 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -142,6 +142,8 @@
extern unsigned long nr_iowait_cpu(int cpu);
extern unsigned long this_cpu_load(void);
+extern void sched_update_nr_prod(int cpu, unsigned long nr, bool inc);
+extern void sched_get_nr_running_avg(int *avg, int *iowait_avg);
extern void calc_global_load(unsigned long ticks);
diff --git a/include/media/vcap_fmt.h b/include/media/vcap_fmt.h
index 2641720..3b1bd7c2 100644
--- a/include/media/vcap_fmt.h
+++ b/include/media/vcap_fmt.h
@@ -13,6 +13,7 @@
#ifndef VCAP_FMT_H
#define VCAP_FMT_H
+#include <linux/videodev2.h>
#define V4L2_BUF_TYPE_INTERLACED_IN_DECODER (V4L2_BUF_TYPE_PRIVATE)
diff --git a/include/sound/q6asm.h b/include/sound/q6asm.h
index 32d3aef..9cc0de4 100644
--- a/include/sound/q6asm.h
+++ b/include/sound/q6asm.h
@@ -284,7 +284,8 @@
uint32_t rate, uint32_t channels);
int q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac,
- uint32_t rate, uint32_t channels);
+ uint32_t rate, uint32_t channels,
+ char *channel_map);
int q6asm_media_format_block_aac(struct audio_client *ac,
struct asm_aac_cfg *cfg);
diff --git a/kernel/rcutree.c b/kernel/rcutree.c
index d0c5baf..4eec66e 100644
--- a/kernel/rcutree.c
+++ b/kernel/rcutree.c
@@ -295,7 +295,9 @@
static int
cpu_needs_another_gp(struct rcu_state *rsp, struct rcu_data *rdp)
{
- return *rdp->nxttail[RCU_DONE_TAIL] && !rcu_gp_in_progress(rsp);
+ return *rdp->nxttail[RCU_DONE_TAIL +
+ ACCESS_ONCE(rsp->completed) != rdp->completed] &&
+ !rcu_gp_in_progress(rsp);
}
/*
diff --git a/kernel/sched/Makefile b/kernel/sched/Makefile
index 9a7dd35..3ede7d9 100644
--- a/kernel/sched/Makefile
+++ b/kernel/sched/Makefile
@@ -11,7 +11,7 @@
CFLAGS_core.o := $(PROFILING) -fno-omit-frame-pointer
endif
-obj-y += core.o clock.o idle_task.o fair.o rt.o stop_task.o
+obj-y += core.o clock.o idle_task.o fair.o rt.o stop_task.o sched_avg.o
obj-$(CONFIG_SMP) += cpupri.o
obj-$(CONFIG_SCHED_AUTOGROUP) += auto_group.o
obj-$(CONFIG_SCHEDSTATS) += stats.o
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index fb3acba..451bd4f 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -916,11 +916,13 @@
static inline void inc_nr_running(struct rq *rq)
{
+ sched_update_nr_prod(cpu_of(rq), rq->nr_running, true);
rq->nr_running++;
}
static inline void dec_nr_running(struct rq *rq)
{
+ sched_update_nr_prod(cpu_of(rq), rq->nr_running, false);
rq->nr_running--;
}
diff --git a/kernel/sched/sched_avg.c b/kernel/sched/sched_avg.c
new file mode 100644
index 0000000..8eaf2f7
--- /dev/null
+++ b/kernel/sched/sched_avg.c
@@ -0,0 +1,106 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/*
+ * Scheduler hook for average runqueue determination
+ */
+#include <linux/module.h>
+#include <linux/percpu.h>
+#include <linux/hrtimer.h>
+#include <linux/sched.h>
+#include <linux/math64.h>
+
+static DEFINE_PER_CPU(u64, nr_prod_sum);
+static DEFINE_PER_CPU(u64, last_time);
+static DEFINE_PER_CPU(u64, nr);
+static DEFINE_PER_CPU(unsigned long, iowait_prod_sum);
+static DEFINE_PER_CPU(spinlock_t, nr_lock) = __SPIN_LOCK_UNLOCKED(nr_lock);
+static s64 last_get_time;
+
+/**
+ * sched_get_nr_running_avg
+ * @return: Average nr_running and iowait value since last poll.
+ * Returns the avg * 100 to return up to two decimal points
+ * of accuracy.
+ *
+ * Obtains the average nr_running value since the last poll.
+ * This function may not be called concurrently with itself
+ */
+void sched_get_nr_running_avg(int *avg, int *iowait_avg)
+{
+ int cpu;
+ u64 curr_time = sched_clock();
+ u64 diff = curr_time - last_get_time;
+ u64 tmp_avg = 0, tmp_iowait = 0;
+
+ *avg = 0;
+ *iowait_avg = 0;
+
+ if (!diff)
+ return;
+
+ last_get_time = curr_time;
+ /* read and reset nr_running counts */
+ for_each_possible_cpu(cpu) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&per_cpu(nr_lock, cpu), flags);
+ tmp_avg += per_cpu(nr_prod_sum, cpu);
+ tmp_avg += per_cpu(nr, cpu) *
+ (curr_time - per_cpu(last_time, cpu));
+ tmp_iowait = per_cpu(iowait_prod_sum, cpu);
+ tmp_iowait += nr_iowait_cpu(cpu) *
+ (curr_time - per_cpu(last_time, cpu));
+ per_cpu(last_time, cpu) = curr_time;
+ per_cpu(nr_prod_sum, cpu) = 0;
+ per_cpu(iowait_prod_sum, cpu) = 0;
+ spin_unlock_irqrestore(&per_cpu(nr_lock, cpu), flags);
+ }
+
+ *avg = (int)div64_u64(tmp_avg * 100, diff);
+ *iowait_avg = (int)div64_u64(tmp_iowait * 100, diff);
+
+ BUG_ON(*avg < 0);
+ pr_debug("%s - avg:%d\n", __func__, *avg);
+ BUG_ON(*iowait_avg < 0);
+ pr_debug("%s - avg:%d\n", __func__, *iowait_avg);
+}
+EXPORT_SYMBOL(sched_get_nr_running_avg);
+
+/**
+ * sched_update_nr_prod
+ * @cpu: The core id of the nr running driver.
+ * @nr: Updated nr running value for cpu.
+ * @inc: Whether we are increasing or decreasing the count
+ * @return: N/A
+ *
+ * Update average with latest nr_running value for CPU
+ */
+void sched_update_nr_prod(int cpu, unsigned long nr_running, bool inc)
+{
+ int diff;
+ s64 curr_time;
+ unsigned long flags;
+
+ spin_lock_irqsave(&per_cpu(nr_lock, cpu), flags);
+ curr_time = sched_clock();
+ diff = curr_time - per_cpu(last_time, cpu);
+ per_cpu(last_time, cpu) = curr_time;
+ per_cpu(nr, cpu) = nr_running + (inc ? 1 : -1);
+
+ BUG_ON(per_cpu(nr, cpu) < 0);
+
+ per_cpu(nr_prod_sum, cpu) += nr_running * diff;
+ per_cpu(iowait_prod_sum, cpu) += nr_iowait_cpu(cpu) * diff;
+ spin_unlock_irqrestore(&per_cpu(nr_lock, cpu), flags);
+}
+EXPORT_SYMBOL(sched_update_nr_prod);
diff --git a/sound/soc/codecs/wcd9304.c b/sound/soc/codecs/wcd9304.c
index 9432a06..b303878 100644
--- a/sound/soc/codecs/wcd9304.c
+++ b/sound/soc/codecs/wcd9304.c
@@ -4976,6 +4976,7 @@
SITAR_REG_VAL(SITAR_A_CDC_RX1_B6_CTL, 0x80),
SITAR_REG_VAL(SITAR_A_CDC_CLSG_FREQ_THRESH_B3_CTL, 0x1B),
+ SITAR_REG_VAL(SITAR_A_CDC_CLSG_FREQ_THRESH_B4_CTL, 0x5B),
};
diff --git a/sound/soc/msm/apq8064-i2s.c b/sound/soc/msm/apq8064-i2s.c
index 6b5314a..e309370 100644
--- a/sound/soc/msm/apq8064-i2s.c
+++ b/sound/soc/msm/apq8064-i2s.c
@@ -2690,7 +2690,8 @@
static void __exit msm_audio_exit(void)
{
- if (!cpu_is_apq8064() || (socinfo_get_id() == 130)) {
+ if (!(cpu_is_apq8064() || cpu_is_apq8064ab()) ||
+ (socinfo_get_id() == 130)) {
pr_err("%s: Not the right machine type\n", __func__);
return ;
}
diff --git a/sound/soc/msm/apq8064.c b/sound/soc/msm/apq8064.c
index c8cf681..7894368 100644
--- a/sound/soc/msm/apq8064.c
+++ b/sound/soc/msm/apq8064.c
@@ -1353,6 +1353,8 @@
pr_debug("%s channels->min %u channels->max %u ()\n", __func__,
channels->min, channels->max);
+ if (channels->max < 2)
+ channels->min = channels->max = 2;
rate->min = rate->max = 48000;
return 0;
@@ -2101,7 +2103,8 @@
{
int ret;
u32 version = socinfo_get_platform_version();
- if (!cpu_is_apq8064() || (socinfo_get_id() == 130) ||
+ if (!(cpu_is_apq8064() || cpu_is_apq8064ab()) ||
+ (socinfo_get_id() == 130) ||
(machine_is_apq8064_mtp() &&
(SOCINFO_VERSION_MINOR(version) == 1))) {
pr_info("%s: Not APQ8064 in SLIMBUS mode\n", __func__);
@@ -2141,7 +2144,8 @@
static void __exit msm_audio_exit(void)
{
- if (!cpu_is_apq8064() || (socinfo_get_id() == 130)) {
+ if (!(cpu_is_apq8064() || cpu_is_apq8064ab()) ||
+ (socinfo_get_id() == 130)) {
pr_err("%s: Not the right machine type\n", __func__);
return ;
}
diff --git a/sound/soc/msm/mpq8064.c b/sound/soc/msm/mpq8064.c
index 957b656..011b798 100644
--- a/sound/soc/msm/mpq8064.c
+++ b/sound/soc/msm/mpq8064.c
@@ -45,6 +45,11 @@
#define TOP_SPK_AMP_POS 0x4
#define TOP_SPK_AMP_NEG 0x8
+#define GPIO_AUX_PCM_DOUT 43
+#define GPIO_AUX_PCM_DIN 44
+#define GPIO_AUX_PCM_SYNC 45
+#define GPIO_AUX_PCM_CLK 46
+
#define TABLA_EXT_CLK_RATE 12288000
#define TABLA_MBHC_DEF_BUTTONS 8
@@ -942,6 +947,78 @@
return ret;
}
+static int mpq8064_auxpcm_be_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_interval *rate = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_RATE);
+
+ struct snd_interval *channels = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_CHANNELS);
+
+ /* PCM only supports mono output with 8khz sample rate */
+ rate->min = rate->max = 8000;
+ channels->min = channels->max = 1;
+
+ return 0;
+}
+
+static int mpq8064_aux_pcm_get_gpios(void)
+{
+ int ret = 0;
+
+ pr_debug("%s\n", __func__);
+
+ ret = gpio_request(GPIO_AUX_PCM_DOUT, "AUX PCM DOUT");
+ if (ret < 0) {
+ pr_err("%s: Failed to request gpio(%d): AUX PCM DOUT",
+ __func__, GPIO_AUX_PCM_DOUT);
+ goto fail_dout;
+ }
+
+ ret = gpio_request(GPIO_AUX_PCM_DIN, "AUX PCM DIN");
+ if (ret < 0) {
+ pr_err("%s: Failed to request gpio(%d): AUX PCM DIN",
+ __func__, GPIO_AUX_PCM_DIN);
+ goto fail_din;
+ }
+
+ ret = gpio_request(GPIO_AUX_PCM_SYNC, "AUX PCM SYNC");
+ if (ret < 0) {
+ pr_err("%s: Failed to request gpio(%d): AUX PCM SYNC",
+ __func__, GPIO_AUX_PCM_SYNC);
+ goto fail_sync;
+ }
+ ret = gpio_request(GPIO_AUX_PCM_CLK, "AUX PCM CLK");
+ if (ret < 0) {
+ pr_err("%s: Failed to request gpio(%d): AUX PCM CLK",
+ __func__, GPIO_AUX_PCM_CLK);
+ goto fail_clk;
+ }
+
+ return 0;
+
+fail_clk:
+ gpio_free(GPIO_AUX_PCM_SYNC);
+fail_sync:
+ gpio_free(GPIO_AUX_PCM_DIN);
+fail_din:
+ gpio_free(GPIO_AUX_PCM_DOUT);
+fail_dout:
+
+ return ret;
+}
+
+static int mpq8064_aux_pcm_free_gpios(void)
+{
+ gpio_free(GPIO_AUX_PCM_DIN);
+ gpio_free(GPIO_AUX_PCM_DOUT);
+ gpio_free(GPIO_AUX_PCM_SYNC);
+ gpio_free(GPIO_AUX_PCM_CLK);
+
+ return 0;
+}
+
static int msm_startup(struct snd_pcm_substream *substream)
{
pr_debug("%s(): substream = %s stream = %d\n", __func__,
@@ -955,12 +1032,39 @@
substream->name, substream->stream);
}
+static int mpq8064_auxpcm_startup(struct snd_pcm_substream *substream)
+{
+ int ret = 0;
+
+ pr_debug("%s(): substream = %s\n", __func__, substream->name);
+ ret = mpq8064_aux_pcm_get_gpios();
+ if (ret < 0) {
+ pr_err("%s: Aux PCM GPIO request failed\n", __func__);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static void mpq8064_auxpcm_shutdown(struct snd_pcm_substream *substream)
+{
+
+ pr_debug("%s(): substream = %s\n", __func__, substream->name);
+ mpq8064_aux_pcm_free_gpios();
+}
+
+
static struct snd_soc_ops msm_be_ops = {
.startup = msm_startup,
.hw_params = msm_hw_params,
.shutdown = msm_shutdown,
};
+static struct snd_soc_ops mpq8064_auxpcm_be_ops = {
+ .startup = mpq8064_auxpcm_startup,
+ .shutdown = mpq8064_auxpcm_shutdown,
+};
+
+
static int mpq8064_sec_i2s_rx_free_gpios(void)
{
int i;
@@ -1341,6 +1445,20 @@
.ignore_pmdown_time = 1, /* this dailink has playback support */
.be_id = MSM_FRONTEND_DAI_MULTIMEDIA8,
},
+ {
+ .name = "AUXPCM Hostless",
+ .stream_name = "AUXPCM Hostless",
+ .cpu_dai_name = "AUXPCM_HOSTLESS",
+ .platform_name = "msm-pcm-hostless",
+ .dynamic = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1, /* dainlink has playback support */
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ },
/* Backend DAI Links */
{
.name = LPASS_BE_SLIMBUS_0_RX,
@@ -1451,6 +1569,31 @@
.no_pcm = 1,
.be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
},
+ /* AUX PCM Backend DAI Links */
+ {
+ .name = LPASS_BE_AUXPCM_RX,
+ .stream_name = "AUX PCM Playback",
+ .cpu_dai_name = "msm-dai-q6.2",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-rx",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_AUXPCM_RX,
+ .be_hw_params_fixup = mpq8064_auxpcm_be_params_fixup,
+ .ops = &mpq8064_auxpcm_be_ops,
+ .ignore_pmdown_time = 1,
+ },
+ {
+ .name = LPASS_BE_AUXPCM_TX,
+ .stream_name = "AUX PCM Capture",
+ .cpu_dai_name = "msm-dai-q6.3",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_AUXPCM_TX,
+ .be_hw_params_fixup = mpq8064_auxpcm_be_params_fixup,
+ },
};
diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
index 550a492..0b9d54f 100644
--- a/sound/soc/msm/msm-compr-q6.c
+++ b/sound/soc/msm/msm-compr-q6.c
@@ -551,9 +551,7 @@
prtd->enabled = 1;
if (compr->info.codec_param.codec.id ==
- SND_AUDIOCODEC_AC3_PASS_THROUGH ||
- compr->info.codec_param.codec.id ==
- SND_AUDIOCODEC_DTS_PASS_THROUGH)
+ SND_AUDIOCODEC_PASS_THROUGH)
msm_pcm_routing_reg_psthr_stream(
soc_prtd->dai_link->be_id,
prtd->session_id, substream->stream,
@@ -768,9 +766,7 @@
q6asm_audio_client_buf_free_contiguous(dir,
prtd->audio_client);
if (compr->info.codec_param.codec.id ==
- SND_AUDIOCODEC_AC3_PASS_THROUGH ||
- compr->info.codec_param.codec.id ==
- SND_AUDIOCODEC_DTS_PASS_THROUGH)
+ SND_AUDIOCODEC_PASS_THROUGH)
msm_pcm_routing_reg_psthr_stream(
soc_prtd->dai_link->be_id,
prtd->session_id, substream->stream,
diff --git a/sound/soc/msm/msm-lowlatency-pcm-q6.c b/sound/soc/msm/msm-lowlatency-pcm-q6.c
index 129f69f..fcfcb66 100644
--- a/sound/soc/msm/msm-lowlatency-pcm-q6.c
+++ b/sound/soc/msm/msm-lowlatency-pcm-q6.c
@@ -218,8 +218,27 @@
if (prtd->enabled)
return 0;
+ if (!prtd->set_channel_map) {
+ memset(prtd->channel_map, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
+ if (prtd->channel_mode == 1) {
+ prtd->channel_map[0] = PCM_CHANNEL_FL;
+ } else if (prtd->channel_mode == 2) {
+ prtd->channel_map[0] = PCM_CHANNEL_FL;
+ prtd->channel_map[0] = PCM_CHANNEL_FR;
+ } else if (prtd->channel_mode == 6) {
+ prtd->channel_map[0] = PCM_CHANNEL_FC;
+ prtd->channel_map[0] = PCM_CHANNEL_FL;
+ prtd->channel_map[0] = PCM_CHANNEL_FR;
+ prtd->channel_map[0] = PCM_CHANNEL_LB;
+ prtd->channel_map[0] = PCM_CHANNEL_RB;
+ prtd->channel_map[0] = PCM_CHANNEL_LFE;
+ } else {
+ pr_err("%s: ERROR.unsupported num_ch = %u\n", __func__,
+ prtd->channel_mode);
+ }
+ }
ret = q6asm_media_format_block_multi_ch_pcm(prtd->audio_client,
- runtime->rate, runtime->channels);
+ runtime->rate, runtime->channels, prtd->channel_map);
if (ret < 0)
pr_info("%s: CMD Format block failed\n", __func__);
@@ -389,6 +408,7 @@
}
prtd->dsp_cnt = 0;
+ prtd->set_channel_map = false;
runtime->private_data = prtd;
pr_debug("substream->pcm->device = %d\n", substream->pcm->device);
pr_debug("soc_prtd->dai_link->be_id = %d\n", soc_prtd->dai_link->be_id);
diff --git a/sound/soc/msm/msm-multi-ch-pcm-q6.c b/sound/soc/msm/msm-multi-ch-pcm-q6.c
index 5b0759c..7d04f95 100644
--- a/sound/soc/msm/msm-multi-ch-pcm-q6.c
+++ b/sound/soc/msm/msm-multi-ch-pcm-q6.c
@@ -269,9 +269,29 @@
prtd->channel_mode = runtime->channels;
if (prtd->enabled)
return 0;
-
+ pr_debug("prtd->set_channel_map: %d", prtd->set_channel_map);
+ if (!prtd->set_channel_map) {
+ pr_debug("using default channel map");
+ memset(prtd->channel_map, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
+ if (prtd->channel_mode == 1) {
+ prtd->channel_map[0] = PCM_CHANNEL_FL;
+ } else if (prtd->channel_mode == 2) {
+ prtd->channel_map[1] = PCM_CHANNEL_FL;
+ prtd->channel_map[2] = PCM_CHANNEL_FR;
+ } else if (prtd->channel_mode == 6) {
+ prtd->channel_map[0] = PCM_CHANNEL_FC;
+ prtd->channel_map[1] = PCM_CHANNEL_FL;
+ prtd->channel_map[2] = PCM_CHANNEL_FR;
+ prtd->channel_map[3] = PCM_CHANNEL_LB;
+ prtd->channel_map[4] = PCM_CHANNEL_RB;
+ prtd->channel_map[5] = PCM_CHANNEL_LFE;
+ } else {
+ pr_err("%s: ERROR.unsupported num_ch = %u\n", __func__,
+ prtd->channel_mode);
+ }
+ }
ret = q6asm_media_format_block_multi_ch_pcm(prtd->audio_client,
- runtime->rate, runtime->channels);
+ runtime->rate, runtime->channels, prtd->channel_map);
if (ret < 0)
pr_info("%s: CMD Format block failed\n", __func__);
@@ -452,6 +472,7 @@
}
prtd->dsp_cnt = 0;
+ prtd->set_channel_map = false;
runtime->private_data = prtd;
pr_debug("substream->pcm->device = %d\n", substream->pcm->device);
pr_debug("soc_prtd->dai_link->be_id = %d\n", soc_prtd->dai_link->be_id);
@@ -492,6 +513,15 @@
return rc;
}
+void multi_ch_pcm_set_channel_map(char *channel_mapping)
+{
+ pr_debug("%s\n", __func__);
+ if (multi_ch_pcm_audio.prtd) {
+ multi_ch_pcm_audio.prtd->set_channel_map = true;
+ memcpy(multi_ch_pcm_audio.prtd->channel_map, channel_mapping,
+ PCM_FORMAT_MAX_NUM_CHANNEL);
+ }
+}
static int msm_pcm_playback_copy(struct snd_pcm_substream *substream, int a,
snd_pcm_uframes_t hwoff, void __user *buf, snd_pcm_uframes_t frames)
diff --git a/sound/soc/msm/msm-pcm-q6.h b/sound/soc/msm/msm-pcm-q6.h
index f1af99a..2678498 100644
--- a/sound/soc/msm/msm-pcm-q6.h
+++ b/sound/soc/msm/msm-pcm-q6.h
@@ -81,6 +81,8 @@
int periods;
int mmap_flag;
atomic_t pending_buffer;
+ bool set_channel_map;
+ char channel_map[8];
};
struct output_meta_data_st {
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 4d0caa3..f28d01a 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -78,6 +78,7 @@
static const DECLARE_TLV_DB_LINEAR(compressed2_rx_vol_gain, 0,
INT_RX_VOL_MAX_STEPS);
static int msm_route_ec_ref_rx;
+static char channel_mapping[PCM_FORMAT_MAX_NUM_CHANNEL];
/* Equal to Frontend after last of the MULTIMEDIA SESSIONS */
#define MAX_EQ_SESSIONS MSM_FRONTEND_DAI_CS_VOICE
@@ -862,6 +863,27 @@
return 0;
}
+static int msm_routing_get_channel_map_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int i;
+ for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
+ ucontrol->value.integer.value[i] = channel_mapping[i];
+ return 0;
+}
+
+static int msm_routing_put_channel_map_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int i;
+
+ for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
+ channel_mapping[i] = (char)(ucontrol->value.integer.value[i]);
+ multi_ch_pcm_set_channel_map(channel_mapping);
+
+ return 0;
+}
+
static int msm_routing_set_compressed_vol_mixer(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -1891,6 +1913,12 @@
msm_routing_set_compressed2_vol_mixer, compressed2_rx_vol_gain),
};
+static const struct snd_kcontrol_new multi_ch_channel_map_mixer_controls[] = {
+ SOC_SINGLE_MULTI_EXT("Playback Channel Map", SND_SOC_NOPM, 0, 8,
+ 0, 8, msm_routing_get_channel_map_mixer,
+ msm_routing_put_channel_map_mixer),
+};
+
static const struct snd_kcontrol_new lpa_SRS_trumedia_controls[] = {
{.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "SRS TruMedia",
@@ -2867,6 +2895,10 @@
snd_soc_add_platform_controls(platform,
ec_ref_rx_mixer_controls,
ARRAY_SIZE(ec_ref_rx_mixer_controls));
+
+ snd_soc_add_platform_controls(platform,
+ multi_ch_channel_map_mixer_controls,
+ ARRAY_SIZE(multi_ch_channel_map_mixer_controls));
return 0;
}
diff --git a/sound/soc/msm/msm-pcm-routing.h b/sound/soc/msm/msm-pcm-routing.h
index 6b87475..14f330b 100644
--- a/sound/soc/msm/msm-pcm-routing.h
+++ b/sound/soc/msm/msm-pcm-routing.h
@@ -126,4 +126,6 @@
int compressed_set_volume(unsigned volume);
+void multi_ch_pcm_set_channel_map(char *channel_mapping);
+
#endif /*_MSM_PCM_H*/
diff --git a/sound/soc/msm/msm8960.c b/sound/soc/msm/msm8960.c
index 59d118e..6ec44bf 100644
--- a/sound/soc/msm/msm8960.c
+++ b/sound/soc/msm/msm8960.c
@@ -1018,6 +1018,8 @@
pr_debug("%s channels->min %u channels->max %u ()\n", __func__,
channels->min, channels->max);
+ if (channels->max < 2)
+ channels->min = channels->max = 2;
rate->min = rate->max = 48000;
return 0;
diff --git a/sound/soc/msm/qdsp6/q6asm.c b/sound/soc/msm/qdsp6/q6asm.c
index b086b8e..0aad217 100644
--- a/sound/soc/msm/qdsp6/q6asm.c
+++ b/sound/soc/msm/qdsp6/q6asm.c
@@ -798,6 +798,25 @@
return 0;
}
+static int32_t is_no_wait_cmd_rsp(uint32_t opcode, uint32_t *cmd_type)
+{
+ if (opcode == APR_BASIC_RSP_RESULT) {
+ if (cmd_type != NULL) {
+ switch (cmd_type[0]) {
+ case ASM_SESSION_CMD_RUN:
+ case ASM_SESSION_CMD_PAUSE:
+ case ASM_DATA_CMD_EOS:
+ return 1;
+ default:
+ break;
+ }
+ } else
+ pr_err("%s: null pointer!", __func__);
+ } else if (opcode == ASM_DATA_CMDRSP_EOS)
+ return 1;
+
+ return 0;
+}
static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
{
@@ -818,14 +837,16 @@
ac->session);
return -EINVAL;
}
- if (atomic_read(&ac->nowait_cmd_cnt) > 0) {
+
+ payload = data->payload;
+ if ((atomic_read(&ac->nowait_cmd_cnt) > 0) &&
+ is_no_wait_cmd_rsp(data->opcode, payload)) {
pr_debug("%s: nowait_cmd_cnt %d\n",
__func__,
atomic_read(&ac->nowait_cmd_cnt));
atomic_dec(&ac->nowait_cmd_cnt);
wakeup_flag = 0;
}
- payload = data->payload;
if (data->opcode == RESET_EVENTS) {
pr_debug("q6asm_callback: Reset event is received: %d %d apr[%p]\n",
@@ -2296,7 +2317,7 @@
}
int q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac,
- uint32_t rate, uint32_t channels)
+ uint32_t rate, uint32_t channels, char *channel_map)
{
struct asm_stream_media_format_update fmt;
u8 *channel_mapping;
@@ -2319,39 +2340,7 @@
channel_mapping =
fmt.write_cfg.multi_ch_pcm_cfg.channel_mapping;
- memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
-
- if (channels == 1) {
- channel_mapping[0] = PCM_CHANNEL_FL;
- } else if (channels == 2) {
- channel_mapping[0] = PCM_CHANNEL_FL;
- channel_mapping[1] = PCM_CHANNEL_FR;
- } else if (channels == 4) {
- channel_mapping[0] = PCM_CHANNEL_FL;
- channel_mapping[1] = PCM_CHANNEL_FR;
- channel_mapping[1] = PCM_CHANNEL_LB;
- channel_mapping[1] = PCM_CHANNEL_RB;
- } else if (channels == 6) {
- channel_mapping[0] = PCM_CHANNEL_FC;
- channel_mapping[1] = PCM_CHANNEL_FL;
- channel_mapping[2] = PCM_CHANNEL_FR;
- channel_mapping[3] = PCM_CHANNEL_LB;
- channel_mapping[4] = PCM_CHANNEL_RB;
- channel_mapping[5] = PCM_CHANNEL_LFE;
- } else if (channels == 8) {
- channel_mapping[0] = PCM_CHANNEL_FC;
- channel_mapping[1] = PCM_CHANNEL_FL;
- channel_mapping[2] = PCM_CHANNEL_FR;
- channel_mapping[3] = PCM_CHANNEL_LB;
- channel_mapping[4] = PCM_CHANNEL_RB;
- channel_mapping[5] = PCM_CHANNEL_LFE;
- channel_mapping[6] = PCM_CHANNEL_FLC;
- channel_mapping[7] = PCM_CHANNEL_FRC;
- } else {
- pr_err("%s: ERROR.unsupported num_ch = %u\n", __func__,
- channels);
- return -EINVAL;
- }
+ memcpy(channel_mapping, channel_map, PCM_FORMAT_MAX_NUM_CHANNEL);
rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
if (rc < 0) {
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 9f98c1b..0dd6faf 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -819,6 +819,10 @@
}
sid = (data->token >> 8) & 0x0F;
ac = q6asm_get_audio_client(sid);
+ if (!ac) {
+ pr_debug("%s: session[%d] already freed\n", __func__, sid);
+ return 0;
+ }
pr_debug("%s:ptr0[0x%x]ptr1[0x%x]opcode[0x%x] token[0x%x]payload_s[%d] src[%d] dest[%d]sid[%d]dir[%d]\n",
__func__, payload[0], payload[1], data->opcode, data->token,
data->payload_size, data->src_port, data->dest_port, sid, dir);